Add GtkShortcutManager
authorEmmanuele Bassi <ebassi@gnome.org>
Thu, 6 Feb 2020 15:43:55 +0000 (15:43 +0000)
committerMatthias Clasen <mclasen@redhat.com>
Thu, 26 Mar 2020 03:14:27 +0000 (23:14 -0400)
This adds an interface for taking care of shortcut controllers with
managed scope.

Only GtkWindow currently implements this interface, so we need to ensure
that we check if any top-level widget we reach is a shortcuts manager
before we call into it.

docs/reference/gtk/gtk4-docs.xml
docs/reference/gtk/gtk4-sections.txt
docs/reference/gtk/gtk4.types.in
gtk/gtk.h
gtk/gtkroot.c
gtk/gtkshortcutcontroller.c
gtk/gtkshortcutmanager.c [new file with mode: 0644]
gtk/gtkshortcutmanager.h [new file with mode: 0644]
gtk/gtkwidget.c
gtk/gtkwindow.c
gtk/meson.build

index 73f3effe677b8d91ca53161aa3e989b24a66ecb6..952019a2b855559ccdb8cd5853e0dcfb81e5ec1d 100644 (file)
       <title>Keyboard shortcuts</title>
       <xi:include href="xml/gtkshortcut.xml" />
       <xi:include href="xml/gtkshortcuttrigger.xml" />
+      <xi:include href="xml/gtkshortcutmanager.xml" />
     </chapter>
 
     <chapter>
index 534653d9228580c46fc1980a461a90164686504e..20a81805f35940206a3f61a4c8395c4e6001aa12 100644 (file)
@@ -6097,12 +6097,21 @@ GTK_SHORTCUT_GET_CLASS
 gtk_shortcut_get_type
 </SECTION>
 
+<SECTION>
+<FILE>gtkshortcutmanager</FILE>
+<TITLE>GtkShortcutManager</TITLE>
+GtkShortcutManager
+GtkShortcutManagerInterface
+</SECTION>
+
 <SECTION>
 <FILE>gtkshortcutcontroller</FILE>
 <TITLE>GtkShortcutController</TITLE>
 GtkShortcutController
 gtk_shortcut_controller_new
 GtkShortcutScope
+GtkShortcutManager
+GtkShortcutManagerInterface
 gtk_shortcut_controller_set_mnemonics_modifiers
 gtk_shortcut_controller_get_mnemonics_modifiers
 gtk_shortcut_controller_set_scope
@@ -6117,9 +6126,16 @@ GTK_SHORTCUT_CONTROLLER_CLASS
 GTK_IS_SHORTCUT_CONTROLLER
 GTK_IS_SHORTCUT_CONTROLLER_CLASS
 GTK_SHORTCUT_CONTROLLER_GET_CLASS
+GTK_TYPE_SHORTCUT_MANAGER
+GTK_SHORTCUT_MANAGER
+GTK_SHORTCUT_MANAGER_CLASS
+GTK_IS_SHORTCUT_MANAGER
+GTK_IS_SHORTCUT_MANAGER_CLASS
+GTK_SHORTCUT_MANAGER_GET_CLASS
 
 <SUBSECTION Private>
 gtk_shortcut_controller_get_type
+gtk_shortcut_manager_get_type
 </SECTION>
 
 <SECTION>
index 19995bc504e09c24c1d46b356cacbdb0487c5f85..c2c9724049ac9bffe24b4af0a076b93f3ebf4174 100644 (file)
@@ -168,6 +168,7 @@ gtk_settings_get_type
 gtk_shortcut_get_type
 gtk_shortcut_controller_get_type
 gtk_shortcut_label_get_type
+gtk_shortcut_manager_get_type
 gtk_shortcuts_window_get_type
 gtk_shortcuts_section_get_type
 gtk_shortcuts_group_get_type
index 46937d324eff7360788ffd7d9f9f9a72b2dc7280..c6979e5487fc10b04b52c52883af6338b18f976d 100644 (file)
--- a/gtk/gtk.h
+++ b/gtk/gtk.h
 #include <gtk/gtkshortcut.h>
 #include <gtk/gtkshortcutcontroller.h>
 #include <gtk/gtkshortcutlabel.h>
+#include <gtk/gtkshortcutmanager.h>
 #include <gtk/gtkshortcutsgroup.h>
 #include <gtk/gtkshortcutssection.h>
 #include <gtk/gtkshortcutsshortcut.h>
