diff options
-rw-r--r-- | include/sway/commands.h | 1 | ||||
-rw-r--r-- | include/sway/desktop/idle_inhibit_v1.h | 20 | ||||
-rw-r--r-- | sway/commands.c | 1 | ||||
-rw-r--r-- | sway/commands/inhibit_idle.c | 51 | ||||
-rw-r--r-- | sway/desktop/idle_inhibit_v1.c | 99 | ||||
-rw-r--r-- | sway/desktop/transaction.c | 2 | ||||
-rw-r--r-- | sway/meson.build | 1 | ||||
-rw-r--r-- | sway/sway.5.scd | 12 |
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; | |||
136 | sway_cmd cmd_gaps; | 136 | sway_cmd cmd_gaps; |
137 | sway_cmd cmd_hide_edge_borders; | 137 | sway_cmd cmd_hide_edge_borders; |
138 | sway_cmd cmd_include; | 138 | sway_cmd cmd_include; |
139 | sway_cmd cmd_inhibit_idle; | ||
139 | sway_cmd cmd_input; | 140 | sway_cmd cmd_input; |
140 | sway_cmd cmd_seat; | 141 | sway_cmd cmd_seat; |
141 | sway_cmd cmd_ipc; | 142 | sway_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 | ||
7 | enum 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 | |||
7 | struct sway_idle_inhibit_manager_v1 { | 15 | struct 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 { | |||
15 | struct sway_idle_inhibitor_v1 { | 23 | struct 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 | ||
23 | void idle_inhibit_v1_check_active( | 32 | void sway_idle_inhibit_v1_check_active( |
24 | struct sway_idle_inhibit_manager_v1 *manager); | 33 | struct sway_idle_inhibit_manager_v1 *manager); |
25 | 34 | ||
35 | void sway_idle_inhibit_v1_user_inhibitor_register(struct sway_view *view, | ||
36 | enum sway_idle_inhibit_mode mode); | ||
37 | |||
38 | struct sway_idle_inhibitor_v1 *sway_idle_inhibit_v1_user_inhibitor_for_view( | ||
39 | struct sway_view *view); | ||
40 | |||
41 | void sway_idle_inhibit_v1_user_inhibitor_destroy( | ||
42 | struct sway_idle_inhibitor_v1 *inhibitor); | ||
43 | |||
26 | struct sway_idle_inhibit_manager_v1 *sway_idle_inhibit_manager_v1_create( | 44 | struct 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 | |||
8 | struct 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 | ||
11 | static 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 | |||
9 | static void handle_destroy(struct wl_listener *listener, void *data) { | 18 | static 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 | ||
19 | void handle_idle_inhibitor_v1(struct wl_listener *listener, void *data) { | 25 | void 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 | |||
48 | void 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 | |||
67 | struct 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 | ||
42 | void idle_inhibit_v1_check_active( | 80 | void 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 | |||
92 | static 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 | |||
119 | void 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 | ||