diff --git a/terminal.c b/terminal.c index acd4f2bd..f0cf76d9 100644 --- a/terminal.c +++ b/terminal.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -44,15 +45,20 @@ 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 @@ -117,25 +123,6 @@ idle_redraw(void *data) return FALSE; } -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) { @@ -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, diff --git a/window.c b/window.c index 4f4b7046..4f94c504 100644 --- 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); } } @@ -342,6 +347,14 @@ window_set_acknowledge_handler(struct window *window, window->user_data = data; } +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) { diff --git a/window.h b/window.h index cf357878..1a28d29b 100644 --- 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