[gtk/wip/carlosg/xdg-activation-3-24] gdk/wayland: Support the xdg-activation wayland protocol




commit 5de90fb6dfec71ca37260288bc67b044e76e2faa
Author: Carlos Garnacho <carlosg gnome org>
Date:   Wed Dec 2 17:22:41 2020 +0100

    gdk/wayland: Support the xdg-activation wayland protocol
    
    This protocol implements the IPC necessary to focus application
    windows across launcher/launchee. Add support for it.

 gdk/wayland/Makefile.am                   |  2 +
 gdk/wayland/gdkapplaunchcontext-wayland.c | 65 ++++++++++++++++++++++++++++++-
 gdk/wayland/gdkdevice-wayland.c           |  2 +-
 gdk/wayland/gdkdisplay-wayland.c          | 14 ++++++-
 gdk/wayland/gdkdisplay-wayland.h          |  3 ++
 gdk/wayland/gdkprivate-wayland.h          |  1 +
 gdk/wayland/gdkwindow-wayland.c           |  9 ++++-
 gdk/wayland/meson.build                   |  1 +
 8 files changed, 93 insertions(+), 4 deletions(-)
---
diff --git a/gdk/wayland/Makefile.am b/gdk/wayland/Makefile.am
index 6595013d3f..2b04a37216 100644
--- a/gdk/wayland/Makefile.am
+++ b/gdk/wayland/Makefile.am
@@ -23,6 +23,8 @@ noinst_LTLIBRARIES =                          \
 BUILT_SOURCES =                                \
        pointer-gestures-unstable-v1-client-protocol.h          \
        pointer-gestures-unstable-v1-protocol.c                 \
+       xdg-activation-unstable-v1-client-protocol.h            \
+       xdg-activation-unstable-v1-protocol.c                   \
        xdg-shell-client-protocol.h                             \
        xdg-shell-protocol.c                                    \
        xdg-shell-unstable-v6-client-protocol.h                 \
diff --git a/gdk/wayland/gdkapplaunchcontext-wayland.c b/gdk/wayland/gdkapplaunchcontext-wayland.c
index f18c13e6b4..0b19c326db 100644
--- a/gdk/wayland/gdkapplaunchcontext-wayland.c
+++ b/gdk/wayland/gdkapplaunchcontext-wayland.c
@@ -30,6 +30,35 @@
 #include "gdkinternals.h"
 #include "gdkintl.h"
 
