[gtk/gbsneto/shortcuts-rebased: 25/112] widget: Add gtk_widget_class_add_shortcut()
- From: Georges Basile Stavracas Neto <gbsneto src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk/gbsneto/shortcuts-rebased: 25/112] widget: Add gtk_widget_class_add_shortcut()
- Date: Thu, 16 May 2019 00:08:27 +0000 (UTC)
commit a1dfe3da526f109cbf70792953fa9bd3fd647644
Author: Benjamin Otte <otte redhat com>
Date: Sat Aug 4 12:16:00 2018 +0200
widget: Add gtk_widget_class_add_shortcut()
This allows adding shortcuts as a replacement for keybindings.
docs/reference/gtk/gtk4-sections.txt | 2 +
gtk/gtkshortcutcontroller.c | 30 +++++++++++-
gtk/gtkwidget.c | 88 ++++++++++++++++++++++++++++++++++++
gtk/gtkwidget.h | 12 +++++
gtk/gtkwidgetprivate.h | 2 +
5 files changed, 132 insertions(+), 2 deletions(-)
---
diff --git a/docs/reference/gtk/gtk4-sections.txt b/docs/reference/gtk/gtk4-sections.txt
index 2118e249b6..242211b6f3 100644
--- a/docs/reference/gtk/gtk4-sections.txt
+++ b/docs/reference/gtk/gtk4-sections.txt
@@ -4423,6 +4423,8 @@ gtk_widget_add_tick_callback
gtk_widget_remove_tick_callback
gtk_widget_size_allocate
gtk_widget_allocate
+gtk_widget_class_add_shortcut
+gtk_widget_class_add_binding_signal
gtk_widget_add_accelerator
gtk_widget_remove_accelerator
gtk_widget_set_accel_path
diff --git a/gtk/gtkshortcutcontroller.c b/gtk/gtkshortcutcontroller.c
index 45aab98e70..7dee9871cc 100644
--- a/gtk/gtkshortcutcontroller.c
+++ b/gtk/gtkshortcutcontroller.c
@@ -33,6 +33,8 @@
#include "gtkeventcontrollerprivate.h"
#include "gtkbindings.h"
+#include "gtkshortcut.h"
+#include "gtkwidgetprivate.h"
#include <gdk/gdk.h>
@@ -57,12 +59,36 @@ gtk_shortcut_controller_finalize (GObject *object)
G_OBJECT_CLASS (gtk_shortcut_controller_parent_class)->finalize (object);
}
+static gboolean
+gtk_shortcut_controller_trigger_shortcut (GtkShortcutController *self,
+ GtkShortcut *shortcut,
+ const GdkEvent *event)
+{
+ if (!gtk_shortcut_trigger (shortcut, event))
+ return FALSE;
+
+ return gtk_shortcut_activate (shortcut, gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (self)));
+}
+
static gboolean
gtk_shortcut_controller_handle_event (GtkEventController *controller,
const GdkEvent *event)
{
- return gtk_bindings_activate_event (G_OBJECT (gtk_event_controller_get_widget (controller)),
- (GdkEventKey *) event);
+ GtkShortcutController *self = GTK_SHORTCUT_CONTROLLER (controller);
+ GtkWidget *widget;
+ const GSList *l;
+
+ widget = gtk_event_controller_get_widget (controller);
+ if (gtk_bindings_activate_event (G_OBJECT (widget), (GdkEventKey *) event))
+ return TRUE;
+
+ for (l = gtk_widget_class_get_shortcuts (GTK_WIDGET_GET_CLASS (widget)); l; l = l->next)
+ {
+ if (gtk_shortcut_controller_trigger_shortcut (self, l->data, event))
+ return TRUE;
+ }
+
+ return FALSE;
}
static void
diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c
index 37a1b0f5b2..0bd1423622 100644
--- a/gtk/gtkwidget.c
+++ b/gtk/gtkwidget.c
@@ -59,6 +59,7 @@
#include "gtkscrollable.h"
#include "gtkselection.h"
#include "gtksettingsprivate.h"
+#include "gtkshortcut.h"
#include "gtkshortcutcontroller.h"
#include "gtksizegroup-private.h"
#include "gtksnapshotprivate.h"
@@ -495,6 +496,7 @@ typedef struct {
struct _GtkWidgetClassPrivate
{
GtkWidgetTemplate *template;
+ GSList *shortcuts;
GType accessible_type;
AtkRole accessible_role;
const char *css_name;
@@ -2112,6 +2114,7 @@ static void
gtk_widget_base_class_finalize (GtkWidgetClass *klass)
{
template_data_free (klass->priv->template);
+ g_slist_free_full (klass->priv->shortcuts, g_object_unref);
}
static void
@@ -4766,6 +4769,91 @@ gtk_widget_adjust_size_allocation (GtkWidget *widget,
}
}
+/**
+ * gtk_widget_class_add_binding_signal: (skip)
+ * @widget_class: the class to add the binding to
+ * @mods: key modifier of binding to install
+ * @keyval: key value of binding to install
+ * @signal: the signal to execute
+ * @format_string: GVariant format string for arguments or %NULL for
+ * no arguments
+ * @...: arguments, as given by format string.
+ *
+ * Creates a new shortcut for @widget_class that emits the given action
+ * @signal with arguments read according to @format_string.
+ * The arguments and format string must be provided in the same way as
+ * with g_variant_new().
+ *
+ * This function is a convenience wrapper around
+ * gtk_widget_class_add_shortcut() and must be called during class
+ * initialization.
+ **/
+void
+gtk_widget_class_add_binding_signal (GtkWidgetClass *widget_class,
+ GdkModifierType mods,
+ guint keyval,
+ const gchar *signal,
+ const gchar *format_string,
+ ...)
+{
+ GtkShortcut *shortcut;
+
+ g_return_if_fail (GTK_IS_WIDGET_CLASS (widget_class));
+ g_return_if_fail (g_signal_lookup (signal, G_TYPE_FROM_CLASS (widget_class)));
+ /* XXX: validate variant format for signal */
+
+ shortcut = gtk_shortcut_new ();
+ gtk_shortcut_set_keyval (shortcut, mods, keyval);
+ gtk_shortcut_set_signal (shortcut, signal);
+ if (format_string)
+ {
+ va_list args;
+ va_start (args, format_string);
+ gtk_shortcut_set_arguments (shortcut,
+ g_variant_new_va (format_string, NULL, &args));
+ va_end (args);
+ }
+
+ gtk_widget_class_add_shortcut (widget_class, shortcut);
+
+ g_object_unref (shortcut);
+}
+
+/**
+ * gtk_widget_class_add_shortcut:
+ * @widget_class: the class to add the shortcut to
+ * @shortcut: (transfer none): the #GtkShortcut to add
+ *
+ * Installs a shortcut in @widget_class. Every instance created for
+ * @widget_class or its subclasses will inherit this shortcut and
+ * trigger it.
+ *
+ * Shortcuts added this way will be triggered in the @GTK_PHASE_BUBBLE
+ * phase, which means they may also trigger if child widgets have focus.
+ *
+ * This function must only be used in class initialization functions
+ * otherwise it is not guaranteed that the shortcut will be installed.
+ **/
+void
+gtk_widget_class_add_shortcut (GtkWidgetClass *widget_class,
+ GtkShortcut *shortcut)
+{
+ GtkWidgetClassPrivate *priv;
+
+ g_return_if_fail (GTK_IS_WIDGET_CLASS (widget_class));
+ g_return_if_fail (GTK_IS_SHORTCUT (shortcut));
+
+ priv = widget_class->priv;
+
+ priv->shortcuts = g_slist_prepend (priv->shortcuts, g_object_ref (shortcut));
+}
+
+const GSList *
+gtk_widget_class_get_shortcuts (GtkWidgetClass *widget_class)
+{
+ return widget_class->priv->shortcuts;
+}
+
static gboolean
gtk_widget_real_can_activate_accel (GtkWidget *widget,
guint signal_id)
diff --git a/gtk/gtkwidget.h b/gtk/gtkwidget.h
index 42a8021e8f..70edcbc647 100644
--- a/gtk/gtkwidget.h
+++ b/gtk/gtkwidget.h
@@ -420,6 +420,18 @@ void gtk_widget_class_set_layout_manager_type (GtkWidg
GDK_AVAILABLE_IN_ALL
GType gtk_widget_class_get_layout_manager_type (GtkWidgetClass *widget_class);
+GDK_AVAILABLE_IN_ALL
+void gtk_widget_class_add_binding_signal
+ (GtkWidgetClass *widget_class,
+ GdkModifierType mods,
+ guint keyval,
+ const gchar *signal,
+ const gchar *format_string,
+ ...);
+GDK_AVAILABLE_IN_ALL
+void gtk_widget_class_add_shortcut (GtkWidgetClass *widget_class,
+ GtkShortcut *shortcut);
+
GDK_AVAILABLE_IN_ALL
void gtk_widget_add_accelerator (GtkWidget *widget,
const gchar *accel_signal,
diff --git a/gtk/gtkwidgetprivate.h b/gtk/gtkwidgetprivate.h
index 061ab2e944..937cd672dc 100644
--- a/gtk/gtkwidgetprivate.h
+++ b/gtk/gtkwidgetprivate.h
@@ -244,6 +244,8 @@ void _gtk_widget_get_preferred_size_and_baseline(GtkWidget *widget,
const gchar* _gtk_widget_get_accel_path (GtkWidget *widget,
gboolean *locked);
+const GSList * gtk_widget_class_get_shortcuts (GtkWidgetClass *widget_class);
+
AtkObject * _gtk_widget_peek_accessible (GtkWidget *widget);
void _gtk_widget_set_has_default (GtkWidget *widget,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]