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