From 3a584414d9df972721a4fbf4b1088bce5e95484b Mon Sep 17 00:00:00 2001
From: Olivier Blin <olivier.blin@softathome.com>
Date: Mon, 12 Oct 2015 17:27:51 +0200
Subject: [PATCH] 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 <giulio.camuffo@jollamobile.com>
---
 .../wayland_wrapper/qwlkeyboard.cpp           | 42 +++++++++++++++----
 .../wayland_wrapper/qwlkeyboard_p.h           |  3 ++
 2 files changed, 37 insertions(+), 8 deletions(-)

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);
 
-- 
GitLab