summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar Mikkel Oscar Lyderik <mikkeloscar@gmail.com>2016-03-29 14:47:30 +0200
committerLibravatar Mikkel Oscar Lyderik <mikkeloscar@gmail.com>2016-03-30 00:47:58 +0200
commit5a13cb0ed136906a4370235214601b0129548c49 (patch)
tree51dce6cdcb9bb1ffe27dcdc9a01ca9bda3a7c87a
parentAdd border <none|normal|toggle|pixel> config (diff)
downloadsway-5a13cb0ed136906a4370235214601b0129548c49.tar.gz
sway-5a13cb0ed136906a4370235214601b0129548c49.tar.zst
sway-5a13cb0ed136906a4370235214601b0129548c49.zip
Implement borders
The borders are implemented as a surface/buffer attached to each view which is sent to and rendered by wlc in the view_pre_render callback. All the drawing logic is handled in sway/border.c and all the logic for calculating the geometry of the border/view is handled in `update_geometry` in sway/layout.c (same place as gaps are calculated).
-rw-r--r--include/border.h (renamed from include/render.h)5
-rw-r--r--include/config.h1
-rw-r--r--include/container.h17
-rw-r--r--sway/CMakeLists.txt3
-rw-r--r--sway/border.c247
-rw-r--r--sway/commands.c29
-rw-r--r--sway/config.c2
-rw-r--r--sway/container.c22
-rw-r--r--sway/focus.c3
-rw-r--r--sway/handlers.c17
-rw-r--r--sway/layout.c76
-rw-r--r--sway/render.c113
12 files changed, 386 insertions, 149 deletions
diff --git a/include/render.h b/include/border.h
index c3d1ca87..63cd63d2 100644
--- a/include/render.h
+++ b/include/border.h
@@ -1,9 +1,10 @@
1#ifndef _SWAY_RENDER_H 1#ifndef _SWAY_BORDER_H
2#define _SWAY_RENDER_H 2#define _SWAY_BORDER_H
3#include <wlc/wlc.h> 3#include <wlc/wlc.h>
4#include "container.h" 4#include "container.h"
5 5
6void render_view_borders(wlc_handle view); 6void render_view_borders(wlc_handle view);
7void update_view_border(swayc_t *view); 7void update_view_border(swayc_t *view);
8int get_font_text_height(const char *font);
8 9
9#endif 10#endif
diff --git a/include/config.h b/include/config.h
index a35cfd0a..fb84423c 100644
--- a/include/config.h
+++ b/include/config.h
@@ -184,6 +184,7 @@ struct sway_config {
184 enum swayc_layouts default_orientation; 184 enum swayc_layouts default_orientation;
185 enum swayc_layouts default_layout; 185 enum swayc_layouts default_layout;
186 char *font; 186 char *font;
187 int font_height;
187 188
188 // Flags 189 // Flags
189 bool focus_follows_mouse; 190 bool focus_follows_mouse;
diff --git a/include/container.h b/include/container.h
index 07514c8a..26da851e 100644
--- a/include/container.h
+++ b/include/container.h
@@ -115,15 +115,16 @@ struct sway_container {
115 * If this container's children include a fullscreen view, this is that view. 115 * If this container's children include a fullscreen view, this is that view.
116 */ 116 */
117 struct sway_container *fullscreen; 117 struct sway_container *fullscreen;
118 /** 118 /**
119 * If this container is a view, this may be set to the window's decoration 119 * If this container is a view, this may be set to the window's decoration
120 * buffer (or NULL). 120 * buffer (or NULL).
121 */ 121 */
122 unsigned char *border; 122 unsigned char *border;
123 enum swayc_border_types border_type; 123 enum swayc_border_types border_type;
124 struct wlc_geometry border_geometry; 124 struct wlc_geometry border_geometry;
125 struct wlc_geometry presumed_geometry; 125 struct wlc_geometry title_bar_geometry;
126 int border_thickness; 126 struct wlc_geometry actual_geometry;
127 int border_thickness;
127}; 128};
128 129
129enum visibility_mask { 130enum visibility_mask {
diff --git a/sway/CMakeLists.txt b/sway/CMakeLists.txt
index 6c62d676..51f27a05 100644
--- a/sway/CMakeLists.txt
+++ b/sway/CMakeLists.txt
@@ -26,7 +26,7 @@ add_executable(sway
26 output.c 26 output.c
27 resize.c 27 resize.c
28 workspace.c 28 workspace.c
29 render.c 29 border.c
30) 30)
31 31
32add_definitions( 32add_definitions(
@@ -36,6 +36,7 @@ add_definitions(
36target_link_libraries(sway 36target_link_libraries(sway
37 sway-common 37 sway-common
38 sway-protocols 38 sway-protocols
39 sway-wayland
39 ${WLC_LIBRARIES} 40 ${WLC_LIBRARIES}
40 ${XKBCOMMON_LIBRARIES} 41 ${XKBCOMMON_LIBRARIES}
41 ${PCRE_LIBRARIES} 42 ${PCRE_LIBRARIES}
diff --git a/sway/border.c b/sway/border.c
new file mode 100644
index 00000000..8c9106e4
--- /dev/null
+++ b/sway/border.c
@@ -0,0 +1,247 @@
1#include "border.h"
2#include <wlc/wlc-render.h>
3#include <cairo/cairo.h>
4#include <pango/pangocairo.h>
5#include <stdlib.h>
6#include <stdio.h>
7#include "container.h"
8#include "config.h"
9#include "client/pango.h"
10
11void cairo_set_source_u32(cairo_t *cairo, uint32_t color) {
12 int endian = 1;
13 if (*(char *)&endian == 1) {
14 cairo_set_source_rgba(cairo,
15 (color >> (1*8) & 0xFF) / 255.0,
16 (color >> (2*8) & 0xFF) / 255.0,
17 (color >> (3*8) & 0xFF) / 255.0,
18 (color >> (0*8) & 0xFF) / 255.0);
19 } else {
20 cairo_set_source_rgba(cairo,
21 (color >> (0*8) & 0xFF) / 255.0,
22 (color >> (3*8) & 0xFF) / 255.0,
23 (color >> (2*8) & 0xFF) / 255.0,
24 (color >> (1*8) & 0xFF) / 255.0);
25 }
26}
27
28static cairo_t *create_border_buffer(swayc_t *view, struct wlc_geometry geo, cairo_surface_t **surface) {
29 cairo_t *cr;
30 view->border_geometry = geo;
31 int stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, geo.size.w);
32 view->border = calloc(stride * geo.size.h, sizeof(unsigned char));
33 if (!view->border) {
34 sway_log(L_DEBUG, "Unable to allocate buffer");
35 return NULL;
36 }
37 *surface = cairo_image_surface_create_for_data(view->border,
38 CAIRO_FORMAT_ARGB32, geo.size.w, geo.size.h, stride);
39 if (cairo_surface_status(*surface) != CAIRO_STATUS_SUCCESS) {
40 free(view->border);
41 view->border = NULL;
42 sway_log(L_DEBUG, "Unable to allocate surface");
43 return NULL;
44 }
45 cr = cairo_create(*surface);
46 if (cairo_status(cr) != CAIRO_STATUS_SUCCESS) {
47 cairo_surface_destroy(*surface);
48 free(view->border);
49 view->border = NULL;
50 sway_log(L_DEBUG, "Unable to create cairo context");
51 return NULL;
52 }
53 return cr;
54}
55
56// TODO: move to client/cairo.h when local set_source_u32 is fixed.
57/**
58 * Renders a sharp line of any width and height.
59 *
60 * The line is drawn from (x,y) to (x+width,y+height) where width/height is 0
61 * if the line has a width/height of one pixel, respectively.
62 */
63static void render_sharp_line(cairo_t *cairo, uint32_t color, double x, double y, double width, double height) {
64 cairo_set_source_u32(cairo, color);
65
66 if (width > 1 && height > 1) {
67 cairo_rectangle(cairo, x, y, width, height);
68 cairo_fill(cairo);
69 } else {
70 if (width == 1) {
71 x += 0.5;
72 height += y;
73 width = x;
74 }
75
76 if (height == 1) {
77 y += 0.5;
78 width += x;
79 height = y;
80 }
81
82 cairo_move_to(cairo, x, y);
83 cairo_set_line_width(cairo, 1.0);
84 cairo_line_to(cairo, width, height);
85 cairo_stroke(cairo);
86 }
87}
88
89int get_font_text_height(const char *font) {
90 cairo_surface_t *surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 200, 200);
91 cairo_t *cr = cairo_create(surface);
92 int width, height;
93 get_text_size(cr, font, &width, &height, "Gg");
94 return height;
95}
96
97static void render_borders(swayc_t *view, cairo_t *cr, struct border_colors *colors) {
98 struct wlc_geometry *b = &view->border_geometry;
99 struct wlc_geometry *v = &view->actual_geometry;
100
101 // left border
102 int left_border = v->origin.x - b->origin.x;
103 if (left_border > 0) {
104 render_sharp_line(cr,
105 colors->child_border,
106 0, 0,
107 left_border,
108 b->size.h);
109 }
110
111 // right border
112 int right_border = b->size.w - v->size.w - left_border;
113 if (right_border > 0) {
114 render_sharp_line(cr,
115 colors->child_border,
116 b->size.w - right_border,
117 0,
118 right_border,
119 b->size.h);
120 }
121
122 // top border
123 int top_border = v->origin.y - b->origin.y;
124 if (top_border > 0) {
125 render_sharp_line(cr,
126 colors->child_border,
127 0, 0,
128 b->size.w,
129 top_border);
130 }
131
132 // bottom border
133 int bottom_border = b->size.h - (top_border + v->size.h);
134 if (bottom_border > 0) {
135 render_sharp_line(cr,
136 colors->child_border,
137 0,
138 b->size.h - bottom_border,
139 b->size.w,
140 bottom_border);
141 }
142}
143
144static void render_with_title_bar(swayc_t *view, cairo_t *cr, struct border_colors *colors) {
145 struct wlc_geometry *tb = &view->title_bar_geometry;
146 struct wlc_geometry *b = &view->border_geometry;
147
148 // borders
149 render_borders(view, cr, colors);
150
151 // title bar background
152 cairo_set_source_u32(cr, colors->child_border);
153 cairo_rectangle(cr, 0, 0, tb->size.w, tb->size.h);
154 cairo_fill(cr);
155
156 // header top line
157 render_sharp_line(cr, colors->border, 0, 0, tb->size.w, 1);
158
159 // text
160 int width, height;
161 get_text_size(cr, config->font, &width, &height, "%s", view->name);
162 cairo_move_to(cr, view->border_thickness, 2);
163 cairo_set_source_u32(cr, colors->text);
164 pango_printf(cr, config->font, "%s", view->name);
165
166 // header bottom line
167 render_sharp_line(cr, colors->border,
168 view->actual_geometry.origin.x - b->origin.x,
169 tb->size.h - 1,
170 view->actual_geometry.size.w, 1);
171}
172
173void update_view_border(swayc_t *view) {
174 cairo_t *cr = NULL;
175 cairo_surface_t *surface = NULL;
176
177 if (view->border) {
178 free(view->border);
179 view->border = NULL;
180 }
181
182 swayc_t *focused = get_focused_view(&root_container);
183 swayc_t *container = swayc_parent_by_type(view, C_CONTAINER);
184 swayc_t *focused_inactive = NULL;
185 if (container) {
186 focused_inactive = swayc_focus_by_type(container, C_VIEW);
187 } else {
188 container = swayc_parent_by_type(view, C_WORKSPACE);
189 if (container) {
190 focused_inactive = swayc_focus_by_type(container, C_VIEW);
191 }
192 }
193
194 switch (view->border_type) {
195 case B_NONE:
196 break;
197 case B_PIXEL:
198 cr = create_border_buffer(view, view->border_geometry, &surface);
199 if (!cr) {
200 break;
201 }
202
203 if (focused == view) {
204 render_borders(view, cr, &config->border_colors.focused);
205 } else if (focused_inactive == view) {
206 render_borders(view, cr, &config->border_colors.focused_inactive);
207 } else {
208 render_borders(view, cr, &config->border_colors.unfocused);
209 }
210
211 break;
212 case B_NORMAL:
213 cr = create_border_buffer(view, view->border_geometry, &surface);
214 if (!cr) {
215 break;
216 }
217
218 if (focused == view) {
219 render_with_title_bar(view, cr, &config->border_colors.focused);
220 } else if (focused_inactive == view) {
221 render_with_title_bar(view, cr, &config->border_colors.focused_inactive);
222 } else {
223 render_with_title_bar(view, cr, &config->border_colors.unfocused);
224 }
225
226 break;
227 }
228 if (surface) {
229 cairo_surface_flush(surface);
230 cairo_surface_destroy(surface);
231 }
232 if (cr) {
233 cairo_destroy(cr);
234 }
235}
236
237void render_view_borders(wlc_handle view) {
238 swayc_t *c = swayc_by_handle(view);
239
240 if (!c || c->border_type == B_NONE) {
241 return;
242 }
243
244 if (c->border) {
245 wlc_pixels_write(WLC_RGBA8888, &c->border_geometry, c->border);
246 }
247}
diff --git a/sway/commands.c b/sway/commands.c
index bc182cee..c53b13c3 100644
--- a/sway/commands.c
+++ b/sway/commands.c
@@ -31,6 +31,7 @@
31#include "ipc-server.h" 31#include "ipc-server.h"
32#include "list.h" 32#include "list.h"
33#include "input.h" 33#include "input.h"
34#include "border.h"
34 35
35typedef struct cmd_results *sway_cmd(int argc, char **argv); 36typedef struct cmd_results *sway_cmd(int argc, char **argv);
36 37
@@ -359,6 +360,14 @@ static struct cmd_results *cmd_border(int argc, char **argv) {
359 } 360 }
360 361
361 enum swayc_border_types border = config->border; 362 enum swayc_border_types border = config->border;
363 int thickness = config->border_thickness;
364
365 swayc_t *view = NULL;
366 if (config->active) {
367 view = get_focused_view(&root_container);
368 border = view->border_type;
369 thickness = view->border_thickness;
370 }
362 371
363 if (strcasecmp(argv[0], "none") == 0) { 372 if (strcasecmp(argv[0], "none") == 0) {
364 border = B_NONE; 373 border = B_NONE;
@@ -367,7 +376,7 @@ static struct cmd_results *cmd_border(int argc, char **argv) {
367 } else if (strcasecmp(argv[0], "pixel") == 0) { 376 } else if (strcasecmp(argv[0], "pixel") == 0) {
368 border = B_PIXEL; 377 border = B_PIXEL;
369 } else if (strcasecmp(argv[0], "toggle") == 0) { 378 } else if (strcasecmp(argv[0], "toggle") == 0) {
370 switch (config->border) { 379 switch (border) {
371 case B_NONE: 380 case B_NONE:
372 border = B_PIXEL; 381 border = B_PIXEL;
373 break; 382 break;
@@ -383,16 +392,24 @@ static struct cmd_results *cmd_border(int argc, char **argv) {
383 "Expected 'border <normal|pixel|none|toggle>"); 392 "Expected 'border <normal|pixel|none|toggle>");
384 } 393 }
385 394
395
386 if (argc == 2 && (border == B_NORMAL || border == B_PIXEL)) { 396 if (argc == 2 && (border == B_NORMAL || border == B_PIXEL)) {
387 int thickness = (int)strtol(argv[1], NULL, 10); 397 thickness = (int)strtol(argv[1], NULL, 10);
388 if (errno == ERANGE || thickness < 0) { 398 if (errno == ERANGE || thickness < 0) {
389 errno = 0; 399 errno = 0;
390 return cmd_results_new(CMD_INVALID, "border", "Number is out out of range."); 400 return cmd_results_new(CMD_INVALID, "border", "Number is out out of range.");
391 } 401 }
402 }
403
404 if (config->active && view) {
405 view->border_type = border;
406 view->border_thickness = thickness;
407 update_geometry(view);
408 } else {
409 config->border = border;
392 config->border_thickness = thickness; 410 config->border_thickness = thickness;
393 } 411 }
394 412
395 config->border = border;
396 return cmd_results_new(CMD_SUCCESS, NULL, NULL); 413 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
397} 414}
398 415
@@ -904,9 +921,9 @@ static struct cmd_results *cmd_move(int argc, char **argv) {
904 } else if (strcasecmp(argv[0], "position") == 0 && strcasecmp(argv[1], "mouse") == 0) { 921 } else if (strcasecmp(argv[0], "position") == 0 && strcasecmp(argv[1], "mouse") == 0) {
905 if (view->is_floating) { 922 if (view->is_floating) {
906 swayc_t *output = swayc_parent_by_type(view, C_OUTPUT); 923 swayc_t *output = swayc_parent_by_type(view, C_OUTPUT);
907 const struct wlc_geometry *geometry = wlc_view_get_geometry(view->handle); 924 struct wlc_geometry g;
925 wlc_view_get_visible_geometry(view->handle, &g);
908 const struct wlc_size *size = wlc_output_get_resolution(output->handle); 926 const struct wlc_size *size = wlc_output_get_resolution(output->handle);
909 struct wlc_geometry g = *geometry;
910 927
911 struct wlc_point origin; 928 struct wlc_point origin;
912 wlc_pointer_get_position(&origin); 929 wlc_pointer_get_position(&origin);
@@ -1954,6 +1971,8 @@ static struct cmd_results *cmd_font(int argc, char **argv) {
1954 config->font = font; 1971 config->font = font;
1955 } 1972 }
1956 1973
1974 config->font_height = get_font_text_height(config->font);
1975
1957 sway_log(L_DEBUG, "Settings font %s", config->font); 1976 sway_log(L_DEBUG, "Settings font %s", config->font);
1958 return cmd_results_new(CMD_SUCCESS, NULL, NULL); 1977 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
1959} 1978}
diff --git a/sway/config.c b/sway/config.c
index 193cfad2..5501ab31 100644
--- a/sway/config.c
+++ b/sway/config.c
@@ -22,6 +22,7 @@
22#include "input_state.h" 22#include "input_state.h"
23#include "criteria.h" 23#include "criteria.h"
24#include "input.h" 24#include "input.h"
25#include "border.h"
25 26
26struct sway_config *config = NULL; 27struct sway_config *config = NULL;
27 28
@@ -161,6 +162,7 @@ static void config_defaults(struct sway_config *config) {
161 config->default_layout = L_NONE; 162 config->default_layout = L_NONE;
162 config->default_orientation = L_NONE; 163 config->default_orientation = L_NONE;
163 config->font = strdup("monospace 10"); 164 config->font = strdup("monospace 10");
165 config->font_height = get_font_text_height(config->font);
164 166
165 // Flags 167 // Flags
166 config->focus_follows_mouse = true; 168 config->focus_follows_mouse = true;
diff --git a/sway/container.c b/sway/container.c
index ac0d3231..21a929b9 100644
--- a/sway/container.c
+++ b/sway/container.c
@@ -22,8 +22,8 @@ static swayc_t *new_swayc(enum swayc_types type) {
22 c->gaps = -1; 22 c->gaps = -1;
23 c->layout = L_NONE; 23 c->layout = L_NONE;
24 c->type = type; 24 c->type = type;
25 c->border_type = B_PIXEL; // TODO: Load default from config 25 c->border_type = config->border;
26 c->border_thickness = 2; 26 c->border_thickness = config->border_thickness;
27 if (type != C_VIEW) { 27 if (type != C_VIEW) {
28 c->children = create_list(); 28 c->children = create_list();
29 c->border_type = B_NONE; 29 c->border_type = B_NONE;
@@ -269,11 +269,12 @@ swayc_t *new_view(swayc_t *sibling, wlc_handle handle) {
269 view->is_focused = true; 269 view->is_focused = true;
270 view->sticky = false; 270 view->sticky = false;
271 // Setup geometry 271 // Setup geometry
272 const struct wlc_geometry* geometry = wlc_view_get_geometry(handle); 272 struct wlc_geometry geometry;
273 wlc_view_get_visible_geometry(handle, &geometry);
273 view->width = 0; 274 view->width = 0;
274 view->height = 0; 275 view->height = 0;
275 view->desired_width = geometry->size.w; 276 view->desired_width = geometry.size.w;
276 view->desired_height = geometry->size.h; 277 view->desired_height = geometry.size.h;
277 278
278 view->is_floating = false; 279 view->is_floating = false;
279 280
@@ -306,13 +307,14 @@ swayc_t *new_floating_view(wlc_handle handle) {
306 view->sticky = false; 307 view->sticky = false;
307 308
308 // Set the geometry of the floating view 309 // Set the geometry of the floating view
309 const struct wlc_geometry* geometry = wlc_view_get_geometry(handle); 310 struct wlc_geometry geometry;
311 wlc_view_get_visible_geometry(handle, &geometry);
310 312
311 // give it requested geometry, but place in center 313 // give it requested geometry, but place in center
312 view->x = (swayc_active_workspace()->width - geometry->size.w) / 2; 314 view->x = (swayc_active_workspace()->width - geometry.size.w) / 2;
313 view->y = (swayc_active_workspace()->height- geometry->size.h) / 2; 315 view->y = (swayc_active_workspace()->height- geometry.size.h) / 2;
314 view->width = geometry->size.w; 316 view->width = geometry.size.w;
315 view->height = geometry->size.h; 317 view->height = geometry.size.h;
316 318
317 view->desired_width = view->width; 319 view->desired_width = view->width;
318 view->desired_height = view->height; 320 view->desired_height = view->height;
diff --git a/sway/focus.c b/sway/focus.c
index 7f96eda7..4cae3b47 100644
--- a/sway/focus.c
+++ b/sway/focus.c
@@ -7,6 +7,7 @@
7#include "config.h" 7#include "config.h"
8#include "input_state.h" 8#include "input_state.h"
9#include "ipc-server.h" 9#include "ipc-server.h"
10#include "border.h"
10 11
11bool locked_container_focus = false; 12bool locked_container_focus = false;
12bool locked_view_focus = false; 13bool locked_view_focus = false;
@@ -130,6 +131,7 @@ bool set_focused_container(swayc_t *c) {
130 // unactivate previous focus 131 // unactivate previous focus
131 if (focused->type == C_VIEW) { 132 if (focused->type == C_VIEW) {
132 wlc_view_set_state(focused->handle, WLC_BIT_ACTIVATED, false); 133 wlc_view_set_state(focused->handle, WLC_BIT_ACTIVATED, false);
134 update_view_border(focused);
133 } 135 }
134 // activate current focus 136 // activate current focus
135 if (p->type == C_VIEW) { 137 if (p->type == C_VIEW) {
@@ -137,6 +139,7 @@ bool set_focused_container(swayc_t *c) {
137 // set focus if view_focus is unlocked 139 // set focus if view_focus is unlocked
138 if (!locked_view_focus) { 140 if (!locked_view_focus) {
139 wlc_view_focus(p->handle); 141 wlc_view_focus(p->handle);
142 update_view_border(p);
140 } 143 }
141 } 144 }
142 } else if (p->type == C_WORKSPACE) { 145 } else if (p->type == C_WORKSPACE) {
diff --git a/sway/handlers.c b/sway/handlers.c
index 47b649fd..fc473640 100644
--- a/sway/handlers.c
+++ b/sway/handlers.c
@@ -9,7 +9,7 @@
9#include <ctype.h> 9#include <ctype.h>
10 10
11#include "handlers.h" 11#include "handlers.h"
12#include "render.h" 12#include "border.h"
13#include "log.h" 13#include "log.h"
14#include "layout.h" 14#include "layout.h"
15#include "config.h" 15#include "config.h"
@@ -349,15 +349,14 @@ static void handle_view_geometry_request(wlc_handle handle, const struct wlc_geo
349 view->desired_width = geometry->size.w; 349 view->desired_width = geometry->size.w;
350 view->desired_height = geometry->size.h; 350 view->desired_height = geometry->size.h;
351 351
352 if (view->is_floating) { 352 /* if (view->is_floating) { */
353 view->width = view->desired_width; 353 /* view->width = view->desired_width; */
354 view->height = view->desired_height; 354 /* view->height = view->desired_height; */
355 view->x = geometry->origin.x; 355 /* view->x = geometry->origin.x; */
356 view->y = geometry->origin.y; 356 /* view->y = geometry->origin.y; */
357 arrange_windows(view->parent, -1, -1); 357 /* /1* arrange_windows(view->parent, -1, -1); *1/ */
358 } 358 /* } */
359 } 359 }
360 update_view_border(view);
361} 360}
362 361
363static void handle_view_state_request(wlc_handle view, enum wlc_view_state_bit state, bool toggle) { 362static void handle_view_state_request(wlc_handle view, enum wlc_view_state_bit state, bool toggle) {
diff --git a/sway/layout.c b/sway/layout.c
index be898c58..a282f36e 100644
--- a/sway/layout.c
+++ b/sway/layout.c
@@ -12,7 +12,7 @@
12#include "focus.h" 12#include "focus.h"
13#include "output.h" 13#include "output.h"
14#include "ipc-server.h" 14#include "ipc-server.h"
15#include "render.h" 15#include "border.h"
16 16
17swayc_t root_container; 17swayc_t root_container;
18list_t *scratchpad; 18list_t *scratchpad;
@@ -427,6 +427,80 @@ void update_geometry(swayc_t *container) {
427 geometry.size.h = ws->y + ws->height - geometry.origin.y; 427 geometry.size.h = ws->y + ws->height - geometry.origin.y;
428 } 428 }
429 } 429 }
430
431 if (swayc_is_fullscreen(container)) {
432 container->border_geometry = (const struct wlc_geometry){0};
433 container->title_bar_geometry = (const struct wlc_geometry){0};
434 } else {
435 // make room for border
436 container->border_geometry = geometry;
437
438 int border_top = container->border_thickness;
439 int border_bottom = container->border_thickness;
440 int border_left = container->border_thickness;
441 int border_right = container->border_thickness;
442
443 // handle hide_edge_borders
444 if (config->hide_edge_borders != E_NONE && gap <= 0) {
445 swayc_t *output = swayc_parent_by_type(container, C_OUTPUT);
446 const struct wlc_size *size = wlc_output_get_resolution(output->handle);
447
448 if (config->hide_edge_borders == E_HORIZONTAL || config->hide_edge_borders == E_BOTH) {
449 if (geometry.origin.x == 0) {
450 border_left = 0;
451 }
452
453 if (geometry.origin.x + geometry.size.w == size->w) {
454 border_right = 0;
455 }
456 }
457
458 if (config->hide_edge_borders == E_VERTICAL || config->hide_edge_borders == E_BOTH) {
459 if (geometry.origin.y == 0) {
460 border_top = 0;
461 }
462
463 if (geometry.origin.y + geometry.size.h == size->h) {
464 border_bottom = 0;
465 }
466 }
467 }
468
469 switch (container->border_type) {
470 case B_NONE:
471 break;
472 case B_PIXEL:
473 geometry.origin.x += border_left;
474 geometry.origin.y += border_top;
475 geometry.size.w -= (border_left + border_right);
476 geometry.size.h -= (border_top + border_bottom);
477 break;
478 case B_NORMAL:
479 {
480 struct wlc_geometry title_bar = {
481 .origin = {
482 .x = container->border_geometry.origin.x,
483 .y = container->border_geometry.origin.y
484 },
485 .size = {
486 .w = container->border_geometry.size.w,
487 .h = config->font_height + 4 // borders + padding
488 }
489 };
490 geometry.origin.x += border_left;
491 geometry.origin.y += title_bar.size.h;
492 geometry.size.w -= (border_left + border_right);
493 geometry.size.h -= (border_bottom + title_bar.size.h);
494 container->title_bar_geometry = title_bar;
495 break;
496 }
497 }
498
499 container->actual_geometry = geometry;
500
501 update_view_border(container);
502 }
503
430 wlc_view_set_geometry(container->handle, 0, &geometry); 504 wlc_view_set_geometry(container->handle, 0, &geometry);
431} 505}
432 506
diff --git a/sway/render.c b/sway/render.c
deleted file mode 100644
index 9388c1d0..00000000
--- a/sway/render.c
+++ /dev/null
@@ -1,113 +0,0 @@
1#include "render.h"
2#include <wlc/wlc-render.h>
3#include <cairo/cairo.h>
4#include <stdlib.h>
5#include <stdio.h>
6#include "container.h"
7
8void cairo_set_source_u32(cairo_t *cairo, uint32_t color) {
9 cairo_set_source_rgba(cairo,
10 (color >> (3*8) & 0xFF) / 255.0,
11 (color >> (2*8) & 0xFF) / 255.0,
12 (color >> (1*8) & 0xFF) / 255.0,
13 (color >> (0*8) & 0xFF) / 255.0);
14}
15
16cairo_t *create_border_buffer(swayc_t *view, struct wlc_geometry geo,
17 cairo_surface_t **surface) {
18 const int channels = 4;
19 cairo_t *cr;
20 view->border_geometry = geo;
21 view->border = calloc(channels * geo.size.w * geo.size.h,
22 sizeof(unsigned char));
23 if (!view->border) {
24 sway_log(L_DEBUG, "Unable to allocate buffer");
25 return NULL;
26 }
27 *surface = cairo_image_surface_create_for_data(view->border,
28 CAIRO_FORMAT_ARGB32, geo.size.w, geo.size.h, channels * geo.size.w);
29 if (cairo_surface_status(*surface) != CAIRO_STATUS_SUCCESS) {
30 free(view->border);
31 view->border = NULL;
32 sway_log(L_DEBUG, "Unable to allocate surface");
33 return NULL;
34 }
35 cr = cairo_create(*surface);
36 if (cairo_status(cr) != CAIRO_STATUS_SUCCESS) {
37 cairo_surface_destroy(*surface);
38 free(view->border);
39 view->border = NULL;
40 sway_log(L_DEBUG, "Unable to create cairo context");
41 return NULL;
42 }
43 return cr;
44}
45
46void update_view_border(swayc_t *view) {
47 struct wlc_geometry geo;
48 wlc_view_get_visible_geometry(view->handle, &geo);
49 cairo_t *cr = NULL;
50 cairo_surface_t *surface = NULL;
51
52 if (view->border) {
53 free(view->border);
54 view->border = NULL;
55 }
56
57 switch (view->border_type) {
58 case B_NONE:
59 view->border_geometry = geo;
60 break;
61 case B_PIXEL:
62 geo.origin.x -= view->border_thickness;
63 geo.origin.y -= view->border_thickness;
64 geo.size.w += view->border_thickness * 2;
65 geo.size.h += view->border_thickness * 2;
66 if (geo.size.w <= 0 || geo.size.h <= 0) {
67 view->border = NULL;
68 break;
69 }
70 cr = create_border_buffer(view, geo, &surface);
71 if (!cr) {
72 break;
73 }
74 cairo_set_source_u32(cr, 0x0000FFFF);
75 cairo_paint(cr);
76 break;
77 case B_NORMAL:
78 // TODO
79 break;
80 }
81 if (surface) {
82 cairo_surface_flush(surface);
83 cairo_surface_destroy(surface);
84 }
85 if (cr) {
86 cairo_destroy(cr);
87 sway_log(L_DEBUG, "Created border for %p (%dx%d+%d,%d)", view,
88 geo.size.w, geo.size.h, geo.origin.x, geo.origin.y);
89 }
90 view->border_geometry = geo;
91}
92
93void render_view_borders(wlc_handle view) {
94 swayc_t *c = swayc_by_handle(view);
95 if (!c || c->border_type == B_NONE) {
96 return;
97 }
98 struct wlc_geometry geo;
99 wlc_view_get_visible_geometry(view, &geo);
100 if (geo.size.w != c->presumed_geometry.size.w
101 || geo.size.h != c->presumed_geometry.size.h
102 || geo.origin.x != c->presumed_geometry.origin.x
103 || geo.origin.y != c->presumed_geometry.origin.y) {
104 update_view_border(c);
105 c->presumed_geometry = geo;
106 }
107 if (c->border) {
108 geo = c->border_geometry;
109 sway_log(L_DEBUG, "Rendering border for %p (%dx%d+%d,%d)", c,
110 geo.size.w, geo.size.h, geo.origin.x, geo.origin.y);
111 wlc_pixels_write(WLC_RGBA8888, &c->border_geometry, c->border);
112 }
113}