commit 70c6001
shrub
·
2026-05-08 12:34:00 +0000 UTC
parent 6a92889
layer shell: stack layers properly
3 files changed,
+100,
-8
+63,
-3
1@@ -1027,6 +1027,40 @@ static const struct view_impl view_impl = {
2 .move = move,
3 };
4
5+static void
6+restack_view_for_layer(struct compositor_view *view, bool raise)
7+{
8+ struct compositor_view *other;
9+ struct wl_list *insert_after = compositor.views.prev;
10+
11+ wl_list_for_each(other, &compositor.views, link)
12+ {
13+ if (other == view) {
14+ continue;
15+ }
16+
17+ if (other->stack_layer > view->stack_layer) {
18+ insert_after = &other->link;
19+ continue;
20+ }
21+
22+ if (other->stack_layer == view->stack_layer) {
23+ if (raise) {
24+ insert_after = other->link.prev;
25+ } else {
26+ insert_after = &other->link;
27+ }
28+ break;
29+ }
30+
31+ insert_after = other->link.prev;
32+ break;
33+ }
34+
35+ wl_list_remove(&view->link);
36+ wl_list_insert(insert_after, &view->link);
37+}
38+
39 static struct compositor_view *
40 view_at(int32_t x, int32_t y)
41 {
42@@ -1101,11 +1135,16 @@ raise_window(struct compositor_view *view)
43 continue;
44 }
45
46- if (other->always_top) {
47+ if (other->stack_layer > STACK_LAYER_NORMAL ||
48+ other->always_top) {
49 insert_after = &other->link;
50 continue;
51 }
52
53+ if (other->stack_layer < STACK_LAYER_NORMAL) {
54+ break;
55+ }
56+
57 if (other->window) {
58 top_window = other;
59 break;
60@@ -1133,8 +1172,28 @@ raise_window(struct compositor_view *view)
61 void
62 raise_window_top(struct compositor_view *view)
63 {
64- wl_list_remove(&view->link);
65- wl_list_insert(&compositor.views, &view->link);
66+ view->stack_layer = STACK_LAYER_OVERLAY;
67+ restack_view_for_layer(view, true);
68+ damage_view(view);
69+ schedule_updates(view->base.screens);
70+}
71+
72+void
73+compositor_view_set_stack_layer(struct compositor_view *view, uint32_t layer,
74+ bool raise)
75+{
76+ if (view->stack_layer == layer) {
77+ if (raise) {
78+ restack_view_for_layer(view, true);
79+ damage_view(view);
80+ schedule_updates(view->base.screens);
81+ }
82+ return;
83+ }
84+
85+ damage_view(view);
86+ view->stack_layer = layer;
87+ restack_view_for_layer(view, raise);
88 damage_view(view);
89 schedule_updates(view->base.screens);
90 }
91@@ -1267,6 +1326,7 @@ compositor_create_view(struct surface *surface)
92 view->buffer_offset_y = 0;
93 view->visible = false;
94 view->always_top = false;
95+ view->stack_layer = STACK_LAYER_NORMAL;
96 view->extents.x1 = 0;
97 view->extents.y1 = 0;
98 view->extents.x2 = 0;
+15,
-0
1@@ -75,6 +75,9 @@ struct compositor_view {
2 /* Whether or not to make it always be on top of other windows */
3 bool always_top;
4
5+ /* Global stacking layer for this view */
6+ uint32_t stack_layer;
7+
8 /* The box that the surface covers (including it's border). */
9 pixman_box32_t extents;
10
11@@ -166,4 +169,16 @@ raise_window(struct compositor_view *view);
12 void
13 raise_window_top(struct compositor_view *view);
14
15+enum compositor_stack_layer {
16+ STACK_LAYER_BACKGROUND = 0,
17+ STACK_LAYER_BOTTOM = 1,
18+ STACK_LAYER_NORMAL = 2,
19+ STACK_LAYER_TOP = 3,
20+ STACK_LAYER_OVERLAY = 4,
21+};
22+
23+void
24+compositor_view_set_stack_layer(struct compositor_view *view, uint32_t layer,
25+ bool raise);
26+
27 #endif
+22,
-5
1@@ -153,13 +153,30 @@ update_usable_geometry(struct layer_surface *surface)
2 static void
3 restack_layer(struct layer_surface *surface)
4 {
5- bool always_top = surface->current.layer == ZWLR_LAYER_SHELL_V1_LAYER_TOP ||
6- surface->current.layer == ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY;
7+ uint32_t stack_layer = STACK_LAYER_NORMAL;
8+ bool always_top = false;
9
10- surface->view->always_top = always_top;
11- if (always_top) {
12- raise_window_top(surface->view);
13+ switch (surface->current.layer) {
14+ case ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND:
15+ stack_layer = STACK_LAYER_BACKGROUND;
16+ break;
17+ case ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM:
18+ stack_layer = STACK_LAYER_BOTTOM;
19+ break;
20+ case ZWLR_LAYER_SHELL_V1_LAYER_TOP:
21+ stack_layer = STACK_LAYER_TOP;
22+ always_top = true;
23+ break;
24+ case ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY:
25+ stack_layer = STACK_LAYER_OVERLAY;
26+ always_top = true;
27+ break;
28+ default:
29+ break;
30 }
31+
32+ surface->view->always_top = always_top;
33+ compositor_view_set_stack_layer(surface->view, stack_layer, true);
34 }
35
36 static void