+ get_menu_border (widget, &menu_border);
+ border_width = gtk_container_get_border_width (GTK_CONTAINER (widget));
+ border->x = border_width + menu_border.left + horizontal_padding;
+ border->y = border_width + menu_border.top + vertical_padding;
+ border->width = gdk_window_get_width (gtk_widget_get_window (widget));
+ border->height = gdk_window_get_height (gtk_widget_get_window (widget));
+
+ switch (arrow_placement)
+ {
+ case GTK_ARROWS_BOTH:
+ upper->x = border->x;
+ upper->y = border->y;
+ upper->width = border->width - 2 * border->x;
+ upper->height = scroll_arrow_height;
+
+ lower->x = border->x;
+ lower->y = border->height - border->y - scroll_arrow_height;
+ lower->width = border->width - 2 * border->x;
+ lower->height = scroll_arrow_height;
+ break;
+
+ case GTK_ARROWS_START:
+ upper->x = border->x;
+ upper->y = border->y;
+ upper->width = (border->width - 2 * border->x) / 2;
+ upper->height = scroll_arrow_height;
+
+ lower->x = border->x + upper->width;
+ lower->y = border->y;
+ lower->width = (border->width - 2 * border->x) / 2;
+ lower->height = scroll_arrow_height;
+ break;
+
+ case GTK_ARROWS_END:
+ upper->x = border->x;
+ upper->y = border->height - border->y - scroll_arrow_height;
+ upper->width = (border->width - 2 * border->x) / 2;
+ upper->height = scroll_arrow_height;
+
+ lower->x = border->x + upper->width;
+ lower->y = border->height - border->y - scroll_arrow_height;
+ lower->width = (border->width - 2 * border->x) / 2;
+ lower->height = scroll_arrow_height;
+ break;
+
+ default:
+ g_assert_not_reached();
+ upper->x = upper->y = upper->width = upper->height = 0;
+ lower->x = lower->y = lower->width = lower->height = 0;
+ }
+
+ *arrow_space = scroll_arrow_height - menu_border.top - menu_border.bottom;
+}
+
+static gboolean
+gtk_menu_draw (GtkWidget *widget,
+ cairo_t *cr)
+{
+ GtkMenu *menu;
+ GtkMenuPrivate *priv;
+ GtkStyleContext *context;
+ GdkRectangle border;
+ GdkRectangle upper;
+ GdkRectangle lower;
+ gint arrow_space;
+ GtkBorder menu_border;
+
+ menu = GTK_MENU (widget);
+ priv = menu->priv;
+ context = gtk_widget_get_style_context (widget);
+
+ get_arrows_visible_area (menu, &border, &upper, &lower, &arrow_space);
+ get_menu_border (widget, &menu_border);
+
+ if (gtk_cairo_should_draw_window (cr, gtk_widget_get_window (widget)))
+ {
+ gfloat arrow_scaling;
+ gint arrow_size;
+
+ gtk_widget_style_get (widget, "arrow-scaling", &arrow_scaling, NULL);
+ arrow_size = arrow_scaling * arrow_space;
+
+ gtk_render_background (context, cr, 0, 0,
+ gtk_widget_get_allocated_width (widget),
+ gtk_widget_get_allocated_height (widget));
+ gtk_render_frame (context, cr, 0, 0,
+ gtk_widget_get_allocated_width (widget),
+ gtk_widget_get_allocated_height (widget));
+
+ gtk_style_context_save (context);
+ gtk_style_context_add_class (context, GTK_STYLE_CLASS_BUTTON);
+
+ if (priv->upper_arrow_visible && !priv->tearoff_active)
+ {
+ gtk_style_context_save (context);
+ gtk_style_context_set_state (context, priv->upper_arrow_state);
+
+ gtk_render_background (context, cr,
+ upper.x, upper.y,
+ upper.width, upper.height);
+ gtk_render_frame (context, cr,
+ upper.x, upper.y,
+ upper.width, upper.height);
+
+ gtk_render_arrow (context, cr, 0,
+ upper.x + (upper.width - arrow_size) / 2,
+ upper.y + menu_border.top + (arrow_space - arrow_size) / 2,
+ arrow_size);
+
+ gtk_style_context_restore (context);
+ }
+
+ if (priv->lower_arrow_visible && !priv->tearoff_active)
+ {
+ gtk_style_context_save (context);
+ gtk_style_context_set_state (context, priv->lower_arrow_state);
+
+ gtk_render_background (context, cr,
+ lower.x, lower.y,
+ lower.width, lower.height);
+ gtk_render_frame (context, cr,
+ lower.x, lower.y,
+ lower.width, lower.height);
+
+ gtk_render_arrow (context, cr, G_PI,
+ lower.x + (lower.width - arrow_size) / 2,
+ lower.y + menu_border.top + (arrow_space - arrow_size) / 2,
+ arrow_size);
+
+ gtk_style_context_restore (context);
+ }
+
+ gtk_style_context_restore (context);
+ }
+
+ if (gtk_cairo_should_draw_window (cr, priv->bin_window))
+ {
+ gint y = -border.y + priv->scroll_offset;
+
+ cairo_save (cr);
+ gtk_cairo_transform_to_window (cr, widget, priv->bin_window);
+
+ if (!priv->tearoff_active)
+ {
+ GtkBorder arrow_border;
+
+ get_arrows_border (menu, &arrow_border);
+ y -= arrow_border.top;
+ }
+
+ gtk_render_background (context, cr,
+ - border.x, y,
+ border.width, border.height);
+ gtk_render_frame (context, cr,
+ - border.x, y,
+ border.width, border.height);
+
+ cairo_restore (cr);
+ }
+
+ GTK_WIDGET_CLASS (gtk_menu_parent_class)->draw (widget, cr);
+
+ return FALSE;
+}
+
+static void
+gtk_menu_show (GtkWidget *widget)
+{
+ GtkMenu *menu = GTK_MENU (widget);
+
+ _gtk_menu_refresh_accel_paths (menu, FALSE);
+
+ GTK_WIDGET_CLASS (gtk_menu_parent_class)->show (widget);
+}
+
+
+static void
+gtk_menu_get_preferred_width (GtkWidget *widget,
+ gint *minimum_size,
+ gint *natural_size)
+{
+ GtkMenu *menu;
+ GtkMenuShell *menu_shell;
+ GtkMenuPrivate *priv;
+ GtkWidget *child;
+ GList *children;
+ guint max_toggle_size;
+ guint max_accel_width;
+ guint horizontal_padding;
+ guint border_width;
+ gint child_min, child_nat;
+ gint min_width, nat_width;
+ GtkBorder border;
+
+ menu = GTK_MENU (widget);
+ menu_shell = GTK_MENU_SHELL (widget);
+ priv = menu->priv;
+
+ min_width = nat_width = 0;
+
+ max_toggle_size = 0;
+ max_accel_width = 0;
+
+ children = menu_shell->priv->children;
+ while (children)
+ {
+ gint part;
+ gint toggle_size;
+ gint l, r, t, b;
+
+ child = children->data;
+ children = children->next;
+
+ if (! gtk_widget_get_visible (child))
+ continue;
+
+ get_effective_child_attach (child, &l, &r, &t, &b);
+
+ /* It's important to size_request the child
+ * before doing the toggle size request, in
+ * case the toggle size request depends on the size
+ * request of a child of the child (e.g. for ImageMenuItem)
+ */
+ gtk_widget_get_preferred_width (child, &child_min, &child_nat);
+
+ gtk_menu_item_toggle_size_request (GTK_MENU_ITEM (child), &toggle_size);
+ max_toggle_size = MAX (max_toggle_size, toggle_size);
+ max_accel_width = MAX (max_accel_width,
+ GTK_MENU_ITEM (child)->priv->accelerator_width);
+
+ part = child_min / (r - l);
+ min_width = MAX (min_width, part);