diff options
author | Carlos Garnacho <carlosg@gnome.org> | 2017-12-11 19:21:38 +0100 |
---|---|---|
committer | Carlos Garnacho <carlosg@gnome.org> | 2018-07-16 15:43:43 +0200 |
commit | e0f3e8a7e5d898aba11cce1fcffe79fd142b12ae (patch) | |
tree | a519f30ebc9b08e363e9faf0351fba2773886847 | |
parent | 1f9de707f7e1bd6f7241000dbbad464530b23e81 (diff) | |
download | gtk+-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.am | 2 | ||||
-rw-r--r-- | gtk/gtk.h | 1 | ||||
-rw-r--r-- | gtk/gtkeventcontrollerkey.c | 217 | ||||
-rw-r--r-- | gtk/gtkeventcontrollerkey.h | 57 | ||||
-rw-r--r-- | po/POTFILES.in | 3 |
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 \ @@ -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 |