[PATCH 13/18] text: fix weston key bindings with input methods

Jan Arne Petersen jpetersen at openismus.com
Wed Jan 16 12:26:50 PST 2013


From: Jan Arne Petersen <jpetersen at openismus.com>

Add a struct weston_keyboard, to handle the input method grab.

Signed-off-by: Jan Arne Petersen <jpetersen at openismus.com>
---
 src/compositor.c    | 29 +++++++++++++++--------------
 src/compositor.h    |  9 ++++++++-
 src/shell.c         | 10 ++++++++--
 src/text-backend.c  | 48 +++++++++++++++++++++++++++---------------------
 src/util.c          |  3 +++
 tests/weston-test.c |  2 +-
 6 files changed, 62 insertions(+), 39 deletions(-)

diff --git a/src/compositor.c b/src/compositor.c
index cd11f6b..3853b5d 100644
--- a/src/compositor.c
+++ b/src/compositor.c
@@ -1791,7 +1791,7 @@ notify_axis(struct weston_seat *seat, uint32_t time, uint32_t axis,
 WL_EXPORT void
 notify_modifiers(struct weston_seat *seat, uint32_t serial)
 {
-	struct wl_keyboard *keyboard = &seat->keyboard;
+	struct wl_keyboard *keyboard = &seat->keyboard.keyboard;
 	struct wl_keyboard_grab *grab = keyboard->grab;
 	uint32_t mods_depressed, mods_latched, mods_locked, group;
 	uint32_t mods_lookup;
@@ -1880,10 +1880,10 @@ notify_key(struct weston_seat *seat, uint32_t time, uint32_t key,
 	   enum weston_key_state_update update_state)
 {
 	struct weston_compositor *compositor = seat->compositor;
-	struct wl_keyboard *keyboard = seat->seat.keyboard;
+	struct weston_keyboard *keyboard = &seat->keyboard;
 	struct weston_surface *focus =
-		(struct weston_surface *) keyboard->focus;
-	struct wl_keyboard_grab *grab = keyboard->grab;
+		(struct weston_surface *) keyboard->keyboard.focus;
+	struct wl_keyboard_grab *grab = keyboard->keyboard.grab;
 	uint32_t serial = wl_display_next_serial(compositor->wl_display);
 	uint32_t *k, *end;
 
@@ -1892,14 +1892,14 @@ notify_key(struct weston_seat *seat, uint32_t time, uint32_t key,
 			compositor->ping_handler(focus, serial);
 
 		weston_compositor_idle_inhibit(compositor);
-		keyboard->grab_key = key;
-		keyboard->grab_time = time;
+		keyboard->keyboard.grab_key = key;
+		keyboard->keyboard.grab_time = time;
 	} else {
 		weston_compositor_idle_release(compositor);
 	}
 
-	end = keyboard->keys.data + keyboard->keys.size;
-	for (k = keyboard->keys.data; k < end; k++) {
+	end = keyboard->keyboard.keys.data + keyboard->keyboard.keys.size;
+	for (k = keyboard->keyboard.keys.data; k < end; k++) {
 		if (*k == key) {
 			/* Ignore server-generated repeats. */
 			if (state == WL_KEYBOARD_KEY_STATE_PRESSED)
@@ -1907,16 +1907,17 @@ notify_key(struct weston_seat *seat, uint32_t time, uint32_t key,
 			*k = *--end;
 		}
 	}
-	keyboard->keys.size = (void *) end - keyboard->keys.data;
+	keyboard->keyboard.keys.size = (void *) end - keyboard->keyboard.keys.data;
 	if (state == WL_KEYBOARD_KEY_STATE_PRESSED) {
-		k = wl_array_add(&keyboard->keys, sizeof *k);
+		k = wl_array_add(&keyboard->keyboard.keys, sizeof *k);
 		*k = key;
 	}
 
-	if (grab == &keyboard->default_grab) {
+	if (grab == &keyboard->keyboard.default_grab ||
+	    grab == &keyboard->input_method_grab) {
 		weston_compositor_run_key_binding(compositor, seat, time, key,
 						  state);
-		grab = keyboard->grab;
+		grab = keyboard->keyboard.grab;
 	}
 
 	grab->interface->key(grab, time, key, state);
@@ -2506,8 +2507,8 @@ weston_seat_init_keyboard(struct weston_seat *seat, struct xkb_keymap *keymap)
 
 	seat->xkb_state.leds = 0;
 
-	wl_keyboard_init(&seat->keyboard);
-	wl_seat_set_keyboard(&seat->seat, &seat->keyboard);
+	wl_keyboard_init(&seat->keyboard.keyboard);
+	wl_seat_set_keyboard(&seat->seat, &seat->keyboard.keyboard);
 
 	seat->has_keyboard = 1;
 }
diff --git a/src/compositor.h b/src/compositor.h
index 544cf33..d284fe6 100644
--- a/src/compositor.h
+++ b/src/compositor.h
@@ -207,11 +207,18 @@ struct weston_xkb_info {
 	xkb_led_index_t scroll_led;
 };
 
+struct weston_keyboard {
+	struct wl_keyboard keyboard;
+
+	struct wl_keyboard_grab input_method_grab;
+	struct wl_resource *input_method_resource;
+};
+
 struct weston_seat {
 	struct wl_seat seat;
 	struct wl_pointer pointer;
 	int has_pointer;
-	struct wl_keyboard keyboard;
+	struct weston_keyboard keyboard;
 	int has_keyboard;
 	struct wl_touch touch;
 	int has_touch;
diff --git a/src/shell.c b/src/shell.c
index 47882a5..1bc6142 100644
--- a/src/shell.c
+++ b/src/shell.c
@@ -866,8 +866,8 @@ move_surface_to_workspace(struct desktop_shell *shell,
 	drop_focus_state(shell, from, surface);
 	wl_list_for_each(seat, &shell->compositor->seat_list, link)
 		if (seat->has_keyboard &&
-		    seat->keyboard.focus == &surface->surface)
-			wl_keyboard_set_focus(&seat->keyboard, NULL);
+		    seat->keyboard.keyboard.focus == &surface->surface)
+			wl_keyboard_set_focus(&seat->keyboard.keyboard, NULL);
 
 	weston_surface_damage_below(surface);
 }
@@ -3389,6 +3389,7 @@ switcher_destroy(struct switcher *switcher)
 {
 	struct weston_surface *surface;
 	struct wl_keyboard *keyboard = switcher->grab.keyboard;
+	struct weston_keyboard *weston_keyboard = (struct weston_keyboard *)keyboard;
 	struct workspace *ws = get_current_workspace(switcher->shell);
 
 	wl_list_for_each(surface, &ws->layer.surface_list, layer_link) {
@@ -3401,6 +3402,8 @@ switcher_destroy(struct switcher *switcher)
 			 (struct weston_seat *) keyboard->seat);
 	wl_list_remove(&switcher->listener.link);
 	wl_keyboard_end_grab(keyboard);
+	if (weston_keyboard->input_method_resource)
+		keyboard->grab = &weston_keyboard->input_method_grab;
 	free(switcher);
 }
 
@@ -3571,7 +3574,10 @@ debug_binding_key(struct wl_keyboard_grab *grab, uint32_t time,
 	}
 
 	if (terminate) {
+		struct weston_keyboard *weston_keyboard = (struct weston_keyboard *) grab->keyboard;
 		wl_keyboard_end_grab(grab->keyboard);
+		if (weston_keyboard->input_method_resource)
+			grab->keyboard->grab = &weston_keyboard->input_method_grab;
 		free(db);
 	}
 }
diff --git a/src/text-backend.c b/src/text-backend.c
index e0b8b7d..c0cddfe 100644
--- a/src/text-backend.c
+++ b/src/text-backend.c
@@ -77,7 +77,6 @@ struct input_method_context {
 	struct wl_list link;
 
 	struct wl_resource *keyboard;
-	struct wl_keyboard_grab grab;
 };
 
 struct text_backend {
@@ -455,14 +454,17 @@ static void
 input_method_context_grab_key(struct wl_keyboard_grab *grab,
 			      uint32_t time, uint32_t key, uint32_t state_w)
 {
-	struct input_method_context *input_method_context = container_of(grab, struct input_method_context, grab);
+	struct weston_keyboard *keyboard = (struct weston_keyboard *)grab->keyboard;
+	struct wl_display *display;
 	uint32_t serial;
-       
-	if (input_method_context->keyboard) {
-		serial = wl_display_next_serial(input_method_context->model->ec->wl_display);
-		wl_keyboard_send_key(input_method_context->keyboard,
-				     serial, time, key, state_w);
-	}
+
+	if (!keyboard->input_method_resource)
+		return;
+
+	display = wl_client_get_display(keyboard->input_method_resource->client);
+	serial = wl_display_next_serial(display);
+	wl_keyboard_send_key(keyboard->input_method_resource,
+			     serial, time, key, state_w);
 }
 
 static void
@@ -470,12 +472,12 @@ input_method_context_grab_modifier(struct wl_keyboard_grab *grab, uint32_t seria
 				   uint32_t mods_depressed, uint32_t mods_latched,
 				   uint32_t mods_locked, uint32_t group)
 {
-	struct input_method_context *input_method_context = container_of(grab, struct input_method_context, grab);
+	struct weston_keyboard *keyboard = (struct weston_keyboard *)grab->keyboard;
 
-	if (!input_method_context->keyboard)
+	if (!keyboard->input_method_resource)
 		return;
 
-	wl_keyboard_send_modifiers(input_method_context->keyboard,
+	wl_keyboard_send_modifiers(keyboard->input_method_resource,
 				   serial, mods_depressed, mods_latched,
 				   mods_locked, group);
 }
@@ -493,7 +495,7 @@ input_method_context_grab_keyboard(struct wl_client *client,
 	struct input_method_context *context = resource->data;
 	struct wl_resource *cr;
 	struct weston_seat *seat = context->input_method->seat;
-	struct wl_keyboard *keyboard = seat->seat.keyboard;
+	struct weston_keyboard *keyboard = &seat->keyboard;
 
 	cr = wl_client_add_object(client, &wl_keyboard_interface,
 				  NULL, id, context);
@@ -505,10 +507,11 @@ input_method_context_grab_keyboard(struct wl_client *client,
 				seat->xkb_info.keymap_fd,
 				seat->xkb_info.keymap_size);
 
-	if (keyboard->grab != &keyboard->default_grab) {
-		wl_keyboard_end_grab(keyboard);
+	if (keyboard->keyboard.grab != &keyboard->keyboard.default_grab) {
+		wl_keyboard_end_grab(&keyboard->keyboard);
 	}
-	wl_keyboard_start_grab(keyboard, &context->grab);
+	wl_keyboard_start_grab(&keyboard->keyboard, &keyboard->input_method_grab);
+	keyboard->input_method_resource = cr;
 }
 
 static void
@@ -600,8 +603,6 @@ input_method_context_create(struct text_model *model,
 	context->input_method = input_method;
 	input_method->context = context;
 
-	context->grab.interface = &input_method_context_grab;
-
 	wl_client_add_resource(input_method->input_method_binding->client, &context->resource);
 
 	input_method_send_activate(input_method->input_method_binding, &context->resource, serial);
@@ -610,13 +611,17 @@ input_method_context_create(struct text_model *model,
 static void
 input_method_context_end_keyboard_grab(struct input_method_context *context)
 {
-	struct wl_keyboard_grab *grab = &context->grab;
+	struct wl_keyboard_grab *grab = &context->input_method->seat->keyboard.input_method_grab;
+	struct weston_keyboard *keyboard = (struct weston_keyboard *)grab->keyboard;
 
-	if (grab->keyboard && (grab->keyboard->grab == grab)) {
+	if (!grab->keyboard)
+		return;
+
+	if (grab->keyboard->grab == grab)
 		wl_keyboard_end_grab(grab->keyboard);
-	}
-}
 
+	keyboard->input_method_resource = NULL;
+}
 
 static void
 unbind_input_method(struct wl_resource *resource)
@@ -699,6 +704,7 @@ input_method_init_seat(struct weston_seat *seat)
 	if (seat->has_keyboard) {
 		seat->input_method->keyboard_focus_listener.notify = handle_keyboard_focus;
 		wl_signal_add(&seat->seat.keyboard->focus_signal, &seat->input_method->keyboard_focus_listener);
+		seat->keyboard.input_method_grab.interface = &input_method_context_grab;
 	}
 
 	seat->input_method->focus_listener_initialized = 1;
diff --git a/src/util.c b/src/util.c
index 5f8e9c8..1cd2b8f 100644
--- a/src/util.c
+++ b/src/util.c
@@ -406,11 +406,14 @@ binding_key(struct wl_keyboard_grab *grab,
 	struct wl_display *display;
 	enum wl_keyboard_key_state state = state_w;
 	uint32_t serial;
+	struct weston_keyboard *keyboard = (struct weston_keyboard *)grab->keyboard;
 
 	resource = grab->keyboard->focus_resource;
 	if (key == b->key) {
 		if (state == WL_KEYBOARD_KEY_STATE_RELEASED) {
 			wl_keyboard_end_grab(grab->keyboard);
+			if (keyboard->input_method_resource)
+				keyboard->keyboard.grab = &keyboard->input_method_grab;
 			free(b);
 		}
 	} else if (resource) {
diff --git a/tests/weston-test.c b/tests/weston-test.c
index be635fa..a9def4b 100644
--- a/tests/weston-test.c
+++ b/tests/weston-test.c
@@ -155,7 +155,7 @@ activate_surface(struct wl_client *client, struct wl_resource *resource,
 
 	if (surface) {
 		weston_surface_activate(surface, seat);
-		notify_keyboard_focus_in(seat, &seat->keyboard.keys,
+		notify_keyboard_focus_in(seat, &seat->keyboard.keyboard.keys,
 					 STATE_UPDATE_AUTOMATIC);
 	}
 	else {
-- 
1.8.1



More information about the wayland-devel mailing list