seat: allow session-switching with keyboard
authorDavid Herrmann <dh.herrmann@googlemail.com>
Mon, 15 Oct 2012 16:02:12 +0000 (18:02 +0200)
committerDavid Herrmann <dh.herrmann@googlemail.com>
Mon, 15 Oct 2012 16:02:12 +0000 (18:02 +0200)
This adds two new grabs to switch sessions within kmscon. They are set to
ctrl+alt+Left/Right by default.

To improve debugging, we also add some log-messages to session management.

Signed-off-by: David Herrmann <dh.herrmann@googlemail.com>
src/kmscon_conf.c
src/kmscon_conf.h
src/kmscon_seat.c

index 5bd7e24..4eca1a4 100644 (file)
@@ -103,14 +103,18 @@ static void print_help()
                "\t    --xkb-repeat-rate <msecs>  [50]\n"
                "\t                                 Delay between two key-repeats in ms\n"
                "\n"
-               "\t    --grab-scroll-up <grab>   [<Shift>Up]\n"
-               "\t                                Shortcut to scroll up\n"
-               "\t    --grab-scroll-down <grab> [<Shift>Down]\n"
-               "\t                                Shortcut to scroll down\n"
-               "\t    --grab-page-up <grab>     [<Shift>Prior]\n"
-               "\t                                Shortcut to scroll page up\n"
-               "\t    --grab-page-down <grab>   [<Shift>Next]\n"
-               "\t                                Shortcut to scroll page down\n"
+               "\t    --grab-scroll-up <grab>    [<Shift>Up]\n"
+               "\t                                 Shortcut to scroll up\n"
+               "\t    --grab-scroll-down <grab>  [<Shift>Down]\n"
+               "\t                                 Shortcut to scroll down\n"
+               "\t    --grab-page-up <grab>      [<Shift>Prior]\n"
+               "\t                                 Shortcut to scroll page up\n"
+               "\t    --grab-page-down <grab>    [<Shift>Next]\n"
+               "\t                                 Shortcut to scroll page down\n"
+               "\t    --grab-session-next <grab> [<Ctrl><Alt>Right]\n"
+               "\t                                 Switch to next session\n"
+               "\t    --grab-session-prev <grab> [<Ctrl><Alt>Left]\n"
+               "\t                                 Switch to previous session\n"
                "\n"
                "Font Options:\n"
                "\t    --font-engine <engine>  [pango]\n"
@@ -245,6 +249,12 @@ static struct conf_grab def_grab_page_up =
 static struct conf_grab def_grab_page_down =
                CONF_SINGLE_GRAB(SHL_SHIFT_MASK, XKB_KEY_Next);
 
