diff options
-rw-r--r-- | include/sway/layers.h | 27 | ||||
-rw-r--r-- | include/sway/output.h | 10 | ||||
-rw-r--r-- | include/sway/server.h | 5 | ||||
-rw-r--r-- | protocols/meson.build | 55 | ||||
-rw-r--r-- | sway/commands/output.c | 2 | ||||
-rw-r--r-- | sway/config/output.c | 31 | ||||
-rw-r--r-- | sway/desktop/layer_shell.c | 320 | ||||
-rw-r--r-- | sway/desktop/output.c | 95 | ||||
-rw-r--r-- | sway/desktop/xwayland.c | 4 | ||||
-rw-r--r-- | sway/meson.build | 10 | ||||
-rw-r--r-- | sway/server.c | 6 | ||||
-rw-r--r-- | sway/tree/container.c | 4 | ||||
-rw-r--r-- | sway/tree/layout.c | 11 | ||||
-rw-r--r-- | swaybg/meson.build | 2 |
14 files changed, 525 insertions, 57 deletions
diff --git a/include/sway/layers.h b/include/sway/layers.h new file mode 100644 index 00000000..22054be1 --- /dev/null +++ b/include/sway/layers.h | |||
@@ -0,0 +1,27 @@ | |||
1 | #ifndef _SWAY_LAYERS_H | ||
2 | #define _SWAY_LAYERS_H | ||
3 | #include <stdbool.h> | ||
4 | #include <wlr/types/wlr_box.h> | ||
5 | #include <wlr/types/wlr_surface.h> | ||
6 | #include <wlr/types/wlr_layer_shell.h> | ||
7 | |||
8 | struct sway_layer_surface { | ||
9 | struct wlr_layer_surface *layer_surface; | ||
10 | struct wl_list link; | ||
11 | |||
12 | struct wl_listener destroy; | ||
13 | struct wl_listener map; | ||
14 | struct wl_listener unmap; | ||
15 | struct wl_listener surface_commit; | ||
16 | struct wl_listener output_destroy; | ||
17 | struct wl_listener output_mode; | ||
18 | struct wl_listener output_transform; | ||
19 | |||
20 | bool configured; | ||
21 | struct wlr_box geo; | ||
22 | }; | ||
23 | |||
24 | struct sway_output; | ||
25 | void arrange_layers(struct sway_output *output); | ||
26 | |||
27 | #endif | ||
diff --git a/include/sway/output.h b/include/sway/output.h index 95d64705..f899230f 100644 --- a/include/sway/output.h +++ b/include/sway/output.h | |||
@@ -1,7 +1,9 @@ | |||
1 | #ifndef _SWAY_OUTPUT_H | 1 | #ifndef _SWAY_OUTPUT_H |
2 | #define _SWAY_OUTPUT_H | 2 | #define _SWAY_OUTPUT_H |
3 | #include <time.h> | 3 | #include <time.h> |
4 | #include <unistd.h> | ||
4 | #include <wayland-server.h> | 5 | #include <wayland-server.h> |
6 | #include <wlr/types/wlr_box.h> | ||
5 | #include <wlr/types/wlr_output.h> | 7 | #include <wlr/types/wlr_output.h> |
6 | 8 | ||
7 | struct sway_server; | 9 | struct sway_server; |
@@ -13,8 +15,14 @@ struct sway_output { | |||
13 | struct sway_server *server; | 15 | struct sway_server *server; |
14 | struct timespec last_frame; | 16 | struct timespec last_frame; |
15 | 17 | ||
18 | struct wl_list layers[4]; // sway_layer_surface::link | ||
19 | struct wlr_box usable_area; | ||
20 | |||
16 | struct wl_listener frame; | 21 | struct wl_listener frame; |
17 | struct wl_listener output_destroy; | 22 | struct wl_listener destroy; |
23 | struct wl_listener mode; | ||
24 | |||
25 | pid_t bg_pid; | ||
18 | }; | 26 | }; |
19 | 27 | ||
20 | #endif | 28 | #endif |
diff --git a/include/sway/server.h b/include/sway/server.h index eb7fa2ff..25eb64fe 100644 --- a/include/sway/server.h +++ b/include/sway/server.h | |||
@@ -6,6 +6,7 @@ | |||
6 | #include <wlr/backend/session.h> | 6 | #include <wlr/backend/session.h> |
7 | #include <wlr/types/wlr_compositor.h> | 7 | #include <wlr/types/wlr_compositor.h> |
8 | #include <wlr/types/wlr_data_device.h> | 8 | #include <wlr/types/wlr_data_device.h> |
9 | #include <wlr/types/wlr_layer_shell.h> | ||
9 | #include <wlr/types/wlr_xdg_shell_v6.h> | 10 | #include <wlr/types/wlr_xdg_shell_v6.h> |
10 | #include <wlr/render/wlr_renderer.h> | 11 | #include <wlr/render/wlr_renderer.h> |
11 | // TODO WLR: make Xwayland optional | 12 | // TODO WLR: make Xwayland optional |
@@ -27,6 +28,9 @@ struct sway_server { | |||
27 | struct wl_listener new_output; | 28 | struct wl_listener new_output; |
28 | struct wl_listener output_frame; | 29 | struct wl_listener output_frame; |
29 | 30 | ||
31 | struct wlr_layer_shell *layer_shell; | ||
32 | struct wl_listener layer_shell_surface; | ||
33 | |||
30 | struct wlr_xdg_shell_v6 *xdg_shell_v6; | 34 | struct wlr_xdg_shell_v6 *xdg_shell_v6; |
31 | struct wl_listener xdg_shell_v6_surface; | 35 | struct wl_listener xdg_shell_v6_surface; |
32 | 36 | ||
@@ -46,6 +50,7 @@ void server_run(struct sway_server *server); | |||
46 | 50 | ||
47 | void handle_new_output(struct wl_listener *listener, void *data); | 51 | void handle_new_output(struct wl_listener *listener, void *data); |
48 | 52 | ||
53 | void handle_layer_shell_surface(struct wl_listener *listener, void *data); | ||
49 | void handle_xdg_shell_v6_surface(struct wl_listener *listener, void *data); | 54 | void handle_xdg_shell_v6_surface(struct wl_listener *listener, void *data); |
50 | void handle_xwayland_surface(struct wl_listener *listener, void *data); | 55 | void handle_xwayland_surface(struct wl_listener *listener, void *data); |
51 | void handle_wl_shell_surface(struct wl_listener *listener, void *data); | 56 | void handle_wl_shell_surface(struct wl_listener *listener, void *data); |
diff --git a/protocols/meson.build b/protocols/meson.build index 1fda600e..3f79e719 100644 --- a/protocols/meson.build +++ b/protocols/meson.build | |||
@@ -14,24 +14,57 @@ wayland_scanner_client = generator( | |||
14 | arguments: ['client-header', '@INPUT@', '@OUTPUT@'], | 14 | arguments: ['client-header', '@INPUT@', '@OUTPUT@'], |
15 | ) | 15 | ) |
16 | 16 | ||
17 | protocols = [ | 17 | wayland_scanner_server = generator( |
18 | wayland_scanner, | ||
19 | output: '@BASENAME@-protocol.h', | ||
20 | arguments: ['server-header', '@INPUT@', '@OUTPUT@'], | ||
21 | ) | ||
22 | |||
23 | client_protocols = [ | ||
18 | [wl_protocol_dir, 'stable/xdg-shell/xdg-shell.xml'], | 24 | [wl_protocol_dir, 'stable/xdg-shell/xdg-shell.xml'], |
19 | ['wlr-layer-shell-unstable-v1.xml'] | 25 | ['wlr-layer-shell-unstable-v1.xml'] |
20 | ] | 26 | ] |
21 | 27 | ||
22 | wl_protos_src = [] | 28 | server_protocols = [ |
23 | wl_protos_headers = [] | 29 | ['wlr-layer-shell-unstable-v1.xml'] |
30 | ] | ||
31 | |||
32 | client_protos_src = [] | ||
33 | client_protos_headers = [] | ||
34 | |||
35 | server_protos_src = [] | ||
36 | server_protos_headers = [] | ||
24 | 37 | ||
25 | foreach p : protocols | 38 | foreach p : client_protocols |
26 | xml = join_paths(p) | 39 | xml = join_paths(p) |
27 | wl_protos_src += wayland_scanner_code.process(xml) | 40 | client_protos_src += wayland_scanner_code.process(xml) |
28 | wl_protos_headers += wayland_scanner_client.process(xml) | 41 | client_protos_headers += wayland_scanner_client.process(xml) |
29 | endforeach | 42 | endforeach |
30 | 43 | ||
31 | lib_wl_protos = static_library('wl_protos', wl_protos_src + wl_protos_headers, | 44 | foreach p : server_protocols |
32 | dependencies: [wayland_client]) # for the include directory | 45 | xml = join_paths(p) |
46 | server_protos_src += wayland_scanner_code.process(xml) | ||
47 | server_protos_headers += wayland_scanner_server.process(xml) | ||
48 | endforeach | ||
49 | |||
50 | lib_client_protos = static_library( | ||
51 | 'client_protos', | ||
52 | client_protos_src + client_protos_headers, | ||
53 | dependencies: [wayland_client] | ||
54 | ) # for the include directory | ||
55 | |||
56 | client_protos = declare_dependency( | ||
57 | link_with: lib_client_protos, | ||
58 | sources: client_protos_headers, | ||
59 | ) | ||
60 | |||
61 | lib_server_protos = static_library( | ||
62 | 'server_protos', | ||
63 | server_protos_src + server_protos_headers, | ||
64 | dependencies: [wayland_client] | ||
65 | ) # for the include directory | ||
33 | 66 | ||
34 | sway_protos = declare_dependency( | 67 | server_protos = declare_dependency( |
35 | link_with: lib_wl_protos, | 68 | link_with: lib_server_protos, |
36 | sources: wl_protos_headers, | 69 | sources: server_protos_headers, |
37 | ) | 70 | ) |
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..9e211861 100644 --- a/sway/config/output.c +++ b/sway/config/output.c | |||
@@ -1,7 +1,10 @@ | |||
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> | ||
7 | #include <unistd.h> | ||
5 | #include <wlr/types/wlr_output.h> | 8 | #include <wlr/types/wlr_output.h> |
6 | #include <wlr/types/wlr_output_layout.h> | 9 | #include <wlr/types/wlr_output_layout.h> |
7 | #include "sway/config.h" | 10 | #include "sway/config.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 new file mode 100644 index 00000000..bd62f84a --- /dev/null +++ b/sway/desktop/layer_shell.c | |||
@@ -0,0 +1,320 @@ | |||
1 | #include <stdbool.h> | ||
2 | #include <stdlib.h> | ||
3 | #include <string.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> | ||
8 | #include <wlr/util/log.h> | ||
9 | #include "sway/layers.h" | ||
10 | #include "sway/layout.h" | ||
11 | #include "sway/output.h" | ||
12 | #include "sway/server.h" | ||
13 | |||
14 | static void apply_exclusive(struct wlr_box *usable_area, | ||
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); | ||
190 | } | ||
191 | |||
192 | static void handle_output_destroy(struct wl_listener *listener, void *data) { | ||
193 | struct sway_layer_surface *sway_layer = | ||
194 | wl_container_of(listener, sway_layer, output_destroy); | ||
195 | wl_list_remove(&sway_layer->output_destroy.link); | ||
196 | wl_list_remove(&sway_layer->output_mode.link); | ||
197 | wl_list_remove(&sway_layer->output_transform.link); | ||
198 | sway_layer->layer_surface->output = NULL; | ||
199 | wlr_layer_surface_close(sway_layer->layer_surface); | ||
200 | } | ||
201 | |||
202 | static void handle_output_mode(struct wl_listener *listener, void *data) { | ||
203 | struct wlr_output *output = data; | ||
204 | arrange_layers((struct sway_output *)output->data); | ||
205 | } | ||
206 | |||
207 | static void handle_output_transform(struct wl_listener *listener, void *data) { | ||
208 | struct wlr_output *output = data; | ||
209 | arrange_layers((struct sway_output *)output->data); | ||
210 | } | ||
211 | |||
212 | static void handle_surface_commit(struct wl_listener *listener, void *data) { | ||
213 | struct sway_layer_surface *layer = | ||
214 | wl_container_of(listener, layer, surface_commit); | ||
215 | struct wlr_layer_surface *layer_surface = layer->layer_surface; | ||
216 | struct wlr_output *wlr_output = layer_surface->output; | ||
217 | if (wlr_output != NULL) { | ||
218 | struct sway_output *output = wlr_output->data; | ||
219 | struct wlr_box old_geo = layer->geo; | ||
220 | arrange_layers(output); | ||
221 | if (memcmp(&old_geo, &layer->geo, sizeof(struct wlr_box)) != 0) { | ||
222 | // TODO DAMAGE apply whole surface from previous and new geos | ||
223 | } else { | ||
224 | // TODO DAMAGE from surface damage | ||
225 | } | ||
226 | } | ||
227 | } | ||
228 | |||
229 | static void unmap(struct wlr_layer_surface *layer_surface) { | ||
230 | // TODO DAMAGE | ||
231 | } | ||
232 | |||
233 | static void handle_destroy(struct wl_listener *listener, void *data) { | ||
234 | struct sway_layer_surface *sway_layer = wl_container_of( | ||
235 | listener, sway_layer, destroy); | ||
236 | if (sway_layer->layer_surface->mapped) { | ||
237 | unmap(sway_layer->layer_surface); | ||
238 | } | ||
239 | wl_list_remove(&sway_layer->link); | ||
240 | wl_list_remove(&sway_layer->destroy.link); | ||
241 | wl_list_remove(&sway_layer->map.link); | ||
242 | wl_list_remove(&sway_layer->unmap.link); | ||
243 | wl_list_remove(&sway_layer->surface_commit.link); | ||
244 | if (sway_layer->layer_surface->output != NULL) { | ||
245 | wl_list_remove(&sway_layer->output_destroy.link); | ||
246 | wl_list_remove(&sway_layer->output_mode.link); | ||
247 | wl_list_remove(&sway_layer->output_transform.link); | ||
248 | } | ||
249 | struct sway_output *output = sway_layer->layer_surface->output->data; | ||
250 | arrange_layers(output); | ||
251 | free(sway_layer); | ||
252 | } | ||
253 | |||
254 | static void handle_map(struct wl_listener *listener, void *data) { | ||
255 | // TODO DAMAGE | ||
256 | } | ||
257 | |||
258 | static void handle_unmap(struct wl_listener *listener, void *data) { | ||
259 | struct sway_layer_surface *sway_layer = wl_container_of( | ||
260 | listener, sway_layer, unmap); | ||
261 | unmap(sway_layer->layer_surface); | ||
262 | } | ||
263 | |||
264 | void handle_layer_shell_surface(struct wl_listener *listener, void *data) { | ||
265 | struct wlr_layer_surface *layer_surface = data; | ||
266 | struct sway_server *server = | ||
267 | wl_container_of(listener, server, layer_shell_surface); | ||
268 | wlr_log(L_DEBUG, "new layer surface: namespace %s layer %d anchor %d " | ||
269 | "size %dx%d margin %d,%d,%d,%d", | ||
270 | layer_surface->namespace, layer_surface->layer, layer_surface->layer, | ||
271 | layer_surface->client_pending.desired_width, | ||
272 | layer_surface->client_pending.desired_height, | ||
273 | layer_surface->client_pending.margin.top, | ||
274 | layer_surface->client_pending.margin.right, | ||
275 | layer_surface->client_pending.margin.bottom, | ||
276 | layer_surface->client_pending.margin.left); | ||
277 | |||
278 | struct sway_layer_surface *sway_layer = | ||
279 | calloc(1, sizeof(struct sway_layer_surface)); | ||
280 | if (!sway_layer) { | ||
281 | return; | ||
282 | } | ||
283 | |||
284 | sway_layer->surface_commit.notify = handle_surface_commit; | ||
285 | wl_signal_add(&layer_surface->surface->events.commit, | ||
286 | &sway_layer->surface_commit); | ||
287 | |||
288 | sway_layer->output_destroy.notify = handle_output_destroy; | ||
289 | wl_signal_add(&layer_surface->output->events.destroy, | ||
290 | &sway_layer->output_destroy); | ||
291 | |||
292 | sway_layer->output_mode.notify = handle_output_mode; | ||
293 | wl_signal_add(&layer_surface->output->events.mode, | ||
294 | &sway_layer->output_mode); | ||
295 | |||
296 | sway_layer->output_transform.notify = handle_output_transform; | ||
297 | wl_signal_add(&layer_surface->output->events.transform, | ||
298 | &sway_layer->output_transform); | ||
299 | |||
300 | sway_layer->destroy.notify = handle_destroy; | ||
301 | wl_signal_add(&layer_surface->events.destroy, &sway_layer->destroy); | ||
302 | sway_layer->map.notify = handle_map; | ||
303 | wl_signal_add(&layer_surface->events.map, &sway_layer->map); | ||
304 | sway_layer->unmap.notify = handle_unmap; | ||
305 | wl_signal_add(&layer_surface->events.unmap, &sway_layer->unmap); | ||
306 | // TODO: Listen for subsurfaces | ||
307 | |||
308 | sway_layer->layer_surface = layer_surface; | ||
309 | layer_surface->data = sway_layer; | ||
310 | |||
311 | struct sway_output *output = layer_surface->output->data; | ||
312 | wl_list_insert(&output->layers[layer_surface->layer], &sway_layer->link); | ||
313 | |||
314 | // Temporarily set the layer's current state to client_pending | ||
315 | // So that we can easily arrange it | ||
316 | struct wlr_layer_surface_state old_state = layer_surface->current; | ||
317 | layer_surface->current = layer_surface->client_pending; | ||
318 | arrange_layers(output); | ||
319 | layer_surface->current = old_state; | ||
320 | } | ||
diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 6c990c47..9e7fbcc6 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" |
@@ -78,9 +81,7 @@ static void render_surface(struct wlr_surface *surface, | |||
78 | rotate_child_position(&sx, &sy, sw, sh, width, height, rotation); | 81 | rotate_child_position(&sx, &sy, sw, sh, width, height, rotation); |
79 | 82 | ||
80 | render_surface(subsurface->surface, wlr_output, when, | 83 | render_surface(subsurface->surface, wlr_output, when, |
81 | lx + sx, | 84 | lx + sx, ly + sy, rotation); |
82 | ly + sy, | ||
83 | rotation); | ||
84 | } | 85 | } |
85 | } | 86 | } |
86 | 87 | ||
@@ -139,9 +140,15 @@ static void render_wl_shell_surface(struct wlr_wl_shell_surface *surface, | |||
139 | } | 140 | } |
140 | } | 141 | } |
141 | 142 | ||
143 | struct render_data { | ||
144 | struct sway_output *output; | ||
145 | struct timespec *now; | ||
146 | }; | ||
142 | 147 | ||
143 | static void output_frame_view(swayc_t *view, void *data) { | 148 | static void output_frame_view(swayc_t *view, void *data) { |
144 | struct sway_output *output = data; | 149 | struct render_data *rdata = data; |
150 | struct sway_output *output = rdata->output; | ||
151 | struct timespec *now = rdata->now; | ||
145 | struct wlr_output *wlr_output = output->wlr_output; | 152 | struct wlr_output *wlr_output = output->wlr_output; |
146 | struct sway_view *sway_view = view->sway_view; | 153 | struct sway_view *sway_view = view->sway_view; |
147 | struct wlr_surface *surface = sway_view->surface; | 154 | struct wlr_surface *surface = sway_view->surface; |
@@ -154,29 +161,38 @@ static void output_frame_view(swayc_t *view, void *data) { | |||
154 | case SWAY_XDG_SHELL_V6_VIEW: { | 161 | case SWAY_XDG_SHELL_V6_VIEW: { |
155 | int window_offset_x = view->sway_view->wlr_xdg_surface_v6->geometry.x; | 162 | int window_offset_x = view->sway_view->wlr_xdg_surface_v6->geometry.x; |
156 | int window_offset_y = view->sway_view->wlr_xdg_surface_v6->geometry.y; | 163 | int window_offset_y = view->sway_view->wlr_xdg_surface_v6->geometry.y; |
157 | render_surface(surface, wlr_output, &output->last_frame, | 164 | render_surface(surface, wlr_output, now, |
158 | view->x - window_offset_x, | 165 | view->x - window_offset_x, view->y - window_offset_y, 0); |
159 | view->y - window_offset_y, | ||
160 | 0); | ||
161 | render_xdg_v6_popups(sway_view->wlr_xdg_surface_v6, wlr_output, | 166 | render_xdg_v6_popups(sway_view->wlr_xdg_surface_v6, wlr_output, |
162 | &output->last_frame, | 167 | now, view->x - window_offset_x, view->y - window_offset_y, 0); |
163 | view->x - window_offset_x, view->y - window_offset_y, | ||
164 | 0); | ||
165 | break; | 168 | break; |
166 | } | 169 | } |
167 | case SWAY_WL_SHELL_VIEW: | 170 | case SWAY_WL_SHELL_VIEW: |
168 | render_wl_shell_surface(sway_view->wlr_wl_shell_surface, wlr_output, | 171 | render_wl_shell_surface(sway_view->wlr_wl_shell_surface, wlr_output, |
169 | &output->last_frame, view->x, view->y, 0, false); | 172 | now, view->x, view->y, 0, false); |
170 | break; | 173 | break; |
171 | case SWAY_XWAYLAND_VIEW: | 174 | case SWAY_XWAYLAND_VIEW: |
172 | render_surface(surface, wlr_output, &output->last_frame, view->x, | 175 | render_surface(surface, wlr_output, now, view->x, view->y, 0); |
173 | view->y, 0); | ||
174 | break; | 176 | break; |
175 | default: | 177 | default: |
176 | break; | 178 | break; |
177 | } | 179 | } |
178 | } | 180 | } |
179 | 181 | ||
182 | static void render_layer(struct sway_output *output, | ||
183 | const struct wlr_box *output_layout_box, | ||
184 | struct timespec *when, | ||
185 | struct wl_list *layer) { | ||
186 | struct sway_layer_surface *sway_layer; | ||
187 | wl_list_for_each(sway_layer, layer, link) { | ||
188 | struct wlr_layer_surface *layer = sway_layer->layer_surface; | ||
189 | render_surface(layer->surface, output->wlr_output, when, | ||
190 | sway_layer->geo.x + output_layout_box->x, | ||
191 | sway_layer->geo.y + output_layout_box->y, 0); | ||
192 | wlr_surface_send_frame_done(layer->surface, when); | ||
193 | } | ||
194 | } | ||
195 | |||
180 | static void output_frame_notify(struct wl_listener *listener, void *data) { | 196 | static void output_frame_notify(struct wl_listener *listener, void *data) { |
181 | struct sway_output *soutput = wl_container_of(listener, soutput, frame); | 197 | struct sway_output *soutput = wl_container_of(listener, soutput, frame); |
182 | struct wlr_output *wlr_output = data; | 198 | struct wlr_output *wlr_output = data; |
@@ -189,13 +205,29 @@ static void output_frame_notify(struct wl_listener *listener, void *data) { | |||
189 | wlr_output_make_current(wlr_output, &buffer_age); | 205 | wlr_output_make_current(wlr_output, &buffer_age); |
190 | wlr_renderer_begin(server->renderer, wlr_output->width, wlr_output->height); | 206 | wlr_renderer_begin(server->renderer, wlr_output->width, wlr_output->height); |
191 | 207 | ||
208 | struct timespec now; | ||
209 | clock_gettime(CLOCK_MONOTONIC, &now); | ||
210 | |||
211 | struct wlr_output_layout *layout = root_container.sway_root->output_layout; | ||
212 | const struct wlr_box *output_box = wlr_output_layout_get_box( | ||
213 | layout, wlr_output); | ||
214 | |||
215 | render_layer(soutput, output_box, &now, | ||
216 | &soutput->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND]); | ||
217 | render_layer(soutput, output_box, &now, | ||
218 | &soutput->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM]); | ||
219 | |||
192 | struct sway_seat *seat = input_manager_current_seat(input_manager); | 220 | struct sway_seat *seat = input_manager_current_seat(input_manager); |
193 | swayc_t *focus = sway_seat_get_focus_inactive(seat, soutput->swayc); | 221 | swayc_t *focus = sway_seat_get_focus_inactive(seat, soutput->swayc); |
194 | swayc_t *workspace = (focus->type == C_WORKSPACE ? | 222 | swayc_t *workspace = (focus->type == C_WORKSPACE ? |
195 | focus : | 223 | focus : |
196 | swayc_parent_by_type(focus, C_WORKSPACE)); | 224 | swayc_parent_by_type(focus, C_WORKSPACE)); |
197 | 225 | ||
198 | swayc_descendants_of_type(workspace, C_VIEW, output_frame_view, soutput); | 226 | struct render_data rdata = { |
227 | .output = soutput, | ||
228 | .now = &now, | ||
229 | }; | ||
230 | swayc_descendants_of_type(workspace, C_VIEW, output_frame_view, &rdata); | ||
199 | 231 | ||
200 | // render unmanaged views on top | 232 | // render unmanaged views on top |
201 | struct sway_view *view; | 233 | struct sway_view *view; |
@@ -210,22 +242,31 @@ static void output_frame_notify(struct wl_listener *listener, void *data) { | |||
210 | } | 242 | } |
211 | } | 243 | } |
212 | 244 | ||
213 | wlr_renderer_end(server->renderer); | 245 | // TODO: Consider revising this when fullscreen windows are supported |
214 | wlr_output_swap_buffers(wlr_output, &soutput->last_frame, NULL); | 246 | render_layer(soutput, output_box, &now, |
247 | &soutput->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]); | ||
248 | render_layer(soutput, output_box, &now, | ||
249 | &soutput->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY]); | ||
215 | 250 | ||
216 | struct timespec now; | 251 | wlr_renderer_end(server->renderer); |
217 | clock_gettime(CLOCK_MONOTONIC, &now); | 252 | wlr_output_swap_buffers(wlr_output, &now, NULL); |
218 | soutput->last_frame = now; | 253 | soutput->last_frame = now; |
219 | } | 254 | } |
220 | 255 | ||
221 | static void handle_output_destroy(struct wl_listener *listener, void *data) { | 256 | static void handle_output_destroy(struct wl_listener *listener, void *data) { |
222 | struct sway_output *output = wl_container_of(listener, output, output_destroy); | 257 | struct sway_output *output = wl_container_of(listener, output, destroy); |
223 | struct wlr_output *wlr_output = data; | 258 | struct wlr_output *wlr_output = data; |
224 | wlr_log(L_DEBUG, "Output %p %s removed", wlr_output, wlr_output->name); | 259 | wlr_log(L_DEBUG, "Output %p %s removed", wlr_output, wlr_output->name); |
225 | 260 | ||
226 | destroy_output(output->swayc); | 261 | destroy_output(output->swayc); |
227 | } | 262 | } |
228 | 263 | ||
264 | static void handle_output_mode(struct wl_listener *listener, void *data) { | ||
265 | struct sway_output *output = wl_container_of(listener, output, mode); | ||
266 | arrange_layers(output); | ||
267 | arrange_windows(output->swayc, -1, -1); | ||
268 | } | ||
269 | |||
229 | void handle_new_output(struct wl_listener *listener, void *data) { | 270 | void handle_new_output(struct wl_listener *listener, void *data) { |
230 | struct sway_server *server = wl_container_of(listener, server, new_output); | 271 | struct sway_server *server = wl_container_of(listener, server, new_output); |
231 | struct wlr_output *wlr_output = data; | 272 | struct wlr_output *wlr_output = data; |
@@ -236,6 +277,7 @@ void handle_new_output(struct wl_listener *listener, void *data) { | |||
236 | return; | 277 | return; |
237 | } | 278 | } |
238 | output->wlr_output = wlr_output; | 279 | output->wlr_output = wlr_output; |
280 | wlr_output->data = output; | ||
239 | output->server = server; | 281 | output->server = server; |
240 | 282 | ||
241 | if (!wl_list_empty(&wlr_output->modes)) { | 283 | if (!wl_list_empty(&wlr_output->modes)) { |
@@ -250,13 +292,20 @@ void handle_new_output(struct wl_listener *listener, void *data) { | |||
250 | return; | 292 | return; |
251 | } | 293 | } |
252 | 294 | ||
295 | size_t len = sizeof(output->layers) / sizeof(output->layers[0]); | ||
296 | for (size_t i = 0; i < len; ++i) { | ||
297 | wl_list_init(&output->layers[i]); | ||
298 | } | ||
299 | |||
253 | sway_input_manager_configure_xcursor(input_manager); | 300 | sway_input_manager_configure_xcursor(input_manager); |
254 | 301 | ||
255 | wl_signal_add(&wlr_output->events.frame, &output->frame); | 302 | wl_signal_add(&wlr_output->events.frame, &output->frame); |
256 | output->frame.notify = output_frame_notify; | 303 | output->frame.notify = output_frame_notify; |
304 | wl_signal_add(&wlr_output->events.destroy, &output->destroy); | ||
305 | output->destroy.notify = handle_output_destroy; | ||
306 | wl_signal_add(&wlr_output->events.mode, &output->mode); | ||
307 | output->mode.notify = handle_output_mode; | ||
257 | 308 | ||
258 | wl_signal_add(&wlr_output->events.destroy, &output->output_destroy); | 309 | arrange_layers(output); |
259 | output->output_destroy.notify = handle_output_destroy; | ||
260 | |||
261 | arrange_windows(&root_container, -1, -1); | 310 | arrange_windows(&root_container, -1, -1); |
262 | } | 311 | } |
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/meson.build b/sway/meson.build index 26e56ad2..8bddb11b 100644 --- a/sway/meson.build +++ b/sway/meson.build | |||
@@ -46,6 +46,7 @@ sway_sources = files( | |||
46 | 'ipc-json.c', | 46 | 'ipc-json.c', |
47 | 'ipc-server.c', | 47 | 'ipc-server.c', |
48 | 'desktop/output.c', | 48 | 'desktop/output.c', |
49 | 'desktop/layer_shell.c', | ||
49 | 'desktop/wl_shell.c', | 50 | 'desktop/wl_shell.c', |
50 | 'desktop/xdg_shell_v6.c', | 51 | 'desktop/xdg_shell_v6.c', |
51 | 'desktop/xwayland.c', | 52 | 'desktop/xwayland.c', |
@@ -57,14 +58,15 @@ sway_sources = files( | |||
57 | ) | 58 | ) |
58 | 59 | ||
59 | sway_deps = [ | 60 | sway_deps = [ |
61 | jsonc, | ||
62 | libcap, | ||
63 | libinput, | ||
64 | math, | ||
60 | pcre, | 65 | pcre, |
61 | pixman, | 66 | pixman, |
67 | server_protos, | ||
62 | wayland_server, | 68 | wayland_server, |
63 | jsonc, | ||
64 | wlroots, | 69 | wlroots, |
65 | libcap, | ||
66 | math, | ||
67 | libinput, | ||
68 | xkbcommon, | 70 | xkbcommon, |
69 | ] | 71 | ] |
70 | 72 | ||
diff --git a/sway/server.c b/sway/server.c index ca08d7fb..92f72f13 100644 --- a/sway/server.c +++ b/sway/server.c | |||
@@ -7,6 +7,7 @@ | |||
7 | #include <wlr/render/wlr_renderer.h> | 7 | #include <wlr/render/wlr_renderer.h> |
8 | #include <wlr/render/gles2.h> | 8 | #include <wlr/render/gles2.h> |
9 | #include <wlr/types/wlr_compositor.h> | 9 | #include <wlr/types/wlr_compositor.h> |
10 | #include <wlr/types/wlr_layer_shell.h> | ||
10 | #include <wlr/types/wlr_wl_shell.h> | 11 | #include <wlr/types/wlr_wl_shell.h> |
11 | // TODO WLR: make Xwayland optional | 12 | // TODO WLR: make Xwayland optional |
12 | #include <wlr/xwayland.h> | 13 | #include <wlr/xwayland.h> |
@@ -51,6 +52,11 @@ bool server_init(struct sway_server *server) { | |||
51 | server->new_output.notify = handle_new_output; | 52 | server->new_output.notify = handle_new_output; |
52 | wl_signal_add(&server->backend->events.new_output, &server->new_output); | 53 | wl_signal_add(&server->backend->events.new_output, &server->new_output); |
53 | 54 | ||
55 | server->layer_shell = wlr_layer_shell_create(server->wl_display); | ||
56 | wl_signal_add(&server->layer_shell->events.new_surface, | ||
57 | &server->layer_shell_surface); | ||
58 | server->layer_shell_surface.notify = handle_layer_shell_surface; | ||
59 | |||
54 | server->xdg_shell_v6 = wlr_xdg_shell_v6_create(server->wl_display); | 60 | server->xdg_shell_v6 = wlr_xdg_shell_v6_create(server->wl_display); |
55 | wl_signal_add(&server->xdg_shell_v6->events.new_surface, | 61 | wl_signal_add(&server->xdg_shell_v6->events.new_surface, |
56 | &server->xdg_shell_v6_surface); | 62 | &server->xdg_shell_v6_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 | } |
diff --git a/swaybg/meson.build b/swaybg/meson.build index 5e10f3c7..8704de6d 100644 --- a/swaybg/meson.build +++ b/swaybg/meson.build | |||
@@ -4,12 +4,12 @@ executable( | |||
4 | include_directories: [sway_inc], | 4 | include_directories: [sway_inc], |
5 | dependencies: [ | 5 | dependencies: [ |
6 | cairo, | 6 | cairo, |
7 | client_protos, | ||
7 | gdk_pixbuf, | 8 | gdk_pixbuf, |
8 | jsonc, | 9 | jsonc, |
9 | math, | 10 | math, |
10 | pango, | 11 | pango, |
11 | pangocairo, | 12 | pangocairo, |
12 | sway_protos, | ||
13 | wayland_client, | 13 | wayland_client, |
14 | wlroots, | 14 | wlroots, |
15 | ], | 15 | ], |