[gtk/widget-class-actions: 6/8] widget: Add api to bind accels to actions
- From: Matthias Clasen <matthiasc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk/widget-class-actions: 6/8] widget: Add api to bind accels to actions
- Date: Tue, 18 Jun 2019 15:37:47 +0000 (UTC)
commit f4f09d15a8d76975d2699cf72ff0fce55eeb6244
Author: Matthias Clasen <mclasen redhat com>
Date: Mon Jun 17 12:50:25 2019 +0000
widget: Add api to bind accels to actions
This is meant to be used at class-init time,
and will replace bindings, eventually.
We are reusing GtkApplicationAccels here.
It should probably be renamed.
docs/reference/gtk/gtk4-sections.txt | 1 +
gtk/gtkwidget.c | 147 +++++++++++++++++++++++++++++++++++
gtk/gtkwidget.h | 8 ++
3 files changed, 156 insertions(+)
---
diff --git a/docs/reference/gtk/gtk4-sections.txt b/docs/reference/gtk/gtk4-sections.txt
index dfcf55c548..42ceaa0bec 100644
--- a/docs/reference/gtk/gtk4-sections.txt
+++ b/docs/reference/gtk/gtk4-sections.txt
@@ -4636,6 +4636,7 @@ gtk_widget_class_install_action
gtk_widget_class_install_stateful_action
gtk_widget_notify_class_action_enabled
gtk_widget_notify_class_action_state
+gtk_widget_class_bind_action
<SUBSECTION Standard>
GTK_WIDGET
diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c
index 2d29fe1f46..5f1850994e 100644
--- a/gtk/gtkwidget.c
+++ b/gtk/gtkwidget.c
@@ -73,6 +73,7 @@
#include "gtkwindowgroup.h"
#include "gtkwindowprivate.h"
#include "gtknativeprivate.h"
+#include "gtkapplicationaccelsprivate.h"
#include "a11y/gtkwidgetaccessible.h"
#include "inspector/window.h"
@@ -502,6 +503,7 @@ struct _GtkWidgetClassPrivate
const char *css_name;
GType layout_manager_type;
GPtrArray *actions;
+ GtkApplicationAccels *accels;
};
enum {
@@ -713,6 +715,9 @@ static gboolean gtk_widget_class_get_visible_by_default (GtkWidgetClass *widget_
static void remove_parent_surface_transform_changed_listener (GtkWidget *widget);
static void add_parent_surface_transform_changed_listener (GtkWidget *widget);
+static gboolean gtk_widget_activate_accels (GtkWidget *widget,
+ const GdkEvent *event);
+
/* --- variables --- */
static gint GtkWidget_private_offset = 0;
@@ -5360,6 +5365,11 @@ gtk_widget_event_internal (GtkWidget *widget,
event->any.type == GDK_KEY_RELEASE))
return_val |= gtk_bindings_activate_event (G_OBJECT (widget), (GdkEventKey *) event);
+ if (return_val == FALSE &&
+ (event->any.type == GDK_KEY_PRESS ||
+ event->any.type == GDK_KEY_RELEASE))
+ return_val = gtk_widget_activate_accels (widget, event);
+
return return_val;
}
@@ -13572,3 +13582,140 @@ gtk_widget_notify_class_action_state (GtkWidget *widget,
muxer = _gtk_widget_get_action_muxer (widget, TRUE);
gtk_action_muxer_action_state_changed (muxer, action_name, state);
}
+
+static void
+gtk_widget_class_add_accel_for_action (GtkWidgetClass *widget_class,
+ const char *detailed_action,
+ const char *accel)
+{
+ GtkWidgetClassPrivate *priv = widget_class->priv;
+ char **accels;
+ int n;
+
+ if (priv->accels == NULL)
+ priv->accels = gtk_application_accels_new ();
+
+ accels = gtk_application_accels_get_accels_for_action (priv->accels, detailed_action);
+
+ if (accels)
+ {
+ n = g_strv_length (accels);
+ accels = g_renew (char *, accels, n + 2);
+ }
+ else
+ {
+ n = 0;
+ accels = g_new (char *, 2);
+ }
+
+ accels[n] = g_strdup (accel);
+ accels[n + 1] = NULL;
+
+ gtk_application_accels_set_accels_for_action (priv->accels, detailed_action, (const char **)accels);
+}
+
+/**
+ * gtk_widget_class_bind_action:
+ * @widget_class: a #GtkWidgetClass
+ * @keyval: key value of the binding
+ * @modifiers: key modifiers of the binding
+ * @action_name: the name of the action to bind
+ * @format_string: (allow-none): GVariant format string for
+ * the parameters, or %NULL
+ *
+ * Binds the @keyval, @modifiers shortcut to
+ * trigger the action named @action_name with the
+ * given parameters.
+ *
+ * This function should be called at class-init time.
+ *
+ * The action must be defined using
+ * gtk_widget_class_install_action() and the parameters
+ * must match the @parameter_type passed to that function.
+ */
+void
+gtk_widget_class_bind_action (GtkWidgetClass *widget_class,
+ guint keyval,
+ GdkModifierType modifiers,
+ const char *action_name,
+ const char *format_string,
+ ...)
+{
+ GtkWidgetClassPrivate *priv = widget_class->priv;
+ gboolean found = FALSE;
+ GVariantType *type = NULL;
+ GVariant *parameters = NULL;
+ char *detailed_action = NULL;
+ char *accel = NULL;
+
+ if (priv->actions)
+ {
+ int i;
+ for (i = 0; i < priv->actions->len; i++)
+ {
+ GtkWidgetAction *action = g_ptr_array_index (priv->actions, i);
+ if (strcmp (action->name, action_name) == 0)
+ {
+ type = action->parameter_type;
+ found = TRUE;
+ break;
+ }
+ }
+ }
+
+ if (!found)
+ {
+ g_warning ("Widget action %s not found", action_name);
+ return;
+ }
+
+ if (format_string)
+ {
+ va_list args;
+ va_start (args, format_string);
+ parameters = g_variant_ref_sink (g_variant_new_va (format_string, NULL, &args));
+ va_end (args);
+ }
+
+ if (parameters && !g_variant_is_of_type (parameters, type))
+ {
+ g_warning ("Parameters don't match expected type for action %s", action_name);
+ g_variant_unref (parameters);
+ return;
+ }
+
+ detailed_action = g_action_print_detailed_name (action_name, parameters);
+
+ accel = gtk_accelerator_name (keyval, modifiers);
+
+ gtk_widget_class_add_accel_for_action (widget_class, detailed_action, accel);
+
+ g_free (detailed_action);
+ g_free (accel);
+}
+
+static gboolean
+gtk_widget_activate_accels (GtkWidget *widget,
+ const GdkEvent *event)
+{
+ GtkWidgetClass *class = GTK_WIDGET_GET_CLASS (widget);
+ GtkWidgetClassPrivate *priv = class->priv;
+ GtkApplicationAccels *accels = priv->accels;
+ GtkActionMuxer *muxer;
+ guint keyval;
+ GdkModifierType modifiers;
+
+ if (!accels)
+ return FALSE;
+
+ muxer = _gtk_widget_get_action_muxer (widget, FALSE);
+ if (!muxer)
+ return FALSE;
+
+ gdk_event_get_keyval ((GdkEvent *)event, &keyval);
+ gdk_event_get_state ((GdkEvent *)event, &modifiers);
+
+ return gtk_application_accels_activate (accels,
+ G_ACTION_GROUP (muxer),
+ keyval, modifiers);
+}
diff --git a/gtk/gtkwidget.h b/gtk/gtkwidget.h
index 618aeca883..9b6408fd4b 100644
--- a/gtk/gtkwidget.h
+++ b/gtk/gtkwidget.h
@@ -1092,6 +1092,14 @@ void gtk_widget_notify_class_action_state (GtkWidget *widget
const char *action_name,
GVariant *state);
+GDK_AVAILABLE_IN_ALL
+void gtk_widget_class_bind_action (GtkWidgetClass *widget_class,
+ guint keyval,
+ GdkModifierType modifiers,
+ const char *action_name,
+ const char *format_string,
+ ...);
+
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkWidget, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkRequisition, gtk_requisition_free)
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]