From: Jan Arne Petersen <[email protected]> Send state and modifier from the demo keyboard with the keysym event and take them into account in the editor example.
Signed-off-by: Jan Arne Petersen <[email protected]> --- clients/editor.c | 50 +++++++++++++++++++++++++++++--------------------- clients/keyboard.c | 32 +++++++++++++++++++++++--------- clients/window.c | 18 ++++++++++++++++++ clients/window.h | 3 +++ 4 files changed, 73 insertions(+), 30 deletions(-) diff --git a/clients/editor.c b/clients/editor.c index 0a52faf..7f03e2b 100644 --- a/clients/editor.c +++ b/clients/editor.c @@ -55,6 +55,7 @@ struct text_entry { uint32_t preedit_cursor; struct text_model *model; struct text_layout *layout; + xkb_mod_mask_t shift_mask; }; struct editor { @@ -370,39 +371,42 @@ text_model_keysym(void *data, uint32_t modifiers) { struct text_entry *entry = data; - const char *state_label; - const char *key_label = "released"; + const char *state_label = "release"; + const char *key_label = "Unknown"; const char *new_char; if (state == WL_KEYBOARD_KEY_STATE_PRESSED) { state_label = "pressed"; } + if (key == XKB_KEY_Left || + key == XKB_KEY_Right) { + if (state != WL_KEYBOARD_KEY_STATE_RELEASED) + return; + + if (key == XKB_KEY_Left) + new_char = utf8_prev_char(entry->text, entry->text + entry->cursor); + else + new_char = utf8_next_char(entry->text + entry->cursor); + + if (new_char != NULL) { + entry->cursor = new_char - entry->text; + if (!(modifiers & entry->shift_mask)) + entry->anchor = entry->cursor; + widget_schedule_redraw(entry->widget); + } + + return; + } + switch (key) { case XKB_KEY_Tab: key_label = "Tab"; break; case XKB_KEY_KP_Enter: + case XKB_KEY_Return: key_label = "Enter"; break; - case XKB_KEY_Left: - new_char = utf8_prev_char(entry->text, entry->text + entry->cursor); - if (new_char != NULL) { - entry->cursor = new_char - entry->text; - entry->anchor = entry->cursor; - widget_schedule_redraw(entry->widget); - } - break; - case XKB_KEY_Right: - new_char = utf8_next_char(entry->text + entry->cursor); - if (new_char != NULL) { - entry->cursor = new_char - entry->text; - entry->anchor = entry->cursor; - widget_schedule_redraw(entry->widget); - } - break; - default: - key_label = "Unknown"; } fprintf(stderr, "%s key was %s.\n", key_label, state_label); @@ -470,7 +474,7 @@ text_entry_create(struct editor *editor, const char *text) { struct text_entry *entry; - entry = malloc(sizeof *entry); + entry = calloc(1, sizeof *entry); entry->widget = widget_add_widget(editor->widget, entry); entry->window = editor->window; @@ -864,6 +868,10 @@ text_entry_button_handler(struct widget *widget, widget_get_allocation(entry->widget, &allocation); input_get_position(input, &x, &y); + if (!entry->shift_mask) { + entry->shift_mask = input_get_mod_mask(input, MOD_SHIFT_MASK); + } + if (button != BTN_LEFT) { return; } diff --git a/clients/keyboard.c b/clients/keyboard.c index d1e5dbf..2d6aa86 100644 --- a/clients/keyboard.c +++ b/clients/keyboard.c @@ -234,12 +234,17 @@ virtual_keyboard_commit_preedit(struct virtual_keyboard *keyboard) } static void -keyboard_handle_key(struct keyboard *keyboard, uint32_t time, const struct key *key) +keyboard_handle_key(struct keyboard *keyboard, uint32_t time, const struct key *key, struct input *input, enum wl_pointer_button_state state) { const char *label = keyboard->state == keyboardstate_default ? key->label : key->alt; + xkb_mod_mask_t mod_mask = input_get_mod_mask(input, keyboard->state == keyboardstate_default ? 0 : MOD_SHIFT_MASK); + uint32_t key_state = (state == WL_POINTER_BUTTON_STATE_PRESSED) ? WL_KEYBOARD_KEY_STATE_PRESSED : WL_KEYBOARD_KEY_STATE_RELEASED; switch (key->key_type) { case keytype_default: + if (state != WL_POINTER_BUTTON_STATE_PRESSED) + break; + keyboard->keyboard->preedit_string = strcat(keyboard->keyboard->preedit_string, label); input_method_context_preedit_string(keyboard->keyboard->context, @@ -247,6 +252,9 @@ keyboard_handle_key(struct keyboard *keyboard, uint32_t time, const struct key * strlen(keyboard->keyboard->preedit_string)); break; case keytype_backspace: + if (state != WL_POINTER_BUTTON_STATE_PRESSED) + break; + if (strlen(keyboard->keyboard->preedit_string) == 0) { input_method_context_delete_surrounding_text(keyboard->keyboard->context, -1, 1); @@ -262,55 +270,61 @@ keyboard_handle_key(struct keyboard *keyboard, uint32_t time, const struct key * input_method_context_keysym(keyboard->keyboard->context, display_get_serial(keyboard->keyboard->display), time, - XKB_KEY_KP_Enter, WL_KEYBOARD_KEY_STATE_PRESSED, 0); + XKB_KEY_Return, key_state, mod_mask); break; case keytype_space: + if (state != WL_POINTER_BUTTON_STATE_PRESSED) + break; keyboard->keyboard->preedit_string = strcat(keyboard->keyboard->preedit_string, " "); virtual_keyboard_commit_preedit(keyboard->keyboard); break; case keytype_switch: + if (state != WL_POINTER_BUTTON_STATE_PRESSED) + break; if (keyboard->state == keyboardstate_default) keyboard->state = keyboardstate_uppercase; else keyboard->state = keyboardstate_default; break; case keytype_symbols: + if (state != WL_POINTER_BUTTON_STATE_PRESSED) + break; break; case keytype_tab: virtual_keyboard_commit_preedit(keyboard->keyboard); input_method_context_keysym(keyboard->keyboard->context, display_get_serial(keyboard->keyboard->display), time, - XKB_KEY_Tab, WL_KEYBOARD_KEY_STATE_PRESSED, 0); + XKB_KEY_Tab, key_state, mod_mask); break; case keytype_arrow_up: virtual_keyboard_commit_preedit(keyboard->keyboard); input_method_context_keysym(keyboard->keyboard->context, display_get_serial(keyboard->keyboard->display), time, - XKB_KEY_Up, WL_KEYBOARD_KEY_STATE_PRESSED, 0); + XKB_KEY_Up, key_state, mod_mask); break; case keytype_arrow_left: virtual_keyboard_commit_preedit(keyboard->keyboard); input_method_context_keysym(keyboard->keyboard->context, display_get_serial(keyboard->keyboard->display), time, - XKB_KEY_Left, WL_KEYBOARD_KEY_STATE_PRESSED, 0); + XKB_KEY_Left, key_state, mod_mask); break; case keytype_arrow_right: virtual_keyboard_commit_preedit(keyboard->keyboard); input_method_context_keysym(keyboard->keyboard->context, display_get_serial(keyboard->keyboard->display), time, - XKB_KEY_Right, WL_KEYBOARD_KEY_STATE_PRESSED, 0); + XKB_KEY_Right, key_state, mod_mask); break; case keytype_arrow_down: virtual_keyboard_commit_preedit(keyboard->keyboard); input_method_context_keysym(keyboard->keyboard->context, display_get_serial(keyboard->keyboard->display), time, - XKB_KEY_Down, WL_KEYBOARD_KEY_STATE_PRESSED, 0); + XKB_KEY_Down, key_state, mod_mask); break; } } @@ -327,7 +341,7 @@ button_handler(struct widget *widget, int row, col; unsigned int i; - if (state != WL_POINTER_BUTTON_STATE_PRESSED || button != BTN_LEFT) { + if (button != BTN_LEFT) { return; } @@ -342,7 +356,7 @@ button_handler(struct widget *widget, for (i = 0; i < sizeof(keys) / sizeof(*keys); ++i) { col -= keys[i].width; if (col < 0) { - keyboard_handle_key(keyboard, time, &keys[i]); + keyboard_handle_key(keyboard, time, &keys[i], input, state); break; } } diff --git a/clients/window.c b/clients/window.c index 288a526..a370c34 100644 --- a/clients/window.c +++ b/clients/window.c @@ -2432,6 +2432,24 @@ input_get_modifiers(struct input *input) return input->modifiers; } +xkb_mod_mask_t +input_get_mod_mask(struct input *input, uint32_t modifier) +{ + xkb_mod_mask_t mod_mask = 0; + + if (!input->keyboard) + return modifier; + + if (modifier & MOD_SHIFT_MASK) + mod_mask |= input->xkb.shift_mask; + if (modifier & MOD_ALT_MASK) + mod_mask |= input->xkb.alt_mask; + if (modifier & MOD_CONTROL_MASK) + mod_mask |= input->xkb.control_mask; + + return mod_mask; +} + struct widget * input_get_focus_widget(struct input *input) { diff --git a/clients/window.h b/clients/window.h index 84846ff..6ba83b1 100644 --- a/clients/window.h +++ b/clients/window.h @@ -411,6 +411,9 @@ input_get_position(struct input *input, int32_t *x, int32_t *y); uint32_t input_get_modifiers(struct input *input); +xkb_mod_mask_t +input_get_mod_mask(struct input *input, uint32_t modifier); + void input_grab(struct input *input, struct widget *widget, uint32_t button); -- 1.7.11.7 _______________________________________________ wayland-devel mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/wayland-devel
