aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/wlr/types/wlr_scene.h6
-rw-r--r--types/scene/output_layout.c110
2 files changed, 80 insertions, 36 deletions
diff --git a/include/wlr/types/wlr_scene.h b/include/wlr/types/wlr_scene.h
index 4b8ea517..49804d83 100644
--- a/include/wlr/types/wlr_scene.h
+++ b/include/wlr/types/wlr_scene.h
@@ -406,8 +406,10 @@ struct wlr_scene_output *wlr_scene_get_scene_output(struct wlr_scene *scene,
/**
* Attach an output layout to a scene.
*
- * Outputs in the output layout are automatically added to the scene. Any
- * change to the output layout is mirrored to the scene-graph outputs.
+ * Adding, removing, or repositioning an output in the output layout
+ * will respectively add, remove or reposition a corresponding
+ * scene-graph output. When the output layout is destroyed, scene-graph
+ * outputs which were created by this helper will be destroyed.
*/
bool wlr_scene_attach_output_layout(struct wlr_scene *scene,
struct wlr_output_layout *output_layout);
diff --git a/types/scene/output_layout.c b/types/scene/output_layout.c
index e2327eb9..21223114 100644
--- a/types/scene/output_layout.c
+++ b/types/scene/output_layout.c
@@ -6,36 +6,58 @@ struct wlr_scene_output_layout {
struct wlr_output_layout *layout;
struct wlr_scene *scene;
+ struct wl_list outputs; // wlr_scene_output_layout_output.link
+
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);
+struct wlr_scene_output_layout_output {
+ struct wlr_output_layout_output *layout_output;
+ struct wlr_scene_output *scene_output;
+
+ struct wl_list link; // wlr_scene_output_layout.outputs
+
+ struct wl_listener layout_output_destroy;
+ struct wl_listener scene_output_destroy;
+};
+
+static void scene_output_layout_output_destroy(
+ struct wlr_scene_output_layout_output *solo) {
+ wlr_scene_output_destroy(solo->scene_output);
+ wl_list_remove(&solo->layout_output_destroy.link);
+ wl_list_remove(&solo->scene_output_destroy.link);
+ wl_list_remove(&solo->link);
+ free(solo);
}
-static void scene_output_layout_handle_layout_destroy(
+static void scene_output_layout_output_handle_layout_output_destroy(
struct wl_listener *listener, void *data) {
- struct wlr_scene_output_layout *sol =
- wl_container_of(listener, sol, layout_destroy);
+ struct wlr_scene_output_layout_output *solo =
+ wl_container_of(listener, solo, layout_output_destroy);
+ scene_output_layout_output_destroy(solo);
+}
- // 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);
- }
- }
+static void scene_output_layout_output_handle_scene_output_destroy(
+ struct wl_listener *listener, void *data) {
+ struct wlr_scene_output_layout_output *solo =
+ wl_container_of(listener, solo, scene_output_destroy);
+ solo->scene_output = NULL;
+ scene_output_layout_output_destroy(solo);
+}
- scene_output_layout_destroy(sol);
+static void scene_output_layout_destroy(struct wlr_scene_output_layout *sol) {
+ struct wlr_scene_output_layout_output *solo, *tmp;
+ wl_list_for_each_safe(solo, tmp, &sol->outputs, link) {
+ scene_output_layout_output_destroy(solo);
+ }
+ wl_list_remove(&sol->layout_add.link);
+ wl_list_remove(&sol->layout_change.link);
+ wl_list_remove(&sol->layout_destroy.link);
+ wl_list_remove(&sol->scene_destroy.link);
+ free(sol);
}
static void scene_output_layout_handle_layout_change(
@@ -43,17 +65,10 @@ static void scene_output_layout_handle_layout_change(
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);
+ struct wlr_scene_output_layout_output *solo;
+ wl_list_for_each(solo, &sol->outputs, link) {
+ wlr_scene_output_set_position(solo->scene_output,
+ solo->layout_output->x, solo->layout_output->y);
}
}
@@ -63,13 +78,38 @@ static void scene_output_layout_handle_layout_add(
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) {
+ struct wlr_scene_output_layout_output *solo = calloc(1, sizeof(*solo));
+ if (solo == NULL) {
return;
}
- wlr_scene_output_set_position(scene_output, lo->x, lo->y);
+ solo->scene_output = wlr_scene_output_create(sol->scene, lo->output);
+ if (solo->scene_output == NULL) {
+ free(solo);
+ return;
+ }
+
+ solo->layout_output = lo;
+
+ solo->layout_output_destroy.notify =
+ scene_output_layout_output_handle_layout_output_destroy;
+ wl_signal_add(&lo->events.destroy, &solo->layout_output_destroy);
+
+ solo->scene_output_destroy.notify =
+ scene_output_layout_output_handle_scene_output_destroy;
+ wl_signal_add(&solo->scene_output->events.destroy,
+ &solo->scene_output_destroy);
+
+ wl_list_insert(&sol->outputs, &solo->link);
+
+ wlr_scene_output_set_position(solo->scene_output, lo->x, lo->y);
+}
+
+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);
+ scene_output_layout_destroy(sol);
}
static void scene_output_layout_handle_scene_destroy(
@@ -89,6 +129,8 @@ bool wlr_scene_attach_output_layout(struct wlr_scene *scene,
sol->scene = scene;
sol->layout = output_layout;
+ wl_list_init(&sol->outputs);
+
sol->layout_destroy.notify = scene_output_layout_handle_layout_destroy;
wl_signal_add(&output_layout->events.destroy, &sol->layout_destroy);