diff options
-rw-r--r-- | man/logind.conf.xml | 14 | ||||
-rw-r--r-- | src/login/logind-action.c | 8 | ||||
-rw-r--r-- | src/login/logind-core.c | 55 | ||||
-rw-r--r-- | src/login/logind.h | 1 |
4 files changed, 71 insertions, 7 deletions
diff --git a/man/logind.conf.xml b/man/logind.conf.xml index 54cc379048..7673201664 100644 --- a/man/logind.conf.xml +++ b/man/logind.conf.xml @@ -242,10 +242,10 @@ <literal>ignore</literal>, logind will never handle these keys. If <literal>lock</literal>, all running - sessions will be screen-locked; otherwise, - the specified action - will be taken in the respective - event. Only input devices with the + sessions will be screen-locked; + otherwise, the specified action will + be taken in the respective event. Only + input devices with the <literal>power-switch</literal> udev tag will be watched for key/lid switch events. <varname>HandlePowerKey=</varname> @@ -257,7 +257,11 @@ default to <literal>suspend</literal>. <varname>HandleHibernateKey=</varname> defaults to - <literal>hibernate</literal>.</para></listitem> + <literal>hibernate</literal>. Note + that the lid switch is ignored if the + system is inserted in a docking + station, or if more than one display + is connected.</para></listitem> </varlistentry> <varlistentry> diff --git a/src/login/logind-action.c b/src/login/logind-action.c index c04f2107d1..da5a8305fa 100644 --- a/src/login/logind-action.c +++ b/src/login/logind-action.c @@ -72,10 +72,18 @@ int manager_handle_action( /* If we are docked don't react to lid closing */ if (inhibit_key == INHIBIT_HANDLE_LID_SWITCH) { + int n; + if (manager_is_docked(m)) { log_debug("Ignoring lid switch request, system is docked."); return 0; } + + n = manager_count_displays(m); + if (n != 1) { + log_debug("Ignoring lid switch request, %s displays connected."); + return 0; + } } /* If the key handling is inhibited, don't do anything */ diff --git a/src/login/logind-core.c b/src/login/logind-core.c index e4e593fa5b..b8d03c3a59 100644 --- a/src/login/logind-core.c +++ b/src/login/logind-core.c @@ -32,6 +32,7 @@ #include "audit.h" #include "bus-util.h" #include "bus-error.h" +#include "udev-util.h" #include "logind.h" int manager_add_device(Manager *m, const char *sysfs, bool master, Device **_device) { @@ -276,9 +277,11 @@ int manager_process_seat_device(Manager *m, struct udev_device *d) { return 0; } - /* ignore non-master devices for unknown seats */ + seat = hashmap_get(m->seats, sn); master = udev_device_has_tag(d, "master-of-seat"); - if (!master && !(seat = hashmap_get(m->seats, sn))) + + /* Ignore non-master devices for unknown seats */ + if (!master && !seat) return 0; r = manager_add_device(m, udev_device_get_syspath(d), master, &device); @@ -514,3 +517,51 @@ bool manager_is_docked(Manager *m) { return false; } + +int manager_count_displays(Manager *m) { + _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL; + struct udev_list_entry *item = NULL, *first = NULL; + int r; + int n = 0; + + e = udev_enumerate_new(m->udev); + if (!e) + return -ENOMEM; + + r = udev_enumerate_add_match_subsystem(e, "drm"); + if (r < 0) + return r; + + r = udev_enumerate_scan_devices(e); + if (r < 0) + return r; + + first = udev_enumerate_get_list_entry(e); + udev_list_entry_foreach(item, first) { + _cleanup_udev_device_unref_ struct udev_device *d = NULL; + struct udev_device *p; + const char *status; + + d = udev_device_new_from_syspath(m->udev, udev_list_entry_get_name(item)); + if (!d) + return -ENOMEM; + + p = udev_device_get_parent(d); + if (!p) + return -ENOMEM; + + /* If the parent shares the same subsystem as the + * device we are looking at then it is a connector, + * which is what we are interested in. */ + if (!streq_ptr(udev_device_get_subsystem(p), "drm")) + continue; + + /* We count any connector which is not explicitly + * "disconnected" as connected. */ + status = udev_device_get_sysattr_value(d, "status"); + if (!streq_ptr(status, "disconnected")) + n++; + } + + return n; +} diff --git a/src/login/logind.h b/src/login/logind.h index 0344acc8bd..74d66415ee 100644 --- a/src/login/logind.h +++ b/src/login/logind.h @@ -149,6 +149,7 @@ 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(Manager *m); +int manager_count_displays(Manager *m); extern const sd_bus_vtable manager_vtable[]; |