From 066d9fdb78691939960044b2c4047a8975347af2 Mon Sep 17 00:00:00 2001 From: David Herrmann Date: Wed, 6 Mar 2013 18:21:25 +0100 Subject: uvtd: seat: implement session IDs Session IDs provide a unique ID for each registered session. They are used to sort the sessions so next/prev return the correct neighbour-sessions. Furthermore, they can be used by outside users to refer to a session directly without knowing the session implementation. Sessions with ID=0 are always linked at the end and considered to be "unnamed". The algorithm to switch to a session with a given ID is: Try to find the first session with the exact same ID. If there is none, return the session with the next higher ID. If there is none, return the ID'th session in the list. If there is none, return the last session. This provides a fairly predictable way of switching between session. It is modeled after the classic VT F1-F12 keys that switch between sessions. If a session is not given, these keys will switch to the next higher session instead. All "unnamed" sessions are put at the end. So if you have only F1-F4, then F5-F12 will map to unnamed sessions. Please note that new sessions are always linked at the end of their group. So new unnamed sessions are at the far end, new named sessions are linked in the sorted list but behind all sessions with the same ID. Hence, the caller should avoid multiple sessions with the same ID, otherwise, some sessions might not be reachable even though they're named (unless you use next/prev of course). Signed-off-by: David Herrmann --- src/uvtd_seat.c | 54 +++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 45 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/uvtd_seat.c b/src/uvtd_seat.c index 2ef3180..0a1d71c 100644 --- a/src/uvtd_seat.c +++ b/src/uvtd_seat.c @@ -64,6 +64,7 @@ struct uvtd_session { struct shl_dlist list; unsigned long ref; struct uvtd_seat *seat; + unsigned int id; bool enabled; bool deactivating; @@ -426,12 +427,36 @@ void uvtd_seat_wake_up(struct uvtd_seat *seat) seat_run(seat); } +void uvtd_seat_schedule(struct uvtd_seat *seat, unsigned int id) +{ + struct shl_dlist *iter; + struct uvtd_session *session; + unsigned int i; + + if (!seat || !id) + return; + + session = NULL; + i = id; + shl_dlist_for_each(iter, &seat->sessions) { + session = shl_dlist_entry(iter, struct uvtd_session, list); + if (!--i) + break; + if (session->id >= id) + break; + } + + if (session) + seat_schedule(seat, session); +} + int uvtd_seat_register_session(struct uvtd_seat *seat, struct uvtd_session **out, unsigned int id, uvtd_session_cb_t cb, void *data) { - struct uvtd_session *sess; + struct uvtd_session *sess, *s; + struct shl_dlist *iter; if (!seat || !out) return -EINVAL; @@ -440,23 +465,34 @@ int uvtd_seat_register_session(struct uvtd_seat *seat, if (!sess) return -ENOMEM; - log_debug("register session %p", sess); + log_debug("register session %p with id %u on seat %p", + sess, id, seat); memset(sess, 0, sizeof(*sess)); sess->ref = 1; sess->seat = seat; sess->cb = cb; sess->data = data; - - /* TODO: add support for \ids */ - /* register new sessions next to the current one */ - if (seat->current_sess) - shl_dlist_link(&seat->current_sess->list, &sess->list); - else - shl_dlist_link_tail(&seat->sessions, &sess->list); + sess->id = id; ++seat->session_count; *out = sess; + + if (sess->id) { + shl_dlist_for_each(iter, &seat->sessions) { + s = shl_dlist_entry(iter, struct uvtd_session, list); + if (!s->id || s->id > sess->id) { + shl_dlist_link_tail(iter, &sess->list); + return 0; + } + + if (s->id == sess->id) + log_warning("session %p shadowed by %p", + sess, s); + } + } + + shl_dlist_link_tail(&seat->sessions, &sess->list); return 0; } -- cgit v1.2.3