From 892f1c39751ec7bda7f1e44988182764772b3c7c Mon Sep 17 00:00:00 2001 From: Jan Arne Petersen Date: Sun, 9 Sep 2012 23:08:42 +0200 Subject: [PATCH] keyboard: Use a qwerty virtual keyboard layout Add support for a proper qwerty virtual keyboard layout with lowercase and uppercase state, space and enter button. Signed-off-by: Jan Arne Petersen --- clients/keyboard.c | 206 +++++++++++++++++++++++++++++++++++++-------- 1 file changed, 171 insertions(+), 35 deletions(-) diff --git a/clients/keyboard.c b/clients/keyboard.c index 6ad966ba..6e73b333 100644 --- a/clients/keyboard.c +++ b/clients/keyboard.c @@ -39,14 +39,124 @@ struct virtual_keyboard { struct display *display; }; +enum key_type { + keytype_default, + keytype_backspace, + keytype_enter, + keytype_space, + keytype_switch, + keytype_symbols, + keytype_tab +}; + +struct key { + enum key_type key_type; + + char *label; + char *alt; + + unsigned int width; +}; + +static const struct key keys[] = { + { keytype_default, "q", "Q", 1}, + { keytype_default, "w", "W", 1}, + { keytype_default, "e", "E", 1}, + { keytype_default, "r", "R", 1}, + { keytype_default, "t", "T", 1}, + { keytype_default, "y", "Y", 1}, + { keytype_default, "u", "U", 1}, + { keytype_default, "i", "I", 1}, + { keytype_default, "o", "O", 1}, + { keytype_default, "p", "P", 1}, + { keytype_backspace, "<--", "<--", 2}, + + { keytype_tab, "->|", "->|", 1}, + { keytype_default, "a", "A", 1}, + { keytype_default, "s", "S", 1}, + { keytype_default, "d", "D", 1}, + { keytype_default, "f", "F", 1}, + { keytype_default, "g", "G", 1}, + { keytype_default, "h", "H", 1}, + { keytype_default, "j", "J", 1}, + { keytype_default, "k", "K", 1}, + { keytype_default, "l", "L", 1}, + { keytype_enter, "Enter", "Enter", 2}, + + { keytype_switch, "ABC", "abc", 2}, + { keytype_default, "z", "Z", 1}, + { keytype_default, "x", "X", 1}, + { keytype_default, "c", "C", 1}, + { keytype_default, "v", "V", 1}, + { keytype_default, "b", "B", 1}, + { keytype_default, "n", "N", 1}, + { keytype_default, "m", "M", 1}, + { keytype_default, ",", ",", 1}, + { keytype_default, ".", ".", 1}, + { keytype_switch, "ABC", "abc", 1}, + + { keytype_symbols, "?123", "?123", 2}, + { keytype_space, "", "", 8}, + { keytype_symbols, "?123", "?123", 2} +}; + +static const unsigned int columns = 12; +static const unsigned int rows = 4; + +static const double key_width = 60; +static const double key_height = 50; + +enum keyboard_state { + keyboardstate_default, + keyboardstate_uppercase +}; + struct keyboard { struct virtual_keyboard *keyboard; struct window *window; struct widget *widget; - int cx; - int cy; + + enum keyboard_state state; }; +static void +draw_key(const struct key *key, + cairo_t *cr, + enum keyboard_state state, + unsigned int row, + unsigned int col) +{ + const char *label; + cairo_text_extents_t extents; + + cairo_save(cr); + cairo_rectangle(cr, + col * key_width, row * key_height, + key->width * key_width, key_height); + cairo_clip(cr); + + /* Paint frame */ + cairo_rectangle(cr, + col * key_width, row * key_height, + key->width * key_width, key_height); + cairo_set_line_width(cr, 3); + cairo_stroke(cr); + + /* Paint text */ + label = state == keyboardstate_default ? key->label : key->alt; + cairo_text_extents(cr, label, &extents); + + cairo_translate(cr, + col * key_width, + row * key_height); + cairo_translate(cr, + (key->width * key_width - extents.width) / 2, + (key_height - extents.y_bearing) / 2); + cairo_show_text(cr, label); + + cairo_restore(cr); +} + static void redraw_handler(struct widget *widget, void *data) { @@ -54,8 +164,8 @@ redraw_handler(struct widget *widget, void *data) cairo_surface_t *surface; struct rectangle allocation; cairo_t *cr; - int cx, cy; - int i; + unsigned int i; + unsigned int row = 0, col = 0; surface = window_get_surface(keyboard->window); widget_get_allocation(keyboard->widget, &allocation); @@ -64,37 +174,26 @@ redraw_handler(struct widget *widget, void *data) cairo_rectangle(cr, allocation.x, allocation.y, allocation.width, allocation.height); cairo_clip(cr); - cairo_translate(cr, allocation.x, allocation.y); + cairo_select_font_face(cr, "sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD); + cairo_set_font_size(cr, 16); - cx = keyboard->cx; - cy = keyboard->cy; + cairo_translate(cr, allocation.x, allocation.y); cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); - cairo_set_source_rgba(cr, 1, 1, 1, 0.5); - cairo_rectangle(cr, 0, 0, 10 * cx, 5 * cy); + cairo_set_source_rgba(cr, 1, 1, 1, 0.75); + cairo_rectangle(cr, 0, 0, columns * key_width, rows * key_height); cairo_paint(cr); cairo_set_operator(cr, CAIRO_OPERATOR_OVER); - for (i = 0; i <= 'Z' - '0'; ++i) { - const int x = i % 10; - const int y = i / 10; - char text[] = { i + '0', '\0' }; - cairo_text_extents_t extents; - int dx, dy; - - cairo_text_extents(cr, text, &extents); - dx = extents.width; - dy = extents.height; - - cairo_set_source_rgb(cr, 0, 0, 0); - cairo_rectangle(cr, x * cx, y * cy, cx, cy); - cairo_stroke(cr); - - cairo_move_to(cr, x * cx + 0.5 * (cx - dx), y * cy + 0.5 * (cy - dy)); - + for (i = 0; i < sizeof(keys) / sizeof(*keys); ++i) { cairo_set_source_rgb(cr, 0, 0, 0); - cairo_show_text(cr, text); + draw_key(&keys[i], cr, keyboard->state, row, col); + col += keys[i].width; + if (col >= columns) { + row += 1; + col = 0; + } } cairo_destroy(cr); @@ -108,6 +207,37 @@ resize_handler(struct widget *widget, /* struct keyboard *keyboard = data; */ } +static void +keyboard_handle_key(struct keyboard *keyboard, const struct key *key) +{ + const char *label = keyboard->state == keyboardstate_default ? key->label : key->alt; + + switch (key->key_type) { + case keytype_default: + input_method_context_commit_string(keyboard->keyboard->context, + label, -1); + break; + case keytype_backspace: + break; + case keytype_enter: + break; + case keytype_space: + input_method_context_commit_string(keyboard->keyboard->context, + " ", -1); + break; + case keytype_switch: + if (keyboard->state == keyboardstate_default) + keyboard->state = keyboardstate_uppercase; + else + keyboard->state = keyboardstate_default; + break; + case keytype_symbols: + break; + case keytype_tab: + break; + } +} + static void button_handler(struct widget *widget, struct input *input, uint32_t time, @@ -116,8 +246,9 @@ button_handler(struct widget *widget, { struct keyboard *keyboard = data; struct rectangle allocation; - int32_t x, y; - char text[] = { '0', '\0' }; + int32_t x, y; + int row, col; + unsigned int i; if (state != WL_POINTER_BUTTON_STATE_PRESSED || button != BTN_LEFT) { return; @@ -129,9 +260,15 @@ button_handler(struct widget *widget, x -= allocation.x; y -= allocation.y; - text[0] = y / keyboard->cy * 10 + x / keyboard->cx + '0'; + row = y / key_height; + col = x / key_width + row * columns; + for (i = 0; i < sizeof(keys) / sizeof(*keys); ++i) { + col -= keys[i].width; + if (col < 0) + break; + } - input_method_context_commit_string(keyboard->keyboard->context, text, -1); + keyboard_handle_key(keyboard, &keys[i]); widget_schedule_redraw(widget); } @@ -213,15 +350,14 @@ keyboard_create(struct output *output, struct virtual_keyboard *virtual_keyboard window_set_title(keyboard->window, "Virtual keyboard"); window_set_user_data(keyboard->window, keyboard); - - keyboard->cx = 40; - keyboard->cy = 40; widget_set_redraw_handler(keyboard->widget, redraw_handler); widget_set_resize_handler(keyboard->widget, resize_handler); widget_set_button_handler(keyboard->widget, button_handler); - window_schedule_resize(keyboard->window, keyboard->cx * 10, keyboard->cy * 5); + window_schedule_resize(keyboard->window, + columns * key_width, + rows * key_height); input_panel_set_surface(virtual_keyboard->input_panel, window_get_wl_surface(keyboard->window),