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




commit 831682e7f6851e91ca8c4b3732ff57f63978860c
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 +++
 meson.build            |  3 +-
 ui/frob-prompt.c       |  2 ++
 ui/gcr-prompt-dialog.c | 81 +++++++++++++++++++++++++++++++++++++++-----------
 ui/meson.build         |  1 -
 6 files changed, 71 insertions(+), 22 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index 9b7c5d7a..18b7ef70 100644
--- a/configure.ac
+++ b/configure.ac
@@ -17,7 +17,7 @@ GLIB_MAX=GLIB_VERSION_2_44
 
 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 6a34cba3..997c819f 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/meson.build b/meson.build
index a26a0f92..196d4564 100644
--- a/meson.build
+++ b/meson.build
@@ -50,9 +50,8 @@ if p11_system_config_modules == ''
 endif
 
 if get_option('gtk')
-  gtk_min_version = '3.12'
+  gtk_min_version = '3.22'
   gtk_dep = dependency('gtk+-3.0', version: '>=' + gtk_min_version)
-  gtk_x11_dep = dependency('gtk+-x11-3.0', version: '>=' + gtk_min_version)
 endif
 
 # configuration
diff --git a/ui/frob-prompt.c b/ui/frob-prompt.c
index 53955bef..f5a84030 100644
--- a/ui/frob-prompt.c
+++ b/ui/frob-prompt.c
@@ -25,7 +25,9 @@
 #include "gcr/gcr-base.h"
 
 #include <gtk/gtk.h>
+#ifdef GDK_WINDOWING_X11
 #include <gdk/gdkx.h>
+#endif
 
 #include <err.h>
 
diff --git a/ui/gcr-prompt-dialog.c b/ui/gcr-prompt-dialog.c
index 11297d5a..5331b6e3 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>
 
 /**
@@ -130,29 +133,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));
@@ -160,12 +156,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);
 }
 
diff --git a/ui/meson.build b/ui/meson.build
index 477412dd..e656ea23 100644
--- a/ui/meson.build
+++ b/ui/meson.build
@@ -84,7 +84,6 @@ gcr_ui_deps = [
   gck_dep,
   gcr_base_dep,
   gtk_dep,
-  gtk_x11_dep,
 ]
 
 gcr_ui_cflags = [


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