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



commit 108e3ffd184a6efb3cf299be238d2fd0ca2bf381
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.

 gcr/gcr-prompt.c       |  4 +++
 ui/gcr-prompt-dialog.c | 81 +++++++++++++++++++++++++++++++++++++++-----------
 2 files changed, 67 insertions(+), 18 deletions(-)
---
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]