Add keyboard input to terminal.
authorKristian Høgsberg <krh@redhat.com>
Mon, 8 Dec 2008 05:01:36 +0000 (00:01 -0500)
committerKristian Høgsberg <krh@redhat.com>
Mon, 8 Dec 2008 05:01:36 +0000 (00:01 -0500)
terminal.c
window.c
window.h

index acd4f2b..f0cf76d 100644 (file)
@@ -31,6 +31,7 @@
 #include <pty.h>
 #include <cairo.h>
 #include <glib.h>
+#include <linux/input.h>
 
 #include <GL/gl.h>
 #include <eagle.h>
 static const char gem_device[] = "/dev/dri/card0";
 static const char socket_name[] = "\0wayland";
 
+#define MOD_SHIFT      0x01
+#define MOD_ALT                0x02
+#define MOD_CTRL       0x04
+
 struct terminal {
        struct window *window;
        struct wl_display *display;
        int resize_scheduled;
        char *data;
        int width, height, tail, row, column;
-       int fd;
+       int fd, master;
        struct buffer *buffer;
        GIOChannel *channel;
+       uint32_t modifiers;
 };
 
 static void
@@ -118,25 +124,6 @@ idle_redraw(void *data)
 }
 
 static void
-resize_handler(struct window *window, int32_t width, int32_t height, void *data)
-{
-       struct terminal *terminal = data;
-
-       if (!terminal->resize_scheduled) {
-               g_idle_add(idle_redraw, terminal);
-               terminal->resize_scheduled = 1;
-       }
-}
-
-static void
-acknowledge_handler(struct window *window, uint32_t key, void *data)
-{
-       struct terminal *terminal = data;
-
-       terminal->resize_scheduled = 0;
-}
-
-static void
 terminal_data(struct terminal *terminal, const char *data, size_t length)
 {
        int i;
@@ -166,6 +153,134 @@ terminal_data(struct terminal *terminal, const char *data, size_t length)
        }
 }
 
+static void
+resize_handler(struct window *window, int32_t width, int32_t height, void *data)
+{
+       struct terminal *terminal = data;
+
+       if (!terminal->resize_scheduled) {
+               g_idle_add(idle_redraw, terminal);
+               terminal->resize_scheduled = 1;
+       }
+}
+
+static void
+acknowledge_handler(struct window *window, uint32_t key, void *data)
+{
+       struct terminal *terminal = data;
+
+       terminal->resize_scheduled = 0;
+}
+
+struct key {
+       int code[2];
+} evdev_keymap[] = {
+       { { 0, 0 } },           /* 0 */
+       { { 0x1b, 0x1b } },
+       { { '1', '!' } },
+       { { '2', '@' } },
+       { { '3', '#' } },
+       { { '4', '$' } },
+       { { '5', '%' } },
+       { { '6', '^' } },
+       { { '7', '&' } },
+       { { '8', '*' } },
+       { { '9', '(' } },
+       { { '0', ')' } },
+       { { '-', '_' } },
+       { { '=', '+' } },
+       { { '\b', '\b' } },
+       { { '\t', '\t' } },
+
+       { { 'q', 'Q' } },               /* 16 */
+       { { 'w', 'W' } },
+       { { 'e', 'E' } },
+       { { 'r', 'R' } },
+       { { 't', 'T' } },
+       { { 'y', 'Y' } },
+       { { 'u', 'U' } },
+       { { 'i', 'I' } },
+       { { 'o', 'O' } },
+       { { 'p', 'P' } },
+       { { '[', '{' } },
+       { { ']', '}' } },
+       { { '\n', '\n' } },
+       { { 0, 0 } },
+       { { 'a', 'A' } },
+       { { 's', 'S' } },
+
+       { { 'd', 'D' } },               /* 32 */
+       { { 'f', 'F' } },
+       { { 'g', 'G' } },
+       { { 'h', 'H' } },
+       { { 'j', 'J' } },
+       { { 'k', 'K' } },
+       { { 'l', 'L' } },
+       { { ';', ':' } },
+       { { '\'', '"' } },
+       { { '`', '~' } },
+       { { 0, 0 } },
+       { { '\\', '|' } },
+       { { 'z', 'Z' } },
+       { { 'x', 'X' } },
+       { { 'c', 'C' } },
+       { { 'v', 'V' } },
+
+       { { 'b', 'B' } },               /* 48 */
+       { { 'n', 'N' } },
+       { { 'm', 'M' } },
+       { { ',', '<' } },
+       { { '.', '>' } },
+       { { '/', '?' } },
+       { { 0, 0 } },
+       { { '*', '*' } },
+       { { 0, 0 } },
+       { { ' ', ' ' } },
+       { { 0, 0 } }
+
+       /* 59 */
+};
+
+#define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0])
+
+static void
+key_handler(struct window *window, uint32_t key, uint32_t state, void *data)
+{
+       struct terminal *terminal = data;
+       uint32_t mod = 0;
+       char c;
+
+       switch (key) {
+       case KEY_LEFTSHIFT:
+       case KEY_RIGHTSHIFT:
+               mod = MOD_SHIFT;
+               break;
+       case KEY_LEFTCTRL:
+       case KEY_RIGHTCTRL:
+               mod = MOD_CTRL;
+               break;
+       case KEY_LEFTALT:
+       case KEY_RIGHTALT:
+               mod = MOD_ALT;
+               break;
+       default:
+               if (key < ARRAY_LENGTH(evdev_keymap)) {
+                       if (terminal->modifiers & MOD_SHIFT)
+                               c = evdev_keymap[key].code[1];
+                       else
+                               c = evdev_keymap[key].code[0];
+                       if (state && c)
+                               write(terminal->master, &c, 1);
+               }
+               break;
+       }
+
+       if (state)
+               terminal->modifiers |= mod;
+       else
+               terminal->modifiers &= ~mod;
+}
+
 static struct terminal *
 terminal_create(struct wl_display *display, int fd)
 {
@@ -190,6 +305,7 @@ terminal_create(struct wl_display *display, int fd)
 
        window_set_resize_handler(terminal->window, resize_handler, terminal);
        window_set_acknowledge_handler(terminal->window, acknowledge_handler, terminal);
+       window_set_key_handler(terminal->window, key_handler, terminal);
 
        return terminal;
 }
