summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarlos Garnacho <carlosg@gnome.org>2017-12-11 19:21:38 +0100
committerCarlos Garnacho <carlosg@gnome.org>2018-07-16 15:43:43 +0200
commite0f3e8a7e5d898aba11cce1fcffe79fd142b12ae (patch)
treea519f30ebc9b08e363e9faf0351fba2773886847
parent1f9de707f7e1bd6f7241000dbbad464530b23e81 (diff)
downloadgtk+-e0f3e8a7e5d898aba11cce1fcffe79fd142b12ae.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/Makefile.am2
-rw-r--r--gtk/gtk.h1
-rw-r--r--gtk/gtkeventcontrollerkey.c217
-rw-r--r--gtk/gtkeventcontrollerkey.h57
-rw-r--r--po/POTFILES.in3
5 files changed, 280 insertions, 0 deletions
diff --git a/gtk/Makefile.am b/gtk/Makefile.am
index ec81f395d7..93f3d5c29c 100644
--- a/gtk/Makefile.am
+++ b/gtk/Makefile.am
@@ -192,6 +192,7 @@ gtk_public_h_sources = \
gtkenums.h \
gtkeventbox.h \
gtkeventcontroller.h \
+ gtkeventcontrollerkey.h \
gtkeventcontrollermotion.h \
gtkeventcontrollerscroll.h \
gtkexpander.h \
@@ -759,6 +760,7 @@ gtk_base_c_sources = \
gtkentrycompletion.c \
gtkeventbox.c \
gtkeventcontroller.c \
+ gtkeventcontrollerkey.c \
gtkeventcontrollermotion.c \
gtkeventcontrollerscroll.c \
gtkexpander.c \
diff --git a/gtk/gtk.h b/gtk/gtk.h
index 46cfbfc063..8dee2a9efc 100644
--- a/gtk/gtk.h
+++ b/gtk/gtk.h
@@ -94,6 +94,7 @@
#include <gtk/gtkenums.h>
#include <gtk/gtkeventbox.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..13015312c7
--- /dev/null
+++ b/gtk/gtkeventcontrollerkey.c
@@ -0,0 +1,217 @@
+/* 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;
+ 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) || !event->key.is_modifier)
+ return FALSE;
+
+ key->current_event = event;
+
+ if (event->key.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..025aa336ef
--- /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_3_24
+GType gtk_event_controller_key_get_type (void) G_GNUC_CONST;
+
+GDK_AVAILABLE_IN_3_24
+GtkEventController *gtk_event_controller_key_new (GtkWidget *widget);
+
+GDK_AVAILABLE_IN_3_24
+void gtk_event_controller_key_set_im_context (GtkEventControllerKey *controller,
+ GtkIMContext *im_context);
+GDK_AVAILABLE_IN_3_24
+GtkIMContext * gtk_event_controller_key_get_im_context (GtkEventControllerKey *controller);
+
+G_END_DECLS
+
+#endif /* __GTK_EVENT_CONTROLLER_KEY_H__ */
diff --git a/po/POTFILES.in b/po/POTFILES.in
index a2cd6f5c86..443d15a77d 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -142,6 +142,9 @@ gtk/gtkentry.c
gtk/gtkentrycompletion.c
gtk/gtkeventbox.c
gtk/gtkeventcontroller.c
+gtk/gtkeventcontrollerkey.c
+gtk/gtkeventcontrollermotion.c
+gtk/gtkeventcontrollerscroll.c
gtk/gtkexpander.c
gtk/gtkfilechooserbutton.c
gtk/gtkfilechooser.c