diff options
author | Drew DeVault <sir@cmpwn.com> | 2018-05-16 21:54:16 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-05-16 21:54:16 -0400 |
commit | c2c5a3f5f6bdc061acae4e0583c4fd85c7ed21ac (patch) | |
tree | 02f3205870487dbedb981a1770a6ec77c8894c15 | |
parent | Merge pull request #1995 from RedSoxFan/fix-1985 (diff) | |
parent | Update marks textures on output scale event (diff) | |
download | sway-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.h | 7 | ||||
-rw-r--r-- | sway/commands.c | 1 | ||||
-rw-r--r-- | sway/commands/mark.c | 1 | ||||
-rw-r--r-- | sway/commands/show_marks.c | 43 | ||||
-rw-r--r-- | sway/commands/unmark.c | 2 | ||||
-rw-r--r-- | sway/desktop/output.c | 165 | ||||
-rw-r--r-- | sway/meson.build | 1 | ||||
-rw-r--r-- | sway/sway.5.scd | 12 | ||||
-rw-r--r-- | sway/tree/container.c | 14 | ||||
-rw-r--r-- | sway/tree/view.c | 94 |
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 | ||
268 | bool view_has_mark(struct sway_view *view, char *mark); | 273 | bool view_has_mark(struct sway_view *view, char *mark); |
269 | 274 | ||
275 | void 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 | |||
11 | static 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 | |||
17 | struct 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 @@ | |||
10 | static void remove_all_marks_iterator(struct sway_container *con, void *data) { | 10 | static 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 | */ |
317 | static void render_container_simple_border_normal(struct sway_output *output, | 319 | static 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 | */ |
421 | static void render_container_simple_border_pixel(struct sway_output *output, | 473 | static 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 | ||
965 | static void handle_scale_iterator(struct sway_container *view, void *data) { | ||
966 | view_update_marks_textures(view->sway_view); | ||
967 | } | ||
968 | |||
901 | static void handle_scale(struct wl_listener *listener, void *data) { | 969 | static 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 | ||
907 | void handle_new_output(struct wl_listener *listener, void *data) { | 976 | void 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 | |||
451 | match any output by using the output name "\*". Be sure to add this output | 451 | match any output by using the output name "\*". Be sure to add this output |
452 | config after the others, or it will be matched instead of the others. | 452 | config 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 | |||
779 | static 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 | |||
852 | void 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 | } | ||