[PATCH v3 3/9] text: Send more information with keysym events
Jan Arne Petersen
jpetersen at openismus.com
Sun Nov 18 10:06:44 PST 2012
From: Jan Arne Petersen <jpetersen at openismus.com>
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 at openismus.com>
---
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
More information about the wayland-devel
mailing list