136 lines
5.5 KiB
Diff
136 lines
5.5 KiB
Diff
From: Carlos Garnacho <carlosg@gnome.org>
|
|
Date: Mon, 28 Feb 2022 18:31:40 +0100
|
|
Subject: 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.
|
|
|
|
Backport-of: 4dcacff3120d5c1cef888061dbc42f5fbe093a58
|
|
Signed-off-by: Joan Bruguera <joanbrugueram@gmail.com>
|
|
Origin: upstream, 3.24.35, commit:45f0b5d052eced18f978707b8aed7a8cbe367557
|
|
---
|
|
gdk/wayland/gdkwindow-wayland.c | 81 ++++++++++++++++++++++++++++++-----------
|
|
1 file changed, 60 insertions(+), 21 deletions(-)
|
|
|
|
diff --git a/gdk/wayland/gdkwindow-wayland.c b/gdk/wayland/gdkwindow-wayland.c
|
|
index 53790e0..e3f97cf 100644
|
|
--- a/gdk/wayland/gdkwindow-wayland.c
|
|
+++ b/gdk/wayland/gdkwindow-wayland.c
|
|
@@ -3811,40 +3811,79 @@ gdk_wayland_window_get_input_shape (GdkWindow *window)
|
|
return NULL;
|
|
}
|
|
|
|
+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_window_focus (GdkWindow *window,
|
|
guint32 timestamp)
|
|
{
|
|
GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
|
|
+ GdkDisplay *display = gdk_window_get_display (window);
|
|
+ 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_window_get_display (window));
|
|
+ GdkSeat *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 (seat));
|
|
+ xdg_activation_token_v1_set_surface (token,
|
|
+ gdk_wayland_window_get_wl_surface (window));
|
|
+ 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
|