@@ -33,6 +33,8 @@ struct swayidle_state {
33
33
struct wl_list timeout_cmds ; // struct swayidle_timeout_cmd *
34
34
char * before_sleep_cmd ;
35
35
char * after_resume_cmd ;
36
+ char * logind_lock_cmd ;
37
+ char * logind_unlock_cmd ;
36
38
bool wait ;
37
39
} state ;
38
40
@@ -109,6 +111,7 @@ static void cmd_exec(char *param) {
109
111
#if HAVE_SYSTEMD || HAVE_ELOGIND
110
112
static int lock_fd = -1 ;
111
113
static struct sd_bus * bus = NULL ;
114
+ static char * session_name = NULL ;
112
115
113
116
static void acquire_sleep_lock (void ) {
114
117
sd_bus_message * msg = NULL ;
@@ -178,6 +181,29 @@ static int prepare_for_sleep(sd_bus_message *msg, void *userdata,
178
181
179
182
return 0 ;
180
183
}
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
+ }
181
207
182
208
static int dbus_event (int fd , uint32_t mask , void * data ) {
183
209
sd_bus * bus = data ;
@@ -205,27 +231,74 @@ static int dbus_event(int fd, uint32_t mask, void *data) {
205
231
return count ;
206
232
}
207
233
208
- static void setup_sleep_listener (void ) {
234
+ static void connect_to_bus (void ) {
209
235
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 ;
210
240
if (ret < 0 ) {
211
241
errno = - ret ;
212
242
swayidle_log_errno (LOG_ERROR , "Failed to open D-Bus connection" );
213
243
return ;
214
244
}
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
+ }
215
257
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" ,
217
272
"/org/freedesktop/login1" , "org.freedesktop.login1.Manager" ,
218
273
"PrepareForSleep" , prepare_for_sleep , NULL );
219
274
if (ret < 0 ) {
220
275
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 " );
222
277
return ;
223
278
}
224
279
acquire_sleep_lock ();
280
+ }
225
281
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
+ }
229
302
}
230
303
#endif
231
304
@@ -381,6 +454,46 @@ static int parse_resume(int argc, char **argv) {
381
454
return 2 ;
382
455
}
383
456
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
+
384
497
static int parse_args (int argc , char * argv []) {
385
498
int c ;
386
499
while ((c = getopt (argc , argv , "hdw" )) != -1 ) {
@@ -416,6 +529,12 @@ static int parse_args(int argc, char *argv[]) {
416
529
} else if (!strcmp ("after-resume" , argv [i ])) {
417
530
swayidle_log (LOG_DEBUG , "Got after-resume" );
418
531
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 ]);
419
538
} else {
420
539
swayidle_log (LOG_ERROR , "Unsupported command '%s'" , argv [i ]);
421
540
return 1 ;
@@ -501,10 +620,19 @@ int main(int argc, char *argv[]) {
501
620
502
621
bool should_run = !wl_list_empty (& state .timeout_cmds );
503
622
#if HAVE_SYSTEMD || HAVE_ELOGIND
623
+ connect_to_bus ();
504
624
if (state .before_sleep_cmd || state .after_resume_cmd ) {
505
625
should_run = true;
506
626
setup_sleep_listener ();
507
627
}
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
+ }
508
636
#endif
509
637
if (!should_run ) {
510
638
swayidle_log (LOG_INFO , "No command specified! Nothing to do, will exit" );
0 commit comments