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.
Add some helper functions to write and read a modifiers_map array. Signed-off-by: Jan Arne Petersen <[email protected]> --- clients/editor.c | 51 ++++++++++++++++++++++++++++++--------------------- clients/keyboard.c | 44 +++++++++++++++++++++++++++++++++++--------- clients/window.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ clients/window.h | 8 ++++++++ 4 files changed, 118 insertions(+), 30 deletions(-) diff --git a/clients/editor.c b/clients/editor.c index 24ccace..abb8d03 100644 --- a/clients/editor.c +++ b/clients/editor.c @@ -55,6 +55,9 @@ struct text_entry { uint32_t preedit_cursor; struct text_model *model; struct text_layout *layout; + struct { + xkb_mod_mask_t shift_mask; + } keysym; }; struct editor { @@ -365,6 +368,9 @@ text_model_modifiers_map(void *data, struct text_model *text_model, struct wl_array *map) { + struct text_entry *entry = data; + + entry->keysym.shift_mask = keysym_modifiers_get_mask(map, "Shift"); } static void @@ -377,39 +383,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->keysym.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); @@ -478,7 +487,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; diff --git a/clients/keyboard.c b/clients/keyboard.c index d1e5dbf..ff35617 100644 --- a/clients/keyboard.c +++ b/clients/keyboard.c @@ -38,6 +38,9 @@ struct virtual_keyboard { struct input_method_context *context; struct display *display; char *preedit_string; + struct { + xkb_mod_mask_t shift_mask; + } keysym; }; enum key_type { @@ -234,12 +237,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 = keyboard->state == keyboardstate_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; 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 +255,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 +273,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 +344,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 +359,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; } } @@ -388,6 +405,7 @@ input_method_activate(void *data, struct input_method_context *context) { struct virtual_keyboard *keyboard = data; + struct wl_array modifiers_map; if (keyboard->context) input_method_context_destroy(keyboard->context); @@ -401,6 +419,14 @@ input_method_activate(void *data, input_method_context_add_listener(context, &input_method_context_listener, keyboard); + + wl_array_init(&modifiers_map); + keysym_modifiers_add(&modifiers_map, "Shift"); + keysym_modifiers_add(&modifiers_map, "Control"); + keysym_modifiers_add(&modifiers_map, "Mod1"); + input_method_context_modifiers_map(context, &modifiers_map); + keyboard->keysym.shift_mask = keysym_modifiers_get_mask(&modifiers_map, "Shift"); + wl_array_release(&modifiers_map); } static void diff --git a/clients/window.c b/clients/window.c index 288a526..aeb6c49 100644 --- a/clients/window.c +++ b/clients/window.c @@ -4169,3 +4169,48 @@ display_exit(struct display *display) { display->running = 0; } + +void +keysym_modifiers_add(struct wl_array *modifiers_map, + const char *name) +{ + size_t len = strlen(name) + 1; + char *p; + + p = wl_array_add(modifiers_map, len); + + if (p == NULL) + return; + + strncpy(p, name, len); +} + +static xkb_mod_index_t +keysym_modifiers_get_index(struct wl_array *modifiers_map, + const char *name) +{ + xkb_mod_index_t index = 0; + char *p = modifiers_map->data; + + while ((const char *)p < (const char *)(modifiers_map->data + modifiers_map->size)) { + if (strcmp(p, name) == 0) + return index; + + index++; + p += strlen(p) + 1; + } + + return XKB_MOD_INVALID; +} + +xkb_mod_mask_t +keysym_modifiers_get_mask(struct wl_array *modifiers_map, + const char *name) +{ + xkb_mod_index_t index = keysym_modifiers_get_index(modifiers_map, name); + + if (index == XKB_MOD_INVALID) + return XKB_MOD_INVALID; + + return 1 << index; +} diff --git a/clients/window.h b/clients/window.h index 84846ff..e43c033 100644 --- a/clients/window.h +++ b/clients/window.h @@ -464,4 +464,12 @@ output_get_allocation(struct output *output, struct rectangle *allocation); struct wl_output * output_get_wl_output(struct output *output); +void +keysym_modifiers_add(struct wl_array *modifiers_map, + const char *name); + +xkb_mod_mask_t +keysym_modifiers_get_mask(struct wl_array *modifiers_map, + const char *name); + #endif -- 1.7.11.7 _______________________________________________ wayland-devel mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/wayland-devel
