1
0
Fork 0

wayland/activation: Apply xdg-activation request when window gets mapped

If the window is not mapped yet and we get an activation request, we
will wait for the window to get mapped or destroyed to try to fullfil
the request.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3728>
This commit is contained in:
Sebastian Wick 2024-05-06 15:44:06 +02:00
parent 77b115399c
commit c166b3fc5b

View file

@ -37,6 +37,7 @@ struct _MetaWaylandActivation
struct wl_list resource_list;
struct wl_list token_list;
GHashTable *tokens;
GHashTable *pending_activations;
};
struct _MetaXdgActivationToken
@ -322,22 +323,20 @@ startup_sequence_is_recent (MetaDisplay *display,
return seq_timestamp_ms >= last_user_time_ms;
}
static void
activation_activate (struct wl_client *client,
struct wl_resource *resource,
const char *token_str,
struct wl_resource *surface_resource)
static gboolean
maybe_activate (MetaWaylandActivation *activation,
MetaWindow *window,
const char *token_str)
{
MetaWaylandActivation *activation = wl_resource_get_user_data (resource);
MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource);
MetaDisplay *display = display_from_activation (activation);
MetaXdgActivationToken *token;
MetaStartupSequence *sequence;
MetaWindow *window;
window = meta_wayland_surface_get_window (surface);
if (!window)
return;
if (!window || window->unmanaging)
return TRUE;
if (!window->mapped)
return FALSE;
token = g_hash_table_lookup (activation->tokens, token_str);
if (token)
@ -351,7 +350,7 @@ activation_activate (struct wl_client *client,
}
if (!sequence)
return;
return TRUE;
if ((token && token_can_activate (token)) ||
(!token && startup_sequence_is_recent (display, sequence)))
@ -374,6 +373,50 @@ activation_activate (struct wl_client *client,
}
meta_startup_sequence_complete (sequence);
return TRUE;
}
static void
complete_pending_activate (MetaWaylandActivation *activation,
MetaWindow *window)
{
g_autofree char *token_str = NULL;
g_signal_handlers_disconnect_by_func (window, complete_pending_activate,
activation);
g_hash_table_steal_extended (activation->pending_activations, window,
NULL, (gpointer *) &token_str);
maybe_activate (activation, window, token_str);
}
static void
activation_activate (struct wl_client *client,
struct wl_resource *resource,
const char *token_str,
struct wl_resource *surface_resource)
{
MetaWaylandActivation *activation = wl_resource_get_user_data (resource);
MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource);
MetaWindow *window = meta_wayland_surface_get_window (surface);
if (maybe_activate (activation, window, token_str))
return;
g_assert (window != NULL);
g_signal_handlers_disconnect_by_func (window,
complete_pending_activate,
activation);
g_signal_connect_swapped (window, "notify::mapped",
G_CALLBACK (complete_pending_activate),
activation);
g_signal_connect_swapped (window, "unmanaged",
G_CALLBACK (complete_pending_activate),
activation);
g_hash_table_insert (activation->pending_activations,
window, g_strdup (token_str));
}
static const struct xdg_activation_v1_interface activation_interface = {
@ -406,6 +449,7 @@ void
meta_wayland_activation_finalize (MetaWaylandCompositor *compositor)
{
g_hash_table_destroy (compositor->activation->tokens);
g_hash_table_destroy (compositor->activation->pending_activations);
g_clear_pointer (&compositor->activation, g_free);
}
@ -424,6 +468,9 @@ meta_wayland_activation_init (MetaWaylandCompositor *compositor)
NULL,
(GDestroyNotify) meta_xdg_activation_token_free);
activation->pending_activations =
g_hash_table_new_full (NULL, NULL, NULL, g_free);
wl_global_create (compositor->wayland_display,
&xdg_activation_v1_interface,
META_XDG_ACTIVATION_V1_VERSION,