diff options
-rw-r--r-- | include/border.h | 11 | ||||
-rw-r--r-- | include/client/pango.h | 10 | ||||
-rw-r--r-- | include/config.h | 30 | ||||
-rw-r--r-- | include/container.h | 18 | ||||
-rw-r--r-- | sway/CMakeLists.txt | 6 | ||||
-rw-r--r-- | sway/border.c | 266 | ||||
-rw-r--r-- | sway/commands.c | 111 | ||||
-rw-r--r-- | sway/config.c | 42 | ||||
-rw-r--r-- | sway/container.c | 21 | ||||
-rw-r--r-- | sway/focus.c | 5 | ||||
-rw-r--r-- | sway/handlers.c | 6 | ||||
-rw-r--r-- | sway/layout.c | 116 | ||||
-rw-r--r-- | sway/sway.5.txt | 12 | ||||
-rw-r--r-- | swaybar/config.c | 4 | ||||
-rw-r--r-- | swaybar/render.c | 22 | ||||
-rw-r--r-- | wayland/pango.c | 22 |
16 files changed, 655 insertions, 47 deletions
diff --git a/include/border.h b/include/border.h new file mode 100644 index 00000000..85c656e0 --- /dev/null +++ b/include/border.h | |||
@@ -0,0 +1,11 @@ | |||
1 | #ifndef _SWAY_BORDER_H | ||
2 | #define _SWAY_BORDER_H | ||
3 | #include <wlc/wlc.h> | ||
4 | #include "container.h" | ||
5 | |||
6 | void render_view_borders(wlc_handle view); | ||
7 | void update_view_border(swayc_t *view); | ||
8 | void map_update_view_border(swayc_t *view, void *data); | ||
9 | int get_font_text_height(const char *font); | ||
10 | |||
11 | #endif | ||
diff --git a/include/client/pango.h b/include/client/pango.h index e25a2211..97c31e38 100644 --- a/include/client/pango.h +++ b/include/client/pango.h | |||
@@ -1,12 +1,12 @@ | |||
1 | #ifndef _SWAY_CLIENT_PANGO_H | 1 | #ifndef _SWAY_CLIENT_PANGO_H |
2 | #define _SWAY_CLIENT_PANGO_H | 2 | #define _SWAY_CLIENT_PANGO_H |
3 | 3 | ||
4 | #include "client/window.h" | 4 | #include <cairo/cairo.h> |
5 | #include "client/buffer.h" | 5 | #include <pango/pangocairo.h> |
6 | #include <stdarg.h> | 6 | #include <stdarg.h> |
7 | 7 | ||
8 | PangoLayout *get_pango_layout(struct window *window, struct buffer *buffer, const char *text); | 8 | PangoLayout *get_pango_layout(cairo_t *cairo, const char *font, const char *text); |
9 | void get_text_size(struct window *window, int *width, int *height, const char *fmt, ...); | 9 | void get_text_size(cairo_t *cairo, const char *font, int *width, int *height, const char *fmt, ...); |
10 | void pango_printf(struct window *window, const char *fmt, ...); | 10 | void pango_printf(cairo_t *cairo, const char *font, const char *fmt, ...); |
11 | 11 | ||
12 | #endif | 12 | #endif |
diff --git a/include/config.h b/include/config.h index 4bcf55e8..fb84423c 100644 --- a/include/config.h +++ b/include/config.h | |||
@@ -148,6 +148,21 @@ struct bar_config { | |||
148 | } colors; | 148 | } colors; |
149 | }; | 149 | }; |
150 | 150 | ||
151 | struct border_colors { | ||
152 | uint32_t border; | ||
153 | uint32_t background; | ||
154 | uint32_t text; | ||
155 | uint32_t indicator; | ||
156 | uint32_t child_border; | ||
157 | }; | ||
158 | |||
159 | enum edge_border_types { | ||
160 | E_NONE, /**< Don't hide edge borders */ | ||
161 | E_VERTICAL, /**< hide vertical edge borders */ | ||
162 | E_HORIZONTAL, /**< hide horizontal edge borders */ | ||
163 | E_BOTH /**< hide vertical and horizontal edge borders */ | ||
164 | }; | ||
165 | |||
151 | /** | 166 | /** |
152 | * The configuration struct. The result of loading a config file. | 167 | * The configuration struct. The result of loading a config file. |
153 | */ | 168 | */ |
@@ -169,6 +184,7 @@ struct sway_config { | |||
169 | enum swayc_layouts default_orientation; | 184 | enum swayc_layouts default_orientation; |
170 | enum swayc_layouts default_layout; | 185 | enum swayc_layouts default_layout; |
171 | char *font; | 186 | char *font; |
187 | int font_height; | ||
172 | 188 | ||
173 | // Flags | 189 | // Flags |
174 | bool focus_follows_mouse; | 190 | bool focus_follows_mouse; |
@@ -187,6 +203,20 @@ struct sway_config { | |||
187 | 203 | ||
188 | list_t *config_chain; | 204 | list_t *config_chain; |
189 | const char *current_config; | 205 | const char *current_config; |
206 | |||
207 | enum swayc_border_types border; | ||
208 | int border_thickness; | ||
209 | enum edge_border_types hide_edge_borders; | ||
210 | |||
211 | // border colors | ||
212 | struct { | ||
213 | struct border_colors focused; | ||
214 | struct border_colors focused_inactive; | ||
215 | struct border_colors unfocused; | ||
216 | struct border_colors urgent; | ||
217 | struct border_colors placeholder; | ||
218 | uint32_t background; | ||
219 | } border_colors; | ||
190 | }; | 220 | }; |
191 | 221 | ||
192 | /** | 222 | /** |
diff --git a/include/container.h b/include/container.h index a96beab9..26da851e 100644 --- a/include/container.h +++ b/include/container.h | |||
@@ -8,7 +8,7 @@ typedef struct sway_container swayc_t; | |||
8 | 8 | ||
9 | /** | 9 | /** |
10 | * Different kinds of containers. | 10 | * Different kinds of containers. |
11 | * | 11 | * |
12 | * This enum is in order. A container will never be inside of a container below | 12 | * This enum is in order. A container will never be inside of a container below |
13 | * it on this list. | 13 | * it on this list. |
14 | */ | 14 | */ |
@@ -36,6 +36,12 @@ enum swayc_layouts { | |||
36 | L_LAYOUTS, | 36 | L_LAYOUTS, |
37 | }; | 37 | }; |
38 | 38 | ||
39 | enum swayc_border_types { | ||
40 | B_NONE, /**< No border */ | ||
41 | B_PIXEL, /**< 1px border */ | ||
42 | B_NORMAL /**< Normal border with title bar */ | ||
43 | }; | ||
44 | |||
39 | /** | 45 | /** |
40 | * Stores information about a container. | 46 | * Stores information about a container. |
41 | * | 47 | * |
@@ -109,6 +115,16 @@ struct sway_container { | |||
109 | * 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. |
110 | */ | 116 | */ |
111 | struct sway_container *fullscreen; | 117 | struct sway_container *fullscreen; |
118 | /** | ||
119 | * If this container is a view, this may be set to the window's decoration | ||
120 | * buffer (or NULL). | ||
121 | */ | ||
122 | unsigned char *border; | ||
123 | enum swayc_border_types border_type; | ||
124 | struct wlc_geometry border_geometry; | ||
125 | struct wlc_geometry title_bar_geometry; | ||
126 | struct wlc_geometry actual_geometry; | ||
127 | int border_thickness; | ||
112 | }; | 128 | }; |
113 | 129 | ||
114 | enum visibility_mask { | 130 | enum visibility_mask { |
diff --git a/sway/CMakeLists.txt b/sway/CMakeLists.txt index 5b6104f3..51f27a05 100644 --- a/sway/CMakeLists.txt +++ b/sway/CMakeLists.txt | |||
@@ -5,6 +5,8 @@ include_directories( | |||
5 | ${JSONC_INCLUDE_DIRS} | 5 | ${JSONC_INCLUDE_DIRS} |
6 | ${XKBCOMMON_INCLUDE_DIRS} | 6 | ${XKBCOMMON_INCLUDE_DIRS} |
7 | ${LIBINPUT_INCLUDE_DIRS} | 7 | ${LIBINPUT_INCLUDE_DIRS} |
8 | ${CAIRO_INCLUDE_DIRS} | ||
9 | ${PANGO_INCLUDE_DIRS} | ||
8 | ) | 10 | ) |
9 | 11 | ||
10 | add_executable(sway | 12 | add_executable(sway |
@@ -24,6 +26,7 @@ add_executable(sway | |||
24 | output.c | 26 | output.c |
25 | resize.c | 27 | resize.c |
26 | workspace.c | 28 | workspace.c |
29 | border.c | ||
27 | ) | 30 | ) |
28 | 31 | ||
29 | add_definitions( | 32 | add_definitions( |
@@ -33,12 +36,15 @@ add_definitions( | |||
33 | target_link_libraries(sway | 36 | target_link_libraries(sway |
34 | sway-common | 37 | sway-common |
35 | sway-protocols | 38 | sway-protocols |
39 | sway-wayland | ||
36 | ${WLC_LIBRARIES} | 40 | ${WLC_LIBRARIES} |
37 | ${XKBCOMMON_LIBRARIES} | 41 | ${XKBCOMMON_LIBRARIES} |
38 | ${PCRE_LIBRARIES} | 42 | ${PCRE_LIBRARIES} |
39 | ${JSONC_LIBRARIES} | 43 | ${JSONC_LIBRARIES} |
40 | ${WAYLAND_SERVER_LIBRARIES} | 44 | ${WAYLAND_SERVER_LIBRARIES} |
41 | ${LIBINPUT_LIBRARIES} | 45 | ${LIBINPUT_LIBRARIES} |
46 | ${PANGO_LIBRARIES} | ||
47 | ${JSONC_LIBRARIES} | ||
42 | m | 48 | m |
43 | ) | 49 | ) |
44 | 50 | ||
diff --git a/sway/border.c b/sway/border.c new file mode 100644 index 00000000..ab4b70f6 --- /dev/null +++ b/sway/border.c | |||
@@ -0,0 +1,266 @@ | |||
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) { // little endian | ||
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 { // big endian | ||
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 | if (view->name) { | ||
161 | int width, height; | ||
162 | get_text_size(cr, config->font, &width, &height, "%s", view->name); | ||
163 | cairo_move_to(cr, view->border_thickness, 2); | ||
164 | cairo_set_source_u32(cr, colors->text); | ||
165 | pango_printf(cr, config->font, "%s", view->name); | ||
166 | } | ||
167 | |||
168 | // header bottom line | ||
169 | render_sharp_line(cr, colors->border, | ||
170 | view->actual_geometry.origin.x - b->origin.x, | ||
171 | tb->size.h - 1, | ||
172 | view->actual_geometry.size.w, 1); | ||
173 | } | ||
174 | |||
175 | void map_update_view_border(swayc_t *view, void *data) { | ||
176 | if (view->type == C_VIEW) { | ||
177 | update_view_border(view); | ||
178 | } | ||
179 | } | ||
180 | |||
181 | void update_view_border(swayc_t *view) { | ||
182 | cairo_t *cr = NULL; | ||
183 | cairo_surface_t *surface = NULL; | ||
184 | |||
185 | if (view->border) { | ||
186 | free(view->border); | ||
187 | view->border = NULL; | ||
188 | } | ||
189 | |||
190 | swayc_t *focused = get_focused_view(&root_container); | ||
191 | swayc_t *container = swayc_parent_by_type(view, C_CONTAINER); | ||
192 | swayc_t *focused_inactive = NULL; | ||
193 | if (container) { | ||
194 | focused_inactive = swayc_focus_by_type(container, C_VIEW); | ||
195 | } else { | ||
196 | container = swayc_parent_by_type(view, C_WORKSPACE); | ||
197 | if (container) { | ||
198 | focused_inactive = swayc_focus_by_type(container, C_VIEW); | ||
199 | } | ||
200 | } | ||
201 | |||
202 | switch (view->border_type) { | ||
203 | case B_NONE: | ||
204 | break; | ||
205 | case B_PIXEL: | ||
206 | cr = create_border_buffer(view, view->border_geometry, &surface); | ||
207 | if (!cr) { | ||
208 | break; | ||
209 | } | ||
210 | |||
211 | if (focused == view) { | ||
212 | render_borders(view, cr, &config->border_colors.focused); | ||
213 | } else if (focused_inactive == view) { | ||
214 | render_borders(view, cr, &config->border_colors.focused_inactive); | ||
215 | } else { | ||
216 | render_borders(view, cr, &config->border_colors.unfocused); | ||
217 | } | ||
218 | |||
219 | break; | ||
220 | case B_NORMAL: | ||
221 | cr = create_border_buffer(view, view->border_geometry, &surface); | ||
222 | if (!cr) { | ||
223 | break; | ||
224 | } | ||
225 | |||
226 | if (focused == view) { | ||
227 | render_with_title_bar(view, cr, &config->border_colors.focused); | ||
228 | } else if (focused_inactive == view) { | ||
229 | render_with_title_bar(view, cr, &config->border_colors.focused_inactive); | ||
230 | } else { | ||
231 | render_with_title_bar(view, cr, &config->border_colors.unfocused); | ||
232 | } | ||
233 | |||
234 | break; | ||
235 | } | ||
236 | if (surface) { | ||
237 | cairo_surface_flush(surface); | ||
238 | cairo_surface_destroy(surface); | ||
239 | } | ||
240 | if (cr) { | ||
241 | cairo_destroy(cr); | ||
242 | } | ||
243 | } | ||
244 | |||
245 | void render_view_borders(wlc_handle view) { | ||
246 | swayc_t *c = swayc_by_handle(view); | ||
247 | |||
248 | if (!c || c->border_type == B_NONE) { | ||
249 | return; | ||
250 | } | ||
251 | |||
252 | if (c->border_type == B_NORMAL) { | ||
253 | // update window title | ||
254 | const char *new_name = wlc_view_get_title(view); | ||
255 | |||
256 | if (new_name && strcmp(c->name, new_name) != 0) { | ||
257 | free(c->name); | ||
258 | c->name = strdup(new_name); | ||
259 | update_view_border(c); | ||
260 | } | ||
261 | } | ||
262 | |||
263 | if (c->border) { | ||
264 | wlc_pixels_write(WLC_RGBA8888, &c->border_geometry, c->border); | ||
265 | } | ||
266 | } | ||
diff --git a/sway/commands.c b/sway/commands.c index d2be2f9b..c621fa92 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 | ||
@@ -43,6 +44,7 @@ static sway_cmd cmd_assign; | |||
43 | static sway_cmd cmd_bar; | 44 | static sway_cmd cmd_bar; |
44 | static sway_cmd cmd_bindcode; | 45 | static sway_cmd cmd_bindcode; |
45 | static sway_cmd cmd_bindsym; | 46 | static sway_cmd cmd_bindsym; |
47 | static sway_cmd cmd_border; | ||
46 | static sway_cmd cmd_debuglog; | 48 | static sway_cmd cmd_debuglog; |
47 | static sway_cmd cmd_exec; | 49 | static sway_cmd cmd_exec; |
48 | static sway_cmd cmd_exec_always; | 50 | static sway_cmd cmd_exec_always; |
@@ -55,6 +57,7 @@ static sway_cmd cmd_font; | |||
55 | static sway_cmd cmd_for_window; | 57 | static sway_cmd cmd_for_window; |
56 | static sway_cmd cmd_fullscreen; | 58 | static sway_cmd cmd_fullscreen; |
57 | static sway_cmd cmd_gaps; | 59 | static sway_cmd cmd_gaps; |
60 | static sway_cmd cmd_hide_edge_borders; | ||
58 | static sway_cmd cmd_include; | 61 | static sway_cmd cmd_include; |
59 | static sway_cmd cmd_input; | 62 | static sway_cmd cmd_input; |
60 | static sway_cmd cmd_kill; | 63 | static sway_cmd cmd_kill; |
@@ -345,6 +348,71 @@ static struct cmd_results *cmd_bindcode(int argc, char **argv) { | |||
345 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | 348 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); |
346 | } | 349 | } |
347 | 350 | ||
351 | static struct cmd_results *cmd_border(int argc, char **argv) { | ||
352 | struct cmd_results *error = NULL; | ||
353 | if ((error = checkarg(argc, "border", EXPECTED_AT_LEAST, 1))) { | ||
354 | return error; | ||
355 | } | ||
356 | |||
357 | if (argc > 2) { | ||
358 | return cmd_results_new(CMD_FAILURE, "border", | ||
359 | "Expected 'border <normal|pixel|none|toggle> [<n>]"); | ||
360 | } | ||
361 | |||
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 | } | ||
371 | |||
372 | if (strcasecmp(argv[0], "none") == 0) { | ||
373 | border = B_NONE; | ||
374 | } else if (strcasecmp(argv[0], "normal") == 0) { | ||
375 | border = B_NORMAL; | ||
376 | } else if (strcasecmp(argv[0], "pixel") == 0) { | ||
377 | border = B_PIXEL; | ||
378 | } else if (strcasecmp(argv[0], "toggle") == 0) { | ||
379 | switch (border) { | ||
380 | case B_NONE: | ||
381 | border = B_PIXEL; | ||
382 | break; | ||
383 | case B_NORMAL: | ||
384 | border = B_NONE; | ||
385 | break; | ||
386 | case B_PIXEL: | ||
387 | border = B_NORMAL; | ||
388 | break; | ||
389 | } | ||
390 | } else { | ||
391 | return cmd_results_new(CMD_FAILURE, "border", | ||
392 | "Expected 'border <normal|pixel|none|toggle>"); | ||
393 | } | ||
394 | |||
395 | |||
396 | if (argc == 2 && (border == B_NORMAL || border == B_PIXEL)) { | ||
397 | thickness = (int)strtol(argv[1], NULL, 10); | ||
398 | if (errno == ERANGE || thickness < 0) { | ||
399 | errno = 0; | ||
400 | return cmd_results_new(CMD_INVALID, "border", "Number is out out of range."); | ||
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; | ||
410 | config->border_thickness = thickness; | ||
411 | } | ||
412 | |||
413 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | ||
414 | } | ||
415 | |||
348 | static struct cmd_results *cmd_exec_always(int argc, char **argv) { | 416 | static struct cmd_results *cmd_exec_always(int argc, char **argv) { |
349 | struct cmd_results *error = NULL; | 417 | struct cmd_results *error = NULL; |
350 | if (!config->active) return cmd_results_new(CMD_DEFER, NULL, NULL); | 418 | if (!config->active) return cmd_results_new(CMD_DEFER, NULL, NULL); |
@@ -847,9 +915,9 @@ static struct cmd_results *cmd_move(int argc, char **argv) { | |||
847 | } else if (strcasecmp(argv[0], "position") == 0 && strcasecmp(argv[1], "mouse") == 0) { | 915 | } else if (strcasecmp(argv[0], "position") == 0 && strcasecmp(argv[1], "mouse") == 0) { |
848 | if (view->is_floating) { | 916 | if (view->is_floating) { |
849 | swayc_t *output = swayc_parent_by_type(view, C_OUTPUT); | 917 | swayc_t *output = swayc_parent_by_type(view, C_OUTPUT); |
850 | const struct wlc_geometry *geometry = wlc_view_get_geometry(view->handle); | 918 | struct wlc_geometry g; |
919 | wlc_view_get_visible_geometry(view->handle, &g); | ||
851 | const struct wlc_size *size = wlc_output_get_resolution(output->handle); | 920 | const struct wlc_size *size = wlc_output_get_resolution(output->handle); |
852 | struct wlc_geometry g = *geometry; | ||
853 | 921 | ||
854 | struct wlc_point origin; | 922 | struct wlc_point origin; |
855 | wlc_pointer_get_position(&origin); | 923 | wlc_pointer_get_position(&origin); |
@@ -1500,6 +1568,29 @@ static struct cmd_results *cmd_smart_gaps(int argc, char **argv) { | |||
1500 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | 1568 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); |
1501 | } | 1569 | } |
1502 | 1570 | ||
1571 | static struct cmd_results *cmd_hide_edge_borders(int argc, char **argv) { | ||
1572 | struct cmd_results *error = NULL; | ||
1573 | if ((error = checkarg(argc, "hide_edge_borders", EXPECTED_EQUAL_TO, 1))) { | ||
1574 | return error; | ||
1575 | } | ||
1576 | |||
1577 | if (strcasecmp(argv[0], "none") == 0) { | ||
1578 | config->hide_edge_borders = E_NONE; | ||
1579 | } else if (strcasecmp(argv[0], "vertical") == 0) { | ||
1580 | config->hide_edge_borders = E_VERTICAL; | ||
1581 | } else if (strcasecmp(argv[0], "horizontal") == 0) { | ||
1582 | config->hide_edge_borders = E_HORIZONTAL; | ||
1583 | } else if (strcasecmp(argv[0], "both") == 0) { | ||
1584 | config->hide_edge_borders = E_BOTH; | ||
1585 | } else { | ||
1586 | return cmd_results_new(CMD_INVALID, "hide_edge_borders", | ||
1587 | "Expected 'hide_edge_borders <none|vertical|horizontal|both>'"); | ||
1588 | } | ||
1589 | |||
1590 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | ||
1591 | } | ||
1592 | |||
1593 | |||
1503 | static struct cmd_results *cmd_kill(int argc, char **argv) { | 1594 | static struct cmd_results *cmd_kill(int argc, char **argv) { |
1504 | if (config->reading) return cmd_results_new(CMD_FAILURE, "kill", "Can't be used in config file."); | 1595 | if (config->reading) return cmd_results_new(CMD_FAILURE, "kill", "Can't be used in config file."); |
1505 | if (!config->active) return cmd_results_new(CMD_FAILURE, "kill", "Can only be used when sway is running."); | 1596 | if (!config->active) return cmd_results_new(CMD_FAILURE, "kill", "Can only be used when sway is running."); |
@@ -1866,16 +1957,18 @@ static struct cmd_results *cmd_font(int argc, char **argv) { | |||
1866 | } | 1957 | } |
1867 | 1958 | ||
1868 | char *font = join_args(argv, argc); | 1959 | char *font = join_args(argv, argc); |
1960 | free(config->font); | ||
1869 | if (strlen(font) > 6 && strncmp("pango:", font, 6) == 0) { | 1961 | if (strlen(font) > 6 && strncmp("pango:", font, 6) == 0) { |
1870 | free(config->font); | 1962 | config->font = strdup(font + 6); |
1871 | config->font = font; | ||
1872 | sway_log(L_DEBUG, "Settings font %s", config->font); | ||
1873 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | ||
1874 | } else { | ||
1875 | free(font); | 1963 | free(font); |
1876 | return cmd_results_new(CMD_FAILURE, "font", "non-pango font detected"); | 1964 | } else { |
1965 | config->font = font; | ||
1877 | } | 1966 | } |
1878 | 1967 | ||
1968 | config->font_height = get_font_text_height(config->font); | ||
1969 | |||
1970 | sway_log(L_DEBUG, "Settings font %s", config->font); | ||
1971 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | ||
1879 | } | 1972 | } |
1880 | 1973 | ||
1881 | 1974 | ||
@@ -2044,6 +2137,7 @@ static struct cmd_handler handlers[] = { | |||
2044 | { "bar", cmd_bar }, | 2137 | { "bar", cmd_bar }, |
2045 | { "bindcode", cmd_bindcode }, | 2138 | { "bindcode", cmd_bindcode }, |
2046 | { "bindsym", cmd_bindsym }, | 2139 | { "bindsym", cmd_bindsym }, |
2140 | { "border", cmd_border }, | ||
2047 | { "debuglog", cmd_debuglog }, | 2141 | { "debuglog", cmd_debuglog }, |
2048 | { "default_orientation", cmd_orientation }, | 2142 | { "default_orientation", cmd_orientation }, |
2049 | { "exec", cmd_exec }, | 2143 | { "exec", cmd_exec }, |
@@ -2057,6 +2151,7 @@ static struct cmd_handler handlers[] = { | |||
2057 | { "for_window", cmd_for_window }, | 2151 | { "for_window", cmd_for_window }, |
2058 | { "fullscreen", cmd_fullscreen }, | 2152 | { "fullscreen", cmd_fullscreen }, |
2059 | { "gaps", cmd_gaps }, | 2153 | { "gaps", cmd_gaps }, |
2154 | { "hide_edge_borders", cmd_hide_edge_borders }, | ||
2060 | { "include", cmd_include }, | 2155 | { "include", cmd_include }, |
2061 | { "input", cmd_input }, | 2156 | { "input", cmd_input }, |
2062 | { "kill", cmd_kill }, | 2157 | { "kill", cmd_kill }, |
diff --git a/sway/config.c b/sway/config.c index a877261c..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 | ||
@@ -160,7 +161,8 @@ static void config_defaults(struct sway_config *config) { | |||
160 | config->resizing_key = M_RIGHT_CLICK; | 161 | config->resizing_key = M_RIGHT_CLICK; |
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("pango: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; |
@@ -181,6 +183,44 @@ static void config_defaults(struct sway_config *config) { | |||
181 | 183 | ||
182 | config->config_chain = create_list(); | 184 | config->config_chain = create_list(); |
183 | config->current_config = NULL; | 185 | config->current_config = NULL; |
186 | |||
187 | // borders | ||
188 | config->border = B_NORMAL; | ||
189 | config->border_thickness = 2; | ||
190 | config->hide_edge_borders = E_NONE; | ||
191 | |||
192 | // border colors | ||
193 | config->border_colors.focused.border = 0x4C7899FF; | ||
194 | config->border_colors.focused.background = 0x285577FF; | ||
195 | config->border_colors.focused.text = 0xFFFFFFFF; | ||
196 | config->border_colors.focused.indicator = 0x2E9EF4FF; | ||
197 | config->border_colors.focused.child_border = 0x285577FF; | ||
198 | |||
199 | config->border_colors.focused_inactive.border = 0x333333FF; | ||
200 | config->border_colors.focused_inactive.background = 0x5F676AFF; | ||
201 | config->border_colors.focused_inactive.text = 0xFFFFFFFF; | ||
202 | config->border_colors.focused_inactive.indicator = 0x484E50FF; | ||
203 | config->border_colors.focused_inactive.child_border = 0x5F676AFF; | ||
204 | |||
205 | config->border_colors.unfocused.border = 0x333333FF; | ||
206 | config->border_colors.unfocused.background = 0x222222FF; | ||
207 | config->border_colors.unfocused.text = 0x888888FF; | ||
208 | config->border_colors.unfocused.indicator = 0x292D2EFF; | ||
209 | config->border_colors.unfocused.child_border = 0x222222FF; | ||
210 | |||
211 | config->border_colors.urgent.border = 0x2F343AFF; | ||
212 | config->border_colors.urgent.background = 0x900000FF; | ||
213 | config->border_colors.urgent.text = 0xFFFFFFFF; | ||
214 | config->border_colors.urgent.indicator = 0x900000FF; | ||
215 | config->border_colors.urgent.child_border = 0x900000FF; | ||
216 | |||
217 | config->border_colors.placeholder.border = 0x000000FF; | ||
218 | config->border_colors.placeholder.background = 0x0C0C0CFF; | ||
219 | config->border_colors.placeholder.text = 0xFFFFFFFF; | ||
220 | config->border_colors.placeholder.indicator = 0x000000FF; | ||
221 | config->border_colors.placeholder.child_border = 0x0C0C0CFF; | ||
222 | |||
223 | config->border_colors.background = 0xFFFFFFFF; | ||
184 | } | 224 | } |
185 | 225 | ||
186 | static int compare_modifiers(const void *left, const void *right) { | 226 | static int compare_modifiers(const void *left, const void *right) { |
diff --git a/sway/container.c b/sway/container.c index 9330a3de..21a929b9 100644 --- a/sway/container.c +++ b/sway/container.c | |||
@@ -22,8 +22,11 @@ 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 = config->border; | ||
26 | c->border_thickness = config->border_thickness; | ||
25 | if (type != C_VIEW) { | 27 | if (type != C_VIEW) { |
26 | c->children = create_list(); | 28 | c->children = create_list(); |
29 | c->border_type = B_NONE; | ||
27 | } | 30 | } |
28 | return c; | 31 | return c; |
29 | } | 32 | } |
@@ -266,11 +269,12 @@ swayc_t *new_view(swayc_t *sibling, wlc_handle handle) { | |||
266 | view->is_focused = true; | 269 | view->is_focused = true; |
267 | view->sticky = false; | 270 | view->sticky = false; |
268 | // Setup geometry | 271 | // Setup geometry |
269 | const struct wlc_geometry* geometry = wlc_view_get_geometry(handle); | 272 | struct wlc_geometry geometry; |
273 | wlc_view_get_visible_geometry(handle, &geometry); | ||
270 | view->width = 0; | 274 | view->width = 0; |
271 | view->height = 0; | 275 | view->height = 0; |
272 | view->desired_width = geometry->size.w; | 276 | view->desired_width = geometry.size.w; |
273 | view->desired_height = geometry->size.h; | 277 | view->desired_height = geometry.size.h; |
274 | 278 | ||
275 | view->is_floating = false; | 279 | view->is_floating = false; |
276 | 280 | ||
@@ -303,13 +307,14 @@ swayc_t *new_floating_view(wlc_handle handle) { | |||
303 | view->sticky = false; | 307 | view->sticky = false; |
304 | 308 | ||
305 | // Set the geometry of the floating view | 309 | // Set the geometry of the floating view |
306 | const struct wlc_geometry* geometry = wlc_view_get_geometry(handle); | 310 | struct wlc_geometry geometry; |
311 | wlc_view_get_visible_geometry(handle, &geometry); | ||
307 | 312 | ||
308 | // give it requested geometry, but place in center | 313 | // give it requested geometry, but place in center |
309 | view->x = (swayc_active_workspace()->width - geometry->size.w) / 2; | 314 | view->x = (swayc_active_workspace()->width - geometry.size.w) / 2; |
310 | view->y = (swayc_active_workspace()->height- geometry->size.h) / 2; | 315 | view->y = (swayc_active_workspace()->height- geometry.size.h) / 2; |
311 | view->width = geometry->size.w; | 316 | view->width = geometry.size.w; |
312 | view->height = geometry->size.h; | 317 | view->height = geometry.size.h; |
313 | 318 | ||
314 | view->desired_width = view->width; | 319 | view->desired_width = view->width; |
315 | view->desired_height = view->height; | 320 | view->desired_height = view->height; |
diff --git a/sway/focus.c b/sway/focus.c index 7f96eda7..0c9719b0 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; |
@@ -28,6 +29,8 @@ static void update_focus(swayc_t *c) { | |||
28 | 29 | ||
29 | // Case where output changes | 30 | // Case where output changes |
30 | case C_OUTPUT: | 31 | case C_OUTPUT: |
32 | // update borders for views in prev | ||
33 | container_map(prev, map_update_view_border, NULL); | ||
31 | wlc_output_focus(c->handle); | 34 | wlc_output_focus(c->handle); |
32 | break; | 35 | break; |
33 | 36 | ||
@@ -130,6 +133,7 @@ bool set_focused_container(swayc_t *c) { | |||
130 | // unactivate previous focus | 133 | // unactivate previous focus |
131 | if (focused->type == C_VIEW) { | 134 | if (focused->type == C_VIEW) { |
132 | wlc_view_set_state(focused->handle, WLC_BIT_ACTIVATED, false); | 135 | wlc_view_set_state(focused->handle, WLC_BIT_ACTIVATED, false); |
136 | update_view_border(focused); | ||
133 | } | 137 | } |
134 | // activate current focus | 138 | // activate current focus |
135 | if (p->type == C_VIEW) { | 139 | if (p->type == C_VIEW) { |
@@ -137,6 +141,7 @@ bool set_focused_container(swayc_t *c) { | |||
137 | // set focus if view_focus is unlocked | 141 | // set focus if view_focus is unlocked |
138 | if (!locked_view_focus) { | 142 | if (!locked_view_focus) { |
139 | wlc_view_focus(p->handle); | 143 | wlc_view_focus(p->handle); |
144 | update_view_border(p); | ||
140 | } | 145 | } |
141 | } | 146 | } |
142 | } else if (p->type == C_WORKSPACE) { | 147 | } else if (p->type == C_WORKSPACE) { |
diff --git a/sway/handlers.c b/sway/handlers.c index 7d4ea263..54326dd0 100644 --- a/sway/handlers.c +++ b/sway/handlers.c | |||
@@ -9,6 +9,7 @@ | |||
9 | #include <ctype.h> | 9 | #include <ctype.h> |
10 | 10 | ||
11 | #include "handlers.h" | 11 | #include "handlers.h" |
12 | #include "border.h" | ||
12 | #include "log.h" | 13 | #include "log.h" |
13 | #include "layout.h" | 14 | #include "layout.h" |
14 | #include "config.h" | 15 | #include "config.h" |
@@ -150,6 +151,10 @@ static void handle_output_post_render(wlc_handle output) { | |||
150 | ipc_get_pixels(output); | 151 | ipc_get_pixels(output); |
151 | } | 152 | } |
152 | 153 | ||
154 | static void handle_view_pre_render(wlc_handle view) { | ||
155 | render_view_borders(view); | ||
156 | } | ||
157 | |||
153 | static void handle_output_resolution_change(wlc_handle output, const struct wlc_size *from, const struct wlc_size *to) { | 158 | static void handle_output_resolution_change(wlc_handle output, const struct wlc_size *from, const struct wlc_size *to) { |
154 | sway_log(L_DEBUG, "Output %u resolution changed to %d x %d", (unsigned int)output, to->w, to->h); | 159 | sway_log(L_DEBUG, "Output %u resolution changed to %d x %d", (unsigned int)output, to->w, to->h); |
155 | swayc_t *c = swayc_by_handle(output); | 160 | swayc_t *c = swayc_by_handle(output); |
@@ -716,6 +721,7 @@ void register_wlc_handlers() { | |||
716 | wlc_set_view_created_cb(handle_view_created); | 721 | wlc_set_view_created_cb(handle_view_created); |
717 | wlc_set_view_destroyed_cb(handle_view_destroyed); | 722 | wlc_set_view_destroyed_cb(handle_view_destroyed); |
718 | wlc_set_view_focus_cb(handle_view_focus); | 723 | wlc_set_view_focus_cb(handle_view_focus); |
724 | wlc_set_view_render_pre_cb(handle_view_pre_render); | ||
719 | wlc_set_view_request_geometry_cb(handle_view_geometry_request); | 725 | wlc_set_view_request_geometry_cb(handle_view_geometry_request); |
720 | wlc_set_view_request_state_cb(handle_view_state_request); | 726 | wlc_set_view_request_state_cb(handle_view_state_request); |
721 | wlc_set_keyboard_key_cb(handle_key); | 727 | wlc_set_keyboard_key_cb(handle_key); |
diff --git a/sway/layout.c b/sway/layout.c index d9c4598f..3f271caf 100644 --- a/sway/layout.c +++ b/sway/layout.c | |||
@@ -12,6 +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 "border.h" | ||
15 | 16 | ||
16 | swayc_t root_container; | 17 | swayc_t root_container; |
17 | list_t *scratchpad; | 18 | list_t *scratchpad; |
@@ -373,6 +374,46 @@ void move_workspace_to(swayc_t* workspace, swayc_t* destination) { | |||
373 | update_visibility(src_op); | 374 | update_visibility(src_op); |
374 | } | 375 | } |
375 | 376 | ||
377 | static void update_border_geometry_floating(swayc_t *c, struct wlc_geometry *geometry) { | ||
378 | struct wlc_geometry g = *geometry; | ||
379 | c->actual_geometry = g; | ||
380 | |||
381 | switch (c->border_type) { | ||
382 | case B_NONE: | ||
383 | break; | ||
384 | case B_PIXEL: | ||
385 | g.origin.x -= c->border_thickness; | ||
386 | g.origin.y -= c->border_thickness; | ||
387 | g.size.w += (c->border_thickness * 2); | ||
388 | g.size.h += (c->border_thickness * 2); | ||
389 | break; | ||
390 | case B_NORMAL: | ||
391 | g.origin.x -= c->border_thickness; | ||
392 | uint32_t title_bar_height = config->font_height + 4; // borders + padding | ||
393 | g.origin.y -= title_bar_height; | ||
394 | g.size.w += (c->border_thickness * 2); | ||
395 | g.size.h += (c->border_thickness + title_bar_height); | ||
396 | |||
397 | struct wlc_geometry title_bar = { | ||
398 | .origin = { | ||
399 | .x = g.origin.x, | ||
400 | .y = g.origin.y | ||
401 | }, | ||
402 | .size = { | ||
403 | .w = g.size.w, | ||
404 | .h = title_bar_height | ||
405 | } | ||
406 | }; | ||
407 | c->title_bar_geometry = title_bar; | ||
408 | break; | ||
409 | } | ||
410 | |||
411 | c->border_geometry = g; | ||
412 | *geometry = c->actual_geometry; | ||
413 | |||
414 | update_view_border(c); | ||
415 | } | ||
416 | |||
376 | void update_geometry(swayc_t *container) { | 417 | void update_geometry(swayc_t *container) { |
377 | if (container->type != C_VIEW) { | 418 | if (container->type != C_VIEW) { |
378 | return; | 419 | return; |
@@ -426,6 +467,81 @@ void update_geometry(swayc_t *container) { | |||
426 | geometry.size.h = ws->y + ws->height - geometry.origin.y; | 467 | geometry.size.h = ws->y + ws->height - geometry.origin.y; |
427 | } | 468 | } |
428 | } | 469 | } |
470 | |||
471 | if (swayc_is_fullscreen(container)) { | ||
472 | container->border_geometry = (const struct wlc_geometry){0}; | ||
473 | container->title_bar_geometry = (const struct wlc_geometry){0}; | ||
474 | } else if (container->is_floating) { // allocate border for floating window | ||
475 | update_border_geometry_floating(container, &geometry); | ||
476 | } else if (!container->is_floating) { // allocate border for titled window | ||
477 | container->border_geometry = geometry; | ||
478 | |||
479 | int border_top = container->border_thickness; | ||
480 | int border_bottom = container->border_thickness; | ||
481 | int border_left = container->border_thickness; | ||
482 | int border_right = container->border_thickness; | ||
483 | |||
484 | // handle hide_edge_borders | ||
485 | if (config->hide_edge_borders != E_NONE && gap <= 0) { | ||
486 | swayc_t *output = swayc_parent_by_type(container, C_OUTPUT); | ||
487 | const struct wlc_size *size = wlc_output_get_resolution(output->handle); | ||
488 | |||
489 | if (config->hide_edge_borders == E_HORIZONTAL || config->hide_edge_borders == E_BOTH) { | ||
490 | if (geometry.origin.x == 0) { | ||
491 | border_left = 0; | ||
492 | } | ||
493 | |||
494 | if (geometry.origin.x + geometry.size.w == size->w) { | ||
495 | border_right = 0; | ||
496 | } | ||
497 | } | ||
498 | |||
499 | if (config->hide_edge_borders == E_VERTICAL || config->hide_edge_borders == E_BOTH) { | ||
500 | if (geometry.origin.y == 0) { | ||
501 | border_top = 0; | ||
502 | } | ||
503 | |||
504 | if (geometry.origin.y + geometry.size.h == size->h) { | ||
505 | border_bottom = 0; | ||
506 | } | ||
507 | } | ||
508 | } | ||
509 | |||
510 | switch (container->border_type) { | ||
511 | case B_NONE: | ||
512 | break; | ||
513 | case B_PIXEL: | ||
514 | geometry.origin.x += border_left; | ||
515 | geometry.origin.y += border_top; | ||
516 | geometry.size.w -= (border_left + border_right); | ||
517 | geometry.size.h -= (border_top + border_bottom); | ||
518 | break; | ||
519 | case B_NORMAL: | ||
520 | { | ||
521 | struct wlc_geometry title_bar = { | ||
522 | .origin = { | ||
523 | .x = container->border_geometry.origin.x, | ||
524 | .y = container->border_geometry.origin.y | ||
525 | }, | ||
526 | .size = { | ||
527 | .w = container->border_geometry.size.w, | ||
528 | .h = config->font_height + 4 // borders + padding | ||
529 | } | ||
530 | }; | ||
531 | geometry.origin.x += border_left; | ||
532 | geometry.origin.y += title_bar.size.h; | ||
533 | geometry.size.w -= (border_left + border_right); | ||
534 | geometry.size.h -= (border_bottom + title_bar.size.h); | ||
535 | container->title_bar_geometry = title_bar; | ||
536 | break; | ||
537 | } | ||
538 | } | ||
539 | |||
540 | container->actual_geometry = geometry; | ||
541 | |||
542 | update_view_border(container); | ||
543 | } | ||
544 | |||
429 | wlc_view_set_geometry(container->handle, 0, &geometry); | 545 | wlc_view_set_geometry(container->handle, 0, &geometry); |
430 | } | 546 | } |
431 | 547 | ||
diff --git a/sway/sway.5.txt b/sway/sway.5.txt index 1bb5cd3b..2eb0276c 100644 --- a/sway/sway.5.txt +++ b/sway/sway.5.txt | |||
@@ -43,6 +43,15 @@ The following commands may only be used in the configuration file. | |||
43 | The following commands cannot be used directly in the configuration file. | 43 | The following commands cannot be used directly in the configuration file. |
44 | They are expected to be used with **bindsym** or at runtime through **swaymsg**(1). | 44 | They are expected to be used with **bindsym** or at runtime through **swaymsg**(1). |
45 | 45 | ||
46 | **border** <normal|pixel> [<n>]:: | ||
47 | Set border style for windows. _normal_ includes a border of thickness _n_ and | ||
48 | a title bar. _pixel_ is just the border without title bar. Default is _normal_ | ||
49 | with border thickness 2. | ||
50 | |||
51 | **border** <none|toggle>:: | ||
52 | Set border style to _none_ or _toggle_ between the available border styles: | ||
53 | _normal_, _pixel_, _none_. | ||
54 | |||
46 | **exit**:: | 55 | **exit**:: |
47 | Exit sway and end your Wayland session. | 56 | Exit sway and end your Wayland session. |
48 | 57 | ||
@@ -67,6 +76,9 @@ They are expected to be used with **bindsym** or at runtime through **swaymsg**( | |||
67 | **fullscreen**:: | 76 | **fullscreen**:: |
68 | Toggles fullscreen status for the focused view. | 77 | Toggles fullscreen status for the focused view. |
69 | 78 | ||
79 | **hide_edge_borders** <none|vertical|horizontal|both>:: | ||
80 | Hide window borders adjacent to the screen edges. Default is _none_. | ||
81 | |||
70 | **layout** <mode>:: | 82 | **layout** <mode>:: |
71 | Sets the layout mode of the focused container. _mode_ can be one of _splith_, | 83 | Sets the layout mode of the focused container. _mode_ can be one of _splith_, |
72 | _splitv_, or _toggle split_. | 84 | _splitv_, or _toggle split_. |
diff --git a/swaybar/config.c b/swaybar/config.c index fddea791..6b9ff86b 100644 --- a/swaybar/config.c +++ b/swaybar/config.c | |||
@@ -35,9 +35,11 @@ uint32_t parse_position(const char *position) { | |||
35 | char *parse_font(const char *font) { | 35 | char *parse_font(const char *font) { |
36 | char *new_font = NULL; | 36 | char *new_font = NULL; |
37 | if (strncmp("pango:", font, 6) == 0) { | 37 | if (strncmp("pango:", font, 6) == 0) { |
38 | new_font = strdup(font + 6); | 38 | font += 6; |
39 | } | 39 | } |
40 | 40 | ||
41 | new_font = strdup(font); | ||
42 | |||
41 | return new_font; | 43 | return new_font; |
42 | } | 44 | } |
43 | 45 | ||
diff --git a/swaybar/render.c b/swaybar/render.c index 1573a373..fff47ab0 100644 --- a/swaybar/render.c +++ b/swaybar/render.c | |||
@@ -50,7 +50,7 @@ static void render_sharp_line(cairo_t *cairo, uint32_t color, double x, double y | |||
50 | 50 | ||
51 | static void render_block(struct window *window, struct config *config, struct status_block *block, double *x, bool edge) { | 51 | static void render_block(struct window *window, struct config *config, struct status_block *block, double *x, bool edge) { |
52 | int width, height, sep_width; | 52 | int width, height, sep_width; |
53 | get_text_size(window, &width, &height, "%s", block->full_text); | 53 | get_text_size(window->cairo, window->font, &width, &height, "%s", block->full_text); |
54 | 54 | ||
55 | int textwidth = width; | 55 | int textwidth = width; |
56 | double block_width = width; | 56 | double block_width = width; |
@@ -74,7 +74,7 @@ static void render_block(struct window *window, struct config *config, struct st | |||
74 | // Add separator | 74 | // Add separator |
75 | if (!edge) { | 75 | if (!edge) { |
76 | if (config->sep_symbol) { | 76 | if (config->sep_symbol) { |
77 | get_text_size(window, &sep_width, &height, "%s", config->sep_symbol); | 77 | get_text_size(window->cairo, window->font, &sep_width, &height, "%s", config->sep_symbol); |
78 | if (sep_width > block->separator_block_width) { | 78 | if (sep_width > block->separator_block_width) { |
79 | block->separator_block_width = sep_width + margin * 2; | 79 | block->separator_block_width = sep_width + margin * 2; |
80 | } | 80 | } |
@@ -136,7 +136,7 @@ static void render_block(struct window *window, struct config *config, struct st | |||
136 | 136 | ||
137 | cairo_move_to(window->cairo, offset, margin); | 137 | cairo_move_to(window->cairo, offset, margin); |
138 | cairo_set_source_u32(window->cairo, block->color); | 138 | cairo_set_source_u32(window->cairo, block->color); |
139 | pango_printf(window, "%s", block->full_text); | 139 | pango_printf(window->cairo, window->font, "%s", block->full_text); |
140 | 140 | ||
141 | pos += width; | 141 | pos += width; |
142 | 142 | ||
@@ -159,7 +159,7 @@ static void render_block(struct window *window, struct config *config, struct st | |||
159 | if (config->sep_symbol) { | 159 | if (config->sep_symbol) { |
160 | offset = pos + (block->separator_block_width - sep_width) / 2; | 160 | offset = pos + (block->separator_block_width - sep_width) / 2; |
161 | cairo_move_to(window->cairo, offset, margin); | 161 | cairo_move_to(window->cairo, offset, margin); |
162 | pango_printf(window, "%s", config->sep_symbol); | 162 | pango_printf(window->cairo, window->font, "%s", config->sep_symbol); |
163 | } else { | 163 | } else { |
164 | cairo_set_line_width(window->cairo, 1); | 164 | cairo_set_line_width(window->cairo, 1); |
165 | cairo_move_to(window->cairo, pos + block->separator_block_width/2, | 165 | cairo_move_to(window->cairo, pos + block->separator_block_width/2, |
@@ -201,7 +201,7 @@ static void render_workspace_button(struct window *window, struct config *config | |||
201 | char *name = handle_workspace_number(config->strip_workspace_numbers, ws->name); | 201 | char *name = handle_workspace_number(config->strip_workspace_numbers, ws->name); |
202 | 202 | ||
203 | int width, height; | 203 | int width, height; |
204 | get_text_size(window, &width, &height, "%s", name); | 204 | get_text_size(window->cairo, window->font, &width, &height, "%s", name); |
205 | struct box_colors box_colors; | 205 | struct box_colors box_colors; |
206 | if (ws->urgent) { | 206 | if (ws->urgent) { |
207 | box_colors = config->colors.urgent_workspace; | 207 | box_colors = config->colors.urgent_workspace; |
@@ -228,7 +228,7 @@ static void render_workspace_button(struct window *window, struct config *config | |||
228 | // text | 228 | // text |
229 | cairo_set_source_u32(window->cairo, box_colors.text); | 229 | cairo_set_source_u32(window->cairo, box_colors.text); |
230 | cairo_move_to(window->cairo, (int)*x + ws_horizontal_padding, margin); | 230 | cairo_move_to(window->cairo, (int)*x + ws_horizontal_padding, margin); |
231 | pango_printf(window, "%s", name); | 231 | pango_printf(window->cairo, window->font, "%s", name); |
232 | 232 | ||
233 | *x += width + ws_horizontal_padding * 2 + ws_spacing; | 233 | *x += width + ws_horizontal_padding * 2 + ws_spacing; |
234 | 234 | ||
@@ -237,7 +237,7 @@ static void render_workspace_button(struct window *window, struct config *config | |||
237 | 237 | ||
238 | static void render_binding_mode_indicator(struct window *window, struct config *config, double pos) { | 238 | static void render_binding_mode_indicator(struct window *window, struct config *config, double pos) { |
239 | int width, height; | 239 | int width, height; |
240 | get_text_size(window, &width, &height, "%s", config->mode); | 240 | get_text_size(window->cairo, window->font, &width, &height, "%s", config->mode); |
241 | 241 | ||
242 | // background | 242 | // background |
243 | cairo_set_source_u32(window->cairo, config->colors.binding_mode.background); | 243 | cairo_set_source_u32(window->cairo, config->colors.binding_mode.background); |
@@ -254,7 +254,7 @@ static void render_binding_mode_indicator(struct window *window, struct config * | |||
254 | // text | 254 | // text |
255 | cairo_set_source_u32(window->cairo, config->colors.binding_mode.text); | 255 | cairo_set_source_u32(window->cairo, config->colors.binding_mode.text); |
256 | cairo_move_to(window->cairo, (int)pos + ws_horizontal_padding, margin); | 256 | cairo_move_to(window->cairo, (int)pos + ws_horizontal_padding, margin); |
257 | pango_printf(window, "%s", config->mode); | 257 | pango_printf(window->cairo, window->font, "%s", config->mode); |
258 | } | 258 | } |
259 | 259 | ||
260 | void render(struct output *output, struct config *config, struct status_line *line) { | 260 | void render(struct output *output, struct config *config, struct status_line *line) { |
@@ -278,9 +278,9 @@ void render(struct output *output, struct config *config, struct status_line *li | |||
278 | int width, height; | 278 | int width, height; |
279 | 279 | ||
280 | if (line->protocol == TEXT) { | 280 | if (line->protocol == TEXT) { |
281 | get_text_size(window, &width, &height, "%s", line->text_line); | 281 | get_text_size(window->cairo, window->font, &width, &height, "%s", line->text_line); |
282 | cairo_move_to(cairo, window->width - margin - width, margin); | 282 | cairo_move_to(cairo, window->width - margin - width, margin); |
283 | pango_printf(window, "%s", line->text_line); | 283 | pango_printf(window->cairo, window->font, "%s", line->text_line); |
284 | } else if (line->protocol == I3BAR && line->block_line) { | 284 | } else if (line->protocol == I3BAR && line->block_line) { |
285 | double pos = window->width - 0.5; | 285 | double pos = window->width - 0.5; |
286 | bool edge = true; | 286 | bool edge = true; |
@@ -312,7 +312,7 @@ void render(struct output *output, struct config *config, struct status_line *li | |||
312 | 312 | ||
313 | void set_window_height(struct window *window, int height) { | 313 | void set_window_height(struct window *window, int height) { |
314 | int text_width, text_height; | 314 | int text_width, text_height; |
315 | get_text_size(window, &text_width, &text_height, "Test string for measuring purposes"); | 315 | get_text_size(window->cairo, window->font, &text_width, &text_height, "Test string for measuring purposes"); |
316 | if (height > 0) { | 316 | if (height > 0) { |
317 | margin = (height - text_height) / 2; | 317 | margin = (height - text_height) / 2; |
318 | ws_vertical_padding = margin - 1.5; | 318 | ws_vertical_padding = margin - 1.5; |
diff --git a/wayland/pango.c b/wayland/pango.c index 9766be6a..d79d89b3 100644 --- a/wayland/pango.c +++ b/wayland/pango.c | |||
@@ -4,21 +4,19 @@ | |||
4 | #include <stdlib.h> | 4 | #include <stdlib.h> |
5 | #include <string.h> | 5 | #include <string.h> |
6 | #include <stdio.h> | 6 | #include <stdio.h> |
7 | #include "client/window.h" | ||
8 | #include "client/buffer.h" | ||
9 | #include "log.h" | 7 | #include "log.h" |
10 | 8 | ||
11 | PangoLayout *get_pango_layout(struct window *window, const char *text) { | 9 | PangoLayout *get_pango_layout(cairo_t *cairo, const char *font, const char *text) { |
12 | PangoLayout *layout = pango_cairo_create_layout(window->cairo); | 10 | PangoLayout *layout = pango_cairo_create_layout(cairo); |
13 | pango_layout_set_text(layout, text, -1); | 11 | pango_layout_set_text(layout, text, -1); |
14 | PangoFontDescription *desc = pango_font_description_from_string(window->font); | 12 | PangoFontDescription *desc = pango_font_description_from_string(font); |
15 | pango_layout_set_font_description(layout, desc); | 13 | pango_layout_set_font_description(layout, desc); |
16 | pango_layout_set_single_paragraph_mode(layout, 1); | 14 | pango_layout_set_single_paragraph_mode(layout, 1); |
17 | pango_font_description_free(desc); | 15 | pango_font_description_free(desc); |
18 | return layout; | 16 | return layout; |
19 | } | 17 | } |
20 | 18 | ||
21 | void get_text_size(struct window *window, int *width, int *height, const char *fmt, ...) { | 19 | void get_text_size(cairo_t *cairo, const char *font, int *width, int *height, const char *fmt, ...) { |
22 | char *buf = malloc(2048); | 20 | char *buf = malloc(2048); |
23 | 21 | ||
24 | va_list args; | 22 | va_list args; |
@@ -28,8 +26,8 @@ void get_text_size(struct window *window, int *width, int *height, const char *f | |||
28 | } | 26 | } |
29 | va_end(args); | 27 | va_end(args); |
30 | 28 | ||
31 | PangoLayout *layout = get_pango_layout(window, buf); | 29 | PangoLayout *layout = get_pango_layout(cairo, font, buf); |
32 | pango_cairo_update_layout(window->cairo, layout); | 30 | pango_cairo_update_layout(cairo, layout); |
33 | 31 | ||
34 | pango_layout_get_pixel_size(layout, width, height); | 32 | pango_layout_get_pixel_size(layout, width, height); |
35 | 33 | ||
@@ -38,7 +36,7 @@ void get_text_size(struct window *window, int *width, int *height, const char *f | |||
38 | free(buf); | 36 | free(buf); |
39 | } | 37 | } |
40 | 38 | ||
41 | void pango_printf(struct window *window, const char *fmt, ...) { | 39 | void pango_printf(cairo_t *cairo, const char *font, const char *fmt, ...) { |
42 | char *buf = malloc(2048); | 40 | char *buf = malloc(2048); |
43 | 41 | ||
44 | va_list args; | 42 | va_list args; |
@@ -48,10 +46,10 @@ void pango_printf(struct window *window, const char *fmt, ...) { | |||
48 | } | 46 | } |
49 | va_end(args); | 47 | va_end(args); |
50 | 48 | ||
51 | PangoLayout *layout = get_pango_layout(window, buf); | 49 | PangoLayout *layout = get_pango_layout(cairo, font, buf); |
52 | pango_cairo_update_layout(window->cairo, layout); | 50 | pango_cairo_update_layout(cairo, layout); |
53 | 51 | ||
54 | pango_cairo_show_layout(window->cairo, layout); | 52 | pango_cairo_show_layout(cairo, layout); |
55 | 53 | ||
56 | g_object_unref(layout); | 54 | g_object_unref(layout); |
57 | 55 | ||