From 3a584414d9df972721a4fbf4b1088bce5e95484b Mon Sep 17 00:00:00 2001 From: Olivier Blin Date: Mon, 12 Oct 2015 17:27:51 +0200 Subject: Update focusResource if needed when wl_keyboard is bound If a QtWayland compositor gives focus to a surface right after its creation during the client startup, the keyboard resource may not be bound yet by the client. In this case, the surface is correctly marked as focused, but the keyboard resource is never marked as focused, and thus no keys are ever sent to the client. To fix this, the focusResource is updated if needed after wl_keyboard is bound. This can be reproduced with weston-simple-im (patched to use wl_shell instead of xdg_shell) and qml-compositor, modified to enable TextInputExtension and call takeFocus() at the end of windowAdded(). Change-Id: I551cb5bc56c05a1e5187b23108f4ef80468782dc Reviewed-by: Giulio Camuffo --- src/compositor/wayland_wrapper/qwlkeyboard.cpp | 42 +++++++++++++++++++++----- src/compositor/wayland_wrapper/qwlkeyboard_p.h | 3 ++ 2 files changed, 37 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/compositor/wayland_wrapper/qwlkeyboard.cpp b/src/compositor/wayland_wrapper/qwlkeyboard.cpp index 7520fae3f..7a5ed5f25 100644 --- a/src/compositor/wayland_wrapper/qwlkeyboard.cpp +++ b/src/compositor/wayland_wrapper/qwlkeyboard.cpp @@ -116,6 +116,30 @@ KeyboardGrabber *Keyboard::currentGrab() const return m_grab; } +void Keyboard::checkFocusResource(wl_keyboard::Resource *keyboardResource) +{ + if (!keyboardResource || !m_focus) + return; + + // this is already the current resource, do no send enter twice + if (m_focusResource == keyboardResource) + return; + + // check if new wl_keyboard resource is from the client owning the focus surface + struct ::wl_client *focusedClient = m_focus->resource()->client(); + if (focusedClient == keyboardResource->client()) { + sendEnter(m_focus, keyboardResource); + m_focusResource = keyboardResource; + } +} + +void Keyboard::sendEnter(Surface *surface, wl_keyboard::Resource *keyboardResource) +{ + uint32_t serial = wl_display_next_serial(m_compositor->wl_display()); + send_modifiers(keyboardResource->handle, serial, m_modsDepressed, m_modsLatched, m_modsLocked, m_group); + send_enter(keyboardResource->handle, serial, surface->resource()->handle, QByteArray::fromRawData((char *)m_keys.data(), m_keys.size() * sizeof(uint32_t))); +} + void Keyboard::focused(Surface *surface) { if (m_focus != surface) { @@ -132,9 +156,7 @@ void Keyboard::focused(Surface *surface) Resource *resource = surface ? resourceMap().value(surface->resource()->client()) : 0; if (resource && (m_focus != surface || m_focusResource != resource)) { - uint32_t serial = wl_display_next_serial(m_compositor->wl_display()); - send_modifiers(resource->handle, serial, m_modsDepressed, m_modsLatched, m_modsLocked, m_group); - send_enter(resource->handle, serial, surface->resource()->handle, QByteArray::fromRawData((char *)m_keys.data(), m_keys.size() * sizeof(uint32_t))); + sendEnter(surface, resource); } m_focusResource = resource; @@ -200,13 +222,17 @@ void Keyboard::keyboard_bind_resource(wl_keyboard::Resource *resource) if (m_context) { send_keymap(resource->handle, WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1, m_keymap_fd, m_keymap_size); - return; } + else #endif - int null_fd = open("/dev/null", O_RDONLY); - send_keymap(resource->handle, 0 /* WL_KEYBOARD_KEYMAP_FORMAT_NO_KEYMAP */, - null_fd, 0); - close(null_fd); + { + int null_fd = open("/dev/null", O_RDONLY); + send_keymap(resource->handle, 0 /* WL_KEYBOARD_KEYMAP_FORMAT_NO_KEYMAP */, + null_fd, 0); + close(null_fd); + } + + checkFocusResource(resource); } void Keyboard::keyboard_destroy_resource(wl_keyboard::Resource *resource) diff --git a/src/compositor/wayland_wrapper/qwlkeyboard_p.h b/src/compositor/wayland_wrapper/qwlkeyboard_p.h index e47bd2102..15185ed56 100644 --- a/src/compositor/wayland_wrapper/qwlkeyboard_p.h +++ b/src/compositor/wayland_wrapper/qwlkeyboard_p.h @@ -132,6 +132,9 @@ protected: void keyboard_release(Resource *resource) Q_DECL_OVERRIDE; private: + void checkFocusResource(wl_keyboard::Resource *resource); + void sendEnter(Surface *surface, wl_keyboard::Resource *resource); + void sendKeyEvent(uint code, uint32_t state); void focusDestroyed(void *data); -- cgit v1.2.3