}
}
+static void
+get_arrows_border (GtkMenu *menu, GtkBorder *border)
+{
+ guint scroll_arrow_height;
+
+ gtk_widget_style_get (GTK_WIDGET (menu),
+ "scroll-arrow-vlength", &scroll_arrow_height,
+ NULL);
+
+ border->top = menu->upper_arrow_visible ? scroll_arrow_height : 0;
+ border->bottom = menu->lower_arrow_visible ? scroll_arrow_height : 0;
+
+ border->left = border->right = 0;
+}
+
static void
gtk_menu_realize (GtkWidget *widget)
{
GList *children;
guint vertical_padding;
guint horizontal_padding;
- guint scroll_arrow_height;
+ GtkBorder arrow_border;
g_return_if_fail (GTK_IS_MENU (widget));
gtk_widget_style_get (GTK_WIDGET (menu),
"vertical-padding", &vertical_padding,
"horizontal-padding", &horizontal_padding,
- "scroll-arrow-vlength", &scroll_arrow_height,
NULL);
attributes.x = border_width + widget->style->xthickness + horizontal_padding;
attributes.width = MAX (1, widget->allocation.width - attributes.x * 2);
attributes.height = MAX (1, widget->allocation.height - attributes.y * 2);
- if (menu->upper_arrow_visible)
- {
- attributes.y += scroll_arrow_height;
- attributes.height -= scroll_arrow_height;
- }
-
- if (menu->lower_arrow_visible)
- attributes.height -= scroll_arrow_height;
+ get_arrows_border (menu, &arrow_border);
+ attributes.y += arrow_border.top;
+ attributes.height -= arrow_border.top;
+ attributes.height -= arrow_border.bottom;
menu->view_window = gdk_window_new (widget->window, &attributes, attributes_mask);
gdk_window_set_user_data (menu->view_window, menu);
gint width, height;
guint vertical_padding;
guint horizontal_padding;
- gint scroll_arrow_height;
g_return_if_fail (GTK_IS_MENU (widget));
g_return_if_fail (allocation != NULL);
gtk_widget_style_get (GTK_WIDGET (menu),
"vertical-padding", &vertical_padding,
"horizontal-padding", &horizontal_padding,
- "scroll-arrow-vlength", &scroll_arrow_height,
NULL);
x = GTK_CONTAINER (menu)->border_width + widget->style->xthickness + horizontal_padding;
if (menu_shell->active)
gtk_menu_scroll_to (menu, menu->scroll_offset);
- if (menu->upper_arrow_visible && !menu->tearoff_active)
+ if (!menu->tearoff_active)
{
- y += scroll_arrow_height;
- height -= scroll_arrow_height;
- }
+ GtkBorder arrow_border;
- if (menu->lower_arrow_visible && !menu->tearoff_active)
- height -= scroll_arrow_height;
+ get_arrows_border (menu, &arrow_border);
+ y += arrow_border.top;
+ height -= arrow_border.top;
+ height -= arrow_border.bottom;
+ }
if (GTK_WIDGET_REALIZED (widget))
{
}
}
+static void
+get_arrows_visible_area (GtkMenu *menu,
+ GdkRectangle *border,
+ GdkRectangle *upper,
+ GdkRectangle *lower,
+ gint *arrow_space)
+{
+ GtkWidget *widget = GTK_WIDGET (menu);
+ guint vertical_padding;
+ guint horizontal_padding;
+ gint scroll_arrow_height;
+
+ gtk_widget_style_get (widget,
+ "vertical-padding", &vertical_padding,
+ "horizontal-padding", &horizontal_padding,
+ "scroll-arrow-vlength", &scroll_arrow_height,
+ NULL);
+
+ border->x = GTK_CONTAINER (widget)->border_width + widget->style->xthickness + horizontal_padding;
+ border->y = GTK_CONTAINER (widget)->border_width + widget->style->ythickness + vertical_padding;
+ gdk_drawable_get_size (widget->window, &border->width, &border->height);
+
+ 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;
+
+ *arrow_space = scroll_arrow_height - 2 * widget->style->ythickness;
+}
+
static void
gtk_menu_paint (GtkWidget *widget,
GdkEventExpose *event)
{
GtkMenu *menu;
GtkMenuPrivate *priv;
- gint width, height;
- gint border_x, border_y;
- guint vertical_padding;
- guint horizontal_padding;
- gint scroll_arrow_height;
+ GdkRectangle border;
+ GdkRectangle upper;
+ GdkRectangle lower;
+ gint arrow_space;
g_return_if_fail (GTK_IS_MENU (widget));
menu = GTK_MENU (widget);
priv = gtk_menu_get_private (menu);
- gtk_widget_style_get (GTK_WIDGET (menu),
- "vertical-padding", &vertical_padding,
- "horizontal-padding", &horizontal_padding,
- "scroll-arrow-vlength", &scroll_arrow_height,
- NULL);
-
- border_x = GTK_CONTAINER (widget)->border_width + widget->style->xthickness + horizontal_padding;
- border_y = GTK_CONTAINER (widget)->border_width + widget->style->ythickness + vertical_padding;
- gdk_drawable_get_size (widget->window, &width, &height);
+ get_arrows_visible_area (menu, &border, &upper, &lower, &arrow_space);
if (event->window == widget->window)
{
- gint arrow_space = scroll_arrow_height - 2 * widget->style->ythickness;
gint arrow_size = 0.7 * arrow_space;
gtk_paint_box (widget->style,
priv->upper_arrow_state,
GTK_SHADOW_OUT,
&event->area, widget, "menu",
- border_x,
- border_y,
- width - 2 * border_x,
- scroll_arrow_height);
+ upper.x,
+ upper.y,
+ upper.width,
+ upper.height);
gtk_paint_arrow (widget->style,
widget->window,
&event->area, widget, "menu_scroll_arrow_up",
GTK_ARROW_UP,
TRUE,
- (width - arrow_size ) / 2,
- border_y + widget->style->ythickness + (arrow_space - arrow_size)/2,
+ upper.x + (upper.width - arrow_size) / 2,
+ upper.y + widget->style->ythickness + (arrow_space - arrow_size) / 2,
arrow_size, arrow_size);
}
priv->lower_arrow_state,
GTK_SHADOW_OUT,
&event->area, widget, "menu",
- border_x,
- height - border_y - scroll_arrow_height,
- width - 2*border_x,
- scroll_arrow_height);
+ lower.x,
+ lower.y,
+ lower.width,
+ lower.height);
gtk_paint_arrow (widget->style,
widget->window,
&event->area, widget, "menu_scroll_arrow_down",
GTK_ARROW_DOWN,
TRUE,
- (width - arrow_size) / 2,
- height - border_y - scroll_arrow_height +
- widget->style->ythickness + (arrow_space - arrow_size)/2,
+ lower.x + (lower.width - arrow_size) / 2,
+ lower.y + widget->style->ythickness + (arrow_space - arrow_size) / 2,
arrow_size, arrow_size);
}
}
else if (event->window == menu->bin_window)
{
- gint y = -border_y + menu->scroll_offset;
+ gint y = -border.y + menu->scroll_offset;
- if (menu->upper_arrow_visible && !menu->tearoff_active)
- y -= scroll_arrow_height;
+ if (!menu->tearoff_active)
+ {
+ GtkBorder arrow_border;
+
+ get_arrows_border (menu, &arrow_border);
+ y -= arrow_border.top;
+ }
gtk_paint_box (widget->style,
menu->bin_window,
GTK_STATE_NORMAL,
GTK_SHADOW_OUT,
&event->area, widget, "menu",
- - border_x, y,
- width, height);
+ - border.x, y,
+ border.width, border.height);
}
}
gint offset;
gint view_width, view_height;
gboolean double_arrows;
- gint scroll_arrow_height;
+ GtkBorder arrow_border;
widget = GTK_WIDGET (menu);
offset = menu->scroll_offset + step;
- gtk_widget_style_get (GTK_WIDGET (menu),
- "scroll-arrow-vlength", &scroll_arrow_height,
- NULL);
+ get_arrows_border (menu, &arrow_border);
double_arrows = get_double_arrows (menu);
* screen space than just scrolling to the top.
*/
if (!double_arrows)
- if ((step < 0) && (offset < scroll_arrow_height))
+ if ((step < 0) && (offset < arrow_border.top))
offset = 0;
/* Don't scroll over the top if we weren't before: */
/* Don't scroll past the bottom if we weren't before: */
if (menu->scroll_offset > 0)
- view_height -= scroll_arrow_height;
+ view_height -= arrow_border.top;
/* When both arrows are always shown, reduce
* view height even more.
*/
if (double_arrows)
- view_height -= scroll_arrow_height;
+ view_height -= arrow_border.bottom;
if ((menu->scroll_offset + view_height <= widget->requisition.height) &&
(offset + view_height > widget->requisition.height))
return TRUE;
}
+static void
+get_arrows_sensitive_area (GtkMenu *menu,
+ GdkRectangle *upper,
+ GdkRectangle *lower)
+{
+ gint width, height;
+ gint border;
+ guint vertical_padding;
+ gint win_x, win_y;
+ gint scroll_arrow_height;
+
+ gdk_drawable_get_size (GTK_WIDGET (menu)->window, &width, &height);
+
+ gtk_widget_style_get (GTK_WIDGET (menu),
+ "vertical-padding", &vertical_padding,
+ "scroll-arrow-vlength", &scroll_arrow_height,
+ NULL);
+
+ border = GTK_CONTAINER (menu)->border_width +
+ GTK_WIDGET (menu)->style->ythickness + vertical_padding;
+
+ gdk_window_get_position (GTK_WIDGET (menu)->window, &win_x, &win_y);
+
+ if (upper)
+ {
+ upper->x = win_x;
+ upper->y = win_y;
+ upper->width = width;
+ upper->height = scroll_arrow_height + border;
+ }
+
+ if (lower)
+ {
+ lower->x = win_x;
+ lower->y = win_y + height - border - scroll_arrow_height;
+ lower->width = width;
+ lower->height = scroll_arrow_height + border;
+ }
+}
+
+
static void
gtk_menu_handle_scrolling (GtkMenu *menu,
gint x,
{
GtkMenuShell *menu_shell;
GtkMenuPrivate *priv;
- gint width, height;
- gint border;
GdkRectangle rect;
gboolean in_arrow;
gboolean scroll_fast = FALSE;
- guint vertical_padding;
gint top_x, top_y;
- gint win_x, win_y;
gboolean touchscreen_mode;
- gint scroll_arrow_height;
priv = gtk_menu_get_private (menu);
menu_shell = GTK_MENU_SHELL (menu);
- gdk_drawable_get_size (GTK_WIDGET (menu)->window, &width, &height);
-
g_object_get (gtk_widget_get_settings (GTK_WIDGET (menu)),
"gtk-touchscreen-mode", &touchscreen_mode,
NULL);
- gtk_widget_style_get (GTK_WIDGET (menu),
- "vertical-padding", &vertical_padding,
- "scroll-arrow-vlength", &scroll_arrow_height,
- NULL);
-
- border = GTK_CONTAINER (menu)->border_width +
- GTK_WIDGET (menu)->style->ythickness + vertical_padding;
-
gdk_window_get_position (menu->toplevel->window, &top_x, &top_y);
x -= top_x;
y -= top_y;
- gdk_window_get_position (GTK_WIDGET (menu)->window, &win_x, &win_y);
-
/* upper arrow handling */
- rect.x = win_x;
- rect.y = win_y;
- rect.width = width;
- rect.height = scroll_arrow_height + border;
+ get_arrows_sensitive_area (menu, &rect, NULL);
in_arrow = FALSE;
if (menu->upper_arrow_visible && !menu->tearoff_active &&
/* lower arrow handling */
- rect.x = win_x;
- rect.y = win_y + height - border - scroll_arrow_height;
- rect.width = width;
- rect.height = scroll_arrow_height + border;
+ get_arrows_sensitive_area (menu, NULL, &rect);
in_arrow = FALSE;
if (menu->lower_arrow_visible && !menu->tearoff_active &&
GdkScreen *screen;
GdkScreen *pointer_screen;
GdkRectangle monitor;
- gint scroll_arrow_height;
g_return_if_fail (GTK_IS_MENU (menu));
screen = gtk_widget_get_screen (widget);
gdk_display_get_pointer (gdk_screen_get_display (screen),
&pointer_screen, &x, &y, NULL);
-
- gtk_widget_style_get (GTK_WIDGET (menu),
- "scroll-arrow-vlength", &scroll_arrow_height,
- NULL);
/* We need the requisition to figure out the right place to
* popup the menu. In fact, we always need to ask here, since
}
if (scroll_offset > 0)
- scroll_offset += scroll_arrow_height;
+ {
+ GtkBorder arrow_border;
+
+ get_arrows_border (menu, &arrow_border);
+ scroll_offset += arrow_border.top;
+ }
gtk_window_move (GTK_WINDOW (GTK_MENU_SHELL (menu)->active ? menu->toplevel : menu->tearoff_window),
x, y);
guint vertical_padding;
guint horizontal_padding;
gboolean double_arrows;
- gint scroll_arrow_height;
+ GtkBorder arrow_border;
widget = GTK_WIDGET (menu);
gtk_widget_style_get (GTK_WIDGET (menu),
"vertical-padding", &vertical_padding,
"horizontal-padding", &horizontal_padding,
- "scroll-arrow-vlength", &scroll_arrow_height,
NULL);
double_arrows = get_double_arrows (menu);
if (!menu->upper_arrow_visible || !menu->lower_arrow_visible)
gtk_widget_queue_draw (GTK_WIDGET (menu));
- view_height -= 2 * scroll_arrow_height;
- y += scroll_arrow_height;
-
menu->upper_arrow_visible = menu->lower_arrow_visible = TRUE;
+ get_arrows_border (menu, &arrow_border);
+ y += arrow_border.top;
+ view_height -= arrow_border.top;
+ view_height -= arrow_border.bottom;
+
if (offset <= 0)
priv->upper_arrow_state = GTK_STATE_INSENSITIVE;
else if (priv->upper_arrow_state == GTK_STATE_INSENSITIVE)
last_visible = menu->upper_arrow_visible;
menu->upper_arrow_visible = offset > 0;
- if (menu->upper_arrow_visible)
- view_height -= scroll_arrow_height;
+ /* upper_arrow_visible may have changed, so requery the border */
+ get_arrows_border (menu, &arrow_border);
+ view_height -= arrow_border.top;
if ((last_visible != menu->upper_arrow_visible) &&
!menu->upper_arrow_visible)
last_visible = menu->lower_arrow_visible;
menu->lower_arrow_visible = offset < menu_height - view_height;
- if (menu->lower_arrow_visible)
- view_height -= scroll_arrow_height;
+ /* lower_arrow_visible may have changed, so requery the border */
+ get_arrows_border (menu, &arrow_border);
+ view_height -= arrow_border.bottom;
if ((last_visible != menu->lower_arrow_visible) &&
!menu->lower_arrow_visible)
}
}
- if (menu->upper_arrow_visible)
- y += scroll_arrow_height;
+ y += arrow_border.top;
}
/* Scroll the menu: */
{
guint vertical_padding;
gboolean double_arrows;
- gint scroll_arrow_height;
y = menu->scroll_offset;
gdk_drawable_get_size (GTK_WIDGET (menu)->window, &width, &height);
gtk_widget_style_get (GTK_WIDGET (menu),
"vertical-padding", &vertical_padding,
- "scroll-arrow-vlength", &scroll_arrow_height,
NULL);
double_arrows = get_double_arrows (menu);
}
else
{
- arrow_height = 0;
- if (menu->upper_arrow_visible && !menu->tearoff_active)
- arrow_height += scroll_arrow_height;
- if (menu->lower_arrow_visible && !menu->tearoff_active)
- arrow_height += scroll_arrow_height;
+ GtkBorder arrow_border;
+
+ arrow_height = 0;
+
+ get_arrows_border (menu, &arrow_border);
+ if (!menu->tearoff_active)
+ arrow_height = arrow_border.top + arrow_border.bottom;
if (child_offset + child_height > y + height - arrow_height)
{
arrow_height = 0;
if ((!last_child && !menu->tearoff_active) || double_arrows)
- arrow_height += scroll_arrow_height;
+ arrow_height += arrow_border.bottom;
y = child_offset + child_height - height + arrow_height;
if (((y > 0) && !menu->tearoff_active) || double_arrows)
{
/* Need upper arrow */
- arrow_height += scroll_arrow_height;
+ arrow_height += arrow_border.top;
y = child_offset + child_height - height + arrow_height;
}
/* Ignore the enter event we might get if the pointer is on the menu
{
GtkWidget *widget = GTK_WIDGET (menu);
GtkContainer *container = GTK_CONTAINER (menu);
- gint scroll_arrow_height;
gint menu_height = (widget->allocation.height
- 2 * (container->border_width
+ widget->style->ythickness));
-
- gtk_widget_style_get (GTK_WIDGET (menu),
- "scroll-arrow-vlength", &scroll_arrow_height,
- NULL);
- if (menu->upper_arrow_visible && !menu->tearoff_active)
- menu_height -= scroll_arrow_height;
- if (menu->lower_arrow_visible && !menu->tearoff_active)
- menu_height -= scroll_arrow_height;
+ if (!menu->tearoff_active)
+ {
+ GtkBorder arrow_border;
+ get_arrows_border (menu, &arrow_border);
+ menu_height -= arrow_border.top;
+ menu_height -= arrow_border.bottom;
+ }
+
return menu_height;
}
{
gint height;
GtkWidget *widget = GTK_WIDGET (menu);
- gint scroll_arrow_height;
- gtk_widget_style_get (GTK_WIDGET (menu),
- "scroll-arrow-vlength", &scroll_arrow_height,
- NULL);
-
height = widget->requisition.height;
height -= (GTK_CONTAINER (widget)->border_width + widget->style->ythickness) * 2;
- if (menu->upper_arrow_visible && !menu->tearoff_active)
- height -= scroll_arrow_height;
+ if (!menu->tearoff_active)
+ {
+ GtkBorder arrow_border;
- if (menu->lower_arrow_visible && !menu->tearoff_active)
- height -= scroll_arrow_height;
+ get_arrows_border (menu, &arrow_border);
+ height -= arrow_border.top;
+ height -= arrow_border.bottom;
+ }
return height;
}
gint page_size = get_visible_size (menu);
gint end_position = get_menu_height (menu);
GtkMenuShell *menu_shell = GTK_MENU_SHELL (menu);
- gint scroll_arrow_height;
-
- gtk_widget_style_get (GTK_WIDGET (menu),
- "scroll-arrow-vlength", &scroll_arrow_height,
- NULL);
switch (type)
{
{
GtkWidget *new_child;
gboolean new_upper_arrow_visible = menu->upper_arrow_visible && !menu->tearoff_active;
+ GtkBorder arrow_border;
+
+ get_arrows_border (menu, &arrow_border);
if (menu->scroll_offset != old_offset)
step = menu->scroll_offset - old_offset;
- step -= (new_upper_arrow_visible - old_upper_arrow_visible) * scroll_arrow_height;
+ step -= (new_upper_arrow_visible - old_upper_arrow_visible) * arrow_border.top;
new_child = child_at (menu, child_offset + step);
if (new_child)