summaryrefslogtreecommitdiffstats
path: root/sway
diff options
context:
space:
mode:
authorLibravatar Ryan Dwyer <ryandwyer1@gmail.com>2018-07-15 22:43:33 +1000
committerLibravatar Ryan Dwyer <ryandwyer1@gmail.com>2018-07-16 08:19:25 +1000
commit315d5311b2004b9e148e7b52a7de161b6dfe3878 (patch)
tree1a70d1d73cbffb26bf432c1c7b395ee996651ad3 /sway
parentMerge pull request #2280 from ianyfan/leaks (diff)
downloadsway-315d5311b2004b9e148e7b52a7de161b6dfe3878.tar.gz
sway-315d5311b2004b9e148e7b52a7de161b6dfe3878.tar.zst
sway-315d5311b2004b9e148e7b52a7de161b6dfe3878.zip
Implement urgency base functionality
Introduces a command to manually set urgency, as well as rendering of urgent views, sending the IPC event, removing urgency after focused for one second, and matching urgent views via criteria.
Diffstat (limited to 'sway')
-rw-r--r--sway/commands.c1
-rw-r--r--sway/commands/urgent.c36
-rw-r--r--sway/criteria.c44
-rw-r--r--sway/desktop/render.c24
-rw-r--r--sway/input/seat.c16
-rw-r--r--sway/ipc-json.c3
-rw-r--r--sway/meson.build1
-rw-r--r--sway/tree/view.c30
-rw-r--r--sway/tree/workspace.c10
9 files changed, 158 insertions, 7 deletions
diff --git a/sway/commands.c b/sway/commands.c
index addd64a6..3578e748 100644
--- a/sway/commands.c
+++ b/sway/commands.c
@@ -153,6 +153,7 @@ static struct cmd_handler command_handlers[] = {
153 { "swap", cmd_swap }, 153 { "swap", cmd_swap },
154 { "title_format", cmd_title_format }, 154 { "title_format", cmd_title_format },
155 { "unmark", cmd_unmark }, 155 { "unmark", cmd_unmark },
156 { "urgent", cmd_urgent },
156}; 157};
157 158
158static int handler_compare(const void *_a, const void *_b) { 159static int handler_compare(const void *_a, const void *_b) {
diff --git a/sway/commands/urgent.c b/sway/commands/urgent.c
new file mode 100644
index 00000000..d199858a
--- /dev/null
+++ b/sway/commands/urgent.c
@@ -0,0 +1,36 @@
1#include "log.h"
2#include "sway/commands.h"
3#include "sway/config.h"
4#include "sway/tree/arrange.h"
5#include "sway/tree/container.h"
6#include "sway/tree/view.h"
7#include "sway/tree/layout.h"
8
9struct cmd_results *cmd_urgent(int argc, char **argv) {
10 struct cmd_results *error = NULL;
11 if ((error = checkarg(argc, "urgent", EXPECTED_EQUAL_TO, 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, "urgent",
18 "Only views can be urgent");
19 }
20 struct sway_view *view = container->sway_view;
21
22 if (strcmp(argv[0], "enable") == 0) {
23 view_set_urgent(view, true);
24 } else if (strcmp(argv[0], "disable") == 0) {
25 view_set_urgent(view, false);
26 } else if (strcmp(argv[0], "allow") == 0) {
27 view->allow_request_urgent = true;
28 } else if (strcmp(argv[0], "deny") == 0) {
29 view->allow_request_urgent = false;
30 } else {
31 return cmd_results_new(CMD_INVALID, "urgent",
32 "Expected 'urgent <enable|disable|allow|deny>'");
33 }
34
35 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
36}
diff --git a/sway/criteria.c b/sway/criteria.c
index 29a3668b..c999d248 100644
--- a/sway/criteria.c
+++ b/sway/criteria.c
@@ -46,6 +46,31 @@ static int regex_cmp(const char *item, const pcre *regex) {
46 return pcre_exec(regex, NULL, item, strlen(item), 0, 0, NULL, 0); 46 return pcre_exec(regex, NULL, item, strlen(item), 0, 0, NULL, 0);
47} 47}
48 48
49static int cmp_urgent(const void *_a, const void *_b) {
50 struct sway_view *a = *(void **)_a;
51 struct sway_view *b = *(void **)_b;
52
53 if (a->urgent.tv_sec < b->urgent.tv_sec) {
54 return -1;
55 } else if (a->urgent.tv_sec > b->urgent.tv_sec) {
56 return 1;
57 }
58 if (a->urgent.tv_nsec < b->urgent.tv_nsec) {
59 return -1;
60 } else if (a->urgent.tv_nsec > b->urgent.tv_nsec) {
61 return 1;
62 }
63 return 0;
64}
65
66static void find_urgent_iterator(struct sway_container *swayc, void *data) {
67 if (swayc->type != C_VIEW || !view_is_urgent(swayc->sway_view)) {
68 return;
69 }
70 list_t *urgent_views = data;
71 list_add(urgent_views, swayc->sway_view);
72}
73
49static bool criteria_matches_view(struct criteria *criteria, 74static bool criteria_matches_view(struct criteria *criteria,
50 struct sway_view *view) { 75 struct sway_view *view) {
51 if (criteria->title) { 76 if (criteria->title) {
@@ -133,8 +158,23 @@ static bool criteria_matches_view(struct criteria *criteria,
133 } 158 }
134 159
135 if (criteria->urgent) { 160 if (criteria->urgent) {
136 // TODO 161 if (!view_is_urgent(view)) {
137 return false; 162 return false;
163 }
164 list_t *urgent_views = create_list();
165 container_for_each_descendant_dfs(&root_container,
166 find_urgent_iterator, urgent_views);
167 list_stable_sort(urgent_views, cmp_urgent);
168 struct sway_view *target;
169 if (criteria->urgent == 'o') { // oldest
170 target = urgent_views->items[0];
171 } else { // latest
172 target = urgent_views->items[urgent_views->length - 1];
173 }
174 list_free(urgent_views);
175 if (view != target) {
176 return false;
177 }
138 } 178 }
139 179
140 if (criteria->workspace) { 180 if (criteria->workspace) {
diff --git a/sway/desktop/render.c b/sway/desktop/render.c
index 17fe823a..3180f8ba 100644
--- a/sway/desktop/render.c
+++ b/sway/desktop/render.c
@@ -553,7 +553,11 @@ static void render_container_simple(struct sway_output *output,
553 struct wlr_texture *marks_texture; 553 struct wlr_texture *marks_texture;
554 struct sway_container_state *state = &child->current; 554 struct sway_container_state *state = &child->current;
555 555
556 if (state->focused || parent_focused) { 556 if (view_is_urgent(view)) {
557 colors = &config->border_colors.urgent;
558 title_texture = child->title_urgent;
559 marks_texture = view->marks_urgent;
560 } else if (state->focused || parent_focused) {
557 colors = &config->border_colors.focused; 561 colors = &config->border_colors.focused;
558 title_texture = child->title_focused; 562 title_texture = child->title_focused;
559 marks_texture = view->marks_focused; 563 marks_texture = view->marks_focused;
@@ -608,7 +612,11 @@ static void render_container_tabbed(struct sway_output *output,
608 struct wlr_texture *title_texture; 612 struct wlr_texture *title_texture;
609 struct wlr_texture *marks_texture; 613 struct wlr_texture *marks_texture;
610 614
611 if (cstate->focused || parent_focused) { 615 if (view && view_is_urgent(view)) {
616 colors = &config->border_colors.urgent;
617 title_texture = child->title_urgent;
618 marks_texture = view->marks_urgent;
619 } else if (cstate->focused || parent_focused) {
612 colors = &config->border_colors.focused; 620 colors = &config->border_colors.focused;
613 title_texture = child->title_focused; 621 title_texture = child->title_focused;
614 marks_texture = view ? view->marks_focused : NULL; 622 marks_texture = view ? view->marks_focused : NULL;
@@ -671,7 +679,11 @@ static void render_container_stacked(struct sway_output *output,
671 struct wlr_texture *title_texture; 679 struct wlr_texture *title_texture;
672 struct wlr_texture *marks_texture; 680 struct wlr_texture *marks_texture;
673 681
674 if (cstate->focused || parent_focused) { 682 if (view && view_is_urgent(view)) {
683 colors = &config->border_colors.urgent;
684 title_texture = child->title_urgent;
685 marks_texture = view->marks_urgent;
686 } else if (cstate->focused || parent_focused) {
675 colors = &config->border_colors.focused; 687 colors = &config->border_colors.focused;
676 title_texture = child->title_focused; 688 title_texture = child->title_focused;
677 marks_texture = view ? view->marks_focused : NULL; 689 marks_texture = view ? view->marks_focused : NULL;
@@ -731,7 +743,11 @@ static void render_floating_container(struct sway_output *soutput,
731 struct wlr_texture *title_texture; 743 struct wlr_texture *title_texture;
732 struct wlr_texture *marks_texture; 744 struct wlr_texture *marks_texture;
733 745
734 if (con->current.focused) { 746 if (view_is_urgent(view)) {
747 colors = &config->border_colors.urgent;
748 title_texture = con->title_urgent;
749 marks_texture = view->marks_urgent;
750 } else if (con->current.focused) {
735 colors = &config->border_colors.focused; 751 colors = &config->border_colors.focused;
736 title_texture = con->title_focused; 752 title_texture = con->title_focused;
737 marks_texture = view->marks_focused; 753 marks_texture = view->marks_focused;
diff --git a/sway/input/seat.c b/sway/input/seat.c
index 74f1375e..7058cc92 100644
--- a/sway/input/seat.c
+++ b/sway/input/seat.c
@@ -594,6 +594,12 @@ static void seat_send_unfocus(struct sway_container *container,
594 } 594 }
595} 595}
596 596
597static int handle_urgent_timeout(void *data) {
598 struct sway_view *view = data;
599 view_set_urgent(view, false);
600 return 0;
601}
602
597void seat_set_focus_warp(struct sway_seat *seat, 603void seat_set_focus_warp(struct sway_seat *seat,
598 struct sway_container *container, bool warp) { 604 struct sway_container *container, bool warp) {
599 if (seat->focused_layer) { 605 if (seat->focused_layer) {
@@ -670,6 +676,16 @@ void seat_set_focus_warp(struct sway_seat *seat,
670 } 676 }
671 } 677 }
672 678
679 // If urgent, start a timer to unset it
680 if (container && container->type == C_VIEW &&
681 view_is_urgent(container->sway_view) &&
682 !container->sway_view->urgent_timer) {
683 struct sway_view *view = container->sway_view;
684 view->urgent_timer = wl_event_loop_add_timer(server.wl_event_loop,
685 handle_urgent_timeout, view);
686 wl_event_source_timer_update(view->urgent_timer, 1000);
687 }
688
673 // If we've focused a floating container, bring it to the front. 689 // If we've focused a floating container, bring it to the front.
674 // We do this by putting it at the end of the floating list. 690 // We do this by putting it at the end of the floating list.
675 // This must happen for both the pending and current children lists. 691 // This must happen for both the pending and current children lists.
diff --git a/sway/ipc-json.c b/sway/ipc-json.c
index 3d0e88f0..8c48e724 100644
--- a/sway/ipc-json.c
+++ b/sway/ipc-json.c
@@ -170,7 +170,8 @@ static void ipc_json_describe_workspace(struct sway_container *workspace,
170 json_object_object_add(object, "output", workspace->parent ? 170 json_object_object_add(object, "output", workspace->parent ?
171 json_object_new_string(workspace->parent->name) : NULL); 171 json_object_new_string(workspace->parent->name) : NULL);
172 json_object_object_add(object, "type", json_object_new_string("workspace")); 172 json_object_object_add(object, "type", json_object_new_string("workspace"));
173 json_object_object_add(object, "urgent", json_object_new_boolean(false)); 173 json_object_object_add(object, "urgent",
174 json_object_new_boolean(workspace_is_urgent(workspace)));
174 json_object_object_add(object, "representation", workspace->formatted_title ? 175 json_object_object_add(object, "representation", workspace->formatted_title ?
175 json_object_new_string(workspace->formatted_title) : NULL); 176 json_object_new_string(workspace->formatted_title) : NULL);
176 177
diff --git a/sway/meson.build b/sway/meson.build
index f878450d..b64bd137 100644
--- a/sway/meson.build
+++ b/sway/meson.build
@@ -76,6 +76,7 @@ sway_sources = files(
76 'commands/swap.c', 76 'commands/swap.c',
77 'commands/title_format.c', 77 'commands/title_format.c',
78 'commands/unmark.c', 78 'commands/unmark.c',
79 'commands/urgent.c',
79 'commands/workspace.c', 80 'commands/workspace.c',
80 'commands/workspace_layout.c', 81 'commands/workspace_layout.c',
81 'commands/ws_auto_back_and_forth.c', 82 'commands/ws_auto_back_and_forth.c',
diff --git a/sway/tree/view.c b/sway/tree/view.c
index bf380d98..a2dbe92c 100644
--- a/sway/tree/view.c
+++ b/sway/tree/view.c
@@ -25,6 +25,7 @@ void view_init(struct sway_view *view, enum sway_view_type type,
25 view->impl = impl; 25 view->impl = impl;
26 view->executed_criteria = create_list(); 26 view->executed_criteria = create_list();
27 view->marks = create_list(); 27 view->marks = create_list();
28 view->allow_request_urgent = true;
28 wl_signal_init(&view->events.unmap); 29 wl_signal_init(&view->events.unmap);
29} 30}
30 31
@@ -589,6 +590,11 @@ void view_unmap(struct sway_view *view) {
589 wl_list_remove(&view->surface_new_subsurface.link); 590 wl_list_remove(&view->surface_new_subsurface.link);
590 wl_list_remove(&view->container_reparent.link); 591 wl_list_remove(&view->container_reparent.link);
591 592
593 if (view->urgent_timer) {
594 wl_event_source_remove(view->urgent_timer);
595 view->urgent_timer = NULL;
596 }
597
592 if (view->is_fullscreen) { 598 if (view->is_fullscreen) {
593 struct sway_container *ws = container_parent(view->swayc, C_WORKSPACE); 599 struct sway_container *ws = container_parent(view->swayc, C_WORKSPACE);
594 ws->sway_workspace->fullscreen = NULL; 600 ws->sway_workspace->fullscreen = NULL;
@@ -1047,3 +1053,27 @@ bool view_is_visible(struct sway_view *view) {
1047 } 1053 }
1048 return true; 1054 return true;
1049} 1055}
1056
1057void view_set_urgent(struct sway_view *view, bool enable) {
1058 if (enable) {
1059 struct sway_seat *seat = input_manager_current_seat(input_manager);
1060 if (seat_get_focus(seat) == view->swayc) {
1061 return;
1062 }
1063 clock_gettime(CLOCK_MONOTONIC, &view->urgent);
1064 } else {
1065 view->urgent = (struct timespec){ 0 };
1066 if (view->urgent_timer) {
1067 wl_event_source_remove(view->urgent_timer);
1068 view->urgent_timer = NULL;
1069 }
1070 }
1071 container_damage_whole(view->swayc);
1072
1073 struct sway_container *ws = container_parent(view->swayc, C_WORKSPACE);
1074 ipc_event_workspace(ws, NULL, "urgent");
1075}
1076
1077bool view_is_urgent(struct sway_view *view) {
1078 return view->urgent.tv_sec || view->urgent.tv_nsec;
1079}
diff --git a/sway/tree/workspace.c b/sway/tree/workspace.c
index 2a2d834a..d71b0a53 100644
--- a/sway/tree/workspace.c
+++ b/sway/tree/workspace.c
@@ -11,6 +11,7 @@
11#include "sway/ipc-server.h" 11#include "sway/ipc-server.h"
12#include "sway/tree/arrange.h" 12#include "sway/tree/arrange.h"
13#include "sway/tree/container.h" 13#include "sway/tree/container.h"
14#include "sway/tree/view.h"
14#include "sway/tree/workspace.h" 15#include "sway/tree/workspace.h"
15#include "list.h" 16#include "list.h"
16#include "log.h" 17#include "log.h"
@@ -518,3 +519,12 @@ struct sway_container *workspace_output_get_highest_available(
518 519
519 return NULL; 520 return NULL;
520} 521}
522
523static bool find_urgent_iterator(struct sway_container *con,
524 void *data) {
525 return con->type == C_VIEW && view_is_urgent(con->sway_view);
526}
527
528bool workspace_is_urgent(struct sway_container *workspace) {
529 return container_find(workspace, find_urgent_iterator, NULL);
530}