forked from pool/systemd
169 lines
6.5 KiB
Diff
169 lines
6.5 KiB
Diff
From 6a79c58603ea816a1b4fa1520397b4e138bc1ca0 Mon Sep 17 00:00:00 2001
|
|
From: Lennart Poettering <lennart@poettering.net>
|
|
Date: Mon, 3 Mar 2014 19:30:16 +0100
|
|
Subject: [PATCH] logind: ignore lid switch if more than 1 display is
|
|
connected
|
|
|
|
Previously we expected the desktop environment to take an inhibitor
|
|
lock, but this opened a race on boot-up where logind might already be
|
|
running but no DE is active.
|
|
|
|
Hence, let's move checking for additional displays into logind. This
|
|
also opens up this logic for other DEs, given that only GNOME
|
|
implemented the inhibitor logic so far.
|
|
---
|
|
man/logind.conf.xml | 14 +++++++-----
|
|
src/login/logind-action.c | 8 +++++++
|
|
src/login/logind-core.c | 55 +++++++++++++++++++++++++++++++++++++++++++--
|
|
src/login/logind.h | 1 +
|
|
4 files changed, 71 insertions(+), 7 deletions(-)
|
|
|
|
diff --git man/logind.conf.xml man/logind.conf.xml
|
|
index 54cc379..7673201 100644
|
|
--- man/logind.conf.xml
|
|
+++ 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 src/login/logind-action.c src/login/logind-action.c
|
|
index c04f210..da5a830 100644
|
|
--- src/login/logind-action.c
|
|
+++ 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 src/login/logind-core.c src/login/logind-core.c
|
|
index e4e593f..b8d03c3 100644
|
|
--- src/login/logind-core.c
|
|
+++ 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 src/login/logind.h src/login/logind.h
|
|
index 0344acc..74d6641 100644
|
|
--- src/login/logind.h
|
|
+++ 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[];
|
|
|
|
--
|
|
1.7.9.2
|
|
|