|
|
bac6df9 |
From 602a41c22ac2df33b4b5e5083719c1cfaf58acf9 Mon Sep 17 00:00:00 2001
|
|
|
bac6df9 |
From: Lennart Poettering <lennart@poettering.net>
|
|
|
bac6df9 |
Date: Wed, 17 Jun 2015 00:24:05 +0200
|
|
|
bac6df9 |
Subject: [PATCH] logind: rework display counting when detecting whether the
|
|
|
bac6df9 |
system is docked
|
|
|
bac6df9 |
|
|
|
bac6df9 |
Previously, we'd just count connected displays, and if there was 2 or
|
|
|
bac6df9 |
more we assumed a "docked" state.
|
|
|
bac6df9 |
|
|
|
bac6df9 |
With this change we now:
|
|
|
bac6df9 |
|
|
|
bac6df9 |
- Only count external displays, ignore internal ones (which we detect by
|
|
|
bac6df9 |
checking the connector name against a whitelist of known external plug
|
|
|
bac6df9 |
types)
|
|
|
bac6df9 |
|
|
|
bac6df9 |
- We ignore connectors which are explicitly disabled
|
|
|
bac6df9 |
|
|
|
bac6df9 |
- We then compare the count with >= 1 rather than >= 2 as before
|
|
|
bac6df9 |
|
|
|
bac6df9 |
This new logic has the benefit that systems that disconnect the internal
|
|
|
bac6df9 |
display when the lid is closed are better supported. Also, explicitly
|
|
|
bac6df9 |
disabled ports do not confuse the algorithm anymore.
|
|
|
bac6df9 |
|
|
|
bac6df9 |
This new algorithm has been suggested here:
|
|
|
bac6df9 |
|
|
|
bac6df9 |
http://lists.freedesktop.org/archives/intel-gfx/2015-June/068821.html
|
|
|
bac6df9 |
|
|
|
bac6df9 |
This also makes two functions static, that are not used outside of their
|
|
|
bac6df9 |
.c files.
|
|
|
bac6df9 |
---
|
|
|
bac6df9 |
src/login/logind-button.c | 2 +-
|
|
|
bac6df9 |
src/login/logind-core.c | 49 ++++++++++++++++++++++++++++++++++++++++-------
|
|
|
bac6df9 |
src/login/logind-dbus.c | 2 +-
|
|
|
bac6df9 |
src/login/logind.h | 4 +---
|
|
|
bac6df9 |
4 files changed, 45 insertions(+), 12 deletions(-)
|
|
|
bac6df9 |
|
|
|
bac6df9 |
diff --git a/src/login/logind-button.c b/src/login/logind-button.c
|
|
|
bac6df9 |
index 8079d0b..210b889 100644
|
|
|
bac6df9 |
--- a/src/login/logind-button.c
|
|
|
bac6df9 |
+++ b/src/login/logind-button.c
|
|
|
bac6df9 |
@@ -100,7 +100,7 @@ static void button_lid_switch_handle_action(Manager *manager, bool is_edge) {
|
|
|
bac6df9 |
assert(manager);
|
|
|
bac6df9 |
|
|
|
bac6df9 |
/* If we are docked, handle the lid switch differently */
|
|
|
bac6df9 |
- if (manager_is_docked_or_multiple_displays(manager))
|
|
|
bac6df9 |
+ if (manager_is_docked_or_external_displays(manager))
|
|
|
bac6df9 |
handle_action = manager->handle_lid_switch_docked;
|
|
|
bac6df9 |
else
|
|
|
bac6df9 |
handle_action = manager->handle_lid_switch;
|
|
|
bac6df9 |
diff --git a/src/login/logind-core.c b/src/login/logind-core.c
|
|
|
bac6df9 |
index f9e6ddf..a6c01f7 100644
|
|
|
bac6df9 |
--- a/src/login/logind-core.c
|
|
|
bac6df9 |
+++ b/src/login/logind-core.c
|
|
|
bac6df9 |
@@ -477,7 +477,7 @@ int manager_spawn_autovt(Manager *m, unsigned int vtnr) {
|
|
|
bac6df9 |
return r;
|
|
|
bac6df9 |
}
|
|
|
bac6df9 |
|
|
|
bac6df9 |
-bool manager_is_docked(Manager *m) {
|
|
|
bac6df9 |
+static bool manager_is_docked(Manager *m) {
|
|
|
bac6df9 |
Iterator i;
|
|
|
bac6df9 |
Button *b;
|
|
|
bac6df9 |
|
|
|
bac6df9 |
@@ -488,7 +488,7 @@ bool manager_is_docked(Manager *m) {
|
|
|
bac6df9 |
return false;
|
|
|
bac6df9 |
}
|
|
|
bac6df9 |
|
|
|
bac6df9 |
-int manager_count_displays(Manager *m) {
|
|
|
bac6df9 |
+static int manager_count_external_displays(Manager *m) {
|
|
|
bac6df9 |
_cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL;
|
|
|
bac6df9 |
struct udev_list_entry *item = NULL, *first = NULL;
|
|
|
bac6df9 |
int r;
|
|
|
bac6df9 |
@@ -510,7 +510,8 @@ int manager_count_displays(Manager *m) {
|
|
|
bac6df9 |
udev_list_entry_foreach(item, first) {
|
|
|
bac6df9 |
_cleanup_udev_device_unref_ struct udev_device *d = NULL;
|
|
|
bac6df9 |
struct udev_device *p;
|
|
|
bac6df9 |
- const char *status;
|
|
|
bac6df9 |
+ const char *status, *enabled, *dash, *nn, *i;
|
|
|
bac6df9 |
+ bool external = false;
|
|
|
bac6df9 |
|
|
|
bac6df9 |
d = udev_device_new_from_syspath(m->udev, udev_list_entry_get_name(item));
|
|
|
bac6df9 |
if (!d)
|
|
|
bac6df9 |
@@ -526,6 +527,40 @@ int manager_count_displays(Manager *m) {
|
|
|
bac6df9 |
if (!streq_ptr(udev_device_get_subsystem(p), "drm"))
|
|
|
bac6df9 |
continue;
|
|
|
bac6df9 |
|
|
|
bac6df9 |
+ nn = udev_device_get_sysname(d);
|
|
|
bac6df9 |
+ if (!nn)
|
|
|
bac6df9 |
+ continue;
|
|
|
bac6df9 |
+
|
|
|
bac6df9 |
+ /* Ignore internal displays: the type is encoded in
|
|
|
bac6df9 |
+ * the sysfs name, as the second dash seperated item
|
|
|
bac6df9 |
+ * (the first is the card name, the last the connector
|
|
|
bac6df9 |
+ * number). We implement a whitelist of external
|
|
|
bac6df9 |
+ * displays here, rather than a whitelist, to ensure
|
|
|
bac6df9 |
+ * we don't block suspends too eagerly. */
|
|
|
bac6df9 |
+ dash = strchr(nn, '-');
|
|
|
bac6df9 |
+ if (!dash)
|
|
|
bac6df9 |
+ continue;
|
|
|
bac6df9 |
+
|
|
|
bac6df9 |
+ dash++;
|
|
|
bac6df9 |
+ FOREACH_STRING(i, "VGA-", "DVI-I-", "DVI-D-", "DVI-A-"
|
|
|
bac6df9 |
+ "Composite-", "SVIDEO-", "Component-",
|
|
|
bac6df9 |
+ "DIN-", "DP-", "HDMI-A-", "HDMI-B-", "TV-") {
|
|
|
bac6df9 |
+
|
|
|
bac6df9 |
+ if (startswith(dash, i)) {
|
|
|
bac6df9 |
+ external = true;
|
|
|
bac6df9 |
+ break;
|
|
|
bac6df9 |
+ }
|
|
|
bac6df9 |
+ }
|
|
|
bac6df9 |
+ if (!external)
|
|
|
bac6df9 |
+ continue;
|
|
|
bac6df9 |
+
|
|
|
bac6df9 |
+ /* Ignore ports that are not enabled */
|
|
|
bac6df9 |
+ enabled = udev_device_get_sysattr_value(d, "enabled");
|
|
|
bac6df9 |
+ if (!enabled)
|
|
|
bac6df9 |
+ continue;
|
|
|
bac6df9 |
+ if (!streq_ptr(enabled, "enabled"))
|
|
|
bac6df9 |
+ continue;
|
|
|
bac6df9 |
+
|
|
|
bac6df9 |
/* We count any connector which is not explicitly
|
|
|
bac6df9 |
* "disconnected" as connected. */
|
|
|
bac6df9 |
status = udev_device_get_sysattr_value(d, "status");
|
|
|
bac6df9 |
@@ -536,7 +571,7 @@ int manager_count_displays(Manager *m) {
|
|
|
bac6df9 |
return n;
|
|
|
bac6df9 |
}
|
|
|
bac6df9 |
|
|
|
bac6df9 |
-bool manager_is_docked_or_multiple_displays(Manager *m) {
|
|
|
bac6df9 |
+bool manager_is_docked_or_external_displays(Manager *m) {
|
|
|
bac6df9 |
int n;
|
|
|
bac6df9 |
|
|
|
bac6df9 |
/* If we are docked don't react to lid closing */
|
|
|
bac6df9 |
@@ -547,11 +582,11 @@ bool manager_is_docked_or_multiple_displays(Manager *m) {
|
|
|
bac6df9 |
|
|
|
bac6df9 |
/* If we have more than one display connected,
|
|
|
bac6df9 |
* assume that we are docked. */
|
|
|
bac6df9 |
- n = manager_count_displays(m);
|
|
|
bac6df9 |
+ n = manager_count_external_displays(m);
|
|
|
bac6df9 |
if (n < 0)
|
|
|
bac6df9 |
log_warning_errno(n, "Display counting failed: %m");
|
|
|
bac6df9 |
- else if (n > 1) {
|
|
|
bac6df9 |
- log_debug("Multiple (%i) displays connected.", n);
|
|
|
bac6df9 |
+ else if (n >= 1) {
|
|
|
bac6df9 |
+ log_debug("External (%i) displays connected.", n);
|
|
|
bac6df9 |
return true;
|
|
|
bac6df9 |
}
|
|
|
bac6df9 |
|
|
|
bac6df9 |
diff --git a/src/login/logind.h b/src/login/logind.h
|
|
|
bac6df9 |
index cd226f5..feb381d 100644
|
|
|
bac6df9 |
--- a/src/login/logind.h
|
|
|
bac6df9 |
+++ b/src/login/logind.h
|
|
|
bac6df9 |
@@ -156,9 +156,7 @@ int manager_get_idle_hint(Manager *m, dual_timestamp *t);
|
|
|
bac6df9 |
int manager_get_user_by_pid(Manager *m, pid_t pid, User **user);
|
|
|
bac6df9 |
int manager_get_session_by_pid(Manager *m, pid_t pid, Session **session);
|
|
|
bac6df9 |
|
|
|
bac6df9 |
-bool manager_is_docked(Manager *m);
|
|
|
bac6df9 |
-int manager_count_displays(Manager *m);
|
|
|
bac6df9 |
-bool manager_is_docked_or_multiple_displays(Manager *m);
|
|
|
bac6df9 |
+bool manager_is_docked_or_external_displays(Manager *m);
|
|
|
bac6df9 |
|
|
|
bac6df9 |
extern const sd_bus_vtable manager_vtable[];
|
|
|
bac6df9 |
|
|
|
bac6df9 |
--
|
|
|
bac6df9 |
2.4.3
|
|
|
bac6df9 |
|