chiark / gitweb /
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)
committerSven Eden <yamakuzure@gmx.net>
Wed, 30 May 2018 05:58:50 +0000 (07:58 +0200)
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 a1a664a826ff7aa7ff31a3aba845813ddec9a426..43cb42698b1e309779f4703a16bbb59a519750ca 100644 (file)
@@ -3,9 +3,9 @@
   "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
 
 <!--
-  This file is part of elogind.
   SPDX-License-Identifier: LGPL-2.1+
 
+  This file is part of elogind.
 
   Copyright 2010 Lennart Poettering
 
 <!-- 0 /// elogind does not have to enable itself in configure
 <refentry id="logind.conf" conditional='ENABLE_LOGIND'
     xmlns:xi="http://www.w3.org/2001/XInclude">
+    <productname>systemd</productname>
 --><!-- else -->
 <refentry id="logind.conf" xmlns:xi="http://www.w3.org/2001/XInclude">
 <!-- // 0 -->
   <refentryinfo>
     <title>logind.conf</title>
-    <productname>elogind</productname>
 
     <authorgroup>
       <author>
         <citerefentry><refentrytitle>loginctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>.
         </para>
         // 0 -->
+
         <para>Note that setting <varname>KillUserProcesses=yes</varname>
         will break tools like
         <citerefentry project='die-net'><refentrytitle>screen</refentrytitle><manvolnum>1</manvolnum></citerefentry>
         <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 625521e34a153c787fc58cc7475f6a7499510a87..c4dd48e086e9bb39341adafe11583d3ed59808a0 100644 (file)
@@ -631,3 +631,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 c3b0565682449c1c1b2e7555c571671eb5a73515..dd441ccc1b2e1f3934cd5eb0728b39b4783f6f23 100644 (file)
@@ -2729,6 +2729,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 63ac5a2b97e6c22f76f6c9c61e64254f9f63ca57..c520cd5ac869204398c7fe7d014468d7fcc47409 100644 (file)
@@ -29,6 +29,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 6993b965eebdf2a3a6878b63caf5b9a23d8ad7c0..356236178524c77c7d62f56155558409ddaa849b 100644 (file)
@@ -66,6 +66,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;
@@ -280,11 +281,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);
@@ -944,12 +941,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 a3b89df4e19a53ae4ae0ad6a5702458de09dc7ab..b1070d10d2a7ef34115c52b91967a60216066741 100644 (file)
@@ -22,6 +22,7 @@
 #HandleSuspendKey=suspend
 #HandleHibernateKey=hibernate
 #HandleLidSwitch=suspend
+#HandleLidSwitchExternalPower=suspend
 #HandleLidSwitchDocked=ignore
 #PowerKeyIgnoreInhibited=no
 #SuspendKeyIgnoreInhibited=no
index 95de51a6556dde98373ccad4025d5ca6fe1e954c..c72d10ef29d9992fb356510ff6c1b9c6aee6f9b8 100644 (file)
@@ -161,6 +161,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;
@@ -205,6 +206,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[];