index dce284a57f81cfd6c841dc921f6992c375305b61..3e6a7b78b626a3697ed3aeba7b7fd3055ca0660e 100644 (file)
@@ -27,6 +27,8 @@
 #include "gtkprivate.h"
 #include "gtkintl.h"
 
+#include "gtkshortcutmanager.h"
+
 /**
  * SECTION:gtkroot
  * @Title: GtkRoot
index c47d657f393bf388d9acf3bd92bbf84706b8947c..915403205c35fc4420ff7dccaef7eceed1b750ef 100644 (file)
@@ -34,6 +34,7 @@
 #include "gtkeventcontrollerprivate.h"
 #include "gtkintl.h"
 #include "gtkshortcut.h"
+#include "gtkshortcutmanager.h"
 #include "gtkshortcuttrigger.h"
 #include "gtktypebuiltins.h"
 #include "gtkwidgetprivate.h"
@@ -295,17 +296,10 @@ gtk_shortcut_controller_init (GtkShortcutController *self)
   self->mnemonics_modifiers = GDK_MOD1_MASK;
 }
 
-static void
-complain_if_reached (gpointer should_be_gone)
-{
-  g_critical ("Shortcut controllers failed to clean up.");
-}
-
 void
 gtk_shortcut_controller_root (GtkShortcutController *self)
 {
-  GtkWidget *attach;
-  GSList *controllers;
+  GtkShortcutManager *manager;
 
   switch (self->scope)
     {
@@ -313,8 +307,30 @@ gtk_shortcut_controller_root (GtkShortcutController *self)
       return;
 
     case GTK_SHORTCUT_SCOPE_MANAGED:
+      {
+        GtkWidget *widget;
+
+        for (widget = gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (self));
+             !GTK_IS_SHORTCUT_MANAGER (widget);
+             widget = _gtk_widget_get_parent (widget))
+          ;
+
+        if (!GTK_IS_SHORTCUT_MANAGER (widget))
+          return;
+
+        manager = GTK_SHORTCUT_MANAGER (widget);
+      }
+      break;
+
     case GTK_SHORTCUT_SCOPE_GLOBAL:
-      attach = GTK_WIDGET (gtk_widget_get_root (gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (self))));
+      {
+        GtkRoot *root = gtk_widget_get_root (gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (self)));
+
+        if (!GTK_IS_SHORTCUT_MANAGER (root))
+          return;
+
+        manager = GTK_SHORTCUT_MANAGER (root);
+      }
       break;
 
     default:
@@ -322,16 +338,13 @@ gtk_shortcut_controller_root (GtkShortcutController *self)
       return;
     }
 
-  controllers = g_object_steal_data (G_OBJECT (attach), "gtk-shortcut-controllers");
-  controllers = g_slist_prepend (controllers, g_object_ref (self));
-  g_object_set_data_full (G_OBJECT (attach), "gtk-shortcut-controllers", controllers, complain_if_reached);
+  GTK_SHORTCUT_MANAGER_GET_IFACE (manager)->add_controller (manager, self);
 }
 
 void
 gtk_shortcut_controller_unroot (GtkShortcutController *self)
 {
-  GtkWidget *attach;
-  GSList *controllers;
+  GtkShortcutManager *manager;
 
   switch (self->scope)
     {
@@ -339,8 +352,30 @@ gtk_shortcut_controller_unroot (GtkShortcutController *self)
       return;
 
     case GTK_SHORTCUT_SCOPE_MANAGED:
+      {
+        GtkWidget *widget;
+
+        for (widget = gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (self));
+             !GTK_IS_SHORTCUT_MANAGER (widget);
+             widget = _gtk_widget_get_parent (widget))
+          ;
+
+        if (!GTK_IS_SHORTCUT_MANAGER (widget))
+          return;
+
+        manager = GTK_SHORTCUT_MANAGER (widget);
+      }
+      break;
+
     case GTK_SHORTCUT_SCOPE_GLOBAL:
-      attach = GTK_WIDGET (gtk_widget_get_root (gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (self))));
+      {
+        GtkRoot *root = gtk_widget_get_root (gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (self)));
+
+        if (!GTK_IS_SHORTCUT_MANAGER (root))
+          return;
+
+        manager = GTK_SHORTCUT_MANAGER (root);
+      }
       break;
 
     default:
@@ -348,11 +383,7 @@ gtk_shortcut_controller_unroot (GtkShortcutController *self)
       return;
     }
 
-  controllers = g_object_steal_data (G_OBJECT (attach), "gtk-shortcut-controllers");
-  controllers = g_slist_remove (controllers, self);
-  if (controllers)
-    g_object_set_data_full (G_OBJECT (attach), "gtk-shortcut-controllers", controllers, complain_if_reached);
-  g_object_unref (self);
+  GTK_SHORTCUT_MANAGER_GET_IFACE (manager)->remove_controller (manager, self);
 }
 
 GtkEventController *
diff --git a/gtk/gtkshortcutmanager.c b/gtk/gtkshortcutmanager.c
new file mode 100644 (file)
index 0000000..6853db9
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * Copyright © 2018 Benjamin Otte
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Benjamin Otte <otte@gnome.org>
+ */
+
+#include "config.h"
+
+#include "gtkshortcutmanager.h"
+
+/**
+ * SECTION:gtkshortcutmanager
+ * @title: GtkShortcutManager
+ * @short_description: Interface for managing shortcuts
+ *
+ * The GtkShortcutManager interface is used to implement
+ * shortcut scopes.
+ */
+G_DEFINE_INTERFACE (GtkShortcutManager, gtk_shortcut_manager, G_TYPE_OBJECT)
+
+static void
+complain_if_reached (gpointer should_be_gone)
+{
+  g_critical ("Shortcut controllers failed to clean up.");
+}
+
+static void
+gtk_shortcut_manager_default_add_controller (GtkShortcutManager    *self,
+                                             GtkShortcutController *controller)
+{
+  GSList *controllers;
+
+  controllers = g_object_steal_data (G_OBJECT (self), "gtk-shortcut-controllers");
+  controllers = g_slist_prepend (controllers, g_object_ref (controller));
+  g_object_set_data_full (G_OBJECT (self), "gtk-shortcut-controllers", controllers, complain_if_reached);
+}
+
+static void
+gtk_shortcut_manager_default_remove_controller (GtkShortcutManager    *self,
+                                                GtkShortcutController *controller)
+{
+  GSList *controllers;
+
+  controllers = g_object_steal_data (G_OBJECT (self), "gtk-shortcut-controllers");
+  controllers = g_slist_remove (controllers, controller);
+  if (controllers)
+    g_object_set_data_full (G_OBJECT (self), "gtk-shortcut-controllers", controllers, complain_if_reached);
+  g_object_unref (controller);
+}
+
+static void
+gtk_shortcut_manager_default_init (GtkShortcutManagerInterface *iface)
+{
+  iface->add_controller = gtk_shortcut_manager_default_add_controller;
+  iface->remove_controller = gtk_shortcut_manager_default_remove_controller;
+}
+
diff --git a/gtk/gtkshortcutmanager.h b/gtk/gtkshortcutmanager.h
new file mode 100644 (file)
index 0000000..0d4ece9
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * Copyright © 2018 Benjamin Otte
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Benjamin Otte <otte@gnome.org>
+ */
+
+#ifndef __GTK_SHORTCUT_MANAGER_H__
+#define __GTK_SHORTCUT_MANAGER_H__
+
+#if !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION)
+#error "Only <gtk/gtk.h> can be included directly."
+#endif
+
+#include <gtk/gtkshortcutcontroller.h>
+#include <gtk/gtkwidget.h>
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_SHORTCUT_MANAGER               (gtk_shortcut_manager_get_type ())
+
+GDK_AVAILABLE_IN_ALL
+G_DECLARE_INTERFACE (GtkShortcutManager, gtk_shortcut_manager, GTK, SHORTCUT_MANAGER, GtkWidget)
+
+/**
+ * GtkShortcutManager:
+ *
+ * This object is used to implement support for #GtkShortcutScopes. Every
+ * widget that implements #GtkShortcutManager will be used as a
+ * %GTK_SHORTCUT_SCOPE_MANAGED.
+ */
+
+/**
+ * GtkShortcutManagerInterface:
+ * @add_controller: Add a #GtkShortcutController to be managed.
+ * @remove_controller: Remove a #GtkShortcutController that had previously
+ *     been added.
+ *
+ * The list of functions that can be implemented for the #GtkShortcutManager interface.
+ *
+ * Note that no function is mandatory to implement, the default implementation will work
+ * fine.
+ */
+struct _GtkShortcutManagerInterface
+{
+  /*< private >*/
+  GTypeInterface g_iface;
+
+  /*< public >*/
+  void                  (* add_controller)              (GtkShortcutManager           *self,
+                                                         GtkShortcutController        *controller);
+  void                  (* remove_controller)           (GtkShortcutManager           *self,
+                                                         GtkShortcutController        *controller);
+};
+
+
+G_END_DECLS
+
+#endif /* __GTK_SHORTCUT_MANAGER_H__ */
index 8d049109222bfe9403be13d05604b44e157ce2cf..8e7a29e2cc31a40981cbea42970d6974b0873173 100644 (file)
@@ -60,6 +60,7 @@
 #include "gtksettingsprivate.h"
 #include "gtkshortcut.h"
 #include "gtkshortcutcontrollerprivate.h"
