2
#include "greetermenubar.h"
4
static void greeter_menu_bar_size_allocate(GtkWidget* widget, GtkAllocation* allocation);
6
G_DEFINE_TYPE(GreeterMenuBar, greeter_menu_bar, GTK_TYPE_MENU_BAR);
9
greeter_menu_bar_class_init(GreeterMenuBarClass* klass)
11
GtkWidgetClass* widget_class = GTK_WIDGET_CLASS(klass);
12
widget_class->size_allocate = greeter_menu_bar_size_allocate;
16
greeter_menu_bar_init(GreeterMenuBar* square)
22
greeter_menu_bar_new(void)
24
return GTK_WIDGET(g_object_new(greeter_menu_bar_get_type(), NULL));
28
sort_minimal_size(gconstpointer a, gconstpointer b, GtkRequestedSize* sizes)
30
gint a_size = sizes[GPOINTER_TO_INT(a)].natural_size;
31
gint b_size = sizes[GPOINTER_TO_INT(b)].natural_size;
32
return a_size == b_size ? 0 : a_size > b_size ? -1 : +1;
36
greeter_menu_bar_size_allocate(GtkWidget* widget, GtkAllocation* allocation)
38
GtkPackDirection pack_direction;
40
GList *shell_children;
41
GList *expand_nums = NULL;
42
guint visible_count = 0;
43
guint expand_count = 0;
45
g_return_if_fail(allocation != NULL);
46
g_return_if_fail(GREETER_IS_MENU_BAR(widget));
48
gtk_widget_set_allocation(widget, allocation);
50
pack_direction = gtk_menu_bar_get_pack_direction(GTK_MENU_BAR(widget));
51
g_return_if_fail(pack_direction == GTK_PACK_DIRECTION_LTR || pack_direction == GTK_PACK_DIRECTION_RTL);
53
shell_children = gtk_container_get_children(GTK_CONTAINER(widget));
55
for(item = shell_children; item; item = g_list_next(item))
56
if(gtk_widget_get_visible(item->data))
58
if(gtk_widget_compute_expand(item->data, GTK_ORIENTATION_HORIZONTAL))
60
expand_nums = g_list_prepend(expand_nums, GINT_TO_POINTER(visible_count));
66
if(gtk_widget_get_realized(widget))
67
gdk_window_move_resize(gtk_widget_get_window(widget),
68
allocation->x, allocation->y,
69
allocation->width, allocation->height);
73
GtkAllocation remaining_space;
74
GtkStyleContext* context = gtk_widget_get_style_context(widget);
75
GtkStateFlags flags = gtk_widget_get_state_flags(widget);
76
GtkRequestedSize* requested_sizes = g_newa(GtkRequestedSize, visible_count);
77
guint border_width = gtk_container_get_border_width(GTK_CONTAINER(widget));
78
GtkShadowType shadow_type = GTK_SHADOW_OUT;
81
GtkRequestedSize* request;
85
gtk_style_context_get_padding(context, flags, &border);
86
gtk_widget_style_get(widget, "shadow-type", &shadow_type, NULL);
88
remaining_space.x = (border_width + border.left);
89
remaining_space.y = (border_width + border.top);
90
remaining_space.width = allocation->width -
91
2 * border_width - border.left - border.right;
92
remaining_space.height = allocation->height -
93
2 * border_width - border.top - border.bottom;
95
if (shadow_type != GTK_SHADOW_NONE)
97
gtk_style_context_get_border(context, flags, &border);
99
remaining_space.x += border.left;
100
remaining_space.y += border.top;
101
remaining_space.width -= border.left + border.right;
102
remaining_space.height -= border.top + border.bottom;
105
request = requested_sizes;
106
size = remaining_space.width;
107
ltr = (gtk_widget_get_direction(widget) == GTK_TEXT_DIR_LTR) == (pack_direction == GTK_PACK_DIRECTION_LTR);
109
for(item = shell_children; item; item = g_list_next(item))
111
if (!gtk_widget_get_visible(item->data))
114
request->data = item->data;
115
gtk_widget_get_preferred_width_for_height(item->data, remaining_space.height,
116
&request->minimum_size,
117
&request->natural_size);
118
gtk_menu_item_toggle_size_request(GTK_MENU_ITEM(item->data),
120
request->minimum_size += toggle_size;
121
request->natural_size += toggle_size;
123
gtk_menu_item_toggle_size_allocate(GTK_MENU_ITEM(item->data), toggle_size);
125
size -= request->minimum_size;
129
size = gtk_distribute_natural_allocation(size, visible_count, requested_sizes);
131
/* Distribution extra space for widgets with expand=True */
132
if(size > 0 && expand_nums)
134
GList *first_item = NULL;
135
gint needed_size = -1;
137
gint total_needed_size = 0;
139
expand_nums = g_list_sort_with_data(expand_nums, (GCompareDataFunc)sort_minimal_size,
141
first_item = expand_nums;
142
max_size = requested_sizes[GPOINTER_TO_INT(first_item->data)].natural_size;
144
/* Free space that all widgets need to have the same (max_size) width
145
* [___max_width___][widget ][widget____ ]
146
* total_needed_size := [] + [ ] + [ ]
147
* total_needed_size = [ ]
149
for(item = g_list_next(expand_nums); item; item = g_list_next(item))
150
total_needed_size += max_size - requested_sizes[GPOINTER_TO_INT(item->data)].natural_size;
154
if(size >= total_needed_size)
156
/* total_needed_size is enough for all remaining widgets */
157
needed_size = max_size + (size - total_needed_size)/expand_count;
160
/* Removing current maximal widget from list */
161
total_needed_size -= max_size - requested_sizes[GPOINTER_TO_INT(first_item->data)].natural_size;
162
first_item = g_list_next(first_item);
164
max_size = requested_sizes[GPOINTER_TO_INT(first_item->data)].natural_size;
167
for(item = first_item; item; item = g_list_next(item))
171
request = &requested_sizes[GPOINTER_TO_INT(item->data)];
172
dsize = needed_size - request->natural_size;
176
request->natural_size += dsize;
181
for(guint i = 0; i < visible_count; i++)
183
GtkAllocation child_allocation = remaining_space;
184
request = &requested_sizes[i];
186
child_allocation.width = request->natural_size;
187
remaining_space.width -= request->natural_size;
189
remaining_space.x += request->natural_size;
191
child_allocation.x += remaining_space.width;
192
gtk_widget_size_allocate(request->data, &child_allocation);
194
g_list_free(expand_nums);
196
g_list_free(shell_children);