diff options
Diffstat (limited to 'src/login')
-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 |
3 files changed, 62 insertions, 2 deletions
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[]; |