summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Clasen <mclasen@redhat.com>2021-05-24 17:27:40 -0400
committerMatthias Clasen <mclasen@redhat.com>2021-05-24 17:27:40 -0400
commita74420bc1a501f6ee951ed152e8f9a941b0c8438 (patch)
treedb1d1343deb5aa5acf3f1efb6b32d04c93a6f25b
parentb05f3f5614a310de05fb8292e96611aade429a1e (diff)
downloadgtk+-a74420bc1a501f6ee951ed152e8f9a941b0c8438.tar.gz
menubutton: Enable F10 for primary menus
Add a ::primary property to GtkMenuButton, which can be set to make the menu activatable with F10, like menubars.
-rw-r--r--gtk/gtkmenubutton.c136
-rw-r--r--gtk/gtkmenubutton.h6
-rw-r--r--gtk/gtkwindow.c6
3 files changed, 147 insertions, 1 deletions
diff --git a/gtk/gtkmenubutton.c b/gtk/gtkmenubutton.c
index d3b85ea72a..6c9a624831 100644
--- a/gtk/gtkmenubutton.c
+++ b/gtk/gtkmenubutton.c
@@ -97,6 +97,7 @@
#include "gtkwidgetprivate.h"
#include "gtkbuttonprivate.h"
#include "gtknative.h"
+#include "gtkwindow.h"
typedef struct _GtkMenuButtonClass GtkMenuButtonClass;
typedef struct _GtkMenuButtonPrivate GtkMenuButtonPrivate;
@@ -116,6 +117,8 @@ struct _GtkMenuButton
GtkWidget *label_widget;
GtkWidget *arrow_widget;
GtkArrowType arrow_type;
+
+ gboolean primary;
};
struct _GtkMenuButtonClass
@@ -133,6 +136,7 @@ enum
PROP_LABEL,
PROP_USE_UNDERLINE,
PROP_HAS_FRAME,
+ PROP_PRIMARY,
LAST_PROP
};
@@ -173,6 +177,9 @@ gtk_menu_button_set_property (GObject *object,
case PROP_HAS_FRAME:
gtk_menu_button_set_has_frame (self, g_value_get_boolean (value));
break;
+ case PROP_PRIMARY:
+ gtk_menu_button_set_primary (self, g_value_get_boolean (value));
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
}
@@ -209,6 +216,9 @@ gtk_menu_button_get_property (GObject *object,
case PROP_HAS_FRAME:
g_value_set_boolean (value, gtk_menu_button_get_has_frame (GTK_MENU_BUTTON (object)));
break;
+ case PROP_PRIMARY:
+ g_value_set_boolean (value, gtk_menu_button_get_primary (GTK_MENU_BUTTON (object)));
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
}
@@ -326,6 +336,9 @@ gtk_menu_button_grab_focus (GtkWidget *widget)
return gtk_widget_grab_focus (self->button);
}
+static void gtk_menu_button_root (GtkWidget *widget);
+static void gtk_menu_button_unroot (GtkWidget *widget);
+
static void
gtk_menu_button_class_init (GtkMenuButtonClass *klass)
{
@@ -337,6 +350,8 @@ gtk_menu_button_class_init (GtkMenuButtonClass *klass)
gobject_class->notify = gtk_menu_button_notify;
gobject_class->dispose = gtk_menu_button_dispose;
+ widget_class->root = gtk_menu_button_root;
+ widget_class->unroot = gtk_menu_button_unroot;
widget_class->measure = gtk_menu_button_measure;
widget_class->size_allocate = gtk_menu_button_size_allocate;
widget_class->state_flags_changed = gtk_menu_button_state_flags_changed;
@@ -432,6 +447,20 @@ gtk_menu_button_class_init (GtkMenuButtonClass *klass)
TRUE,
GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
+ /**
+ * GtkMenuButton:primary: (attributes org.gtk.Property.get=gtk_menu_button_get_primary org.gtk.Property.set=gtk_menu_button_set_primary)
+ *
+ * Whether the menu button acts as a primary menu.
+ *
+ * Primary menus can be opened using the <kbd>F10</kbd> key
+ */
+ menu_button_props[PROP_PRIMARY] =
+ g_param_spec_boolean ("primary",
+ P_("Primary"),
+ P_("Whether the menubutton acts as a primary menu"),
+ FALSE,
+ GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
+
g_object_class_install_properties (gobject_class, LAST_PROP, menu_button_props);
gtk_widget_class_set_css_name (widget_class, I_("menubutton"));
@@ -1039,3 +1068,110 @@ gtk_menu_button_get_use_underline (GtkMenuButton *menu_button)
return gtk_button_get_use_underline (GTK_BUTTON (menu_button->button));
}
+
+static GList *
+get_menu_bars (GtkWindow *window)
+{
+ return g_object_get_data (G_OBJECT (window), "gtk-menu-bar-list");
+}
+
+static void
+set_menu_bars (GtkWindow *window,
+ GList *menubars)
+{
+ g_object_set_data (G_OBJECT (window), I_("gtk-menu-bar-list"), menubars);
+}
+
+static void
+add_to_window (GtkWindow *window,
+ GtkMenuButton *button)
+{
+ GList *menubars = get_menu_bars (window);
+
+ set_menu_bars (window, g_list_prepend (menubars, button));
+}
+
+static void
+remove_from_window (GtkWindow *window,
+ GtkMenuButton *button)
+{
+ GList *menubars = get_menu_bars (window);
+
+ menubars = g_list_remove (menubars, button);
+ set_menu_bars (window, menubars);
+}
+
+static void
+gtk_menu_button_root (GtkWidget *widget)
+{
+ GtkMenuButton *button = GTK_MENU_BUTTON (widget);
+
+ GTK_WIDGET_CLASS (gtk_menu_button_parent_class)->root (widget);
+
+ if (button->primary)
+ {
+ GtkWidget *toplevel = GTK_WIDGET (gtk_widget_get_root (widget));
+ add_to_window (GTK_WINDOW (toplevel), button);
+ }
+}
+
+static void
+gtk_menu_button_unroot (GtkWidget *widget)
+{
+ GtkWidget *toplevel;
+
+ toplevel = GTK_WIDGET (gtk_widget_get_root (widget));
+ remove_from_window (GTK_WINDOW (toplevel), GTK_MENU_BUTTON (widget));
+
+ GTK_WIDGET_CLASS (gtk_menu_button_parent_class)->unroot (widget);
+}
+
+/**
+ * gtk_menu_button_set_primary: (attributes org.gtk.Method.set_property=primary)
+ * @menu_button: a `GtkMenuButton`
+ * @primary: whether the menubutton should act as a primary menu
+ *
+ * Sets whether menu button acts as a primary menu.
+ *
+ * Primary menus can be opened with the <kbd>F10</kbd> key.
+ */
+void
+gtk_menu_button_set_primary (GtkMenuButton *menu_button,
+ gboolean primary)
+{
+ GtkRoot *toplevel;
+
+ g_return_if_fail (GTK_IS_MENU_BUTTON (menu_button));
+
+ if (menu_button->primary == primary)
+ return;
+
+ menu_button->primary = primary;
+ toplevel = gtk_widget_get_root (GTK_WIDGET (menu_button));
+
+ if (toplevel)
+ {
+ if (menu_button->primary)
+ add_to_window (GTK_WINDOW (toplevel), menu_button);
+ else
+ remove_from_window (GTK_WINDOW (toplevel), menu_button);
+ }
+
+ g_object_notify_by_pspec (G_OBJECT (menu_button), menu_button_props[PROP_PRIMARY]);
+}
+
+/**
+ * gtk_menu_button_get_primary: (attributes org.gtk.Method.get_property=primary)
+ * @menu_button: a `GtkMenuButton`
+ *
+ * Returns whether the menu button acts as a primary menu.
+ *
+ * Returns: %TRUE if the button is a primary menu
+ */
+gboolean
+gtk_menu_button_get_primary (GtkMenuButton *menu_button)
+{
+ g_return_val_if_fail (GTK_IS_MENU_BUTTON (menu_button), FALSE);
+
+ return menu_button->primary;
+}
diff --git a/gtk/gtkmenubutton.h b/gtk/gtkmenubutton.h
index 4ac9da798b..af71beedd6 100644
--- a/gtk/gtkmenubutton.h
+++ b/gtk/gtkmenubutton.h
@@ -109,6 +109,12 @@ void gtk_menu_button_set_create_popup_func (GtkMenuButton
gpointer user_data,
GDestroyNotify destroy_notify);
+GDK_AVAILABLE_IN_4_4
+void gtk_menu_button_set_primary (GtkMenuButton *menu_button,
+ gboolean primary);
+GDK_AVAILABLE_IN_4_4
+gboolean gtk_menu_button_get_primary (GtkMenuButton *menu_button);
+
G_END_DECLS
#endif /* __GTK_MENU_BUTTON_H__ */
diff --git a/gtk/gtkwindow.c b/gtk/gtkwindow.c
index 501341bd22..a826d890f1 100644
--- a/gtk/gtkwindow.c
+++ b/gtk/gtkwindow.c
@@ -64,6 +64,7 @@
#include "gtkpopovermenubarprivate.h"
#include "gtkcssboxesimplprivate.h"
#include "gtktooltipprivate.h"
+#include "gtkmenubutton.h"
#include "inspector/window.h"
@@ -5807,7 +5808,10 @@ gtk_window_activate_menubar (GtkWidget *widget,
gtk_widget_focus_sort (GTK_WIDGET (window), GTK_DIR_TAB_FORWARD, menubars);
first = g_ptr_array_index (menubars, 0);
- gtk_popover_menu_bar_select_first (GTK_POPOVER_MENU_BAR (first));
+ if (GTK_IS_POPOVER_MENU_BAR (first))
+ gtk_popover_menu_bar_select_first (GTK_POPOVER_MENU_BAR (first));
+ else if (GTK_IS_MENU_BUTTON (first))
+ gtk_menu_button_popup (GTK_MENU_BUTTON (first));
g_ptr_array_free (menubars, TRUE);