aboutsummaryrefslogtreecommitdiffstats
path: root/sway
diff options
context:
space:
mode:
authorLibravatar emersion <contact@emersion.fr>2018-05-01 15:31:02 +0100
committerLibravatar GitHub <noreply@github.com>2018-05-01 15:31:02 +0100
commit0e51c7be449dd68025d5acd8c634f8dcacb10a16 (patch)
treec2c7e713a150c7f9a947b100e0fa4c56efb5c3b2 /sway
parentMerge pull request #1876 from RyanDwyer/view-unmap-segfault (diff)
parentRemove unnecessary pointers (diff)
downloadsway-0e51c7be449dd68025d5acd8c634f8dcacb10a16.tar.gz
sway-0e51c7be449dd68025d5acd8c634f8dcacb10a16.tar.zst
sway-0e51c7be449dd68025d5acd8c634f8dcacb10a16.zip
Merge pull request #1874 from RyanDwyer/borders
Implement borders
Diffstat (limited to 'sway')
-rw-r--r--sway/commands.c6
-rw-r--r--sway/commands/border.c48
-rw-r--r--sway/commands/client.c79
-rw-r--r--sway/commands/default_border.c27
-rw-r--r--sway/config.c71
-rw-r--r--sway/desktop/output.c235
-rw-r--r--sway/desktop/wl_shell.c1
-rw-r--r--sway/desktop/xdg_shell_v6.c1
-rw-r--r--sway/desktop/xwayland.c2
-rw-r--r--sway/meson.build3
-rw-r--r--sway/tree/arrange.c10
-rw-r--r--sway/tree/container.c14
-rw-r--r--sway/tree/view.c47
13 files changed, 483 insertions, 61 deletions
diff --git a/sway/commands.c b/sway/commands.c
index a67bc127..8abfd40b 100644
--- a/sway/commands.c
+++ b/sway/commands.c
@@ -97,6 +97,11 @@ static struct cmd_handler handlers[] = {
97 { "bar", cmd_bar }, 97 { "bar", cmd_bar },
98 { "bindcode", cmd_bindcode }, 98 { "bindcode", cmd_bindcode },
99 { "bindsym", cmd_bindsym }, 99 { "bindsym", cmd_bindsym },
100 { "client.focused", cmd_client_focused },
101 { "client.focused_inactive", cmd_client_focused_inactive },
102 { "client.unfocused", cmd_client_unfocused },
103 { "client.urgent", cmd_client_urgent },
104 { "default_border", cmd_default_border },
100 { "exec", cmd_exec }, 105 { "exec", cmd_exec },
101 { "exec_always", cmd_exec_always }, 106 { "exec_always", cmd_exec_always },
102 { "focus_follows_mouse", cmd_focus_follows_mouse }, 107 { "focus_follows_mouse", cmd_focus_follows_mouse },
@@ -162,6 +167,7 @@ static struct cmd_handler config_handlers[] = {
162 167
163/* Runtime-only commands. Keep alphabetized */ 168/* Runtime-only commands. Keep alphabetized */
164static struct cmd_handler command_handlers[] = { 169static struct cmd_handler command_handlers[] = {
170 { "border", cmd_border },
165 { "exit", cmd_exit }, 171 { "exit", cmd_exit },
166 { "focus", cmd_focus }, 172 { "focus", cmd_focus },
167 { "kill", cmd_kill }, 173 { "kill", cmd_kill },
diff --git a/sway/commands/border.c b/sway/commands/border.c
new file mode 100644
index 00000000..1eb06a21
--- /dev/null
+++ b/sway/commands/border.c
@@ -0,0 +1,48 @@
1#include "log.h"
2#include "sway/commands.h"
3#include "sway/config.h"
4#include "sway/input/cursor.h"
5#include "sway/input/input-manager.h"
6#include "sway/tree/container.h"
7#include "sway/tree/view.h"
8
9struct cmd_results *cmd_border(int argc, char **argv) {
10 struct cmd_results *error = NULL;
11 if ((error = checkarg(argc, "border", EXPECTED_AT_LEAST, 1))) {
12 return error;
13 }
14
15 struct sway_container *container =
16 config->handler_context.current_container;
17 if (container->type != C_VIEW) {
18 return cmd_results_new(CMD_INVALID, "border",
19 "Only views can have borders");
20 }
21 struct sway_view *view = container->sway_view;
22
23 if (strcmp(argv[0], "none") == 0) {
24 view->border = B_NONE;
25 } else if (strcmp(argv[0], "normal") == 0) {
26 view->border = B_NORMAL;
27 } else if (strcmp(argv[0], "pixel") == 0) {
28 view->border = B_PIXEL;
29 if (argc == 2) {
30 view->border_thickness = atoi(argv[1]);
31 }
32 } else if (strcmp(argv[0], "toggle") == 0) {
33 view->border = (view->border + 1) % 3;
34 } else {
35 return cmd_results_new(CMD_INVALID, "border",
36 "Expected 'border <none|normal|pixel|toggle>' "
37 "or 'border pixel <px>'");
38 }
39
40 view_autoconfigure(view);
41
42 struct sway_seat *seat = input_manager_current_seat(input_manager);
43 if (seat->cursor) {
44 cursor_send_pointer_motion(seat->cursor, 0);
45 }
46
47 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
48}
diff --git a/sway/commands/client.c b/sway/commands/client.c
new file mode 100644
index 00000000..156ff95c
--- /dev/null
+++ b/sway/commands/client.c
@@ -0,0 +1,79 @@
1#include "log.h"
2#include "sway/commands.h"
3#include "sway/config.h"
4#include "sway/tree/container.h"
5
6static bool parse_color(char *hexstring, float dest[static 4]) {
7 if (hexstring[0] != '#') {
8 return false;
9 }
10
11 if (strlen(hexstring) != 7) {
12 return false;
13 }
14
15 ++hexstring;
16 char *end;
17 uint32_t decimal = strtol(hexstring, &end, 16);
18
19 if (*end != '\0') {
20 return false;
21 }
22
23 dest[0] = ((decimal >> 16) & 0xff) / 255.0;
24 dest[1] = ((decimal >> 8) & 0xff) / 255.0;
25 dest[2] = (decimal & 0xff) / 255.0;
26 dest[3] = 1.0;
27 return true;
28}
29
30static struct cmd_results *handle_command(int argc, char **argv,
31 struct border_colors *class, char *cmd_name) {
32 struct cmd_results *error = NULL;
33 if ((error = checkarg(argc, cmd_name, EXPECTED_EQUAL_TO, 5))) {
34 return error;
35 }
36
37 if (!parse_color(argv[0], class->border)) {
38 return cmd_results_new(CMD_INVALID, cmd_name,
39 "Unable to parse border color");
40 }
41
42 if (!parse_color(argv[1], class->background)) {
43 return cmd_results_new(CMD_INVALID, cmd_name,
44 "Unable to parse background color");
45 }
46
47 if (!parse_color(argv[2], class->text)) {
48 return cmd_results_new(CMD_INVALID, cmd_name,
49 "Unable to parse text color");
50 }
51
52 if (!parse_color(argv[3], class->indicator)) {
53 return cmd_results_new(CMD_INVALID, cmd_name,
54 "Unable to parse indicator color");
55 }
56
57 if (!parse_color(argv[4], class->child_border)) {
58 return cmd_results_new(CMD_INVALID, cmd_name,
59 "Unable to parse child border color");
60 }
61
62 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
63}
64
65struct cmd_results *cmd_client_focused(int argc, char **argv) {
66 return handle_command(argc, argv, &config->border_colors.focused, "client.focused");
67}
68
69struct cmd_results *cmd_client_focused_inactive(int argc, char **argv) {
70 return handle_command(argc, argv, &config->border_colors.focused_inactive, "client.focused_inactive");
71}
72
73struct cmd_results *cmd_client_unfocused(int argc, char **argv) {
74 return handle_command(argc, argv, &config->border_colors.unfocused, "client.unfocused");
75}
76
77struct cmd_results *cmd_client_urgent(int argc, char **argv) {
78 return handle_command(argc, argv, &config->border_colors.urgent, "client.urgent");
79}
diff --git a/sway/commands/default_border.c b/sway/commands/default_border.c
new file mode 100644
index 00000000..fcd2c075
--- /dev/null
+++ b/sway/commands/default_border.c
@@ -0,0 +1,27 @@
1#include "log.h"
2#include "sway/commands.h"
3#include "sway/config.h"
4#include "sway/tree/container.h"
5
6struct cmd_results *cmd_default_border(int argc, char **argv) {
7 struct cmd_results *error = NULL;
8 if ((error = checkarg(argc, "default_border", EXPECTED_AT_LEAST, 1))) {
9 return error;
10 }
11
12 if (strcmp(argv[0], "none") == 0) {
13 config->border = B_NONE;
14 } else if (strcmp(argv[0], "normal") == 0) {
15 config->border = B_NORMAL;
16 } else if (strcmp(argv[0], "pixel") == 0) {
17 config->border = B_PIXEL;
18 if (argc == 2) {
19 config->border_thickness = atoi(argv[1]);
20 }
21 } else {
22 return cmd_results_new(CMD_INVALID, "default_border",
23 "Expected 'default_border <none|normal|pixel>' or 'default_border pixel <px>'");
24 }
25
26 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
27}
diff --git a/sway/config.c b/sway/config.c
index 90b833ab..f4d78e19 100644
--- a/sway/config.c
+++ b/sway/config.c
@@ -130,6 +130,13 @@ static void destroy_removed_seats(struct sway_config *old_config,
130 } 130 }
131} 131}
132 132
133static void set_color(float dest[static 4], uint32_t color) {
134 dest[0] = ((color >> 16) & 0xff) / 255.0;
135 dest[1] = ((color >> 8) & 0xff) / 255.0;
136 dest[2] = (color & 0xff) / 255.0;
137 dest[3] = 1.0;
138}
139
133static void config_defaults(struct sway_config *config) { 140static void config_defaults(struct sway_config *config) {
134 if (!(config->symbols = create_list())) goto cleanup; 141 if (!(config->symbols = create_list())) goto cleanup;
135 if (!(config->modes = create_list())) goto cleanup; 142 if (!(config->modes = create_list())) goto cleanup;
@@ -162,7 +169,6 @@ static void config_defaults(struct sway_config *config) {
162 config->default_layout = L_NONE; 169 config->default_layout = L_NONE;
163 config->default_orientation = L_NONE; 170 config->default_orientation = L_NONE;
164 if (!(config->font = strdup("monospace 10"))) goto cleanup; 171 if (!(config->font = strdup("monospace 10"))) goto cleanup;
165 // TODO: border
166 //config->font_height = get_font_text_height(config->font); 172 //config->font_height = get_font_text_height(config->font);
167 173
168 // floating view 174 // floating view
@@ -199,37 +205,38 @@ static void config_defaults(struct sway_config *config) {
199 config->hide_edge_borders = E_NONE; 205 config->hide_edge_borders = E_NONE;
200 206
201 // border colors 207 // border colors
202 config->border_colors.focused.border = 0x4C7899FF; 208 set_color(config->border_colors.focused.border, 0x4C7899);
203 config->border_colors.focused.background = 0x285577FF; 209 set_color(config->border_colors.focused.border, 0x4C7899);
204 config->border_colors.focused.text = 0xFFFFFFFF; 210 set_color(config->border_colors.focused.background, 0x285577);
205 config->border_colors.focused.indicator = 0x2E9EF4FF; 211 set_color(config->border_colors.focused.text, 0xFFFFFF);
206 config->border_colors.focused.child_border = 0x285577FF; 212 set_color(config->border_colors.focused.indicator, 0x2E9EF4);
207 213 set_color(config->border_colors.focused.child_border, 0x285577);
208 config->border_colors.focused_inactive.border = 0x333333FF; 214
209 config->border_colors.focused_inactive.background = 0x5F676AFF; 215 set_color(config->border_colors.focused_inactive.border, 0x333333);
210 config->border_colors.focused_inactive.text = 0xFFFFFFFF; 216 set_color(config->border_colors.focused_inactive.background, 0x5F676A);
211 config->border_colors.focused_inactive.indicator = 0x484E50FF; 217 set_color(config->border_colors.focused_inactive.text, 0xFFFFFF);
212 config->border_colors.focused_inactive.child_border = 0x5F676AFF; 218 set_color(config->border_colors.focused_inactive.indicator, 0x484E50);
213 219 set_color(config->border_colors.focused_inactive.child_border, 0x5F676A);
214 config->border_colors.unfocused.border = 0x333333FF; 220
215 config->border_colors.unfocused.background = 0x222222FF; 221 set_color(config->border_colors.unfocused.border, 0x333333);
216 config->border_colors.unfocused.text = 0x888888FF; 222 set_color(config->border_colors.unfocused.background, 0x222222);
217 config->border_colors.unfocused.indicator = 0x292D2EFF; 223 set_color(config->border_colors.unfocused.text, 0x888888);
218 config->border_colors.unfocused.child_border = 0x222222FF; 224 set_color(config->border_colors.unfocused.indicator, 0x292D2E);
219 225 set_color(config->border_colors.unfocused.child_border, 0x222222);
220 config->border_colors.urgent.border = 0x2F343AFF; 226
221 config->border_colors.urgent.background = 0x900000FF; 227 set_color(config->border_colors.urgent.border, 0x2F343A);
222 config->border_colors.urgent.text = 0xFFFFFFFF; 228 set_color(config->border_colors.urgent.background, 0x900000);
223 config->border_colors.urgent.indicator = 0x900000FF; 229 set_color(config->border_colors.urgent.text, 0xFFFFFF);
224 config->border_colors.urgent.child_border = 0x900000FF; 230 set_color(config->border_colors.urgent.indicator, 0x900000);
225 231 set_color(config->border_colors.urgent.child_border, 0x900000);
226 config->border_colors.placeholder.border = 0x000000FF; 232
227 config->border_colors.placeholder.background = 0x0C0C0CFF; 233 set_color(config->border_colors.placeholder.border, 0x000000);
228 config->border_colors.placeholder.text = 0xFFFFFFFF; 234 set_color(config->border_colors.placeholder.background, 0x0C0C0C);
229 config->border_colors.placeholder.indicator = 0x000000FF; 235 set_color(config->border_colors.placeholder.text, 0xFFFFFF);
230 config->border_colors.placeholder.child_border = 0x0C0C0CFF; 236 set_color(config->border_colors.placeholder.indicator, 0x000000);
231 237 set_color(config->border_colors.placeholder.child_border, 0x0C0C0C);
232 config->border_colors.background = 0xFFFFFFFF; 238
239 set_color(config->border_colors.background, 0xFFFFFF);
233 240
234 // Security 241 // Security
235 if (!(config->command_policies = create_list())) goto cleanup; 242 if (!(config->command_policies = create_list())) goto cleanup;
diff --git a/sway/desktop/output.c b/sway/desktop/output.c
index d9ae890f..e0a211d1 100644
--- a/sway/desktop/output.c
+++ b/sway/desktop/output.c
@@ -116,8 +116,8 @@ static void surface_for_each_surface(struct wlr_surface *surface,
116static void output_view_for_each_surface(struct sway_view *view, 116static void output_view_for_each_surface(struct sway_view *view,
117 struct root_geometry *geo, wlr_surface_iterator_func_t iterator, 117 struct root_geometry *geo, wlr_surface_iterator_func_t iterator,
118 void *user_data) { 118 void *user_data) {
119 geo->x = view->swayc->x; 119 geo->x = view->x;
120 geo->y = view->swayc->y; 120 geo->y = view->y;
121 geo->width = view->surface->current->width; 121 geo->width = view->surface->current->width;
122 geo->height = view->surface->current->height; 122 geo->height = view->surface->current->height;
123 geo->rotation = 0; // TODO 123 geo->rotation = 0; // TODO
@@ -217,23 +217,228 @@ static void render_unmanaged(struct sway_output *output,
217 render_surface_iterator, &data); 217 render_surface_iterator, &data);
218} 218}
219 219
220static void render_container_iterator(struct sway_container *con, 220static void render_view(struct sway_view *view, struct sway_output *output) {
221 void *_data) { 221 struct render_data data = { .output = output, .alpha = view->swayc->alpha };
222 struct sway_output *output = _data; 222 output_view_for_each_surface(
223 if (!sway_assert(con->type == C_VIEW, "expected a view")) { 223 view, &data.root_geo, render_surface_iterator, &data);
224 return; 224}
225
226/**
227 * Render decorations for a view with "border normal".
228 */
229static void render_container_simple_border_normal(struct sway_output *output,
230 struct sway_container *con, struct border_colors *colors) {
231 struct wlr_renderer *renderer =
232 wlr_backend_get_renderer(output->wlr_output->backend);
233 struct wlr_box box;
234 float color[4];
235 color[3] = con->alpha;
236
237 // Child border - left edge
238 memcpy(&color, colors->child_border, sizeof(float) * 3);
239 box.x = con->x;
240 box.y = con->y + 1;
241 box.width = con->sway_view->border_thickness;
242 box.height = con->height - 1;
243 scale_box(&box, output->wlr_output->scale);
244 wlr_render_rect(renderer, &box, color,
245 output->wlr_output->transform_matrix);
246
247 // Child border - right edge
248 if (con->parent->children->length == 1 && con->parent->layout == L_HORIZ) {
249 memcpy(&color, colors->indicator, sizeof(float) * 3);
250 } else {
251 memcpy(&color, colors->child_border, sizeof(float) * 3);
225 } 252 }
226 struct render_data data = { .output = output, .alpha = con->alpha }; 253 box.x = con->x + con->width - con->sway_view->border_thickness;
227 output_view_for_each_surface(con->sway_view, &data.root_geo, 254 box.y = con->y + 1;
228 render_surface_iterator, &data); 255 box.width = con->sway_view->border_thickness;
256 box.height = con->height - 1;
257 scale_box(&box, output->wlr_output->scale);
258 wlr_render_rect(renderer, &box, color,
259 output->wlr_output->transform_matrix);
260
261 // Child border - bottom edge
262 if (con->parent->children->length == 1 && con->parent->layout == L_VERT) {
263 memcpy(&color, colors->indicator, sizeof(float) * 3);
264 } else {
265 memcpy(&color, colors->child_border, sizeof(float) * 3);
266 }
267 box.x = con->x;
268 box.y = con->y + con->height - con->sway_view->border_thickness;
269 box.width = con->width;
270 box.height = con->sway_view->border_thickness;
271 scale_box(&box, output->wlr_output->scale);
272 wlr_render_rect(renderer, &box, color,
273 output->wlr_output->transform_matrix);
274
275 // Single pixel bar above title
276 memcpy(&color, colors->border, sizeof(float) * 3);
277 box.x = con->x;
278 box.y = con->y;
279 box.width = con->width;
280 box.height = 1;
281 scale_box(&box, output->wlr_output->scale);
282 wlr_render_rect(renderer, &box, color,
283 output->wlr_output->transform_matrix);
284
285 // Single pixel bar below title
286 box.x = con->x + con->sway_view->border_thickness;
287 box.y = con->sway_view->y - 1;
288 box.width = con->width - con->sway_view->border_thickness * 2;
289 box.height = 1;
290 scale_box(&box, output->wlr_output->scale);
291 wlr_render_rect(renderer, &box, color,
292 output->wlr_output->transform_matrix);
293
294 // Title background
295 memcpy(&color, colors->background, sizeof(float) * 3);
296 box.x = con->x + con->sway_view->border_thickness;
297 box.y = con->y + 1;
298 box.width = con->width - con->sway_view->border_thickness * 2;
299 box.height = con->sway_view->y - con->y - 2;
300 scale_box(&box, output->wlr_output->scale);
301 wlr_render_rect(renderer, &box, color,
302 output->wlr_output->transform_matrix);
303
304 // Title text
305 // TODO
306}
307
308/**
309 * Render decorations for a view with "border pixel".
310 */
311static void render_container_simple_border_pixel(struct sway_output *output,
312 struct sway_container *con, struct border_colors *colors) {
313 struct wlr_renderer *renderer =
314 wlr_backend_get_renderer(output->wlr_output->backend);
315 struct wlr_box box;
316 float color[4];
317 color[3] = con->alpha;
318
319 // Child border - left edge
320 memcpy(&color, colors->child_border, sizeof(float) * 3);
321 box.x = con->x;
322 box.y = con->y;
323 box.width = con->sway_view->border_thickness;
324 box.height = con->height;
325 scale_box(&box, output->wlr_output->scale);
326 wlr_render_rect(renderer, &box, color,
327 output->wlr_output->transform_matrix);
328
329 // Child border - right edge
330 if (con->parent->children->length == 1 && con->parent->layout == L_HORIZ) {
331 memcpy(&color, colors->indicator, sizeof(float) * 3);
332 } else {
333 memcpy(&color, colors->child_border, sizeof(float) * 3);
334 }
335 box.x = con->x + con->width - con->sway_view->border_thickness;
336 box.y = con->y;
337 box.width = con->sway_view->border_thickness;
338 box.height = con->height;
339 scale_box(&box, output->wlr_output->scale);
340 wlr_render_rect(renderer, &box, color,
341 output->wlr_output->transform_matrix);
342
343 // Child border - top edge
344 box.x = con->x;
345 box.y = con->y;
346 box.width = con->width;
347 box.height = con->sway_view->border_thickness;
348 scale_box(&box, output->wlr_output->scale);
349 wlr_render_rect(renderer, &box, color,
350 output->wlr_output->transform_matrix);
351
352 // Child border - bottom edge
353 if (con->parent->children->length == 1 && con->parent->layout == L_VERT) {
354 memcpy(&color, colors->indicator, sizeof(float) * 3);
355 } else {
356 memcpy(&color, colors->child_border, sizeof(float) * 3);
357 }
358 box.x = con->x;
359 box.y = con->y + con->height - con->sway_view->border_thickness;
360 box.width = con->width;
361 box.height = con->sway_view->border_thickness;
362 scale_box(&box, output->wlr_output->scale);
363 wlr_render_rect(renderer, &box, color,
364 output->wlr_output->transform_matrix);
229} 365}
230 366
231static void render_container(struct sway_output *output, 367static void render_container(struct sway_output *output,
368 struct sway_container *con);
369
370/**
371 * Render a container's children using a L_HORIZ or L_VERT layout.
372 *
373 * Wrap child views in borders and leave child containers borderless because
374 * they'll apply their own borders to their children.
375 */
376static void render_container_simple(struct sway_output *output,
232 struct sway_container *con) { 377 struct sway_container *con) {
233 if (con->type == C_VIEW) { // Happens if a view is fullscreened 378 struct sway_seat *seat = input_manager_current_seat(input_manager);
234 render_container_iterator(con, output); 379 struct sway_container *focus = seat_get_focus(seat);
235 } else { 380
236 container_descendants(con, C_VIEW, render_container_iterator, output); 381 for (int i = 0; i < con->children->length; ++i) {
382 struct sway_container *child = con->children->items[i];
383
384 if (child->type == C_VIEW) {
385 if (child->sway_view->border != B_NONE) {
386 struct border_colors *colors;
387 if (focus == child) {
388 colors = &config->border_colors.focused;
389 } else if (seat_get_focus_inactive(seat, con) == child) {
390 colors = &config->border_colors.focused_inactive;
391 } else {
392 colors = &config->border_colors.unfocused;
393 }
394
395 if (child->sway_view->border == B_NORMAL) {
396 render_container_simple_border_normal(output, child,
397 colors);
398 } else {
399 render_container_simple_border_pixel(output, child, colors);
400 }
401 }
402 render_view(child->sway_view, output);
403 } else {
404 render_container(output, child);
405 }
406 }
407}
408
409/**
410 * Render a container's children using the L_TABBED layout.
411 */
412static void render_container_tabbed(struct sway_output *output,
413 struct sway_container *con) {
414 // TODO
415}
416
417/**
418 * Render a container's children using the L_STACKED layout.
419 */
420static void render_container_stacked(struct sway_output *output,
421 struct sway_container *con) {
422 // TODO
423}
424
425static void render_container(struct sway_output *output,
426 struct sway_container *con) {
427 switch (con->layout) {
428 case L_NONE:
429 case L_HORIZ:
430 case L_VERT:
431 render_container_simple(output, con);
432 break;
433 case L_STACKED:
434 render_container_stacked(output, con);
435 break;
436 case L_TABBED:
437 render_container_tabbed(output, con);
438 break;
439 case L_FLOATING:
440 // TODO
441 break;
237 } 442 }
238} 443}
239 444
@@ -282,7 +487,7 @@ static void render_output(struct sway_output *output, struct timespec *when,
282 float clear_color[] = {0.0f, 0.0f, 0.0f, 1.0f}; 487 float clear_color[] = {0.0f, 0.0f, 0.0f, 1.0f};
283 wlr_renderer_clear(renderer, clear_color); 488 wlr_renderer_clear(renderer, clear_color);
284 // TODO: handle views smaller than the output 489 // TODO: handle views smaller than the output
285 render_container(output, workspace->sway_workspace->fullscreen->swayc); 490 render_view(workspace->sway_workspace->fullscreen, output);
286 491
287 if (workspace->sway_workspace->fullscreen->type == SWAY_VIEW_XWAYLAND) { 492 if (workspace->sway_workspace->fullscreen->type == SWAY_VIEW_XWAYLAND) {
288 render_unmanaged(output, 493 render_unmanaged(output,
diff --git a/sway/desktop/wl_shell.c b/sway/desktop/wl_shell.c
index 2d666d95..e97a898e 100644
--- a/sway/desktop/wl_shell.c
+++ b/sway/desktop/wl_shell.c
@@ -40,7 +40,6 @@ static void configure(struct sway_view *view, double ox, double oy, int width,
40 if (wl_shell_view == NULL) { 40 if (wl_shell_view == NULL) {
41 return; 41 return;
42 } 42 }
43 view_update_position(view, ox, oy);
44 wl_shell_view->pending_width = width; 43 wl_shell_view->pending_width = width;
45 wl_shell_view->pending_height = height; 44 wl_shell_view->pending_height = height;
46 wlr_wl_shell_surface_configure(view->wlr_wl_shell_surface, 0, width, height); 45 wlr_wl_shell_surface_configure(view->wlr_wl_shell_surface, 0, width, height);
diff --git a/sway/desktop/xdg_shell_v6.c b/sway/desktop/xdg_shell_v6.c
index 2aaedd6c..94556231 100644
--- a/sway/desktop/xdg_shell_v6.c
+++ b/sway/desktop/xdg_shell_v6.c
@@ -102,7 +102,6 @@ static void configure(struct sway_view *view, double ox, double oy, int width,
102 return; 102 return;
103 } 103 }
104 104
105 view_update_position(view, ox, oy);
106 xdg_shell_v6_view->pending_width = width; 105 xdg_shell_v6_view->pending_width = width;
107 xdg_shell_v6_view->pending_height = height; 106 xdg_shell_v6_view->pending_height = height;
108 wlr_xdg_toplevel_v6_set_size(view->wlr_xdg_surface_v6, width, height); 107 wlr_xdg_toplevel_v6_set_size(view->wlr_xdg_surface_v6, width, height);
diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c
index aa9e1797..28f93d6e 100644
--- a/sway/desktop/xwayland.c
+++ b/sway/desktop/xwayland.c
@@ -163,8 +163,6 @@ static void configure(struct sway_view *view, double ox, double oy, int width,
163 return; 163 return;
164 } 164 }
165 165
166 view_update_position(view, ox, oy);
167
168 xwayland_view->pending_width = width; 166 xwayland_view->pending_width = width;
169 xwayland_view->pending_height = height; 167 xwayland_view->pending_height = height;
170 wlr_xwayland_surface_configure(xsurface, ox + loutput->x, oy + loutput->y, 168 wlr_xwayland_surface_configure(xsurface, ox + loutput->x, oy + loutput->y,
diff --git a/sway/meson.build b/sway/meson.build
index 146ad4b8..83e8e656 100644
--- a/sway/meson.build
+++ b/sway/meson.build
@@ -29,6 +29,9 @@ sway_sources = files(
29 'commands/assign.c', 29 'commands/assign.c',
30 'commands/bar.c', 30 'commands/bar.c',
31 'commands/bind.c', 31 'commands/bind.c',
32 'commands/border.c',
33 'commands/client.c',
34 'commands/default_border.c',
32 'commands/default_orientation.c', 35 'commands/default_orientation.c',
33 'commands/exit.c', 36 'commands/exit.c',
34 'commands/exec.c', 37 'commands/exec.c',
diff --git a/sway/tree/arrange.c b/sway/tree/arrange.c
index e1f3ad13..83bb20fb 100644
--- a/sway/tree/arrange.c
+++ b/sway/tree/arrange.c
@@ -174,12 +174,7 @@ void arrange_children_of(struct sway_container *parent) {
174 } 174 }
175 if (workspace->sway_workspace->fullscreen) { 175 if (workspace->sway_workspace->fullscreen) {
176 // Just arrange the fullscreen view and jump out 176 // Just arrange the fullscreen view and jump out
177 struct sway_container *view = 177 view_autoconfigure(workspace->sway_workspace->fullscreen);
178 workspace->sway_workspace->fullscreen->swayc;
179 view_configure(view->sway_view, 0, 0,
180 workspace->parent->width, workspace->parent->height);
181 view->width = workspace->parent->width;
182 view->height = workspace->parent->height;
183 return; 178 return;
184 } 179 }
185 180
@@ -204,8 +199,7 @@ void arrange_children_of(struct sway_container *parent) {
204 for (int i = 0; i < parent->children->length; ++i) { 199 for (int i = 0; i < parent->children->length; ++i) {
205 struct sway_container *child = parent->children->items[i]; 200 struct sway_container *child = parent->children->items[i];
206 if (child->type == C_VIEW) { 201 if (child->type == C_VIEW) {
207 view_configure(child->sway_view, child->x, child->y, 202 view_autoconfigure(child->sway_view);
208 child->width, child->height);
209 } else { 203 } else {
210 arrange_children_of(child); 204 arrange_children_of(child);
211 } 205 }
diff --git a/sway/tree/container.c b/sway/tree/container.c
index 03d7e49c..995da5ce 100644
--- a/sway/tree/container.c
+++ b/sway/tree/container.c
@@ -423,8 +423,8 @@ struct sway_container *container_at(struct sway_container *parent,
423 soutput->sway_output->wlr_output); 423 soutput->sway_output->wlr_output);
424 double ox = lx - output_box->x; 424 double ox = lx - output_box->x;
425 double oy = ly - output_box->y; 425 double oy = ly - output_box->y;
426 double view_sx = ox - swayc->x; 426 double view_sx = ox - sview->x;
427 double view_sy = oy - swayc->y; 427 double view_sy = oy - sview->y;
428 428
429 double _sx, _sy; 429 double _sx, _sy;
430 struct wlr_surface *_surface; 430 struct wlr_surface *_surface;
@@ -455,6 +455,16 @@ struct sway_container *container_at(struct sway_container *parent,
455 *surface = _surface; 455 *surface = _surface;
456 return swayc; 456 return swayc;
457 } 457 }
458 // Check the view's decorations
459 struct wlr_box swayc_box = {
460 .x = swayc->x,
461 .y = swayc->y,
462 .width = swayc->width,
463 .height = swayc->height,
464 };
465 if (wlr_box_contains_point(&swayc_box, ox, oy)) {
466 return swayc;
467 }
458 } else { 468 } else {
459 list_cat(queue, swayc->children); 469 list_cat(queue, swayc->children);
460 } 470 }
diff --git a/sway/tree/view.c b/sway/tree/view.c
index 519c3c78..05a9b277 100644
--- a/sway/tree/view.c
+++ b/sway/tree/view.c
@@ -1,5 +1,6 @@
1#include <stdlib.h> 1#include <stdlib.h>
2#include <wayland-server.h> 2#include <wayland-server.h>
3#include <wlr/render/wlr_renderer.h>
3#include <wlr/types/wlr_output_layout.h> 4#include <wlr/types/wlr_output_layout.h>
4#include "log.h" 5#include "log.h"
5#include "sway/criteria.h" 6#include "sway/criteria.h"
@@ -73,6 +74,47 @@ void view_configure(struct sway_view *view, double ox, double oy, int width,
73 } 74 }
74} 75}
75 76
77void view_autoconfigure(struct sway_view *view) {
78 if (!sway_assert(view->swayc,
79 "Called view_autoconfigure() on a view without a swayc")) {
80 return;
81 }
82
83 if (view->is_fullscreen) {
84 struct sway_container *output = container_parent(view->swayc, C_OUTPUT);
85 view_configure(view, 0, 0, output->width, output->height);
86 view->x = view->y = 0;
87 return;
88 }
89
90 double x, y, width, height;
91 switch (view->border) {
92 case B_NONE:
93 x = view->swayc->x;
94 y = view->swayc->y;
95 width = view->swayc->width;
96 height = view->swayc->height;
97 break;
98 case B_PIXEL:
99 x = view->swayc->x + view->border_thickness;
100 y = view->swayc->y + view->border_thickness;
101 width = view->swayc->width - view->border_thickness * 2;
102 height = view->swayc->height - view->border_thickness * 2;
103 break;
104 case B_NORMAL:
105 // TODO: Size the title bar by checking the font
106 x = view->swayc->x + view->border_thickness;
107 y = view->swayc->y + 20;
108 width = view->swayc->width - view->border_thickness * 2;
109 height = view->swayc->height - view->border_thickness - 20;
110 break;
111 }
112
113 view->x = x;
114 view->y = y;
115 view_configure(view, x, y, width, height);
116}
117
76void view_set_activated(struct sway_view *view, bool activated) { 118void view_set_activated(struct sway_view *view, bool activated) {
77 if (view->impl->set_activated) { 119 if (view->impl->set_activated) {
78 view->impl->set_activated(view, activated); 120 view->impl->set_activated(view, activated);
@@ -262,6 +304,8 @@ void view_map(struct sway_view *view, struct wlr_surface *wlr_surface) {
262 304
263 view->surface = wlr_surface; 305 view->surface = wlr_surface;
264 view->swayc = cont; 306 view->swayc = cont;
307 view->border = config->border;
308 view->border_thickness = config->border_thickness;
265 309
266 view_init_subsurfaces(view, wlr_surface); 310 view_init_subsurfaces(view, wlr_surface);
267 wl_signal_add(&wlr_surface->events.new_subsurface, 311 wl_signal_add(&wlr_surface->events.new_subsurface,
@@ -314,6 +358,8 @@ void view_update_position(struct sway_view *view, double ox, double oy) {
314 return; 358 return;
315 } 359 }
316 360
361 // TODO: Only allow this if the view is floating (this function will only be
362 // called in response to wayland clients wanting to reposition themselves).
317 view_damage(view, true); 363 view_damage(view, true);
318 view->swayc->x = ox; 364 view->swayc->x = ox;
319 view->swayc->y = oy; 365 view->swayc->y = oy;
@@ -326,6 +372,7 @@ void view_update_size(struct sway_view *view, int width, int height) {
326 } 372 }
327 373
328 view_damage(view, true); 374 view_damage(view, true);
375 // Should we update the swayc width/height here too?
329 view->width = width; 376 view->width = width;
330 view->height = height; 377 view->height = height;
331 view_damage(view, true); 378 view_damage(view, true);