diff options
author | Lennart Poettering <lennart@poettering.net> | 2014-03-03 20:49:33 +0100 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2014-03-03 20:57:09 +0100 |
commit | f9cd6be10ece07e10488c05e270a0b5860779864 (patch) | |
tree | f236bd39b54c2b66276c7ac72a36cb565cf0b53e /src/login/logind.c | |
parent | 7e9110a29d90041b0364cb93a84aec9dd72363b6 (diff) |
logind: ignore lid switch events for 30s after each suspend and 3min after startup
This is needed to give USB docking stations and suchlike time to settle,
so that a display connected to an USB docking station can actually act
as a lid swith inhibitor correctly.
With this change we should have somewhat reliable docking station
support in place.
Diffstat (limited to 'src/login/logind.c')
-rw-r--r-- | src/login/logind.c | 45 |
1 files changed, 45 insertions, 0 deletions
diff --git a/src/login/logind.c b/src/login/logind.c index 10f61aba38..fd113b3e79 100644 --- a/src/login/logind.c +++ b/src/login/logind.c @@ -144,6 +144,7 @@ void manager_free(Manager *m) { sd_event_source_unref(m->udev_device_event_source); sd_event_source_unref(m->udev_vcsa_event_source); sd_event_source_unref(m->udev_button_event_source); + sd_event_source_unref(m->lid_switch_ignore_event_source); if (m->console_active_fd >= 0) close_nointr_nofail(m->console_active_fd); @@ -959,6 +960,46 @@ static int manager_dispatch_idle_action(sd_event_source *s, uint64_t t, void *us return 0; } +static int lid_switch_ignore_handler(sd_event_source *e, uint64_t usec, void *userdata) { + Manager *m = userdata; + + assert(e); + assert(m); + + m->lid_switch_ignore_event_source = sd_event_source_unref(m->lid_switch_ignore_event_source); + return 0; +} + +int manager_set_lid_switch_ignore(Manager *m, usec_t until) { + int r; + + assert(m); + + if (until <= now(CLOCK_MONOTONIC)) + return 0; + + /* We want to ignore the lid switch for a while after each + * suspend, and after boot-up. Hence let's install a timer for + * this. As long as the event source exists we ignore the lid + * switch. */ + + if (m->lid_switch_ignore_event_source) { + usec_t u; + + r = sd_event_source_get_time(m->lid_switch_ignore_event_source, &u); + if (r < 0) + return r; + + if (until <= u) + return 0; + + r = sd_event_source_set_time(m->lid_switch_ignore_event_source, until); + } else + r = sd_event_add_monotonic(m->event, &m->lid_switch_ignore_event_source, until, 0, lid_switch_ignore_handler, m); + + return r; +} + int manager_startup(Manager *m) { int r; Seat *seat; @@ -994,6 +1035,10 @@ int manager_startup(Manager *m) { return r; } + r = manager_set_lid_switch_ignore(m, 0 + IGNORE_LID_SWITCH_STARTUP_USEC); + if (r < 0) + log_warning("Failed to set up lid switch ignore event source: %s", strerror(-r)); + /* Deserialize state */ r = manager_enumerate_devices(m); if (r < 0) |