diff options
author | Simon Ser <[email protected]> | 2021-09-02 12:47:28 +0200 |
---|---|---|
committer | Kenny Levinsen <[email protected]> | 2021-09-09 12:04:35 +0200 |
commit | f5b359f5b68b92be2cac3d396fef6feab6078700 (patch) | |
tree | c1dfb5fe0cf1a18b049c4574d1c5d0f9b0076ea8 | |
parent | 0272bcb3139dd52b86bfc427b01055d2131a458f (diff) |
scene: add wlr_scene_attach_output_layout
This is a helper to integrate wlr_scene with wlr_output_layout.
-rw-r--r-- | output_layout.c | 105 |
1 files changed, 105 insertions, 0 deletions
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 <stdlib.h> +#include <wlr/types/wlr_output_layout.h> +#include <wlr/types/wlr_scene.h> + +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; +} |