+static struct conf_grab def_grab_session_next =
+               CONF_SINGLE_GRAB(SHL_CONTROL_MASK | SHL_ALT_MASK, XKB_KEY_Right);
+
+static struct conf_grab def_grab_session_prev =
+               CONF_SINGLE_GRAB(SHL_CONTROL_MASK | SHL_ALT_MASK, XKB_KEY_Left);
+
 struct conf_option options[] = {
        CONF_OPTION_BOOL('h', "help", aftercheck_help, &kmscon_conf.help, false),
        CONF_OPTION_BOOL('v', "verbose", NULL, &kmscon_conf.verbose, false),
@@ -265,6 +275,8 @@ struct conf_option options[] = {
        CONF_OPTION_GRAB(0, "grab-scroll-down", NULL, &kmscon_conf.grab_scroll_down, &def_grab_scroll_down),
        CONF_OPTION_GRAB(0, "grab-page-up", NULL, &kmscon_conf.grab_page_up, &def_grab_page_up),
        CONF_OPTION_GRAB(0, "grab-page-down", NULL, &kmscon_conf.grab_page_down, &def_grab_page_down),
+       CONF_OPTION_GRAB(0, "grab-session-next", NULL, &kmscon_conf.grab_session_next, &def_grab_session_next),
+       CONF_OPTION_GRAB(0, "grab-session-prev", NULL, &kmscon_conf.grab_session_prev, &def_grab_session_prev),
        CONF_OPTION_STRING(0, "xkb-layout", NULL, &kmscon_conf.xkb_layout, "us"),
        CONF_OPTION_STRING(0, "xkb-variant", NULL, &kmscon_conf.xkb_variant, ""),
        CONF_OPTION_STRING(0, "xkb-options", NULL, &kmscon_conf.xkb_options, ""),
index 46afa9c..43bccaa 100644 (file)
@@ -72,6 +72,7 @@ struct kmscon_conf_t {
        char **argv;
        /* terminal scroll-back buffer size */
        unsigned int sb_size;
+
        /* scroll-up grab */
        struct conf_grab *grab_scroll_up;
        /* scroll-down grab */
@@ -80,6 +81,10 @@ struct kmscon_conf_t {
        struct conf_grab *grab_page_up;
        /* page-down grab */
        struct conf_grab *grab_page_down;
+       /* session-next grab */
+       struct conf_grab *grab_session_next;
+       /* session-prev grab */
+       struct conf_grab *grab_session_prev;
 
        /* seats */
        char **seats;
index 2b66230..ffc6235 100644 (file)
@@ -32,6 +32,7 @@
 #include <errno.h>
 #include <stdlib.h>
 #include <string.h>
+#include "conf.h"
 #include "eloop.h"
 #include "kmscon_conf.h"
 #include "kmscon_seat.h"
@@ -88,11 +89,13 @@ static void session_call(struct kmscon_session *sess, unsigned int event,
 
 static void session_call_activate(struct kmscon_session *sess)
 {
+       log_debug("activate session %p", sess);
        session_call(sess, KMSCON_SESSION_ACTIVATE, NULL);
 }
 
 static void session_call_deactivate(struct kmscon_session *sess)
 {
+       log_debug("deactivate session %p", sess);
        session_call(sess, KMSCON_SESSION_DEACTIVATE, NULL);
 }
 
@@ -108,12 +111,14 @@ static void session_call_display_gone(struct kmscon_session *sess,
        session_call(sess, KMSCON_SESSION_DISPLAY_GONE, disp);
 }
 
-static void session_activate(struct kmscon_session *sess)
+static int session_activate(struct kmscon_session *sess)
 {
        struct kmscon_seat *seat = sess->seat;
 
-       if (seat->cur_sess == sess || !sess->enabled)
-               return;
+       if (seat->cur_sess == sess)
+               return 0;
+       if (!sess->enabled)
+               return -EINVAL;
 
        if (seat->cur_sess) {
                if (seat->awake)
@@ -124,12 +129,15 @@ static void session_activate(struct kmscon_session *sess)
        seat->cur_sess = sess;
        if (seat->awake)
                session_call_activate(sess);
+
+       return 0;
 }
 
 static void session_deactivate(struct kmscon_session *sess)
 {
        struct kmscon_seat *seat = sess->seat;
        struct shl_dlist *iter;
+       struct kmscon_session *s;
 
        if (seat->cur_sess != sess)
                return;
@@ -138,18 +146,50 @@ static void session_deactivate(struct kmscon_session *sess)
                session_call_deactivate(sess);
 
        seat->cur_sess = NULL;
-       shl_dlist_for_each(iter, &seat->sessions) {
-               sess = shl_dlist_entry(iter, struct kmscon_session, list);
-               if (!sess->enabled)
+       shl_dlist_for_each_but_one(iter, &sess->list, &seat->sessions) {
+               s = shl_dlist_entry(iter, struct kmscon_session, list);
+               if (!s->enabled)
                        continue;
 
-               seat->cur_sess = sess;
+               seat->cur_sess = s;
                if (seat->awake)
                        session_call_activate(seat->cur_sess);
                break;
        }
 }
 
+static void seat_activate_next(struct kmscon_seat *seat)
+{
+       struct shl_dlist *iter;
+       struct kmscon_session *sess;
+
+       if (!seat->cur_sess)
+               return;
+
+       shl_dlist_for_each_but_one(iter, &seat->cur_sess->list,
+                                  &seat->sessions) {
+               sess = shl_dlist_entry(iter, struct kmscon_session, list);
+               if (!session_activate(sess))
+                       break;
+       }
+}
+
+static void seat_activate_prev(struct kmscon_seat *seat)
+{
+       struct shl_dlist *iter;
+       struct kmscon_session *sess;
+
+       if (!seat->cur_sess)
+               return;
+
+       shl_dlist_for_each_reverse_but_one(iter, &seat->cur_sess->list,
+                                          &seat->sessions) {
+               sess = shl_dlist_entry(iter, struct kmscon_session, list);
+               if (!session_activate(sess))
+                       break;
+       }
+}
+
 static void activate_display(struct kmscon_display *d)
 {
        int ret;
@@ -257,6 +297,29 @@ static int seat_vt_event(struct uterm_vt *vt, unsigned int event, void *data)
        return 0;
 }
 
+static void seat_input_event(struct uterm_input *input,
+                            struct uterm_input_event *ev,
+                            void *data)
+{
+       struct kmscon_seat *seat = data;
+
+       if (ev->handled)
+               return;
+
+       if (conf_grab_matches(kmscon_conf.grab_session_next,
+                             ev->mods, ev->num_syms, ev->keysyms)) {
+               ev->handled = true;
+               seat_activate_next(seat);
+               return;
+       }
+       if (conf_grab_matches(kmscon_conf.grab_session_prev,
+                             ev->mods, ev->num_syms, ev->keysyms)) {
+               ev->handled = true;
+               seat_activate_prev(seat);
+               return;
+       }
+}
+
 int kmscon_seat_new(struct kmscon_seat **out,
                    struct ev_eloop *eloop,
                    struct uterm_vt_master *vtm,
@@ -298,24 +361,38 @@ int kmscon_seat_new(struct kmscon_seat **out,
        if (ret)
                goto err_name;
 
-       ret = uterm_vt_allocate(seat->vtm, &seat->vt, seat->name,
-                               seat->input, kmscon_conf.vt, seat_vt_event,
-                               seat);
+       ret = uterm_input_register_cb(seat->input, seat_input_event, seat);
        if (ret)
                goto err_input;
 
-       ret = kmscon_terminal_register(&s, seat);
+       ret = uterm_vt_allocate(seat->vtm, &seat->vt, seat->name,
+                               seat->input, kmscon_conf.vt, seat_vt_event,
+                               seat);
        if (ret)
-               goto err_vt;
-       kmscon_session_enable(s);
+               goto err_input_cb;
 
        ev_eloop_ref(seat->eloop);
        uterm_vt_master_ref(seat->vtm);
        *out = seat;
+
+       /* register built-in sessions */
+
+       ret = kmscon_terminal_register(&s, seat);
+       if (ret == -EOPNOTSUPP)
+               log_notice("terminal support not compiled in");
+       else if (ret)
+               goto err_sessions;
+       else
+               kmscon_session_enable(s);
+
        return 0;
 
-err_vt:
-       uterm_vt_deallocate(seat->vt);
+err_sessions:
+       kmscon_seat_free(seat);
+       return ret;
+
+err_input_cb:
+       uterm_input_unregister_cb(seat->input, seat_input_event, seat);
 err_input:
        uterm_input_unref(seat->input);
 err_name:
@@ -348,6 +425,7 @@ void kmscon_seat_free(struct kmscon_seat *seat)
        }
 
        uterm_vt_deallocate(seat->vt);
+       uterm_input_unregister_cb(seat->input, seat_input_event, seat);
        uterm_input_unref(seat->input);
        free(seat->name);
        uterm_vt_master_unref(seat->vtm);
@@ -437,13 +515,16 @@ int kmscon_seat_register_session(struct kmscon_seat *seat,
                          seat->name);
                return -ENOMEM;
        }
+
+       log_debug("register session %p", sess);
+
        memset(sess, 0, sizeof(*sess));
        sess->ref = 1;
        sess->seat = seat;
        sess->cb = cb;
        sess->data = data;
 
-       shl_dlist_link(&seat->sessions, &sess->list);
+       shl_dlist_link_tail(&seat->sessions, &sess->list);
        *out = sess;
 
        return 0;
@@ -471,8 +552,10 @@ void kmscon_session_unregister(struct kmscon_session *sess)
        if (!sess || !sess->seat)
                return;
 
-       shl_dlist_unlink(&sess->list);
+       log_debug("unregister session %p", sess);
+
        session_deactivate(sess);
+       shl_dlist_unlink(&sess->list);
        sess->seat = NULL;
        session_call(sess, KMSCON_SESSION_UNREGISTER, NULL);
 }
@@ -508,6 +591,8 @@ void kmscon_session_enable(struct kmscon_session *sess)
        if (!sess)
                return;
 
+       log_debug("enable session %p", sess);
+
        sess->enabled = true;
        if (sess->seat && !sess->seat->cur_sess)
                session_activate(sess);
@@ -518,6 +603,8 @@ void kmscon_session_disable(struct kmscon_session *sess)
        if (!sess)
                return;
 
+       log_debug("disable session %p", sess);
+
        if (sess->seat)
                session_deactivate(sess);
        sess->enabled = false;