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 wl_listener bind;
struct wl_listener destroy;
bool suspended;
} 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_surface_output *surface_output;
wl_list_for_each(surface_output, &surface->current_outputs, link) {
if (frame_pacing_output == NULL ||
surface_output->output->refresh > frame_pacing_output->refresh) {
if (!surface_output->suspended && (frame_pacing_output == NULL ||
surface_output->output->refresh > frame_pacing_output->refresh)) {
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 *scene = scene_node_get_root(&surface->buffer->node);
// If the surface is no longer visible on any output, keep the last sent
// preferred configuration to avoid unnecessary redraws
if (event->size == 0) {
return;
}
// If the surface is no longer visible on any output in the scene, keep the
// last sent preferred configuration to avoid unnecessary redraws
bool suspend = event->size == 0;
// 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:
@ -121,11 +119,24 @@ static void handle_scene_buffer_outputs_update(
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++) {
// This function internally checks if an enter event was already sent for the output
// to avoid sending redundant events.