[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