+#include "gtkshortcutmanager.h"
 #include "gtkshortcuttrigger.h"
 #include "gtksizegroup-private.h"
 #include "gtksnapshotprivate.h"
@@ -2422,9 +2423,10 @@ gtk_widget_init (GTypeInstance *instance, gpointer g_class)
   gtk_css_node_set_name (priv->cssnode, GTK_WIDGET_CLASS (g_class)->priv->css_name);
 
   if (g_type_is_a (G_TYPE_FROM_CLASS (g_class), GTK_TYPE_ROOT))
-    {
-      priv->root = (GtkRoot *) widget;
+    priv->root = (GtkRoot *) widget;
 
+  if (g_type_is_a (G_TYPE_FROM_CLASS (g_class), GTK_TYPE_SHORTCUT_MANAGER))
+    {
       controller = gtk_shortcut_controller_new ();
       gtk_shortcut_controller_set_run_managed (GTK_SHORTCUT_CONTROLLER (controller), TRUE);
       gtk_widget_add_controller (widget, controller);
index bd2e804a3c82b1519778548f8d4ac2660e011a22..d247800417798840d064a4be7e199fe4a4d14132 100644 (file)
@@ -64,6 +64,7 @@
 #include "gtksettings.h"
 #include "gtkshortcut.h"
 #include "gtkshortcutcontroller.h"
+#include "gtkshortcutmanager.h"
 #include "gtkshortcuttrigger.h"
 #include "gtksnapshot.h"
 #include "gtkstylecontextprivate.h"
@@ -534,6 +535,7 @@ static void     gtk_window_buildable_custom_finished        (GtkBuildable
                                                              const gchar        *tagname,
                                                              gpointer            user_data);
 
+static void             gtk_window_shortcut_manager_interface_init      (GtkShortcutManagerInterface *iface);
 /* GtkRoot */
 static void             gtk_window_root_interface_init (GtkRootInterface *iface);
 static void             gtk_window_native_interface_init  (GtkNativeInterface  *iface);
@@ -554,6 +556,8 @@ G_DEFINE_TYPE_WITH_CODE (GtkWindow, gtk_window, GTK_TYPE_BIN,
                                                gtk_window_buildable_interface_init)
                          G_IMPLEMENT_INTERFACE (GTK_TYPE_NATIVE,
                                                gtk_window_native_interface_init)
+                         G_IMPLEMENT_INTERFACE (GTK_TYPE_SHORTCUT_MANAGER,
+                                               gtk_window_shortcut_manager_interface_init)
                          G_IMPLEMENT_INTERFACE (GTK_TYPE_ROOT,
                                                gtk_window_root_interface_init))
 
@@ -2178,6 +2182,11 @@ gtk_window_buildable_custom_finished (GtkBuildable  *buildable,
     }
 }
 
+static void
+gtk_window_shortcut_manager_interface_init (GtkShortcutManagerInterface *iface)
+{
+}
+
 static GdkDisplay *
 gtk_window_root_get_display (GtkRoot *root)
 {
index 0d8fafdc1aa0b17d7734a2a2076b59263432e2e2..7e9e2115271de7a8efc2705bf2ce2872c7d1077b 100644 (file)
@@ -333,6 +333,7 @@ gtk_public_sources = files([
   'gtkshortcut.c',
   'gtkshortcutcontroller.c',
   'gtkshortcutlabel.c',
+  'gtkshortcutmanager.c',
   'gtkshortcutsgroup.c',
   'gtkshortcutssection.c',
   'gtkshortcutsshortcut.c',
@@ -572,6 +573,7 @@ gtk_public_headers = files([
   'gtkshortcut.h',
   'gtkshortcutcontroller.h',
   'gtkshortcutlabel.h',
+  'gtkshortcutmanager.h',
   'gtkshortcutsgroup.h',
   'gtkshortcutssection.h',
   'gtkshortcutsshortcut.h',