[gtksourceview] completionlist: avoid grabs in completion list
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtksourceview] completionlist: avoid grabs in completion list
- Date: Thu, 1 Sep 2022 04:42:49 +0000 (UTC)
commit 65d038709a5add983fb838c2b1ca56ab16c96802
Author: Christian Hergert <chergert redhat com>
Date: Wed Aug 31 20:42:54 2022 -0700
completionlist: avoid grabs in completion list
This follows suit of other GtkSourceAssistant by removing the grabs that
would otherwise be taken by the completion list and instead uses
GtkPopover:autohide=FAlSE.
This allows us a bit more flexibility in how events are routed but also
ensures that input doesn't continually enter/leave the source view on
every display of the list.
It also simplifies the grab management for the native surfaces since they
no longer need to track crossings and break grabs.
gtksourceview/gtksourcecompletionlist.c | 115 ++++++++++++++++++++------------
1 file changed, 74 insertions(+), 41 deletions(-)
---
diff --git a/gtksourceview/gtksourcecompletionlist.c b/gtksourceview/gtksourcecompletionlist.c
index 3ccb20f3..af1dbfd2 100644
--- a/gtksourceview/gtksourcecompletionlist.c
+++ b/gtksourceview/gtksourcecompletionlist.c
@@ -48,6 +48,10 @@ struct _GtkSourceCompletionList
GtkSourceCompletionCell *comments;
GtkLabel *alternate_label;
+ GtkEventController *key;
+ gulong key_press_handler;
+ gulong key_release_handler;
+
guint remember_info_visibility : 1;
};
@@ -62,6 +66,38 @@ G_DEFINE_TYPE (GtkSourceCompletionList, _gtk_source_completion_list, GTK_SOURCE_
static GParamSpec *properties [N_PROPS];
+static void
+_gtk_source_completion_list_unroot (GtkWidget *widget)
+{
+ GtkSourceCompletionList *self = (GtkSourceCompletionList *)widget;
+ GtkWidget *view;
+
+ g_assert (GTK_SOURCE_IS_COMPLETION_LIST (self));
+
+ if ((view = gtk_widget_get_ancestor (widget, GTK_SOURCE_TYPE_VIEW)))
+ {
+ gtk_widget_remove_controller (view, self->key);
+ }
+
+ GTK_WIDGET_CLASS (_gtk_source_completion_list_parent_class)->unroot (widget);
+}
+
+static void
+_gtk_source_completion_list_root (GtkWidget *widget)
+{
+ GtkSourceCompletionList *self = (GtkSourceCompletionList *)widget;
+ GtkWidget *view;
+
+ g_assert (GTK_SOURCE_IS_COMPLETION_LIST (self));
+
+ GTK_WIDGET_CLASS (_gtk_source_completion_list_parent_class)->root (widget);
+
+ if ((view = gtk_widget_get_ancestor (widget, GTK_SOURCE_TYPE_VIEW)))
+ {
+ gtk_widget_add_controller (view, g_object_ref (self->key));
+ }
+}
+
static void
_gtk_source_completion_list_hide (GtkWidget *widget)
{
@@ -69,6 +105,9 @@ _gtk_source_completion_list_hide (GtkWidget *widget)
g_assert (GTK_SOURCE_IS_COMPLETION_LIST (self));
+ g_signal_handler_block (self->key, self->key_press_handler);
+ g_signal_handler_block (self->key, self->key_release_handler);
+
GTK_WIDGET_CLASS (_gtk_source_completion_list_parent_class)->hide (widget);
if (!self->remember_info_visibility)
@@ -90,6 +129,9 @@ _gtk_source_completion_list_show (GtkWidget *widget)
{
gtk_widget_show (GTK_WIDGET (self->info));
}
+
+ g_signal_handler_unblock (self->key, self->key_press_handler);
+ g_signal_handler_unblock (self->key, self->key_release_handler);
}
static void
@@ -263,30 +305,17 @@ key_press_propagate_cb (GtkSourceCompletionList *self,
GdkModifierType modifiers,
GtkEventControllerKey *key)
{
- GtkWidget *parent;
-
g_assert (GTK_SOURCE_IS_COMPLETION_LIST (self));
g_assert (GTK_IS_EVENT_CONTROLLER_KEY (key));
- parent = gtk_widget_get_ancestor (GTK_WIDGET (self), GTK_SOURCE_TYPE_VIEW);
-
- /* Process Escape inline because we want to both hide our assistant
- * but also allow the view to handle Escape too (which might pass it
- * along to somehwere else like Vim emulation.
- */
-
if (keyval == GDK_KEY_Escape)
{
+ /* Still propagate after hiding */
gtk_widget_hide (GTK_WIDGET (self));
}
else if (gtk_event_controller_key_forward (key, GTK_WIDGET (self->listbox)))
{
- return TRUE;
- }
-
- if (GTK_SOURCE_IS_VIEW (parent))
- {
- return gtk_event_controller_key_forward (key, parent);
+ return GDK_EVENT_STOP;
}
return GDK_EVENT_PROPAGATE;
@@ -299,21 +328,12 @@ key_release_propagate_cb (GtkSourceCompletionList *self,
GdkModifierType modifiers,
GtkEventControllerKey *key)
{
- GtkWidget *parent;
-
g_assert (GTK_SOURCE_IS_COMPLETION_LIST (self));
g_assert (GTK_IS_EVENT_CONTROLLER_KEY (key));
if (gtk_event_controller_key_forward (key, GTK_WIDGET (self->listbox)))
{
- return TRUE;
- }
-
- parent = gtk_widget_get_ancestor (GTK_WIDGET (self), GTK_SOURCE_TYPE_VIEW);
-
- if (GTK_SOURCE_IS_VIEW (parent))
- {
- return gtk_event_controller_key_forward (key, parent);
+ return GDK_EVENT_STOP;
}
return GDK_EVENT_PROPAGATE;
@@ -347,6 +367,13 @@ _gtk_source_completion_list_dispose (GObject *object)
g_clear_object (&self->context);
+ if (self->key)
+ {
+ g_clear_signal_handler (&self->key_press_handler, self->key);
+ g_clear_signal_handler (&self->key_release_handler, self->key);
+ g_clear_object (&self->key);
+ }
+
G_OBJECT_CLASS (_gtk_source_completion_list_parent_class)->dispose (object);
}
@@ -410,6 +437,8 @@ _gtk_source_completion_list_class_init (GtkSourceCompletionListClass *klass)
widget_class->get_request_mode = _gtk_source_completion_list_get_request_mode;
widget_class->show = _gtk_source_completion_list_show;
widget_class->hide = _gtk_source_completion_list_hide;
+ widget_class->root = _gtk_source_completion_list_root;
+ widget_class->unroot = _gtk_source_completion_list_unroot;
assistant_class->get_offset = _gtk_source_completion_list_get_offset;
assistant_class->get_target_location = _gtk_source_completion_list_get_target_location;
@@ -446,25 +475,29 @@ _gtk_source_completion_list_class_init (GtkSourceCompletionListClass *klass)
static void
_gtk_source_completion_list_init (GtkSourceCompletionList *self)
{
- GtkEventController *key;
-
gtk_widget_init_template (GTK_WIDGET (self));
gtk_widget_add_css_class (GTK_WIDGET (self), "completion");
- gtk_popover_set_position (GTK_POPOVER (self), GTK_POS_BOTTOM);
- key = gtk_event_controller_key_new ();
- gtk_event_controller_set_propagation_phase (key, GTK_PHASE_BUBBLE);
- g_signal_connect_object (key,
- "key-pressed",
- G_CALLBACK (key_press_propagate_cb),
- self,
- G_CONNECT_SWAPPED);
- g_signal_connect_object (key,
- "key-released",
- G_CALLBACK (key_release_propagate_cb),
- self,
- G_CONNECT_SWAPPED);
- gtk_widget_add_controller (GTK_WIDGET (self), g_steal_pointer (&key));
+ gtk_popover_set_position (GTK_POPOVER (self), GTK_POS_BOTTOM);
+ gtk_popover_set_autohide (GTK_POPOVER (self), FALSE);
+
+ self->key = gtk_event_controller_key_new ();
+ gtk_event_controller_set_name (self->key, "gtk-source-completion");
+ gtk_event_controller_set_propagation_phase (self->key, GTK_PHASE_CAPTURE);
+ self->key_press_handler =
+ g_signal_connect_object (self->key,
+ "key-pressed",
+ G_CALLBACK (key_press_propagate_cb),
+ self,
+ G_CONNECT_SWAPPED);
+ self->key_release_handler =
+ g_signal_connect_object (self->key,
+ "key-released",
+ G_CALLBACK (key_release_propagate_cb),
+ self,
+ G_CONNECT_SWAPPED);
+ g_signal_handler_block (self->key, self->key_press_handler);
+ g_signal_handler_block (self->key, self->key_release_handler);
self->info = GTK_SOURCE_COMPLETION_INFO (_gtk_source_completion_info_new ());
_gtk_source_assistant_attach (GTK_SOURCE_ASSISTANT (self->info),
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]