When running a key binding we don't send the key press to the client
via the wl_keyboard.key event. Instead, send a wl_keyboard.leave/enter
pair so that the client knows the actual state of the keyboard.
---
 src/bindings.c | 23 ++++++++++++++++++++---
 src/input.c    |  3 +--
 2 files changed, 21 insertions(+), 5 deletions(-)

diff --git a/src/bindings.c b/src/bindings.c
index 5e24725..5cb031a 100644
--- a/src/bindings.c
+++ b/src/bindings.c
@@ -203,7 +203,8 @@ binding_key(struct weston_keyboard_grab *grab,
                                keyboard->grab = &keyboard->input_method_grab;
                        free(b);
                }
-       } else if (!wl_list_empty(&keyboard->focus_resource_list)) {
+       }
+       if (!wl_list_empty(&keyboard->focus_resource_list)) {
                serial = wl_display_next_serial(display);
                wl_resource_for_each(resource, &keyboard->focus_resource_list) {
                        wl_keyboard_send_key(resource,
@@ -245,7 +246,8 @@ static const struct weston_keyboard_grab_interface 
binding_grab = {
 };
 
 static void
-install_binding_grab(struct weston_seat *seat, uint32_t time, uint32_t key)
+install_binding_grab(struct weston_seat *seat, uint32_t time, uint32_t key,
+                     struct weston_surface *focus)
 {
        struct binding_keyboard_grab *grab;
 
@@ -253,6 +255,19 @@ install_binding_grab(struct weston_seat *seat, uint32_t 
time, uint32_t key)
        grab->key = key;
        grab->grab.interface = &binding_grab;
        weston_keyboard_start_grab(seat->keyboard, &grab->grab);
+
+       /* Notify the surface which had the focus before this binding
+        * triggered that we stole a keypress from under it, by forcing
+        * a wl_keyboard leave/enter pair. The enter event will contain
+        * the pressed key in the keys array, so the client will know
+        * the exact state of the keyboard.
+        * If the old focus surface is different than the new one it
+        * means it was changed in the binding handler, so it received
+        * the enter event already. */
+       if (focus && seat->keyboard->focus == focus) {
+               weston_keyboard_set_focus(seat->keyboard, NULL);
+               weston_keyboard_set_focus(seat->keyboard, focus);
+       }
 }
 
 WL_EXPORT void
@@ -262,6 +277,7 @@ weston_compositor_run_key_binding(struct weston_compositor 
*compositor,
                                  enum wl_keyboard_key_state state)
 {
        struct weston_binding *b, *tmp;
+       struct weston_surface *focus;
 
        if (state == WL_KEYBOARD_KEY_STATE_RELEASED)
                return;
@@ -273,6 +289,7 @@ weston_compositor_run_key_binding(struct weston_compositor 
*compositor,
        wl_list_for_each_safe(b, tmp, &compositor->key_binding_list, link) {
                if (b->key == key && b->modifier == seat->modifier_state) {
                        weston_key_binding_handler_t handler = b->handler;
+                       focus = seat->keyboard->focus;
                        handler(seat, time, key, b->data);
 
                        /* If this was a key binding and it didn't
@@ -280,7 +297,7 @@ weston_compositor_run_key_binding(struct weston_compositor 
*compositor,
                         * swallow the key release. */
                        if (seat->keyboard->grab ==
                            &seat->keyboard->default_grab)
-                               install_binding_grab(seat, time, key);
+                               install_binding_grab(seat, time, key, focus);
                }
        }
 }
diff --git a/src/input.c b/src/input.c
index 15ff6ed..093d781 100644
--- a/src/input.c
+++ b/src/input.c
@@ -753,14 +753,13 @@ weston_keyboard_set_focus(struct weston_keyboard 
*keyboard,
        wl_signal_emit(&keyboard->focus_signal, keyboard);
 }
 
+/* Users of this function must manually manage the keyboard focus */
 WL_EXPORT void
 weston_keyboard_start_grab(struct weston_keyboard *keyboard,
                           struct weston_keyboard_grab *grab)
 {
        keyboard->grab = grab;
        grab->keyboard = keyboard;
-
-       /* XXX focus? */
 }
 
 WL_EXPORT void
-- 
2.1.3

_______________________________________________
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel

Reply via email to