[gcr/wip/nielsdg/lose-x11-dependency: 1/2] prompt: Support transient_for in Wayland



commit 095d8d98ce943e2d6d3db6e40fae71c3210d0d9f
Author: Niels De Graef <nielsdegraef gmail com>
Date:   Tue Dec 3 08:51:28 2019 +0100

    prompt: Support transient_for in Wayland
    
    GDK provides an interface to the _xdg-foreign_ protocol extension, which
    exactly allows to export a handle that another window can use to set
    itself transient to.
    
    Also bump the minmal GTK version to 3.22, since that is the version that
    adds the necessary methods to do this in GDK.

 configure.ac           |  2 +-
 gcr/gcr-prompt.c       |  4 +++
 ui/gcr-prompt-dialog.c | 81 +++++++++++++++++++++++++++++++++++++++-----------
 3 files changed, 68 insertions(+), 19 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index c7c5e65..6133d09 100644
--- a/configure.ac
+++ b/configure.ac
@@ -17,7 +17,7 @@ GLIB_MAX=GLIB_VERSION_2_38
 
 GCRYPT_VERSION=1.4.5
 
-GTK_REQ=3.12
+GTK_REQ=3.22
 
 dnl ****************************************************************************
 dnl Library package and libtool versioning
diff --git a/gcr/gcr-prompt.c b/gcr/gcr-prompt.c
index d1e71a4..a2a6aaf 100644
--- a/gcr/gcr-prompt.c
+++ b/gcr/gcr-prompt.c
@@ -210,6 +210,10 @@ gcr_prompt_default_init (GcrPromptIface *iface)
                 * The caller window indicates to the prompt which window is prompting the
                 * user. The prompt may choose to ignore this information or use it in whatever
                 * way it sees fit.
+                *
+                * In X11, this will be a stringified version of the XWindow handle; in
+                * Wayland this is the result of an export using the XDG foreign
+                * protocol.
                 */
                g_object_interface_install_property (iface,
                                g_param_spec_string ("caller-window", "Caller window", "Window ID of 
application window requesting prompt",
diff --git a/ui/gcr-prompt-dialog.c b/ui/gcr-prompt-dialog.c
index f623df1..147a05b 100644
--- a/ui/gcr-prompt-dialog.c
+++ b/ui/gcr-prompt-dialog.c
@@ -30,6 +30,9 @@
 #ifdef GDK_WINDOWING_X11
 #include <gdk/gdkx.h>
 #endif
+#ifdef GDK_WINDOWING_WAYLAND
+#include <gdk/gdkwayland.h>
+#endif
 #include <glib/gi18n.h>
 
 /**
@@ -126,29 +129,22 @@ G_DEFINE_TYPE_WITH_CODE (GcrPromptDialog, gcr_prompt_dialog, GTK_TYPE_DIALOG,
                          G_IMPLEMENT_INTERFACE (GCR_TYPE_PROMPT, gcr_prompt_dialog_prompt_iface);
 );
 
-static void
-update_transient_for (GcrPromptDialog *self)
+#ifdef GDK_WINDOWING_X11
+static gboolean
+update_transient_for_x11 (GcrPromptDialog *self, GdkWindow *window)
 {
-       GdkDisplay *display;
-       GdkWindow *transient_for = NULL;
-       GdkWindow *window;
        gint64 handle;
        gchar *end;
+       GdkDisplay *display;
+       GdkWindow *transient_for;
 
-       if (self->pv->caller_window == NULL || g_str_equal (self->pv->caller_window, "")) {
-               gtk_window_set_modal (GTK_WINDOW (self), FALSE);
-               return;
-       }
-
-       window = gtk_widget_get_window (GTK_WIDGET (self));
-       if (window == NULL)
-               return;
+       if (!GDK_IS_X11_WINDOW (window))
+               return FALSE;
 
-#ifdef GDK_WINDOWING_X11
        handle = g_ascii_strtoll (self->pv->caller_window, &end, 10);
        if (!end || *end != '\0') {
                g_warning ("couldn't parse caller-window property: %s", self->pv->caller_window);
-               return;
+               return FALSE;
        }
 
        display = gtk_widget_get_display (GTK_WIDGET (self));
@@ -156,12 +152,61 @@ update_transient_for (GcrPromptDialog *self)
        if (transient_for == NULL) {
                g_warning ("caller-window property doesn't represent a window on current display: %s",
                           self->pv->caller_window);
-       } else {
-               gdk_window_set_transient_for (window, transient_for);
-               g_object_unref (transient_for);
+               return FALSE;
        }
+
+       gdk_window_set_transient_for (window, transient_for);
+       g_object_unref (transient_for);
+       return TRUE;
+}
 #endif
 
+#ifdef GDK_WINDOWING_WAYLAND
+static gboolean
+update_transient_for_wl (GcrPromptDialog *self, GdkWindow *window)
+{
+       if (!GDK_IS_WAYLAND_WINDOW (window))
+               return FALSE;
+
+       if (gdk_wayland_window_set_transient_for_exported (window, self->pv->caller_window)) {
+               g_debug ("Succesfully set transient for WL window %s", self->pv->caller_window);
+               return TRUE;
+       }
+
+       g_warning ("caller-window property doesn't represent a window on current display: %s",
+                  self->pv->caller_window);
+       return FALSE;
+}
+#endif
+
+static void
+update_transient_for (GcrPromptDialog *self)
+{
+       GdkWindow *window;
+       gboolean success = FALSE;
+
+       if (self->pv->caller_window == NULL || g_str_equal (self->pv->caller_window, "")) {
+               gtk_window_set_modal (GTK_WINDOW (self), FALSE);
+               return;
+       }
+
+       window = gtk_widget_get_window (GTK_WIDGET (self));
+       if (window == NULL)
+               return;
+
+#ifdef GDK_WINDOWING_X11
+       if (!success)
+               success |= update_transient_for_x11 (self, window);
+#endif
+#ifdef GDK_WINDOWING_WAYLAND
+       if (!success)
+               success |= update_transient_for_wl (self, window);
+#endif
+
+       if (!success) {
+               g_warning ("Couldn't set transient to caller window");
+       }
+
        gtk_window_set_modal (GTK_WINDOW (self), TRUE);
 }
 


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