@@ -206,7 +322,6 @@ io_handler(GIOChannel   *source,
 
        g_io_channel_read_chars(source, buffer, sizeof buffer,
                                &bytes_read, &error);
-       printf("got data: %.*s\n", bytes_read, buffer);
 
        terminal_data(terminal, buffer, bytes_read);
 
@@ -234,6 +349,7 @@ terminal_run(struct terminal *terminal, const char *path)
        }
 
        close(slave);
+       terminal->master = master;
        terminal->channel = g_io_channel_unix_new(master);
        fcntl(master, F_SETFL, O_NONBLOCK);
        g_io_add_watch(terminal->channel, G_IO_IN,
index 4f4b704..4f94c50 100644 (file)
--- a/window.c
+++ b/window.c
@@ -55,6 +55,7 @@ struct window {
        window_resize_handler_t resize_handler;
        window_frame_handler_t frame_handler;
        window_acknowledge_handler_t acknowledge_handler;
+       window_key_handler_t key_handler;
        void *user_data;
 };
 
@@ -293,6 +294,10 @@ event_handler(struct wl_display *display,
                } else if (button == 0 && state == 0) {
                        window->state = WINDOW_STABLE;
                }
+       } else if (opcode == 2) {
+               if (window->key_handler)
+                       (*window->key_handler)(window, p[0], p[1],
+                                              window->user_data);
        }
 }
 
@@ -343,6 +348,14 @@ window_set_acknowledge_handler(struct window *window,
 }
 
 void
+window_set_key_handler(struct window *window,
+                      window_key_handler_t handler, void *data)
+{
+       window->key_handler = handler;
+       window->user_data = data;
+}
+
+void
 window_set_minimum_size(struct window *window, uint32_t width, int32_t height)
 {
        window->minimum_width = width;
index cf35787..1a28d29 100644 (file)
--- a/window.h
+++ b/window.h
@@ -35,6 +35,8 @@ struct rectangle {
 typedef void (*window_resize_handler_t)(struct window *window, int32_t width, int32_t height, void *data);
 typedef void (*window_frame_handler_t)(struct window *window, uint32_t frame, uint32_t timestamp, void *data);
 typedef void (*window_acknowledge_handler_t)(struct window *window, uint32_t key, void *data);
+typedef void (*window_key_handler_t)(struct window *window, uint32_t key, uint32_t state, void *data);
+
 
 struct window *
 window_create(struct wl_display *display, int fd,
@@ -63,5 +65,8 @@ window_set_frame_handler(struct window *window,
 void
 window_set_acknowledge_handler(struct window *window,
                               window_acknowledge_handler_t handler, void *data);
+void
+window_set_key_handler(struct window *window,
+                      window_key_handler_t handler, void *data);
 
 #endif