[gtk/wip/carlosg/input-cleanups: 2/26] gtkmain: Look up transient-for hierarchies to determine modality



commit 31b95ce47f214965323d980bd09a7a1bed65ed7e
Author: Carlos Garnacho <carlosg gnome org>
Date:   Mon Jun 22 15:31:36 2020 +0200

    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

 gtk/gtkmain.c | 28 ++++++++++++++++++++++++++--
 1 file changed, 26 insertions(+), 2 deletions(-)
---
diff --git a/gtk/gtkmain.c b/gtk/gtkmain.c
index 84e7efdc8d..fd43c9eb77 100644
--- a/gtk/gtkmain.c
+++ b/gtk/gtkmain.c
@@ -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);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]