diff --git a/clients/keyboard.c b/clients/keyboard.c index 49b94baae..a8c26b348 100644 --- a/clients/keyboard.c +++ b/clients/keyboard.c @@ -62,6 +62,8 @@ struct virtual_keyboard { bool toplevel; bool overlay; struct zwp_input_panel_surface_v1 *ips; + + struct weston_config *config; }; enum key_type { @@ -76,7 +78,8 @@ enum key_type { keytype_arrow_left, keytype_arrow_right, keytype_arrow_down, - keytype_style + keytype_style, + keytype_none, }; struct key { @@ -101,126 +104,121 @@ struct layout { }; static const struct key normal_keys[] = { - { keytype_default, "q", "Q", "1", 1}, - { keytype_default, "w", "W", "2", 1}, - { keytype_default, "e", "E", "3", 1}, - { keytype_default, "r", "R", "4", 1}, - { keytype_default, "t", "T", "5", 1}, - { keytype_default, "y", "Y", "6", 1}, - { keytype_default, "u", "U", "7", 1}, - { keytype_default, "i", "I", "8", 1}, - { keytype_default, "o", "O", "9", 1}, - { keytype_default, "p", "P", "0", 1}, + { keytype_none, "", "", "", 2}, + { keytype_default, "q", "Q", "1", 2}, + { keytype_default, "w", "W", "2", 2}, + { keytype_default, "e", "E", "3", 2}, + { keytype_default, "r", "R", "4", 2}, + { keytype_default, "t", "T", "5", 2}, + { keytype_default, "y", "Y", "6", 2}, + { keytype_default, "u", "U", "7", 2}, + { keytype_default, "i", "I", "8", 2}, + { keytype_default, "o", "O", "9", 2}, + { keytype_default, "p", "P", "0", 2}, { 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", "Enter", 2}, + { keytype_tab, "->|", "->|", "->|", 3}, + { keytype_default, "a", "A", "-", 2}, + { keytype_default, "s", "S", "@", 2}, + { keytype_default, "d", "D", "*", 2}, + { keytype_default, "f", "F", "^", 2}, + { keytype_default, "g", "G", ":", 2}, + { keytype_default, "h", "H", ";", 2}, + { keytype_default, "j", "J", "(", 2}, + { keytype_default, "k", "K", ")", 2}, + { keytype_default, "l", "L", "~", 2}, + { keytype_enter, "Enter", "Enter", "Enter", 3}, + { keytype_switch, "ABC", "abc", "ABC", 4}, + { keytype_default, "z", "Z", "/", 2}, + { keytype_default, "x", "X", "\'", 2}, + { keytype_default, "c", "C", "\"", 2}, + { keytype_default, "v", "V", "+", 2}, + { keytype_default, "b", "B", "=", 2}, + { keytype_default, "n", "N", "?", 2}, + { keytype_default, "m", "M", "!", 2}, + { keytype_default, ",", ",", "\\", 2}, + { keytype_default, ".", ".", "|", 2}, { keytype_switch, "ABC", "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", "ABC", 1}, - { keytype_symbols, "?123", "?123", "abc", 1}, - { keytype_space, "", "", "", 5}, - { keytype_arrow_up, "/\\", "/\\", "/\\", 1}, - { keytype_arrow_left, "<", "<", "<", 1}, - { keytype_arrow_right, ">", ">", ">", 1}, - { keytype_arrow_down, "\\/", "\\/", "\\/", 1}, - { keytype_style, "", "", "", 2} + { keytype_symbols, "?123", "?123", "abc", 2}, + { keytype_space, "", "", "", 10}, + { keytype_arrow_up, "/\\", "/\\", "/\\", 2}, + { keytype_arrow_left, "<", "<", "<", 2}, + { keytype_arrow_right, ">", ">", ">", 2}, + { keytype_arrow_down, "\\/", "\\/", "\\/", 2}, + { keytype_style, "", "", "", 4} }; static const struct key numeric_keys[] = { - { keytype_default, "1", "1", "1", 1}, - { keytype_default, "2", "2", "2", 1}, - { keytype_default, "3", "3", "3", 1}, - { keytype_default, "4", "4", "4", 1}, - { keytype_default, "5", "5", "5", 1}, - { keytype_default, "6", "6", "6", 1}, - { keytype_default, "7", "7", "7", 1}, - { keytype_default, "8", "8", "8", 1}, - { keytype_default, "9", "9", "9", 1}, - { keytype_default, "0", "0", "0", 1}, - { keytype_backspace, "<--", "<--", "<--", 2}, - - { keytype_space, "", "", "", 4}, - { keytype_enter, "Enter", "Enter", "Enter", 2}, - { keytype_arrow_up, "/\\", "/\\", "/\\", 1}, - { keytype_arrow_left, "<", "<", "<", 1}, - { keytype_arrow_right, ">", ">", ">", 1}, - { keytype_arrow_down, "\\/", "\\/", "\\/", 1}, - { keytype_style, "", "", "", 2} + { keytype_default, "7", "7", "7", 2}, + { keytype_default, "8", "8", "8", 2}, + { keytype_default, "9", "9", "9", 2}, + { keytype_default, "4", "4", "4", 2}, + { keytype_default, "5", "5", "5", 2}, + { keytype_default, "6", "6", "6", 2}, + { keytype_default, "1", "1", "1", 2}, + { keytype_default, "2", "2", "2", 2}, + { keytype_default, "3", "3", "3", 2}, + { keytype_default, "0", "0", "0", 4}, + { keytype_default,".", ".", ".", 2}, + { keytype_enter, "Enter", "Enter", "Enter", 3}, + { keytype_backspace, "<--", "<--", "<--", 3}, }; static const struct key arabic_keys[] = { - { keytype_default, "ض", "ﹶ", "۱", 1}, - { keytype_default, "ص", "ﹰ", "۲", 1}, - { keytype_default, "ث", "ﹸ", "۳", 1}, - { keytype_default, "ق", "ﹲ", "۴", 1}, - { keytype_default, "ف", "ﻹ", "۵", 1}, - { keytype_default, "غ", "ﺇ", "۶", 1}, - { keytype_default, "ع", "`", "۷", 1}, - { keytype_default, "ه", "٪", "۸", 1}, - { keytype_default, "خ", ">", "۹", 1}, - { keytype_default, "ح", "<", "۰", 1}, - { keytype_backspace, "-->", "-->", "-->", 2}, + { keytype_default, "ض", "ﹶ", "۱", 2}, + { keytype_default, "ص", "ﹰ", "۲", 2}, + { keytype_default, "ث", "ﹸ", "۳", 2}, + { keytype_default, "ق", "ﹲ", "۴", 2}, + { keytype_default, "ف", "ﻹ", "۵", 2}, + { keytype_default, "غ", "ﺇ", "۶", 2}, + { keytype_default, "ع", "`", "۷", 2}, + { keytype_default, "ه", "٪", "۸", 2}, + { keytype_default, "خ", ">", "۹", 2}, + { keytype_default, "ح", "<", "۰", 2}, + { keytype_backspace, "-->", "-->", "-->", 4}, - { keytype_tab, "->|", "->|", "->|", 1}, - { keytype_default, "ش", "ﹺ", "ﹼ", 1}, - { keytype_default, "س", "ﹴ", "!", 1}, - { keytype_default, "ي", "[", "@", 1}, - { keytype_default, "ب", "]", "#", 1}, - { keytype_default, "ل", "ﻷ", "$", 1}, - { keytype_default, "ا", "أ", "%", 1}, - { keytype_default, "ت", "-", "^", 1}, - { keytype_default, "ن", "x", "&", 1}, - { keytype_default, "م", "/", "*", 1}, - { keytype_default, "ك", ":", "_", 1}, - { keytype_default, "د", "\"", "+", 1}, - { keytype_enter, "Enter", "Enter", "Enter", 2}, + { keytype_tab, "->|", "->|", "->|", 2}, + { keytype_default, "ش", "ﹺ", "ﹼ", 2}, + { keytype_default, "س", "ﹴ", "!", 2}, + { keytype_default, "ي", "[", "@", 2}, + { keytype_default, "ب", "]", "#", 2}, + { keytype_default, "ل", "ﻷ", "$", 2}, + { keytype_default, "ا", "أ", "%", 2}, + { keytype_default, "ت", "-", "^", 2}, + { keytype_default, "ن", "x", "&", 2}, + { keytype_default, "م", "/", "*", 2}, + { keytype_default, "ك", ":", "_", 2}, + { keytype_default, "د", "\"", "+", 2}, + { keytype_enter, "Enter", "Enter", "Enter", 4}, - { keytype_switch, "Shift", "Base", "Shift", 2}, - { keytype_default, "ئ", "~", ")", 1}, - { keytype_default, "ء", "°", "(", 1}, - { keytype_default, "ؤ", "{", "\"", 1}, - { keytype_default, "ر", "}", "\'", 1}, - { keytype_default, "ى", "ﺁ", "؟", 1}, - { keytype_default, "ة", "'", "!", 1}, - { keytype_default, "و", ",", ";", 1}, - { keytype_default, "ﺯ", ".", "\\", 1}, - { keytype_default, "ظ", "؟", "=", 1}, - { keytype_switch, "Shift", "Base", "Shift", 2}, + { keytype_switch, "Shift", "Base", "Shift", 4}, + { keytype_default, "ئ", "~", ")", 2}, + { keytype_default, "ء", "°", "(", 2}, + { keytype_default, "ؤ", "{", "\"", 2}, + { keytype_default, "ر", "}", "\'", 2}, + { keytype_default, "ى", "ﺁ", "؟", 2}, + { keytype_default, "ة", "'", "!", 2}, + { keytype_default, "و", ",", ";", 2}, + { keytype_default, "ﺯ", ".", "\\", 2}, + { keytype_default, "ظ", "؟", "=", 2}, + { keytype_switch, "Shift", "Base", "Shift", 4}, - { keytype_symbols, "؟٣٢١", "؟٣٢١", "Base", 1}, - { keytype_default, "ﻻ", "ﻵ", "|", 1}, - { keytype_default, ",", "،", "،", 1}, - { keytype_space, "", "", "", 6}, - { keytype_default, ".", "ذ", "]", 1}, - { keytype_default, "ط", "ﺝ", "[", 1}, - { keytype_style, "", "", "", 2} + { keytype_symbols, "؟٣٢١", "؟٣٢١", "Base", 2}, + { keytype_default, "ﻻ", "ﻵ", "|", 2}, + { keytype_default, ",", "،", "،", 2}, + { keytype_space, "", "", "", 12}, + { keytype_default, ".", "ذ", "]", 2}, + { keytype_default, "ط", "ﺝ", "[", 2}, + { keytype_style, "", "", "", 4} }; static const struct layout normal_layout = { normal_keys, sizeof(normal_keys) / sizeof(*normal_keys), - 12, + 24, 4, "en", ZWP_TEXT_INPUT_V1_TEXT_DIRECTION_LTR @@ -229,8 +227,8 @@ static const struct layout normal_layout = { static const struct layout numeric_layout = { numeric_keys, sizeof(numeric_keys) / sizeof(*numeric_keys), - 12, - 2, + 6, + 5, "en", ZWP_TEXT_INPUT_V1_TEXT_DIRECTION_LTR }; @@ -238,12 +236,19 @@ static const struct layout numeric_layout = { static const struct layout arabic_layout = { arabic_keys, sizeof(arabic_keys) / sizeof(*arabic_keys), - 13, + 26, 4, "ar", ZWP_TEXT_INPUT_V1_TEXT_DIRECTION_RTL }; +#define MAX(x, y) (((x) > (y)) ? (x) : (y)) +#define MIN(x, y) (((x) < (y)) ? (x) : (y)) +#define max_count MAX(MAX(sizeof(arabic_keys) / sizeof(*arabic_keys), sizeof(numeric_keys) / sizeof(*numeric_keys) ), sizeof(normal_keys) / sizeof(*normal_keys)) + +#define min_columns MIN(MIN(normal_layout.columns, numeric_layout.columns), arabic_layout.columns) +#define min_rows MIN(MIN(normal_layout.rows, numeric_layout.rows), arabic_layout.rows) + static const char *style_labels[] = { "default", "none", @@ -255,8 +260,8 @@ static const char *style_labels[] = { "incorrect" }; -static const double key_width = 60; -static const double key_height = 50; +static const double key_width = 30; +static const double key_height = 60; enum keyboard_state { KEYBOARD_STATE_DEFAULT, @@ -270,6 +275,22 @@ struct keyboard { struct widget *widget; enum keyboard_state state; + uint32_t key_state[max_count]; + int32_t key_touch_event_id[max_count]; + + uint32_t key_margin; + uint32_t key_radius; + + uint32_t key_fg_color; + uint32_t key_bg_color; + uint32_t key_pressed_fg_color; + uint32_t key_pressed_bg_color; + uint32_t special_key_fg_color; + uint32_t special_key_bg_color; + uint32_t special_key_pressed_fg_color; + uint32_t special_key_pressed_bg_color; + uint32_t panel_fg_color; + uint32_t panel_bg_color; }; static void __attribute__ ((format (printf, 1, 2))) @@ -284,6 +305,29 @@ dbg(const char *fmt, ...) #endif } +static void +set_hex_color(cairo_t *cr, uint32_t color) +{ + cairo_set_source_rgba(cr, + ((color >> 16) & 0xff) / 255.0, + ((color >> 8) & 0xff) / 255.0, + ((color >> 0) & 0xff) / 255.0, + ((color >> 24) & 0xff) / 255.0); +} + +static bool +contains_decimal_point(const char* str) +{ + for (size_t i = 0; i < strlen(str); ++i) + { + if (str[i] == '.') + { + return true; + } + } + return false; +} + static const char * label_from_key(struct keyboard *keyboard, const struct key *key) @@ -291,6 +335,9 @@ label_from_key(struct keyboard *keyboard, if (key->key_type == keytype_style) return style_labels[keyboard->keyboard->preedit_style]; + if (key->key_type == keytype_none) + return ""; + switch(keyboard->state) { case KEYBOARD_STATE_DEFAULT: return key->label; @@ -303,26 +350,62 @@ label_from_key(struct keyboard *keyboard, return ""; } +static void +rounded_rectangle_path(cairo_t *cr, double x, double y, double width, double height, double radius) +{ + double degrees = M_PI / 180.0; + + cairo_new_sub_path (cr); + cairo_arc (cr, x + width - radius, y + radius, radius, -90 * degrees, 0 * degrees); + cairo_arc (cr, x + width - radius, y + height - radius, radius, 0 * degrees, 90 * degrees); + cairo_arc (cr, x + radius, y + height - radius, radius, 90 * degrees, 180 * degrees); + cairo_arc (cr, x + radius, y + radius, radius, 180 * degrees, 270 * degrees); + cairo_close_path (cr); +} + static void draw_key(struct keyboard *keyboard, const struct key *key, + uint32_t key_state, cairo_t *cr, unsigned int row, unsigned int col) { + const uint32_t margin = keyboard->key_margin; const char *label; cairo_text_extents_t extents; + uint32_t fg_color = keyboard->key_fg_color; + uint32_t bg_color = keyboard->key_bg_color; + + if (key_state == WL_KEYBOARD_KEY_STATE_RELEASED) { + fg_color = (key->key_type == keytype_default ? keyboard->key_fg_color : keyboard->special_key_fg_color); + bg_color = (key->key_type == keytype_default ? keyboard->key_bg_color : keyboard->special_key_bg_color); + } else { + fg_color = (key->key_type == keytype_default ? keyboard->key_pressed_fg_color : keyboard->special_key_pressed_fg_color); + bg_color = (key->key_type == keytype_default ? keyboard->key_pressed_bg_color : keyboard->special_key_pressed_bg_color); + } + + if (key->key_type == keytype_none) + return; + cairo_save(cr); cairo_rectangle(cr, col * key_width, row * key_height, key->width * key_width, key_height); cairo_clip(cr); + rounded_rectangle_path(cr, + col * key_width + margin, row * key_height + margin, + key->width * key_width - 2*margin, key_height - 2*margin, + key_width / 5); + + + /* Paint key background */ + set_hex_color(cr, bg_color); + cairo_fill_preserve(cr); /* Paint frame */ - cairo_rectangle(cr, - col * key_width, row * key_height, - key->width * key_width, key_height); + set_hex_color(cr, fg_color); cairo_set_line_width(cr, 3); cairo_stroke(cr); @@ -377,21 +460,22 @@ redraw_handler(struct widget *widget, void *data) cairo_rectangle(cr, allocation.x, allocation.y, allocation.width, allocation.height); cairo_clip(cr); - cairo_select_font_face(cr, "sans-serif", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD); + cairo_select_font_face(cr, "sans-serif", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL); cairo_set_font_size(cr, 16); cairo_translate(cr, allocation.x, allocation.y); cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); - cairo_set_source_rgba(cr, 1, 1, 1, 0.75); cairo_rectangle(cr, 0, 0, layout->columns * key_width, layout->rows * key_height); - cairo_paint(cr); + set_hex_color(cr, keyboard->panel_bg_color); + cairo_fill_preserve(cr); + set_hex_color(cr, keyboard->panel_fg_color); + cairo_stroke(cr); cairo_set_operator(cr, CAIRO_OPERATOR_OVER); for (i = 0; i < layout->count; ++i) { - cairo_set_source_rgb(cr, 0, 0, 0); - draw_key(keyboard, &layout->keys[i], cr, row, col); + draw_key(keyboard, &layout->keys[i], keyboard->key_state[i], cr, row, col); col += layout->keys[i].width; if (col >= layout->columns) { row += 1; @@ -486,6 +570,22 @@ prev_utf8_char(const char *s, const char *p) return NULL; } +static int utf8_char_size(const char* c) +{ + if (c != NULL) + { + if ((*c & 0x80) == 0) + return 1; + if ((*c & 0xe0) == 0xc0) + return 2; + if ((*c & 0xf0) == 0xe0) + return 3; + if ((*c & 0xf8) == 0xf0) + return 4; + } + return 0; +} + static void delete_before_cursor(struct virtual_keyboard *keyboard) { @@ -506,8 +606,8 @@ delete_before_cursor(struct virtual_keyboard *keyboard) end = keyboard->surrounding_text + keyboard->surrounding_cursor; zwp_input_method_context_v1_delete_surrounding_text(keyboard->context, - start - keyboard->surrounding_text, - end - start); + (start - keyboard->surrounding_text) - keyboard->surrounding_cursor, + 0); zwp_input_method_context_v1_commit_string(keyboard->context, keyboard->serial, ""); @@ -535,8 +635,13 @@ append(char *s1, const char *s2) } static void -keyboard_handle_key(struct keyboard *keyboard, uint32_t time, const struct key *key, struct input *input, enum wl_pointer_button_state state) +keyboard_handle_key(struct keyboard *keyboard, uint32_t time, const struct key *key, uint32_t key_num, struct input *input, enum wl_pointer_button_state state) { + if (keyboard->keyboard->context == NULL) + { + return; + } + const char *label = NULL; switch(keyboard->state) { @@ -551,14 +656,27 @@ keyboard_handle_key(struct keyboard *keyboard, uint32_t time, const struct key * break; } - xkb_mod_mask_t mod_mask = keyboard->state == KEYBOARD_STATE_DEFAULT ? 0 : keyboard->keyboard->keysym.shift_mask; + xkb_mod_mask_t mod_mask = (keyboard->state == KEYBOARD_STATE_DEFAULT) ? 0 : keyboard->keyboard->keysym.shift_mask; uint32_t key_state = (state == WL_POINTER_BUTTON_STATE_PRESSED) ? WL_KEYBOARD_KEY_STATE_PRESSED : WL_KEYBOARD_KEY_STATE_RELEASED; + keyboard->key_state[key_num] = key_state; + switch (key->key_type) { case keytype_default: if (state != WL_POINTER_BUTTON_STATE_PRESSED) break; + // Check if content purpose is number + if ((((keyboard->keyboard->content_purpose == ZWP_TEXT_INPUT_V1_CONTENT_PURPOSE_DIGITS) || + (keyboard->keyboard->content_purpose == ZWP_TEXT_INPUT_V1_CONTENT_PURPOSE_NUMBER)) && + contains_decimal_point(label)) && + (contains_decimal_point(keyboard->keyboard->surrounding_text) || + contains_decimal_point(keyboard->keyboard->preedit_string))) + { + // Do not enter a second decimal point. + return; + } + keyboard->keyboard->preedit_string = append(keyboard->keyboard->preedit_string, label); @@ -571,7 +689,23 @@ keyboard_handle_key(struct keyboard *keyboard, uint32_t time, const struct key * if (strlen(keyboard->keyboard->preedit_string) == 0) { delete_before_cursor(keyboard->keyboard); } else { - keyboard->keyboard->preedit_string[strlen(keyboard->keyboard->preedit_string) - 1] = '\0'; + const size_t len = strlen(keyboard->keyboard->preedit_string); + const char *prev_utf8 = prev_utf8_char(keyboard->keyboard->preedit_string + (len - MIN(len, 4)), + keyboard->keyboard->preedit_string + strlen(keyboard->keyboard->preedit_string)); + + if (prev_utf8) + { + const int pref_utf8_offset = prev_utf8 - keyboard->keyboard->preedit_string; + if ((strlen(keyboard->keyboard->preedit_string + pref_utf8_offset) - utf8_char_size(prev_utf8)) == 0) + { + keyboard->keyboard->preedit_string[pref_utf8_offset] = '\0'; + } + else + { + keyboard->keyboard->preedit_string[strlen(keyboard->keyboard->preedit_string) - 1] = '\0'; + } + } + virtual_keyboard_send_preedit(keyboard->keyboard, -1); } break; @@ -594,14 +728,12 @@ keyboard_handle_key(struct keyboard *keyboard, uint32_t time, const struct key * break; switch(keyboard->state) { case KEYBOARD_STATE_DEFAULT: + case KEYBOARD_STATE_SYMBOLS: keyboard->state = KEYBOARD_STATE_UPPERCASE; break; case KEYBOARD_STATE_UPPERCASE: keyboard->state = KEYBOARD_STATE_DEFAULT; break; - case KEYBOARD_STATE_SYMBOLS: - keyboard->state = KEYBOARD_STATE_UPPERCASE; - break; } break; case keytype_symbols: @@ -609,8 +741,6 @@ keyboard_handle_key(struct keyboard *keyboard, uint32_t time, const struct key * break; switch(keyboard->state) { case KEYBOARD_STATE_DEFAULT: - keyboard->state = KEYBOARD_STATE_SYMBOLS; - break; case KEYBOARD_STATE_UPPERCASE: keyboard->state = KEYBOARD_STATE_SYMBOLS; break; @@ -660,6 +790,8 @@ keyboard_handle_key(struct keyboard *keyboard, uint32_t time, const struct key * keyboard->keyboard->preedit_style = (keyboard->keyboard->preedit_style + 1) % 8; /* TODO */ virtual_keyboard_send_preedit(keyboard->keyboard, -1); break; + case keytype_none: + break; } } @@ -669,6 +801,10 @@ button_handler(struct widget *widget, uint32_t button, enum wl_pointer_button_state state, void *data) { + if (button != BTN_LEFT) { + return; + } + struct keyboard *keyboard = data; struct rectangle allocation; int32_t x, y; @@ -678,10 +814,6 @@ button_handler(struct widget *widget, layout = get_current_layout(keyboard->keyboard); - if (button != BTN_LEFT) { - return; - } - input_get_position(input, &x, &y); widget_get_allocation(keyboard->widget, &allocation); @@ -689,11 +821,11 @@ button_handler(struct widget *widget, y -= allocation.y; row = y / key_height; - col = x / key_width + row * layout->columns; + col = x / (key_width + (row * layout->columns)); for (i = 0; i < layout->count; ++i) { col -= layout->keys[i].width; if (col < 0) { - keyboard_handle_key(keyboard, time, &layout->keys[i], input, state); + keyboard_handle_key(keyboard, time, &layout->keys[i], i, input, state); break; } } @@ -702,7 +834,7 @@ button_handler(struct widget *widget, } static void -touch_handler(struct input *input, uint32_t time, +touch_handler(struct input *input, uint32_t time, int32_t id, float x, float y, uint32_t state, void *data) { struct keyboard *keyboard = data; @@ -723,8 +855,9 @@ touch_handler(struct input *input, uint32_t time, for (i = 0; i < layout->count; ++i) { col -= layout->keys[i].width; if (col < 0) { + keyboard->key_touch_event_id[i] = id; keyboard_handle_key(keyboard, time, - &layout->keys[i], input, state); + &layout->keys[i], i, input, state); break; } } @@ -737,7 +870,7 @@ touch_down_handler(struct widget *widget, struct input *input, uint32_t serial, uint32_t time, int32_t id, float x, float y, void *data) { - touch_handler(input, time, x, y, + touch_handler(input, time, id, x, y, WL_POINTER_BUTTON_STATE_PRESSED, data); } @@ -746,11 +879,21 @@ touch_up_handler(struct widget *widget, struct input *input, uint32_t serial, uint32_t time, int32_t id, void *data) { - float x, y; + struct keyboard *keyboard = data; - input_get_touch(input, id, &x, &y); + for (size_t i = 0; i < max_count; ++i) + { + if (id == keyboard->key_touch_event_id[i]) + { + keyboard->key_touch_event_id[i] = -1; + keyboard->key_state[i] = WL_KEYBOARD_KEY_STATE_RELEASED; + } + } - touch_handler(input, time, x, y, + float x, y; + input_get_touch(input, id, &x, &y); + + touch_handler(input, time, id, x, y, WL_POINTER_BUTTON_STATE_RELEASED, data); } @@ -791,8 +934,28 @@ handle_content_type(void *data, { struct virtual_keyboard *keyboard = data; - keyboard->content_hint = hint; - keyboard->content_purpose = purpose; + if ((keyboard->content_hint != hint) || (keyboard->content_purpose != purpose)) + { + keyboard->content_hint = hint; + keyboard->content_purpose = purpose; + + // A change of the content type means a new layout. + // So we have to update. + const struct layout *layout = get_current_layout(keyboard); + + zwp_input_method_context_v1_language(context, + keyboard->serial, + layout->language); + zwp_input_method_context_v1_text_direction(context, + keyboard->serial, + layout->text_direction); + + window_schedule_resize(keyboard->keyboard->window, + layout->columns * key_width, + layout->rows * key_height); + + widget_schedule_redraw(keyboard->keyboard->widget); + } } static void @@ -1011,6 +1174,7 @@ keyboard_create(struct virtual_keyboard *virtual_keyboard) window_set_appid(keyboard->window, "org.freedesktop.weston.virtual-keyboard"); window_set_user_data(keyboard->window, keyboard); + window_set_min_allocation(keyboard->window, min_columns * (int32_t)key_width, min_rows * (int32_t)key_height); widget_set_redraw_handler(keyboard->widget, redraw_handler); widget_set_resize_handler(keyboard->widget, resize_handler); @@ -1043,6 +1207,45 @@ keyboard_destroy(struct virtual_keyboard *virtual_keyboard) free(virtual_keyboard->keyboard); } +static void +config_load(struct virtual_keyboard *virtual_keyboard) +{ + struct weston_config_section *s; + const char *config_file; + config_file = weston_config_get_name_from_env(); + virtual_keyboard->config = weston_config_parse(config_file); + s = weston_config_get_section(virtual_keyboard->config, "keyboard", NULL, NULL); + + weston_config_section_get_uint(s, "key-margin", &virtual_keyboard->keyboard->key_margin, 0); + weston_config_section_get_uint(s, "key-radius", &virtual_keyboard->keyboard->key_radius, 0); + + weston_config_section_get_color(s, "key-fg", + &virtual_keyboard->keyboard->key_fg_color, 0xcc000000); + weston_config_section_get_color(s, "key-bg", + &virtual_keyboard->keyboard->key_bg_color, 0xccffffff); + weston_config_section_get_color(s, "key-pressed-fg", + &virtual_keyboard->keyboard->key_pressed_fg_color, 0xcc000000); + weston_config_section_get_color(s, "key-pressed-bg", + &virtual_keyboard->keyboard->key_pressed_bg_color, 0xccffffff); + weston_config_section_get_color(s, "special-key-fg", + &virtual_keyboard->keyboard->special_key_fg_color, 0xcc000000); + weston_config_section_get_color(s, "special-key-bg", + &virtual_keyboard->keyboard->special_key_bg_color, 0xccffffff); + weston_config_section_get_color(s, "special-key-pressed-fg", + &virtual_keyboard->keyboard->special_key_pressed_fg_color, 0xcc000000); + weston_config_section_get_color(s, "special-key-pressed-bg", + &virtual_keyboard->keyboard->special_key_pressed_bg_color, 0xccffffff); + weston_config_section_get_color(s, "panel-bg", + &virtual_keyboard->keyboard->panel_bg_color, 0xccffffff); + weston_config_section_get_color(s, "panel-fg", + &virtual_keyboard->keyboard->panel_fg_color, 0xcc000000); +} + +static void config_destroy(struct virtual_keyboard *virtual_keyboard) +{ + weston_config_destroy(virtual_keyboard->config); +} + int main(int argc, char *argv[]) { @@ -1067,10 +1270,13 @@ main(int argc, char *argv[]) keyboard_create(&virtual_keyboard); + config_load(&virtual_keyboard); + display_run(virtual_keyboard.display); keyboard_destroy(&virtual_keyboard); display_destroy(virtual_keyboard.display); + config_destroy(&virtual_keyboard); return 0; } diff --git a/clients/window.c b/clients/window.c index 90440c114..d88576856 100644 --- a/clients/window.c +++ b/clients/window.c @@ -4871,6 +4871,12 @@ window_is_resizing(struct window *window) return window->resizing; } +void window_set_min_allocation(struct window *window, int32_t width, int32_t height) +{ + window->min_allocation.width = width; + window->min_allocation.height = height; +} + void window_set_minimized(struct window *window) { diff --git a/clients/window.h b/clients/window.h index 8b3d9d1f3..add6ef601 100644 --- a/clients/window.h +++ b/clients/window.h @@ -481,6 +481,9 @@ window_set_maximized(struct window *window, int maximized); int window_is_resizing(struct window *window); +void +window_set_min_allocation(struct window *window, int32_t width, int32_t height); + void window_set_minimized(struct window *window); diff --git a/desktop-shell/input-panel.c b/desktop-shell/input-panel.c index a7645b7a4..89a0f33a4 100644 --- a/desktop-shell/input-panel.c +++ b/desktop-shell/input-panel.c @@ -191,7 +191,15 @@ input_panel_committed(struct weston_surface *surface, return; if (weston_surface_is_mapped(surface)) + { + if (shell->showing_input_panels) + { + struct weston_coord_global pos; + if (!calc_input_panel_position(ip_surface, &pos)) + weston_view_set_position(ip_surface->view, pos); + } return; + } weston_surface_map(surface);