diff --git a/man/logind.conf.xml b/man/logind.conf.xml index 8d2bfc5d5b..4a64ddb827 100644 --- a/man/logind.conf.xml +++ b/man/logind.conf.xml @@ -211,6 +211,7 @@ HandleSuspendKey= HandleHibernateKey= HandleLidSwitch= + HandleLidSwitchExternalPower= HandleLidSwitchDocked= Controls how logind shall handle the @@ -235,12 +236,17 @@ HandleSuspendKey= and HandleLidSwitch= default to suspend. - HandleLidSwitchDocked= defaults to - ignore. + HandleLidSwitchExternalPower= is completely + ignored by default (for backwards compatibility) — an explicit + value must be set before it will be used to determine + behaviour. HandleLidSwitchDocked= defaults + to ignore. HandleHibernateKey= defaults to hibernate. If the system is inserted in a docking station, or if more than one display is connected, the action specified by HandleLidSwitchDocked= + occurs; if the system is on external power the action (if any) + specified by HandleLidSwitchExternalPower= occurs; otherwise the HandleLidSwitch= action occurs. diff --git a/src/login/logind-button.c b/src/login/logind-button.c index 94945f0bcb..2da6e69952 100644 --- a/src/login/logind-button.c +++ b/src/login/logind-button.c @@ -110,9 +110,13 @@ static void button_lid_switch_handle_action(Manager *manager, bool is_edge) { assert(manager); - /* If we are docked, handle the lid switch differently */ + /* If we are docked or on external power, handle the lid switch + * differently */ if (manager_is_docked_or_external_displays(manager)) handle_action = manager->handle_lid_switch_docked; + else if (manager->handle_lid_switch_ep != _HANDLE_ACTION_INVALID && + manager_is_on_external_power()) + handle_action = manager->handle_lid_switch_ep; else handle_action = manager->handle_lid_switch; diff --git a/src/login/logind-core.c b/src/login/logind-core.c index e338682f41..cd10536ce5 100644 --- a/src/login/logind-core.c +++ b/src/login/logind-core.c @@ -602,3 +602,34 @@ bool manager_is_docked_or_external_displays(Manager *m) { return false; } + +bool manager_is_on_external_power(void) { + int r; + + /* For now we only check for AC power, but 'external power' can apply + * to anything that isn't an internal battery */ + r = on_ac_power(); + if (r < 0) + log_warning_errno(r, "Failed to read AC power status: %m"); + else if (r > 0) + return true; + + return false; +} + +bool manager_all_buttons_ignored(Manager *m) { + if (m->handle_power_key != HANDLE_IGNORE) + return false; + if (m->handle_suspend_key != HANDLE_IGNORE) + return false; + if (m->handle_hibernate_key != HANDLE_IGNORE) + return false; + if (m->handle_lid_switch != HANDLE_IGNORE) + return false; + if (m->handle_lid_switch_ep != _HANDLE_ACTION_INVALID && + m->handle_lid_switch_ep != HANDLE_IGNORE) + return false; + if (m->handle_lid_switch_docked != HANDLE_IGNORE) + return false; + return true; +} diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c index ae36ececb5..ed9eba1ee0 100644 --- a/src/login/logind-dbus.c +++ b/src/login/logind-dbus.c @@ -2653,6 +2653,7 @@ const sd_bus_vtable manager_vtable[] = { SD_BUS_PROPERTY("HandleSuspendKey", "s", property_get_handle_action, offsetof(Manager, handle_suspend_key), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("HandleHibernateKey", "s", property_get_handle_action, offsetof(Manager, handle_hibernate_key), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("HandleLidSwitch", "s", property_get_handle_action, offsetof(Manager, handle_lid_switch), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("HandleLidSwitchExternalPower", "s", property_get_handle_action, offsetof(Manager, handle_lid_switch_ep), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("HandleLidSwitchDocked", "s", property_get_handle_action, offsetof(Manager, handle_lid_switch_docked), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("HoldoffTimeoutUSec", "t", NULL, offsetof(Manager, holdoff_timeout_usec), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("IdleAction", "s", property_get_handle_action, offsetof(Manager, idle_action), SD_BUS_VTABLE_PROPERTY_CONST), diff --git a/src/login/logind-gperf.gperf b/src/login/logind-gperf.gperf index ee62db63a5..f6f57526f6 100644 --- a/src/login/logind-gperf.gperf +++ b/src/login/logind-gperf.gperf @@ -27,6 +27,7 @@ Login.HandlePowerKey, config_parse_handle_action, 0, offsetof(Manag Login.HandleSuspendKey, config_parse_handle_action, 0, offsetof(Manager, handle_suspend_key) Login.HandleHibernateKey, config_parse_handle_action, 0, offsetof(Manager, handle_hibernate_key) Login.HandleLidSwitch, config_parse_handle_action, 0, offsetof(Manager, handle_lid_switch) +Login.HandleLidSwitchExternalPower,config_parse_handle_action, 0, offsetof(Manager, handle_lid_switch_ep) Login.HandleLidSwitchDocked, config_parse_handle_action, 0, offsetof(Manager, handle_lid_switch_docked) Login.PowerKeyIgnoreInhibited, config_parse_bool, 0, offsetof(Manager, power_key_ignore_inhibited) Login.SuspendKeyIgnoreInhibited, config_parse_bool, 0, offsetof(Manager, suspend_key_ignore_inhibited) diff --git a/src/login/logind.c b/src/login/logind.c index d15d4cec5b..d9b5f026cf 100644 --- a/src/login/logind.c +++ b/src/login/logind.c @@ -53,6 +53,7 @@ static void manager_reset_config(Manager *m) { m->handle_suspend_key = HANDLE_SUSPEND; m->handle_hibernate_key = HANDLE_HIBERNATE; m->handle_lid_switch = HANDLE_SUSPEND; + m->handle_lid_switch_ep = _HANDLE_ACTION_INVALID; m->handle_lid_switch_docked = HANDLE_IGNORE; m->power_key_ignore_inhibited = false; m->suspend_key_ignore_inhibited = false; @@ -253,11 +254,7 @@ static int manager_enumerate_buttons(Manager *m) { /* Loads buttons from udev */ - if (m->handle_power_key == HANDLE_IGNORE && - m->handle_suspend_key == HANDLE_IGNORE && - m->handle_hibernate_key == HANDLE_IGNORE && - m->handle_lid_switch == HANDLE_IGNORE && - m->handle_lid_switch_docked == HANDLE_IGNORE) + if (manager_all_buttons_ignored(m)) return 0; e = udev_enumerate_new(m->udev); @@ -905,12 +902,7 @@ static int manager_connect_udev(Manager *m) { return r; /* Don't watch keys if nobody cares */ - if (m->handle_power_key != HANDLE_IGNORE || - m->handle_suspend_key != HANDLE_IGNORE || - m->handle_hibernate_key != HANDLE_IGNORE || - m->handle_lid_switch != HANDLE_IGNORE || - m->handle_lid_switch_docked != HANDLE_IGNORE) { - + if (!manager_all_buttons_ignored(m)) { m->udev_button_monitor = udev_monitor_new_from_netlink(m->udev, "udev"); if (!m->udev_button_monitor) return -ENOMEM; diff --git a/src/login/logind.conf.in b/src/login/logind.conf.in index 6f720b7708..40a77dc7be 100644 --- a/src/login/logind.conf.in +++ b/src/login/logind.conf.in @@ -22,6 +22,7 @@ #HandleSuspendKey=suspend #HandleHibernateKey=hibernate #HandleLidSwitch=suspend +#HandleLidSwitchExternalPower=suspend #HandleLidSwitchDocked=ignore #PowerKeyIgnoreInhibited=no #SuspendKeyIgnoreInhibited=no diff --git a/src/login/logind.h b/src/login/logind.h index 8262367135..918bc1f919 100644 --- a/src/login/logind.h +++ b/src/login/logind.h @@ -118,6 +118,7 @@ struct Manager { HandleAction handle_suspend_key; HandleAction handle_hibernate_key; HandleAction handle_lid_switch; + HandleAction handle_lid_switch_ep; HandleAction handle_lid_switch_docked; bool power_key_ignore_inhibited; @@ -160,6 +161,8 @@ int manager_get_user_by_pid(Manager *m, pid_t pid, User **user); int manager_get_session_by_pid(Manager *m, pid_t pid, Session **session); bool manager_is_docked_or_external_displays(Manager *m); +bool manager_is_on_external_power(void); +bool manager_all_buttons_ignored(Manager *m); extern const sd_bus_vtable manager_vtable[];