Commit 3a584414 authored by Olivier Blin's avatar Olivier Blin Committed by Olivier Blin
Browse files

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: default avatarGiulio Camuffo <giulio.camuffo@jollamobile.com>
Showing with 37 additions and 8 deletions
...@@ -116,6 +116,30 @@ KeyboardGrabber *Keyboard::currentGrab() const ...@@ -116,6 +116,30 @@ KeyboardGrabber *Keyboard::currentGrab() const
return m_grab; 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) void Keyboard::focused(Surface *surface)
{ {
if (m_focus != surface) { if (m_focus != surface) {
...@@ -132,9 +156,7 @@ void Keyboard::focused(Surface *surface) ...@@ -132,9 +156,7 @@ void Keyboard::focused(Surface *surface)
Resource *resource = surface ? resourceMap().value(surface->resource()->client()) : 0; Resource *resource = surface ? resourceMap().value(surface->resource()->client()) : 0;
if (resource && (m_focus != surface || m_focusResource != resource)) { if (resource && (m_focus != surface || m_focusResource != resource)) {
uint32_t serial = wl_display_next_serial(m_compositor->wl_display()); sendEnter(surface, resource);
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)));
} }
m_focusResource = resource; m_focusResource = resource;
...@@ -200,13 +222,17 @@ void Keyboard::keyboard_bind_resource(wl_keyboard::Resource *resource) ...@@ -200,13 +222,17 @@ void Keyboard::keyboard_bind_resource(wl_keyboard::Resource *resource)
if (m_context) { if (m_context) {
send_keymap(resource->handle, WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1, send_keymap(resource->handle, WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1,
m_keymap_fd, m_keymap_size); m_keymap_fd, m_keymap_size);
return;
} }
else
#endif #endif
int null_fd = open("/dev/null", O_RDONLY); {
send_keymap(resource->handle, 0 /* WL_KEYBOARD_KEYMAP_FORMAT_NO_KEYMAP */, int null_fd = open("/dev/null", O_RDONLY);
null_fd, 0); send_keymap(resource->handle, 0 /* WL_KEYBOARD_KEYMAP_FORMAT_NO_KEYMAP */,
close(null_fd); null_fd, 0);
close(null_fd);
}
checkFocusResource(resource);
} }
void Keyboard::keyboard_destroy_resource(wl_keyboard::Resource *resource) void Keyboard::keyboard_destroy_resource(wl_keyboard::Resource *resource)
......
...@@ -132,6 +132,9 @@ protected: ...@@ -132,6 +132,9 @@ protected:
void keyboard_release(Resource *resource) Q_DECL_OVERRIDE; void keyboard_release(Resource *resource) Q_DECL_OVERRIDE;
private: private:
void checkFocusResource(wl_keyboard::Resource *resource);
void sendEnter(Surface *surface, wl_keyboard::Resource *resource);
void sendKeyEvent(uint code, uint32_t state); void sendKeyEvent(uint code, uint32_t state);
void focusDestroyed(void *data); void focusDestroyed(void *data);
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment