summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--man/logind.conf.xml14
-rw-r--r--src/login/logind-action.c8
-rw-r--r--src/login/logind-core.c55
-rw-r--r--src/login/logind.h1
4 files changed, 71 insertions, 7 deletions
diff --git a/man/logind.conf.xml b/man/logind.conf.xml
index 54cc37904..767320166 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 c04f2107d..da5a8305f 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 e4e593fa5..b8d03c3a5 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 0344acc8b..74d66415e 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[];