[gtk/wip/carlosg/input-cleanups: 21/26] gtkmain: Make grab-notify notifications more targeted
- From: Carlos Garnacho <carlosg src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk/wip/carlosg/input-cleanups: 21/26] gtkmain: Make grab-notify notifications more targeted
- Date: Wed, 24 Jun 2020 18:38:15 +0000 (UTC)
commit ddb3a4be3e7b993208a08bd72080bda3c53ff172
Author: Carlos Garnacho <carlosg gnome org>
Date: Wed Jun 24 17:19:57 2020 +0200
gtkmain: Make grab-notify notifications more targeted
We only want to send grab-notify to widgets that might have been
interacting with devices via events. Instead of going through all
widgets in all toplevels, we have the window/pointer focus information,
so we can just traverse the widget stacks for every involved foci.
gtk/gtkmain.c | 129 ++-----------------------------------------------
gtk/gtkwindow.c | 103 +++++++++++++++++++++++++++++++++++++++
gtk/gtkwindowprivate.h | 4 ++
3 files changed, 111 insertions(+), 125 deletions(-)
---
diff --git a/gtk/gtkmain.c b/gtk/gtkmain.c
index dd1aae99cf..9f845a4866 100644
--- a/gtk/gtkmain.c
+++ b/gtk/gtkmain.c
@@ -1859,120 +1859,6 @@ gtk_main_get_window_group (GtkWidget *widget)
return gtk_window_get_group (NULL);
}
-typedef struct
-{
- GtkWidget *old_grab_widget;
- GtkWidget *new_grab_widget;
- gboolean was_grabbed;
- gboolean is_grabbed;
- gboolean from_grab;
- GList *notified_surfaces;
-} GrabNotifyInfo;
-
-static void
-synth_crossing_for_grab_notify (GtkWidget *from,
- GtkWidget *to,
- GrabNotifyInfo *info,
- GdkDevice **devices,
- guint n_devices,
- GdkCrossingMode mode)
-{
- guint i;
-
- for (i = 0; i < n_devices; i++)
- {
- GdkDevice *device = devices[i];
- GdkSurface *from_surface, *to_surface;
-
- if (!from)
- from_surface = NULL;
- else
- from_surface = gtk_native_get_surface (gtk_widget_get_native (from));
-
- if (!to)
- to_surface = NULL;
- else
- to_surface = gtk_native_get_surface (gtk_widget_get_native (to));
-
- if (from_surface || to_surface)
- {
- _gtk_widget_synthesize_crossing ((from_surface) ? from : NULL,
- (to_surface) ? to : NULL,
- device, mode);
-
- if (from_surface)
- info->notified_surfaces = g_list_prepend (info->notified_surfaces, from_surface);
-
- if (to_surface)
- info->notified_surfaces = g_list_prepend (info->notified_surfaces, to_surface);
- }
- }
-}
-
-static void
-gtk_grab_notify_foreach (GtkWidget *child,
- gpointer data)
-{
- GrabNotifyInfo *info = data;
- gboolean was_grabbed, is_grabbed, was_shadowed, is_shadowed;
- GdkDevice **devices;
- guint n_devices;
-
- was_grabbed = info->was_grabbed;
- is_grabbed = info->is_grabbed;
-
- info->was_grabbed = info->was_grabbed || (child == info->old_grab_widget);
- info->is_grabbed = info->is_grabbed || (child == info->new_grab_widget);
-
- was_shadowed = info->old_grab_widget && !info->was_grabbed;
- is_shadowed = info->new_grab_widget && !info->is_grabbed;
-
- g_object_ref (child);
-
- if (was_shadowed || is_shadowed)
- {
- GtkWidget *p;
-
- for (p = _gtk_widget_get_first_child (child);
- p != NULL;
- p = _gtk_widget_get_next_sibling (p))
- {
- gtk_grab_notify_foreach (p, info);
- }
- }
-
- devices = _gtk_widget_list_devices (child, &n_devices);
-
- if (is_shadowed)
- {
- _gtk_widget_set_shadowed (child, TRUE);
- if (!was_shadowed && devices &&
- gtk_widget_is_sensitive (child))
- synth_crossing_for_grab_notify (child, info->new_grab_widget,
- info, devices, n_devices,
- GDK_CROSSING_GTK_GRAB);
- }
- else
- {
- _gtk_widget_set_shadowed (child, FALSE);
- if (was_shadowed && devices &&
- gtk_widget_is_sensitive (child))
- synth_crossing_for_grab_notify (info->old_grab_widget, child,
- info, devices, n_devices,
- info->from_grab ? GDK_CROSSING_GTK_GRAB :
- GDK_CROSSING_GTK_UNGRAB);
- }
-
- if (was_shadowed != is_shadowed)
- _gtk_widget_grab_notify (child, was_shadowed);
-
- g_object_unref (child);
- g_free (devices);
-
- info->was_grabbed = was_grabbed;
- info->is_grabbed = is_grabbed;
-}
-
static void
gtk_grab_notify (GtkWindowGroup *group,
GtkWidget *old_grab_widget,
@@ -1980,15 +1866,10 @@ gtk_grab_notify (GtkWindowGroup *group,
gboolean from_grab)
{
GList *toplevels;
- GrabNotifyInfo info = { 0 };
if (old_grab_widget == new_grab_widget)
return;
- info.old_grab_widget = old_grab_widget;
- info.new_grab_widget = new_grab_widget;
- info.from_grab = from_grab;
-
g_object_ref (group);
toplevels = gtk_window_list_toplevels ();
@@ -1999,15 +1880,13 @@ gtk_grab_notify (GtkWindowGroup *group,
GtkWindow *toplevel = toplevels->data;
toplevels = g_list_delete_link (toplevels, toplevels);
- info.was_grabbed = FALSE;
- info.is_grabbed = FALSE;
-
- if (group == gtk_window_get_group (toplevel))
- gtk_grab_notify_foreach (GTK_WIDGET (toplevel), &info);
+ gtk_window_grab_notify (toplevel,
+ old_grab_widget,
+ new_grab_widget,
+ from_grab);
g_object_unref (toplevel);
}
- g_list_free (info.notified_surfaces);
g_object_unref (group);
}
diff --git a/gtk/gtkwindow.c b/gtk/gtkwindow.c
index c9d3bfd33f..aeeb383088 100644
--- a/gtk/gtkwindow.c
+++ b/gtk/gtkwindow.c
@@ -7221,3 +7221,106 @@ gtk_window_get_foci_on_widget (GtkWindow *window,
return (GdkDevice**) g_ptr_array_free (array, FALSE);
}
+
+static void
+gtk_grab_notify_foreach (GtkWidget *child,
+ GdkDevice *device,
+ GtkWidget *new_grab_widget,
+ GtkWidget *old_grab_widget,
+ gboolean from_grab,
+ gboolean was_shadowed,
+ gboolean is_shadowed)
+{
+ g_object_ref (child);
+
+ if (is_shadowed)
+ {
+ _gtk_widget_set_shadowed (child, TRUE);
+ if (!was_shadowed &&
+ gtk_widget_is_sensitive (child))
+ _gtk_widget_synthesize_crossing (child,
+ new_grab_widget,
+ device,
+ GDK_CROSSING_GTK_GRAB);
+ }
+ else
+ {
+ _gtk_widget_set_shadowed (child, FALSE);
+ if (was_shadowed &&
+ gtk_widget_is_sensitive (child))
+ _gtk_widget_synthesize_crossing (old_grab_widget, child,
+ device,
+ from_grab ? GDK_CROSSING_GTK_GRAB :
+ GDK_CROSSING_GTK_UNGRAB);
+ }
+
+ _gtk_widget_grab_notify (child, was_shadowed);
+
+ g_object_unref (child);
+}
+
+static void
+gtk_window_propagate_grab_notify (GtkWindow *window,
+ GtkWidget *target,
+ GdkDevice *device,
+ GtkWidget *old_grab_widget,
+ GtkWidget *new_grab_widget,
+ gboolean from_grab)
+{
+ GList *l, *widgets = NULL;
+ gboolean was_grabbed = FALSE, is_grabbed = FALSE;
+
+ while (target)
+ {
+ widgets = g_list_prepend (widgets, g_object_ref (target));
+ target = gtk_widget_get_parent (target);
+ }
+
+ widgets = g_list_reverse (widgets);
+
+ for (l = widgets; l; l = l->next)
+ {
+ gboolean was_shadowed, is_shadowed;
+
+ was_grabbed |= (l->data == old_grab_widget);
+ is_grabbed |= (l->data == new_grab_widget);
+
+ was_shadowed = old_grab_widget && !was_grabbed;
+ is_shadowed = new_grab_widget && is_grabbed;
+
+ if (was_shadowed == is_shadowed)
+ break;
+
+ gtk_grab_notify_foreach (l->data,
+ device,
+ old_grab_widget,
+ new_grab_widget,
+ from_grab,
+ was_shadowed,
+ is_shadowed);
+ }
+
+ g_list_free_full (widgets, g_object_unref);
+}
+
+void
+gtk_window_grab_notify (GtkWindow *window,
+ GtkWidget *old_grab_widget,
+ GtkWidget *new_grab_widget,
+ gboolean from_grab)
+{
+ GtkWindowPrivate *priv = gtk_window_get_instance_private (window);
+ GList *l;
+
+ for (l = priv->foci; l; l = l->next)
+ {
+ GtkPointerFocus *focus = l->data;
+
+ gtk_window_propagate_grab_notify (window,
+ gtk_pointer_focus_get_effective_target (focus),
+ focus->device,
+ old_grab_widget,
+ new_grab_widget,
+ from_grab);
+ }
+}
diff --git a/gtk/gtkwindowprivate.h b/gtk/gtkwindowprivate.h
index 14a3f8617c..4cb31c3eed 100644
--- a/gtk/gtkwindowprivate.h
+++ b/gtk/gtkwindowprivate.h
@@ -127,6 +127,10 @@ GtkWidget * gtk_window_pick_popover (GtkWindow *window,
GdkDevice** gtk_window_get_foci_on_widget (GtkWindow *window,
GtkWidget *widget,
guint *n_devices);
+void gtk_window_grab_notify (GtkWindow *window,
+ GtkWidget *old_grab_widget,
+ GtkWidget *new_grab_widget,
+ gboolean from_grab);
G_END_DECLS
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]