Merge branch 'scene-confusion' into 'master'

scene: only send leave events to outputs with matching scene root

See merge request wlroots/wlroots!5315
This commit is contained in:
Ronan Pigott 2026-04-12 03:14:35 -07:00
commit fb4f6d1f12
2 changed files with 22 additions and 9 deletions

View file

@ -127,6 +127,8 @@ struct wlr_surface_output {
struct { struct {
struct wl_listener bind; struct wl_listener bind;
struct wl_listener destroy; struct wl_listener destroy;
bool suspended;
} WLR_PRIVATE; } WLR_PRIVATE;
}; };

View file

@ -30,8 +30,8 @@ static struct wlr_output *get_surface_frame_pacing_output(struct wlr_surface *su
struct wlr_output *frame_pacing_output = NULL; struct wlr_output *frame_pacing_output = NULL;
struct wlr_surface_output *surface_output; struct wlr_surface_output *surface_output;
wl_list_for_each(surface_output, &surface->current_outputs, link) { wl_list_for_each(surface_output, &surface->current_outputs, link) {
if (frame_pacing_output == NULL || if (!surface_output->suspended && (frame_pacing_output == NULL ||
surface_output->output->refresh > frame_pacing_output->refresh) { surface_output->output->refresh > frame_pacing_output->refresh)) {
frame_pacing_output = surface_output->output; frame_pacing_output = surface_output->output;
} }
} }
@ -97,11 +97,9 @@ static void handle_scene_buffer_outputs_update(
struct wlr_scene_outputs_update_event *event = data; struct wlr_scene_outputs_update_event *event = data;
struct wlr_scene *scene = scene_node_get_root(&surface->buffer->node); struct wlr_scene *scene = scene_node_get_root(&surface->buffer->node);
// If the surface is no longer visible on any output, keep the last sent // If the surface is no longer visible on any output in the scene, keep the
// preferred configuration to avoid unnecessary redraws // last sent preferred configuration to avoid unnecessary redraws
if (event->size == 0) { bool suspend = event->size == 0;
return;
}
// To avoid sending redundant leave/enter events when a surface is hidden and then shown // To avoid sending redundant leave/enter events when a surface is hidden and then shown
// without moving to a different output the following policy is implemented: // without moving to a different output the following policy is implemented:
@ -121,11 +119,24 @@ static void handle_scene_buffer_outputs_update(
break; break;
} }
} }
if (!active) {
wlr_surface_send_leave(surface->surface, entered_output->output); struct wlr_scene_output *scene_output;
wl_list_for_each(scene_output, &scene->outputs, link) {
if (scene_output->output == entered_output->output) {
entered_output->suspended = suspend;
if (!suspend && !active) {
wlr_surface_send_leave(surface->surface, entered_output->output);
}
break;
}
} }
} }
// No reason to update the preferred configuration if we aren't sending leave/enter events.
if (suspend) {
return;
}
for (size_t i = 0; i < event->size; i++) { for (size_t i = 0; i < event->size; i++) {
// This function internally checks if an enter event was already sent for the output // This function internally checks if an enter event was already sent for the output
// to avoid sending redundant events. // to avoid sending redundant events.