aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/sway/config.h4
-rw-r--r--include/sway/tree/container.h7
-rw-r--r--sway/commands.c1
-rw-r--r--sway/commands/client.c27
-rw-r--r--sway/commands/font.c18
-rw-r--r--sway/config.c25
-rw-r--r--sway/desktop/output.c18
-rw-r--r--sway/meson.build1
-rw-r--r--sway/tree/arrange.c1
-rw-r--r--sway/tree/container.c65
-rw-r--r--sway/tree/view.c7
11 files changed, 155 insertions, 19 deletions
diff --git a/include/sway/config.h b/include/sway/config.h
index a0113e98..02ae3b63 100644
--- a/include/sway/config.h
+++ b/include/sway/config.h
@@ -206,7 +206,7 @@ struct bar_config {
206struct border_colors { 206struct border_colors {
207 float border[4]; 207 float border[4];
208 float background[4]; 208 float background[4];
209 float text[4]; 209 uint32_t text; /**< uint32_t because that's the format that cairo uses */
210 float indicator[4]; 210 float indicator[4];
211 float child_border[4]; 211 float child_border[4];
212}; 212};
@@ -461,6 +461,8 @@ struct bar_config *default_bar_config(void);
461 461
462void free_bar_config(struct bar_config *bar); 462void free_bar_config(struct bar_config *bar);
463 463
464int get_font_text_height(char *font);
465
464/* Global config singleton. */ 466/* Global config singleton. */
465extern struct sway_config *config; 467extern struct sway_config *config;
466 468
diff --git a/include/sway/tree/container.h b/include/sway/tree/container.h
index d092af49..b508f310 100644
--- a/include/sway/tree/container.h
+++ b/include/sway/tree/container.h
@@ -85,6 +85,11 @@ struct sway_container {
85 85
86 float alpha; 86 float alpha;
87 87
88 struct wlr_texture *title_focused;
89 struct wlr_texture *title_focused_inactive;
90 struct wlr_texture *title_unfocused;
91 struct wlr_texture *title_urgent;
92
88 struct { 93 struct {
89 struct wl_signal destroy; 94 struct wl_signal destroy;
90 // Raised after the tree updates, but before arrange_windows 95 // Raised after the tree updates, but before arrange_windows
@@ -191,4 +196,6 @@ struct sway_container *container_reap_empty_recursive(
191 196
192struct sway_container *container_flatten(struct sway_container *container); 197struct sway_container *container_flatten(struct sway_container *container);
193 198
199void container_update_title_textures(struct sway_container *container);
200
194#endif 201#endif
diff --git a/sway/commands.c b/sway/commands.c
index 8abfd40b..62f9ea87 100644
--- a/sway/commands.c
+++ b/sway/commands.c
@@ -106,6 +106,7 @@ static struct cmd_handler handlers[] = {
106 { "exec_always", cmd_exec_always }, 106 { "exec_always", cmd_exec_always },
107 { "focus_follows_mouse", cmd_focus_follows_mouse }, 107 { "focus_follows_mouse", cmd_focus_follows_mouse },
108 { "for_window", cmd_for_window }, 108 { "for_window", cmd_for_window },
109 { "font", cmd_font },
109 { "fullscreen", cmd_fullscreen }, 110 { "fullscreen", cmd_fullscreen },
110 { "include", cmd_include }, 111 { "include", cmd_include },
111 { "input", cmd_input }, 112 { "input", cmd_input },
diff --git a/sway/commands/client.c b/sway/commands/client.c
index c3dc2ee2..0abd0167 100644
--- a/sway/commands/client.c
+++ b/sway/commands/client.c
@@ -3,7 +3,10 @@
3#include "sway/config.h" 3#include "sway/config.h"
4#include "sway/tree/container.h" 4#include "sway/tree/container.h"
5 5
6static bool parse_color(char *hexstring, float dest[static 4]) { 6/**
7 * Parse the hex string into an integer.
8 */
9static bool parse_color_int(char *hexstring, uint32_t *dest) {
7 if (hexstring[0] != '#') { 10 if (hexstring[0] != '#') {
8 return false; 11 return false;
9 } 12 }
@@ -25,6 +28,18 @@ static bool parse_color(char *hexstring, float dest[static 4]) {
25 decimal = (decimal << 8) | 0xff; 28 decimal = (decimal << 8) | 0xff;
26 } 29 }
27 30
31 *dest = decimal;
32 return true;
33}
34
35/**
36 * Parse the hex string into a float value.
37 */
38static bool parse_color_float(char *hexstring, float dest[static 4]) {
39 uint32_t decimal;
40 if (!parse_color_int(hexstring, &decimal)) {
41 return false;
42 }
28 dest[0] = ((decimal >> 24) & 0xff) / 255.0; 43 dest[0] = ((decimal >> 24) & 0xff) / 255.0;
29 dest[1] = ((decimal >> 16) & 0xff) / 255.0; 44 dest[1] = ((decimal >> 16) & 0xff) / 255.0;
30 dest[2] = ((decimal >> 8) & 0xff) / 255.0; 45 dest[2] = ((decimal >> 8) & 0xff) / 255.0;
@@ -39,27 +54,27 @@ static struct cmd_results *handle_command(int argc, char **argv,
39 return error; 54 return error;
40 } 55 }
41 56
42 if (!parse_color(argv[0], class->border)) { 57 if (!parse_color_float(argv[0], class->border)) {
43 return cmd_results_new(CMD_INVALID, cmd_name, 58 return cmd_results_new(CMD_INVALID, cmd_name,
44 "Unable to parse border color"); 59 "Unable to parse border color");
45 } 60 }
46 61
47 if (!parse_color(argv[1], class->background)) { 62 if (!parse_color_float(argv[1], class->background)) {
48 return cmd_results_new(CMD_INVALID, cmd_name, 63 return cmd_results_new(CMD_INVALID, cmd_name,
49 "Unable to parse background color"); 64 "Unable to parse background color");
50 } 65 }
51 66
52 if (!parse_color(argv[2], class->text)) { 67 if (!parse_color_int(argv[2], &class->text)) {
53 return cmd_results_new(CMD_INVALID, cmd_name, 68 return cmd_results_new(CMD_INVALID, cmd_name,
54 "Unable to parse text color"); 69 "Unable to parse text color");
55 } 70 }
56 71
57 if (!parse_color(argv[3], class->indicator)) { 72 if (!parse_color_float(argv[3], class->indicator)) {
58 return cmd_results_new(CMD_INVALID, cmd_name, 73 return cmd_results_new(CMD_INVALID, cmd_name,
59 "Unable to parse indicator color"); 74 "Unable to parse indicator color");
60 } 75 }
61 76
62 if (!parse_color(argv[4], class->child_border)) { 77 if (!parse_color_float(argv[4], class->child_border)) {
63 return cmd_results_new(CMD_INVALID, cmd_name, 78 return cmd_results_new(CMD_INVALID, cmd_name,
64 "Unable to parse child border color"); 79 "Unable to parse child border color");
65 } 80 }
diff --git a/sway/commands/font.c b/sway/commands/font.c
new file mode 100644
index 00000000..96127055
--- /dev/null
+++ b/sway/commands/font.c
@@ -0,0 +1,18 @@
1#define _POSIX_C_SOURCE 200809L
2#include <string.h>
3#include "sway/commands.h"
4#include "sway/config.h"
5#include "log.h"
6#include "stringop.h"
7
8struct cmd_results *cmd_font(int argc, char **argv) {
9 struct cmd_results *error = NULL;
10 if ((error = checkarg(argc, "font", EXPECTED_AT_LEAST, 1))) {
11 return error;
12 }
13 char *font = join_args(argv, argc);
14 free(config->font);
15 config->font = strdup(font);
16 config->font_height = get_font_text_height(font);
17 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
18}
diff --git a/sway/config.c b/sway/config.c
index f4d78e19..60b62bbc 100644
--- a/sway/config.c
+++ b/sway/config.c
@@ -25,6 +25,8 @@
25#include "sway/commands.h" 25#include "sway/commands.h"
26#include "sway/config.h" 26#include "sway/config.h"
27#include "sway/tree/layout.h" 27#include "sway/tree/layout.h"
28#include "cairo.h"
29#include "pango.h"
28#include "readline.h" 30#include "readline.h"
29#include "stringop.h" 31#include "stringop.h"
30#include "list.h" 32#include "list.h"
@@ -130,6 +132,17 @@ static void destroy_removed_seats(struct sway_config *old_config,
130 } 132 }
131} 133}
132 134
135int get_font_text_height(char *font) {
136 cairo_t *cairo = cairo_create(NULL);
137 int text_height;
138 get_text_size(cairo, font, NULL, &text_height, 1, false,
139 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
140 "abcdefghijklmnopqrstuvwxyz"
141 "!@#$%^&*([{|");
142 cairo_destroy(cairo);
143 return text_height;
144}
145
133static void set_color(float dest[static 4], uint32_t color) { 146static void set_color(float dest[static 4], uint32_t color) {
134 dest[0] = ((color >> 16) & 0xff) / 255.0; 147 dest[0] = ((color >> 16) & 0xff) / 255.0;
135 dest[1] = ((color >> 8) & 0xff) / 255.0; 148 dest[1] = ((color >> 8) & 0xff) / 255.0;
@@ -169,7 +182,7 @@ static void config_defaults(struct sway_config *config) {
169 config->default_layout = L_NONE; 182 config->default_layout = L_NONE;
170 config->default_orientation = L_NONE; 183 config->default_orientation = L_NONE;
171 if (!(config->font = strdup("monospace 10"))) goto cleanup; 184 if (!(config->font = strdup("monospace 10"))) goto cleanup;
172 //config->font_height = get_font_text_height(config->font); 185 config->font_height = get_font_text_height(config->font);
173 186
174 // floating view 187 // floating view
175 config->floating_maximum_width = 0; 188 config->floating_maximum_width = 0;
@@ -208,31 +221,31 @@ static void config_defaults(struct sway_config *config) {
208 set_color(config->border_colors.focused.border, 0x4C7899); 221 set_color(config->border_colors.focused.border, 0x4C7899);
209 set_color(config->border_colors.focused.border, 0x4C7899); 222 set_color(config->border_colors.focused.border, 0x4C7899);
210 set_color(config->border_colors.focused.background, 0x285577); 223 set_color(config->border_colors.focused.background, 0x285577);
211 set_color(config->border_colors.focused.text, 0xFFFFFF); 224 config->border_colors.focused.text = 0xFFFFFFFF;
212 set_color(config->border_colors.focused.indicator, 0x2E9EF4); 225 set_color(config->border_colors.focused.indicator, 0x2E9EF4);
213 set_color(config->border_colors.focused.child_border, 0x285577); 226 set_color(config->border_colors.focused.child_border, 0x285577);
214 227
215 set_color(config->border_colors.focused_inactive.border, 0x333333); 228 set_color(config->border_colors.focused_inactive.border, 0x333333);
216 set_color(config->border_colors.focused_inactive.background, 0x5F676A); 229 set_color(config->border_colors.focused_inactive.background, 0x5F676A);
217 set_color(config->border_colors.focused_inactive.text, 0xFFFFFF); 230 config->border_colors.focused_inactive.text = 0xFFFFFFFF;
218 set_color(config->border_colors.focused_inactive.indicator, 0x484E50); 231 set_color(config->border_colors.focused_inactive.indicator, 0x484E50);
219 set_color(config->border_colors.focused_inactive.child_border, 0x5F676A); 232 set_color(config->border_colors.focused_inactive.child_border, 0x5F676A);
220 233
221 set_color(config->border_colors.unfocused.border, 0x333333); 234 set_color(config->border_colors.unfocused.border, 0x333333);
222 set_color(config->border_colors.unfocused.background, 0x222222); 235 set_color(config->border_colors.unfocused.background, 0x222222);
223 set_color(config->border_colors.unfocused.text, 0x888888); 236 config->border_colors.unfocused.text = 0x888888FF;
224 set_color(config->border_colors.unfocused.indicator, 0x292D2E); 237 set_color(config->border_colors.unfocused.indicator, 0x292D2E);
225 set_color(config->border_colors.unfocused.child_border, 0x222222); 238 set_color(config->border_colors.unfocused.child_border, 0x222222);
226 239
227 set_color(config->border_colors.urgent.border, 0x2F343A); 240 set_color(config->border_colors.urgent.border, 0x2F343A);
228 set_color(config->border_colors.urgent.background, 0x900000); 241 set_color(config->border_colors.urgent.background, 0x900000);
229 set_color(config->border_colors.urgent.text, 0xFFFFFF); 242 config->border_colors.urgent.text = 0xFFFFFFFF;
230 set_color(config->border_colors.urgent.indicator, 0x900000); 243 set_color(config->border_colors.urgent.indicator, 0x900000);
231 set_color(config->border_colors.urgent.child_border, 0x900000); 244 set_color(config->border_colors.urgent.child_border, 0x900000);
232 245
233 set_color(config->border_colors.placeholder.border, 0x000000); 246 set_color(config->border_colors.placeholder.border, 0x000000);
234 set_color(config->border_colors.placeholder.background, 0x0C0C0C); 247 set_color(config->border_colors.placeholder.background, 0x0C0C0C);
235 set_color(config->border_colors.placeholder.text, 0xFFFFFF); 248 config->border_colors.placeholder.text = 0xFFFFFFFF;
236 set_color(config->border_colors.placeholder.indicator, 0x000000); 249 set_color(config->border_colors.placeholder.indicator, 0x000000);
237 set_color(config->border_colors.placeholder.child_border, 0x0C0C0C); 250 set_color(config->border_colors.placeholder.child_border, 0x0C0C0C);
238 251
diff --git a/sway/desktop/output.c b/sway/desktop/output.c
index 4fff8cd3..03af4239 100644
--- a/sway/desktop/output.c
+++ b/sway/desktop/output.c
@@ -227,7 +227,8 @@ static void render_view(struct sway_view *view, struct sway_output *output) {
227 * Render decorations for a view with "border normal". 227 * Render decorations for a view with "border normal".
228 */ 228 */
229static void render_container_simple_border_normal(struct sway_output *output, 229static void render_container_simple_border_normal(struct sway_output *output,
230 struct sway_container *con, struct border_colors *colors) { 230 struct sway_container *con, struct border_colors *colors,
231 struct wlr_texture *title_texture) {
231 struct wlr_renderer *renderer = 232 struct wlr_renderer *renderer =
232 wlr_backend_get_renderer(output->wlr_output->backend); 233 wlr_backend_get_renderer(output->wlr_output->backend);
233 struct wlr_box box; 234 struct wlr_box box;
@@ -306,7 +307,14 @@ static void render_container_simple_border_normal(struct sway_output *output,
306 output->wlr_output->transform_matrix); 307 output->wlr_output->transform_matrix);
307 308
308 // Title text 309 // Title text
309 // TODO 310 if (title_texture) {
311 double x = (con->x + con->sway_view->border_thickness)
312 * output->wlr_output->scale;
313 double y = (con->y + con->sway_view->border_thickness)
314 * output->wlr_output->scale;
315 wlr_render_texture(renderer, title_texture,
316 output->wlr_output->transform_matrix, x, y, 1);
317 }
310} 318}
311 319
312/** 320/**
@@ -390,17 +398,21 @@ static void render_container_simple(struct sway_output *output,
390 if (child->type == C_VIEW) { 398 if (child->type == C_VIEW) {
391 if (child->sway_view->border != B_NONE) { 399 if (child->sway_view->border != B_NONE) {
392 struct border_colors *colors; 400 struct border_colors *colors;
401 struct wlr_texture *title_texture;
393 if (focus == child) { 402 if (focus == child) {
394 colors = &config->border_colors.focused; 403 colors = &config->border_colors.focused;
404 title_texture = child->title_focused;
395 } else if (seat_get_focus_inactive(seat, con) == child) { 405 } else if (seat_get_focus_inactive(seat, con) == child) {
396 colors = &config->border_colors.focused_inactive; 406 colors = &config->border_colors.focused_inactive;
407 title_texture = child->title_focused_inactive;
397 } else { 408 } else {
398 colors = &config->border_colors.unfocused; 409 colors = &config->border_colors.unfocused;
410 title_texture = child->title_unfocused;
399 } 411 }
400 412
401 if (child->sway_view->border == B_NORMAL) { 413 if (child->sway_view->border == B_NORMAL) {
402 render_container_simple_border_normal(output, child, 414 render_container_simple_border_normal(output, child,
403 colors); 415 colors, title_texture);
404 } else { 416 } else {
405 render_container_simple_border_pixel(output, child, colors); 417 render_container_simple_border_pixel(output, child, colors);
406 } 418 }
diff --git a/sway/meson.build b/sway/meson.build
index 83e8e656..7c93b5c4 100644
--- a/sway/meson.build
+++ b/sway/meson.build
@@ -38,6 +38,7 @@ sway_sources = files(
38 'commands/exec_always.c', 38 'commands/exec_always.c',
39 'commands/focus.c', 39 'commands/focus.c',
40 'commands/focus_follows_mouse.c', 40 'commands/focus_follows_mouse.c',
41 'commands/font.c',
41 'commands/for_window.c', 42 'commands/for_window.c',
42 'commands/fullscreen.c', 43 'commands/fullscreen.c',
43 'commands/kill.c', 44 'commands/kill.c',
diff --git a/sway/tree/arrange.c b/sway/tree/arrange.c
index 83bb20fb..1299beb6 100644
--- a/sway/tree/arrange.c
+++ b/sway/tree/arrange.c
@@ -203,6 +203,7 @@ void arrange_children_of(struct sway_container *parent) {
203 } else { 203 } else {
204 arrange_children_of(child); 204 arrange_children_of(child);
205 } 205 }
206 container_update_title_textures(child);
206 } 207 }
207 container_damage_whole(parent); 208 container_damage_whole(parent);
208 update_debug_tree(); 209 update_debug_tree();
diff --git a/sway/tree/container.c b/sway/tree/container.c
index 6ac59547..b33985af 100644
--- a/sway/tree/container.c
+++ b/sway/tree/container.c
@@ -7,6 +7,8 @@
7#include <wayland-server.h> 7#include <wayland-server.h>
8#include <wlr/types/wlr_output_layout.h> 8#include <wlr/types/wlr_output_layout.h>
9#include <wlr/types/wlr_wl_shell.h> 9#include <wlr/types/wlr_wl_shell.h>
10#include "cairo.h"
11#include "pango.h"
10#include "sway/config.h" 12#include "sway/config.h"
11#include "sway/input/input-manager.h" 13#include "sway/input/input-manager.h"
12#include "sway/input/seat.h" 14#include "sway/input/seat.h"
@@ -120,6 +122,13 @@ static void _container_destroy(struct sway_container *cont) {
120 if (cont->name) { 122 if (cont->name) {
121 free(cont->name); 123 free(cont->name);
122 } 124 }
125 if (cont->title_focused) {
126 // If one is set then all of these are set
127 wlr_texture_destroy(cont->title_focused);
128 wlr_texture_destroy(cont->title_focused_inactive);
129 wlr_texture_destroy(cont->title_unfocused);
130 wlr_texture_destroy(cont->title_urgent);
131 }
123 list_free(cont->children); 132 list_free(cont->children);
124 cont->children = NULL; 133 cont->children = NULL;
125 free(cont); 134 free(cont);
@@ -546,3 +555,59 @@ void container_damage_whole(struct sway_container *con) {
546 } 555 }
547 output_damage_whole_container(output->sway_output, con); 556 output_damage_whole_container(output->sway_output, con);
548} 557}
558
559static void update_title_texture(struct sway_container *con,
560 struct wlr_texture **texture, struct border_colors *class) {
561 if (!sway_assert(con->type == C_CONTAINER || con->type == C_VIEW,
562 "Unexpected type %s", container_type_to_str(con->type))) {
563 return;
564 }
565 if (!con->width) {
566 return;
567 }
568 struct sway_container *output = container_parent(con, C_OUTPUT);
569 if (!output) {
570 return;
571 }
572 if (*texture) {
573 wlr_texture_destroy(*texture);
574 }
575 if (!con->name) {
576 return;
577 }
578
579 int width = con->width * output->sway_output->wlr_output->scale;
580 int height = config->font_height * output->sway_output->wlr_output->scale;
581
582 cairo_surface_t *surface = cairo_image_surface_create(
583 CAIRO_FORMAT_ARGB32, width, height);
584 cairo_t *cairo = cairo_create(surface);
585 PangoContext *pango = pango_cairo_create_context(cairo);
586 cairo_set_source_u32(cairo, class->text);
587 cairo_move_to(cairo, 0, 0);
588
589 pango_printf(cairo, config->font, output->sway_output->wlr_output->scale,
590 false, "%s", con->name);
591
592 cairo_surface_flush(surface);
593 unsigned char *data = cairo_image_surface_get_data(surface);
594 int stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, width);
595 struct wlr_renderer *renderer = wlr_backend_get_renderer(
596 output->sway_output->wlr_output->backend);
597 *texture = wlr_texture_from_pixels(
598 renderer, WL_SHM_FORMAT_ARGB8888, stride, width, height, data);
599 cairo_surface_destroy(surface);
600 g_object_unref(pango);
601 cairo_destroy(cairo);
602}
603
604void container_update_title_textures(struct sway_container *container) {
605 update_title_texture(container, &container->title_focused,
606 &config->border_colors.focused);
607 update_title_texture(container, &container->title_focused_inactive,
608 &config->border_colors.focused_inactive);
609 update_title_texture(container, &container->title_unfocused,
610 &config->border_colors.unfocused);
611 update_title_texture(container, &container->title_urgent,
612 &config->border_colors.urgent);
613}
diff --git a/sway/tree/view.c b/sway/tree/view.c
index 87ed62c2..84962306 100644
--- a/sway/tree/view.c
+++ b/sway/tree/view.c
@@ -103,11 +103,12 @@ void view_autoconfigure(struct sway_view *view) {
103 height = view->swayc->height - view->border_thickness * 2; 103 height = view->swayc->height - view->border_thickness * 2;
104 break; 104 break;
105 case B_NORMAL: 105 case B_NORMAL:
106 // TODO: Size the title bar by checking the font 106 // Height is: border + title height + border + view height + border
107 x = view->swayc->x + view->border_thickness; 107 x = view->swayc->x + view->border_thickness;
108 y = view->swayc->y + 20; 108 y = view->swayc->y + config->font_height + view->border_thickness * 2;
109 width = view->swayc->width - view->border_thickness * 2; 109 width = view->swayc->width - view->border_thickness * 2;
110 height = view->swayc->height - view->border_thickness - 20; 110 height = view->swayc->height - config->font_height
111 - view->border_thickness * 3;
111 break; 112 break;
112 } 113 }
113 114