text: Send more information with keysym events

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>
dev
Jan Arne Petersen 13 years ago committed by Kristian Høgsberg
parent d9be93b964
commit cd99706b61
  1. 51
      clients/editor.c
  2. 44
      clients/keyboard.c
  3. 45
      clients/window.c
  4. 8
      clients/window.h

@ -55,6 +55,9 @@ struct text_entry {
uint32_t preedit_cursor; uint32_t preedit_cursor;
struct text_model *model; struct text_model *model;
struct text_layout *layout; struct text_layout *layout;
struct {
xkb_mod_mask_t shift_mask;
} keysym;
}; };
struct editor { struct editor {
@ -365,6 +368,9 @@ text_model_modifiers_map(void *data,
struct text_model *text_model, struct text_model *text_model,
struct wl_array *map) struct wl_array *map)
{ {
struct text_entry *entry = data;
entry->keysym.shift_mask = keysym_modifiers_get_mask(map, "Shift");
} }
static void static void
@ -377,39 +383,42 @@ text_model_keysym(void *data,
uint32_t modifiers) uint32_t modifiers)
{ {
struct text_entry *entry = data; struct text_entry *entry = data;
const char *state_label; const char *state_label = "release";
const char *key_label = "released"; const char *key_label = "Unknown";
const char *new_char; const char *new_char;
if (state == WL_KEYBOARD_KEY_STATE_PRESSED) { if (state == WL_KEYBOARD_KEY_STATE_PRESSED) {
state_label = "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) { switch (key) {
case XKB_KEY_Tab: case XKB_KEY_Tab:
key_label = "Tab"; key_label = "Tab";
break; break;
case XKB_KEY_KP_Enter: case XKB_KEY_KP_Enter:
case XKB_KEY_Return:
key_label = "Enter"; key_label = "Enter";
break; 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); 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; struct text_entry *entry;
entry = malloc(sizeof *entry); entry = calloc(1, sizeof *entry);
entry->widget = widget_add_widget(editor->widget, entry); entry->widget = widget_add_widget(editor->widget, entry);
entry->window = editor->window; entry->window = editor->window;

@ -38,6 +38,9 @@ struct virtual_keyboard {
struct input_method_context *context; struct input_method_context *context;
struct display *display; struct display *display;
char *preedit_string; char *preedit_string;
struct {
xkb_mod_mask_t shift_mask;
} keysym;
}; };
enum key_type { enum key_type {
@ -234,12 +237,17 @@ virtual_keyboard_commit_preedit(struct virtual_keyboard *keyboard)
} }
static void 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; 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) { switch (key->key_type) {
case keytype_default: case keytype_default:
if (state != WL_POINTER_BUTTON_STATE_PRESSED)
break;
keyboard->keyboard->preedit_string = strcat(keyboard->keyboard->preedit_string, keyboard->keyboard->preedit_string = strcat(keyboard->keyboard->preedit_string,
label); label);
input_method_context_preedit_string(keyboard->keyboard->context, 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)); strlen(keyboard->keyboard->preedit_string));
break; break;
case keytype_backspace: case keytype_backspace:
if (state != WL_POINTER_BUTTON_STATE_PRESSED)
break;
if (strlen(keyboard->keyboard->preedit_string) == 0) { if (strlen(keyboard->keyboard->preedit_string) == 0) {
input_method_context_delete_surrounding_text(keyboard->keyboard->context, input_method_context_delete_surrounding_text(keyboard->keyboard->context,
-1, 1); -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, input_method_context_keysym(keyboard->keyboard->context,
display_get_serial(keyboard->keyboard->display), display_get_serial(keyboard->keyboard->display),
time, time,
XKB_KEY_KP_Enter, WL_KEYBOARD_KEY_STATE_PRESSED, 0); XKB_KEY_Return, key_state, mod_mask);
break; break;
case keytype_space: case keytype_space:
if (state != WL_POINTER_BUTTON_STATE_PRESSED)
break;
keyboard->keyboard->preedit_string = strcat(keyboard->keyboard->preedit_string, keyboard->keyboard->preedit_string = strcat(keyboard->keyboard->preedit_string,
" "); " ");
virtual_keyboard_commit_preedit(keyboard->keyboard); virtual_keyboard_commit_preedit(keyboard->keyboard);
break; break;
case keytype_switch: case keytype_switch:
if (state != WL_POINTER_BUTTON_STATE_PRESSED)
break;
if (keyboard->state == keyboardstate_default) if (keyboard->state == keyboardstate_default)
keyboard->state = keyboardstate_uppercase; keyboard->state = keyboardstate_uppercase;
else else
keyboard->state = keyboardstate_default; keyboard->state = keyboardstate_default;
break; break;
case keytype_symbols: case keytype_symbols:
if (state != WL_POINTER_BUTTON_STATE_PRESSED)
break;
break; break;
case keytype_tab: case keytype_tab:
virtual_keyboard_commit_preedit(keyboard->keyboard); virtual_keyboard_commit_preedit(keyboard->keyboard);
input_method_context_keysym(keyboard->keyboard->context, input_method_context_keysym(keyboard->keyboard->context,
display_get_serial(keyboard->keyboard->display), display_get_serial(keyboard->keyboard->display),
time, time,
XKB_KEY_Tab, WL_KEYBOARD_KEY_STATE_PRESSED, 0); XKB_KEY_Tab, key_state, mod_mask);
break; break;
case keytype_arrow_up: case keytype_arrow_up:
virtual_keyboard_commit_preedit(keyboard->keyboard); virtual_keyboard_commit_preedit(keyboard->keyboard);
input_method_context_keysym(keyboard->keyboard->context, input_method_context_keysym(keyboard->keyboard->context,
display_get_serial(keyboard->keyboard->display), display_get_serial(keyboard->keyboard->display),
time, time,
XKB_KEY_Up, WL_KEYBOARD_KEY_STATE_PRESSED, 0); XKB_KEY_Up, key_state, mod_mask);
break; break;
case keytype_arrow_left: case keytype_arrow_left:
virtual_keyboard_commit_preedit(keyboard->keyboard); virtual_keyboard_commit_preedit(keyboard->keyboard);
input_method_context_keysym(keyboard->keyboard->context, input_method_context_keysym(keyboard->keyboard->context,
display_get_serial(keyboard->keyboard->display), display_get_serial(keyboard->keyboard->display),
time, time,
XKB_KEY_Left, WL_KEYBOARD_KEY_STATE_PRESSED, 0); XKB_KEY_Left, key_state, mod_mask);
break; break;
case keytype_arrow_right: case keytype_arrow_right:
virtual_keyboard_commit_preedit(keyboard->keyboard); virtual_keyboard_commit_preedit(keyboard->keyboard);
input_method_context_keysym(keyboard->keyboard->context, input_method_context_keysym(keyboard->keyboard->context,
display_get_serial(keyboard->keyboard->display), display_get_serial(keyboard->keyboard->display),
time, time,
XKB_KEY_Right, WL_KEYBOARD_KEY_STATE_PRESSED, 0); XKB_KEY_Right, key_state, mod_mask);
break; break;
case keytype_arrow_down: case keytype_arrow_down:
virtual_keyboard_commit_preedit(keyboard->keyboard); virtual_keyboard_commit_preedit(keyboard->keyboard);
input_method_context_keysym(keyboard->keyboard->context, input_method_context_keysym(keyboard->keyboard->context,
display_get_serial(keyboard->keyboard->display), display_get_serial(keyboard->keyboard->display),
time, time,
XKB_KEY_Down, WL_KEYBOARD_KEY_STATE_PRESSED, 0); XKB_KEY_Down, key_state, mod_mask);
break; break;
} }
} }
@ -327,7 +344,7 @@ button_handler(struct widget *widget,
int row, col; int row, col;
unsigned int i; unsigned int i;
if (state != WL_POINTER_BUTTON_STATE_PRESSED || button != BTN_LEFT) { if (button != BTN_LEFT) {
return; return;
} }
@ -342,7 +359,7 @@ button_handler(struct widget *widget,
for (i = 0; i < sizeof(keys) / sizeof(*keys); ++i) { for (i = 0; i < sizeof(keys) / sizeof(*keys); ++i) {
col -= keys[i].width; col -= keys[i].width;
if (col < 0) { if (col < 0) {
keyboard_handle_key(keyboard, time, &keys[i]); keyboard_handle_key(keyboard, time, &keys[i], input, state);
break; break;
} }
} }
@ -388,6 +405,7 @@ input_method_activate(void *data,
struct input_method_context *context) struct input_method_context *context)
{ {
struct virtual_keyboard *keyboard = data; struct virtual_keyboard *keyboard = data;
struct wl_array modifiers_map;
if (keyboard->context) if (keyboard->context)
input_method_context_destroy(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_add_listener(context,
&input_method_context_listener, &input_method_context_listener,
keyboard); 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 static void

@ -4165,3 +4165,48 @@ display_exit(struct display *display)
{ {
display->running = 0; 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;
}

@ -455,4 +455,12 @@ output_get_allocation(struct output *output, struct rectangle *allocation);
struct wl_output * struct wl_output *
output_get_wl_output(struct output *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 #endif

Loading…
Cancel
Save