text: Send more information with keysym events
authorJan Arne Petersen <jpetersen@openismus.com>
Sun, 18 Nov 2012 18:06:44 +0000 (19:06 +0100)
committerKristian Høgsberg <krh@bitplanet.net>
Tue, 27 Nov 2012 18:06:21 +0000 (13:06 -0500)
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 <jpetersen@openismus.com>
clients/editor.c
clients/keyboard.c
clients/window.c
clients/window.h

index 24ccace..abb8d03 100644 (file)
@@ -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;
index d1e5dbf..ff35617 100644 (file)
@@ -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
index 8cf53d3..c3365ba 100644 (file)
@@ -4165,3 +4165,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;
+}
index 25122d0..9b820a0 100644 (file)
@@ -455,4 +455,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