gtkmain: Look up transient-for hierarchies to determine modality

Windows that are not modal, but are transient-for a modal window should
still be able to receive and handle events. Inspect the window hierarchy
in those cases, so these windows are handled just like widgets within
the modal dialog.

Fixes: https://gitlab.gnome.org/GNOME/gtk/-/issues/2851
Related: https://gitlab.gnome.org/GNOME/gtk/-/issues/2850
This commit is contained in:
Carlos Garnacho
2020-06-22 15:31:36 +02:00
parent 4fe608e423
commit 31b95ce47f

View File

@@ -1663,6 +1663,25 @@ handle_key_event (GdkEvent *event)
return focus_widget ? focus_widget : event_widget;
}
static gboolean
is_transient_for (GtkWindow *child,
GtkWindow *parent)
{
GtkWindow *transient_for;
transient_for = gtk_window_get_transient_for (child);
while (transient_for)
{
if (transient_for == parent)
return TRUE;
transient_for = gtk_window_get_transient_for (transient_for);
}
return FALSE;
}
void
gtk_main_do_event (GdkEvent *event)
{
@@ -1726,11 +1745,16 @@ gtk_main_do_event (GdkEvent *event)
/* If the grab widget is an ancestor of the event widget
* then we send the event to the original event widget.
* This is the key to implementing modality.
* This is the key to implementing modality. This also applies
* across windows that are directly or indirectly transient-for
* the modal one.
*/
if (!grab_widget ||
((gtk_widget_is_sensitive (target_widget) || gdk_event_get_event_type (event) == GDK_SCROLL) &&
gtk_widget_is_ancestor (target_widget, grab_widget)))
gtk_widget_is_ancestor (target_widget, grab_widget)) ||
(GTK_IS_WINDOW (grab_widget) &&
grab_widget != event_widget &&
is_transient_for (GTK_WINDOW (event_widget), GTK_WINDOW (grab_widget))))
grab_widget = target_widget;
g_object_ref (target_widget);