summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar Drew DeVault <sir@cmpwn.com>2018-05-16 21:54:16 -0400
committerLibravatar GitHub <noreply@github.com>2018-05-16 21:54:16 -0400
commitc2c5a3f5f6bdc061acae4e0583c4fd85c7ed21ac (patch)
tree02f3205870487dbedb981a1770a6ec77c8894c15
parentMerge pull request #1995 from RedSoxFan/fix-1985 (diff)
parentUpdate marks textures on output scale event (diff)
downloadsway-c2c5a3f5f6bdc061acae4e0583c4fd85c7ed21ac.tar.gz
sway-c2c5a3f5f6bdc061acae4e0583c4fd85c7ed21ac.tar.zst
sway-c2c5a3f5f6bdc061acae4e0583c4fd85c7ed21ac.zip
Merge pull request #1982 from RyanDwyer/show-marks
Implement show_marks
-rw-r--r--include/sway/tree/view.h7
-rw-r--r--sway/commands.c1
-rw-r--r--sway/commands/mark.c1
-rw-r--r--sway/commands/show_marks.c43
-rw-r--r--sway/commands/unmark.c2
-rw-r--r--sway/desktop/output.c165
-rw-r--r--sway/meson.build1
-rw-r--r--sway/sway.5.scd12
-rw-r--r--sway/tree/container.c14
-rw-r--r--sway/tree/view.c94
10 files changed, 279 insertions, 61 deletions
diff --git a/include/sway/tree/view.h b/include/sway/tree/view.h
index 7ed4d3df..951912d0 100644
--- a/include/sway/tree/view.h
+++ b/include/sway/tree/view.h
@@ -63,6 +63,11 @@ struct sway_view {
63 list_t *executed_criteria; // struct criteria * 63 list_t *executed_criteria; // struct criteria *
64 list_t *marks; // char * 64 list_t *marks; // char *
65 65
66 struct wlr_texture *marks_focused;
67 struct wlr_texture *marks_focused_inactive;
68 struct wlr_texture *marks_unfocused;
69 struct wlr_texture *marks_urgent;
70
66 union { 71 union {
67 struct wlr_xdg_surface_v6 *wlr_xdg_surface_v6; 72 struct wlr_xdg_surface_v6 *wlr_xdg_surface_v6;
68 struct wlr_xdg_surface *wlr_xdg_surface; 73 struct wlr_xdg_surface *wlr_xdg_surface;
@@ -267,4 +272,6 @@ void view_clear_marks(struct sway_view *view);
267 272
268bool view_has_mark(struct sway_view *view, char *mark); 273bool view_has_mark(struct sway_view *view, char *mark);
269 274
275void view_update_marks_textures(struct sway_view *view);
276
270#endif 277#endif
diff --git a/sway/commands.c b/sway/commands.c
index 9b6d6459..6cba0a1c 100644
--- a/sway/commands.c
+++ b/sway/commands.c
@@ -116,6 +116,7 @@ static struct cmd_handler handlers[] = {
116 { "mouse_warping", cmd_mouse_warping }, 116 { "mouse_warping", cmd_mouse_warping },
117 { "output", cmd_output }, 117 { "output", cmd_output },
118 { "seat", cmd_seat }, 118 { "seat", cmd_seat },
119 { "show_marks", cmd_show_marks },
119 { "workspace", cmd_workspace }, 120 { "workspace", cmd_workspace },
120 { "workspace_auto_back_and_forth", cmd_ws_auto_back_and_forth }, 121 { "workspace_auto_back_and_forth", cmd_ws_auto_back_and_forth },
121}; 122};
diff --git a/sway/commands/mark.c b/sway/commands/mark.c
index b131f2f3..5a897e69 100644
--- a/sway/commands/mark.c
+++ b/sway/commands/mark.c
@@ -62,6 +62,7 @@ struct cmd_results *cmd_mark(int argc, char **argv) {
62 } 62 }
63 63
64 free(mark); 64 free(mark);
65 view_update_marks_textures(view);
65 view_execute_criteria(view); 66 view_execute_criteria(view);
66 67
67 return cmd_results_new(CMD_SUCCESS, NULL, NULL); 68 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
diff --git a/sway/commands/show_marks.c b/sway/commands/show_marks.c
new file mode 100644
index 00000000..c7fdc538
--- /dev/null
+++ b/sway/commands/show_marks.c
@@ -0,0 +1,43 @@
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 "sway/output.h"
7#include "list.h"
8#include "log.h"
9#include "stringop.h"
10
11static void rebuild_marks_iterator(struct sway_container *con, void *data) {
12 if (con->type == C_VIEW) {
13 view_update_marks_textures(con->sway_view);
14 }
15}
16
17struct cmd_results *cmd_show_marks(int argc, char **argv) {
18 struct cmd_results *error = NULL;
19 if ((error = checkarg(argc, "show_marks", EXPECTED_AT_LEAST, 1))) {
20 return error;
21 }
22
23 if (strcmp(*argv, "yes") == 0) {
24 config->show_marks = true;
25 } else if (strcmp(*argv, "no") == 0) {
26 config->show_marks = false;
27 } else {
28 return cmd_results_new(CMD_INVALID, "show_marks",
29 "Expected 'show_marks <yes|no>'");
30 }
31
32 if (config->show_marks) {
33 container_for_each_descendant_dfs(&root_container,
34 rebuild_marks_iterator, NULL);
35 }
36
37 for (int i = 0; i < root_container.children->length; ++i) {
38 struct sway_container *con = root_container.children->items[i];
39 output_damage_whole(con->sway_output);
40 }
41
42 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
43}
diff --git a/sway/commands/unmark.c b/sway/commands/unmark.c
index ea2a5709..1ce2c56b 100644
--- a/sway/commands/unmark.c
+++ b/sway/commands/unmark.c
@@ -10,6 +10,7 @@
10static void remove_all_marks_iterator(struct sway_container *con, void *data) { 10static void remove_all_marks_iterator(struct sway_container *con, void *data) {
11 if (con->type == C_VIEW) { 11 if (con->type == C_VIEW) {
12 view_clear_marks(con->sway_view); 12 view_clear_marks(con->sway_view);
13 view_update_marks_textures(con->sway_view);
13 } 14 }
14} 15}
15 16
@@ -45,6 +46,7 @@ struct cmd_results *cmd_unmark(int argc, char **argv) {
45 } else if (view && !mark) { 46 } else if (view && !mark) {
46 // Clear all marks from the given view 47 // Clear all marks from the given view
47 view_clear_marks(view); 48 view_clear_marks(view);
49 view_update_marks_textures(view);
48 } else if (!view && mark) { 50 } else if (!view && mark) {
49 // Remove mark from whichever view has it 51 // Remove mark from whichever view has it
50 view_find_and_unmark(mark); 52 view_find_and_unmark(mark);
diff --git a/sway/desktop/output.c b/sway/desktop/output.c
index b12130d9..94562052 100644
--- a/sway/desktop/output.c
+++ b/sway/desktop/output.c
@@ -287,7 +287,6 @@ static void render_rect(struct wlr_output *wlr_output,
287 wlr_backend_get_renderer(wlr_output->backend); 287 wlr_backend_get_renderer(wlr_output->backend);
288 288
289 struct wlr_box box = *_box; 289 struct wlr_box box = *_box;
290 scale_box(&box, wlr_output->scale);
291 290
292 pixman_region32_t damage; 291 pixman_region32_t damage;
293 pixman_region32_init(&damage); 292 pixman_region32_init(&damage);
@@ -313,26 +312,33 @@ damage_finish:
313 312
314/** 313/**
315 * Render decorations for a view with "border normal". 314 * Render decorations for a view with "border normal".
315 *
316 * Care must be taken not to render over the same pixel multiple times,
317 * otherwise the colors will be incorrect when using opacity.
316 */ 318 */
317static void render_container_simple_border_normal(struct sway_output *output, 319static void render_container_simple_border_normal(struct sway_output *output,
318 pixman_region32_t *output_damage, 320 pixman_region32_t *output_damage,
319 struct sway_container *con, struct border_colors *colors, 321 struct sway_container *con, struct border_colors *colors,
320 struct wlr_texture *title_texture) { 322 struct wlr_texture *title_texture, struct wlr_texture *marks_texture) {
321 struct wlr_box box; 323 struct wlr_box box;
322 float color[4]; 324 float color[4];
325 struct sway_view *view = con->sway_view;
326 float output_scale = output->wlr_output->scale;
323 327
324 if (con->sway_view->border_left) { 328 if (view->border_left) {
325 // Child border - left edge 329 // Child border - left edge
326 memcpy(&color, colors->child_border, sizeof(float) * 4); 330 memcpy(&color, colors->child_border, sizeof(float) * 4);
327 color[3] *= con->alpha; 331 color[3] *= con->alpha;
328 box.x = con->x; 332 box.x = con->x;
329 box.y = con->y + 1; 333 box.y = con->y + 1;
330 box.width = con->sway_view->border_thickness; 334 box.width = view->border_thickness;
331 box.height = con->height - 1; 335 box.height = con->height - 1
336 - view->border_thickness * view->border_bottom;
337 scale_box(&box, output_scale);
332 render_rect(output->wlr_output, output_damage, &box, color); 338 render_rect(output->wlr_output, output_damage, &box, color);
333 } 339 }
334 340
335 if (con->sway_view->border_right) { 341 if (view->border_right) {
336 // Child border - right edge 342 // Child border - right edge
337 if (con->parent->children->length == 1 343 if (con->parent->children->length == 1
338 && con->parent->layout == L_HORIZ) { 344 && con->parent->layout == L_HORIZ) {
@@ -341,14 +347,16 @@ static void render_container_simple_border_normal(struct sway_output *output,
341 memcpy(&color, colors->child_border, sizeof(float) * 4); 347 memcpy(&color, colors->child_border, sizeof(float) * 4);
342 } 348 }
343 color[3] *= con->alpha; 349 color[3] *= con->alpha;
344 box.x = con->x + con->width - con->sway_view->border_thickness; 350 box.x = con->x + con->width - view->border_thickness;
345 box.y = con->y + 1; 351 box.y = con->y + 1;
346 box.width = con->sway_view->border_thickness; 352 box.width = view->border_thickness;
347 box.height = con->height - 1; 353 box.height = con->height - 1
354 - view->border_thickness * view->border_bottom;
355 scale_box(&box, output_scale);
348 render_rect(output->wlr_output, output_damage, &box, color); 356 render_rect(output->wlr_output, output_damage, &box, color);
349 } 357 }
350 358
351 if (con->sway_view->border_bottom) { 359 if (view->border_bottom) {
352 // Child border - bottom edge 360 // Child border - bottom edge
353 if (con->parent->children->length == 1 361 if (con->parent->children->length == 1
354 && con->parent->layout == L_VERT) { 362 && con->parent->layout == L_VERT) {
@@ -358,9 +366,10 @@ static void render_container_simple_border_normal(struct sway_output *output,
358 } 366 }
359 color[3] *= con->alpha; 367 color[3] *= con->alpha;
360 box.x = con->x; 368 box.x = con->x;
361 box.y = con->y + con->height - con->sway_view->border_thickness; 369 box.y = con->y + con->height - view->border_thickness;
362 box.width = con->width; 370 box.width = con->width;
363 box.height = con->sway_view->border_thickness; 371 box.height = view->border_thickness;
372 scale_box(&box, output_scale);
364 render_rect(output->wlr_output, output_damage, &box, color); 373 render_rect(output->wlr_output, output_damage, &box, color);
365 } 374 }
366 375
@@ -371,71 +380,118 @@ static void render_container_simple_border_normal(struct sway_output *output,
371 box.y = con->y; 380 box.y = con->y;
372 box.width = con->width; 381 box.width = con->width;
373 box.height = 1; 382 box.height = 1;
383 scale_box(&box, output_scale);
374 render_rect(output->wlr_output, output_damage, &box, color); 384 render_rect(output->wlr_output, output_damage, &box, color);
375 385
376 // Single pixel bar below title 386 // Single pixel bar below title
377 memcpy(&color, colors->border, sizeof(float) * 4); 387 memcpy(&color, colors->border, sizeof(float) * 4);
378 color[3] *= con->alpha; 388 color[3] *= con->alpha;
379 box.x = con->x + con->sway_view->border_thickness; 389 box.x = con->x + view->border_thickness;
380 box.y = con->sway_view->y - 1; 390 box.y = view->y - 1;
381 box.width = con->width - con->sway_view->border_thickness * 2; 391 box.width = con->width - view->border_thickness * 2;
382 box.height = 1; 392 box.height = 1;
393 scale_box(&box, output_scale);
383 render_rect(output->wlr_output, output_damage, &box, color); 394 render_rect(output->wlr_output, output_damage, &box, color);
384 395
385 // Title background 396 // Setting these makes marks and title easier
386 memcpy(&color, colors->background, sizeof(float) * 4); 397 size_t inner_x = con->x + view->border_thickness * view->border_left;
387 color[3] *= con->alpha; 398 size_t inner_width = con->width - view->border_thickness * view->border_left
388 box.x = con->x 399 - view->border_thickness * view->border_right;
389 + con->sway_view->border_thickness * con->sway_view->border_left; 400
390 box.y = con->y + 1; 401 // Marks
391 box.width = con->width 402 size_t marks_width = 0;
392 - con->sway_view->border_thickness * con->sway_view->border_left 403 if (config->show_marks && marks_texture) {
393 - con->sway_view->border_thickness * con->sway_view->border_right; 404 struct wlr_box texture_box;
394 box.height = con->sway_view->y - con->y - 2; 405 wlr_texture_get_size(marks_texture,
395 render_rect(output->wlr_output, output_damage, &box, color); 406 &texture_box.width, &texture_box.height);
407 texture_box.x = (inner_x + inner_width) * output_scale - texture_box.width;
408 texture_box.y = (con->y + view->border_thickness) * output_scale;
409
410 float matrix[9];
411 wlr_matrix_project_box(matrix, &texture_box,
412 WL_OUTPUT_TRANSFORM_NORMAL,
413 0.0, output->wlr_output->transform_matrix);
414
415 render_texture(output->wlr_output, output_damage, marks_texture,
416 &texture_box, matrix, con->alpha);
417 marks_width = texture_box.width;
418 }
396 419
397 // Title text 420 // Title text
421 size_t title_width = 0;
398 if (title_texture) { 422 if (title_texture) {
399 float output_scale = output->wlr_output->scale; 423 struct wlr_box texture_box;
400 struct wlr_box texture_box = {
401 .x = box.x * output_scale,
402 .y = box.y * output_scale,
403 };
404 wlr_texture_get_size(title_texture, 424 wlr_texture_get_size(title_texture,
405 &texture_box.width, &texture_box.height); 425 &texture_box.width, &texture_box.height);
426 texture_box.x = inner_x * output_scale;
427 texture_box.y = (con->y + view->border_thickness) * output_scale;
406 428
407 float matrix[9]; 429 float matrix[9];
408 wlr_matrix_project_box(matrix, &texture_box, 430 wlr_matrix_project_box(matrix, &texture_box,
409 WL_OUTPUT_TRANSFORM_NORMAL, 431 WL_OUTPUT_TRANSFORM_NORMAL,
410 0.0, output->wlr_output->transform_matrix); 432 0.0, output->wlr_output->transform_matrix);
411 433
412 texture_box.width = box.width * output_scale; 434 if (inner_width * output_scale - marks_width < texture_box.width) {
435 texture_box.width = inner_width * output_scale - marks_width;
436 }
413 render_texture(output->wlr_output, output_damage, title_texture, 437 render_texture(output->wlr_output, output_damage, title_texture,
414 &texture_box, matrix, 1.0); 438 &texture_box, matrix, con->alpha);
439 title_width = texture_box.width;
440 }
441
442 // Title background - above the text
443 memcpy(&color, colors->background, sizeof(float) * 4);
444 color[3] *= con->alpha;
445 box.x = inner_x;
446 box.y = con->y + 1;
447 box.width = inner_width;
448 box.height = view->border_thickness - 1;
449 scale_box(&box, output_scale);
450 render_rect(output->wlr_output, output_damage, &box, color);
451
452 // Title background - below the text
453 box.y = (con->y + view->border_thickness + config->font_height)
454 * output_scale;
455 render_rect(output->wlr_output, output_damage, &box, color);
456
457 // Title background - filler between title and marks
458 box.width = inner_width * output_scale - title_width - marks_width;
459 if (box.width > 0) {
460 box.x = inner_x * output_scale + title_width;
461 box.y = (con->y + view->border_thickness) * output_scale;
462 box.height = config->font_height * output_scale;
463 render_rect(output->wlr_output, output_damage, &box, color);
415 } 464 }
416} 465}
417 466
418/** 467/**
419 * Render decorations for a view with "border pixel". 468 * Render decorations for a view with "border pixel".
469 *
470 * Care must be taken not to render over the same pixel multiple times,
471 * otherwise the colors will be incorrect when using opacity.
420 */ 472 */
421static void render_container_simple_border_pixel(struct sway_output *output, 473static void render_container_simple_border_pixel(struct sway_output *output,
422 pixman_region32_t *output_damage, struct sway_container *con, 474 pixman_region32_t *output_damage, struct sway_container *con,
423 struct border_colors *colors) { 475 struct border_colors *colors) {
424 struct wlr_box box; 476 struct wlr_box box;
425 float color[4]; 477 float color[4];
478 struct sway_view *view = con->sway_view;
479 float output_scale = output->wlr_output->scale;
426 480
427 if (con->sway_view->border_left) { 481 if (view->border_left) {
428 // Child border - left edge 482 // Child border - left edge
429 memcpy(&color, colors->child_border, sizeof(float) * 4); 483 memcpy(&color, colors->child_border, sizeof(float) * 4);
430 color[3] *= con->alpha; 484 color[3] *= con->alpha;
431 box.x = con->x; 485 box.x = con->x;
432 box.y = con->y; 486 box.y = con->y + view->border_thickness * view->border_top;
433 box.width = con->sway_view->border_thickness; 487 box.width = view->border_thickness;
434 box.height = con->height; 488 box.height = con->height - view->border_thickness
489 * (view->border_top + view->border_bottom);
490 scale_box(&box, output_scale);
435 render_rect(output->wlr_output, output_damage, &box, color); 491 render_rect(output->wlr_output, output_damage, &box, color);
436 } 492 }
437 493
438 if (con->sway_view->border_right) { 494 if (view->border_right) {
439 // Child border - right edge 495 // Child border - right edge
440 if (con->parent->children->length == 1 496 if (con->parent->children->length == 1
441 && con->parent->layout == L_HORIZ) { 497 && con->parent->layout == L_HORIZ) {
@@ -444,25 +500,28 @@ static void render_container_simple_border_pixel(struct sway_output *output,
444 memcpy(&color, colors->child_border, sizeof(float) * 4); 500 memcpy(&color, colors->child_border, sizeof(float) * 4);
445 } 501 }
446 color[3] *= con->alpha; 502 color[3] *= con->alpha;
447 box.x = con->x + con->width - con->sway_view->border_thickness; 503 box.x = con->x + con->width - view->border_thickness;
448 box.y = con->y; 504 box.y = con->y + view->border_thickness * view->border_top;
449 box.width = con->sway_view->border_thickness; 505 box.width = view->border_thickness;
450 box.height = con->height; 506 box.height = con->height - view->border_thickness
507 * (view->border_top + view->border_bottom);
508 scale_box(&box, output_scale);
451 render_rect(output->wlr_output, output_damage, &box, color); 509 render_rect(output->wlr_output, output_damage, &box, color);
452 } 510 }
453 511
454 if (con->sway_view->border_top) { 512 if (view->border_top) {
455 // Child border - top edge 513 // Child border - top edge
456 memcpy(&color, colors->child_border, sizeof(float) * 4); 514 memcpy(&color, colors->child_border, sizeof(float) * 4);
457 color[3] *= con->alpha; 515 color[3] *= con->alpha;
458 box.x = con->x; 516 box.x = con->x;
459 box.y = con->y; 517 box.y = con->y;
460 box.width = con->width; 518 box.width = con->width;
461 box.height = con->sway_view->border_thickness; 519 box.height = view->border_thickness;
520 scale_box(&box, output_scale);
462 render_rect(output->wlr_output, output_damage, &box, color); 521 render_rect(output->wlr_output, output_damage, &box, color);
463 } 522 }
464 523
465 if (con->sway_view->border_bottom) { 524 if (view->border_bottom) {
466 // Child border - bottom edge 525 // Child border - bottom edge
467 if (con->parent->children->length == 1 526 if (con->parent->children->length == 1
468 && con->parent->layout == L_VERT) { 527 && con->parent->layout == L_VERT) {
@@ -472,9 +531,10 @@ static void render_container_simple_border_pixel(struct sway_output *output,
472 } 531 }
473 color[3] *= con->alpha; 532 color[3] *= con->alpha;
474 box.x = con->x; 533 box.x = con->x;
475 box.y = con->y + con->height - con->sway_view->border_thickness; 534 box.y = con->y + con->height - view->border_thickness;
476 box.width = con->width; 535 box.width = con->width;
477 box.height = con->sway_view->border_thickness; 536 box.height = view->border_thickness;
537 scale_box(&box, output_scale);
478 render_rect(output->wlr_output, output_damage, &box, color); 538 render_rect(output->wlr_output, output_damage, &box, color);
479 } 539 }
480} 540}
@@ -501,20 +561,24 @@ static void render_container_simple(struct sway_output *output,
501 if (child->sway_view->border != B_NONE) { 561 if (child->sway_view->border != B_NONE) {
502 struct border_colors *colors; 562 struct border_colors *colors;
503 struct wlr_texture *title_texture; 563 struct wlr_texture *title_texture;
564 struct wlr_texture *marks_texture;
504 if (focus == child || parent_focused) { 565 if (focus == child || parent_focused) {
505 colors = &config->border_colors.focused; 566 colors = &config->border_colors.focused;
506 title_texture = child->title_focused; 567 title_texture = child->title_focused;
568 marks_texture = child->sway_view->marks_focused;
507 } else if (seat_get_focus_inactive(seat, con) == child) { 569 } else if (seat_get_focus_inactive(seat, con) == child) {
508 colors = &config->border_colors.focused_inactive; 570 colors = &config->border_colors.focused_inactive;
509 title_texture = child->title_focused_inactive; 571 title_texture = child->title_focused_inactive;
572 marks_texture = child->sway_view->marks_focused_inactive;
510 } else { 573 } else {
511 colors = &config->border_colors.unfocused; 574 colors = &config->border_colors.unfocused;
512 title_texture = child->title_unfocused; 575 title_texture = child->title_unfocused;
576 marks_texture = child->sway_view->marks_unfocused;
513 } 577 }
514 578
515 if (child->sway_view->border == B_NORMAL) { 579 if (child->sway_view->border == B_NORMAL) {
516 render_container_simple_border_normal(output, damage, 580 render_container_simple_border_normal(output, damage,
517 child, colors, title_texture); 581 child, colors, title_texture, marks_texture);
518 } else { 582 } else {
519 render_container_simple_border_pixel(output, damage, child, 583 render_container_simple_border_pixel(output, damage, child,
520 colors); 584 colors);
@@ -898,10 +962,15 @@ static void handle_transform(struct wl_listener *listener, void *data) {
898 arrange_output(output->swayc); 962 arrange_output(output->swayc);
899} 963}
900 964
965static void handle_scale_iterator(struct sway_container *view, void *data) {
966 view_update_marks_textures(view->sway_view);
967}
968
901static void handle_scale(struct wl_listener *listener, void *data) { 969static void handle_scale(struct wl_listener *listener, void *data) {
902 struct sway_output *output = wl_container_of(listener, output, scale); 970 struct sway_output *output = wl_container_of(listener, output, scale);
903 arrange_layers(output); 971 arrange_layers(output);
904 arrange_output(output->swayc); 972 arrange_output(output->swayc);
973 container_descendants(output->swayc, C_VIEW, handle_scale_iterator, NULL);
905} 974}
906 975
907void handle_new_output(struct wl_listener *listener, void *data) { 976void handle_new_output(struct wl_listener *listener, void *data) {
diff --git a/sway/meson.build b/sway/meson.build
index ed14b51a..72347d51 100644
--- a/sway/meson.build
+++ b/sway/meson.build
@@ -60,6 +60,7 @@ sway_sources = files(
60 'commands/seat/cursor.c', 60 'commands/seat/cursor.c',
61 'commands/seat/fallback.c', 61 'commands/seat/fallback.c',
62 'commands/set.c', 62 'commands/set.c',
63 'commands/show_marks.c',
63 'commands/split.c', 64 'commands/split.c',
64 'commands/swaybg_command.c', 65 'commands/swaybg_command.c',
65 'commands/title_format.c', 66 'commands/title_format.c',
diff --git a/sway/sway.5.scd b/sway/sway.5.scd
index 2ebdb8ed..ff138562 100644
--- a/sway/sway.5.scd
+++ b/sway/sway.5.scd
@@ -174,7 +174,7 @@ runtime.
174 Assigns views matching _criteria_ (see *CRITERIA* for details) to 174 Assigns views matching _criteria_ (see *CRITERIA* for details) to
175 _workspace_. The → (U+2192) is optional and cosmetic. This command is 175 _workspace_. The → (U+2192) is optional and cosmetic. This command is
176 equivalent to: 176 equivalent to:
177 177
178 for\_window <criteria> move container to workspace <workspace> 178 for\_window <criteria> move container to workspace <workspace>
179 179
180*bindsym* <key combo> <command> 180*bindsym* <key combo> <command>
@@ -238,7 +238,7 @@ The default colors are:
238[- *class* 238[- *class*
239:[ _border_ 239:[ _border_
240:[ _background_ 240:[ _background_
241:[ _text_ 241:[ _text_
242:[ _indicator_ 242:[ _indicator_
243:[ _child\_border_ 243:[ _child\_border_
244|[ *background* 244|[ *background*
@@ -451,10 +451,10 @@ You can get a list of output names with *swaymsg -t get\_outputs*. You may also
451match any output by using the output name "\*". Be sure to add this output 451match any output by using the output name "\*". Be sure to add this output
452config after the others, or it will be matched instead of the others. 452config after the others, or it will be matched instead of the others.
453 453
454*show\_marks* on|off 454*show\_marks* yes|no
455 If *show\_marks* is on, marks will be displayed in the window borders. 455 If *show\_marks* is yes, marks will be displayed in the window borders.
456 Any mark that starts with an underscore will not be drawn even if the 456 Any mark that starts with an underscore will not be drawn even if
457 option is on. The default is _on_. 457 *show\_marks* is yes. The default is _yes_.
458 458
459*opacity* <value> 459*opacity* <value>
460 Set the opacity of the window between 0 (completely transparent) and 1 460 Set the opacity of the window between 0 (completely transparent) and 1
diff --git a/sway/tree/container.c b/sway/tree/container.c
index a17b20f7..e47338e7 100644
--- a/sway/tree/container.c
+++ b/sway/tree/container.c
@@ -123,13 +123,12 @@ static void _container_destroy(struct sway_container *cont) {
123 if (cont->name) { 123 if (cont->name) {
124 free(cont->name); 124 free(cont->name);
125 } 125 }
126 if (cont->title_focused) { 126
127 // If one is set then all of these are set 127 wlr_texture_destroy(cont->title_focused);
128 wlr_texture_destroy(cont->title_focused); 128 wlr_texture_destroy(cont->title_focused_inactive);
129 wlr_texture_destroy(cont->title_focused_inactive); 129 wlr_texture_destroy(cont->title_unfocused);
130 wlr_texture_destroy(cont->title_unfocused); 130 wlr_texture_destroy(cont->title_urgent);
131 wlr_texture_destroy(cont->title_urgent); 131
132 }
133 list_free(cont->children); 132 list_free(cont->children);
134 cont->children = NULL; 133 cont->children = NULL;
135 free(cont); 134 free(cont);
@@ -592,6 +591,7 @@ static void update_title_texture(struct sway_container *con,
592 } 591 }
593 if (*texture) { 592 if (*texture) {
594 wlr_texture_destroy(*texture); 593 wlr_texture_destroy(*texture);
594 *texture = NULL;
595 } 595 }
596 if (!con->formatted_title) { 596 if (!con->formatted_title) {
597 return; 597 return;
diff --git a/sway/tree/view.c b/sway/tree/view.c
index 833345c5..648c1655 100644
--- a/sway/tree/view.c
+++ b/sway/tree/view.c
@@ -43,6 +43,11 @@ void view_destroy(struct sway_view *view) {
43 } 43 }
44 list_free(view->marks); 44 list_free(view->marks);
45 45
46 wlr_texture_destroy(view->marks_focused);
47 wlr_texture_destroy(view->marks_focused_inactive);
48 wlr_texture_destroy(view->marks_unfocused);
49 wlr_texture_destroy(view->marks_urgent);
50
46 container_destroy(view->swayc); 51 container_destroy(view->swayc);
47 52
48 if (view->impl->destroy) { 53 if (view->impl->destroy) {
@@ -746,6 +751,7 @@ bool view_find_and_unmark(char *mark) {
746 if (strcmp(view_mark, mark) == 0) { 751 if (strcmp(view_mark, mark) == 0) {
747 free(view_mark); 752 free(view_mark);
748 list_del(view->marks, i); 753 list_del(view->marks, i);
754 view_update_marks_textures(view);
749 return true; 755 return true;
750 } 756 }
751 } 757 }
@@ -769,3 +775,91 @@ bool view_has_mark(struct sway_view *view, char *mark) {
769 } 775 }
770 return false; 776 return false;
771} 777}
778
779static void update_marks_texture(struct sway_view *view,
780 struct wlr_texture **texture, struct border_colors *class) {
781 struct sway_container *output = container_parent(view->swayc, C_OUTPUT);
782 if (!output) {
783 return;
784 }
785 if (*texture) {
786 wlr_texture_destroy(*texture);
787 *texture = NULL;
788 }
789 if (!view->marks->length) {
790 return;
791 }
792
793 size_t len = 0;
794 for (int i = 0; i < view->marks->length; ++i) {
795 char *mark = view->marks->items[i];
796 if (mark[0] != '_') {
797 len += strlen(mark) + 2;
798 }
799 }
800 char *buffer = calloc(len + 1, 1);
801 char *part = malloc(len + 1);
802
803 if (!sway_assert(buffer && part, "Unable to allocate memory")) {
804 free(buffer);
805 return;
806 }
807
808 for (int i = 0; i < view->marks->length; ++i) {
809 char *mark = view->marks->items[i];
810 if (mark[0] != '_') {
811 sprintf(part, "[%s]", mark);
812 strcat(buffer, part);
813 }
814 }
815 free(part);
816
817 double scale = output->sway_output->wlr_output->scale;
818 int width = 0;
819 int height = config->font_height * scale;
820
821 cairo_t *c = cairo_create(NULL);
822 get_text_size(c, config->font, &width, NULL, scale, false, "%s", buffer);
823 cairo_destroy(c);
824
825 cairo_surface_t *surface = cairo_image_surface_create(
826 CAIRO_FORMAT_ARGB32, width, height);
827 cairo_t *cairo = cairo_create(surface);
828 cairo_set_source_rgba(cairo, class->background[0], class->background[1],
829 class->background[2], class->background[3]);
830 cairo_paint(cairo);
831 PangoContext *pango = pango_cairo_create_context(cairo);
832 cairo_set_antialias(cairo, CAIRO_ANTIALIAS_BEST);
833 cairo_set_source_rgba(cairo, class->text[0], class->text[1],
834 class->text[2], class->text[3]);
835 cairo_move_to(cairo, 0, 0);
836
837 pango_printf(cairo, config->font, scale, false, "%s", buffer);
838
839 cairo_surface_flush(surface);
840 unsigned char *data = cairo_image_surface_get_data(surface);
841 int stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, width);
842 struct wlr_renderer *renderer = wlr_backend_get_renderer(
843 output->sway_output->wlr_output->backend);
844 *texture = wlr_texture_from_pixels(
845 renderer, WL_SHM_FORMAT_ARGB8888, stride, width, height, data);
846 cairo_surface_destroy(surface);
847 g_object_unref(pango);
848 cairo_destroy(cairo);
849 free(buffer);
850}
851
852void view_update_marks_textures(struct sway_view *view) {
853 if (!config->show_marks) {
854 return;
855 }
856 update_marks_texture(view, &view->marks_focused,
857 &config->border_colors.focused);
858 update_marks_texture(view, &view->marks_focused_inactive,
859 &config->border_colors.focused_inactive);
860 update_marks_texture(view, &view->marks_unfocused,
861 &config->border_colors.unfocused);
862 update_marks_texture(view, &view->marks_urgent,
863 &config->border_colors.urgent);
864 container_damage_whole(view->swayc);
865}