mirror of
https://github.com/brl/mutter.git
synced 2024-11-28 11:00:54 -05:00
wayland/surface: Send enter event when a client binds to wl_output late
When hotplugging a new monitor, we recreate all the MetaWaylandOutputs and need to emit leave events to the surfaces for the old wl_outputs and enter events for the newly created ones. There's a race condition though: We might update the monitors a surface is on (and thus emit enter/leave events for the wl_outputs) before the Wayland client is registered with the new wl_output (ie. the bind_output() callback of MetaWaylandOutput was called), which means we don't send an enter event to the client in surface_entered_output(). Since MetaWaylandSurface now has the MetaWaylandOutput in its outputs hashtable, it thinks the client has been notified and won't send any more enter events. To fix that, make MetaWaylandOutput emit a new signal "output-bound" when a client bound to the output and make all surfaces which are on that output listen to the signal. In the signal handler compare the newly added client to the client the surface belongs to, and if it's the same one, send an enter event to that client. https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1230
This commit is contained in:
parent
38db4a5a65
commit
696b534570
@ -41,6 +41,7 @@
|
||||
enum
|
||||
{
|
||||
OUTPUT_DESTROYED,
|
||||
OUTPUT_BOUND,
|
||||
|
||||
LAST_SIGNAL
|
||||
};
|
||||
@ -339,6 +340,7 @@ bind_output (struct wl_client *client,
|
||||
|
||||
send_output_events (resource, wayland_output, logical_monitor, TRUE, NULL);
|
||||
|
||||
g_signal_emit (wayland_output, signals[OUTPUT_BOUND], 0, resource);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -558,6 +560,14 @@ meta_wayland_output_class_init (MetaWaylandOutputClass *klass)
|
||||
0,
|
||||
NULL, NULL, NULL,
|
||||
G_TYPE_NONE, 0);
|
||||
|
||||
signals[OUTPUT_BOUND] = g_signal_new ("output-bound",
|
||||
G_TYPE_FROM_CLASS (object_class),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
0,
|
||||
NULL, NULL, NULL,
|
||||
G_TYPE_NONE, 1,
|
||||
G_TYPE_POINTER);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1162,6 +1162,16 @@ static const struct wl_surface_interface meta_wayland_wl_surface_interface = {
|
||||
wl_surface_damage_buffer,
|
||||
};
|
||||
|
||||
static void
|
||||
handle_output_bound (MetaWaylandOutput *wayland_output,
|
||||
struct wl_resource *output_resource,
|
||||
MetaWaylandSurface *surface)
|
||||
{
|
||||
if (wl_resource_get_client (output_resource) ==
|
||||
wl_resource_get_client (surface->resource))
|
||||
wl_surface_send_enter (surface->resource, output_resource);
|
||||
}
|
||||
|
||||
static void
|
||||
surface_entered_output (MetaWaylandSurface *surface,
|
||||
MetaWaylandOutput *wayland_output)
|
||||
@ -1179,6 +1189,10 @@ surface_entered_output (MetaWaylandSurface *surface,
|
||||
|
||||
wl_surface_send_enter (surface->resource, resource);
|
||||
}
|
||||
|
||||
g_signal_connect (wayland_output, "output-bound",
|
||||
G_CALLBACK (handle_output_bound),
|
||||
surface);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1188,6 +1202,10 @@ surface_left_output (MetaWaylandSurface *surface,
|
||||
GList *iter;
|
||||
struct wl_resource *resource;
|
||||
|
||||
g_signal_handlers_disconnect_by_func (wayland_output,
|
||||
G_CALLBACK (handle_output_bound),
|
||||
surface);
|
||||
|
||||
for (iter = wayland_output->resources; iter != NULL; iter = iter->next)
|
||||
{
|
||||
resource = iter->data;
|
||||
@ -1265,9 +1283,18 @@ update_surface_output_state (gpointer key, gpointer value, gpointer user_data)
|
||||
}
|
||||
|
||||
static void
|
||||
surface_output_disconnect_signal (gpointer key, gpointer value, gpointer user_data)
|
||||
surface_output_disconnect_signals (gpointer key,
|
||||
gpointer value,
|
||||
gpointer user_data)
|
||||
{
|
||||
g_signal_handler_disconnect (key, (gulong) GPOINTER_TO_SIZE (value));
|
||||
MetaWaylandOutput *wayland_output = key;
|
||||
MetaWaylandSurface *surface = user_data;
|
||||
|
||||
g_signal_handler_disconnect (wayland_output,
|
||||
(gulong) GPOINTER_TO_SIZE (value));
|
||||
g_signal_handlers_disconnect_by_func (wayland_output,
|
||||
G_CALLBACK (handle_output_bound),
|
||||
surface);
|
||||
}
|
||||
|
||||
void
|
||||
@ -1338,7 +1365,7 @@ wl_surface_destructor (struct wl_resource *resource)
|
||||
meta_wayland_compositor_destroy_frame_callbacks (compositor, surface);
|
||||
|
||||
g_hash_table_foreach (surface->outputs_to_destroy_notify_id,
|
||||
surface_output_disconnect_signal,
|
||||
surface_output_disconnect_signals,
|
||||
surface);
|
||||
g_hash_table_unref (surface->outputs_to_destroy_notify_id);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user