diff options
-rw-r--r-- | include/sway/layers.h | 3 | ||||
-rw-r--r-- | include/sway/output.h | 6 | ||||
-rw-r--r-- | sway/commands/output.c | 2 | ||||
-rw-r--r-- | sway/config/output.c | 31 | ||||
-rw-r--r-- | sway/desktop/layer_shell.c | 239 | ||||
-rw-r--r-- | sway/desktop/output.c | 53 | ||||
-rw-r--r-- | sway/desktop/xwayland.c | 4 | ||||
-rw-r--r-- | sway/tree/container.c | 4 | ||||
-rw-r--r-- | sway/tree/layout.c | 11 |
9 files changed, 320 insertions, 33 deletions
diff --git a/include/sway/layers.h b/include/sway/layers.h index 73fb7cb8..22054be1 100644 --- a/include/sway/layers.h +++ b/include/sway/layers.h | |||
@@ -21,4 +21,7 @@ struct sway_layer_surface { | |||
21 | struct wlr_box geo; | 21 | struct wlr_box geo; |
22 | }; | 22 | }; |
23 | 23 | ||
24 | struct sway_output; | ||
25 | void arrange_layers(struct sway_output *output); | ||
26 | |||
24 | #endif | 27 | #endif |
diff --git a/include/sway/output.h b/include/sway/output.h index 769d44d0..44d009d1 100644 --- a/include/sway/output.h +++ b/include/sway/output.h | |||
@@ -4,6 +4,7 @@ | |||
4 | #include <wayland-server.h> | 4 | #include <wayland-server.h> |
5 | #include <wlr/types/wlr_box.h> | 5 | #include <wlr/types/wlr_box.h> |
6 | #include <wlr/types/wlr_output.h> | 6 | #include <wlr/types/wlr_output.h> |
7 | #include <unistd.h> | ||
7 | 8 | ||
8 | struct sway_server; | 9 | struct sway_server; |
9 | struct sway_container; | 10 | struct sway_container; |
@@ -18,7 +19,10 @@ struct sway_output { | |||
18 | struct wlr_box usable_area; | 19 | struct wlr_box usable_area; |
19 | 20 | ||
20 | struct wl_listener frame; | 21 | struct wl_listener frame; |
21 | struct wl_listener output_destroy; | 22 | struct wl_listener destroy; |
23 | struct wl_listener mode; | ||
24 | |||
25 | pid_t bg_pid; | ||
22 | }; | 26 | }; |
23 | 27 | ||
24 | #endif | 28 | #endif |
diff --git a/sway/commands/output.c b/sway/commands/output.c index e747eb4e..35bc8099 100644 --- a/sway/commands/output.c +++ b/sway/commands/output.c | |||
@@ -188,7 +188,7 @@ static struct cmd_results *cmd_output_background(struct output_config *output, | |||
188 | } | 188 | } |
189 | 189 | ||
190 | wordexp_t p; | 190 | wordexp_t p; |
191 | char *src = join_args(argv + *i - 1, j); | 191 | char *src = join_args(argv + *i, j); |
192 | if (wordexp(src, &p, 0) != 0 || p.we_wordv[0] == NULL) { | 192 | if (wordexp(src, &p, 0) != 0 || p.we_wordv[0] == NULL) { |
193 | return cmd_results_new(CMD_INVALID, "output", | 193 | return cmd_results_new(CMD_INVALID, "output", |
194 | "Invalid syntax (%s).", src); | 194 | "Invalid syntax (%s).", src); |
diff --git a/sway/config/output.c b/sway/config/output.c index 69e883f1..c4168b4f 100644 --- a/sway/config/output.c +++ b/sway/config/output.c | |||
@@ -1,9 +1,12 @@ | |||
1 | #define _XOPEN_SOURCE 700 | 1 | #define _XOPEN_SOURCE 700 |
2 | #include <assert.h> | ||
2 | #include <stdbool.h> | 3 | #include <stdbool.h> |
3 | #include <string.h> | 4 | #include <string.h> |
4 | #include <assert.h> | 5 | #include <signal.h> |
6 | #include <sys/wait.h> | ||
5 | #include <wlr/types/wlr_output.h> | 7 | #include <wlr/types/wlr_output.h> |
6 | #include <wlr/types/wlr_output_layout.h> | 8 | #include <wlr/types/wlr_output_layout.h> |
9 | #include <unistd.h> | ||
7 | #include "sway/config.h" | 10 | #include "sway/config.h" |
8 | #include "sway/output.h" | 11 | #include "sway/output.h" |
9 | #include "log.h" | 12 | #include "log.h" |
@@ -107,6 +110,16 @@ static void set_mode(struct wlr_output *output, int width, int height, | |||
107 | } | 110 | } |
108 | } | 111 | } |
109 | 112 | ||
113 | void terminate_swaybg(pid_t pid) { | ||
114 | int ret = kill(pid, SIGTERM); | ||
115 | if (ret != 0) { | ||
116 | wlr_log(L_ERROR, "Unable to terminate swaybg [pid: %d]", pid); | ||
117 | } else { | ||
118 | int status; | ||
119 | waitpid(pid, &status, 0); | ||
120 | } | ||
121 | } | ||
122 | |||
110 | void apply_output_config(struct output_config *oc, swayc_t *output) { | 123 | void apply_output_config(struct output_config *oc, swayc_t *output) { |
111 | assert(output->type == C_OUTPUT); | 124 | assert(output->type == C_OUTPUT); |
112 | 125 | ||
@@ -160,12 +173,12 @@ void apply_output_config(struct output_config *oc, swayc_t *output) { | |||
160 | } | 173 | } |
161 | 174 | ||
162 | if (oc && oc->background) { | 175 | if (oc && oc->background) { |
163 | // TODO swaybg | 176 | if (output->sway_output->bg_pid != 0) { |
164 | /*if (output->bg_pid != 0) { | 177 | terminate_swaybg(output->sway_output->bg_pid); |
165 | terminate_swaybg(output->bg_pid); | ||
166 | } | 178 | } |
167 | 179 | ||
168 | wlr_log(L_DEBUG, "Setting background for output %d to %s", output_i, oc->background); | 180 | wlr_log(L_DEBUG, "Setting background for output %d to %s", |
181 | output_i, oc->background); | ||
169 | 182 | ||
170 | size_t bufsize = 12; | 183 | size_t bufsize = 12; |
171 | char output_id[bufsize]; | 184 | char output_id[bufsize]; |
@@ -173,17 +186,17 @@ void apply_output_config(struct output_config *oc, swayc_t *output) { | |||
173 | output_id[bufsize-1] = 0; | 186 | output_id[bufsize-1] = 0; |
174 | 187 | ||
175 | char *const cmd[] = { | 188 | char *const cmd[] = { |
176 | "swaybg", | 189 | "./swaybg/swaybg", |
177 | output_id, | 190 | output_id, |
178 | oc->background, | 191 | oc->background, |
179 | oc->background_option, | 192 | oc->background_option, |
180 | NULL, | 193 | NULL, |
181 | }; | 194 | }; |
182 | 195 | ||
183 | output->bg_pid = fork(); | 196 | output->sway_output->bg_pid = fork(); |
184 | if (output->bg_pid == 0) { | 197 | if (output->sway_output->bg_pid == 0) { |
185 | execvp(cmd[0], cmd); | 198 | execvp(cmd[0], cmd); |
186 | }*/ | 199 | } |
187 | } | 200 | } |
188 | } | 201 | } |
189 | 202 | ||
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 | ||
8 | static void arrange_layers(struct sway_output *output) { | 14 | static 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 | |||
76 | static 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 | |||
155 | void 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 | ||
12 | static void handle_output_destroy(struct wl_listener *listener, void *data) { | 192 | static 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 | ||
16 | static void handle_output_mode(struct wl_listener *listener, void *data) { | 201 | static 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 | ||
20 | static void handle_output_transform(struct wl_listener *listener, void *data) { | 206 | static 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 | ||
24 | static void handle_surface_commit(struct wl_listener *listener, void *data) { | 211 | static 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 | |||
228 | static void unmap(struct wlr_layer_surface *layer_surface) { | ||
229 | // TODO DAMAGE | ||
26 | } | 230 | } |
27 | 231 | ||
28 | static void handle_destroy(struct wl_listener *listener, void *data) { | 232 | static 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 | ||
32 | static void handle_map(struct wl_listener *listener, void *data) { | 251 | static void handle_map(struct wl_listener *listener, void *data) { |
33 | // TODO | 252 | // TODO DAMAGE |
34 | } | 253 | } |
35 | 254 | ||
36 | static void handle_unmap(struct wl_listener *listener, void *data) { | 255 | static 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 | ||
40 | void handle_layer_shell_surface(struct wl_listener *listener, void *data) { | 261 | void handle_layer_shell_surface(struct wl_listener *listener, void *data) { |
diff --git a/sway/desktop/output.c b/sway/desktop/output.c index a9aa47a6..59f79a81 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c | |||
@@ -4,14 +4,17 @@ | |||
4 | #include <time.h> | 4 | #include <time.h> |
5 | #include <wayland-server.h> | 5 | #include <wayland-server.h> |
6 | #include <wlr/render/wlr_renderer.h> | 6 | #include <wlr/render/wlr_renderer.h> |
7 | #include <wlr/types/wlr_box.h> | ||
7 | #include <wlr/types/wlr_matrix.h> | 8 | #include <wlr/types/wlr_matrix.h> |
8 | #include <wlr/types/wlr_output.h> | 9 | #include <wlr/types/wlr_output.h> |
10 | #include <wlr/types/wlr_output_layout.h> | ||
9 | #include <wlr/types/wlr_surface.h> | 11 | #include <wlr/types/wlr_surface.h> |
10 | #include <wlr/types/wlr_wl_shell.h> | 12 | #include <wlr/types/wlr_wl_shell.h> |
11 | #include "log.h" | 13 | #include "log.h" |
12 | #include "sway/container.h" | 14 | #include "sway/container.h" |
13 | #include "sway/input/input-manager.h" | 15 | #include "sway/input/input-manager.h" |
14 | #include "sway/input/seat.h" | 16 | #include "sway/input/seat.h" |
17 | #include "sway/layers.h" | ||
15 | #include "sway/layout.h" | 18 | #include "sway/layout.h" |
16 | #include "sway/output.h" | 19 | #include "sway/output.h" |
17 | #include "sway/server.h" | 20 | #include "sway/server.h" |
@@ -177,6 +180,20 @@ static void output_frame_view(swayc_t *view, void *data) { | |||
177 | } | 180 | } |
178 | } | 181 | } |
179 | 182 | ||
183 | static void render_layer(struct sway_output *output, | ||
184 | const struct wlr_box *output_layout_box, | ||
185 | struct timespec *when, | ||
186 | struct wl_list *layer) { | ||
187 | struct sway_layer_surface *sway_layer; | ||
188 | wl_list_for_each(sway_layer, layer, link) { | ||
189 | struct wlr_layer_surface *layer = sway_layer->layer_surface; | ||
190 | render_surface(layer->surface, output->wlr_output, when, | ||
191 | sway_layer->geo.x + output_layout_box->x, | ||
192 | sway_layer->geo.y + output_layout_box->y, 0); | ||
193 | wlr_surface_send_frame_done(layer->surface, when); | ||
194 | } | ||
195 | } | ||
196 | |||
180 | static void output_frame_notify(struct wl_listener *listener, void *data) { | 197 | static void output_frame_notify(struct wl_listener *listener, void *data) { |
181 | struct sway_output *soutput = wl_container_of(listener, soutput, frame); | 198 | struct sway_output *soutput = wl_container_of(listener, soutput, frame); |
182 | struct wlr_output *wlr_output = data; | 199 | struct wlr_output *wlr_output = data; |
@@ -189,6 +206,18 @@ static void output_frame_notify(struct wl_listener *listener, void *data) { | |||
189 | wlr_output_make_current(wlr_output, &buffer_age); | 206 | wlr_output_make_current(wlr_output, &buffer_age); |
190 | wlr_renderer_begin(server->renderer, wlr_output->width, wlr_output->height); | 207 | wlr_renderer_begin(server->renderer, wlr_output->width, wlr_output->height); |
191 | 208 | ||
209 | struct timespec now; | ||
210 | clock_gettime(CLOCK_MONOTONIC, &now); | ||
211 | |||
212 | struct wlr_output_layout *layout = root_container.sway_root->output_layout; | ||
213 | const struct wlr_box *output_box = wlr_output_layout_get_box( | ||
214 | layout, wlr_output); | ||
215 | |||
216 | render_layer(soutput, output_box, &now, | ||
217 | &soutput->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND]); | ||
218 | render_layer(soutput, output_box, &now, | ||
219 | &soutput->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM]); | ||
220 | |||
192 | struct sway_seat *seat = input_manager_current_seat(input_manager); | 221 | struct sway_seat *seat = input_manager_current_seat(input_manager); |
193 | swayc_t *focus = sway_seat_get_focus_inactive(seat, soutput->swayc); | 222 | swayc_t *focus = sway_seat_get_focus_inactive(seat, soutput->swayc); |
194 | swayc_t *workspace = (focus->type == C_WORKSPACE ? | 223 | swayc_t *workspace = (focus->type == C_WORKSPACE ? |
@@ -210,22 +239,32 @@ static void output_frame_notify(struct wl_listener *listener, void *data) { | |||
210 | } | 239 | } |
211 | } | 240 | } |
212 | 241 | ||
242 | // TODO: Consider revising this when fullscreen windows are supported | ||
243 | render_layer(soutput, output_box, &now, | ||
244 | &soutput->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]); | ||
245 | render_layer(soutput, output_box, &now, | ||
246 | &soutput->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY]); | ||
247 | |||
213 | wlr_renderer_end(server->renderer); | 248 | wlr_renderer_end(server->renderer); |
214 | wlr_output_swap_buffers(wlr_output, &soutput->last_frame, NULL); | 249 | wlr_output_swap_buffers(wlr_output, &soutput->last_frame, NULL); |
215 | 250 | ||
216 | struct timespec now; | ||
217 | clock_gettime(CLOCK_MONOTONIC, &now); | ||
218 | soutput->last_frame = now; | 251 | soutput->last_frame = now; |
219 | } | 252 | } |
220 | 253 | ||
221 | static void handle_output_destroy(struct wl_listener *listener, void *data) { | 254 | static void handle_output_destroy(struct wl_listener *listener, void *data) { |
222 | struct sway_output *output = wl_container_of(listener, output, output_destroy); | 255 | struct sway_output *output = wl_container_of(listener, output, destroy); |
223 | struct wlr_output *wlr_output = data; | 256 | struct wlr_output *wlr_output = data; |
224 | wlr_log(L_DEBUG, "Output %p %s removed", wlr_output, wlr_output->name); | 257 | wlr_log(L_DEBUG, "Output %p %s removed", wlr_output, wlr_output->name); |
225 | 258 | ||
226 | destroy_output(output->swayc); | 259 | destroy_output(output->swayc); |
227 | } | 260 | } |
228 | 261 | ||
262 | static void handle_output_mode(struct wl_listener *listener, void *data) { | ||
263 | struct sway_output *output = wl_container_of(listener, output, mode); | ||
264 | arrange_layers(output); | ||
265 | arrange_windows(output->swayc, -1, -1); | ||
266 | } | ||
267 | |||
229 | void handle_new_output(struct wl_listener *listener, void *data) { | 268 | void handle_new_output(struct wl_listener *listener, void *data) { |
230 | struct sway_server *server = wl_container_of(listener, server, new_output); | 269 | struct sway_server *server = wl_container_of(listener, server, new_output); |
231 | struct wlr_output *wlr_output = data; | 270 | struct wlr_output *wlr_output = data; |
@@ -260,9 +299,11 @@ void handle_new_output(struct wl_listener *listener, void *data) { | |||
260 | 299 | ||
261 | wl_signal_add(&wlr_output->events.frame, &output->frame); | 300 | wl_signal_add(&wlr_output->events.frame, &output->frame); |
262 | output->frame.notify = output_frame_notify; | 301 | output->frame.notify = output_frame_notify; |
302 | wl_signal_add(&wlr_output->events.destroy, &output->destroy); | ||
303 | output->destroy.notify = handle_output_destroy; | ||
304 | wl_signal_add(&wlr_output->events.mode, &output->mode); | ||
305 | output->mode.notify = handle_output_mode; | ||
263 | 306 | ||
264 | wl_signal_add(&wlr_output->events.destroy, &output->output_destroy); | 307 | arrange_layers(output); |
265 | output->output_destroy.notify = handle_output_destroy; | ||
266 | |||
267 | arrange_windows(&root_container, -1, -1); | 308 | arrange_windows(&root_container, -1, -1); |
268 | } | 309 | } |
diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c index 6b5e03f9..f9b5242b 100644 --- a/sway/desktop/xwayland.c +++ b/sway/desktop/xwayland.c | |||
@@ -84,7 +84,7 @@ static void set_activated(struct sway_view *view, bool activated) { | |||
84 | wlr_xwayland_surface_activate(surface, activated); | 84 | wlr_xwayland_surface_activate(surface, activated); |
85 | } | 85 | } |
86 | 86 | ||
87 | static void close(struct sway_view *view) { | 87 | static void close_view(struct sway_view *view) { |
88 | if (!assert_xwayland(view)) { | 88 | if (!assert_xwayland(view)) { |
89 | return; | 89 | return; |
90 | } | 90 | } |
@@ -203,7 +203,7 @@ void handle_xwayland_surface(struct wl_listener *listener, void *data) { | |||
203 | sway_view->iface.set_size = set_size; | 203 | sway_view->iface.set_size = set_size; |
204 | sway_view->iface.set_position = set_position; | 204 | sway_view->iface.set_position = set_position; |
205 | sway_view->iface.set_activated = set_activated; | 205 | sway_view->iface.set_activated = set_activated; |
206 | sway_view->iface.close = close; | 206 | sway_view->iface.close = close_view; |
207 | sway_view->wlr_xwayland_surface = xsurface; | 207 | sway_view->wlr_xwayland_surface = xsurface; |
208 | sway_view->sway_xwayland_surface = sway_surface; | 208 | sway_view->sway_xwayland_surface = sway_surface; |
209 | sway_view->surface = xsurface->surface; | 209 | sway_view->surface = xsurface->surface; |
diff --git a/sway/tree/container.c b/sway/tree/container.c index 705221d7..bbafe9ec 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c | |||
@@ -254,7 +254,9 @@ swayc_t *destroy_output(swayc_t *output) { | |||
254 | } | 254 | } |
255 | } | 255 | } |
256 | 256 | ||
257 | wl_list_remove(&output->sway_output->output_destroy.link); | 257 | wl_list_remove(&output->sway_output->frame.link); |
258 | wl_list_remove(&output->sway_output->destroy.link); | ||
259 | wl_list_remove(&output->sway_output->mode.link); | ||
258 | 260 | ||
259 | wlr_log(L_DEBUG, "OUTPUT: Destroying output '%s'", output->name); | 261 | wlr_log(L_DEBUG, "OUTPUT: Destroying output '%s'", output->name); |
260 | free_swayc(output); | 262 | free_swayc(output); |
diff --git a/sway/tree/layout.c b/sway/tree/layout.c index 3d04a1a7..de9e7b58 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c | |||
@@ -204,10 +204,13 @@ void arrange_windows(swayc_t *container, double width, double height) { | |||
204 | case C_WORKSPACE: | 204 | case C_WORKSPACE: |
205 | { | 205 | { |
206 | swayc_t *output = swayc_parent_by_type(container, C_OUTPUT); | 206 | swayc_t *output = swayc_parent_by_type(container, C_OUTPUT); |
207 | container->width = output->width; | 207 | struct wlr_box *area = &output->sway_output->usable_area; |
208 | container->height = output->height; | 208 | wlr_log(L_DEBUG, "Usable area for ws: %dx%d@%d,%d", |
209 | container->x = x; | 209 | area->width, area->height, area->x, area->y); |
210 | container->y = y; | 210 | container->width = area->width; |
211 | container->height = area->height; | ||
212 | container->x = x = area->x; | ||
213 | container->y = y = area->y; | ||
211 | wlr_log(L_DEBUG, "Arranging workspace '%s' at %f, %f", | 214 | wlr_log(L_DEBUG, "Arranging workspace '%s' at %f, %f", |
212 | container->name, container->x, container->y); | 215 | container->name, container->x, container->y); |
213 | } | 216 | } |