From b7fee9f9d2bb457781e92c73c73005a17a783e2c Mon Sep 17 00:00:00 2001 From: Carlos Garnacho Date: Sat, 1 Apr 2017 22:38:02 +0200 Subject: [PATCH] gtkwindow: Revoke implicit grabs when activating an explicit one Only if they fall outside the grab widget, in that case the widget holding the implicit grab won't be receiving events anymore, so we can just undo it. --- gtk/gtkwindow.c | 28 ++++++++++++++++++++++++++++ gtk/gtkwindowgroup.c | 23 +++++++++++++++++++++++ gtk/gtkwindowprivate.h | 4 ++++ 3 files changed, 55 insertions(+) diff --git a/gtk/gtkwindow.c b/gtk/gtkwindow.c index d6efac75ee..f0e8f07125 100644 --- a/gtk/gtkwindow.c +++ b/gtk/gtkwindow.c @@ -11470,6 +11470,34 @@ gtk_window_update_pointer_focus_on_state_change (GtkWindow *window, } } +void +gtk_window_maybe_revoke_implicit_grab (GtkWindow *window, + GdkDevice *device, + GtkWidget *grab_widget) +{ + GList *l = window->priv->foci, *cur; + + while (l) + { + GtkPointerFocus *focus = l->data; + + cur = l; + focus = cur->data; + l = cur->next; + + if (focus->toplevel != window) + continue; + + if (device && focus->device == device && + focus->target != grab_widget && + !gtk_widget_is_ancestor (focus->target, grab_widget)) + gtk_window_set_pointer_focus_grab (window, + focus->device, + focus->sequence, + NULL); + } +} + void gtk_window_set_pointer_focus_grab (GtkWindow *window, GdkDevice *device, diff --git a/gtk/gtkwindowgroup.c b/gtk/gtkwindowgroup.c index bb1265065f..38befc5a4c 100644 --- a/gtk/gtkwindowgroup.c +++ b/gtk/gtkwindowgroup.c @@ -253,6 +253,25 @@ gtk_window_group_get_current_grab (GtkWindowGroup *window_group) return NULL; } +static void +revoke_implicit_grabs (GtkWindowGroup *window_group, + GdkDevice *device, + GtkWidget *grab_widget) +{ + GList *windows, *l; + + windows = gtk_window_group_list_windows (window_group); + + for (l = windows; l; l = l->next) + { + gtk_window_maybe_revoke_implicit_grab (l->data, + device, + grab_widget); + } + + g_list_free (windows); +} + void _gtk_window_group_add_grab (GtkWindowGroup *window_group, GtkWidget *widget) @@ -261,6 +280,8 @@ _gtk_window_group_add_grab (GtkWindowGroup *window_group, priv = window_group->priv; priv->grabs = g_slist_prepend (priv->grabs, widget); + + revoke_implicit_grabs (window_group, NULL, widget); } void @@ -290,6 +311,8 @@ _gtk_window_group_add_device_grab (GtkWindowGroup *window_group, info->block_others = block_others; priv->device_grabs = g_slist_prepend (priv->device_grabs, info); + + revoke_implicit_grabs (window_group, device, widget); } void diff --git a/gtk/gtkwindowprivate.h b/gtk/gtkwindowprivate.h index 7d8d18965d..857121985e 100644 --- a/gtk/gtkwindowprivate.h +++ b/gtk/gtkwindowprivate.h @@ -161,6 +161,10 @@ void gtk_window_set_pointer_focus_grab (GtkWindow *window, void gtk_window_update_pointer_focus_on_state_change (GtkWindow *window, GtkWidget *widget); +void gtk_window_maybe_revoke_implicit_grab (GtkWindow *window, + GdkDevice *device, + GtkWidget *grab_widget); + G_END_DECLS #endif /* __GTK_WINDOW_PRIVATE_H__ */