diff --git a/include/wlr/types/wlr_compositor.h b/include/wlr/types/wlr_compositor.h index 9331e8af6..aff42aea6 100644 --- a/include/wlr/types/wlr_compositor.h +++ b/include/wlr/types/wlr_compositor.h @@ -127,6 +127,8 @@ struct wlr_surface_output { struct { struct wl_listener bind; struct wl_listener destroy; + + bool suspended; } WLR_PRIVATE; }; diff --git a/types/scene/surface.c b/types/scene/surface.c index e6ea1333a..64928ca72 100644 --- a/types/scene/surface.c +++ b/types/scene/surface.c @@ -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.