diff --git a/docs/reference/gtk/gtk4-sections.txt b/docs/reference/gtk/gtk4-sections.txt index 945848a72e..58250d18a1 100644 --- a/docs/reference/gtk/gtk4-sections.txt +++ b/docs/reference/gtk/gtk4-sections.txt @@ -6732,6 +6732,8 @@ gtk_shortcut_get_type 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 @@ -6746,9 +6748,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 gtk_shortcut_controller_get_type +gtk_shortcut_manager_get_type
diff --git a/docs/reference/gtk/gtk4.types.in b/docs/reference/gtk/gtk4.types.in index ac4dfc6eab..3b32f469eb 100644 --- a/docs/reference/gtk/gtk4.types.in +++ b/docs/reference/gtk/gtk4.types.in @@ -163,6 +163,7 @@ gtk_settings_get_type gtk_shortcut_controller_get_type gtk_shortcut_get_type gtk_shortcut_label_get_type +gtk_shortcut_manager_get_type gtk_shortcut_trigger_get_type gtk_shortcuts_window_get_type gtk_shortcuts_section_get_type diff --git a/gtk/gtk.h b/gtk/gtk.h index 28832f409c..61e80db40a 100644 --- a/gtk/gtk.h +++ b/gtk/gtk.h @@ -203,6 +203,7 @@ #include #include #include +#include #include #include #include diff --git a/gtk/gtkroot.c b/gtk/gtkroot.c index 919aa65f94..d62ca678fb 100644 --- a/gtk/gtkroot.c +++ b/gtk/gtkroot.c @@ -27,6 +27,8 @@ #include "gtkprivate.h" #include "gtkintl.h" +#include "gtkshortcutmanager.h" + /** * SECTION:gtkroot * @Title: GtkRoot @@ -42,7 +44,8 @@ */ G_DEFINE_INTERFACE_WITH_CODE (GtkRoot, gtk_root, GTK_TYPE_WIDGET, - g_type_interface_add_prerequisite (g_define_type_id, GTK_TYPE_NATIVE)) + g_type_interface_add_prerequisite (g_define_type_id, GTK_TYPE_NATIVE); + g_type_interface_add_prerequisite (g_define_type_id, GTK_TYPE_SHORTCUT_MANAGER)); static GdkDisplay * gtk_root_default_get_display (GtkRoot *self) diff --git a/gtk/gtkshortcutcontroller.c b/gtk/gtkshortcutcontroller.c index 0841397e50..4e4e882fc7 100644 --- a/gtk/gtkshortcutcontroller.c +++ b/gtk/gtkshortcutcontroller.c @@ -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" @@ -291,17 +292,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) { @@ -309,8 +303,18 @@ 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)); + 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)))); + manager = GTK_SHORTCUT_MANAGER (gtk_widget_get_root (gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (self)))); break; default: @@ -318,16 +322,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) { @@ -335,8 +336,18 @@ 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)); + 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)))); + manager = GTK_SHORTCUT_MANAGER (gtk_widget_get_root (gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (self)))); break; default: @@ -344,11 +355,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 index 0000000000..d3036f8772 --- /dev/null +++ b/gtk/gtkshortcutmanager.c @@ -0,0 +1,62 @@ +/* + * 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 . + * + * Authors: Benjamin Otte + */ + +#include "config.h" + +#include "gtkshortcutmanager.h" + +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 index 0000000000..0d4ece9745 --- /dev/null +++ b/gtk/gtkshortcutmanager.h @@ -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 . + * + * Authors: Benjamin Otte + */ + +#ifndef __GTK_SHORTCUT_MANAGER_H__ +#define __GTK_SHORTCUT_MANAGER_H__ + +#if !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION) +#error "Only can be included directly." +#endif + +#include +#include + +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__ */ diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c index ed386649f6..8afd7f028f 100644 --- a/gtk/gtkwidget.c +++ b/gtk/gtkwidget.c @@ -62,6 +62,7 @@ #include "gtksettingsprivate.h" #include "gtkshortcut.h" #include "gtkshortcutcontrollerprivate.h" +#include "gtkshortcutmanager.h" #include "gtkshortcuttrigger.h" #include "gtksizegroup-private.h" #include "gtksnapshotprivate.h" @@ -2853,9 +2854,10 @@ gtk_widget_init (GTypeInstance *instance, gpointer g_class) gtk_css_node_set_widget_type (priv->cssnode, G_TYPE_FROM_CLASS (g_class)); 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); diff --git a/gtk/gtkwindow.c b/gtk/gtkwindow.c index b43b7daef3..93d9ce96a6 100644 --- a/gtk/gtkwindow.c +++ b/gtk/gtkwindow.c @@ -66,6 +66,7 @@ #include "gtksettings.h" #include "gtkshortcut.h" #include "gtkshortcutcontroller.h" +#include "gtkshortcutmanager.h" #include "gtkshortcuttrigger.h" #include "gtksnapshot.h" #include "gtkstylecontextprivate.h" @@ -562,6 +563,7 @@ static void gtk_window_buildable_custom_finished (GtkBuildable *buildable, 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); @@ -583,6 +585,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)) @@ -2346,6 +2350,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) { diff --git a/gtk/meson.build b/gtk/meson.build index 26f30bd1dd..4c4f851df0 100644 --- a/gtk/meson.build +++ b/gtk/meson.build @@ -335,6 +335,7 @@ gtk_public_sources = files([ 'gtkshortcut.c', 'gtkshortcutcontroller.c', 'gtkshortcutlabel.c', + 'gtkshortcutmanager.c', 'gtkshortcutsgroup.c', 'gtkshortcutssection.c', 'gtkshortcutsshortcut.c', @@ -583,6 +584,7 @@ gtk_public_headers = files([ 'gtkshortcut.h', 'gtkshortcutcontroller.h', 'gtkshortcutlabel.h', + 'gtkshortcutmanager.h', 'gtkshortcutsgroup.h', 'gtkshortcutssection.h', 'gtkshortcutsshortcut.h',