Skip to content

Commit 3e392e3

Browse files
boucmanemersion
authored andcommitted
Add support for logind's lock/unlock signals
Signed-off-by: Jérémy Rosen <[email protected]>
1 parent 1f72732 commit 3e392e3

File tree

2 files changed

+143
-7
lines changed

2 files changed

+143
-7
lines changed

main.c

Lines changed: 134 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ struct swayidle_state {
3333
struct wl_list timeout_cmds; // struct swayidle_timeout_cmd *
3434
char *before_sleep_cmd;
3535
char *after_resume_cmd;
36+
char *logind_lock_cmd;
37+
char *logind_unlock_cmd;
3638
bool wait;
3739
} state;
3840

@@ -109,6 +111,7 @@ static void cmd_exec(char *param) {
109111
#if HAVE_SYSTEMD || HAVE_ELOGIND
110112
static int lock_fd = -1;
111113
static struct sd_bus *bus = NULL;
114+
static char *session_name = NULL;
112115

113116
static void acquire_sleep_lock(void) {
114117
sd_bus_message *msg = NULL;
@@ -178,6 +181,29 @@ static int prepare_for_sleep(sd_bus_message *msg, void *userdata,
178181

179182
return 0;
180183
}
184+
static int handle_lock(sd_bus_message *msg, void *userdata,
185+
sd_bus_error *ret_error) {
186+
swayidle_log(LOG_DEBUG, "Lock signal received");
187+
188+
if (state.logind_lock_cmd) {
189+
cmd_exec(state.logind_lock_cmd);
190+
}
191+
swayidle_log(LOG_DEBUG, "Lock command done");
192+
193+
return 0;
194+
}
195+
196+
static int handle_unlock(sd_bus_message *msg, void *userdata,
197+
sd_bus_error *ret_error) {
198+
swayidle_log(LOG_DEBUG, "Unlock signal received");
199+
200+
if (state.logind_unlock_cmd) {
201+
cmd_exec(state.logind_unlock_cmd);
202+
}
203+
swayidle_log(LOG_DEBUG, "Unlock command done");
204+
205+
return 0;
206+
}
181207

182208
static int dbus_event(int fd, uint32_t mask, void *data) {
183209
sd_bus *bus = data;
@@ -205,27 +231,74 @@ static int dbus_event(int fd, uint32_t mask, void *data) {
205231
return count;
206232
}
207233

208-
static void setup_sleep_listener(void) {
234+
static void connect_to_bus(void) {
209235
int ret = sd_bus_default_system(&bus);
236+
sd_bus_message *msg = NULL;
237+
sd_bus_error error = SD_BUS_ERROR_NULL;
238+
pid_t my_pid = getpid();
239+
const char *session_name_tmp;
210240
if (ret < 0) {
211241
errno = -ret;
212242
swayidle_log_errno(LOG_ERROR, "Failed to open D-Bus connection");
213243
return;
214244
}
245+
struct wl_event_source *source = wl_event_loop_add_fd(state.event_loop,
246+
sd_bus_get_fd(bus), WL_EVENT_READABLE, dbus_event, bus);
247+
wl_event_source_check(source);
248+
ret = sd_bus_call_method(bus, "org.freedesktop.login1",
249+
"/org/freedesktop/login1",
250+
"org.freedesktop.login1.Manager", "GetSessionByPID",
251+
&error, &msg, "u", my_pid);
252+
if (ret < 0) {
253+
swayidle_log(LOG_ERROR,
254+
"Failed to find session name: %s", error.message);
255+
goto cleanup;
256+
}
215257

216-
ret = sd_bus_match_signal(bus, NULL, "org.freedesktop.login1",
258+
ret = sd_bus_message_read(msg, "o", &session_name_tmp);
259+
if (ret < 0) {
260+
swayidle_log(LOG_ERROR,
261+
"Failed to read session name\n");
262+
goto cleanup;
263+
}
264+
session_name = strdup(session_name_tmp);
265+
cleanup:
266+
sd_bus_error_free(&error);
267+
sd_bus_message_unref(msg);
268+
}
269+
270+
static void setup_sleep_listener(void) {
271+
int ret = sd_bus_match_signal(bus, NULL, "org.freedesktop.login1",
217272
"/org/freedesktop/login1", "org.freedesktop.login1.Manager",
218273
"PrepareForSleep", prepare_for_sleep, NULL);
219274
if (ret < 0) {
220275
errno = -ret;
221-
swayidle_log_errno(LOG_ERROR, "Failed to add D-Bus signal match");
276+
swayidle_log_errno(LOG_ERROR, "Failed to add D-Bus signal match : sleep");
222277
return;
223278
}
224279
acquire_sleep_lock();
280+
}
225281

226-
struct wl_event_source *source = wl_event_loop_add_fd(state.event_loop,
227-
sd_bus_get_fd(bus), WL_EVENT_READABLE, dbus_event, bus);
228-
wl_event_source_check(source);
282+
static void setup_lock_listener(void) {
283+
int ret = sd_bus_match_signal(bus, NULL, "org.freedesktop.login1",
284+
session_name, "org.freedesktop.login1.Session",
285+
"Lock", handle_lock, NULL);
286+
if (ret < 0) {
287+
errno = -ret;
288+
swayidle_log_errno(LOG_ERROR, "Failed to add D-Bus signal match : lock");
289+
return;
290+
}
291+
}
292+
293+
static void setup_unlock_listener(void) {
294+
int ret = sd_bus_match_signal(bus, NULL, "org.freedesktop.login1",
295+
session_name, "org.freedesktop.login1.Session",
296+
"Unlock", handle_unlock, NULL);
297+
if (ret < 0) {
298+
errno = -ret;
299+
swayidle_log_errno(LOG_ERROR, "Failed to add D-Bus signal match : unlock");
300+
return;
301+
}
229302
}
230303
#endif
231304

@@ -381,6 +454,46 @@ static int parse_resume(int argc, char **argv) {
381454
return 2;
382455
}
383456

457+
static int parse_lock(int argc, char **argv) {
458+
#if !HAVE_SYSTEMD && !HAVE_ELOGIND
459+
swayidle_log(LOG_ERROR, "lock not supported: swayidle was compiled"
460+
" with neither systemd nor elogind support.");
461+
exit(-1);
462+
#endif
463+
if (argc < 2) {
464+
swayidle_log(LOG_ERROR, "Too few parameters to lock command. "
465+
"Usage: lock <command>");
466+
exit(-1);
467+
}
468+
469+
state.logind_lock_cmd = parse_command(argc - 1, &argv[1]);
470+
if (state.logind_lock_cmd) {
471+
swayidle_log(LOG_DEBUG, "Setup lock hook: %s", state.logind_lock_cmd);
472+
}
473+
474+
return 2;
475+
}
476+
477+
static int parse_unlock(int argc, char **argv) {
478+
#if !HAVE_SYSTEMD && !HAVE_ELOGIND
479+
swayidle_log(LOG_ERROR, "unlock not supported: swayidle was compiled"
480+
" with neither systemd nor elogind support.");
481+
exit(-1);
482+
#endif
483+
if (argc < 2) {
484+
swayidle_log(LOG_ERROR, "Too few parameters to unlock command. "
485+
"Usage: unlock <command>");
486+
exit(-1);
487+
}
488+
489+
state.logind_unlock_cmd = parse_command(argc - 1, &argv[1]);
490+
if (state.logind_unlock_cmd) {
491+
swayidle_log(LOG_DEBUG, "Setup unlock hook: %s", state.logind_unlock_cmd);
492+
}
493+
494+
return 2;
495+
}
496+
384497
static int parse_args(int argc, char *argv[]) {
385498
int c;
386499
while ((c = getopt(argc, argv, "hdw")) != -1) {
@@ -416,6 +529,12 @@ static int parse_args(int argc, char *argv[]) {
416529
} else if (!strcmp("after-resume", argv[i])) {
417530
swayidle_log(LOG_DEBUG, "Got after-resume");
418531
i += parse_resume(argc - i, &argv[i]);
532+
} else if (!strcmp("lock", argv[i])) {
533+
swayidle_log(LOG_DEBUG, "Got lock");
534+
i += parse_lock(argc - i, &argv[i]);
535+
} else if (!strcmp("unlock", argv[i])) {
536+
swayidle_log(LOG_DEBUG, "Got unlock");
537+
i += parse_unlock(argc - i, &argv[i]);
419538
} else {
420539
swayidle_log(LOG_ERROR, "Unsupported command '%s'", argv[i]);
421540
return 1;
@@ -501,10 +620,19 @@ int main(int argc, char *argv[]) {
501620

502621
bool should_run = !wl_list_empty(&state.timeout_cmds);
503622
#if HAVE_SYSTEMD || HAVE_ELOGIND
623+
connect_to_bus();
504624
if (state.before_sleep_cmd || state.after_resume_cmd) {
505625
should_run = true;
506626
setup_sleep_listener();
507627
}
628+
if (state.logind_lock_cmd) {
629+
should_run = true;
630+
setup_lock_listener();
631+
}
632+
if (state.logind_unlock_cmd) {
633+
should_run = true;
634+
setup_unlock_listener();
635+
}
508636
#endif
509637
if (!should_run) {
510638
swayidle_log(LOG_INFO, "No command specified! Nothing to do, will exit");

swayidle.1.scd

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,14 @@ Sending SIGUSR1 to swayidle will immediately enter idle state.
5050
If built with systemd support, executes _command_ after logind signals that the
5151
computer resumed from sleep.
5252

53+
*lock* <command>
54+
If built with systemd support, executes _command_ when logind signals that the
55+
session should be locked
56+
57+
*unlock* <command>
58+
If built with systemd support, executes _command_ when logind signals that the
59+
session should be unlocked
60+
5361
All commands are executed in a shell.
5462

5563
# EXAMPLE
@@ -77,4 +85,4 @@ https://github.com/swaywm/swayidle.
7785

7886
# SEE ALSO
7987

80-
*sway*(5) *swaymsg*(1) *sway-input*(5) *sway-output*(5) *sway-bar*(5)
88+
*sway*(5) *swaymsg*(1) *sway-input*(5) *sway-output*(5) *sway-bar*(5) *loginctl*(1)

0 commit comments

Comments
 (0)