From f5b359f5b68b92be2cac3d396fef6feab6078700 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Thu, 2 Sep 2021 12:47:28 +0200 Subject: scene: add wlr_scene_attach_output_layout This is a helper to integrate wlr_scene with wlr_output_layout. --- output_layout.c | 105 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 output_layout.c (limited to 'output_layout.c') diff --git a/output_layout.c b/output_layout.c new file mode 100644 index 0000000..33dac13 --- /dev/null +++ b/output_layout.c @@ -0,0 +1,105 @@ +#include +#include +#include + +struct wlr_scene_output_layout { + struct wlr_output_layout *layout; + struct wlr_scene *scene; + + struct wl_listener layout_add; + struct wl_listener layout_change; + struct wl_listener layout_destroy; + struct wl_listener scene_destroy; +}; + +static void scene_output_layout_destroy(struct wlr_scene_output_layout *sol) { + wl_list_remove(&sol->layout_destroy.link); + wl_list_remove(&sol->layout_add.link); + wl_list_remove(&sol->layout_change.link); + wl_list_remove(&sol->scene_destroy.link); + free(sol); +} + +static void scene_output_layout_handle_layout_destroy( + struct wl_listener *listener, void *data) { + struct wlr_scene_output_layout *sol = + wl_container_of(listener, sol, layout_destroy); + + // Remove all outputs managed by the output layout + struct wlr_scene_output *scene_output, *tmp; + wl_list_for_each_safe(scene_output, tmp, &sol->scene->outputs, link) { + struct wlr_output_layout_output *lo = + wlr_output_layout_get(sol->layout, scene_output->output); + if (lo != NULL) { + wlr_scene_output_destroy(scene_output); + } + } + + scene_output_layout_destroy(sol); +} + +static void scene_output_layout_handle_layout_change( + struct wl_listener *listener, void *data) { + struct wlr_scene_output_layout *sol = + wl_container_of(listener, sol, layout_change); + + struct wlr_scene_output *scene_output, *tmp; + wl_list_for_each_safe(scene_output, tmp, &sol->scene->outputs, link) { + struct wlr_output_layout_output *lo = + wlr_output_layout_get(sol->layout, scene_output->output); + if (lo == NULL) { + // Output has been removed from the layout + wlr_scene_output_destroy(scene_output); + continue; + } + + wlr_scene_output_set_position(scene_output, lo->x, lo->y); + } +} + +static void scene_output_layout_handle_layout_add( + struct wl_listener *listener, void *data) { + struct wlr_scene_output_layout *sol = + wl_container_of(listener, sol, layout_add); + struct wlr_output_layout_output *lo = data; + + struct wlr_scene_output *scene_output = + wlr_scene_output_create(sol->scene, lo->output); + if (scene_output == NULL) { + return; + } + + wlr_scene_output_set_position(scene_output, lo->x, lo->y); +} + +static void scene_output_layout_handle_scene_destroy( + struct wl_listener *listener, void *data) { + struct wlr_scene_output_layout *sol = + wl_container_of(listener, sol, scene_destroy); + scene_output_layout_destroy(sol); +} + +bool wlr_scene_attach_output_layout(struct wlr_scene *scene, + struct wlr_output_layout *output_layout) { + struct wlr_scene_output_layout *sol = calloc(1, sizeof(*sol)); + if (sol == NULL) { + return false; + } + + sol->scene = scene; + sol->layout = output_layout; + + sol->layout_destroy.notify = scene_output_layout_handle_layout_destroy; + wl_signal_add(&output_layout->events.destroy, &sol->layout_destroy); + + sol->layout_change.notify = scene_output_layout_handle_layout_change; + wl_signal_add(&output_layout->events.change, &sol->layout_change); + + sol->layout_add.notify = scene_output_layout_handle_layout_add; + wl_signal_add(&output_layout->events.add, &sol->layout_add); + + sol->scene_destroy.notify = scene_output_layout_handle_scene_destroy; + wl_signal_add(&output_layout->events.destroy, &sol->scene_destroy); + + return true; +} -- cgit v1.2.3