diff --git a/idle.xml b/idle.xml new file mode 100644 index 0000000..92d9989 --- /dev/null +++ b/idle.xml @@ -0,0 +1,49 @@ + + + . + ]]> + + + This interface allows to monitor user idle time on a given seat. The interface + allows to register timers which trigger after no user activity was registered + on the seat for a given interval. It notifies when user activity resumes. + + This is useful for applications wanting to perform actions when the user is not + interacting with the system, e.g. chat applications setting the user as away, power + management features to dim screen, etc.. + + + + + + + + + + + + + + + + + + + + + + diff --git a/main.c b/main.c index 41eecc4..a25e154 100644 --- a/main.c +++ b/main.c @@ -18,7 +18,6 @@ #include #include "config.h" #include "idle-client-protocol.h" -#include "list.h" #if HAVE_SYSTEMD #include #include @@ -33,11 +32,12 @@ static struct wl_seat *seat = NULL; struct swayidle_state { struct wl_display *display; struct wl_event_loop *event_loop; - list_t *timeout_cmds; // struct swayidle_timeout_cmd * + struct wl_list timeout_cmds; // struct swayidle_timeout_cmd * char *lock_cmd; } state; struct swayidle_timeout_cmd { + struct wl_list link; int timeout, registered_timeout; struct org_kde_kwin_idle_timeout *idle_timer; char *idle_cmd; @@ -318,7 +318,7 @@ static int parse_timeout(int argc, char **argv) { cmd->resume_cmd = parse_command(argc - 4, &argv[4]); result = 5; } - list_add(state.timeout_cmds, cmd); + wl_list_insert(&state.timeout_cmds, &cmd->link); return result; } @@ -359,7 +359,7 @@ static int parse_args(int argc, char *argv[]) { wlr_log_init(debug ? WLR_DEBUG : WLR_INFO, NULL); - state.timeout_cmds = create_list(); + wl_list_init(&state.timeout_cmds); int i = optind; while (i < argc) { @@ -386,8 +386,9 @@ static int handle_signal(int sig, void *data) { return 0; case SIGUSR1: wlr_log(WLR_DEBUG, "Got SIGUSR1"); - for (int i = 0; i < state.timeout_cmds->length; ++i) { - register_timeout(state.timeout_cmds->items[i], 0); + struct swayidle_timeout_cmd *cmd; + wl_list_for_each(cmd, &state.timeout_cmds, link) { + register_timeout(cmd, 0); } return 1; } @@ -451,7 +452,7 @@ int main(int argc, char *argv[]) { return -5; } - bool should_run = state.timeout_cmds->length > 0; + bool should_run = !wl_list_empty(&state.timeout_cmds); #if HAVE_SYSTEMD || HAVE_ELOGIND if (state.lock_cmd) { should_run = true; @@ -463,8 +464,8 @@ int main(int argc, char *argv[]) { sway_terminate(0); } - for (int i = 0; i < state.timeout_cmds->length; ++i) { - struct swayidle_timeout_cmd *cmd = state.timeout_cmds->items[i]; + struct swayidle_timeout_cmd *cmd; + wl_list_for_each(cmd, &state.timeout_cmds, link) { register_timeout(cmd, cmd->timeout); } diff --git a/meson.build b/meson.build index 79d2c5c..3676772 100644 --- a/meson.build +++ b/meson.build @@ -1,4 +1,70 @@ +project( + 'swayidle', + 'c', + license: 'MIT', + default_options: [ + 'c_std=c11', + 'warning_level=2', + 'werror=true', + ], +) + +add_project_arguments( + [ + '-DWL_HIDE_DEPRECATED', + '-DWLR_USE_UNSTABLE', + '-Wno-unused-parameter', + '-Wno-unused-result', + '-Wundef', + ], + language: 'c', +) + +elogind = dependency('libelogind', required: false) +systemd = dependency('libsystemd', required: false) threads = dependency('threads') +pixman = dependency('pixman-1') +wayland_client = dependency('wayland-client') +wayland_protos = dependency('wayland-protocols', version: '>=1.14') +wayland_server = dependency('wayland-server') +wlroots = dependency('wlroots') + +scdoc = find_program('scdoc', required: false) +wayland_scanner = find_program('wayland-scanner') + +wl_protocol_dir = wayland_protos.get_pkgconfig_variable('pkgdatadir') + +if wayland_server.version().version_compare('>=1.14.91') + code_type = 'private-code' +else + code_type = 'code' +endif + +wayland_scanner_code = generator( + wayland_scanner, + output: '@BASENAME@-protocol.c', + arguments: [code_type, '@INPUT@', '@OUTPUT@'], +) + +wayland_scanner_client = generator( + wayland_scanner, + output: '@BASENAME@-client-protocol.h', + arguments: ['client-header', '@INPUT@', '@OUTPUT@'], +) + +client_protos_src = wayland_scanner_code.process('idle.xml') +client_protos_headers = wayland_scanner_client.process('idle.xml') + +lib_client_protos = static_library( + 'client_protos', + [client_protos_src, client_protos_headers], + dependencies: [wayland_client] +) # for the include directory + +client_protos = declare_dependency( + link_with: lib_client_protos, + sources: client_protos_headers, +) swayidle_deps = [ client_protos, @@ -15,13 +81,39 @@ if elogind.found() swayidle_deps += elogind endif +conf_data = configuration_data() +conf_data.set10('HAVE_SYSTEMD', systemd.found()) +conf_data.set10('HAVE_ELOGIND', elogind.found()) +configure_file(output: 'config.h', configuration: conf_data) + executable( 'swayidle', [ 'main.c', ], - include_directories: [sway_inc], dependencies: swayidle_deps, - link_with: [lib_sway_common, lib_sway_client], - install_rpath : rpathdir, install: true ) + +if scdoc.found() + sh = find_program('sh') + mandir = get_option('mandir') + man_files = [ + 'swayidle.1.scd', + ] + foreach filename : man_files + topic = filename.split('.')[-3].split('/')[-1] + section = filename.split('.')[-2] + output = '@0@.@1@'.format(topic, section) + + custom_target( + output, + input: filename, + output: output, + command: [ + sh, '-c', '@0@ < @INPUT@ > @1@'.format(scdoc.path(), output) + ], + install: true, + install_dir: '@0@/man@1@'.format(mandir, section) + ) + endforeach +endif