chiark / gitweb /
logind: put correct user object paths in introspection data
[elogind.git] / src / login / logind-session.c
index fcc1901ed626c9f2c21d6762fb42273bbac59ace..27aa33514232d67131d8b49040f05a8e508f5e7b 100644 (file)
 #include "dbus-common.h"
 #include "logind-session.h"
 
+static unsigned devt_hash_func(const void *p) {
+        uint64_t u = *(const dev_t*)p;
+
+        return uint64_hash_func(&u);
+}
+
+static int devt_compare_func(const void *_a, const void *_b) {
+        dev_t a, b;
+
+        a = *(const dev_t*) _a;
+        b = *(const dev_t*) _b;
+
+        return a < b ? -1 : (a > b ? 1 : 0);
+}
+
 Session* session_new(Manager *m, const char *id) {
         Session *s;
 
@@ -53,7 +68,7 @@ Session* session_new(Manager *m, const char *id) {
                 return NULL;
         }
 
-        s->devices = hashmap_new(trivial_hash_func, trivial_compare_func);
+        s->devices = hashmap_new(devt_hash_func, devt_compare_func);
         if (!s->devices) {
                 free(s->state_file);
                 free(s);
@@ -100,6 +115,8 @@ void session_free(Session *s) {
         if (s->seat) {
                 if (s->seat->active == s)
                         s->seat->active = NULL;
+                if (s->seat->pending_switch == s)
+                        s->seat->pending_switch = NULL;
 
                 LIST_REMOVE(Session, sessions_by_seat, s->seat->sessions, s);
         }
@@ -242,7 +259,6 @@ int session_load(Session *s) {
                 *seat = NULL,
                 *vtnr = NULL,
                 *leader = NULL,
-                *audit_id = NULL,
                 *type = NULL,
                 *class = NULL,
                 *uid = NULL,
@@ -375,21 +391,40 @@ int session_load(Session *s) {
 }
 
 int session_activate(Session *s) {
+        unsigned int num_pending;
+
         assert(s);
         assert(s->user);
 
-        if (s->vtnr <= 0)
-                return -ENOTSUP;
-
         if (!s->seat)
                 return -ENOTSUP;
 
         if (s->seat->active == s)
                 return 0;
 
-        assert(seat_has_vts(s->seat));
+        /* on seats with VTs, we let VTs manage session-switching */
+        if (seat_has_vts(s->seat)) {
+                if (s->vtnr <= 0)
+                        return -ENOTSUP;
+
+                return chvt(s->vtnr);
+        }
+
+        /* On seats without VTs, we implement session-switching in logind. We
+         * try to pause all session-devices and wait until the session
+         * controller acknowledged them. Once all devices are asleep, we simply
+         * switch the active session and be done.
+         * We save the session we want to switch to in seat->pending_switch and
+         * seat_complete_switch() will perform the final switch. */
+
+        s->seat->pending_switch = s;
 
-        return chvt(s->vtnr);
+        /* if no devices are running, immediately perform the session switch */
+        num_pending = session_device_try_pause_all(s);
+        if (!num_pending)
+                seat_complete_switch(s->seat);
+
+        return 0;
 }
 
 static int session_link_x11_socket(Session *s) {