diff options
Diffstat (limited to 'backend/session/logind.c')
-rw-r--r-- | backend/session/logind.c | 127 |
1 files changed, 127 insertions, 0 deletions
diff --git a/backend/session/logind.c b/backend/session/logind.c index 39143a2f..b44112e6 100644 --- a/backend/session/logind.c +++ b/backend/session/logind.c @@ -35,6 +35,11 @@ struct logind_session { char *id; char *path; + + // specifies whether a drm device was taken + // if so, the session will be (de)activated with the drm fd, + // otherwise with the dbus PropertiesChanged on "active" signal + bool has_drm; }; static struct logind_session *logind_session_from_session( @@ -57,6 +62,10 @@ static int logind_take_device(struct wlr_session *base, const char *path) { return -1; } + if (major(st.st_rdev) == DRM_MAJOR) { + session->has_drm = true; + } + ret = sd_bus_call_method(session->bus, "org.freedesktop.login1", session->path, "org.freedesktop.login1.Session", "TakeDevice", &error, &msg, "uu", major(st.st_rdev), minor(st.st_rdev)); @@ -262,6 +271,7 @@ static int pause_device(sd_bus_message *msg, void *userdata, sd_bus_error *ret_e } if (major == DRM_MAJOR) { + assert(session->has_drm); session->base.active = false; wlr_signal_emit_safe(&session->base.session_signal, session); } @@ -307,6 +317,115 @@ error: return 0; } +static int properties_changed(sd_bus_message *msg, void *userdata, + sd_bus_error *ret_error) { + struct logind_session *session = userdata; + int ret = 0; + + // if we have a drm fd we don't depend on this + if (session->has_drm) { + return 0; + } + + // PropertiesChanged arg 1: interface + const char *interface; + ret = sd_bus_message_read_basic(msg, 's', &interface); // skip path + if (ret < 0) { + goto error; + } + + if (strcmp(interface, "org.freedesktop.login1.Session") != 0) { + // not interesting for us; ignore + wlr_log(WLR_DEBUG, "ignoring PropertiesChanged from %s", interface); + return 0; + } + + // PropertiesChanged arg 2: changed properties with values + ret = sd_bus_message_enter_container(msg, 'a', "{sv}"); + if (ret < 0) { + goto error; + } + + const char *s; + while ((ret = sd_bus_message_enter_container(msg, 'e', "sv")) > 0) { + ret = sd_bus_message_read_basic(msg, 's', &s); + if (ret < 0) { + goto error; + } + + if (strcmp(s, "Active") == 0) { + int ret; + ret = sd_bus_message_enter_container(msg, 'v', "b"); + if (ret < 0) { + goto error; + } + + bool active; + ret = sd_bus_message_read_basic(msg, 'b', &active); + if (ret < 0) { + goto error; + } + + if (session->base.active != active) { + session->base.active = active; + wlr_signal_emit_safe(&session->base.session_signal, session); + } + return 0; + } else { + sd_bus_message_skip(msg, "{sv}"); + } + + ret = sd_bus_message_exit_container(msg); + if (ret < 0) { + goto error; + } + } + + if (ret < 0) { + goto error; + } + + ret = sd_bus_message_exit_container(msg); + if (ret < 0) { + goto error; + } + + // PropertiesChanged arg 3: changed properties without values + sd_bus_message_enter_container(msg, 'a', "s"); + while ((ret = sd_bus_message_read_basic(msg, 's', &s)) > 0) { + if (strcmp(s, "Active") == 0) { + sd_bus_error error = SD_BUS_ERROR_NULL; + bool active; + ret = sd_bus_get_property_trivial(session->bus, + "org.freedesktop.login1", session->path, + "org.freedesktop.login1.Session", "Active", &error, + 'b', &active); + if (ret < 0) { + wlr_log(WLR_ERROR, "Failed to get 'Active' property: '%s' (%s)", + error.message, strerror(ret)); + return 0; + } + + if (session->base.active != active) { + session->base.active = active; + wlr_signal_emit_safe(&session->base.session_signal, session); + } + return 0; + } + } + + if (ret < 0) { + goto error; + } + + return 0; + +error: + wlr_log(WLR_ERROR, "Failed to parse D-Bus PropertiesChanged %s", + strerror(-ret)); + return 0; +} + static bool add_signal_matches(struct logind_session *session) { int ret; @@ -338,6 +457,14 @@ static bool add_signal_matches(struct logind_session *session) { return false; } + ret = sd_bus_match_signal(session->bus, NULL, "org.freedesktop.login1", + session->path, "org.freedesktop.DBus.Properties", "PropertiesChanged", + properties_changed, session); + if (ret < 0) { + wlr_log(WLR_ERROR, "Failed to add D-Bus match: %s", strerror(-ret)); + return false; + } + return true; } |