[gtk/matthiasc/for-master] modelbutton: Fix keynav for check and radio




commit 6891f401107ce400729de86f75e7160d99c3f1cf
Author: Matthias Clasen <mclasen redhat com>
Date:   Sun Nov 15 21:52:07 2020 -0500

    modelbutton: Fix keynav for check and radio
    
    The expected behavior when activating check or radio
    menuitems via keynav is that Space toggles the item
    but keeps the menu open, while Return toggles the
    item and closes the menu.

 gtk/gtkmodelbutton.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 48 insertions(+), 1 deletion(-)
---
diff --git a/gtk/gtkmodelbutton.c b/gtk/gtkmodelbutton.c
index 9efed319aa..501dc5e087 100644
--- a/gtk/gtkmodelbutton.c
+++ b/gtk/gtkmodelbutton.c
@@ -179,6 +179,7 @@ struct _GtkModelButton
   guint active : 1;
   guint centered : 1;
   guint iconic : 1;
+  guint keep_open : 1;
 };
 
 typedef struct _GtkModelButtonClass GtkModelButtonClass;
@@ -1044,7 +1045,7 @@ gtk_model_button_clicked (GtkModelButton *self)
       gtk_popover_menu_set_open_submenu (menu, submenu);
       gtk_popover_menu_set_parent_menu (GTK_POPOVER_MENU (submenu), GTK_WIDGET (menu));
     }
-  else if (self->role == GTK_BUTTON_ROLE_NORMAL)
+  else if (!self->keep_open)
     {
       GtkWidget *popover;
 
@@ -1057,6 +1058,20 @@ gtk_model_button_clicked (GtkModelButton *self)
     gtk_action_helper_activate (self->action_helper);
 }
 
+static gboolean
+toggle_cb (GtkWidget *widget,
+           GVariant  *args,
+           gpointer   user_data)
+{
+  GtkModelButton *self = GTK_MODEL_BUTTON (widget);
+
+  self->keep_open = self->role != GTK_BUTTON_ROLE_NORMAL;
+  g_signal_emit (widget, signals[SIGNAL_CLICKED], 0);
+  self->keep_open = FALSE;
+
+  return TRUE;
+}
+
 static void
 gtk_model_button_finalize (GObject *object)
 {
@@ -1128,6 +1143,14 @@ gtk_model_button_class_init (GtkModelButtonClass *class)
 {
   GObjectClass *object_class = G_OBJECT_CLASS (class);
   GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
+  GtkShortcutAction *action;
+  guint activate_keyvals[] = {
+    GDK_KEY_Return, GDK_KEY_ISO_Enter, GDK_KEY_KP_Enter
+  };
+  guint toggle_keyvals[] = {
+    GDK_KEY_space, GDK_KEY_KP_Space
+  };
+  int i;
 
   object_class->dispose = gtk_model_button_dispose;
   object_class->finalize = gtk_model_button_finalize;
@@ -1277,6 +1300,30 @@ gtk_model_button_class_init (GtkModelButtonClass *class)
   gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BOX_LAYOUT);
   gtk_widget_class_set_css_name (widget_class, I_("modelbutton"));
   gtk_widget_class_set_accessible_role (widget_class, GTK_ACCESSIBLE_ROLE_MENU_ITEM);
+
+  action = gtk_signal_action_new ("clicked");
+  for (i = 0; i < G_N_ELEMENTS (activate_keyvals); i++)
+    {
+      GtkShortcut *shortcut;
+
+      shortcut = gtk_shortcut_new (gtk_keyval_trigger_new (activate_keyvals[i], 0),
+                                   g_object_ref (action));
+      gtk_widget_class_add_shortcut (widget_class, shortcut);
+      g_object_unref (shortcut);
+    }
+  g_object_unref (action);
+
+  action = gtk_callback_action_new (toggle_cb, NULL, NULL);
+  for (i = 0; i < G_N_ELEMENTS (toggle_keyvals); i++)
+    {
+      GtkShortcut *shortcut;
+
+      shortcut = gtk_shortcut_new (gtk_keyval_trigger_new (toggle_keyvals[i], 0),
+                                   g_object_ref (action));
+      gtk_widget_class_add_shortcut (widget_class, shortcut);
+      g_object_unref (shortcut);
+    }
+  g_object_unref (action);
 }
 
 static void


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]