diff --git a/docs/reference/gtk/gtk4-docs.xml b/docs/reference/gtk/gtk4-docs.xml index 5fe94f13ac..b7655ba771 100644 --- a/docs/reference/gtk/gtk4-docs.xml +++ b/docs/reference/gtk/gtk4-docs.xml @@ -343,6 +343,7 @@ Keyboard shortcuts + diff --git a/docs/reference/gtk/gtk4-sections.txt b/docs/reference/gtk/gtk4-sections.txt index 0aa6c5d71f..0bf40340e2 100644 --- a/docs/reference/gtk/gtk4-sections.txt +++ b/docs/reference/gtk/gtk4-sections.txt @@ -6096,12 +6096,21 @@ GTK_SHORTCUT_GET_CLASS gtk_shortcut_get_type +
+gtkshortcutmanager +GtkShortcutManager +GtkShortcutManager +GtkShortcutManagerInterface +
+
gtkshortcutcontroller GtkShortcutController 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 @@ -6116,9 +6125,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 19995bc504..c2c9724049 100644 --- a/docs/reference/gtk/gtk4.types.in +++ b/docs/reference/gtk/gtk4.types.in @@ -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 diff --git a/gtk/gtk.h b/gtk/gtk.h index 46937d324e..c6979e5487 100644 --- a/gtk/gtk.h +++ b/gtk/gtk.h @@ -200,6 +200,7 @@ #include #include #include +#include #include #include #include diff --git a/gtk/gtkroot.c b/gtk/gtkroot.c index dce284a57f..3e6a7b78b6 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 diff --git a/gtk/gtkshortcutcontroller.c b/gtk/gtkshortcutcontroller.c index c47d657f39..915403205c 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" @@ -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 index 0000000000..6853db9ce5 --- /dev/null +++ b/gtk/gtkshortcutmanager.c @@ -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 . + * + * Authors: Benjamin Otte + */ + +#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 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 b1e9f8ca75..1b942a063a 100644 --- a/gtk/gtkwidget.c +++ b/gtk/gtkwidget.c @@ -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" @@ -2439,9 +2440,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); diff --git a/gtk/gtkwindow.c b/gtk/gtkwindow.c index 01a1f9ff0b..63d1279ca5 100644 --- a/gtk/gtkwindow.c +++ b/gtk/gtkwindow.c @@ -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" @@ -547,6 +548,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); @@ -567,6 +569,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)) @@ -2230,6 +2234,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 0d8fafdc1a..7e9e211527 100644 --- a/gtk/meson.build +++ b/gtk/meson.build @@ -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',