chiark / gitweb /
logind: fix Display property of user objects
authorLennart Poettering <lennart@poettering.net>
Mon, 19 May 2014 00:03:20 +0000 (09:03 +0900)
committerLennart Poettering <lennart@poettering.net>
Mon, 19 May 2014 00:03:20 +0000 (09:03 +0900)
When we dropped support for creating a per-user to the "main" X11
display we stopped returning useful data in the "Display" user property.
With this change this is fixed and we again expose an appropriate
(graphical session) in the property that is useful as the "main" one, if
one is needed.

src/login/logind-session.c
src/login/logind-session.h
src/login/logind-user-dbus.c
src/login/logind-user.c
src/login/logind-user.h

index 4fb229e354b91d49dc790245562f3c926f04a793..9a541013017f7cf75faa46edee7519932b89c219 100644 (file)
@@ -545,6 +545,8 @@ int session_start(Session *s) {
 
         s->started = true;
 
+        user_elect_display(s->user);
+
         /* Save data */
         session_save(s);
         user_save(s->user);
@@ -553,7 +555,7 @@ int session_start(Session *s) {
 
         /* Send signals */
         session_send_signal(s, true);
-        user_send_changed(s->user, "Sessions", NULL);
+        user_send_changed(s->user, "Sessions", "Display", NULL);
         if (s->seat) {
                 if (s->seat->active == s)
                         seat_send_changed(s->seat, "Sessions", "ActiveSession", NULL);
@@ -612,6 +614,8 @@ int session_stop(Session *s, bool force) {
 
         s->stopping = true;
 
+        user_elect_display(s->user);
+
         session_save(s);
         user_save(s->user);
 
@@ -660,7 +664,7 @@ int session_finalize(Session *s) {
         }
 
         user_save(s->user);
-        user_send_changed(s->user, "Sessions", NULL);
+        user_send_changed(s->user, "Sessions", "Display", NULL);
 
         return r;
 }
index f78f30956d2ba9b1d05bc3834f696b2ab512664c..81957dfa78d6f6c74ba025daaacbc4e04f3089a3 100644 (file)
@@ -60,6 +60,8 @@ typedef enum SessionType {
         _SESSION_TYPE_INVALID = -1
 } SessionType;
 
+#define SESSION_TYPE_IS_GRAPHICAL(type) IN_SET(type, SESSION_X11, SESSION_WAYLAND, SESSION_MIR)
+
 enum KillWho {
         KILL_LEADER,
         KILL_ALL,
index 6266ccb0f08d0f51379adeabdf797f957e3ffe48..51793f6dad6b2160ee5d6a326a34350c57be9f9d 100644 (file)
@@ -220,7 +220,7 @@ const sd_bus_vtable user_vtable[] = {
         SD_BUS_PROPERTY("RuntimePath", "s", NULL, offsetof(User, runtime_path), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("Service", "s", NULL, offsetof(User, service), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("Slice", "s", NULL, offsetof(User, slice), SD_BUS_VTABLE_PROPERTY_CONST),
-        SD_BUS_PROPERTY("Display", "(so)", property_get_display, 0, SD_BUS_VTABLE_PROPERTY_CONST),
+        SD_BUS_PROPERTY("Display", "(so)", property_get_display, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
         SD_BUS_PROPERTY("State", "s", property_get_state, 0, 0),
         SD_BUS_PROPERTY("Sessions", "a(so)", property_get_sessions, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
         SD_BUS_PROPERTY("IdleHint", "b", property_get_idle_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
index 5fffa651a32508c7728962ebd9b082455fe179c1..fdbccb364c1814f45d07249253c9107b8bbee8c7 100644 (file)
@@ -713,6 +713,43 @@ int user_kill(User *u, int signo) {
         return manager_kill_unit(u->manager, u->slice, KILL_ALL, signo, NULL);
 }
 
+void user_elect_display(User *u) {
+        Session *graphical = NULL, *text = NULL, *s;
+
+        assert(u);
+
+        /* This elects a primary session for each user, which we call
+         * the "display". We try to keep the assignment stable, but we
+         * "upgrade" to better choices. */
+
+        LIST_FOREACH(sessions_by_user, s, u->sessions) {
+
+                if (s->class != SESSION_USER)
+                        continue;
+
+                if (s->stopping)
+                        continue;
+
+                if (SESSION_TYPE_IS_GRAPHICAL(s->type))
+                        graphical = s;
+                else
+                        text = s;
+        }
+
+        if (graphical &&
+            (!u->display ||
+             u->display->class != SESSION_USER ||
+             u->display->stopping ||
+             !SESSION_TYPE_IS_GRAPHICAL(u->display->type)))
+                u->display = graphical;
+
+        if (text &&
+            (!u->display ||
+             u->display->class != SESSION_USER ||
+             u->display->stopping))
+                u->display = text;
+}
+
 static const char* const user_state_table[_USER_STATE_MAX] = {
         [USER_OFFLINE] = "offline",
         [USER_OPENING] = "opening",
index f237d2a6b97f7e3c5d768278286ce2b88ef23e55..4e0568fea92b7e98ee99868c2870a968afbbc3fe 100644 (file)
@@ -80,6 +80,7 @@ int user_save(User *u);
 int user_load(User *u);
 int user_kill(User *u, int signo);
 int user_check_linger_file(User *u);
+void user_elect_display(User *u);
 
 extern const sd_bus_vtable user_vtable[];
 int user_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error);