+typedef struct {
+  gchar *token;
+  gboolean failed;
+} AppLaunchData;
+
+static void
+token_provider_done (gpointer                                  data,
+                     struct zxdg_activation_token_provider_v1 *provider,
+                     const char                               *token)
+{
+  AppLaunchData *app_launch_data = data;
+
+  app_launch_data->token = g_strdup (token);
+}
+
+static void
+token_provider_failed (gpointer                                  data,
+                       struct zxdg_activation_token_provider_v1 *provider)
+{
+  AppLaunchData *app_launch_data = data;
+
+  app_launch_data->failed = TRUE;
+}
+
+static const struct zxdg_activation_token_provider_v1_listener token_provider_listener = {
+  token_provider_done,
+  token_provider_failed,
+};
+
 static char *
 gdk_wayland_app_launch_context_get_startup_notify_id (GAppLaunchContext *context,
                                                       GAppInfo          *info,
@@ -40,7 +69,41 @@ gdk_wayland_app_launch_context_get_startup_notify_id (GAppLaunchContext *context
 
   g_object_get (context, "display", &display, NULL);
 
-  if (display->gtk_shell_version >= 3)
+  if (display->xdg_activation)
+    {
+      struct zxdg_activation_token_provider_v1 *token_provider;
+      GdkSeat *seat;
+      GdkWindow *focus_window;
+      AppLaunchData app_launch_data = { 0 };
+
+      seat = gdk_display_get_default_seat (GDK_DISPLAY (display));
+      focus_window = gdk_wayland_device_get_focus (gdk_seat_get_keyboard (seat));
+      token_provider =
+        zxdg_activation_v1_get_activation_token (display->xdg_activation,
+                                                 gdk_wayland_window_get_wl_surface (focus_window),
+                                                 _gdk_wayland_seat_get_last_implicit_grab_serial (seat, 
NULL),
+                                                 gdk_wayland_seat_get_wl_seat (seat));
+
+      zxdg_activation_token_provider_v1_add_listener (token_provider,
+                                                      &token_provider_listener,
+                                                      &app_launch_data);
+
+      while (app_launch_data.token == NULL && !app_launch_data.failed)
+        wl_display_roundtrip (display->wl_display);
+
+      if (!app_launch_data.failed)
+        {
+          zxdg_activation_v1_associate (display->xdg_activation,
+                                        app_launch_data.token,
+                                        g_app_info_get_id (info));
+        }
+      else
+        g_warning ("App activation failed");
+
+      zxdg_activation_token_provider_v1_destroy (token_provider);
+      id = app_launch_data.token;
+    }
+  else if (display->gtk_shell_version >= 3)
     {
       id = g_uuid_string_random ();
       gtk_shell1_notify_launch (display->gtk_shell, id);
diff --git a/gdk/wayland/gdkdevice-wayland.c b/gdk/wayland/gdkdevice-wayland.c
index c5b273eb90..5f0c952e36 100644
--- a/gdk/wayland/gdkdevice-wayland.c
+++ b/gdk/wayland/gdkdevice-wayland.c
@@ -732,7 +732,7 @@ device_emit_grab_crossing (GdkDevice       *device,
     }
 }
 
-static GdkWindow *
+GdkWindow *
 gdk_wayland_device_get_focus (GdkDevice *device)
 {
   GdkWaylandSeat *wayland_seat = GDK_WAYLAND_SEAT (gdk_device_get_seat (device));
diff --git a/gdk/wayland/gdkdisplay-wayland.c b/gdk/wayland/gdkdisplay-wayland.c
index dfb8d3069a..a1504f9900 100644
--- a/gdk/wayland/gdkdisplay-wayland.c
+++ b/gdk/wayland/gdkdisplay-wayland.c
@@ -85,6 +85,7 @@
 #define MIN_SYSTEM_BELL_DELAY_MS 20
 
 #define GTK_SHELL1_VERSION       3
+#define XDG_ACTIVATION_VERSION   1
 
 static void _gdk_wayland_display_load_cursor_theme (GdkWaylandDisplay *display_wayland);
 
@@ -530,6 +531,15 @@ gdk_registry_handle_global (void               *data,
       _gdk_wayland_screen_init_xdg_output (display_wayland->screen);
       _gdk_wayland_display_async_roundtrip (display_wayland);
     }
+  else if (strcmp (interface, "zxdg_activation_v1") == 0)
+    {
+      display_wayland->xdg_activation_version =
+        MIN (version, XDG_ACTIVATION_VERSION);
+      display_wayland->xdg_activation =
+        wl_registry_bind (display_wayland->wl_registry, id,
+                          &zxdg_activation_v1_interface,
+                          display_wayland->xdg_activation_version);
+    }
 
   g_hash_table_insert (display_wayland->known_globals,
                        GUINT_TO_POINTER (id), g_strdup (interface));
@@ -951,7 +961,9 @@ gdk_wayland_display_notify_startup_complete (GdkDisplay  *display,
         return;
     }
 
-  if (display_wayland->gtk_shell)
+  if (display_wayland->xdg_activation)
+    zxdg_activation_v1_set_activation_token (display_wayland->xdg_activation, startup_id);
+  else if (display_wayland->gtk_shell)
     gtk_shell1_set_startup_id (display_wayland->gtk_shell, startup_id);
 }
 
diff --git a/gdk/wayland/gdkdisplay-wayland.h b/gdk/wayland/gdkdisplay-wayland.h
index 62696300d1..5ee4ef94e5 100644
--- a/gdk/wayland/gdkdisplay-wayland.h
+++ b/gdk/wayland/gdkdisplay-wayland.h
@@ -36,6 +36,7 @@
 #include <gdk/wayland/server-decoration-client-protocol.h>
 #include <gdk/wayland/xdg-output-unstable-v1-client-protocol.h>
 #include <gdk/wayland/primary-selection-unstable-v1-client-protocol.h>
+#include <gdk/wayland/xdg-activation-unstable-v1-client-protocol.h>
 
 #include <glib.h>
 #include <gdk/gdkkeys.h>
@@ -97,6 +98,7 @@ struct _GdkWaylandDisplay
   struct zwp_keyboard_shortcuts_inhibit_manager_v1 *keyboard_shortcuts_inhibit;
   struct org_kde_kwin_server_decoration_manager *server_decoration_manager;
   struct zxdg_output_manager_v1 *xdg_output_manager;
+  struct zxdg_activation_v1 *xdg_activation;
   uint32_t xdg_output_version;
 
   GList *async_roundtrips;
@@ -125,6 +127,7 @@ struct _GdkWaylandDisplay
   int data_device_manager_version;
   int gtk_shell_version;
   int xdg_output_manager_version;
+  int xdg_activation_version;
 
   uint32_t server_decoration_mode;
 
diff --git a/gdk/wayland/gdkprivate-wayland.h b/gdk/wayland/gdkprivate-wayland.h
index 4a921b3b99..5173873381 100644
--- a/gdk/wayland/gdkprivate-wayland.h
+++ b/gdk/wayland/gdkprivate-wayland.h
@@ -187,6 +187,7 @@ uint32_t _gdk_wayland_device_get_implicit_grab_serial(GdkWaylandDevice *device,
                                                       const GdkEvent   *event);
 uint32_t _gdk_wayland_seat_get_last_implicit_grab_serial (GdkSeat           *seat,
                                                           GdkEventSequence **seqence);
+GdkWindow * gdk_wayland_device_get_focus (GdkDevice *device);
 struct wl_data_device * gdk_wayland_device_get_data_device (GdkDevice *gdk_device);
 void gdk_wayland_seat_set_selection (GdkSeat               *seat,
                                      struct wl_data_source *source);
diff --git a/gdk/wayland/gdkwindow-wayland.c b/gdk/wayland/gdkwindow-wayland.c
index 811b37ce5c..6006fc44a3 100644
--- a/gdk/wayland/gdkwindow-wayland.c
+++ b/gdk/wayland/gdkwindow-wayland.c
@@ -3737,7 +3737,14 @@ gdk_wayland_window_focus (GdkWindow *window,
       GdkWaylandDisplay *display_wayland =
         GDK_WAYLAND_DISPLAY (gdk_window_get_display (window));
 
-      if (display_wayland->gtk_shell_version >= 3)
+      if (display_wayland->xdg_activation)
+        {
+          zxdg_activation_v1_set_activation_token (display_wayland->xdg_activation,
+                                                   display_wayland->startup_notification_id);
+          zxdg_activation_v1_activate (display_wayland->xdg_activation,
+                                       impl->display_server.wl_surface);
+        }
+      else if (display_wayland->gtk_shell_version >= 3)
         {
           gtk_surface1_request_focus (impl->display_server.gtk_surface,
                                       display_wayland->startup_notification_id);
diff --git a/gdk/wayland/meson.build b/gdk/wayland/meson.build
index e66afd7f95..f1e1cdbfb4 100644
--- a/gdk/wayland/meson.build
+++ b/gdk/wayland/meson.build
@@ -57,6 +57,7 @@ proto_sources = [
   ['server-decoration', 'private' ],
   ['xdg-output', 'unstable', 'v1', ],
   ['primary-selection', 'unstable', 'v1', ],
+  ['xdg-activation', 'unstable', 'v1', ],
 ]
 
 gdk_wayland_gen_headers = []


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