summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarlos Garnacho <carlosg@gnome.org>2022-02-28 18:31:40 +0100
committerCarlos Garnacho <carlosg@gnome.org>2022-03-16 19:50:21 +0100
commit9822d2b6b2ace41cb4c92e41545ea7dc66fd386c (patch)
tree22ff89a97c366aafbbf4787c5c867cf3ae858d42
parenta36594e754f8982a00160a18aec65ffbc11297f9 (diff)
downloadgtk+-9822d2b6b2ace41cb4c92e41545ea7dc66fd386c.tar.gz
wayland: Use xdg-activation for non-startup initiated focus requests
Currently, we have all the plumbing in place so that GTK consumes the startup notification ID when focusing a window through the xdg-activation protocol. This however misses the case that a window might be requested to be focused with no startup ID (i.e. via interaction with the application, not through GApplication or other application launching logic). In this case, we let the application create a token that will be consumed by itself. The serial used is that from the last interaction, so the compositor will still be able to do focus prevention logic if it applies. Since we already do have a last serial at hand, prefer xdg-activation all the way over the now stale gtk-shell focusing support. The timestamp argument becomes unused, but that is a weak argument to prefer the private protocol over the standard one. The gtk-shell protocol support is so far left for interaction with older Mutter.
-rw-r--r--gdk/wayland/gdksurface-wayland.c82
1 files changed, 61 insertions, 21 deletions
diff --git a/gdk/wayland/gdksurface-wayland.c b/gdk/wayland/gdksurface-wayland.c
index 25be2f0b7c..09328bdb89 100644
--- a/gdk/wayland/gdksurface-wayland.c
+++ b/gdk/wayland/gdksurface-wayland.c
@@ -3454,39 +3454,79 @@ gdk_wayland_surface_destroy (GdkSurface *surface,
}
static void
+token_done (gpointer data,
+ struct xdg_activation_token_v1 *provider,
+ const char *token)
+{
+ char **token_out = data;
+
+ *token_out = g_strdup (token);
+}
+
+static const struct xdg_activation_token_v1_listener token_listener = {
+ token_done,
+};
+
+static void
gdk_wayland_surface_focus (GdkSurface *surface,
guint32 timestamp)
{
GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
+ GdkDisplay *display = gdk_surface_get_display (surface);
+ GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (display);
+ gchar *startup_id = NULL;
- if (!impl->display_server.gtk_surface)
- return;
+ startup_id = g_steal_pointer (&display_wayland->startup_notification_id);
- if (timestamp == GDK_CURRENT_TIME)
+ if (display_wayland->xdg_activation)
{
- GdkWaylandDisplay *display_wayland =
- GDK_WAYLAND_DISPLAY (gdk_surface_get_display (surface));
+ GdkWaylandSeat *seat =
+ GDK_WAYLAND_SEAT (gdk_display_get_default_seat (display));
- if (display_wayland->startup_notification_id)
+ /* If the focus request does not have a startup ID associated, get a
+ * new token to activate the window.
+ */
+ if (!startup_id)
{
- if (display_wayland->xdg_activation)
- {
- xdg_activation_v1_activate (display_wayland->xdg_activation,
- display_wayland->startup_notification_id,
- impl->display_server.wl_surface);
- gdk_wayland_display_set_startup_notification_id (GDK_DISPLAY (display_wayland), NULL);
- }
- else if (display_wayland->gtk_shell_version >= 3)
- {
- gtk_surface1_request_focus (impl->display_server.gtk_surface,
- display_wayland->startup_notification_id);
- }
+ struct xdg_activation_token_v1 *token;
+ struct wl_event_queue *event_queue;
+
+ event_queue = wl_display_create_queue (display_wayland->wl_display);
+
+ token = xdg_activation_v1_get_activation_token (display_wayland->xdg_activation);
+ wl_proxy_set_queue ((struct wl_proxy *) token, event_queue);
+
+ xdg_activation_token_v1_add_listener (token,
+ &token_listener,
+ &startup_id);
+ xdg_activation_token_v1_set_serial (token,
+ _gdk_wayland_seat_get_last_implicit_grab_serial (seat, NULL),
+ gdk_wayland_seat_get_wl_seat (GDK_SEAT (seat)));
+ xdg_activation_token_v1_set_surface (token,
+ gdk_wayland_surface_get_wl_surface (surface));
+ xdg_activation_token_v1_commit (token);
+
+ while (startup_id == NULL)
+ wl_display_dispatch_queue (display_wayland->wl_display, event_queue);
- g_clear_pointer (&display_wayland->startup_notification_id, g_free);
+ xdg_activation_token_v1_destroy (token);
+ wl_event_queue_destroy (event_queue);
}
+
+ xdg_activation_v1_activate (display_wayland->xdg_activation,
+ startup_id,
+ impl->display_server.wl_surface);
}
- else
- gtk_surface1_present (impl->display_server.gtk_surface, timestamp);
+ else if (impl->display_server.gtk_surface)
+ {
+ if (timestamp != GDK_CURRENT_TIME)
+ gtk_surface1_present (impl->display_server.gtk_surface, timestamp);
+ else if (startup_id && display_wayland->gtk_shell_version >= 3)
+ gtk_surface1_request_focus (impl->display_server.gtk_surface,
+ startup_id);
+ }
+
+ g_free (startup_id);
}
static void