diff --git a/include/common/scaled-scene-buffer.h b/include/common/scaled-scene-buffer.h index 66d0df47..989600d9 100644 --- a/include/common/scaled-scene-buffer.h +++ b/include/common/scaled-scene-buffer.h @@ -34,8 +34,7 @@ struct scaled_scene_buffer { /* cached wlr_buffers for each scale */ struct wl_list cache; /* struct scaled_buffer_cache_entry.link */ struct wl_listener destroy; - struct wl_listener output_enter; - struct wl_listener output_leave; + struct wl_listener outputs_update; const struct scaled_scene_buffer_impl *impl; /* * Pointer to the per-implementation list of scaled-scene-buffers. diff --git a/src/common/scaled-scene-buffer.c b/src/common/scaled-scene-buffer.c index 19575f4b..7ab0b8ce 100644 --- a/src/common/scaled-scene-buffer.c +++ b/src/common/scaled-scene-buffer.c @@ -8,33 +8,11 @@ #include #include #include "buffer.h" +#include "common/macros.h" #include "common/mem.h" #include "common/scaled-scene-buffer.h" #include "node.h" -/** - * TODO - * - * This implementation does not react to output scale changes itself but only - * to movement of scene nodes to different outputs. To also handle output scale - * changes we'd need to keep a list of struct wlr_outputs * in sync and listen - * to their commit signals. - * - * The detection of the max output scale is also not 100% robust for all use - * cases as on output_enter we only compare the new output scale with the - * primary_output scale. In specific conditions the primary output may be the - * same as the new output even though a smaller part of the buffer node is - * still visible on an output with a bigger scale. This could be solved the - * same way as the previous point in keeping a list of outputs in sync. - * - * Most of this would be easier when wlroots would instead provide a - * max_scale_changed event because it already touches all the relevant parts - * when calculating the primary_output and inform wlr_scene_buffers about - * output changes. - * - * See wlroots/types/scene/wlr_scene.c scene_buffer_update_outputs() - */ - /* Internal API */ static void _cache_entry_destroy(struct scaled_scene_buffer_cache_entry *cache_entry, bool drop_buffer) @@ -162,8 +140,7 @@ _handle_node_destroy(struct wl_listener *listener, void *data) struct scaled_scene_buffer *self = wl_container_of(listener, self, destroy); wl_list_remove(&self->destroy.link); - wl_list_remove(&self->output_enter.link); - wl_list_remove(&self->output_leave.link); + wl_list_remove(&self->outputs_update.link); wl_list_for_each_safe(cache_entry, cache_entry_tmp, &self->cache, link) { _cache_entry_destroy(cache_entry, self->drop_buffer); @@ -178,38 +155,21 @@ _handle_node_destroy(struct wl_listener *listener, void *data) } static void -_handle_output_enter(struct wl_listener *listener, void *data) +_handle_outputs_update(struct wl_listener *listener, void *data) { struct scaled_scene_buffer *self = - wl_container_of(listener, self, output_enter); - /* primary_output is the output most of the node area is in */ - struct wlr_scene_output *primary = self->scene_buffer->primary_output; - /* scene_output is the output we just entered */ - struct wlr_scene_output *scene_output = data; - double max_scale = scene_output->output->scale; + wl_container_of(listener, self, outputs_update); - if (primary && primary->output->scale > max_scale) { - max_scale = primary->output->scale; + double max_scale = 0; + struct wlr_scene_outputs_update_event *event = data; + for (size_t i = 0; i < event->size; i++) { + max_scale = MAX(max_scale, event->active[i]->output->scale); } - - if (self->active_scale != max_scale) { + if (max_scale && self->active_scale != max_scale) { _update_buffer(self, max_scale); } } -static void -_handle_output_leave(struct wl_listener *listener, void *data) -{ - struct scaled_scene_buffer *self = - wl_container_of(listener, self, output_leave); - /* primary_output is the output most of the node area is in */ - struct wlr_scene_output *primary = self->scene_buffer->primary_output; - - if (primary && primary->output->scale != self->active_scale) { - _update_buffer(self, primary->output->scale); - } -} - /* Public API */ struct scaled_scene_buffer * scaled_scene_buffer_create(struct wlr_scene_tree *parent, @@ -247,11 +207,9 @@ scaled_scene_buffer_create(struct wlr_scene_tree *parent, wl_list_init(&self->link); } - /* Listen to output enter/leave so we get notified about scale changes */ - self->output_enter.notify = _handle_output_enter; - wl_signal_add(&self->scene_buffer->events.output_enter, &self->output_enter); - self->output_leave.notify = _handle_output_leave; - wl_signal_add(&self->scene_buffer->events.output_leave, &self->output_leave); + /* Listen to outputs_update so we get notified about scale changes */ + self->outputs_update.notify = _handle_outputs_update; + wl_signal_add(&self->scene_buffer->events.outputs_update, &self->outputs_update); /* Let it destroy automatically when the scene node destroys */ self->destroy.notify = _handle_node_destroy;