wayland: Handle xdg_activation_v1_activate on non XDG activation tokens

The XDG activation support was missing interoperability with other
startup sequences, notably those coming from other means than XDG
activation.

In order to play nice with X11 startup sequence IDs, we not just
have to check for the startup ID being in the general pool, but
we also need to fallback into X11-style timestamp comparison so the
window ends up properly focused.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2314>
This commit is contained in:
Carlos Garnacho 2022-02-28 14:01:34 +01:00
parent fe41e69eea
commit 32332fd53d

View File

@ -283,6 +283,18 @@ token_can_activate (MetaXdgActivationToken *token)
FALSE, NULL, NULL); FALSE, NULL, NULL);
} }
static gboolean
startup_sequence_is_recent (MetaDisplay *display,
MetaStartupSequence *sequence)
{
uint32_t seq_timestamp_ms, last_user_time_ms;
seq_timestamp_ms = meta_startup_sequence_get_timestamp (sequence);
last_user_time_ms = meta_display_get_last_user_time (display);
return seq_timestamp_ms >= last_user_time_ms;
}
static void static void
activation_activate (struct wl_client *client, activation_activate (struct wl_client *client,
struct wl_resource *resource, struct wl_resource *resource,
@ -291,7 +303,9 @@ activation_activate (struct wl_client *client,
{ {
MetaWaylandActivation *activation = wl_resource_get_user_data (resource); MetaWaylandActivation *activation = wl_resource_get_user_data (resource);
MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource); MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource);
MetaDisplay *display = meta_get_display ();
MetaXdgActivationToken *token; MetaXdgActivationToken *token;
MetaStartupSequence *sequence;
MetaWindow *window; MetaWindow *window;
window = meta_wayland_surface_get_window (surface); window = meta_wayland_surface_get_window (surface);
@ -299,16 +313,27 @@ activation_activate (struct wl_client *client,
return; return;
token = g_hash_table_lookup (activation->tokens, token_str); token = g_hash_table_lookup (activation->tokens, token_str);
if (!token) if (token)
{
sequence = token->sequence;
}
else
{
sequence = meta_startup_notification_lookup_sequence (display->startup_notification,
token_str);
}
if (!sequence)
return; return;
if (token_can_activate (token)) if ((token && token_can_activate (token)) ||
(!token && startup_sequence_is_recent (display, sequence)))
{ {
uint32_t timestamp; uint32_t timestamp;
int32_t workspace_idx; int32_t workspace_idx;
workspace_idx = meta_startup_sequence_get_workspace (token->sequence); workspace_idx = meta_startup_sequence_get_workspace (sequence);
timestamp = meta_startup_sequence_get_timestamp (token->sequence); timestamp = meta_startup_sequence_get_timestamp (sequence);
if (workspace_idx >= 0) if (workspace_idx >= 0)
meta_window_change_workspace_by_index (window, workspace_idx, TRUE); meta_window_change_workspace_by_index (window, workspace_idx, TRUE);
@ -321,7 +346,7 @@ activation_activate (struct wl_client *client,
meta_window_set_demands_attention (window); meta_window_set_demands_attention (window);
} }
meta_startup_sequence_complete (token->sequence); meta_startup_sequence_complete (sequence);
} }
static const struct xdg_activation_v1_interface activation_interface = { static const struct xdg_activation_v1_interface activation_interface = {