aboutsummaryrefslogtreecommitdiffstats
path: root/sway/desktop/layer_shell.c
diff options
context:
space:
mode:
authorLibravatar Drew DeVault <sir@cmpwn.com>2018-03-28 16:38:11 -0400
committerLibravatar Drew DeVault <sir@cmpwn.com>2018-03-28 16:42:13 -0400
commit68cfa7ef6705c530ff28d9754c5b6cab7b429150 (patch)
tree0c25eb44f1285f2522b6a5f014276239cfa6ae3f /sway/desktop/layer_shell.c
parentAdd initial layer shell skeleton (diff)
downloadsway-68cfa7ef6705c530ff28d9754c5b6cab7b429150.tar.gz
sway-68cfa7ef6705c530ff28d9754c5b6cab7b429150.tar.zst
sway-68cfa7ef6705c530ff28d9754c5b6cab7b429150.zip
Render layer surfaces and respect exclusive zone
Diffstat (limited to 'sway/desktop/layer_shell.c')
-rw-r--r--sway/desktop/layer_shell.c239
1 files changed, 230 insertions, 9 deletions
diff --git a/sway/desktop/layer_shell.c b/sway/desktop/layer_shell.c
index 3cf171bd..a2506d21 100644
--- a/sway/desktop/layer_shell.c
+++ b/sway/desktop/layer_shell.c
@@ -1,40 +1,261 @@
1#include <stdbool.h>
1#include <stdlib.h> 2#include <stdlib.h>
3#include <string.h>
2#include <wayland-server.h> 4#include <wayland-server.h>
5#include <wlr/types/wlr_box.h>
6#include <wlr/types/wlr_layer_shell.h>
7#include <wlr/types/wlr_output.h>
3#include <wlr/util/log.h> 8#include <wlr/util/log.h>
4#include "sway/layers.h" 9#include "sway/layers.h"
10#include "sway/layout.h"
5#include "sway/output.h" 11#include "sway/output.h"
6#include "sway/server.h" 12#include "sway/server.h"
7 13
8static void arrange_layers(struct sway_output *output) { 14static void apply_exclusive(struct wlr_box *usable_area,
9 // TODO 15 uint32_t anchor, int32_t exclusive,
16 int32_t margin_top, int32_t margin_right,
17 int32_t margin_bottom, int32_t margin_left) {
18 if (exclusive <= 0) {
19 return;
20 }
21 struct {
22 uint32_t anchors;
23 int *positive_axis;
24 int *negative_axis;
25 int margin;
26 } edges[] = {
27 {
28 .anchors =
29 ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT |
30 ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT |
31 ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP,
32 .positive_axis = &usable_area->y,
33 .negative_axis = &usable_area->height,
34 .margin = margin_top,
35 },
36 {
37 .anchors =
38 ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT |
39 ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT |
40 ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM,
41 .positive_axis = NULL,
42 .negative_axis = &usable_area->height,
43 .margin = margin_bottom,
44 },
45 {
46 .anchors =
47 ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT |
48 ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP |
49 ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM,
50 .positive_axis = &usable_area->x,
51 .negative_axis = &usable_area->width,
52 .margin = margin_left,
53 },
54 {
55 .anchors =
56 ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT |
57 ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP |
58 ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM,
59 .positive_axis = NULL,
60 .negative_axis = &usable_area->width,
61 .margin = margin_right,
62 },
63 };
64 for (size_t i = 0; i < sizeof(edges) / sizeof(edges[0]); ++i) {
65 if ((anchor & edges[i].anchors) == edges[i].anchors) {
66 if (edges[i].positive_axis) {
67 *edges[i].positive_axis += exclusive + edges[i].margin;
68 }
69 if (edges[i].negative_axis) {
70 *edges[i].negative_axis -= exclusive + edges[i].margin;
71 }
72 }
73 }
74}
75
76static void arrange_layer(struct sway_output *output, struct wl_list *list,
77 struct wlr_box *usable_area, bool exclusive) {
78 struct sway_layer_surface *sway_layer;
79 struct wlr_box full_area = { 0 };
80 wlr_output_effective_resolution(output->wlr_output,
81 &full_area.width, &full_area.height);
82 wl_list_for_each(sway_layer, list, link) {
83 struct wlr_layer_surface *layer = sway_layer->layer_surface;
84 struct wlr_layer_surface_state *state = &layer->current;
85 if (exclusive != (state->exclusive_zone > 0)) {
86 continue;
87 }
88 struct wlr_box bounds;
89 if (state->exclusive_zone == -1) {
90 bounds = full_area;
91 } else {
92 bounds = *usable_area;
93 }
94 struct wlr_box box = {
95 .width = state->desired_width,
96 .height = state->desired_height
97 };
98 // Horizontal axis
99 const uint32_t both_horiz = ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT
100 | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT;
101 if ((state->anchor & both_horiz) && box.width == 0) {
102 box.x = bounds.x;
103 box.width = bounds.width;
104 } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT)) {
105 box.x = bounds.x;
106 } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT)) {
107 box.x = bounds.x + (bounds.width - box.width);
108 } else {
109 box.x = bounds.x + ((bounds.width / 2) - (box.width / 2));
110 }
111 // Vertical axis
112 const uint32_t both_vert = ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP
113 | ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM;
114 if ((state->anchor & both_vert) && box.height == 0) {
115 box.y = bounds.y;
116 box.height = bounds.height;
117 } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP)) {
118 box.y = bounds.y;
119 } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM)) {
120 box.y = bounds.y + (bounds.height - box.height);
121 } else {
122 box.y = bounds.y + ((bounds.height / 2) - (box.height / 2));
123 }
124 // Margin
125 if ((state->anchor & both_horiz) == both_horiz) {
126 box.x += state->margin.left;
127 box.width -= state->margin.left + state->margin.right;
128 } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT)) {
129 box.x += state->margin.left;
130 } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT)) {
131 box.x -= state->margin.right;
132 }
133 if ((state->anchor & both_vert) == both_vert) {
134 box.y += state->margin.top;
135 box.height -= state->margin.top + state->margin.bottom;
136 } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP)) {
137 box.y += state->margin.top;
138 } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM)) {
139 box.y -= state->margin.bottom;
140 }
141 if (box.width < 0 || box.height < 0) {
142 // TODO: Bubble up a protocol error?
143 wlr_layer_surface_close(layer);
144 continue;
145 }
146 // Apply
147 sway_layer->geo = box;
148 apply_exclusive(usable_area, state->anchor, state->exclusive_zone,
149 state->margin.top, state->margin.right,
150 state->margin.bottom, state->margin.left);
151 wlr_layer_surface_configure(layer, box.width, box.height);
152 }
153}
154
155void arrange_layers(struct sway_output *output) {
156 struct wlr_box usable_area = { 0 };
157 wlr_output_effective_resolution(output->wlr_output,
158 &usable_area.width, &usable_area.height);
159 struct wlr_box usable_area_before = output->usable_area;
160
161 // Arrange exclusive surfaces from top->bottom
162 arrange_layer(output, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY],
163 &usable_area, true);
164 arrange_layer(output, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP],
165 &usable_area, true);
166 arrange_layer(output, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM],
167 &usable_area, true);
168 arrange_layer(output, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND],
169 &usable_area, true);
170 memcpy(&output->usable_area, &usable_area, sizeof(struct wlr_box));
171
172 if (memcmp(&usable_area_before,
173 &usable_area, sizeof(struct wlr_box)) != 0) {
174 wlr_log(L_DEBUG, "arrange");
175 arrange_windows(output->swayc, -1, -1);
176 }
177
178 // Arrange non-exlusive surfaces from top->bottom
179 usable_area.x = usable_area.y = 0;
180 wlr_output_effective_resolution(output->wlr_output,
181 &usable_area.width, &usable_area.height);
182 arrange_layer(output, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY],
183 &usable_area, false);
184 arrange_layer(output, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP],
185 &usable_area, false);
186 arrange_layer(output, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM],
187 &usable_area, false);
188 arrange_layer(output, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND],
189 &usable_area, false);
10} 190}
11 191
12static void handle_output_destroy(struct wl_listener *listener, void *data) { 192static void handle_output_destroy(struct wl_listener *listener, void *data) {
13 // TODO 193 struct sway_layer_surface *sway_layer =
194 wl_container_of(listener, sway_layer, output_destroy);
195 sway_layer->layer_surface->output = NULL;
196 wl_list_remove(&sway_layer->output_destroy.link);
197 wl_list_remove(&sway_layer->output_mode.link);
198 wlr_layer_surface_close(sway_layer->layer_surface);
14} 199}
15 200
16static void handle_output_mode(struct wl_listener *listener, void *data) { 201static void handle_output_mode(struct wl_listener *listener, void *data) {
17 // TODO 202 struct wlr_output *output = data;
203 arrange_layers((struct sway_output *)output->data);
18} 204}
19 205
20static void handle_output_transform(struct wl_listener *listener, void *data) { 206static void handle_output_transform(struct wl_listener *listener, void *data) {
21 // TODO 207 struct wlr_output *output = data;
208 arrange_layers((struct sway_output *)output->data);
22} 209}
23 210
24static void handle_surface_commit(struct wl_listener *listener, void *data) { 211static void handle_surface_commit(struct wl_listener *listener, void *data) {
25 // TODO 212 struct sway_layer_surface *layer =
213 wl_container_of(listener, layer, surface_commit);
214 struct wlr_layer_surface *layer_surface = layer->layer_surface;
215 struct wlr_output *wlr_output = layer_surface->output;
216 if (wlr_output != NULL) {
217 struct sway_output *output = wlr_output->data;
218 struct wlr_box old_geo = layer->geo;
219 arrange_layers(output);
220 if (memcmp(&old_geo, &layer->geo, sizeof(struct wlr_box)) != 0) {
221 // TODO DAMAGE apply whole surface from previous and new geos
222 } else {
223 // TODO DAMAGE from surface damage
224 }
225 }
226}
227
228static void unmap(struct wlr_layer_surface *layer_surface) {
229 // TODO DAMAGE
26} 230}
27 231
28static void handle_destroy(struct wl_listener *listener, void *data) { 232static void handle_destroy(struct wl_listener *listener, void *data) {
29 // TODO 233 struct sway_layer_surface *sway_layer = wl_container_of(
234 listener, sway_layer, destroy);
235 if (sway_layer->layer_surface->mapped) {
236 unmap(sway_layer->layer_surface);
237 }
238 wl_list_remove(&sway_layer->link);
239 wl_list_remove(&sway_layer->destroy.link);
240 wl_list_remove(&sway_layer->map.link);
241 wl_list_remove(&sway_layer->unmap.link);
242 wl_list_remove(&sway_layer->surface_commit.link);
243 wl_list_remove(&sway_layer->output_destroy.link);
244 wl_list_remove(&sway_layer->output_mode.link);
245 wl_list_remove(&sway_layer->output_transform.link);
246 struct sway_output *output = sway_layer->layer_surface->output->data;
247 arrange_layers(output);
248 free(sway_layer);
30} 249}
31 250
32static void handle_map(struct wl_listener *listener, void *data) { 251static void handle_map(struct wl_listener *listener, void *data) {
33 // TODO 252 // TODO DAMAGE
34} 253}
35 254
36static void handle_unmap(struct wl_listener *listener, void *data) { 255static void handle_unmap(struct wl_listener *listener, void *data) {
37 // TODO 256 struct sway_layer_surface *sway_layer = wl_container_of(
257 listener, sway_layer, unmap);
258 unmap(sway_layer->layer_surface);
38} 259}
39 260
40void handle_layer_shell_surface(struct wl_listener *listener, void *data) { 261void handle_layer_shell_surface(struct wl_listener *listener, void *data) {