[mutter/wip/carlosg/gtk-shell-request-focus: 16/16] wayland: Implement window activation and focus stealing prevention



commit 177b4df2170037a494db137505875da92e58bb9d
Author: Carlos Garnacho <carlosg gnome org>
Date:   Wed Jan 23 16:51:16 2019 +0100

    wayland: Implement window activation and focus stealing prevention
    
    This is done through gtk-shell ATM. If a window requests focus with
    an invalid startup ID, just the demands-attention flag will be set.
    The "did user interaction happen in between" checks are left to
    meta_window_activate_full/meta_window_focus, by passing the timestamp
    of the original launch request.

 src/wayland/meta-wayland-gtk-shell.c | 75 +++++++++++++++++++++++++++++++++---
 src/wayland/meta-wayland-versions.h  |  2 +-
 2 files changed, 71 insertions(+), 6 deletions(-)
---
diff --git a/src/wayland/meta-wayland-gtk-shell.c b/src/wayland/meta-wayland-gtk-shell.c
index 0853dd1f6..c629e3a4d 100644
--- a/src/wayland/meta-wayland-gtk-shell.c
+++ b/src/wayland/meta-wayland-gtk-shell.c
@@ -151,11 +151,50 @@ gtk_surface_present (struct wl_client   *client,
                              META_CLIENT_TYPE_APPLICATION, NULL);
 }
 
+static void
+gtk_surface_request_focus (struct wl_client   *client,
+                           struct wl_resource *resource,
+                           const char         *startup_id)
+{
+  MetaWaylandGtkSurface *gtk_surface = wl_resource_get_user_data (resource);
+  MetaWaylandSurface *surface = gtk_surface->surface;
+  MetaDisplay *display = meta_get_display ();
+  MetaStartupSequence *sequence = NULL;
+  MetaWindow *window;
+
+  window = surface->window;
+  if (!window)
+    return;
+
+  if (startup_id)
+    sequence = meta_startup_notification_lookup_sequence (display->startup_notification,
+                                                          startup_id);
+
+  if (sequence)
+    {
+      uint32_t timestamp;
+
+      timestamp = meta_startup_sequence_get_timestamp (sequence);
+
+      meta_startup_sequence_complete (sequence);
+      meta_startup_notification_remove_sequence (display->startup_notification,
+                                                 sequence);
+
+      meta_window_activate_full (window, timestamp,
+                                 META_CLIENT_TYPE_APPLICATION, NULL);
+    }
+  else
+    {
+      meta_window_set_demands_attention (window);
+    }
+}
+
 static const struct gtk_surface1_interface meta_wayland_gtk_surface_interface = {
   gtk_surface_set_dbus_properties,
   gtk_surface_set_modal,
   gtk_surface_unset_modal,
   gtk_surface_present,
+  gtk_surface_request_focus,
 };
 
 static void
@@ -329,11 +368,7 @@ gtk_shell_set_startup_id (struct wl_client   *client,
   sequence = meta_startup_notification_lookup_sequence (display->startup_notification,
                                                         startup_id);
   if (sequence)
-    {
-      meta_startup_sequence_complete (sequence);
-      meta_startup_notification_remove_sequence (display->startup_notification,
-                                                 sequence);
-    }
+    meta_startup_sequence_complete (sequence);
 }
 
 static void
@@ -360,10 +395,40 @@ gtk_shell_system_bell (struct wl_client   *client,
     }
 }
 
+static void
+gtk_shell_notify_launch (struct wl_client   *client,
+                         struct wl_resource *resource,
+                         const char         *startup_id)
+{
+  MetaDisplay *display = meta_get_display ();
+  MetaStartupSequence *sequence;
+  uint32_t timestamp;
+
+  sequence = meta_startup_notification_lookup_sequence (display->startup_notification,
+                                                        startup_id);
+  if (sequence)
+    {
+      g_warning ("Naughty client notified launch with duplicate startup_id '%s'",
+                 startup_id);
+      return;
+    }
+
+  timestamp = meta_display_get_current_time_roundtrip (display);
+  sequence = g_object_new (META_TYPE_STARTUP_SEQUENCE,
+                           "id", startup_id,
+                           "timestamp", timestamp,
+                           NULL);
+
+  meta_startup_notification_add_sequence (display->startup_notification,
+                                          sequence);
+  g_object_unref (sequence);
+}
+
 static const struct gtk_shell1_interface meta_wayland_gtk_shell_interface = {
   gtk_shell_get_gtk_surface,
   gtk_shell_set_startup_id,
   gtk_shell_system_bell,
+  gtk_shell_notify_launch,
 };
 
 static void
diff --git a/src/wayland/meta-wayland-versions.h b/src/wayland/meta-wayland-versions.h
index 9e1139a91..19a558016 100644
--- a/src/wayland/meta-wayland-versions.h
+++ b/src/wayland/meta-wayland-versions.h
@@ -43,7 +43,7 @@
 #define META_WL_SEAT_VERSION                5
 #define META_WL_OUTPUT_VERSION              2
 #define META_XSERVER_VERSION                1
-#define META_GTK_SHELL1_VERSION             2
+#define META_GTK_SHELL1_VERSION             3
 #define META_WL_SUBCOMPOSITOR_VERSION       1
 #define META_ZWP_POINTER_GESTURES_V1_VERSION    1
 #define META_ZXDG_EXPORTER_V1_VERSION       1


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