summaryrefslogtreecommitdiffstats
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
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.
-rw-r--r--include/sway/commands.h1
-rw-r--r--include/sway/tree/view.h8
-rw-r--r--include/sway/tree/workspace.h3
-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
12 files changed, 170 insertions, 7 deletions
diff --git a/include/sway/commands.h b/include/sway/commands.h
index 3ebd0002..1e93e2a3 100644
--- a/include/sway/commands.h
+++ b/include/sway/commands.h
@@ -152,6 +152,7 @@ sway_cmd cmd_swaybg_command;
152sway_cmd cmd_swap; 152sway_cmd cmd_swap;
153sway_cmd cmd_title_format; 153sway_cmd cmd_title_format;
154sway_cmd cmd_unmark; 154sway_cmd cmd_unmark;
155sway_cmd cmd_urgent;
155sway_cmd cmd_workspace; 156sway_cmd cmd_workspace;
156sway_cmd cmd_ws_auto_back_and_forth; 157sway_cmd cmd_ws_auto_back_and_forth;
157sway_cmd cmd_workspace_layout; 158sway_cmd cmd_workspace_layout;
diff --git a/include/sway/tree/view.h b/include/sway/tree/view.h
index 21d6403e..9022f7a6 100644
--- a/include/sway/tree/view.h
+++ b/include/sway/tree/view.h
@@ -70,6 +70,10 @@ struct sway_view {
70 bool border_left; 70 bool border_left;
71 bool border_right; 71 bool border_right;
72 72
73 struct timespec urgent;
74 bool allow_request_urgent;
75 struct wl_event_source *urgent_timer;
76
73 bool destroying; 77 bool destroying;
74 78
75 list_t *executed_criteria; // struct criteria * 79 list_t *executed_criteria; // struct criteria *
@@ -305,4 +309,8 @@ void view_update_marks_textures(struct sway_view *view);
305 */ 309 */
306bool view_is_visible(struct sway_view *view); 310bool view_is_visible(struct sway_view *view);
307 311
312void view_set_urgent(struct sway_view *view, bool enable);
313
314bool view_is_urgent(struct sway_view *view);
315
308#endif 316#endif
diff --git a/include/sway/tree/workspace.h b/include/sway/tree/workspace.h
index c72a4ac0..8c2f4cd5 100644
--- a/include/sway/tree/workspace.h
+++ b/include/sway/tree/workspace.h
@@ -42,4 +42,7 @@ void workspace_output_add_priority(struct sway_container *workspace,
42 42
43struct sway_container *workspace_output_get_highest_available( 43struct sway_container *workspace_output_get_highest_available(
44 struct sway_container *ws, struct sway_container *exclude); 44 struct sway_container *ws, struct sway_container *exclude);
45
46bool workspace_is_urgent(struct sway_container *workspace);
47
45#endif 48#endif
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}