menu: Adapt scroll offset if arrow is shown
When a popup is placed using move_to_rect(), it'll get feedback about the position and size it got assigned. We use this feedback to update the scroll offset, but while doing so, if the visibility of the arrow changed, we didn't adapt the offset accordingly. Fix this by offsetting the provided offset by the height of the arrow, if it was made visible as a side effect of the scroll offset change triggered by the feedback. Related: mutter#105 Closes: #1463
This commit is contained in:
parent
3e586a82e6
commit
c35878ecf1
@ -213,6 +213,12 @@ enum {
|
||||
CHILD_PROP_BOTTOM_ATTACH
|
||||
};
|
||||
|
||||
typedef enum _GtkMenuScrollFlag
|
||||
{
|
||||
GTK_MENU_SCROLL_FLAG_NONE = 0,
|
||||
GTK_MENU_SCROLL_FLAG_ADAPT = 1 << 0,
|
||||
} GtkMenuScrollFlag;
|
||||
|
||||
static void gtk_menu_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
@ -255,7 +261,8 @@ static gboolean gtk_menu_enter_notify (GtkWidget *widget,
|
||||
static gboolean gtk_menu_leave_notify (GtkWidget *widget,
|
||||
GdkEventCrossing *event);
|
||||
static void gtk_menu_scroll_to (GtkMenu *menu,
|
||||
gint offset);
|
||||
gint offset,
|
||||
GtkMenuScrollFlag flags);
|
||||
static void gtk_menu_grab_notify (GtkWidget *widget,
|
||||
gboolean was_grabbed);
|
||||
static gboolean gtk_menu_captured_event (GtkWidget *widget,
|
||||
@ -1977,7 +1984,7 @@ gtk_menu_popup_internal (GtkMenu *menu,
|
||||
|
||||
associate_menu_grab_transfer_window (menu);
|
||||
|
||||
gtk_menu_scroll_to (menu, priv->scroll_offset);
|
||||
gtk_menu_scroll_to (menu, priv->scroll_offset, GTK_MENU_SCROLL_FLAG_NONE);
|
||||
|
||||
/* if no item is selected, select the first one */
|
||||
if (!menu_shell->priv->active_menu_item &&
|
||||
@ -2479,7 +2486,8 @@ gtk_menu_update_scroll_offset (GtkMenu *menu,
|
||||
|
||||
get_arrows_border (menu, &arrows_border);
|
||||
menu->priv->scroll_offset = arrows_border.top + (final_rect->y - flipped_rect->y);
|
||||
gtk_menu_scroll_to (menu, menu->priv->scroll_offset);
|
||||
gtk_menu_scroll_to (menu, menu->priv->scroll_offset,
|
||||
GTK_MENU_SCROLL_FLAG_ADAPT);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2552,7 +2560,8 @@ gtk_menu_popdown (GtkMenu *menu)
|
||||
* non-tearoff menu was popped down.
|
||||
*/
|
||||
if (!priv->tearoff_active)
|
||||
gtk_menu_scroll_to (menu, priv->saved_scroll_offset);
|
||||
gtk_menu_scroll_to (menu, priv->saved_scroll_offset,
|
||||
GTK_MENU_SCROLL_FLAG_NONE);
|
||||
priv->tearoff_active = TRUE;
|
||||
}
|
||||
else
|
||||
@ -2843,7 +2852,7 @@ gtk_menu_scrollbar_changed (GtkAdjustment *adjustment,
|
||||
|
||||
value = gtk_adjustment_get_value (adjustment);
|
||||
if (menu->priv->scroll_offset != value)
|
||||
gtk_menu_scroll_to (menu, value);
|
||||
gtk_menu_scroll_to (menu, value, GTK_MENU_SCROLL_FLAG_NONE);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -3036,7 +3045,7 @@ gtk_menu_set_tearoff_state (GtkMenu *menu,
|
||||
gtk_widget_show (GTK_WIDGET (menu));
|
||||
gtk_widget_show (priv->tearoff_window);
|
||||
|
||||
gtk_menu_scroll_to (menu, 0);
|
||||
gtk_menu_scroll_to (menu, 0, GTK_MENU_SCROLL_FLAG_NONE);
|
||||
|
||||
}
|
||||
else
|
||||
@ -3482,7 +3491,7 @@ gtk_menu_size_allocate (GtkWidget *widget,
|
||||
height = allocation->height - (2 * border_width) - padding.top - padding.bottom;
|
||||
|
||||
if (menu_shell->priv->active)
|
||||
gtk_menu_scroll_to (menu, priv->scroll_offset);
|
||||
gtk_menu_scroll_to (menu, priv->scroll_offset, GTK_MENU_SCROLL_FLAG_NONE);
|
||||
|
||||
get_arrows_border (menu, &arrow_border);
|
||||
|
||||
@ -3590,7 +3599,7 @@ gtk_menu_size_allocate (GtkWidget *widget,
|
||||
gtk_widget_hide (priv->tearoff_scrollbar);
|
||||
gtk_menu_set_tearoff_hints (menu, allocation->width);
|
||||
|
||||
gtk_menu_scroll_to (menu, 0);
|
||||
gtk_menu_scroll_to (menu, 0, GTK_MENU_SCROLL_FLAG_NONE);
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -4168,7 +4177,7 @@ gtk_menu_scroll_by (GtkMenu *menu,
|
||||
offset = priv->requested_height - view_height;
|
||||
|
||||
if (offset != priv->scroll_offset)
|
||||
gtk_menu_scroll_to (menu, offset);
|
||||
gtk_menu_scroll_to (menu, offset, GTK_MENU_SCROLL_FLAG_NONE);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@ -4678,7 +4687,7 @@ gtk_menu_captured_event (GtkWidget *widget,
|
||||
MIN (priv->scroll_offset, 0),
|
||||
MAX (priv->scroll_offset, priv->requested_height - view_height));
|
||||
|
||||
gtk_menu_scroll_to (menu, offset);
|
||||
gtk_menu_scroll_to (menu, offset, GTK_MENU_SCROLL_FLAG_NONE);
|
||||
|
||||
retval = TRUE;
|
||||
}
|
||||
@ -5323,11 +5332,26 @@ gtk_menu_stop_scrolling (GtkMenu *menu)
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_menu_scroll_to (GtkMenu *menu,
|
||||
gint offset)
|
||||
sync_arrows_state (GtkMenu *menu)
|
||||
{
|
||||
GtkMenuPrivate *priv = menu->priv;
|
||||
GtkCssNode *top_arrow_node, *bottom_arrow_node;
|
||||
|
||||
top_arrow_node = gtk_css_gadget_get_node (priv->top_arrow_gadget);
|
||||
gtk_css_node_set_visible (top_arrow_node, priv->upper_arrow_visible);
|
||||
gtk_css_node_set_state (top_arrow_node, priv->upper_arrow_state);
|
||||
|
||||
bottom_arrow_node = gtk_css_gadget_get_node (priv->bottom_arrow_gadget);
|
||||
gtk_css_node_set_visible (bottom_arrow_node, priv->lower_arrow_visible);
|
||||
gtk_css_node_set_state (bottom_arrow_node, priv->lower_arrow_state);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_menu_scroll_to (GtkMenu *menu,
|
||||
gint offset,
|
||||
GtkMenuScrollFlag flags)
|
||||
{
|
||||
GtkMenuPrivate *priv = menu->priv;
|
||||
GtkBorder arrow_border, padding;
|
||||
GtkWidget *widget;
|
||||
gint x, y;
|
||||
@ -5363,13 +5387,25 @@ gtk_menu_scroll_to (GtkMenu *menu,
|
||||
{
|
||||
GtkStateFlags upper_arrow_previous_state = priv->upper_arrow_state;
|
||||
GtkStateFlags lower_arrow_previous_state = priv->lower_arrow_state;
|
||||
gboolean should_offset_by_arrow;
|
||||
|
||||
if (!priv->upper_arrow_visible || !priv->lower_arrow_visible)
|
||||
gtk_widget_queue_draw (GTK_WIDGET (menu));
|
||||
|
||||
if (!priv->upper_arrow_visible &
|
||||
flags & GTK_MENU_SCROLL_FLAG_ADAPT)
|
||||
should_offset_by_arrow = TRUE;
|
||||
else
|
||||
should_offset_by_arrow = FALSE;
|
||||
|
||||
priv->upper_arrow_visible = priv->lower_arrow_visible = TRUE;
|
||||
|
||||
if (flags & GTK_MENU_SCROLL_FLAG_ADAPT)
|
||||
sync_arrows_state (menu);
|
||||
|
||||
get_arrows_border (menu, &arrow_border);
|
||||
if (should_offset_by_arrow)
|
||||
offset += arrow_border.top;
|
||||
y += arrow_border.top;
|
||||
view_height -= arrow_border.top;
|
||||
view_height -= arrow_border.bottom;
|
||||
@ -5436,13 +5472,7 @@ gtk_menu_scroll_to (GtkMenu *menu,
|
||||
}
|
||||
}
|
||||
|
||||
top_arrow_node = gtk_css_gadget_get_node (priv->top_arrow_gadget);
|
||||
gtk_css_node_set_visible (top_arrow_node, priv->upper_arrow_visible);
|
||||
gtk_css_node_set_state (top_arrow_node, priv->upper_arrow_state);
|
||||
|
||||
bottom_arrow_node = gtk_css_gadget_get_node (priv->bottom_arrow_gadget);
|
||||
gtk_css_node_set_visible (bottom_arrow_node, priv->lower_arrow_visible);
|
||||
gtk_css_node_set_state (bottom_arrow_node, priv->lower_arrow_state);
|
||||
sync_arrows_state (menu);
|
||||
|
||||
/* Scroll the menu: */
|
||||
if (gtk_widget_get_realized (widget))
|
||||
@ -5528,7 +5558,7 @@ gtk_menu_scroll_item_visible (GtkMenuShell *menu_shell,
|
||||
* is on the menu
|
||||
*/
|
||||
menu_shell->priv->ignore_enter = TRUE;
|
||||
gtk_menu_scroll_to (menu, child_offset);
|
||||
gtk_menu_scroll_to (menu, child_offset, GTK_MENU_SCROLL_FLAG_NONE);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -5549,7 +5579,7 @@ gtk_menu_scroll_item_visible (GtkMenuShell *menu_shell,
|
||||
* is on the menu
|
||||
*/
|
||||
menu_shell->priv->ignore_enter = TRUE;
|
||||
gtk_menu_scroll_to (menu, y);
|
||||
gtk_menu_scroll_to (menu, y, GTK_MENU_SCROLL_FLAG_NONE);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -6033,7 +6063,7 @@ gtk_menu_real_move_scroll (GtkMenu *menu,
|
||||
new_offset = priv->scroll_offset + step;
|
||||
new_offset = CLAMP (new_offset, 0, end_position - page_size);
|
||||
|
||||
gtk_menu_scroll_to (menu, new_offset);
|
||||
gtk_menu_scroll_to (menu, new_offset, GTK_MENU_SCROLL_FLAG_NONE);
|
||||
|
||||
if (menu_shell->priv->active_menu_item)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user