summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarlos Garnacho <carlosg@gnome.org>2017-12-11 19:21:38 +0100
committerCarlos Garnacho <carlosg@gnome.org>2018-04-05 19:26:04 +0200
commit1ce79b29e363e585872901424d3b72041b55e3e4 (patch)
tree378a04a9acbdb36768527ea99dce756e91b8435e
parent47ea3a9452becc5b707617557ec03ceaeac87ada (diff)
downloadgtk+-1ce79b29e363e585872901424d3b72041b55e3e4.tar.gz
gtk: Add GtkEventControllerKey
This event controller is meant to replace usage from key-press/release-event handlers all through. Optionally it can be set a GtkIMContext, so interaction is carried by the controller.
-rw-r--r--gtk/gtk.h1
-rw-r--r--gtk/gtkeventcontrollerkey.c218
-rw-r--r--gtk/gtkeventcontrollerkey.h57
-rw-r--r--gtk/meson.build3
-rw-r--r--po/POTFILES.in1
5 files changed, 280 insertions, 0 deletions
diff --git a/gtk/gtk.h b/gtk/gtk.h
index 0775fb04d8..b5b2dbd10e 100644
--- a/gtk/gtk.h
+++ b/gtk/gtk.h
@@ -93,6 +93,7 @@
#include <gtk/gtkentrycompletion.h>
#include <gtk/gtkenums.h>
#include <gtk/gtkeventcontroller.h>
+#include <gtk/gtkeventcontrollerkey.h>
#include <gtk/gtkeventcontrollermotion.h>
#include <gtk/gtkeventcontrollerscroll.h>
#include <gtk/gtkexpander.h>
diff --git a/gtk/gtkeventcontrollerkey.c b/gtk/gtkeventcontrollerkey.c
new file mode 100644
index 0000000000..922b147624
--- /dev/null
+++ b/gtk/gtkeventcontrollerkey.c
@@ -0,0 +1,218 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 2017, Red Hat, Inc.
+ *
+ * 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 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/>.
+ *
+ * Author(s): Carlos Garnacho <carlosg@gnome.org>
+ */
+
+#include "config.h"
+
+#include "gtkintl.h"
+#include "gtkprivate.h"
+#include "gtkwidget.h"
+#include "gtkeventcontrollerprivate.h"
+#include "gtkeventcontrollerkey.h"
+#include "gtkbindings.h"
+
+#include <gdk/gdk.h>
+
+struct _GtkEventControllerKey
+{
+ GtkEventController parent_instance;
+ GtkIMContext *im_context;
+ GHashTable *pressed_keys;
+
+ const GdkEvent *current_event;
+};
+
+struct _GtkEventControllerKeyClass
+{
+ GtkEventControllerClass parent_class;
+};
+
+enum {
+ KEY_PRESSED,
+ KEY_RELEASED,
+ MODIFIERS,
+ IM_UPDATE,
+ N_SIGNALS
+};
+
+static guint signals[N_SIGNALS] = { 0 };
+
+G_DEFINE_TYPE (GtkEventControllerKey, gtk_event_controller_key,
+ GTK_TYPE_EVENT_CONTROLLER)
+
+static void
+gtk_event_controller_finalize (GObject *object)
+{
+ GtkEventControllerKey *key = GTK_EVENT_CONTROLLER_KEY (object);
+
+ g_hash_table_destroy (key->pressed_keys);
+ g_clear_object (&key->im_context);
+
+ G_OBJECT_CLASS (gtk_event_controller_key_parent_class)->finalize (object);
+}
+
+static gboolean
+gtk_event_controller_key_handle_event (GtkEventController *controller,
+ const GdkEvent *event)
+{
+ GtkEventControllerKey *key = GTK_EVENT_CONTROLLER_KEY (controller);
+ GdkEventType event_type = gdk_event_get_event_type (event);
+ gboolean handled, is_modifier;
+ GdkModifierType state;
+ guint16 keycode;
+ guint keyval;
+
+ if (event_type != GDK_KEY_PRESS && event_type != GDK_KEY_RELEASE)
+ return FALSE;
+
+ if (key->im_context &&
+ gtk_im_context_filter_keypress (key->im_context, (GdkEventKey *) event))
+ {
+ g_signal_emit (controller, signals[IM_UPDATE], 0);
+ return TRUE;
+ }
+
+ if (!gdk_event_get_state (event, &state) ||
+ !gdk_event_get_key_is_modifier (event, &is_modifier))
+ return FALSE;
+
+ key->current_event = event;
+
+ if (is_modifier)
+ {
+ if (event_type == GDK_KEY_PRESS)
+ g_signal_emit (controller, signals[MODIFIERS], 0, state, &handled);
+ else
+ handled = TRUE;
+
+ if (handled == TRUE)
+ {
+ key->current_event = NULL;
+ return TRUE;
+ }
+ }
+
+ gdk_event_get_keycode (event, &keycode);
+ gdk_event_get_keyval (event, &keyval);
+
+ if (event_type == GDK_KEY_PRESS)
+ {
+ g_signal_emit (controller, signals[KEY_PRESSED], 0,
+ keyval, keycode, state, &handled);
+ if (handled)
+ g_hash_table_add (key->pressed_keys, GUINT_TO_POINTER (keyval));
+ }
+ else if (event_type == GDK_KEY_RELEASE)
+ {
+ g_signal_emit (controller, signals[KEY_RELEASED], 0,
+ keyval, keycode, state);
+
+ handled = g_hash_table_lookup (key->pressed_keys, GUINT_TO_POINTER (keyval)) != NULL;
+ g_hash_table_remove (key->pressed_keys, GUINT_TO_POINTER (keyval));
+ }
+ else
+ handled = FALSE;
+
+ key->current_event = NULL;
+
+ return handled;
+}
+
+static void
+gtk_event_controller_key_class_init (GtkEventControllerKeyClass *klass)
+{
+ GtkEventControllerClass *controller_class = GTK_EVENT_CONTROLLER_CLASS (klass);
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = gtk_event_controller_finalize;
+ controller_class->handle_event = gtk_event_controller_key_handle_event;
+
+ signals[KEY_PRESSED] =
+ g_signal_new (I_("key-pressed"),
+ GTK_TYPE_EVENT_CONTROLLER_KEY,
+ G_SIGNAL_RUN_LAST,
+ 0, _gtk_boolean_handled_accumulator, NULL, NULL,
+ G_TYPE_BOOLEAN, 3, G_TYPE_UINT, G_TYPE_UINT, GDK_TYPE_MODIFIER_TYPE);
+ signals[KEY_RELEASED] =
+ g_signal_new (I_("key-released"),
+ GTK_TYPE_EVENT_CONTROLLER_KEY,
+ G_SIGNAL_RUN_LAST,
+ 0, NULL, NULL, NULL,
+ G_TYPE_NONE, 3, G_TYPE_UINT, G_TYPE_UINT, GDK_TYPE_MODIFIER_TYPE);
+ signals[MODIFIERS] =
+ g_signal_new (I_("modifiers"),
+ GTK_TYPE_EVENT_CONTROLLER_KEY,
+ G_SIGNAL_RUN_LAST,
+ 0, NULL, NULL,
+ g_cclosure_marshal_BOOLEAN__FLAGS,
+ G_TYPE_BOOLEAN, 1, GDK_TYPE_MODIFIER_TYPE);
+ signals[IM_UPDATE] =
+ g_signal_new (I_("im-update"),
+ GTK_TYPE_EVENT_CONTROLLER_KEY,
+ G_SIGNAL_RUN_LAST,
+ 0, NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+}
+
+static void
+gtk_event_controller_key_init (GtkEventControllerKey *controller)
+{
+ controller->pressed_keys = g_hash_table_new (NULL, NULL);
+}
+
+GtkEventController *
+gtk_event_controller_key_new (GtkWidget *widget)
+{
+ g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
+
+ return g_object_new (GTK_TYPE_EVENT_CONTROLLER_KEY,
+ "widget", widget,
+ NULL);
+}
+
+void
+gtk_event_controller_key_set_im_context (GtkEventControllerKey *controller,
+ GtkIMContext *im_context)
+{
+ g_return_if_fail (GTK_IS_EVENT_CONTROLLER_KEY (controller));
+ g_return_if_fail (!im_context || GTK_IS_IM_CONTEXT (im_context));
+
+ if (controller->im_context)
+ gtk_im_context_reset (controller->im_context);
+
+ g_set_object (&controller->im_context, im_context);
+}
+
+/**
+ * gtk_event_controller_key_get_im_context:
+ * @controller: a #GtkEventControllerKey
+ *
+ * Gets the IM context of a key controller.
+ *
+ * Returns: (transfer none): the IM context
+ *
+ * Since: 3.94
+ **/
+GtkIMContext *
+gtk_event_controller_key_get_im_context (GtkEventControllerKey *controller)
+{
+ g_return_val_if_fail (GTK_IS_EVENT_CONTROLLER_KEY (controller), NULL);
+
+ return controller->im_context;
+}
diff --git a/gtk/gtkeventcontrollerkey.h b/gtk/gtkeventcontrollerkey.h
new file mode 100644
index 0000000000..0b3bcdebdb
--- /dev/null
+++ b/gtk/gtkeventcontrollerkey.h
@@ -0,0 +1,57 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 2017, Red Hat, Inc.
+ *
+ * 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 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/>.
+ *
+ * Author(s): Carlos Garnacho <carlosg@gnome.org>
+ */
+
+#ifndef __GTK_EVENT_CONTROLLER_KEY_H__
+#define __GTK_EVENT_CONTROLLER_KEY_H__
+
+#if !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION)
+#error "Only <gtk/gtk.h> can be included directly."
+#endif
+
+#include <gdk/gdk.h>
+#include <gtk/gtkeventcontroller.h>
+#include <gtk/gtkimcontext.h>
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_EVENT_CONTROLLER_KEY (gtk_event_controller_key_get_type ())
+#define GTK_EVENT_CONTROLLER_KEY(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GTK_TYPE_EVENT_CONTROLLER_KEY, GtkEventControllerKey))
+#define GTK_EVENT_CONTROLLER_KEY_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), GTK_TYPE_EVENT_CONTROLLER_KEY, GtkEventControllerKeyClass))
+#define GTK_IS_EVENT_CONTROLLER_KEY(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GTK_TYPE_EVENT_CONTROLLER_KEY))
+#define GTK_IS_EVENT_CONTROLLER_KEY_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GTK_TYPE_EVENT_CONTROLLER_KEY))
+#define GTK_EVENT_CONTROLLER_KEY_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GTK_TYPE_EVENT_CONTROLLER_KEY, GtkEventControllerKeyClass))
+
+typedef struct _GtkEventControllerKey GtkEventControllerKey;
+typedef struct _GtkEventControllerKeyClass GtkEventControllerKeyClass;
+
+GDK_AVAILABLE_IN_ALL
+GType gtk_event_controller_key_get_type (void) G_GNUC_CONST;
+
+GDK_AVAILABLE_IN_ALL
+GtkEventController *gtk_event_controller_key_new (GtkWidget *widget);
+
+GDK_AVAILABLE_IN_ALL
+void gtk_event_controller_key_set_im_context (GtkEventControllerKey *controller,
+ GtkIMContext *im_context);
+GDK_AVAILABLE_IN_ALL
+GtkIMContext * gtk_event_controller_key_get_im_context (GtkEventControllerKey *controller);
+
+G_END_DECLS
+
+#endif /* __GTK_EVENT_CONTROLLER_KEY_H__ */
diff --git a/gtk/meson.build b/gtk/meson.build
index 5507ec3037..6c68274a25 100644
--- a/gtk/meson.build
+++ b/gtk/meson.build
@@ -201,6 +201,8 @@ gtk_public_sources = files([
'gtkentrybuffer.c',
'gtkentrycompletion.c',
'gtkeventcontroller.c',
+ 'gtkeventcontrollerkey.c',
+ 'gtkeventcontrollerlegacy.c',
'gtkeventcontrollermotion.c',
'gtkeventcontrollerscroll.c',
'gtkexpander.c',
@@ -439,6 +441,7 @@ gtk_public_headers = files([
'gtkentrycompletion.h',
'gtkenums.h',
'gtkeventcontroller.h',
+ 'gtkeventcontrollerkey.h',
'gtkeventcontrollerscroll.h',
'gtkeventcontrollermotion.h',
'gtkexpander.h',
diff --git a/po/POTFILES.in b/po/POTFILES.in
index f3f97c2fa5..03237acd36 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -130,6 +130,7 @@ gtk/gtkentrybuffer.c
gtk/gtkentry.c
gtk/gtkentrycompletion.c
gtk/gtkeventcontroller.c
+gtk/gtkeventcontrollerkey.c
gtk/gtkeventcontrollermotion.c
gtk/gtkeventcontrollerscroll.c
gtk/gtkexpander.c