From 8ba3c7568264214bd8a069dc6a9d5d01f943dc38 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Fri, 31 May 2019 03:20:50 +0000 Subject: [PATCH] More menu work --- gtk/gtkcombobox.c | 13 +++++-- gtk/gtkmenu.c | 44 ++++++++++++++-------- gtk/gtkmenubar.c | 31 ++++++++++++++- gtk/gtkmenuitem.c | 2 +- gtk/gtkmenuitemprivate.h | 3 ++ gtk/gtkmenushell.c | 69 ++++------------------------------ gtk/gtkmenushell.h | 1 + gtk/gtkmenushellprivate.h | 3 +- gtk/gtktreemenu.c | 14 ++++--- gtk/theme/Adwaita/_common.scss | 2 +- 10 files changed, 90 insertions(+), 92 deletions(-) diff --git a/gtk/gtkcombobox.c b/gtk/gtkcombobox.c index 3d8afc863b..ea8c1f6968 100644 --- a/gtk/gtkcombobox.c +++ b/gtk/gtkcombobox.c @@ -1228,7 +1228,7 @@ update_menu_sensitivity (GtkComboBox *combo_box, if (!priv->model) return; - children = gtk_container_get_children (GTK_CONTAINER (menu)); + children = gtk_menu_shell_get_items (GTK_MENU_SHELL (menu)); for (child = children; child; child = child->next) { @@ -1321,20 +1321,24 @@ gtk_combo_box_menu_popup (GtkComboBox *combo_box) if (!(active && gtk_widget_get_visible (active))) { - for (i = GTK_MENU_SHELL (priv->popup_widget)->priv->children; i && !active; i = i->next) + GList *children; + children = gtk_menu_shell_get_items (GTK_MENU_SHELL (priv->popup_widget)); + for (i = children; i && !active; i = i->next) { child = i->data; if (child && gtk_widget_get_visible (child)) active = child; } + g_list_free (children); } if (active) { gint child_height; - - for (i = GTK_MENU_SHELL (priv->popup_widget)->priv->children; i && i->data != active; i = i->next) + GList *children; + children = gtk_menu_shell_get_items (GTK_MENU_SHELL (priv->popup_widget)); + for (i = children; i && i->data != active; i = i->next) { child = i->data; @@ -1345,6 +1349,7 @@ gtk_combo_box_menu_popup (GtkComboBox *combo_box) rect_anchor_dy -= child_height; } } + g_list_free (children); gtk_widget_measure (active, GTK_ORIENTATION_VERTICAL, -1, &child_height, NULL, NULL, NULL); diff --git a/gtk/gtkmenu.c b/gtk/gtkmenu.c index 98f1541184..fe69fc88cf 100644 --- a/gtk/gtkmenu.c +++ b/gtk/gtkmenu.c @@ -652,7 +652,11 @@ gtk_menu_get_property (GObject *object, switch (prop_id) { case PROP_ACTIVE: - g_value_set_int (value, g_list_index (GTK_MENU_SHELL (menu)->priv->children, gtk_menu_get_active (menu))); + { + GList *children = gtk_menu_shell_get_items (GTK_MENU_SHELL (menu)); + g_value_set_int (value, g_list_index (children, gtk_menu_get_active (menu))); + g_list_free (children); + } break; case PROP_ACCEL_GROUP: g_value_set_object (value, gtk_menu_get_accel_group (menu)); @@ -1015,6 +1019,8 @@ gtk_menu_remove (GtkContainer *container, gtk_container_remove (GTK_CONTAINER (priv->box), widget); + GTK_CONTAINER_CLASS (gtk_menu_parent_class)->remove (container, widget); + menu_queue_resize (menu); } @@ -1040,6 +1046,7 @@ gtk_menu_real_insert (GtkMenuShell *menu_shell, GtkMenuPrivate *priv = menu->priv; gtk_container_add (GTK_CONTAINER (priv->box), child); + gtk_menu_reorder_child (menu, child, position); menu_queue_resize (menu); } @@ -1639,7 +1646,7 @@ gtk_menu_get_active (GtkMenu *menu) { GtkMenuPrivate *priv; GtkWidget *child; - GList *children; + GList *children, *l; g_return_val_if_fail (GTK_IS_MENU (menu), NULL); @@ -1647,18 +1654,16 @@ gtk_menu_get_active (GtkMenu *menu) if (!priv->old_active_menu_item) { - child = NULL; - children = GTK_MENU_SHELL (menu)->priv->children; - - while (children) + children = gtk_menu_shell_get_items (GTK_MENU_SHELL (menu)); + for (l = children; l; l = l->next) { - child = children->data; - children = children->next; + child = l->data; if (gtk_bin_get_child (GTK_BIN (child))) break; child = NULL; } + g_list_free (children); priv->old_active_menu_item = child; if (priv->old_active_menu_item) @@ -1683,13 +1688,15 @@ gtk_menu_set_active (GtkMenu *menu, { GtkMenuPrivate *priv; GtkWidget *child; + GList *children; GList *tmp_list; g_return_if_fail (GTK_IS_MENU (menu)); priv = menu->priv; - tmp_list = g_list_nth (GTK_MENU_SHELL (menu)->priv->children, index); + children = gtk_menu_shell_get_items (GTK_MENU_SHELL (menu)); + tmp_list = g_list_nth (children, index); if (tmp_list) { child = tmp_list->data; @@ -1702,6 +1709,7 @@ gtk_menu_set_active (GtkMenu *menu, } } g_object_notify (G_OBJECT (menu), "active"); + g_list_free (children); } /** @@ -1904,20 +1912,24 @@ gtk_menu_reorder_child (GtkMenu *menu, GtkWidget *child, gint position) { - GtkMenuShell *menu_shell; + GtkWidget *sibling = NULL; + int i; g_return_if_fail (GTK_IS_MENU (menu)); g_return_if_fail (GTK_IS_MENU_ITEM (child)); - menu_shell = GTK_MENU_SHELL (menu); + if (position < 0) + sibling = gtk_widget_get_last_child (menu->priv->box); - if (g_list_find (menu_shell->priv->children, child)) + for (i = 0; i < position; i++) { - menu_shell->priv->children = g_list_remove (menu_shell->priv->children, child); - menu_shell->priv->children = g_list_insert (menu_shell->priv->children, child, position); - - menu_queue_resize (menu); + if (sibling == NULL) + sibling = gtk_widget_get_first_child (menu->priv->box); + else + sibling = gtk_widget_get_next_sibling (sibling); } + + gtk_box_reorder_child_after (GTK_BOX (menu->priv->box), child, sibling); } static gboolean diff --git a/gtk/gtkmenubar.c b/gtk/gtkmenubar.c index 165412318f..ce9a868d0b 100644 --- a/gtk/gtkmenubar.c +++ b/gtk/gtkmenubar.c @@ -351,9 +351,11 @@ _gtk_menu_bar_cycle_focus (GtkMenuBar *menubar, { GtkWidget *next = g_ptr_array_index (menubars, index + 1); GtkMenuShell *new_menushell = GTK_MENU_SHELL (next); + GList *children = gtk_menu_shell_get_items (new_menushell); - if (new_menushell->priv->children) - to_activate = new_menushell->priv->children->data; + if (children) + to_activate = children->data; + g_list_free (children); } g_ptr_array_free (menubars, TRUE); @@ -440,6 +442,30 @@ gtk_menu_bar_remove (GtkContainer *container, GtkMenuBar *menu_bar = GTK_MENU_BAR (container); gtk_container_remove (GTK_CONTAINER (menu_bar->box), widget); + + GTK_CONTAINER_CLASS (gtk_menu_bar_parent_class)->remove (container, widget); +} + +static void +gtk_menu_bar_reorder_child (GtkMenuBar *menu_bar, + GtkWidget *child, + gint position) +{ + GtkWidget *sibling = NULL; + int i; + + if (position < 0) + sibling = gtk_widget_get_last_child (menu_bar->box); + + for (i = 0; i < position; i++) + { + if (sibling == NULL) + sibling = gtk_widget_get_first_child (menu_bar->box); + else + sibling = gtk_widget_get_next_sibling (sibling); + } + + gtk_box_reorder_child_after (GTK_BOX (menu_bar->box), child, sibling); } static void @@ -450,4 +476,5 @@ gtk_menu_bar_insert (GtkMenuShell *menu_shell, GtkMenuBar *menu_bar = GTK_MENU_BAR (menu_shell); gtk_container_add (GTK_CONTAINER (menu_bar->box), child); + gtk_menu_bar_reorder_child (menu_bar, child, position); } diff --git a/gtk/gtkmenuitem.c b/gtk/gtkmenuitem.c index c0d46800a6..549c9b479c 100644 --- a/gtk/gtkmenuitem.c +++ b/gtk/gtkmenuitem.c @@ -262,7 +262,7 @@ gtk_menu_item_actionable_interface_init (GtkActionableInterface *iface) iface->get_action_target_value = gtk_menu_item_get_action_target_value; } -static GtkMenuShell * +GtkMenuShell * gtk_menu_item_get_menu_shell (GtkMenuItem *item) { return GTK_MENU_SHELL (gtk_widget_get_ancestor (GTK_WIDGET (item), GTK_TYPE_MENU_SHELL)); diff --git a/gtk/gtkmenuitemprivate.h b/gtk/gtkmenuitemprivate.h index 0008c1f187..7b461f100e 100644 --- a/gtk/gtkmenuitemprivate.h +++ b/gtk/gtkmenuitemprivate.h @@ -19,6 +19,7 @@ #define __GTK_MENU_ITEM_PRIVATE_H__ #include +#include #include #include #include @@ -56,6 +57,8 @@ gboolean _gtk_menu_item_is_selectable (GtkWidget *menu_item); void _gtk_menu_item_popup_submenu (GtkWidget *menu_item, gboolean with_delay); void _gtk_menu_item_popdown_submenu (GtkWidget *menu_item); +GtkMenuShell * + gtk_menu_item_get_menu_shell (GtkMenuItem *menu_item); G_END_DECLS diff --git a/gtk/gtkmenushell.c b/gtk/gtkmenushell.c index 7ae0a0a1d5..4ed273df34 100644 --- a/gtk/gtkmenushell.c +++ b/gtk/gtkmenushell.c @@ -137,12 +137,6 @@ static void gtk_menu_shell_add (GtkContainer *container, GtkWidget *widget); static void gtk_menu_shell_remove (GtkContainer *container, GtkWidget *widget); -static void gtk_menu_shell_forall (GtkContainer *container, - GtkCallback callback, - gpointer callback_data); -static void gtk_menu_shell_real_insert (GtkMenuShell *menu_shell, - GtkWidget *child, - gint position); static void gtk_real_menu_shell_deactivate (GtkMenuShell *menu_shell); static GType gtk_menu_shell_child_type (GtkContainer *container); static void gtk_menu_shell_real_select_item (GtkMenuShell *menu_shell, @@ -191,7 +185,6 @@ gtk_menu_shell_class_init (GtkMenuShellClass *klass) container_class->add = gtk_menu_shell_add; container_class->remove = gtk_menu_shell_remove; - container_class->forall = gtk_menu_shell_forall; container_class->child_type = gtk_menu_shell_child_type; klass->submenu_placement = GTK_TOP_BOTTOM; @@ -201,7 +194,6 @@ gtk_menu_shell_class_init (GtkMenuShellClass *klass) klass->activate_current = gtk_real_menu_shell_activate_current; klass->cancel = gtk_real_menu_shell_cancel; klass->select_item = gtk_menu_shell_real_select_item; - klass->insert = gtk_menu_shell_real_insert; klass->move_selected = gtk_menu_shell_real_move_selected; /** @@ -555,19 +547,6 @@ gtk_menu_shell_insert (GtkMenuShell *menu_shell, g_signal_emit (menu_shell, menu_shell_signals[INSERT], 0, child, position); } -static void -gtk_menu_shell_real_insert (GtkMenuShell *menu_shell, - GtkWidget *child, - gint position) -{ - GtkMenuShellPrivate *priv = menu_shell->priv; - - priv->children = g_list_insert (priv->children, child, position); - - if (gtk_widget_get_parent (child) == NULL) - gtk_widget_set_parent (child, GTK_WIDGET (menu_shell)); -} - /** * gtk_menu_shell_deactivate: * @menu_shell: a #GtkMenuShell @@ -656,16 +635,16 @@ click_pressed (GtkGestureClick *gesture, GtkMenuShellPrivate *priv = menu_shell->priv; GtkWidget *menu_item; GdkEvent *event; - GtkWidget *item_shell; + GtkMenuShell *item_shell; event = gtk_get_current_event (); menu_item = gtk_get_event_target_with_type (event, GTK_TYPE_MENU_ITEM); if (menu_item) - item_shell = gtk_widget_get_ancestor (GTK_WIDGET (menu_item), GTK_TYPE_MENU_SHELL); + item_shell = gtk_menu_item_get_menu_shell (GTK_MENU_ITEM (menu_item)); if (menu_item && _gtk_menu_item_is_selectable (menu_item) && - item_shell == GTK_WIDGET (menu_shell)) + item_shell == menu_shell) { if (menu_item != menu_shell->priv->active_menu_item) { @@ -702,7 +681,7 @@ click_pressed (GtkGestureClick *gesture, if (menu_item) { if (_gtk_menu_item_is_selectable (menu_item) && - item_shell == GTK_WIDGET (menu_shell) && + item_shell == menu_shell && menu_item != priv->active_menu_item) { priv->active = TRUE; @@ -798,7 +777,7 @@ click_released (GtkGestureClick *gesture, if (menu_item) { GtkWidget *submenu = GTK_MENU_ITEM (menu_item)->priv->submenu; - GtkWidget *parent_menu_item_shell = gtk_widget_get_parent (menu_item); + GtkMenuShell *parent_menu_item_shell = gtk_menu_item_get_menu_shell (GTK_MENU_ITEM (menu_item)); if (!_gtk_menu_item_is_selectable (GTK_WIDGET (menu_item))) return; @@ -967,46 +946,14 @@ gtk_menu_shell_remove (GtkContainer *container, { GtkMenuShell *menu_shell = GTK_MENU_SHELL (container); GtkMenuShellPrivate *priv = menu_shell->priv; - gint was_visible; - - was_visible = gtk_widget_get_visible (widget); - priv->children = g_list_remove (priv->children, widget); if (widget == priv->active_menu_item) { g_signal_emit_by_name (priv->active_menu_item, "deselect"); priv->active_menu_item = NULL; } - - gtk_widget_unparent (widget); - - /* Queue resize regardless of gtk_widget_get_visible (container), - * since that's what is needed by toplevels. - */ - if (was_visible) - gtk_widget_queue_resize (GTK_WIDGET (container)); } -static void -gtk_menu_shell_forall (GtkContainer *container, - GtkCallback callback, - gpointer callback_data) -{ - GtkMenuShell *menu_shell = GTK_MENU_SHELL (container); - GtkWidget *child; - GList *children; - - children = menu_shell->priv->children; - while (children) - { - child = children->data; - children = children->next; - - (* callback) (child, callback_data); - } -} - - static void gtk_real_menu_shell_deactivate (GtkMenuShell *menu_shell) { @@ -1197,7 +1144,7 @@ gtk_menu_shell_activate_item (GtkMenuShell *menu_shell, g_object_unref (menu_item); } -static GList * +GList * gtk_menu_shell_get_items (GtkMenuShell *menu_shell) { return GTK_MENU_SHELL_GET_CLASS (menu_shell)->get_items (menu_shell); @@ -1440,13 +1387,13 @@ gtk_real_menu_shell_move_current (GtkMenuShell *menu_shell, case GTK_MENU_DIR_PREV: gtk_menu_shell_move_selected (menu_shell, -1); - if (!had_selection && !priv->active_menu_item && priv->children) + if (!had_selection && !priv->active_menu_item) _gtk_menu_shell_select_last (menu_shell, TRUE); break; case GTK_MENU_DIR_NEXT: gtk_menu_shell_move_selected (menu_shell, 1); - if (!had_selection && !priv->active_menu_item && priv->children) + if (!had_selection && !priv->active_menu_item) gtk_menu_shell_select_first (menu_shell, TRUE); break; diff --git a/gtk/gtkmenushell.h b/gtk/gtkmenushell.h index 58b635def0..10274da35f 100644 --- a/gtk/gtkmenushell.h +++ b/gtk/gtkmenushell.h @@ -75,6 +75,7 @@ struct _GtkMenuShellClass gint (*get_popup_delay) (GtkMenuShell *menu_shell); gboolean (*move_selected) (GtkMenuShell *menu_shell, gint distance); + GList * (*get_items) (GtkMenuShell *menu_shell); /*< private >*/ gpointer padding[8]; diff --git a/gtk/gtkmenushellprivate.h b/gtk/gtkmenushellprivate.h index 9ea3fa281f..0c42c4d50d 100644 --- a/gtk/gtkmenushellprivate.h +++ b/gtk/gtkmenushellprivate.h @@ -36,8 +36,6 @@ typedef enum struct _GtkMenuShellPrivate { - GList *children; - GtkWidget *active_menu_item; /* This is not an "active" menu item * (there is no such thing) but rather, * the selected menu item in that MenuShell, @@ -92,6 +90,7 @@ void _gtk_menu_shell_update_mnemonics (GtkMenuShell *menu_shell); void _gtk_menu_shell_set_keyboard_mode (GtkMenuShell *menu_shell, gboolean keyboard_mode); gboolean _gtk_menu_shell_get_keyboard_mode (GtkMenuShell *menu_shell); +GList *gtk_menu_shell_get_items (GtkMenuShell *menu_shell); G_END_DECLS diff --git a/gtk/gtktreemenu.c b/gtk/gtktreemenu.c index f3f728f9ee..28a8ace5ca 100644 --- a/gtk/gtktreemenu.c +++ b/gtk/gtktreemenu.c @@ -800,6 +800,7 @@ row_changed_cb (GtkTreeModel *model, GtkTreeMenuPrivate *priv = menu->priv; gboolean is_separator = FALSE; GtkWidget *item; + GList *children; item = gtk_tree_menu_get_path_item (menu, path); @@ -814,7 +815,9 @@ row_changed_cb (GtkTreeModel *model, { /* Destroy the header item and then the following separator */ gtk_widget_destroy (item); - gtk_widget_destroy (GTK_MENU_SHELL (menu)->priv->children->data); + children = gtk_menu_shell_get_items (GTK_MENU_SHELL (menu)); + gtk_widget_destroy (children->data); + g_list_free (children); priv->menu_with_header = FALSE; } @@ -885,6 +888,7 @@ area_apply_attributes_cb (GtkCellArea *area, GtkWidget *item; gboolean is_header; gboolean sensitive; + GList *children; path = gtk_tree_model_get_path (tree_model, iter); @@ -905,14 +909,14 @@ area_apply_attributes_cb (GtkCellArea *area, /* For header items we need to set the sensitivity * of the following separator item */ - if (GTK_MENU_SHELL (menu)->priv->children && - GTK_MENU_SHELL (menu)->priv->children->next) + children = gtk_menu_shell_get_items (GTK_MENU_SHELL (menu)); + if (children && children->next) { - GtkWidget *separator = - GTK_MENU_SHELL (menu)->priv->children->next->data; + GtkWidget *separator = children->next->data; gtk_widget_set_sensitive (separator, sensitive); } + g_list_free (children); } } } diff --git a/gtk/theme/Adwaita/_common.scss b/gtk/theme/Adwaita/_common.scss index ecdaeccaaf..3c0759b135 100644 --- a/gtk/theme/Adwaita/_common.scss +++ b/gtk/theme/Adwaita/_common.scss @@ -2025,7 +2025,7 @@ menubar, &:backdrop { background-color: $backdrop_bg_color; } - > menuitem { + > box > menuitem { min-height: 16px; padding: 4px 8px;