summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar Nicolas Braud-Santoni <nicolas@braud-santoni.eu>2018-05-05 20:42:17 +0200
committerLibravatar GitHub <noreply@github.com>2018-05-05 20:42:17 +0200
commit30c00b26966d8bdd491e808604b7da87ec89f679 (patch)
treed508d2e5999e6f258b49e6698fcc874ba03ca8b6
parentswaymsg: Fix spelling in error message (diff)
parentMerge pull request #1915 from RyanDwyer/title-format (diff)
downloadsway-30c00b26966d8bdd491e808604b7da87ec89f679.tar.gz
sway-30c00b26966d8bdd491e808604b7da87ec89f679.tar.zst
sway-30c00b26966d8bdd491e808604b7da87ec89f679.zip
Merge branch 'master' into spelling
-rw-r--r--include/sway/commands.h1
-rw-r--r--include/sway/config.h5
-rw-r--r--include/sway/tree/container.h6
-rw-r--r--include/sway/tree/view.h10
-rw-r--r--sway/commands.c1
-rw-r--r--sway/commands/font.c6
-rw-r--r--sway/commands/title_format.c29
-rw-r--r--sway/config.c9
-rw-r--r--sway/desktop/xdg_shell_v6.c3
-rw-r--r--sway/desktop/xwayland.c2
-rw-r--r--sway/meson.build1
-rw-r--r--sway/tree/container.c46
-rw-r--r--sway/tree/view.c128
13 files changed, 198 insertions, 49 deletions
diff --git a/include/sway/commands.h b/include/sway/commands.h
index 0732a90a..d39ac56c 100644
--- a/include/sway/commands.h
+++ b/include/sway/commands.h
@@ -144,6 +144,7 @@ sway_cmd cmd_splitt;
144sway_cmd cmd_splitv; 144sway_cmd cmd_splitv;
145sway_cmd cmd_sticky; 145sway_cmd cmd_sticky;
146sway_cmd cmd_swaybg_command; 146sway_cmd cmd_swaybg_command;
147sway_cmd cmd_title_format;
147sway_cmd cmd_unmark; 148sway_cmd cmd_unmark;
148sway_cmd cmd_workspace; 149sway_cmd cmd_workspace;
149sway_cmd cmd_ws_auto_back_and_forth; 150sway_cmd cmd_ws_auto_back_and_forth;
diff --git a/include/sway/config.h b/include/sway/config.h
index db942c3f..fa40ef4e 100644
--- a/include/sway/config.h
+++ b/include/sway/config.h
@@ -465,8 +465,11 @@ void free_bar_config(struct bar_config *bar);
465 * Updates the value of config->font_height based on the max title height 465 * Updates the value of config->font_height based on the max title height
466 * reported by each container. If recalculate is true, the containers will 466 * reported by each container. If recalculate is true, the containers will
467 * recalculate their heights before reporting. 467 * recalculate their heights before reporting.
468 *
469 * If the height has changed, all containers will be rearranged to take on the
470 * new size.
468 */ 471 */
469void config_find_font_height(bool recalculate); 472void config_update_font_height(bool recalculate);
470 473
471/* Global config singleton. */ 474/* Global config singleton. */
472extern struct sway_config *config; 475extern struct sway_config *config;
diff --git a/include/sway/tree/container.h b/include/sway/tree/container.h
index b07af72c..61ab7ca1 100644
--- a/include/sway/tree/container.h
+++ b/include/sway/tree/container.h
@@ -63,7 +63,8 @@ struct sway_container {
63 */ 63 */
64 size_t id; 64 size_t id;
65 65
66 char *name; 66 char *name; // The view's title (unformatted)
67 char *formatted_title; // The title displayed in the title bar
67 68
68 enum sway_container_type type; 69 enum sway_container_type type;
69 enum sway_container_layout layout; 70 enum sway_container_layout layout;
@@ -204,7 +205,6 @@ void container_update_title_textures(struct sway_container *container);
204 */ 205 */
205void container_calculate_title_height(struct sway_container *container); 206void container_calculate_title_height(struct sway_container *container);
206 207
207void container_update_title(struct sway_container *container, 208void container_notify_child_title_changed(struct sway_container *container);
208 const char *new_title);
209 209
210#endif 210#endif
diff --git a/include/sway/tree/view.h b/include/sway/tree/view.h
index 21127ab1..9d4256f7 100644
--- a/include/sway/tree/view.h
+++ b/include/sway/tree/view.h
@@ -48,6 +48,7 @@ struct sway_view {
48 48
49 bool is_fullscreen; 49 bool is_fullscreen;
50 50
51 char *title_format;
51 enum sway_container_border border; 52 enum sway_container_border border;
52 int border_thickness; 53 int border_thickness;
53 54
@@ -164,6 +165,8 @@ const char *view_get_class(struct sway_view *view);
164 165
165const char *view_get_instance(struct sway_view *view); 166const char *view_get_instance(struct sway_view *view);
166 167
168const char *view_get_type(struct sway_view *view);
169
167void view_configure(struct sway_view *view, double ox, double oy, int width, 170void view_configure(struct sway_view *view, double ox, double oy, int width,
168 int height); 171 int height);
169 172
@@ -207,4 +210,11 @@ void view_child_init(struct sway_view_child *child,
207 210
208void view_child_destroy(struct sway_view_child *child); 211void view_child_destroy(struct sway_view_child *child);
209 212
213/**
214 * Re-read the view's title property and update any relevant title bars.
215 * The force argument makes it recreate the title bars even if the title hasn't
216 * changed.
217 */
218void view_update_title(struct sway_view *view, bool force);
219
210#endif 220#endif
diff --git a/sway/commands.c b/sway/commands.c
index efed7ddf..2e1cdc2c 100644
--- a/sway/commands.c
+++ b/sway/commands.c
@@ -182,6 +182,7 @@ static struct cmd_handler command_handlers[] = {
182 { "splith", cmd_splith }, 182 { "splith", cmd_splith },
183 { "splitt", cmd_splitt }, 183 { "splitt", cmd_splitt },
184 { "splitv", cmd_splitv }, 184 { "splitv", cmd_splitv },
185 { "title_format", cmd_title_format },
185}; 186};
186 187
187static int handler_compare(const void *_a, const void *_b) { 188static int handler_compare(const void *_a, const void *_b) {
diff --git a/sway/commands/font.c b/sway/commands/font.c
index 38ad8880..8e0b51e3 100644
--- a/sway/commands/font.c
+++ b/sway/commands/font.c
@@ -2,7 +2,6 @@
2#include <string.h> 2#include <string.h>
3#include "sway/commands.h" 3#include "sway/commands.h"
4#include "sway/config.h" 4#include "sway/config.h"
5#include "sway/tree/arrange.h"
6#include "log.h" 5#include "log.h"
7#include "stringop.h" 6#include "stringop.h"
8 7
@@ -14,9 +13,6 @@ struct cmd_results *cmd_font(int argc, char **argv) {
14 char *font = join_args(argv, argc); 13 char *font = join_args(argv, argc);
15 free(config->font); 14 free(config->font);
16 config->font = strdup(font); 15 config->font = strdup(font);
17 config_find_font_height(true); 16 config_update_font_height(true);
18 if (!config->reading) {
19 arrange_root();
20 }
21 return cmd_results_new(CMD_SUCCESS, NULL, NULL); 17 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
22} 18}
diff --git a/sway/commands/title_format.c b/sway/commands/title_format.c
new file mode 100644
index 00000000..3d1c578c
--- /dev/null
+++ b/sway/commands/title_format.c
@@ -0,0 +1,29 @@
1#define _POSIX_C_SOURCE 200809L
2#include <string.h>
3#include "sway/commands.h"
4#include "sway/config.h"
5#include "sway/tree/view.h"
6#include "log.h"
7#include "stringop.h"
8
9struct cmd_results *cmd_title_format(int argc, char **argv) {
10 struct cmd_results *error = NULL;
11 if ((error = checkarg(argc, "title_format", EXPECTED_AT_LEAST, 1))) {
12 return error;
13 }
14 struct sway_container *container =
15 config->handler_context.current_container;
16 if (container->type != C_VIEW) {
17 return cmd_results_new(CMD_INVALID, "title_format",
18 "Only views can have a title_format");
19 }
20 struct sway_view *view = container->sway_view;
21 char *format = join_args(argv, argc);
22 if (view->title_format) {
23 free(view->title_format);
24 }
25 view->title_format = format;
26 view_update_title(view, true);
27 config_update_font_height(true);
28 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
29}
diff --git a/sway/config.c b/sway/config.c
index 2e5eab2b..a14f4ec6 100644
--- a/sway/config.c
+++ b/sway/config.c
@@ -24,6 +24,7 @@
24#include "sway/input/seat.h" 24#include "sway/input/seat.h"
25#include "sway/commands.h" 25#include "sway/commands.h"
26#include "sway/config.h" 26#include "sway/config.h"
27#include "sway/tree/arrange.h"
27#include "sway/tree/layout.h" 28#include "sway/tree/layout.h"
28#include "cairo.h" 29#include "cairo.h"
29#include "pango.h" 30#include "pango.h"
@@ -741,8 +742,14 @@ static void find_font_height_iterator(struct sway_container *container,
741 } 742 }
742} 743}
743 744
744void config_find_font_height(bool recalculate) { 745void config_update_font_height(bool recalculate) {
746 size_t prev_max_height = config->font_height;
745 config->font_height = 0; 747 config->font_height = 0;
748
746 container_for_each_descendant_dfs(&root_container, 749 container_for_each_descendant_dfs(&root_container,
747 find_font_height_iterator, &recalculate); 750 find_font_height_iterator, &recalculate);
751
752 if (config->font_height != prev_max_height) {
753 arrange_root();
754 }
748} 755}
diff --git a/sway/desktop/xdg_shell_v6.c b/sway/desktop/xdg_shell_v6.c
index 5880e9a9..fcee8ce9 100644
--- a/sway/desktop/xdg_shell_v6.c
+++ b/sway/desktop/xdg_shell_v6.c
@@ -176,8 +176,7 @@ static void handle_commit(struct wl_listener *listener, void *data) {
176 // TODO: Let floating views do whatever 176 // TODO: Let floating views do whatever
177 view_update_size(view, xdg_shell_v6_view->pending_width, 177 view_update_size(view, xdg_shell_v6_view->pending_width,
178 xdg_shell_v6_view->pending_height); 178 xdg_shell_v6_view->pending_height);
179 container_update_title(view->swayc, 179 view_update_title(view, false);
180 view->wlr_xdg_surface_v6->toplevel->title);
181 view_damage(view, false); 180 view_damage(view, false);
182} 181}
183 182
diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c
index a1e672ce..b4eda71f 100644
--- a/sway/desktop/xwayland.c
+++ b/sway/desktop/xwayland.c
@@ -223,7 +223,7 @@ static void handle_commit(struct wl_listener *listener, void *data) {
223 view_update_size(view, xwayland_view->pending_width, 223 view_update_size(view, xwayland_view->pending_width,
224 xwayland_view->pending_height); 224 xwayland_view->pending_height);
225 view_damage(view, false); 225 view_damage(view, false);
226 container_update_title(view->swayc, view->wlr_xwayland_surface->title); 226 view_update_title(view, false);
227} 227}
228 228
229static void handle_unmap(struct wl_listener *listener, void *data) { 229static void handle_unmap(struct wl_listener *listener, void *data) {
diff --git a/sway/meson.build b/sway/meson.build
index 7c93b5c4..f70a8e44 100644
--- a/sway/meson.build
+++ b/sway/meson.build
@@ -60,6 +60,7 @@ sway_sources = files(
60 'commands/set.c', 60 'commands/set.c',
61 'commands/split.c', 61 'commands/split.c',
62 'commands/swaybg_command.c', 62 'commands/swaybg_command.c',
63 'commands/title_format.c',
63 'commands/workspace.c', 64 'commands/workspace.c',
64 'commands/ws_auto_back_and_forth.c', 65 'commands/ws_auto_back_and_forth.c',
65 66
diff --git a/sway/tree/container.c b/sway/tree/container.c
index 9fb47020..e1be32d1 100644
--- a/sway/tree/container.c
+++ b/sway/tree/container.c
@@ -348,7 +348,6 @@ struct sway_container *container_view_create(struct sway_container *sibling,
348 swayc, title, sibling, sibling ? sibling->type : 0, sibling->name); 348 swayc, title, sibling, sibling ? sibling->type : 0, sibling->name);
349 // Setup values 349 // Setup values
350 swayc->sway_view = sway_view; 350 swayc->sway_view = sway_view;
351 container_update_title(swayc, title);
352 swayc->width = 0; 351 swayc->width = 0;
353 swayc->height = 0; 352 swayc->height = 0;
354 353
@@ -572,7 +571,7 @@ static void update_title_texture(struct sway_container *con,
572 if (*texture) { 571 if (*texture) {
573 wlr_texture_destroy(*texture); 572 wlr_texture_destroy(*texture);
574 } 573 }
575 if (!con->name) { 574 if (!con->formatted_title) {
576 return; 575 return;
577 } 576 }
578 577
@@ -581,7 +580,8 @@ static void update_title_texture(struct sway_container *con,
581 int height = config->font_height * scale; 580 int height = config->font_height * scale;
582 581
583 cairo_t *c = cairo_create(NULL); 582 cairo_t *c = cairo_create(NULL);
584 get_text_size(c, config->font, &width, NULL, scale, false, "%s", con->name); 583 get_text_size(c, config->font, &width, NULL, scale, false,
584 "%s", con->formatted_title);
585 cairo_destroy(c); 585 cairo_destroy(c);
586 586
587 cairo_surface_t *surface = cairo_image_surface_create( 587 cairo_surface_t *surface = cairo_image_surface_create(
@@ -596,7 +596,7 @@ static void update_title_texture(struct sway_container *con,
596 class->text[2], class->text[3]); 596 class->text[2], class->text[3]);
597 cairo_move_to(cairo, 0, 0); 597 cairo_move_to(cairo, 0, 0);
598 598
599 pango_printf(cairo, config->font, scale, false, "%s", con->name); 599 pango_printf(cairo, config->font, scale, false, "%s", con->formatted_title);
600 600
601 cairo_surface_flush(surface); 601 cairo_surface_flush(surface);
602 unsigned char *data = cairo_image_surface_get_data(surface); 602 unsigned char *data = cairo_image_surface_get_data(surface);
@@ -622,57 +622,31 @@ void container_update_title_textures(struct sway_container *container) {
622} 622}
623 623
624void container_calculate_title_height(struct sway_container *container) { 624void container_calculate_title_height(struct sway_container *container) {
625 if (!container->name) { 625 if (!container->formatted_title) {
626 container->title_height = 0; 626 container->title_height = 0;
627 return; 627 return;
628 } 628 }
629 cairo_t *cairo = cairo_create(NULL); 629 cairo_t *cairo = cairo_create(NULL);
630 int height; 630 int height;
631 get_text_size(cairo, config->font, NULL, &height, 1, false, 631 get_text_size(cairo, config->font, NULL, &height, 1, false,
632 "%s", container->name); 632 "%s", container->formatted_title);
633 cairo_destroy(cairo); 633 cairo_destroy(cairo);
634 container->title_height = height; 634 container->title_height = height;
635} 635}
636 636
637static void container_notify_child_title_changed( 637void container_notify_child_title_changed(struct sway_container *container) {
638 struct sway_container *container) {
639 if (!container || container->type != C_CONTAINER) { 638 if (!container || container->type != C_CONTAINER) {
640 return; 639 return;
641 } 640 }
642 if (container->layout != L_TABBED && container->layout != L_STACKED) { 641 if (container->layout != L_TABBED && container->layout != L_STACKED) {
643 return; 642 return;
644 } 643 }
645 if (container->name) { 644 if (container->formatted_title) {
646 free(container->name); 645 free(container->formatted_title);
647 } 646 }
648 // TODO: iterate children and concatenate their titles 647 // TODO: iterate children and concatenate their titles
649 container->name = strdup(""); 648 container->formatted_title = strdup("");
650 container_calculate_title_height(container); 649 container_calculate_title_height(container);
651 container_update_title_textures(container); 650 container_update_title_textures(container);
652 container_notify_child_title_changed(container->parent); 651 container_notify_child_title_changed(container->parent);
653} 652}
654
655void container_update_title(struct sway_container *container,
656 const char *new_title) {
657 if (!new_title) {
658 new_title = "";
659 }
660
661 if (container->name && strcmp(container->name, new_title) == 0) {
662 return;
663 }
664
665 if (container->name) {
666 free(container->name);
667 }
668 container->name = strdup(new_title);
669 container_calculate_title_height(container);
670 container_update_title_textures(container);
671 container_notify_child_title_changed(container->parent);
672
673 size_t prev_max_height = config->font_height;
674 config_find_font_height(false);
675 if (config->font_height != prev_max_height) {
676 arrange_root();
677 }
678}
diff --git a/sway/tree/view.c b/sway/tree/view.c
index 84962306..fe944466 100644
--- a/sway/tree/view.c
+++ b/sway/tree/view.c
@@ -1,3 +1,4 @@
1#define _POSIX_C_SOURCE 200809L
1#include <stdlib.h> 2#include <stdlib.h>
2#include <wayland-server.h> 3#include <wayland-server.h>
3#include <wlr/render/wlr_renderer.h> 4#include <wlr/render/wlr_renderer.h>
@@ -67,6 +68,18 @@ const char *view_get_instance(struct sway_view *view) {
67 return NULL; 68 return NULL;
68} 69}
69 70
71const char *view_get_type(struct sway_view *view) {
72 switch(view->type) {
73 case SWAY_VIEW_WL_SHELL:
74 return "wl_shell";
75 case SWAY_VIEW_XDG_SHELL_V6:
76 return "xdg_shell_v6";
77 case SWAY_VIEW_XWAYLAND:
78 return "xwayland";
79 }
80 return "unknown";
81}
82
70void view_configure(struct sway_view *view, double ox, double oy, int width, 83void view_configure(struct sway_view *view, double ox, double oy, int width,
71 int height) { 84 int height) {
72 if (view->impl->configure) { 85 if (view->impl->configure) {
@@ -348,6 +361,11 @@ void view_unmap(struct sway_view *view) {
348 view->swayc = NULL; 361 view->swayc = NULL;
349 view->surface = NULL; 362 view->surface = NULL;
350 363
364 if (view->title_format) {
365 free(view->title_format);
366 view->title_format = NULL;
367 }
368
351 if (parent->type == C_OUTPUT) { 369 if (parent->type == C_OUTPUT) {
352 arrange_output(parent); 370 arrange_output(parent);
353 } else { 371 } else {
@@ -475,3 +493,113 @@ void view_child_destroy(struct sway_view_child *child) {
475 free(child); 493 free(child);
476 } 494 }
477} 495}
496
497/**
498 * Calculate and return the length of the formatted title.
499 * If buffer is not NULL, also populate the buffer with the formatted title.
500 */
501static size_t parse_title_format(struct sway_view *view, char *buffer) {
502 if (!view->title_format || strcmp(view->title_format, "%title") == 0) {
503 const char *title = view_get_title(view);
504 if (buffer && title) {
505 strcpy(buffer, title);
506 }
507 return title ? strlen(title) : 0;
508 }
509 const char *title = view_get_title(view);
510 const char *class = view_get_class(view);
511 const char *instance = view_get_instance(view);
512 const char *shell = view_get_type(view);
513 size_t title_len = title ? strlen(title) : 0;
514 size_t class_len = class ? strlen(class) : 0;
515 size_t instance_len = instance ? strlen(instance) : 0;
516 size_t shell_len = shell ? strlen(shell) : 0;
517
518 size_t len = 0;
519 char *format = view->title_format;
520 char *next = strchr(format, '%');
521 while (next) {
522 if (buffer) {
523 // Copy everything up to the %
524 strncat(buffer, format, next - format);
525 }
526 len += next - format;
527 format = next;
528
529 if (strncmp(next, "%title", 6) == 0) {
530 if (buffer && title) {
531 strcat(buffer, title);
532 }
533 len += title_len;
534 format += 6;
535 } else if (strncmp(next, "%class", 6) == 0) {
536 if (buffer && class) {
537 strcat(buffer, class);
538 }
539 len += class_len;
540 format += 6;
541 } else if (strncmp(next, "%instance", 9) == 0) {
542 if (buffer && instance) {
543 strcat(buffer, instance);
544 }
545 len += instance_len;
546 format += 9;
547 } else if (strncmp(next, "%shell", 6) == 0) {
548 if (buffer) {
549 strcat(buffer, shell);
550 }
551 len += shell_len;
552 format += 6;
553 } else {
554 if (buffer) {
555 strcat(buffer, "%");
556 }
557 ++format;
558 ++len;
559 }
560 next = strchr(format, '%');
561 }
562 if (buffer) {
563 strcat(buffer, format);
564 }
565 len += strlen(format);
566
567 return len;
568}
569
570void view_update_title(struct sway_view *view, bool force) {
571 if (!view->swayc) {
572 return;
573 }
574 const char *title = view_get_title(view);
575
576 if (!force) {
577 if (title && view->swayc->name && strcmp(title, view->swayc->name) == 0) {
578 return;
579 }
580 if (!title && !view->swayc->name) {
581 return;
582 }
583 }
584
585 free(view->swayc->name);
586 free(view->swayc->formatted_title);
587 if (title) {
588 size_t len = parse_title_format(view, NULL);
589 char *buffer = calloc(len + 1, 1);
590 if (!sway_assert(buffer, "Unable to allocate title string")) {
591 return;
592 }
593 parse_title_format(view, buffer);
594
595 view->swayc->name = strdup(title);
596 view->swayc->formatted_title = buffer;
597 } else {
598 view->swayc->name = NULL;
599 view->swayc->formatted_title = NULL;
600 }
601 container_calculate_title_height(view->swayc);
602 container_update_title_textures(view->swayc);
603 container_notify_child_title_changed(view->swayc->parent);
604 config_update_font_height(false);
605}