summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/sway/config.h12
-rw-r--r--include/sway/tree/container.h2
-rw-r--r--include/sway/tree/view.h11
-rw-r--r--sway/commands.c6
-rw-r--r--sway/commands/border.c41
-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.c205
-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/view.c60
15 files changed, 452 insertions, 79 deletions
diff --git a/include/sway/config.h b/include/sway/config.h
index 87123289..a0113e98 100644
--- a/include/sway/config.h
+++ b/include/sway/config.h
@@ -204,11 +204,11 @@ struct bar_config {
204}; 204};
205 205
206struct border_colors { 206struct border_colors {
207 uint32_t border; 207 float border[4];
208 uint32_t background; 208 float background[4];
209 uint32_t text; 209 float text[4];
210 uint32_t indicator; 210 float indicator[4];
211 uint32_t child_border; 211 float child_border[4];
212}; 212};
213 213
214enum edge_border_types { 214enum edge_border_types {
@@ -338,7 +338,7 @@ struct sway_config {
338 struct border_colors unfocused; 338 struct border_colors unfocused;
339 struct border_colors urgent; 339 struct border_colors urgent;
340 struct border_colors placeholder; 340 struct border_colors placeholder;
341 uint32_t background; 341 float background[4];
342 } border_colors; 342 } border_colors;
343 343
344 // floating view 344 // floating view
diff --git a/include/sway/tree/container.h b/include/sway/tree/container.h
index 9c921fc4..d092af49 100644
--- a/include/sway/tree/container.h
+++ b/include/sway/tree/container.h
@@ -72,8 +72,8 @@ struct sway_container {
72 // For C_ROOT, this has no meaning 72 // For C_ROOT, this has no meaning
73 // For C_OUTPUT, this is the output position in layout coordinates 73 // For C_OUTPUT, this is the output position in layout coordinates
74 // For other types, this is the position in output-local coordinates 74 // For other types, this is the position in output-local coordinates
75 // Includes borders
75 double x, y; 76 double x, y;
76 // does not include borders or gaps.
77 double width, height; 77 double width, height;
78 double saved_width, saved_height; 78 double saved_width, saved_height;
79 79
diff --git a/include/sway/tree/view.h b/include/sway/tree/view.h
index a4ad9971..352a62bc 100644
--- a/include/sway/tree/view.h
+++ b/include/sway/tree/view.h
@@ -41,9 +41,16 @@ struct sway_view {
41 41
42 struct sway_container *swayc; // NULL for unmapped views 42 struct sway_container *swayc; // NULL for unmapped views
43 struct wlr_surface *surface; // NULL for unmapped views 43 struct wlr_surface *surface; // NULL for unmapped views
44
45 // Geometry of the view itself (excludes borders)
46 double x, y;
44 int width, height; 47 int width, height;
48
45 bool is_fullscreen; 49 bool is_fullscreen;
46 50
51 enum sway_container_border border;
52 int border_thickness;
53
47 union { 54 union {
48 struct wlr_xdg_surface_v6 *wlr_xdg_surface_v6; 55 struct wlr_xdg_surface_v6 *wlr_xdg_surface_v6;
49 struct wlr_xwayland_surface *wlr_xwayland_surface; 56 struct wlr_xwayland_surface *wlr_xwayland_surface;
@@ -160,6 +167,8 @@ const char *view_get_instance(struct sway_view *view);
160void view_configure(struct sway_view *view, double ox, double oy, int width, 167void view_configure(struct sway_view *view, double ox, double oy, int width,
161 int height); 168 int height);
162 169
170void view_autoconfigure(struct sway_view *view);
171
163void view_set_activated(struct sway_view *view, bool activated); 172void view_set_activated(struct sway_view *view, bool activated);
164 173
165void view_set_fullscreen_raw(struct sway_view *view, bool fullscreen); 174void view_set_fullscreen_raw(struct sway_view *view, bool fullscreen);
@@ -184,8 +193,6 @@ void view_map(struct sway_view *view, struct wlr_surface *wlr_surface);
184 193
185void view_unmap(struct sway_view *view); 194void view_unmap(struct sway_view *view);
186 195
187void view_update_position(struct sway_view *view, double ox, double oy);
188
189void view_update_size(struct sway_view *view, int width, int height); 196void view_update_size(struct sway_view *view, int width, int height);
190 197
191void view_child_init(struct sway_view_child *child, 198void view_child_init(struct sway_view_child *child,
diff --git a/sway/commands.c b/sway/commands.c
index a67bc127..575859c9 100644
--- a/sway/commands.c
+++ b/sway/commands.c
@@ -97,8 +97,13 @@ 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 },
100 { "exec", cmd_exec }, 104 { "exec", cmd_exec },
101 { "exec_always", cmd_exec_always }, 105 { "exec_always", cmd_exec_always },
106 { "default_border", cmd_default_border },
102 { "focus_follows_mouse", cmd_focus_follows_mouse }, 107 { "focus_follows_mouse", cmd_focus_follows_mouse },
103 { "for_window", cmd_for_window }, 108 { "for_window", cmd_for_window },
104 { "fullscreen", cmd_fullscreen }, 109 { "fullscreen", cmd_fullscreen },
@@ -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..873abb68
--- /dev/null
+++ b/sway/commands/border.c
@@ -0,0 +1,41 @@
1#include "log.h"
2#include "sway/commands.h"
3#include "sway/config.h"
4#include "sway/tree/container.h"
5#include "sway/tree/view.h"
6
7struct cmd_results *cmd_border(int argc, char **argv) {
8 struct cmd_results *error = NULL;
9 if ((error = checkarg(argc, "border", EXPECTED_AT_LEAST, 1))) {
10 return error;
11 }
12
13 struct sway_container *container =
14 config->handler_context.current_container;
15 if (container->type != C_VIEW) {
16 return cmd_results_new(CMD_INVALID, "border",
17 "Only views can have borders");
18 }
19 struct sway_view *view = container->sway_view;
20
21 if (strcmp(argv[0], "none") == 0) {
22 view->border = B_NONE;
23 } else if (strcmp(argv[0], "normal") == 0) {
24 view->border = B_NORMAL;
25 } else if (strcmp(argv[0], "pixel") == 0) {
26 view->border = B_PIXEL;
27 if (argc == 2) {
28 view->border_thickness = atoi(argv[1]);
29 }
30 } else if (strcmp(argv[0], "toggle") == 0) {
31 view->border = (view->border + 1) % 3;
32 } else {
33 return cmd_results_new(CMD_INVALID, "border",
34 "Expected 'border <none|normal|pixel|toggle>' "
35 "or 'border pixel <px>'");
36 }
37
38 view_autoconfigure(view);
39
40 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
41}
diff --git a/sway/commands/client.c b/sway/commands/client.c
new file mode 100644
index 00000000..ce519381
--- /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)[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..ed291450 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)[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..2511c610 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,198 @@ 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 wlr_render_rect(renderer, &box, color,
244 output->wlr_output->transform_matrix);
245
246 // Child border - right edge
247 box.x = con->x + con->width - con->sway_view->border_thickness;
248 box.y = con->y + 1;
249 box.width = con->sway_view->border_thickness;
250 box.height = con->height - 1;
251 wlr_render_rect(renderer, &box, color,
252 output->wlr_output->transform_matrix);
253
254 // Child border - bottom edge
255 box.x = con->x;
256 box.y = con->y + con->height - con->sway_view->border_thickness;
257 box.width = con->width;
258 box.height = con->sway_view->border_thickness;
259 wlr_render_rect(renderer, &box, color,
260 output->wlr_output->transform_matrix);
261
262 // Single pixel bar above title
263 memcpy(&color, colors->border, sizeof(float) * 3);
264 box.x = con->x;
265 box.y = con->y;
266 box.width = con->width;
267 box.height = 1;
268 wlr_render_rect(renderer, &box, color,
269 output->wlr_output->transform_matrix);
270
271 // Single pixel bar below title
272 box.x = con->x + con->sway_view->border_thickness;
273 box.y = con->sway_view->y - 1;
274 box.width = con->width - con->sway_view->border_thickness * 2;
275 box.height = 1;
276 wlr_render_rect(renderer, &box, color,
277 output->wlr_output->transform_matrix);
278
279 // Title background
280 memcpy(&color, colors->background, sizeof(float) * 3);
281 box.x = con->x + con->sway_view->border_thickness;
282 box.y = con->y + 1;
283 box.width = con->width - con->sway_view->border_thickness * 2;
284 box.height = con->sway_view->y - con->y - 2;
285 wlr_render_rect(renderer, &box, color,
286 output->wlr_output->transform_matrix);
287
288 // Title text
289 // TODO
290}
291
292/**
293 * Render decorations for a view with "border pixel".
294 */
295static void render_container_simple_border_pixel(struct sway_output *output,
296 struct sway_container *con, struct border_colors *colors) {
297 struct wlr_renderer *renderer =
298 wlr_backend_get_renderer(output->wlr_output->backend);
299 struct wlr_box box;
300 float color[4];
301 color[3] = con->alpha;
302
303 // Child border - left edge
304 memcpy(&color, colors->child_border, sizeof(float) * 3);
305 box.x = con->x;
306 box.y = con->y;
307 box.width = con->sway_view->border_thickness;
308 box.height = con->height;
309 wlr_render_rect(renderer, &box, color,
310 output->wlr_output->transform_matrix);
311
312 // Child border - right edge
313 box.x = con->x + con->width - con->sway_view->border_thickness;
314 box.y = con->y;
315 box.width = con->sway_view->border_thickness;
316 box.height = con->height;
317 wlr_render_rect(renderer, &box, color,
318 output->wlr_output->transform_matrix);
319
320 // Child border - top edge
321 box.x = con->x;
322 box.y = con->y;
323 box.width = con->width;
324 box.height = con->sway_view->border_thickness;
325 wlr_render_rect(renderer, &box, color,
326 output->wlr_output->transform_matrix);
327
328 // Child border - bottom edge
329 box.x = con->x;
330 box.y = con->y + con->height - con->sway_view->border_thickness;
331 box.width = con->width;
332 box.height = con->sway_view->border_thickness;
333 wlr_render_rect(renderer, &box, color,
334 output->wlr_output->transform_matrix);
335}
336
337static void render_container(struct sway_output *output,
338 struct sway_container *con);
339
340/**
341 * Render a container's children using a L_HORIZ or L_VERT layout.
342 *
343 * Wrap child views in borders and leave child containers borderless because
344 * they'll apply their own borders to their children.
345 */
346static void render_container_simple(struct sway_output *output,
347 struct sway_container *con) {
348 struct sway_seat *seat = input_manager_current_seat(input_manager);
349 struct sway_container *focus = seat_get_focus(seat);
350
351 for (int i = 0; i < con->children->length; ++i) {
352 struct sway_container *child = con->children->items[i];
353
354 if (child->type == C_VIEW) {
355 if (child->sway_view->border != B_NONE) {
356 struct border_colors *colors;
357 if (focus == child) {
358 colors = &config->border_colors.focused;
359 } else if (seat_get_focus_inactive(seat, con) == child) {
360 colors = &config->border_colors.focused_inactive;
361 } else {
362 colors = &config->border_colors.unfocused;
363 }
364
365 if (child->sway_view->border == B_NORMAL) {
366 render_container_simple_border_normal(output, child,
367 colors);
368 } else {
369 render_container_simple_border_pixel(output, child, colors);
370 }
371 }
372 render_view(child->sway_view, output);
373 } else {
374 render_container(output, child);
375 }
225 } 376 }
226 struct render_data data = { .output = output, .alpha = con->alpha }; 377}
227 output_view_for_each_surface(con->sway_view, &data.root_geo, 378
228 render_surface_iterator, &data); 379/**
380 * Render a container's children using the L_TABBED layout.
381 */
382static void render_container_tabbed(struct sway_output *output,
383 struct sway_container *con) {
384 // TODO
385}
386
387/**
388 * Render a container's children using the L_STACKED layout.
389 */
390static void render_container_stacked(struct sway_output *output,
391 struct sway_container *con) {
392 // TODO
229} 393}
230 394
231static void render_container(struct sway_output *output, 395static void render_container(struct sway_output *output,
232 struct sway_container *con) { 396 struct sway_container *con) {
233 if (con->type == C_VIEW) { // Happens if a view is fullscreened 397 switch (con->layout) {
234 render_container_iterator(con, output); 398 case L_NONE:
235 } else { 399 case L_HORIZ:
236 container_descendants(con, C_VIEW, render_container_iterator, output); 400 case L_VERT:
401 render_container_simple(output, con);
402 break;
403 case L_STACKED:
404 render_container_stacked(output, con);
405 break;
406 case L_TABBED:
407 render_container_tabbed(output, con);
408 break;
409 case L_FLOATING:
410 // TODO
411 break;
237 } 412 }
238} 413}
239 414
@@ -282,7 +457,7 @@ static void render_output(struct sway_output *output, struct timespec *when,
282 float clear_color[] = {0.0f, 0.0f, 0.0f, 1.0f}; 457 float clear_color[] = {0.0f, 0.0f, 0.0f, 1.0f};
283 wlr_renderer_clear(renderer, clear_color); 458 wlr_renderer_clear(renderer, clear_color);
284 // TODO: handle views smaller than the output 459 // TODO: handle views smaller than the output
285 render_container(output, workspace->sway_workspace->fullscreen->swayc); 460 render_view(workspace->sway_workspace->fullscreen, output);
286 461
287 if (workspace->sway_workspace->fullscreen->type == SWAY_VIEW_XWAYLAND) { 462 if (workspace->sway_workspace->fullscreen->type == SWAY_VIEW_XWAYLAND) {
288 render_unmanaged(output, 463 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/view.c b/sway/tree/view.c
index 519c3c78..26902c23 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,51 @@ void view_configure(struct sway_view *view, double ox, double oy, int width,
73 } 74 }
74} 75}
75 76
77/**
78 * Configure the view's position and size based on the swayc's position and
79 * size, taking borders into consideration.
80 */
81void view_autoconfigure(struct sway_view *view) {
82 if (!sway_assert(view->swayc,
83 "Called view_autoconfigure() on a view without a swayc")) {
84 return;
85 }
86
87 if (view->is_fullscreen) {
88 struct sway_container *output = container_parent(view->swayc, C_OUTPUT);
89 view_configure(view, 0, 0, output->width, output->height);
90 view->x = view->y = 0;
91 return;
92 }
93
94 double x, y, width, height;
95 switch (view->border) {
96 case B_NONE:
97 x = view->swayc->x;
98 y = view->swayc->y;
99 width = view->swayc->width;
100 height = view->swayc->height;
101 break;
102 case B_PIXEL:
103 x = view->swayc->x + view->border_thickness;
104 y = view->swayc->y + view->border_thickness;
105 width = view->swayc->width - view->border_thickness * 2;
106 height = view->swayc->height - view->border_thickness * 2;
107 break;
108 case B_NORMAL:
109 // TODO: Size the title bar by checking the font
110 x = view->swayc->x + view->border_thickness;
111 y = view->swayc->y + 20;
112 width = view->swayc->width - view->border_thickness * 2;
113 height = view->swayc->height - view->border_thickness - 20;
114 break;
115 }
116
117 view->x = x;
118 view->y = y;
119 view_configure(view, x, y, width, height);
120}
121
76void view_set_activated(struct sway_view *view, bool activated) { 122void view_set_activated(struct sway_view *view, bool activated) {
77 if (view->impl->set_activated) { 123 if (view->impl->set_activated) {
78 view->impl->set_activated(view, activated); 124 view->impl->set_activated(view, activated);
@@ -262,6 +308,8 @@ void view_map(struct sway_view *view, struct wlr_surface *wlr_surface) {
262 308
263 view->surface = wlr_surface; 309 view->surface = wlr_surface;
264 view->swayc = cont; 310 view->swayc = cont;
311 view->border = config->border;
312 view->border_thickness = config->border_thickness;
265 313
266 view_init_subsurfaces(view, wlr_surface); 314 view_init_subsurfaces(view, wlr_surface);
267 wl_signal_add(&wlr_surface->events.new_subsurface, 315 wl_signal_add(&wlr_surface->events.new_subsurface,
@@ -309,23 +357,13 @@ void view_unmap(struct sway_view *view) {
309 } 357 }
310} 358}
311 359
312void view_update_position(struct sway_view *view, double ox, double oy) {
313 if (view->swayc->x == ox && view->swayc->y == oy) {
314 return;
315 }
316
317 view_damage(view, true);
318 view->swayc->x = ox;
319 view->swayc->y = oy;
320 view_damage(view, true);
321}
322
323void view_update_size(struct sway_view *view, int width, int height) { 360void view_update_size(struct sway_view *view, int width, int height) {
324 if (view->width == width && view->height == height) { 361 if (view->width == width && view->height == height) {
325 return; 362 return;
326 } 363 }
327 364
328 view_damage(view, true); 365 view_damage(view, true);
366 // Should we update the swayc width/height here too?
329 view->width = width; 367 view->width = width;
330 view->height = height; 368 view->height = height;
331 view_damage(view, true); 369 view_damage(view, true);