The current inhibitors for going into suspend at lid closure are based on the
presence of a docking station, multiple or no displays and a fixed timeout
after the last suspend event.
I understand the goal to prevent an immediate suspend when the system is booted
with closed lid and other inhibitors are not yet present.
But, ignoring the lid close event for a certain time, might not give the
best user experience.
I wondering wheter we couldn't set the inhibitors in a more userfriendly way.
My approach is based on the assumption that a user only wants a suspend at lid
closure, if there was a lid open before.
If the lid was not opened before, we can IMHO savely assume that there is
another display connected or there is a docking station or the user just want
to boot without display for any reason.
If so, we could record a previous lid open event e.g. in a status file.
We could then inhibit the suspend if there was no previous lid open event or
allow it without timeout, if there was one.
I'm attaching a little example patch to visualize my approach.
Any comment is appreciated.
Regards
Thomas Blume
--
SUSE LINUX Products GmbH GF: Jeff Hawn, Jennifer Guild, Felix Imendörffer, HRB
16746 (AG Nürnberg)
Maxfeldstr. 5 / D-90409 Nürnberg / Phone: +49-911-740 53 - 0
GPG 2048R/2CD4D3E8 9A50 048F 1C73 59AA 4D2E 424E B3C6 3FD9 2CD4 D3E8diff --git a/src/login/logind-button.c b/src/login/logind-button.c
index 2561d13..43d645d 100644
--- a/src/login/logind-button.c
+++ b/src/login/logind-button.c
@@ -32,6 +32,8 @@
#include "util.h"
#include "special.h"
#include "logind-button.h"
+#include
+#include
Button* button_new(Manager *m, const char *name) {
Button *b;
@@ -99,11 +101,21 @@ int button_set_seat(Button *b, const char *sn) {
static int button_recheck(sd_event_source *e, void *userdata) {
Button *b = userdata;
+struct stat st;
assert(b);
assert(b->lid_closed);
-manager_handle_action(b->manager, INHIBIT_HANDLE_LID_SWITCH, b->manager->handle_lid_switch, b->manager->lid_switch_ignore_inhibited, false);
+if (stat("/run/systemd/systemd-lid-opened", &st) == 0) {
+int r;
+
+if (unlink("/run/systemd/systemd-lid-opened") < 0) {
+log_error("Failed to remove /run/systemd/systemd-lid-opened file: %m");
+r = -errno;
+}
+manager_handle_action(b->manager, INHIBIT_HANDLE_LID_SWITCH, b->manager->handle_lid_switch, b->manager->lid_switch_ignore_inhibited, false);
+}
+
return 1;
}
@@ -125,7 +137,7 @@ static int button_install_check_event_source(Button *b) {
static int button_dispatch(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
Button *b = userdata;
-struct input_event ev;
+struct input_event ev, stat st;
ssize_t l;
assert(s);
@@ -186,7 +198,17 @@ static int button_dispatch(sd_event_source *s, int fd, uint32_t revents, void *u
NULL);
b->lid_closed = true;
-manager_handle_action(b->manager, INHIBIT_HANDLE_LID_SWITCH, b->manager->handle_lid_switch, b->manager->lid_switch_ignore_inhibited, true);
+
+if (stat("/run/systemd/systemd-lid-opened", &st) == 0) {
+int r;
+
+if (unlink("/run/systemd/systemd-lid-opened") < 0) {
+log_error("Failed to remove /run/systemd/systemd-lid-opened file: %m");
+r = -errno;
+}
+manager_handle_action(b->manager, INHIBIT_HANDLE_LID_SWITCH, b->manager->handle_lid_switch, b->manager->lid_switch_ignore_inhibited, true);
+}
+
button_install_check_event_source(b);
} else if (ev.code == SW_DOCK) {
@@ -201,12 +223,21 @@ static int button_dispatch(sd_event_source *s, int fd, uint32_t revents, void *u
} else if (ev.type == EV_SW && ev.value == 0) {
if (ev.code == SW_LID) {
+_cleanup_fclose_ FILE *f = NULL;
log_struct(LOG_INFO,
"MESSAGE=Lid opened.",
MESSAGE_ID(SD_MESSAGE_LID_OPENED),
NULL);
b->lid_closed = false;
+
+//save lid open state
+f = fopen("/run/systemd/systemd-lid-opened", "we");
+if (!f) {
+log_error("Failed to write Lid state file: %m");
+return -errno;
+}
+
b->check_event_source = sd_event_source_unref(b->check_event_source);
} else if (ev.code ==