diff options
Diffstat (limited to 'sway')
-rw-r--r-- | sway/CMakeLists.txt | 3 | ||||
-rw-r--r-- | sway/border.c | 247 | ||||
-rw-r--r-- | sway/commands.c | 29 | ||||
-rw-r--r-- | sway/config.c | 2 | ||||
-rw-r--r-- | sway/container.c | 22 | ||||
-rw-r--r-- | sway/focus.c | 3 | ||||
-rw-r--r-- | sway/handlers.c | 17 | ||||
-rw-r--r-- | sway/layout.c | 76 | ||||
-rw-r--r-- | sway/render.c | 113 |
9 files changed, 373 insertions, 139 deletions
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 | ||
32 | add_definitions( | 32 | add_definitions( |
@@ -36,6 +36,7 @@ add_definitions( | |||
36 | target_link_libraries(sway | 36 | target_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 | |||
11 | void 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 | |||
28 | static 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 | */ | ||
63 | static 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 | |||
89 | int 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 | |||
97 | static 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 | |||
144 | static 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 | |||
173 | void 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 | |||
237 | void 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 | ||
35 | typedef struct cmd_results *sway_cmd(int argc, char **argv); | 36 | typedef 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 | ||
26 | struct sway_config *config = NULL; | 27 | struct 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 | ||
11 | bool locked_container_focus = false; | 12 | bool locked_container_focus = false; |
12 | bool locked_view_focus = false; | 13 | bool 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 | ||
363 | static void handle_view_state_request(wlc_handle view, enum wlc_view_state_bit state, bool toggle) { | 362 | static 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 | ||
17 | swayc_t root_container; | 17 | swayc_t root_container; |
18 | list_t *scratchpad; | 18 | list_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 | |||
8 | void 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 | |||
16 | cairo_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 | |||
46 | void 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 | |||
93 | void 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 | } | ||