aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar Brian Ashworth <bosrsf04@gmail.com>2019-03-24 21:21:24 -0400
committerLibravatar Drew DeVault <sir@cmpwn.com>2019-03-24 19:26:12 -0600
commitd9de5b87583ccf8b633980ebbdec67227bbe7db4 (patch)
tree4084a568e8b28e2e37142b8a293e00f619d48e17
parentFix #3924 (diff)
downloadsway-d9de5b87583ccf8b633980ebbdec67227bbe7db4.tar.gz
sway-d9de5b87583ccf8b633980ebbdec67227bbe7db4.tar.zst
sway-d9de5b87583ccf8b633980ebbdec67227bbe7db4.zip
Implement inhibit_idle command
This implements the following command to set/unset a user idle inhibitor for a view: `inhibit_idle focus|fullscreen|open|none|visible` The modes are as follows: - focus: inhibited when the view is focused by any seat - fullscreen: inhibited when the view is fullscreen (or a descendant of a fullscreen container) and is visible on any output - open: inhibited until the view is closed or the inhibitor is unset or changed - none: unsets any user set idle inhibitors for the view - visible: inhibited when the view is visible on any output This should have no effect on idle inhibitors set by the applications themselves and those should still work as intended. Since this operates on the view in the handler context, it is possible to set it on the currently focused view, on any existing view with criteria, or for any future view with for_window.
-rw-r--r--include/sway/commands.h1
-rw-r--r--include/sway/desktop/idle_inhibit_v1.h20
-rw-r--r--sway/commands.c1
-rw-r--r--sway/commands/inhibit_idle.c51
-rw-r--r--sway/desktop/idle_inhibit_v1.c99
-rw-r--r--sway/desktop/transaction.c2
-rw-r--r--sway/meson.build1
-rw-r--r--sway/sway.5.scd12
8 files changed, 171 insertions, 16 deletions
diff --git a/include/sway/commands.h b/include/sway/commands.h
index 7533a14d..9bd0f1cb 100644
--- a/include/sway/commands.h
+++ b/include/sway/commands.h
@@ -136,6 +136,7 @@ sway_cmd cmd_fullscreen;
136sway_cmd cmd_gaps; 136sway_cmd cmd_gaps;
137sway_cmd cmd_hide_edge_borders; 137sway_cmd cmd_hide_edge_borders;
138sway_cmd cmd_include; 138sway_cmd cmd_include;
139sway_cmd cmd_inhibit_idle;
139sway_cmd cmd_input; 140sway_cmd cmd_input;
140sway_cmd cmd_seat; 141sway_cmd cmd_seat;
141sway_cmd cmd_ipc; 142sway_cmd cmd_ipc;
diff --git a/include/sway/desktop/idle_inhibit_v1.h b/include/sway/desktop/idle_inhibit_v1.h
index e5ed8a3d..4d4e59b0 100644
--- a/include/sway/desktop/idle_inhibit_v1.h
+++ b/include/sway/desktop/idle_inhibit_v1.h
@@ -4,6 +4,14 @@
4#include <wlr/types/wlr_idle.h> 4#include <wlr/types/wlr_idle.h>
5#include "sway/server.h" 5#include "sway/server.h"
6 6
7enum sway_idle_inhibit_mode {
8 INHIBIT_IDLE_APPLICATION, // Application set inhibitor (when visible)
9 INHIBIT_IDLE_FOCUS, // User set inhibitor when focused
10 INHIBIT_IDLE_FULLSCREEN, // User set inhibitor when fullscreen + visible
11 INHIBIT_IDLE_OPEN, // User set inhibitor while open
12 INHIBIT_IDLE_VISIBLE // User set inhibitor when visible
13};
14
7struct sway_idle_inhibit_manager_v1 { 15struct sway_idle_inhibit_manager_v1 {
8 struct wlr_idle_inhibit_manager_v1 *wlr_manager; 16 struct wlr_idle_inhibit_manager_v1 *wlr_manager;
9 struct wl_listener new_idle_inhibitor_v1; 17 struct wl_listener new_idle_inhibitor_v1;
@@ -15,14 +23,24 @@ struct sway_idle_inhibit_manager_v1 {
15struct sway_idle_inhibitor_v1 { 23struct sway_idle_inhibitor_v1 {
16 struct sway_idle_inhibit_manager_v1 *manager; 24 struct sway_idle_inhibit_manager_v1 *manager;
17 struct sway_view *view; 25 struct sway_view *view;
26 enum sway_idle_inhibit_mode mode;
18 27
19 struct wl_list link; 28 struct wl_list link;
20 struct wl_listener destroy; 29 struct wl_listener destroy;
21}; 30};
22 31
23void idle_inhibit_v1_check_active( 32void sway_idle_inhibit_v1_check_active(
24 struct sway_idle_inhibit_manager_v1 *manager); 33 struct sway_idle_inhibit_manager_v1 *manager);
25 34
35void sway_idle_inhibit_v1_user_inhibitor_register(struct sway_view *view,
36 enum sway_idle_inhibit_mode mode);
37
38struct sway_idle_inhibitor_v1 *sway_idle_inhibit_v1_user_inhibitor_for_view(
39 struct sway_view *view);
40
41void sway_idle_inhibit_v1_user_inhibitor_destroy(
42 struct sway_idle_inhibitor_v1 *inhibitor);
43
26struct sway_idle_inhibit_manager_v1 *sway_idle_inhibit_manager_v1_create( 44struct sway_idle_inhibit_manager_v1 *sway_idle_inhibit_manager_v1_create(
27 struct wl_display *wl_display, struct wlr_idle *idle); 45 struct wl_display *wl_display, struct wlr_idle *idle);
28#endif 46#endif
diff --git a/sway/commands.c b/sway/commands.c
index 0d9460a2..abdaa3b8 100644
--- a/sway/commands.c
+++ b/sway/commands.c
@@ -112,6 +112,7 @@ static struct cmd_handler command_handlers[] = {
112 { "exit", cmd_exit }, 112 { "exit", cmd_exit },
113 { "floating", cmd_floating }, 113 { "floating", cmd_floating },
114 { "fullscreen", cmd_fullscreen }, 114 { "fullscreen", cmd_fullscreen },
115 { "inhibit_idle", cmd_inhibit_idle },
115 { "kill", cmd_kill }, 116 { "kill", cmd_kill },
116 { "layout", cmd_layout }, 117 { "layout", cmd_layout },
117 { "mark", cmd_mark }, 118 { "mark", cmd_mark },
diff --git a/sway/commands/inhibit_idle.c b/sway/commands/inhibit_idle.c
new file mode 100644
index 00000000..aebc2bf9
--- /dev/null
+++ b/sway/commands/inhibit_idle.c
@@ -0,0 +1,51 @@
1#include <string.h>
2#include "sway/commands.h"
3#include "sway/config.h"
4#include "sway/desktop/idle_inhibit_v1.h"
5#include "sway/tree/container.h"
6#include "sway/tree/view.h"
7
8struct cmd_results *cmd_inhibit_idle(int argc, char **argv) {
9 struct cmd_results *error = NULL;
10 if ((error = checkarg(argc, "inhibit_idle", EXPECTED_EQUAL_TO, 1))) {
11 return error;
12 }
13
14 struct sway_container *con = config->handler_context.container;
15 if (!con || !con->view) {
16 return cmd_results_new(CMD_INVALID,
17 "Only views can have idle inhibitors");
18 }
19
20 bool clear = false;
21 enum sway_idle_inhibit_mode mode;
22 if (strcmp(argv[0], "focus") == 0) {
23 mode = INHIBIT_IDLE_FOCUS;
24 } else if (strcmp(argv[0], "fullscreen") == 0) {
25 mode = INHIBIT_IDLE_FULLSCREEN;
26 } else if (strcmp(argv[0], "open") == 0) {
27 mode = INHIBIT_IDLE_OPEN;
28 } else if (strcmp(argv[0], "none") == 0) {
29 clear = true;
30 } else if (strcmp(argv[0], "visible") == 0) {
31 mode = INHIBIT_IDLE_VISIBLE;
32 } else {
33 return cmd_results_new(CMD_INVALID,
34 "Expected `inhibit_idle focus|fullscreen|open|none|visible`");
35 }
36
37 struct sway_idle_inhibitor_v1 *inhibitor =
38 sway_idle_inhibit_v1_user_inhibitor_for_view(con->view);
39 if (inhibitor) {
40 if (clear) {
41 sway_idle_inhibit_v1_user_inhibitor_destroy(inhibitor);
42 } else {
43 inhibitor->mode = mode;
44 sway_idle_inhibit_v1_check_active(server.idle_inhibit_manager_v1);
45 }
46 } else if (!clear) {
47 sway_idle_inhibit_v1_user_inhibitor_register(con->view, mode);
48 }
49
50 return cmd_results_new(CMD_SUCCESS, NULL);
51}
diff --git a/sway/desktop/idle_inhibit_v1.c b/sway/desktop/idle_inhibit_v1.c
index 87b4ef43..b981e5e5 100644
--- a/sway/desktop/idle_inhibit_v1.c
+++ b/sway/desktop/idle_inhibit_v1.c
@@ -2,18 +2,24 @@
2#include <wlr/types/wlr_idle.h> 2#include <wlr/types/wlr_idle.h>
3#include "log.h" 3#include "log.h"
4#include "sway/desktop/idle_inhibit_v1.h" 4#include "sway/desktop/idle_inhibit_v1.h"
5#include "sway/input/seat.h"
6#include "sway/tree/container.h"
5#include "sway/tree/view.h" 7#include "sway/tree/view.h"
6#include "sway/server.h" 8#include "sway/server.h"
7 9
8 10
11static void destroy_inhibitor(struct sway_idle_inhibitor_v1 *inhibitor) {
12 wl_list_remove(&inhibitor->link);
13 wl_list_remove(&inhibitor->destroy.link);
14 sway_idle_inhibit_v1_check_active(inhibitor->manager);
15 free(inhibitor);
16}
17
9static void handle_destroy(struct wl_listener *listener, void *data) { 18static void handle_destroy(struct wl_listener *listener, void *data) {
10 struct sway_idle_inhibitor_v1 *inhibitor = 19 struct sway_idle_inhibitor_v1 *inhibitor =
11 wl_container_of(listener, inhibitor, destroy); 20 wl_container_of(listener, inhibitor, destroy);
12 sway_log(SWAY_DEBUG, "Sway idle inhibitor destroyed"); 21 sway_log(SWAY_DEBUG, "Sway idle inhibitor destroyed");
13 wl_list_remove(&inhibitor->link); 22 destroy_inhibitor(inhibitor);
14 wl_list_remove(&inhibitor->destroy.link);
15 idle_inhibit_v1_check_active(inhibitor->manager);
16 free(inhibitor);
17} 23}
18 24
19void handle_idle_inhibitor_v1(struct wl_listener *listener, void *data) { 25void handle_idle_inhibitor_v1(struct wl_listener *listener, void *data) {
@@ -29,28 +35,93 @@ void handle_idle_inhibitor_v1(struct wl_listener *listener, void *data) {
29 } 35 }
30 36
31 inhibitor->manager = manager; 37 inhibitor->manager = manager;
38 inhibitor->mode = INHIBIT_IDLE_APPLICATION;
32 inhibitor->view = view_from_wlr_surface(wlr_inhibitor->surface); 39 inhibitor->view = view_from_wlr_surface(wlr_inhibitor->surface);
33 wl_list_insert(&manager->inhibitors, &inhibitor->link); 40 wl_list_insert(&manager->inhibitors, &inhibitor->link);
34 41
35
36 inhibitor->destroy.notify = handle_destroy; 42 inhibitor->destroy.notify = handle_destroy;
37 wl_signal_add(&wlr_inhibitor->events.destroy, &inhibitor->destroy); 43 wl_signal_add(&wlr_inhibitor->events.destroy, &inhibitor->destroy);
38 44
39 idle_inhibit_v1_check_active(manager); 45 sway_idle_inhibit_v1_check_active(manager);
46}
47
48void sway_idle_inhibit_v1_user_inhibitor_register(struct sway_view *view,
49 enum sway_idle_inhibit_mode mode) {
50 struct sway_idle_inhibitor_v1 *inhibitor =
51 calloc(1, sizeof(struct sway_idle_inhibitor_v1));
52 if (!inhibitor) {
53 return;
54 }
55
56 inhibitor->manager = server.idle_inhibit_manager_v1;
57 inhibitor->mode = mode;
58 inhibitor->view = view;
59 wl_list_insert(&inhibitor->manager->inhibitors, &inhibitor->link);
60
61 inhibitor->destroy.notify = handle_destroy;
62 wl_signal_add(&view->events.unmap, &inhibitor->destroy);
63
64 sway_idle_inhibit_v1_check_active(inhibitor->manager);
65}
66
67struct sway_idle_inhibitor_v1 *sway_idle_inhibit_v1_user_inhibitor_for_view(
68 struct sway_view *view) {
69 struct sway_idle_inhibitor_v1 *inhibitor;
70 wl_list_for_each(inhibitor, &server.idle_inhibit_manager_v1->inhibitors,
71 link) {
72 if (inhibitor->view == view &&
73 inhibitor->mode != INHIBIT_IDLE_APPLICATION) {
74 return inhibitor;
75 }
76 }
77 return NULL;
40} 78}
41 79
42void idle_inhibit_v1_check_active( 80void sway_idle_inhibit_v1_user_inhibitor_destroy(
81 struct sway_idle_inhibitor_v1 *inhibitor) {
82 if (!inhibitor) {
83 return;
84 }
85 if (!sway_assert(inhibitor->mode != INHIBIT_IDLE_APPLICATION,
86 "User should not be able to destroy application inhibitor")) {
87 return;
88 }
89 destroy_inhibitor(inhibitor);
90}
91
92static bool check_active(struct sway_idle_inhibitor_v1 *inhibitor) {
93 switch (inhibitor->mode) {
94 case INHIBIT_IDLE_APPLICATION:
95 // If there is no view associated with the inhibitor, assume visible
96 return !inhibitor->view || view_is_visible(inhibitor->view);
97 case INHIBIT_IDLE_FOCUS:;
98 struct sway_seat *seat = NULL;
99 wl_list_for_each(seat, &server.input->seats, link) {
100 struct sway_container *con = seat_get_focused_container(seat);
101 if (con && con->view && con->view == inhibitor->view) {
102 return true;
103 }
104 }
105 return false;
106 case INHIBIT_IDLE_FULLSCREEN:
107 return inhibitor->view->container &&
108 container_is_fullscreen_or_child(inhibitor->view->container) &&
109 view_is_visible(inhibitor->view);
110 case INHIBIT_IDLE_OPEN:
111 // Inhibitor is destroyed on unmap so it must be open/mapped
112 return true;
113 case INHIBIT_IDLE_VISIBLE:
114 return view_is_visible(inhibitor->view);
115 }
116 return false;
117}
118
119void sway_idle_inhibit_v1_check_active(
43 struct sway_idle_inhibit_manager_v1 *manager) { 120 struct sway_idle_inhibit_manager_v1 *manager) {
44 struct sway_idle_inhibitor_v1 *inhibitor; 121 struct sway_idle_inhibitor_v1 *inhibitor;
45 bool inhibited = false; 122 bool inhibited = false;
46 wl_list_for_each(inhibitor, &manager->inhibitors, link) { 123 wl_list_for_each(inhibitor, &manager->inhibitors, link) {
47 if (!inhibitor->view || !inhibitor->view->container) { 124 if ((inhibited = check_active(inhibitor))) {
48 /* Cannot guess if view is visible so assume it is */
49 inhibited = true;
50 break;
51 }
52 if (view_is_visible(inhibitor->view)) {
53 inhibited = true;
54 break; 125 break;
55 } 126 }
56 } 127 }
diff --git a/sway/desktop/transaction.c b/sway/desktop/transaction.c
index e5f0ee3d..51c6e7fc 100644
--- a/sway/desktop/transaction.c
+++ b/sway/desktop/transaction.c
@@ -349,7 +349,7 @@ static void transaction_progress_queue(void) {
349 list_del(server.transactions, 0); 349 list_del(server.transactions, 0);
350 350
351 if (!server.transactions->length) { 351 if (!server.transactions->length) {
352 idle_inhibit_v1_check_active(server.idle_inhibit_manager_v1); 352 sway_idle_inhibit_v1_check_active(server.idle_inhibit_manager_v1);
353 return; 353 return;
354 } 354 }
355 355
diff --git a/sway/meson.build b/sway/meson.build
index 9f79fb6c..12b86efb 100644
--- a/sway/meson.build
+++ b/sway/meson.build
@@ -63,6 +63,7 @@ sway_sources = files(
63 'commands/fullscreen.c', 63 'commands/fullscreen.c',
64 'commands/gaps.c', 64 'commands/gaps.c',
65 'commands/hide_edge_borders.c', 65 'commands/hide_edge_borders.c',
66 'commands/inhibit_idle.c',
66 'commands/kill.c', 67 'commands/kill.c',
67 'commands/mark.c', 68 'commands/mark.c',
68 'commands/opacity.c', 69 'commands/opacity.c',
diff --git a/sway/sway.5.scd b/sway/sway.5.scd
index dbfeefe3..1650cd60 100644
--- a/sway/sway.5.scd
+++ b/sway/sway.5.scd
@@ -146,6 +146,18 @@ set|plus|minus <amount>
146 _right_, _bottom_, and _left_ or per direction with _horizontal_ and 146 _right_, _bottom_, and _left_ or per direction with _horizontal_ and
147 _vertical_. 147 _vertical_.
148 148
149*inhibit_idle* focus|fullscreen|open|none|visible
150 Set/unset an idle inhibitor for the view. _focus_ will inhibit idle when
151 the view is focused by any seat. _fullscreen_ will inhibit idle when the
152 view is fullscreen (or a descendant of a fullscreen container) and is
153 visible. _open_ will inhibit idle until the view is closed (or the
154 inhibitor is unset/changed). _visible_ will inhibit idle when the view is
155 visible on any output. _none_ will remove any existing idle inhibitor for
156 the view.
157
158 This can also be used with criteria to set an idle inhibitor for any
159 existing view or with _for_window_ to set idle inhibitors for future views.
160
149*layout* default|splith|splitv|stacking|tabbed 161*layout* default|splith|splitv|stacking|tabbed
150 Sets the layout mode of the focused container. 162 Sets the layout mode of the focused container.
151 163