[PATCH v2 3/9] text: Send more information with keysym events

Jan Arne Petersen jpetersen at openismus.com
Thu Nov 15 02:29:47 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.

Signed-off-by: Jan Arne Petersen <jpetersen at openismus.com>
---
 clients/editor.c   | 50 +++++++++++++++++++++++++++++---------------------
 clients/keyboard.c | 32 +++++++++++++++++++++++---------
 clients/window.c   | 18 ++++++++++++++++++
 clients/window.h   |  3 +++
 4 files changed, 73 insertions(+), 30 deletions(-)

diff --git a/clients/editor.c b/clients/editor.c
index 0a52faf..7f03e2b 100644
--- a/clients/editor.c
+++ b/clients/editor.c
@@ -55,6 +55,7 @@ struct text_entry {
 	uint32_t preedit_cursor;
 	struct text_model *model;
 	struct text_layout *layout;
+	xkb_mod_mask_t shift_mask;
 };
 
 struct editor {
@@ -370,39 +371,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->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);
@@ -470,7 +474,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;
@@ -864,6 +868,10 @@ text_entry_button_handler(struct widget *widget,
 	widget_get_allocation(entry->widget, &allocation);
 	input_get_position(input, &x, &y);
 
+	if (!entry->shift_mask) {
+		entry->shift_mask = input_get_mod_mask(input, MOD_SHIFT_MASK);
+	}
+
 	if (button != BTN_LEFT) {
 		return;
 	}
diff --git a/clients/keyboard.c b/clients/keyboard.c
index d1e5dbf..2d6aa86 100644
--- a/clients/keyboard.c
+++ b/clients/keyboard.c
@@ -234,12 +234,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 = input_get_mod_mask(input, keyboard->state == keyboardstate_default ? 0 : MOD_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 +252,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 +270,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 +341,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 +356,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;
 		}
 	}
diff --git a/clients/window.c b/clients/window.c
index 288a526..a370c34 100644
--- a/clients/window.c
+++ b/clients/window.c
@@ -2432,6 +2432,24 @@ input_get_modifiers(struct input *input)
 	return input->modifiers;
 }
 
+xkb_mod_mask_t
+input_get_mod_mask(struct input *input, uint32_t modifier)
+{
+	xkb_mod_mask_t mod_mask = 0;
+
+	if (!input->keyboard)
+		return modifier;
+
+	if (modifier & MOD_SHIFT_MASK)
+		mod_mask |= input->xkb.shift_mask;
+	if (modifier & MOD_ALT_MASK)
+		mod_mask |= input->xkb.alt_mask;
+	if (modifier & MOD_CONTROL_MASK)
+		mod_mask |= input->xkb.control_mask;
+
+	return mod_mask;
+}
+
 struct widget *
 input_get_focus_widget(struct input *input)
 {
diff --git a/clients/window.h b/clients/window.h
index 84846ff..6ba83b1 100644
--- a/clients/window.h
+++ b/clients/window.h
@@ -411,6 +411,9 @@ input_get_position(struct input *input, int32_t *x, int32_t *y);
 uint32_t
 input_get_modifiers(struct input *input);
 
+xkb_mod_mask_t
+input_get_mod_mask(struct input *input, uint32_t modifier);
+
 void
 input_grab(struct input *input, struct widget *widget, uint32_t button);
 
-- 
1.7.11.7



More information about the wayland-devel mailing list