+void seat_evict_position(Seat *s, Session *session) {
+ Session *iter;
+ unsigned int pos = session->pos;
+
+ session->pos = 0;
+
+ if (!pos)
+ return;
+
+ if (pos < s->position_count && s->positions[pos] == session) {
+ s->positions[pos] = NULL;
+
+ /* There might be another session claiming the same
+ * position (eg., during gdm->session transition), so lets look
+ * for it and set it on the free slot. */
+ LIST_FOREACH(sessions_by_seat, iter, s->sessions) {
+ if (iter->pos == pos) {
+ s->positions[pos] = iter;
+ break;
+ }
+ }
+ }
+}
+
+void seat_claim_position(Seat *s, Session *session, unsigned int pos) {
+ /* with VTs, the position is always the same as the VTnr */
+ if (seat_has_vts(s))
+ pos = session->vtnr;
+
+ if (!GREEDY_REALLOC0(s->positions, s->position_count, pos + 1))
+ return;
+
+ seat_evict_position(s, session);
+
+ session->pos = pos;
+ if (pos > 0 && !s->positions[pos])
+ s->positions[pos] = session;
+}
+
+static void seat_assign_position(Seat *s, Session *session) {
+ unsigned int pos;
+
+ if (session->pos > 0)
+ return;
+
+ for (pos = 1; pos < s->position_count; ++pos)
+ if (!s->positions[pos])
+ break;
+
+ seat_claim_position(s, session, pos);
+}
+