diff --git a/man/org.freedesktop.login1.xml b/man/org.freedesktop.login1.xml
index 108a47a38da..4cc9f278919 100644
--- a/man/org.freedesktop.login1.xml
+++ b/man/org.freedesktop.login1.xml
@@ -1075,6 +1075,7 @@ node /org/freedesktop/login1/session/1 {
TakeControl(in b force);
ReleaseControl();
SetType(in s type);
+ SetDisplay(in s display);
TakeDevice(in u major,
in u minor,
out h fd,
@@ -1172,6 +1173,8 @@ node /org/freedesktop/login1/session/1 {
+
+
@@ -1268,6 +1271,11 @@ node /org/freedesktop/login1/session/1 {
connection. This should help prevent a session from entering an inconsistent state, for example if the
controller crashes. The only argument type is the new session type.
+ SetDisplay() allows the display name of the graphical session to be changed. This is
+ useful if the display server is started as part of the session. It can only be called by session's current
+ controller. If TakeControl() has not been called, this method will fail. The only argument
+ display is the new display name.
+
TakeDevice() allows a session controller to get a file descriptor for a
specific device. Pass in the major and minor numbers of the character device and
systemd-logind will return a file descriptor for the device. Only a limited set of
diff --git a/src/login/logind-session-dbus.c b/src/login/logind-session-dbus.c
index 7d46759822b..539109c5e88 100644
--- a/src/login/logind-session-dbus.c
+++ b/src/login/logind-session-dbus.c
@@ -413,6 +413,30 @@ static int method_set_type(sd_bus_message *message, void *userdata, sd_bus_error
return sd_bus_reply_method_return(message, NULL);
}
+static int method_set_display(sd_bus_message *message, void *userdata, sd_bus_error *error) {
+ Session *s = ASSERT_PTR(userdata);
+ const char *display;
+ int r;
+
+ assert(message);
+
+ r = sd_bus_message_read(message, "s", &display);
+ if (r < 0)
+ return r;
+
+ if (!session_is_controller(s, sd_bus_message_get_sender(message)))
+ return sd_bus_error_set(error, BUS_ERROR_NOT_IN_CONTROL, "You must be in control of this session to set display");
+
+ if (!SESSION_TYPE_IS_GRAPHICAL(s->type))
+ return sd_bus_error_set(error, SD_BUS_ERROR_NOT_SUPPORTED, "Setting display is only supported for graphical sessions");
+
+ r = session_set_display(s, display);
+ if (r < 0)
+ return r;
+
+ return sd_bus_reply_method_return(message, NULL);
+}
+
static int method_take_device(sd_bus_message *message, void *userdata, sd_bus_error *error) {
Session *s = userdata;
uint32_t major, minor;
@@ -901,6 +925,11 @@ static const sd_bus_vtable session_vtable[] = {
SD_BUS_NO_RESULT,
method_set_type,
SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_ARGS("SetDisplay",
+ SD_BUS_ARGS("s", display),
+ SD_BUS_NO_RESULT,
+ method_set_display,
+ SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD_WITH_ARGS("TakeDevice",
SD_BUS_ARGS("u", major, "u", minor),
SD_BUS_RESULT("h", fd, "b", inactive),
diff --git a/src/login/logind-session.c b/src/login/logind-session.c
index 4995e5885aa..ac3904352e9 100644
--- a/src/login/logind-session.c
+++ b/src/login/logind-session.c
@@ -1044,6 +1044,26 @@ void session_set_type(Session *s, SessionType t) {
session_send_changed(s, "Type", NULL);
}
+int session_set_display(Session *s, const char *display) {
+ int r;
+
+ assert(s);
+ assert(display);
+
+ if (streq(s->display, display))
+ return 0;
+
+ r = free_and_strdup(&s->display, display);
+ if (r < 0)
+ return r;
+
+ session_save(s);
+
+ session_send_changed(s, "Display", NULL);
+
+ return 1;
+}
+
static int session_dispatch_fifo(sd_event_source *es, int fd, uint32_t revents, void *userdata) {
Session *s = userdata;
diff --git a/src/login/logind-session.h b/src/login/logind-session.h
index 5c35071dc52..6b6ac2d573f 100644
--- a/src/login/logind-session.h
+++ b/src/login/logind-session.h
@@ -137,6 +137,7 @@ int session_set_idle_hint(Session *s, bool b);
int session_get_locked_hint(Session *s);
void session_set_locked_hint(Session *s, bool b);
void session_set_type(Session *s, SessionType t);
+int session_set_display(Session *s, const char *display);
int session_create_fifo(Session *s);
int session_start(Session *s, sd_bus_message *properties, sd_bus_error *error);
int session_stop(Session *s, bool force);
diff --git a/src/login/org.freedesktop.login1.conf b/src/login/org.freedesktop.login1.conf
index 95d2ef0f063..6113b64aa7e 100644
--- a/src/login/org.freedesktop.login1.conf
+++ b/src/login/org.freedesktop.login1.conf
@@ -346,6 +346,10 @@
send_interface="org.freedesktop.login1.User"
send_member="Kill"/>
+
+