]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
Suspend on lid close based on power status. (#8016)
authorSimon Fowler <simon.fowler@anu.edu.au>
Fri, 9 Feb 2018 16:37:39 +0000 (02:37 +1000)
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Fri, 9 Feb 2018 16:37:39 +0000 (17:37 +0100)
This change adds support for controlling the suspend-on-lid-close
behaviour based on the power status as well as whether the machine is
docked or has an external monitor. For backwards compatibility the new
configuration file variable is ignored completely by default, and must
be set explicitly before being considered in any decisions.

man/logind.conf.xml
src/login/logind-button.c
src/login/logind-core.c
src/login/logind-dbus.c
src/login/logind-gperf.gperf
src/login/logind.c
src/login/logind.conf.in
src/login/logind.h

index 8d2bfc5d5bffa4fe2ef824f4dee4a3fcc12e0538..4a64ddb82774f3467cad39b9d3be764c52e0e229 100644 (file)
         <term><varname>HandleSuspendKey=</varname></term>
         <term><varname>HandleHibernateKey=</varname></term>
         <term><varname>HandleLidSwitch=</varname></term>
+        <term><varname>HandleLidSwitchExternalPower=</varname></term>
         <term><varname>HandleLidSwitchDocked=</varname></term>
 
         <listitem><para>Controls how logind shall handle the
         <varname>HandleSuspendKey=</varname> and
         <varname>HandleLidSwitch=</varname> default to
         <literal>suspend</literal>.
-        <varname>HandleLidSwitchDocked=</varname> defaults to
-        <literal>ignore</literal>.
+        <varname>HandleLidSwitchExternalPower=</varname> is completely
+        ignored by default (for backwards compatibility) &#x2014; an explicit
+        value must be set before it will be used to determine
+        behaviour.  <varname>HandleLidSwitchDocked=</varname> defaults
+        to <literal>ignore</literal>.
         <varname>HandleHibernateKey=</varname> defaults to
         <literal>hibernate</literal>. If the system is inserted in a
         docking station, or if more than one display is connected, the
         action specified by <varname>HandleLidSwitchDocked=</varname>
+        occurs; if the system is on external power the action (if any)
+        specified by <varname>HandleLidSwitchExternalPower=</varname>
         occurs; otherwise the <varname>HandleLidSwitch=</varname>
         action occurs.</para>
 
index 94945f0bcb3dcca8383689d1ec711459e2d4f85d..2da6e699522c833798e023519ec7a5b165ebc682 100644 (file)
@@ -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;
 
index e338682f419cc3064788142655c2b30f365d82e8..cd10536ce524d21f4ea1a2fb1fbfd3e1343ad54a 100644 (file)
@@ -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;
+}
index ae36ececb51746bde8ef0427f8740d123c19aa63..ed9eba1ee05156404931f72ac805b3a065377d22 100644 (file)
@@ -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),
index ee62db63a559b4cd0b9739748436def0767ab22b..f6f57526f6143bf68f9f28ae380051a5bc97380f 100644 (file)
@@ -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)
index d15d4cec5b0327774a52df1155b00d69c1c0a0db..d9b5f026cff8a09fefd2abcca51ae50a9feeadb8 100644 (file)
@@ -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;
index 6f720b77087142237a9666d07b3465b7b03e78e4..40a77dc7be9eb6dad779b7ec4909dbd3963edebf 100644 (file)
@@ -22,6 +22,7 @@
 #HandleSuspendKey=suspend
 #HandleHibernateKey=hibernate
 #HandleLidSwitch=suspend
+#HandleLidSwitchExternalPower=suspend
 #HandleLidSwitchDocked=ignore
 #PowerKeyIgnoreInhibited=no
 #SuspendKeyIgnoreInhibited=no
index 82623671352addf9f2d9f9bb617d462de24adb13..918bc1f91901c7ddcde39560e6244c730714eb82 100644 (file)
@@ -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[];