diff options
-rw-r--r-- | config.in | 14 | ||||
-rw-r--r-- | include/sway/config.h | 7 | ||||
-rw-r--r-- | include/sway/server.h | 1 | ||||
-rw-r--r-- | meson.build | 16 | ||||
-rw-r--r-- | protocols/idle.xml | 49 | ||||
-rw-r--r-- | protocols/meson.build | 1 | ||||
-rw-r--r-- | sway/commands/output.c | 25 | ||||
-rw-r--r-- | sway/config.c | 1 | ||||
-rw-r--r-- | sway/config/output.c | 17 | ||||
-rw-r--r-- | sway/input/cursor.c | 11 | ||||
-rw-r--r-- | sway/input/keyboard.c | 2 | ||||
-rw-r--r-- | sway/server.c | 2 | ||||
-rw-r--r-- | swayidle/main.c | 414 | ||||
-rw-r--r-- | swayidle/meson.build | 17 | ||||
-rw-r--r-- | swayidle/swayidle.1.scd | 61 | ||||
-rw-r--r-- | swayidle/swayidle.1.txt | 67 |
16 files changed, 703 insertions, 2 deletions
@@ -29,6 +29,20 @@ output * bg @datadir@/backgrounds/sway/Sway_Wallpaper_Blue_1920x1080.png fill | |||
29 | # | 29 | # |
30 | # You can get the names of your outputs by running: swaymsg -t get_outputs | 30 | # You can get the names of your outputs by running: swaymsg -t get_outputs |
31 | 31 | ||
32 | ### Idle configuration | ||
33 | # | ||
34 | # Example configuration: | ||
35 | # | ||
36 | #exec swayidle \ | ||
37 | # timeout 300 'swaylock -c 000000' \ | ||
38 | # timeout 600 'swaymsg "output * dpms off"' \ | ||
39 | # resume 'swaymsg "output * dpms on"' \ | ||
40 | # before-sleep 'swaylock -c 000000' | ||
41 | # | ||
42 | # This will lock your screen after 300 seconds of inactivity, then turn off | ||
43 | # your displays after another 600 seconds, and turn your screens back on when | ||
44 | # resumed. It will also lock your screen before your computer goes to sleep. | ||
45 | |||
32 | ### Input configuration | 46 | ### Input configuration |
33 | # | 47 | # |
34 | # Example configuration: | 48 | # Example configuration: |
diff --git a/include/sway/config.h b/include/sway/config.h index b20458cb..f77c3b50 100644 --- a/include/sway/config.h +++ b/include/sway/config.h | |||
@@ -107,6 +107,12 @@ struct seat_config { | |||
107 | list_t *attachments; // list of seat_attachment configs | 107 | list_t *attachments; // list of seat_attachment configs |
108 | }; | 108 | }; |
109 | 109 | ||
110 | enum config_dpms { | ||
111 | DPMS_IGNORE, | ||
112 | DPMS_ON, | ||
113 | DPMS_OFF | ||
114 | }; | ||
115 | |||
110 | /** | 116 | /** |
111 | * Size and position configuration for a particular output. | 117 | * Size and position configuration for a particular output. |
112 | * | 118 | * |
@@ -123,6 +129,7 @@ struct output_config { | |||
123 | 129 | ||
124 | char *background; | 130 | char *background; |
125 | char *background_option; | 131 | char *background_option; |
132 | enum config_dpms dpms_state; | ||
126 | }; | 133 | }; |
127 | 134 | ||
128 | /** | 135 | /** |
diff --git a/include/sway/server.h b/include/sway/server.h index 296fbf22..ac685bf8 100644 --- a/include/sway/server.h +++ b/include/sway/server.h | |||
@@ -21,6 +21,7 @@ struct sway_server { | |||
21 | 21 | ||
22 | struct wlr_compositor *compositor; | 22 | struct wlr_compositor *compositor; |
23 | struct wlr_data_device_manager *data_device_manager; | 23 | struct wlr_data_device_manager *data_device_manager; |
24 | struct wlr_idle *idle; | ||
24 | 25 | ||
25 | struct sway_input_manager *input; | 26 | struct sway_input_manager *input; |
26 | 27 | ||
diff --git a/meson.build b/meson.build index a1f406ec..b943236f 100644 --- a/meson.build +++ b/meson.build | |||
@@ -20,6 +20,8 @@ datadir = get_option('datadir') | |||
20 | sysconfdir = get_option('sysconfdir') | 20 | sysconfdir = get_option('sysconfdir') |
21 | prefix = get_option('prefix') | 21 | prefix = get_option('prefix') |
22 | 22 | ||
23 | swayidle_deps = [] | ||
24 | |||
23 | jsonc = dependency('json-c', version: '>=0.13') | 25 | jsonc = dependency('json-c', version: '>=0.13') |
24 | pcre = dependency('libpcre') | 26 | pcre = dependency('libpcre') |
25 | wlroots = dependency('wlroots', fallback: ['wlroots', 'wlroots']) | 27 | wlroots = dependency('wlroots', fallback: ['wlroots', 'wlroots']) |
@@ -37,6 +39,8 @@ pixman = dependency('pixman-1') | |||
37 | libcap = dependency('libcap') | 39 | libcap = dependency('libcap') |
38 | libinput = dependency('libinput', version: '>=1.6.0') | 40 | libinput = dependency('libinput', version: '>=1.6.0') |
39 | libpam = cc.find_library('pam') | 41 | libpam = cc.find_library('pam') |
42 | systemd = dependency('libsystemd', required: false) | ||
43 | elogind = dependency('libelogind', required: false) | ||
40 | math = cc.find_library('m') | 44 | math = cc.find_library('m') |
41 | rt = cc.find_library('rt') | 45 | rt = cc.find_library('rt') |
42 | git = find_program('git', required: false) | 46 | git = find_program('git', required: false) |
@@ -47,6 +51,16 @@ if gdk_pixbuf.found() | |||
47 | conf_data.set('HAVE_GDK_PIXBUF', true) | 51 | conf_data.set('HAVE_GDK_PIXBUF', true) |
48 | endif | 52 | endif |
49 | 53 | ||
54 | if systemd.found() | ||
55 | conf_data.set('SWAY_IDLE_HAS_SYSTEMD', true) | ||
56 | swayidle_deps += systemd | ||
57 | endif | ||
58 | |||
59 | if elogind.found() | ||
60 | conf_data.set('SWAY_IDLE_HAS_ELOGIND', true) | ||
61 | swayidle_deps += elogind | ||
62 | endif | ||
63 | |||
50 | scdoc = find_program('scdoc', required: false) | 64 | scdoc = find_program('scdoc', required: false) |
51 | 65 | ||
52 | if scdoc.found() | 66 | if scdoc.found() |
@@ -59,6 +73,7 @@ if scdoc.found() | |||
59 | 'sway/sway-input.5.scd', | 73 | 'sway/sway-input.5.scd', |
60 | 'swaylock/swaylock.1.scd', | 74 | 'swaylock/swaylock.1.scd', |
61 | 'swaymsg/swaymsg.1.scd', | 75 | 'swaymsg/swaymsg.1.scd', |
76 | 'swayidle/swayidle.1.scd', | ||
62 | ] | 77 | ] |
63 | foreach filename : man_files | 78 | foreach filename : man_files |
64 | topic = filename.split('.')[-3].split('/')[-1] | 79 | topic = filename.split('.')[-3].split('/')[-1] |
@@ -106,6 +121,7 @@ subdir('client') | |||
106 | subdir('swaybg') | 121 | subdir('swaybg') |
107 | subdir('swaybar') | 122 | subdir('swaybar') |
108 | subdir('swaylock') | 123 | subdir('swaylock') |
124 | subdir('swayidle') | ||
109 | 125 | ||
110 | config = configuration_data() | 126 | config = configuration_data() |
111 | config.set('sysconfdir', join_paths(prefix, sysconfdir)) | 127 | config.set('sysconfdir', join_paths(prefix, sysconfdir)) |
diff --git a/protocols/idle.xml b/protocols/idle.xml new file mode 100644 index 00000000..92d9989c --- /dev/null +++ b/protocols/idle.xml | |||
@@ -0,0 +1,49 @@ | |||
1 | <?xml version="1.0" encoding="UTF-8"?> | ||
2 | <protocol name="idle"> | ||
3 | <copyright><![CDATA[ | ||
4 | Copyright (C) 2015 Martin Gräßlin | ||
5 | |||
6 | This program is free software: you can redistribute it and/or modify | ||
7 | it under the terms of the GNU Lesser General Public License as published by | ||
8 | the Free Software Foundation, either version 2.1 of the License, or | ||
9 | (at your option) any later version. | ||
10 | |||
11 | This program is distributed in the hope that it will be useful, | ||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | GNU Lesser General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU Lesser General Public License | ||
17 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | ]]></copyright> | ||
19 | <interface name="org_kde_kwin_idle" version="1"> | ||
20 | <description summary="User idle time manager"> | ||
21 | This interface allows to monitor user idle time on a given seat. The interface | ||
22 | allows to register timers which trigger after no user activity was registered | ||
23 | on the seat for a given interval. It notifies when user activity resumes. | ||
24 | |||
25 | This is useful for applications wanting to perform actions when the user is not | ||
26 | interacting with the system, e.g. chat applications setting the user as away, power | ||
27 | management features to dim screen, etc.. | ||
28 | </description> | ||
29 | <request name="get_idle_timeout"> | ||
30 | <arg name="id" type="new_id" interface="org_kde_kwin_idle_timeout"/> | ||
31 | <arg name="seat" type="object" interface="wl_seat"/> | ||
32 | <arg name="timeout" type="uint" summary="The idle timeout in msec"/> | ||
33 | </request> | ||
34 | </interface> | ||
35 | <interface name="org_kde_kwin_idle_timeout" version="1"> | ||
36 | <request name="release" type="destructor"> | ||
37 | <description summary="release the timeout object"/> | ||
38 | </request> | ||
39 | <request name="simulate_user_activity"> | ||
40 | <description summary="Simulates user activity for this timeout, behaves just like real user activity on the seat"/> | ||
41 | </request> | ||
42 | <event name="idle"> | ||
43 | <description summary="Triggered when there has not been any user activity in the requested idle time interval"/> | ||
44 | </event> | ||
45 | <event name="resumed"> | ||
46 | <description summary="Triggered on the first user activity after an idle event"/> | ||
47 | </event> | ||
48 | </interface> | ||
49 | </protocol> | ||
diff --git a/protocols/meson.build b/protocols/meson.build index 9d213f81..fa6d696c 100644 --- a/protocols/meson.build +++ b/protocols/meson.build | |||
@@ -30,6 +30,7 @@ wayland_scanner_server = generator( | |||
30 | client_protocols = [ | 30 | client_protocols = [ |
31 | [wl_protocol_dir, 'stable/xdg-shell/xdg-shell.xml'], | 31 | [wl_protocol_dir, 'stable/xdg-shell/xdg-shell.xml'], |
32 | ['wlr-layer-shell-unstable-v1.xml'], | 32 | ['wlr-layer-shell-unstable-v1.xml'], |
33 | ['idle.xml'], | ||
33 | ['wlr-input-inhibitor-unstable-v1.xml'] | 34 | ['wlr-input-inhibitor-unstable-v1.xml'] |
34 | ] | 35 | ] |
35 | 36 | ||
diff --git a/sway/commands/output.c b/sway/commands/output.c index f7e3372c..e8881f77 100644 --- a/sway/commands/output.c +++ b/sway/commands/output.c | |||
@@ -20,6 +20,25 @@ static char *bg_options[] = { | |||
20 | "tile", | 20 | "tile", |
21 | }; | 21 | }; |
22 | 22 | ||
23 | static struct cmd_results *cmd_output_dpms(struct output_config *output, | ||
24 | int *i, int argc, char **argv) { | ||
25 | |||
26 | if (++*i >= argc) { | ||
27 | return cmd_results_new(CMD_INVALID, "output", "Missing dpms argument."); | ||
28 | } | ||
29 | |||
30 | char *value = argv[*i]; | ||
31 | if (strcmp(value, "on") == 0) { | ||
32 | output->dpms_state = DPMS_ON; | ||
33 | } else if (strcmp(value, "off") == 0) { | ||
34 | output->dpms_state = DPMS_OFF; | ||
35 | } else { | ||
36 | return cmd_results_new(CMD_INVALID, "output", | ||
37 | "Invalid dpms state, valid states are on/off."); | ||
38 | } | ||
39 | return NULL; | ||
40 | } | ||
41 | |||
23 | static struct cmd_results *cmd_output_mode(struct output_config *output, | 42 | static struct cmd_results *cmd_output_mode(struct output_config *output, |
24 | int *i, int argc, char **argv) { | 43 | int *i, int argc, char **argv) { |
25 | if (++*i >= argc) { | 44 | if (++*i >= argc) { |
@@ -263,6 +282,8 @@ struct cmd_results *cmd_output(int argc, char **argv) { | |||
263 | } else if (strcasecmp(command, "background") == 0 || | 282 | } else if (strcasecmp(command, "background") == 0 || |
264 | strcasecmp(command, "bg") == 0) { | 283 | strcasecmp(command, "bg") == 0) { |
265 | error = cmd_output_background(output, &i, argc, argv); | 284 | error = cmd_output_background(output, &i, argc, argv); |
285 | } else if (strcasecmp(command, "dpms") == 0) { | ||
286 | error = cmd_output_dpms(output, &i, argc, argv); | ||
266 | } else { | 287 | } else { |
267 | error = cmd_results_new(CMD_INVALID, "output", | 288 | error = cmd_results_new(CMD_INVALID, "output", |
268 | "Invalid output subcommand: %s.", command); | 289 | "Invalid output subcommand: %s.", command); |
@@ -285,10 +306,10 @@ struct cmd_results *cmd_output(int argc, char **argv) { | |||
285 | } | 306 | } |
286 | 307 | ||
287 | wlr_log(L_DEBUG, "Config stored for output %s (enabled: %d) (%dx%d@%fHz " | 308 | wlr_log(L_DEBUG, "Config stored for output %s (enabled: %d) (%dx%d@%fHz " |
288 | "position %d,%d scale %f transform %d) (bg %s %s)", | 309 | "position %d,%d scale %f transform %d) (bg %s %s) (dpms %d)", |
289 | output->name, output->enabled, output->width, output->height, | 310 | output->name, output->enabled, output->width, output->height, |
290 | output->refresh_rate, output->x, output->y, output->scale, | 311 | output->refresh_rate, output->x, output->y, output->scale, |
291 | output->transform, output->background, output->background_option); | 312 | output->transform, output->background, output->background_option, output->dpms_state); |
292 | 313 | ||
293 | // Try to find the output container and apply configuration now. If | 314 | // Try to find the output container and apply configuration now. If |
294 | // this is during startup then there will be no container and config | 315 | // this is during startup then there will be no container and config |
diff --git a/sway/config.c b/sway/config.c index 270c1d86..34c8a280 100644 --- a/sway/config.c +++ b/sway/config.c | |||
@@ -165,6 +165,7 @@ static void config_defaults(struct sway_config *config) { | |||
165 | config->floating_mod = 0; | 165 | config->floating_mod = 0; |
166 | config->dragging_key = BTN_LEFT; | 166 | config->dragging_key = BTN_LEFT; |
167 | config->resizing_key = BTN_RIGHT; | 167 | config->resizing_key = BTN_RIGHT; |
168 | |||
168 | if (!(config->floating_scroll_up_cmd = strdup(""))) goto cleanup; | 169 | if (!(config->floating_scroll_up_cmd = strdup(""))) goto cleanup; |
169 | if (!(config->floating_scroll_down_cmd = strdup(""))) goto cleanup; | 170 | if (!(config->floating_scroll_down_cmd = strdup(""))) goto cleanup; |
170 | if (!(config->floating_scroll_left_cmd = strdup(""))) goto cleanup; | 171 | if (!(config->floating_scroll_left_cmd = strdup(""))) goto cleanup; |
diff --git a/sway/config/output.c b/sway/config/output.c index 68022278..ee2440ea 100644 --- a/sway/config/output.c +++ b/sway/config/output.c | |||
@@ -81,6 +81,9 @@ void merge_output_config(struct output_config *dst, struct output_config *src) { | |||
81 | free(dst->background_option); | 81 | free(dst->background_option); |
82 | dst->background_option = strdup(src->background_option); | 82 | dst->background_option = strdup(src->background_option); |
83 | } | 83 | } |
84 | if (src->dpms_state != 0) { | ||
85 | dst->dpms_state = src->dpms_state; | ||
86 | } | ||
84 | } | 87 | } |
85 | 88 | ||
86 | static void set_mode(struct wlr_output *output, int width, int height, | 89 | static void set_mode(struct wlr_output *output, int width, int height, |
@@ -204,6 +207,20 @@ void apply_output_config(struct output_config *oc, struct sway_container *output | |||
204 | execvp(cmd[0], cmd); | 207 | execvp(cmd[0], cmd); |
205 | } | 208 | } |
206 | } | 209 | } |
210 | if (oc && oc->dpms_state != DPMS_IGNORE) { | ||
211 | switch (oc->dpms_state) { | ||
212 | case DPMS_ON: | ||
213 | wlr_log(L_DEBUG, "Turning on screen"); | ||
214 | wlr_output_enable(wlr_output, true); | ||
215 | break; | ||
216 | case DPMS_OFF: | ||
217 | wlr_log(L_DEBUG, "Turning off screen"); | ||
218 | wlr_output_enable(wlr_output, false); | ||
219 | break; | ||
220 | case DPMS_IGNORE: | ||
221 | break; | ||
222 | } | ||
223 | } | ||
207 | } | 224 | } |
208 | 225 | ||
209 | void free_output_config(struct output_config *oc) { | 226 | void free_output_config(struct output_config *oc) { |
diff --git a/sway/input/cursor.c b/sway/input/cursor.c index 51ce86e1..9259c475 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c | |||
@@ -7,6 +7,7 @@ | |||
7 | #endif | 7 | #endif |
8 | #include <wlr/types/wlr_cursor.h> | 8 | #include <wlr/types/wlr_cursor.h> |
9 | #include <wlr/types/wlr_xcursor_manager.h> | 9 | #include <wlr/types/wlr_xcursor_manager.h> |
10 | #include <wlr/types/wlr_idle.h> | ||
10 | #include "list.h" | 11 | #include "list.h" |
11 | #include "log.h" | 12 | #include "log.h" |
12 | #include "sway/input/cursor.h" | 13 | #include "sway/input/cursor.h" |
@@ -172,6 +173,7 @@ void cursor_send_pointer_motion(struct sway_cursor *cursor, uint32_t time_msec) | |||
172 | 173 | ||
173 | static void handle_cursor_motion(struct wl_listener *listener, void *data) { | 174 | static void handle_cursor_motion(struct wl_listener *listener, void *data) { |
174 | struct sway_cursor *cursor = wl_container_of(listener, cursor, motion); | 175 | struct sway_cursor *cursor = wl_container_of(listener, cursor, motion); |
176 | wlr_idle_notify_activity(cursor->seat->input->server->idle, cursor->seat->wlr_seat); | ||
175 | struct wlr_event_pointer_motion *event = data; | 177 | struct wlr_event_pointer_motion *event = data; |
176 | wlr_cursor_move(cursor->cursor, event->device, | 178 | wlr_cursor_move(cursor->cursor, event->device, |
177 | event->delta_x, event->delta_y); | 179 | event->delta_x, event->delta_y); |
@@ -182,6 +184,7 @@ static void handle_cursor_motion_absolute( | |||
182 | struct wl_listener *listener, void *data) { | 184 | struct wl_listener *listener, void *data) { |
183 | struct sway_cursor *cursor = | 185 | struct sway_cursor *cursor = |
184 | wl_container_of(listener, cursor, motion_absolute); | 186 | wl_container_of(listener, cursor, motion_absolute); |
187 | wlr_idle_notify_activity(cursor->seat->input->server->idle, cursor->seat->wlr_seat); | ||
185 | struct wlr_event_pointer_motion_absolute *event = data; | 188 | struct wlr_event_pointer_motion_absolute *event = data; |
186 | wlr_cursor_warp_absolute(cursor->cursor, event->device, event->x, event->y); | 189 | wlr_cursor_warp_absolute(cursor->cursor, event->device, event->x, event->y); |
187 | cursor_send_pointer_motion(cursor, event->time_msec); | 190 | cursor_send_pointer_motion(cursor, event->time_msec); |
@@ -231,6 +234,7 @@ void dispatch_cursor_button(struct sway_cursor *cursor, | |||
231 | 234 | ||
232 | static void handle_cursor_button(struct wl_listener *listener, void *data) { | 235 | static void handle_cursor_button(struct wl_listener *listener, void *data) { |
233 | struct sway_cursor *cursor = wl_container_of(listener, cursor, button); | 236 | struct sway_cursor *cursor = wl_container_of(listener, cursor, button); |
237 | wlr_idle_notify_activity(cursor->seat->input->server->idle, cursor->seat->wlr_seat); | ||
234 | struct wlr_event_pointer_button *event = data; | 238 | struct wlr_event_pointer_button *event = data; |
235 | dispatch_cursor_button(cursor, | 239 | dispatch_cursor_button(cursor, |
236 | event->time_msec, event->button, event->state); | 240 | event->time_msec, event->button, event->state); |
@@ -238,6 +242,7 @@ static void handle_cursor_button(struct wl_listener *listener, void *data) { | |||
238 | 242 | ||
239 | static void handle_cursor_axis(struct wl_listener *listener, void *data) { | 243 | static void handle_cursor_axis(struct wl_listener *listener, void *data) { |
240 | struct sway_cursor *cursor = wl_container_of(listener, cursor, axis); | 244 | struct sway_cursor *cursor = wl_container_of(listener, cursor, axis); |
245 | wlr_idle_notify_activity(cursor->seat->input->server->idle, cursor->seat->wlr_seat); | ||
241 | struct wlr_event_pointer_axis *event = data; | 246 | struct wlr_event_pointer_axis *event = data; |
242 | wlr_seat_pointer_notify_axis(cursor->seat->wlr_seat, event->time_msec, | 247 | wlr_seat_pointer_notify_axis(cursor->seat->wlr_seat, event->time_msec, |
243 | event->orientation, event->delta, event->delta_discrete, event->source); | 248 | event->orientation, event->delta, event->delta_discrete, event->source); |
@@ -245,6 +250,7 @@ static void handle_cursor_axis(struct wl_listener *listener, void *data) { | |||
245 | 250 | ||
246 | static void handle_touch_down(struct wl_listener *listener, void *data) { | 251 | static void handle_touch_down(struct wl_listener *listener, void *data) { |
247 | struct sway_cursor *cursor = wl_container_of(listener, cursor, touch_down); | 252 | struct sway_cursor *cursor = wl_container_of(listener, cursor, touch_down); |
253 | wlr_idle_notify_activity(cursor->seat->input->server->idle, cursor->seat->wlr_seat); | ||
248 | struct wlr_event_touch_down *event = data; | 254 | struct wlr_event_touch_down *event = data; |
249 | 255 | ||
250 | struct wlr_seat *seat = cursor->seat->wlr_seat; | 256 | struct wlr_seat *seat = cursor->seat->wlr_seat; |
@@ -271,6 +277,7 @@ static void handle_touch_down(struct wl_listener *listener, void *data) { | |||
271 | 277 | ||
272 | static void handle_touch_up(struct wl_listener *listener, void *data) { | 278 | static void handle_touch_up(struct wl_listener *listener, void *data) { |
273 | struct sway_cursor *cursor = wl_container_of(listener, cursor, touch_up); | 279 | struct sway_cursor *cursor = wl_container_of(listener, cursor, touch_up); |
280 | wlr_idle_notify_activity(cursor->seat->input->server->idle, cursor->seat->wlr_seat); | ||
274 | struct wlr_event_touch_up *event = data; | 281 | struct wlr_event_touch_up *event = data; |
275 | struct wlr_seat *seat = cursor->seat->wlr_seat; | 282 | struct wlr_seat *seat = cursor->seat->wlr_seat; |
276 | // TODO: fall back to cursor simulation if client has not bound to touch | 283 | // TODO: fall back to cursor simulation if client has not bound to touch |
@@ -280,6 +287,7 @@ static void handle_touch_up(struct wl_listener *listener, void *data) { | |||
280 | static void handle_touch_motion(struct wl_listener *listener, void *data) { | 287 | static void handle_touch_motion(struct wl_listener *listener, void *data) { |
281 | struct sway_cursor *cursor = | 288 | struct sway_cursor *cursor = |
282 | wl_container_of(listener, cursor, touch_motion); | 289 | wl_container_of(listener, cursor, touch_motion); |
290 | wlr_idle_notify_activity(cursor->seat->input->server->idle, cursor->seat->wlr_seat); | ||
283 | struct wlr_event_touch_motion *event = data; | 291 | struct wlr_event_touch_motion *event = data; |
284 | 292 | ||
285 | struct wlr_seat *seat = cursor->seat->wlr_seat; | 293 | struct wlr_seat *seat = cursor->seat->wlr_seat; |
@@ -331,6 +339,7 @@ static void apply_mapping_from_region(struct wlr_input_device *device, | |||
331 | 339 | ||
332 | static void handle_tool_axis(struct wl_listener *listener, void *data) { | 340 | static void handle_tool_axis(struct wl_listener *listener, void *data) { |
333 | struct sway_cursor *cursor = wl_container_of(listener, cursor, tool_axis); | 341 | struct sway_cursor *cursor = wl_container_of(listener, cursor, tool_axis); |
342 | wlr_idle_notify_activity(cursor->seat->input->server->idle, cursor->seat->wlr_seat); | ||
334 | struct wlr_event_tablet_tool_axis *event = data; | 343 | struct wlr_event_tablet_tool_axis *event = data; |
335 | struct sway_input_device *input_device = event->device->data; | 344 | struct sway_input_device *input_device = event->device->data; |
336 | 345 | ||
@@ -353,6 +362,7 @@ static void handle_tool_axis(struct wl_listener *listener, void *data) { | |||
353 | 362 | ||
354 | static void handle_tool_tip(struct wl_listener *listener, void *data) { | 363 | static void handle_tool_tip(struct wl_listener *listener, void *data) { |
355 | struct sway_cursor *cursor = wl_container_of(listener, cursor, tool_tip); | 364 | struct sway_cursor *cursor = wl_container_of(listener, cursor, tool_tip); |
365 | wlr_idle_notify_activity(cursor->seat->input->server->idle, cursor->seat->wlr_seat); | ||
356 | struct wlr_event_tablet_tool_tip *event = data; | 366 | struct wlr_event_tablet_tool_tip *event = data; |
357 | dispatch_cursor_button(cursor, event->time_msec, | 367 | dispatch_cursor_button(cursor, event->time_msec, |
358 | BTN_LEFT, event->state == WLR_TABLET_TOOL_TIP_DOWN ? | 368 | BTN_LEFT, event->state == WLR_TABLET_TOOL_TIP_DOWN ? |
@@ -361,6 +371,7 @@ static void handle_tool_tip(struct wl_listener *listener, void *data) { | |||
361 | 371 | ||
362 | static void handle_tool_button(struct wl_listener *listener, void *data) { | 372 | static void handle_tool_button(struct wl_listener *listener, void *data) { |
363 | struct sway_cursor *cursor = wl_container_of(listener, cursor, tool_button); | 373 | struct sway_cursor *cursor = wl_container_of(listener, cursor, tool_button); |
374 | wlr_idle_notify_activity(cursor->seat->input->server->idle, cursor->seat->wlr_seat); | ||
364 | struct wlr_event_tablet_tool_button *event = data; | 375 | struct wlr_event_tablet_tool_button *event = data; |
365 | // TODO: the user may want to configure which tool buttons are mapped to | 376 | // TODO: the user may want to configure which tool buttons are mapped to |
366 | // which simulated pointer buttons | 377 | // which simulated pointer buttons |
diff --git a/sway/input/keyboard.c b/sway/input/keyboard.c index dbf2ce01..c07557db 100644 --- a/sway/input/keyboard.c +++ b/sway/input/keyboard.c | |||
@@ -2,6 +2,7 @@ | |||
2 | #include <limits.h> | 2 | #include <limits.h> |
3 | #include <wlr/backend/multi.h> | 3 | #include <wlr/backend/multi.h> |
4 | #include <wlr/backend/session.h> | 4 | #include <wlr/backend/session.h> |
5 | #include <wlr/types/wlr_idle.h> | ||
5 | #include "sway/input/seat.h" | 6 | #include "sway/input/seat.h" |
6 | #include "sway/input/keyboard.h" | 7 | #include "sway/input/keyboard.h" |
7 | #include "sway/input/input-manager.h" | 8 | #include "sway/input/input-manager.h" |
@@ -330,6 +331,7 @@ static void handle_keyboard_key(struct wl_listener *listener, void *data) { | |||
330 | struct wlr_seat *wlr_seat = keyboard->seat_device->sway_seat->wlr_seat; | 331 | struct wlr_seat *wlr_seat = keyboard->seat_device->sway_seat->wlr_seat; |
331 | struct wlr_input_device *wlr_device = | 332 | struct wlr_input_device *wlr_device = |
332 | keyboard->seat_device->input_device->wlr_device; | 333 | keyboard->seat_device->input_device->wlr_device; |
334 | wlr_idle_notify_activity(keyboard->seat_device->sway_seat->input->server->idle, wlr_seat); | ||
333 | struct wlr_event_keyboard_key *event = data; | 335 | struct wlr_event_keyboard_key *event = data; |
334 | 336 | ||
335 | xkb_keycode_t keycode = event->keycode + 8; | 337 | xkb_keycode_t keycode = event->keycode + 8; |
diff --git a/sway/server.c b/sway/server.c index 8c41ee87..ccc215eb 100644 --- a/sway/server.c +++ b/sway/server.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <wlr/types/wlr_xcursor_manager.h> | 16 | #include <wlr/types/wlr_xcursor_manager.h> |
17 | #include <wlr/types/wlr_xdg_output.h> | 17 | #include <wlr/types/wlr_xdg_output.h> |
18 | #include <wlr/types/wlr_wl_shell.h> | 18 | #include <wlr/types/wlr_wl_shell.h> |
19 | #include <wlr/types/wlr_idle.h> | ||
19 | #include <wlr/util/log.h> | 20 | #include <wlr/util/log.h> |
20 | // TODO WLR: make Xwayland optional | 21 | // TODO WLR: make Xwayland optional |
21 | #include <wlr/xwayland.h> | 22 | #include <wlr/xwayland.h> |
@@ -61,6 +62,7 @@ bool server_init(struct sway_server *server) { | |||
61 | server->data_device_manager = | 62 | server->data_device_manager = |
62 | wlr_data_device_manager_create(server->wl_display); | 63 | wlr_data_device_manager_create(server->wl_display); |
63 | 64 | ||
65 | server->idle = wlr_idle_create(server->wl_display); | ||
64 | wlr_screenshooter_create(server->wl_display); | 66 | wlr_screenshooter_create(server->wl_display); |
65 | wlr_gamma_control_manager_create(server->wl_display); | 67 | wlr_gamma_control_manager_create(server->wl_display); |
66 | wlr_primary_selection_device_manager_create(server->wl_display); | 68 | wlr_primary_selection_device_manager_create(server->wl_display); |
diff --git a/swayidle/main.c b/swayidle/main.c new file mode 100644 index 00000000..0eb9e202 --- /dev/null +++ b/swayidle/main.c | |||
@@ -0,0 +1,414 @@ | |||
1 | #define _XOPEN_SOURCE 500 | ||
2 | #include <getopt.h> | ||
3 | #include <signal.h> | ||
4 | #include <pthread.h> | ||
5 | #include <stdio.h> | ||
6 | #include <stdlib.h> | ||
7 | #include <errno.h> | ||
8 | #include <string.h> | ||
9 | #include <unistd.h> | ||
10 | #include <wayland-client-protocol.h> | ||
11 | #include <wayland-client.h> | ||
12 | #include <wayland-util.h> | ||
13 | #include <wlr/config.h> | ||
14 | #include <wlr/util/log.h> | ||
15 | #include <wlr/types/wlr_output_layout.h> | ||
16 | #include <wlr/types/wlr_output.h> | ||
17 | #include "idle-client-protocol.h" | ||
18 | #include "config.h" | ||
19 | #include "list.h" | ||
20 | #ifdef SWAY_IDLE_HAS_SYSTEMD | ||
21 | #include <systemd/sd-bus.h> | ||
22 | #include <systemd/sd-login.h> | ||
23 | #elif defined(SWAY_IDLE_HAS_ELOGIND) | ||
24 | #include <elogind/sd-bus.h> | ||
25 | #include <elogind/sd-login.h> | ||
26 | #endif | ||
27 | |||
28 | typedef void (*timer_callback_func)(void *data); | ||
29 | |||
30 | static struct org_kde_kwin_idle *idle_manager = NULL; | ||
31 | static struct wl_seat *seat = NULL; | ||
32 | bool debug = false; | ||
33 | |||
34 | struct swayidle_state { | ||
35 | struct wl_display *display; | ||
36 | struct org_kde_kwin_idle_timeout *idle_timer; | ||
37 | struct org_kde_kwin_idle_timeout *lock_timer; | ||
38 | struct wlr_output_layout *layout; | ||
39 | struct wl_event_loop *event_loop; | ||
40 | list_t *timeout_cmds; | ||
41 | } state; | ||
42 | |||
43 | struct swayidle_cmd { | ||
44 | timer_callback_func callback; | ||
45 | char *param; | ||
46 | }; | ||
47 | |||
48 | struct swayidle_cmd *lock_cmd = NULL; | ||
49 | |||
50 | struct swayidle_timeout_cmd { | ||
51 | uint32_t timeout; | ||
52 | struct swayidle_cmd *idle_cmd; | ||
53 | struct swayidle_cmd *resume_cmd; | ||
54 | }; | ||
55 | |||
56 | static void cmd_exec(void *data) { | ||
57 | if (data == NULL) { | ||
58 | return; | ||
59 | } | ||
60 | char *param = (char *)data; | ||
61 | wlr_log(L_DEBUG, "Cmd exec %s", param); | ||
62 | int pid = fork(); | ||
63 | if (pid == 0) { | ||
64 | char *const cmd[] = { "sh", "-c", param, NULL, }; | ||
65 | execvp(cmd[0], cmd); | ||
66 | exit(1); | ||
67 | } | ||
68 | wlr_log(L_DEBUG, "Spawned process %d", pid); | ||
69 | } | ||
70 | |||
71 | #if defined(SWAY_IDLE_HAS_SYSTEMD) || defined(SWAY_IDLE_HAS_ELOGIND) | ||
72 | static int lock_fd = -1; | ||
73 | static int ongoing_fd = -1; | ||
74 | |||
75 | static int release_lock(void *data) { | ||
76 | wlr_log(L_INFO, "Releasing sleep lock %d", ongoing_fd); | ||
77 | if (ongoing_fd >= 0) { | ||
78 | close(ongoing_fd); | ||
79 | } | ||
80 | ongoing_fd = -1; | ||
81 | return 0; | ||
82 | } | ||
83 | |||
84 | void acquire_sleep_lock() { | ||
85 | sd_bus_message *msg = NULL; | ||
86 | sd_bus_error error = SD_BUS_ERROR_NULL; | ||
87 | struct sd_bus *bus; | ||
88 | int ret = sd_bus_default_system(&bus); | ||
89 | |||
90 | if (ret < 0) { | ||
91 | wlr_log(L_ERROR, "Failed to open D-Bus connection: %s", | ||
92 | strerror(-ret)); | ||
93 | return; | ||
94 | } | ||
95 | |||
96 | ret = sd_bus_call_method(bus, "org.freedesktop.login1", | ||
97 | "/org/freedesktop/login1", | ||
98 | "org.freedesktop.login1.Manager", "Inhibit", | ||
99 | &error, &msg, "ssss", "sleep", "swayidle", | ||
100 | "Setup Up Lock Screen", "delay"); | ||
101 | if (ret < 0) { | ||
102 | wlr_log(L_ERROR, "Failed to send Inhibit signal: %s", | ||
103 | strerror(-ret)); | ||
104 | } else { | ||
105 | ret = sd_bus_message_read(msg, "h", &lock_fd); | ||
106 | if (ret < 0) { | ||
107 | wlr_log(L_ERROR, | ||
108 | "Failed to parse D-Bus response for Inhibit: %s", | ||
109 | strerror(-ret)); | ||
110 | } | ||
111 | } | ||
112 | wlr_log(L_INFO, "Got sleep lock: %d", lock_fd); | ||
113 | } | ||
114 | |||
115 | static int prepare_for_sleep(sd_bus_message *msg, void *userdata, | ||
116 | sd_bus_error *ret_error) { | ||
117 | bool going_down = true; | ||
118 | int ret = sd_bus_message_read(msg, "b", &going_down); | ||
119 | if (ret < 0) { | ||
120 | wlr_log(L_ERROR, "Failed to parse D-Bus response for Inhibit: %s", | ||
121 | strerror(-ret)); | ||
122 | } | ||
123 | wlr_log(L_DEBUG, "PrepareForSleep signal received %d", going_down); | ||
124 | if (!going_down) { | ||
125 | acquire_sleep_lock(); | ||
126 | return 0; | ||
127 | } | ||
128 | |||
129 | ongoing_fd = lock_fd; | ||
130 | |||
131 | if (lock_cmd && lock_cmd->callback) { | ||
132 | lock_cmd->callback(lock_cmd->param); | ||
133 | } | ||
134 | |||
135 | if (ongoing_fd >= 0) { | ||
136 | struct wl_event_source *source = | ||
137 | wl_event_loop_add_timer(state.event_loop, release_lock, NULL); | ||
138 | wl_event_source_timer_update(source, 1000); | ||
139 | } | ||
140 | wlr_log(L_DEBUG, "Prepare for sleep done"); | ||
141 | return 0; | ||
142 | } | ||
143 | |||
144 | static int dbus_event(int fd, uint32_t mask, void *data) { | ||
145 | sd_bus *bus = data; | ||
146 | while (sd_bus_process(bus, NULL) > 0) { | ||
147 | // Do nothing. | ||
148 | } | ||
149 | return 1; | ||
150 | } | ||
151 | |||
152 | void setup_sleep_listener() { | ||
153 | struct sd_bus *bus; | ||
154 | |||
155 | int ret = sd_bus_default_system(&bus); | ||
156 | if (ret < 0) { | ||
157 | wlr_log(L_ERROR, "Failed to open D-Bus connection: %s", | ||
158 | strerror(-ret)); | ||
159 | return; | ||
160 | } | ||
161 | |||
162 | char str[256]; | ||
163 | const char *fmt = "type='signal'," | ||
164 | "sender='org.freedesktop.login1'," | ||
165 | "interface='org.freedesktop.login1.%s'," | ||
166 | "member='%s'," "path='%s'"; | ||
167 | |||
168 | snprintf(str, sizeof(str), fmt, "Manager", "PrepareForSleep", | ||
169 | "/org/freedesktop/login1"); | ||
170 | ret = sd_bus_add_match(bus, NULL, str, prepare_for_sleep, NULL); | ||
171 | if (ret < 0) { | ||
172 | wlr_log(L_ERROR, "Failed to add D-Bus match: %s", strerror(-ret)); | ||
173 | return; | ||
174 | } | ||
175 | acquire_sleep_lock(); | ||
176 | |||
177 | wl_event_loop_add_fd(state.event_loop, sd_bus_get_fd(bus), | ||
178 | WL_EVENT_READABLE, dbus_event, bus); | ||
179 | } | ||
180 | #endif | ||
181 | |||
182 | static void handle_global(void *data, struct wl_registry *registry, | ||
183 | uint32_t name, const char *interface, uint32_t version) { | ||
184 | if (strcmp(interface, org_kde_kwin_idle_interface.name) == 0) { | ||
185 | idle_manager = | ||
186 | wl_registry_bind(registry, name, &org_kde_kwin_idle_interface, 1); | ||
187 | } else if (strcmp(interface, wl_seat_interface.name) == 0) { | ||
188 | seat = wl_registry_bind(registry, name, &wl_seat_interface, 1); | ||
189 | } | ||
190 | } | ||
191 | |||
192 | static void handle_global_remove(void *data, struct wl_registry *registry, | ||
193 | uint32_t name) { | ||
194 | } | ||
195 | |||
196 | static const struct wl_registry_listener registry_listener = { | ||
197 | .global = handle_global, | ||
198 | .global_remove = handle_global_remove, | ||
199 | }; | ||
200 | |||
201 | static void handle_idle(void *data, struct org_kde_kwin_idle_timeout *timer) { | ||
202 | struct swayidle_timeout_cmd *cmd = data; | ||
203 | wlr_log(L_DEBUG, "idle state"); | ||
204 | if (cmd && cmd->idle_cmd && cmd->idle_cmd->callback) { | ||
205 | cmd->idle_cmd->callback(cmd->idle_cmd->param); | ||
206 | } | ||
207 | } | ||
208 | |||
209 | static void handle_resume(void *data, struct org_kde_kwin_idle_timeout *timer) { | ||
210 | struct swayidle_timeout_cmd *cmd = data; | ||
211 | wlr_log(L_DEBUG, "active state"); | ||
212 | if (cmd && cmd->resume_cmd && cmd->resume_cmd->callback) { | ||
213 | cmd->resume_cmd->callback(cmd->resume_cmd->param); | ||
214 | } | ||
215 | } | ||
216 | |||
217 | static const struct org_kde_kwin_idle_timeout_listener idle_timer_listener = { | ||
218 | .idle = handle_idle, | ||
219 | .resumed = handle_resume, | ||
220 | }; | ||
221 | |||
222 | struct swayidle_cmd *parse_command(int argc, char **argv) { | ||
223 | if (argc < 1) { | ||
224 | wlr_log(L_ERROR, "Too few parameters for command in parse_command"); | ||
225 | return NULL; | ||
226 | } | ||
227 | |||
228 | struct swayidle_cmd *cmd = calloc(1, sizeof(struct swayidle_cmd)); | ||
229 | wlr_log(L_DEBUG, "Command: %s", argv[0]); | ||
230 | cmd->callback = cmd_exec; | ||
231 | cmd->param = argv[0]; | ||
232 | return cmd; | ||
233 | } | ||
234 | |||
235 | int parse_timeout(int argc, char **argv) { | ||
236 | if (argc < 3) { | ||
237 | wlr_log(L_ERROR, "Too few parameters to timeout command. " | ||
238 | "Usage: timeout <seconds> <command>"); | ||
239 | exit(-1); | ||
240 | } | ||
241 | errno = 0; | ||
242 | char *endptr; | ||
243 | int seconds = strtoul(argv[1], &endptr, 10); | ||
244 | if (errno != 0 || *endptr != '\0') { | ||
245 | wlr_log(L_ERROR, "Invalid timeout parameter '%s', it should be a " | ||
246 | "numeric value representing seconds", optarg); | ||
247 | exit(-1); | ||
248 | } | ||
249 | struct swayidle_timeout_cmd *cmd = | ||
250 | calloc(1, sizeof(struct swayidle_timeout_cmd)); | ||
251 | cmd->timeout = seconds * 1000; | ||
252 | |||
253 | wlr_log(L_DEBUG, "Register idle timeout at %d ms", cmd->timeout); | ||
254 | wlr_log(L_DEBUG, "Setup idle"); | ||
255 | cmd->idle_cmd = parse_command(argc - 2, &argv[2]); | ||
256 | |||
257 | int result = 3; | ||
258 | if (argc >= 5 && !strcmp("resume", argv[3])) { | ||
259 | wlr_log(L_DEBUG, "Setup resume"); | ||
260 | cmd->resume_cmd = parse_command(argc - 4, &argv[4]); | ||
261 | result = 5; | ||
262 | } | ||
263 | list_add(state.timeout_cmds, cmd); | ||
264 | return result; | ||
265 | } | ||
266 | |||
267 | int parse_sleep(int argc, char **argv) { | ||
268 | if (argc < 2) { | ||
269 | wlr_log(L_ERROR, "Too few parameters to before-sleep command. " | ||
270 | "Usage: before-sleep <command>"); | ||
271 | exit(-1); | ||
272 | } | ||
273 | |||
274 | lock_cmd = parse_command(argc - 1, &argv[1]); | ||
275 | if (lock_cmd) { | ||
276 | wlr_log(L_DEBUG, "Setup sleep lock: %s", lock_cmd->param); | ||
277 | } | ||
278 | |||
279 | return 2; | ||
280 | } | ||
281 | |||
282 | |||
283 | int parse_args(int argc, char *argv[]) { | ||
284 | int c; | ||
285 | |||
286 | while ((c = getopt(argc, argv, "hs:d")) != -1) { | ||
287 | switch(c) { | ||
288 | case 'd': | ||
289 | debug = true; | ||
290 | break; | ||
291 | case 'h': | ||
292 | case '?': | ||
293 | printf("Usage: %s [OPTIONS]\n", argv[0]); | ||
294 | printf(" -d\tdebug\n"); | ||
295 | printf(" -h\tthis help menu\n"); | ||
296 | return 1; | ||
297 | default: | ||
298 | return 1; | ||
299 | } | ||
300 | } | ||
301 | |||
302 | if (debug) { | ||
303 | wlr_log_init(L_DEBUG, NULL); | ||
304 | wlr_log(L_DEBUG, "Loglevel debug"); | ||
305 | } else { | ||
306 | wlr_log_init(L_INFO, NULL); | ||
307 | } | ||
308 | |||
309 | |||
310 | state.timeout_cmds = create_list(); | ||
311 | |||
312 | int i = optind; | ||
313 | while (i < argc) { | ||
314 | if (!strcmp("timeout", argv[i])) { | ||
315 | wlr_log(L_DEBUG, "Got timeout"); | ||
316 | i += parse_timeout(argc - i, &argv[i]); | ||
317 | } else if (!strcmp("before-sleep", argv[i])) { | ||
318 | wlr_log(L_DEBUG, "Got before-sleep"); | ||
319 | i += parse_sleep(argc - i, &argv[i]); | ||
320 | } else { | ||
321 | wlr_log(L_ERROR, "Unsupported command '%s'", argv[i]); | ||
322 | exit(-1); | ||
323 | } | ||
324 | } | ||
325 | return 0; | ||
326 | } | ||
327 | |||
328 | void sway_terminate(int exit_code) { | ||
329 | if (state.event_loop) { | ||
330 | wl_event_loop_destroy(state.event_loop); | ||
331 | } | ||
332 | if (state.display) { | ||
333 | wl_display_disconnect(state.display); | ||
334 | } | ||
335 | exit(exit_code); | ||
336 | } | ||
337 | |||
338 | void sig_handler(int signal) { | ||
339 | sway_terminate(0); | ||
340 | } | ||
341 | |||
342 | static int display_event(int fd, uint32_t mask, void *data) { | ||
343 | wl_display_dispatch(state.display); | ||
344 | return 0; | ||
345 | } | ||
346 | |||
347 | void register_idle_timeout(void *item) { | ||
348 | struct swayidle_timeout_cmd *cmd = item; | ||
349 | if (cmd == NULL || !cmd->timeout) { | ||
350 | wlr_log(L_ERROR, "Invalid idle cmd, will not register"); | ||
351 | return; | ||
352 | } | ||
353 | state.idle_timer = | ||
354 | org_kde_kwin_idle_get_idle_timeout(idle_manager, seat, cmd->timeout); | ||
355 | if (state.idle_timer != NULL) { | ||
356 | org_kde_kwin_idle_timeout_add_listener(state.idle_timer, | ||
357 | &idle_timer_listener, cmd); | ||
358 | } else { | ||
359 | wlr_log(L_ERROR, "Could not create idle timer"); | ||
360 | } | ||
361 | } | ||
362 | |||
363 | int main(int argc, char *argv[]) { | ||
364 | signal(SIGINT, sig_handler); | ||
365 | signal(SIGTERM, sig_handler); | ||
366 | |||
367 | if (parse_args(argc, argv) != 0) { | ||
368 | return -1; | ||
369 | } | ||
370 | |||
371 | state.display = wl_display_connect(NULL); | ||
372 | if (state.display == NULL) { | ||
373 | wlr_log(L_ERROR, "Failed to create display"); | ||
374 | return -3; | ||
375 | } | ||
376 | |||
377 | struct wl_registry *registry = wl_display_get_registry(state.display); | ||
378 | wl_registry_add_listener(registry, ®istry_listener, NULL); | ||
379 | wl_display_roundtrip(state.display); | ||
380 | state.layout = wlr_output_layout_create(); | ||
381 | state.event_loop = wl_event_loop_create(); | ||
382 | |||
383 | if (idle_manager == NULL) { | ||
384 | wlr_log(L_ERROR, "Display doesn't support idle protocol"); | ||
385 | return -4; | ||
386 | } | ||
387 | if (seat == NULL) { | ||
388 | wlr_log(L_ERROR, "Seat error"); | ||
389 | return -5; | ||
390 | } | ||
391 | |||
392 | bool should_run = state.timeout_cmds->length > 0; | ||
393 | #if defined(SWAY_IDLE_HAS_SYSTEMD) || defined(SWAY_IDLE_HAS_ELOGIND) | ||
394 | if (lock_cmd) { | ||
395 | should_run = true; | ||
396 | setup_sleep_listener(); | ||
397 | } | ||
398 | #endif | ||
399 | if (!should_run) { | ||
400 | wlr_log(L_INFO, "No command specified! Nothing to do, will exit"); | ||
401 | sway_terminate(0); | ||
402 | } | ||
403 | list_foreach(state.timeout_cmds, register_idle_timeout); | ||
404 | |||
405 | wl_display_roundtrip(state.display); | ||
406 | |||
407 | wl_event_loop_add_fd(state.event_loop, wl_display_get_fd(state.display), | ||
408 | WL_EVENT_READABLE, display_event, NULL); | ||
409 | |||
410 | while (wl_event_loop_dispatch(state.event_loop, 0) != -1) { | ||
411 | ; //Intentionally left blank; | ||
412 | } | ||
413 | sway_terminate(0); | ||
414 | } | ||
diff --git a/swayidle/meson.build b/swayidle/meson.build new file mode 100644 index 00000000..09c482d6 --- /dev/null +++ b/swayidle/meson.build | |||
@@ -0,0 +1,17 @@ | |||
1 | threads = dependency('threads') | ||
2 | |||
3 | executable( | ||
4 | 'swayidle', [ | ||
5 | 'main.c', | ||
6 | ], | ||
7 | include_directories: [sway_inc], | ||
8 | dependencies: [ | ||
9 | client_protos, | ||
10 | wayland_client, | ||
11 | wayland_server, | ||
12 | wlroots, | ||
13 | swayidle_deps, | ||
14 | ], | ||
15 | link_with: [lib_sway_common, lib_sway_client], | ||
16 | install: true | ||
17 | ) | ||
diff --git a/swayidle/swayidle.1.scd b/swayidle/swayidle.1.scd new file mode 100644 index 00000000..5cd4a7fd --- /dev/null +++ b/swayidle/swayidle.1.scd | |||
@@ -0,0 +1,61 @@ | |||
1 | swayidle (1) | ||
2 | |||
3 | # NAME | ||
4 | |||
5 | swayidle - Idle manager for Wayland | ||
6 | |||
7 | # SYNOPSIS | ||
8 | |||
9 | *swayidle* [options] [events...] | ||
10 | |||
11 | # OPTIONS | ||
12 | |||
13 | *-h* | ||
14 | Show help message and quit. | ||
15 | |||
16 | *-d* | ||
17 | Enable debug output. | ||
18 | |||
19 | # DESCRIPTION | ||
20 | |||
21 | swayidle listens for idle activity on your Wayland compositor and executes tasks | ||
22 | on various idle-related events. You can specify any number of events at the | ||
23 | command line. | ||
24 | |||
25 | # EVENTS | ||
26 | |||
27 | *timeout* <timeout> <timeout command> [resume <resume command>] | ||
28 | Execute _timeout command_ if there is no activity for <timeout> seconds. | ||
29 | |||
30 | If you specify "resume <resume command>", _resume command_ will be run when | ||
31 | there is activity again. | ||
32 | |||
33 | *before-sleep* <command> | ||
34 | If built with systemd support, executes _command_ before systemd puts the | ||
35 | computer to sleep. | ||
36 | |||
37 | All commands are executed in a shell. | ||
38 | |||
39 | # EXAMPLE | ||
40 | |||
41 | ``` | ||
42 | swayidle \ | ||
43 | timeout 300 'swaylock -c 000000' \ | ||
44 | timeout 600 'swaymsg "output * dpms off"' \ | ||
45 | resume 'swaymsg "output * dpms on"' \ | ||
46 | before-sleep 'swaylock -c 000000' | ||
47 | ``` | ||
48 | |||
49 | This will lock your screen after 300 seconds of inactivity, then turn off your | ||
50 | displays after another 600 seconds, and turn your screens back on when resumed. | ||
51 | It will also lock your screen before your computer goes to sleep. | ||
52 | |||
53 | # AUTHORS | ||
54 | |||
55 | Maintained by Drew DeVault <sir@cmpwn.com>, who is assisted by other open | ||
56 | source contributors. For more information about sway development, see | ||
57 | https://github.com/swaywm/sway. | ||
58 | |||
59 | # SEE ALSO | ||
60 | |||
61 | *sway*(5) *swaymsg*(1) *swaygrab*(1) *sway-input*(5) *sway-bar*(5) | ||
diff --git a/swayidle/swayidle.1.txt b/swayidle/swayidle.1.txt new file mode 100644 index 00000000..a32e6fd5 --- /dev/null +++ b/swayidle/swayidle.1.txt | |||
@@ -0,0 +1,67 @@ | |||
1 | ///// | ||
2 | vim:set ts=4 sw=4 tw=82 noet: | ||
3 | ///// | ||
4 | :quotes.~: | ||
5 | |||
6 | swayidle (1) | ||
7 | ============ | ||
8 | |||
9 | Name | ||
10 | ---- | ||
11 | swayidle - Idle manager for Wayland | ||
12 | |||
13 | Synopsis | ||
14 | -------- | ||
15 | 'swayidle' [options] [events...] | ||
16 | |||
17 | Options | ||
18 | ------- | ||
19 | |||
20 | *-h*:: | ||
21 | Show help message and quit. | ||
22 | |||
23 | *-d*:: | ||
24 | Enable debug output. | ||
25 | |||
26 | Description | ||
27 | ----------- | ||
28 | |||
29 | swayidle listens for idle activity on your Wayland compositor and executes tasks | ||
30 | on various idle-related events. You can specify any number of events at the | ||
31 | command line. | ||
32 | |||
33 | Events | ||
34 | ------ | ||
35 | |||
36 | *timeout* <timeout> <timeout command> [resume <resume command>]:: | ||
37 | Execute <timeout command> if there is no activity for <timeout> seconds. | ||
38 | + | ||
39 | If you specify "resume <resume command>", <resume command> will be run when | ||
40 | there is activity again. | ||
41 | |||
42 | *before-sleep* <command>:: | ||
43 | If built with systemd support, executes <command> before systemd puts the | ||
44 | computer to sleep. | ||
45 | |||
46 | All commands are executed in a shell. | ||
47 | |||
48 | Example | ||
49 | ------- | ||
50 | |||
51 | swayidle \ | ||
52 | timeout 300 'swaylock -c 000000' \ | ||
53 | timeout 600 'swaymsg "output * dpms off"' \ | ||
54 | resume 'swaymsg "output * dpms on"' \ | ||
55 | before-sleep 'swaylock -c 000000' | ||
56 | |||
57 | This will lock your screen after 300 seconds of inactivity, then turn off your | ||
58 | displays after another 600 seconds, and turn your screens back on when resumed. | ||
59 | It will also lock your screen before your computer goes to sleep. | ||
60 | |||
61 | Authors | ||
62 | ------- | ||
63 | |||
64 | Maintained by Drew DeVault <sir@cmpwn.com>, who is assisted by other open | ||
65 | source contributors. For more information about sway development, see | ||
66 | <https://github.com/swaywm/sway>. | ||
67 | |||