WindowSystems: input event handler and input device of Wayland Input handling for...
authorNobuhiko Tanibata <ntanibata@jp.adit-jv.com>
Wed, 19 Sep 2012 02:35:48 +0000 (11:35 +0900)
committerTimo Lotterbach <timo.lotterbach@bmw-carit.de>
Thu, 22 Nov 2012 10:01:27 +0000 (02:01 -0800)
-WaylandInputDevice: provide pointer and keyboard events to WaylandWindowSystem
-WaylandX11InputDevice: Inherits WaylandInputDevice and handle input event by xcb
-WaylandInputEvent: Receive local event from WaylandWindowSysmte and send  input event via wayland protocol

LayerManagerPlugins/Renderers/Graphic/CMakeLists.txt
LayerManagerPlugins/Renderers/Graphic/include/WindowSystems/WaylandInputDevice.h [new file with mode: 0644]
LayerManagerPlugins/Renderers/Graphic/include/WindowSystems/WaylandInputEvent.h [new file with mode: 0644]
LayerManagerPlugins/Renderers/Graphic/include/WindowSystems/WaylandX11InputEvent.h [new file with mode: 0644]
LayerManagerPlugins/Renderers/Graphic/src/WindowSystems/WaylandInputDevice.cpp [new file with mode: 0644]
LayerManagerPlugins/Renderers/Graphic/src/WindowSystems/WaylandInputEvent.cpp [new file with mode: 0644]
LayerManagerPlugins/Renderers/Graphic/src/WindowSystems/WaylandX11InputEvent.cpp [new file with mode: 0644]
cmake/modules/FindWayland.cmake

index 488c5e0..7f454e1 100644 (file)
@@ -253,6 +253,7 @@ if (WITH_WAYLAND)
                 ${LIBS}
                 ${X11_X11_LIB}
                 ${WAYLAND_EGL_LIBRARIES}
+                ${XKB_LIBRARIES}
         )
         
         set(SOURCES
@@ -262,6 +263,9 @@ if (WITH_WAYLAND)
             src/WindowSystems/WaylandBaseWindowSystem.cpp
             src/WindowSystems/WaylandX11WindowSystem.cpp
             src/WindowSystems/WaylandServerinfoProtocol.cpp  
+            src/WindowSystems/WaylandInputDevice.cpp
+            src/WindowSystems/WaylandInputEvent.cpp
+            src/WindowSystems/WaylandX11InputEvent.cpp
             src/TextureBinders/WaylandGLESTexture.cpp
         )
         
diff --git a/LayerManagerPlugins/Renderers/Graphic/include/WindowSystems/WaylandInputDevice.h b/LayerManagerPlugins/Renderers/Graphic/include/WindowSystems/WaylandInputDevice.h
new file mode 100644 (file)
index 0000000..94abce4
--- /dev/null
@@ -0,0 +1,140 @@
+/***************************************************************************
+ *
+ * Copyright 2010, 2011 BMW Car IT GmbH
+ * Copyright (C) 2011 DENSO CORPORATION and Robert Bosch Car Multimedia Gmbh
+ *
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+ * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ ****************************************************************************/
+#ifndef _WAYLANDINPUTDEVICE_H_
+#define _WAYLANDINPUTDEVICE_H_
+#include <wayland-server.h>
+#include "Log.h"
+#include "config.h"
+#include "InputManager.h"
+
+//////////////////////////////////////////////////////////////////////////////
+class WaylandInputDevice
+{
+// Properties
+private:
+    struct wl_display* m_wlDisplay;
+    struct wl_seat     m_wlSeat;
+    bool               m_hasPointer;
+    bool               m_hasKeyboard;
+    bool               m_hasTouch;
+    int                m_nTp;
+
+    struct {
+        struct wl_pointer  wlPointer;
+        struct wl_keyboard wlKeyboard;
+        struct wl_touch    wlTouch;
+    } m_deviceInterfaces;
+
+// Methods
+public:
+    WaylandInputDevice(wl_display *display);
+    virtual ~WaylandInputDevice();
+
+    void initPointerDevice();
+    void initKeyboardDevice();
+    void initTouchDevice();
+
+    struct wl_seat* seat();
+    bool hasPointer() const;
+    bool hasKeyboard() const;
+    bool hasTouch() const;
+
+    struct wl_pointer  *pointerDevice();
+    struct wl_keyboard *keyboardDevice();
+    struct wl_touch    *touchDevice();
+    const struct wl_pointer  *pointerDevice() const;
+    const struct wl_keyboard *keyboardDevice() const;
+    const struct wl_touch    *touchDevice() const;
+
+    void sendMousePressEvent(const Point& globalPos, const Point& localPos,
+                             uint32_t button, uint32_t time);
+    void sendMouseReleaseEvent(const Point& globalPos, const Point& localPos,
+                               uint32_t button, uint32_t time);
+    void sendMouseMotionEvent(struct wl_surface *surface,
+                              const Point& globalPos, const Point& localPos, uint32_t time);
+
+    void sendKeyPressEvent(struct wl_surface *surface, uint32_t time, uint32_t code);
+    void sendKeyReleaseEvent(struct wl_surface *surface, uint32_t time, uint32_t code);
+    void setKeyboardFocus(struct wl_surface *surface);
+
+    void sendTouchPointEvent();
+    void sendTouchFrameEvent();
+    void sendTouchCancelEvent();
+
+private:
+    void releaseDevices();
+    void cleanupDataDeviceForClient(struct wl_client *client, bool destroyDev);
+
+    void setMouseFocus(struct wl_surface *surface,
+                       const Point& globalPos,
+                       const Point& localPos);
+    void sendMouseMotionEvent(const Point& globalPos,
+                              const Point& localPos,
+                              uint32_t time);
+
+    const static struct wl_seat_interface m_seatInterface;
+
+    static void bindInputDevice(struct wl_client *client,
+                                void *data,
+                                uint32_t version,
+                                uint32_t id);
+    static void destroyResource(struct wl_resource *resource);
+    static void destroyDeviceResource(struct wl_resource *resource);
+
+    static void getPointer(struct wl_client *client,
+                           struct wl_resource *resource,
+                           uint32_t id);
+    static void getKeyboard(struct wl_client *client,
+                            struct wl_resource *resource,
+                            uint32_t id);
+    static void getTouch(struct wl_client *client,
+                         struct wl_resource *resource,
+                         uint32_t id);
+};
+
+inline struct wl_seat* WaylandInputDevice::seat() { return &m_wlSeat; }
+inline bool WaylandInputDevice::hasPointer() const { return m_hasPointer; }
+inline bool WaylandInputDevice::hasKeyboard() const { return m_hasKeyboard; }
+inline bool WaylandInputDevice::hasTouch() const { return m_hasTouch; }
+
+inline struct wl_pointer* WaylandInputDevice::pointerDevice()
+    { return &m_deviceInterfaces.wlPointer; }
+inline struct wl_keyboard* WaylandInputDevice::keyboardDevice()
+    { return &m_deviceInterfaces.wlKeyboard; }
+inline struct wl_touch* WaylandInputDevice::touchDevice()
+    { return &m_deviceInterfaces.wlTouch; }
+
+inline const struct wl_pointer* WaylandInputDevice::pointerDevice() const
+    { return &m_deviceInterfaces.wlPointer; }
+inline const struct wl_keyboard* WaylandInputDevice::keyboardDevice() const
+    { return &m_deviceInterfaces.wlKeyboard; }
+inline const struct wl_touch* WaylandInputDevice::touchDevice() const
+    { return &m_deviceInterfaces.wlTouch; }
+
+#endif /* _WAYLANDINPUTDEVICE_H_ */
diff --git a/LayerManagerPlugins/Renderers/Graphic/include/WindowSystems/WaylandInputEvent.h b/LayerManagerPlugins/Renderers/Graphic/include/WindowSystems/WaylandInputEvent.h
new file mode 100644 (file)
index 0000000..65bb639
--- /dev/null
@@ -0,0 +1,81 @@
+/***************************************************************************
+ *
+ * Copyright 2010, 2011 BMW Car IT GmbH
+ * Copyright (C) 2011 DENSO CORPORATION and Robert Bosch Car Multimedia Gmbh
+ *
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+ * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ ****************************************************************************/
+
+#ifndef _WAYLANDINPUTEVENT_H_
+#define _WAYLANDINPUTEVENT_H_
+#include <wayland-server.h>
+#include "Log.h"
+#include "config.h"
+#include "WindowSystems/WaylandInputDevice.h"
+
+//////////////////////////////////////////////////////////////////////////////
+extern "C"
+{
+};
+
+class WaylandBaseWindowSystem;
+
+//////////////////////////////////////////////////////////////////////////////
+class WaylandInputEvent
+{
+// Properties
+protected:
+    WaylandBaseWindowSystem *m_windowSystem;
+    WaylandInputDevice      *m_inputDevice;
+    struct wl_event_source  *m_wlEventSource;
+    int m_fd;
+
+    struct xkbInfo {
+        struct xkb_keymap *keymap;
+        int                keymapFd;
+        size_t             keymapSize;
+        char              *keymapArea;
+    } m_xkbInfo;
+
+// Methods
+public:
+    WaylandInputEvent(WaylandBaseWindowSystem *windowSystem);
+    virtual ~WaylandInputEvent();
+
+    virtual void setupInputEvent();
+
+    WaylandInputDevice& inputDevice() const;
+    WaylandBaseWindowSystem& windowSystem() const;
+
+protected:
+    int createAnonymousFile(off_t size);
+
+private:
+    void initInputEvent();
+};
+
+inline WaylandInputDevice& WaylandInputEvent::inputDevice() const { return *m_inputDevice; }
+inline WaylandBaseWindowSystem& WaylandInputEvent::windowSystem() const { return *m_windowSystem; }
+
+#endif /* _WAYLANDINPUTEVENT_H_ */
diff --git a/LayerManagerPlugins/Renderers/Graphic/include/WindowSystems/WaylandX11InputEvent.h b/LayerManagerPlugins/Renderers/Graphic/include/WindowSystems/WaylandX11InputEvent.h
new file mode 100644 (file)
index 0000000..4b04162
--- /dev/null
@@ -0,0 +1,123 @@
+/***************************************************************************
+ *
+ * Copyright 2010, 2011 BMW Car IT GmbH
+ * Copyright (C) 2011 DENSO CORPORATION and Robert Bosch Car Multimedia Gmbh
+ *
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+ * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ ****************************************************************************/
+
+#ifndef _WAYLANDX11INPUTEVENT_H_
+#define _WAYLANDX11INPUTEVENT_H_
+
+#include "config.h"
+
+#define HAVE_XCB_POLL_FOR_QUEUED_EVENT 1
+
+#include <wayland-server.h>
+#include <xcb/xcb.h>
+#ifdef HAVE_XCB_XKB // XCB-XKB Extension: not required
+  #define explicit tmpexplicit
+  #include <xcb/xkb.h>
+  #undef explicit
+#endif
+#include <xkbcommon/xkbcommon.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/Xlib-xcb.h>
+
+#include "Log.h"
+#include "WindowSystems/WaylandBaseWindowSystem.h"
+
+//////////////////////////////////////////////////////////////////////////////
+extern "C"
+{
+    struct atom_ {
+        xcb_atom_t xkbNames;
+        xcb_atom_t string;
+    };
+
+    struct weston_xkb_info_ {
+        struct xkb_keymap *keymap;
+        int keymap_fd;
+        size_t keymap_size;
+        char *keymap_area;
+        xkb_mod_index_t shift_mod;
+        xkb_mod_index_t caps_mod;
+        xkb_mod_index_t ctrl_mod;
+        xkb_mod_index_t alt_mod;
+        xkb_mod_index_t mod2_mod;
+        xkb_mod_index_t mod3_mod;
+        xkb_mod_index_t super_mod;
+        xkb_mod_index_t mod5_mod;
+        xkb_led_index_t num_led;
+        xkb_led_index_t caps_led;
+        xkb_led_index_t scroll_led;
+    };
+};
+
+//////////////////////////////////////////////////////////////////////////////
+class WaylandX11InputEvent : public WaylandInputEvent
+{
+// Properties
+private:
+    Display          *m_x11Display;
+    xcb_connection_t *m_xcbConn;
+    xcb_screen_t     *m_xcbScreen;
+
+    bool              m_hasXkb;
+    uint8_t           m_xkbEventBase;
+    struct xkb_context     *m_xkbContext;
+    struct xkb_rule_names   m_xkbNames;
+    struct xkb_state       *m_xkbState;
+    struct atom_            m_atom;
+    struct weston_xkb_info_ m_xkbInfo;
+
+// Methods
+public:
+    WaylandX11InputEvent(WaylandBaseWindowSystem *windowSystem);
+    virtual ~WaylandX11InputEvent();
+
+    virtual void setupInputEvent();
+
+protected:
+private:
+    static int handleInputEvent(int fd, uint32_t mask, void *data);
+    static void updateXkbStateFromCore();
+
+    bool initXkb();
+    void setupXkb();
+    bool hasXkb();
+    struct xkb_keymap *getKeymap();
+    void createNewKeymap();
+    void buildGlobalKeymap();
+
+    xcb_connection_t *connection();
+    uint8_t xkbEventBase();
+};
+
+inline bool WaylandX11InputEvent::hasXkb() { return m_hasXkb; }
+inline xcb_connection_t* WaylandX11InputEvent::connection() { return m_xcbConn; }
+inline uint8_t WaylandX11InputEvent::xkbEventBase() { return m_xkbEventBase; }
+
+#endif /* _WAYLANDX11INPUTEVENT_H_ */
diff --git a/LayerManagerPlugins/Renderers/Graphic/src/WindowSystems/WaylandInputDevice.cpp b/LayerManagerPlugins/Renderers/Graphic/src/WindowSystems/WaylandInputDevice.cpp
new file mode 100644 (file)
index 0000000..8f4789f
--- /dev/null
@@ -0,0 +1,345 @@
+/***************************************************************************
+*
+* Copyright 2010, 2011 BMW Car IT GmbH
+* Copyright (C) 2011 DENSO CORPORATION and Robert Bosch Car Multimedia Gmbh
+*
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*        http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*
+*
+* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+* FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
+* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+* CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*
+****************************************************************************/
+#include <time.h>
+#include <sys/time.h>
+#include <sys/wait.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "WindowSystems/WaylandInputDevice.h"
+
+/////////////////////////////////////////////////////////////////////////////
+
+WaylandInputDevice::WaylandInputDevice(struct wl_display *display)
+: m_wlDisplay(display)
+, m_hasPointer(false)
+, m_hasKeyboard(false)
+, m_hasTouch(false)
+, m_nTp(0)
+{
+    wl_seat_init(&m_wlSeat);
+    wl_display_add_global(m_wlDisplay,
+                          &wl_seat_interface,
+                          this,
+                          WaylandInputDevice::bindInputDevice);
+}
+
+WaylandInputDevice::~WaylandInputDevice()
+{
+    releaseDevices();
+}
+
+void
+WaylandInputDevice::initPointerDevice()
+{
+    if (m_hasPointer)
+        return;
+
+    wl_pointer_init(&m_deviceInterfaces.wlPointer);
+    wl_seat_set_pointer(&m_wlSeat, &m_deviceInterfaces.wlPointer);
+
+    m_hasPointer = true;
+    LOG_INFO("WaylandInputDevice", "Available pointer");
+}
+
+void
+WaylandInputDevice::initKeyboardDevice()
+{
+    if (m_hasKeyboard)
+        return;
+
+    wl_keyboard_init(&m_deviceInterfaces.wlKeyboard);
+    wl_seat_set_keyboard(&m_wlSeat, &m_deviceInterfaces.wlKeyboard);
+
+    m_hasKeyboard = true;
+    LOG_INFO("WaylandInputDevice", "Available keyboard");
+}
+
+void
+WaylandInputDevice::initTouchDevice()
+{
+    if (m_hasTouch)
+        return;
+
+    wl_touch_init(&m_deviceInterfaces.wlTouch);
+    wl_seat_set_touch(&m_wlSeat, &m_deviceInterfaces.wlTouch);
+
+    m_hasTouch = true;
+    LOG_INFO("WaylandInputDevice", "Available touch");
+}
+
+void
+WaylandInputDevice::releaseDevices()
+{
+    if (m_hasPointer)
+        wl_pointer_release(&m_deviceInterfaces.wlPointer);
+
+    if (m_hasKeyboard)
+        wl_keyboard_release(&m_deviceInterfaces.wlKeyboard);
+
+    if (m_hasTouch)
+        wl_touch_release(&m_deviceInterfaces.wlTouch);
+}
+
+void
+WaylandInputDevice::cleanupDataDeviceForClient(struct wl_client *client, bool destroyDev)
+{
+}
+
+void
+WaylandInputDevice::bindInputDevice(struct wl_client *client,
+                                    void *data,
+                                    uint32_t /*version*/,
+                                    uint32_t id)
+{
+    struct wl_resource *resource =
+        wl_client_add_object(client,
+                             &wl_seat_interface,
+                             &WaylandInputDevice::m_seatInterface,
+                             id,
+                             data);
+
+    WaylandInputDevice *inputDevice = static_cast<WaylandInputDevice*>(data);
+    struct wl_seat *seat = inputDevice->seat();
+
+    resource->destroy = WaylandInputDevice::destroyResource;
+    wl_list_insert(&seat->base_resource_list, &resource->link);
+
+    uint32_t caps = 0;
+
+    if (inputDevice->hasPointer())
+        caps |= WL_SEAT_CAPABILITY_POINTER;
+    if (inputDevice->hasKeyboard())
+        caps |= WL_SEAT_CAPABILITY_KEYBOARD;
+    if (inputDevice->hasTouch())
+        caps |= WL_SEAT_CAPABILITY_TOUCH;
+
+    wl_seat_send_capabilities(resource, caps);
+}
+
+void
+WaylandInputDevice::destroyResource(struct wl_resource *resource)
+{
+    WaylandInputDevice *inputDevice = static_cast<WaylandInputDevice*>(resource->data);
+    if (inputDevice->keyboardDevice()->focus_resource == resource){
+        inputDevice->keyboardDevice()->focus_resource = 0;
+    }
+    if (inputDevice->pointerDevice()->focus_resource == resource){
+        inputDevice->pointerDevice()->focus_resource = 0;
+    }
+
+    inputDevice->cleanupDataDeviceForClient(resource->client, true);
+
+    wl_list_remove(&resource->link);
+
+    free(resource);
+}
+
+void
+WaylandInputDevice::destroyDeviceResource(struct wl_resource *resource)
+{
+    wl_list_remove(&resource->link);
+    free(resource);
+}
+
+const struct wl_seat_interface WaylandInputDevice::m_seatInterface = {
+    getPointer,
+    getKeyboard,
+    getTouch
+};
+
+void
+WaylandInputDevice::getPointer(struct wl_client *client,
+                               struct wl_resource *resource,
+                               uint32_t id)
+{
+    WaylandInputDevice *inputDevice = static_cast<WaylandInputDevice*>(resource->data);
+    wl_pointer *pointer = inputDevice->pointerDevice();
+    wl_resource *clientResource = wl_client_add_object(client,
+                                                       &wl_pointer_interface,
+                                                       0,
+                                                       id,
+                                                       pointer);
+    wl_list_insert(&pointer->resource_list, &clientResource->link);
+    clientResource->destroy = WaylandInputDevice::destroyDeviceResource;
+}
+
+void
+WaylandInputDevice::getKeyboard(struct wl_client *client,
+                                struct wl_resource *resource,
+                                uint32_t id)
+{
+    WaylandInputDevice *inputDevice = static_cast<WaylandInputDevice*>(resource->data);
+    wl_keyboard *keyboard = inputDevice->keyboardDevice();
+    wl_resource *clientResource = wl_client_add_object(client,
+                                                       &wl_keyboard_interface,
+                                                       0,
+                                                       id,
+                                                       keyboard);
+    wl_list_insert(&keyboard->resource_list, &clientResource->link);
+    clientResource->destroy = WaylandInputDevice::destroyDeviceResource;
+}
+
+void
+WaylandInputDevice::getTouch(struct wl_client *client,
+                             struct wl_resource *resource,
+                             uint32_t id)
+{
+    WaylandInputDevice *inputDevice = static_cast<WaylandInputDevice*>(resource->data);
+    wl_touch *touch = inputDevice->touchDevice();
+    wl_resource *clientResource = wl_client_add_object(client,
+                                                       &wl_touch_interface,
+                                                       0,
+                                                       id,
+                                                       touch);
+    wl_list_insert(&touch->resource_list, &clientResource->link);
+    clientResource->destroy = WaylandInputDevice::destroyDeviceResource;
+}
+
+void
+WaylandInputDevice::sendMousePressEvent(const Point& globalPos,
+                                        const Point& localPos,
+                                        uint32_t button,
+                                        uint32_t time)
+{
+    sendMouseMotionEvent(globalPos, localPos, time);
+    wl_pointer *pointer = pointerDevice();
+    pointer->button_count++;
+    const struct wl_pointer_grab_interface *interface = pointer->grab->interface;
+    interface->button(pointer->grab,
+                      time,
+                      button,
+                      WL_POINTER_BUTTON_STATE_PRESSED);
+}
+
+void
+WaylandInputDevice::sendMouseReleaseEvent(const Point& globalPos,
+                                          const Point& localPos,
+                                          uint32_t button,
+                                          uint32_t time)
+{
+    sendMouseMotionEvent(globalPos, localPos, time);
+    wl_pointer *pointer = pointerDevice();
+    pointer->button_count--;
+    const struct wl_pointer_grab_interface *interface = pointer->grab->interface;
+    interface->button(pointer->grab,
+                      time,
+                      button,
+                      WL_POINTER_BUTTON_STATE_RELEASED);
+}
+
+void
+WaylandInputDevice::sendMouseMotionEvent(struct wl_surface* surface,
+                                         const Point& globalPos,
+                                         const Point& localPos,
+                                         uint32_t time)
+{
+    setMouseFocus(surface, globalPos, localPos);
+    sendMouseMotionEvent(globalPos, localPos, time);
+}
+
+void
+WaylandInputDevice::sendMouseMotionEvent(const Point& globalPos,
+                                         const Point& localPos,
+                                         uint32_t time)
+{
+    wl_pointer *pointer = pointerDevice();
+    const struct wl_pointer_grab_interface *interface = pointer->grab->interface;
+    pointer->x = wl_fixed_from_double(globalPos.x);
+    pointer->y = wl_fixed_from_double(globalPos.y);
+    interface->motion(pointer->grab,
+                      time,
+                      wl_fixed_from_double(localPos.x),
+                      wl_fixed_from_double(localPos.y));
+}
+
+void
+WaylandInputDevice::sendKeyPressEvent(struct wl_surface* surface,
+                                      uint32_t time, uint32_t code)
+{
+    wl_keyboard *keyboard = keyboardDevice();
+    if (!keyboard->focus){
+        setKeyboardFocus(surface);
+    }
+    if (keyboard->focus_resource){
+        uint32_t serial = wl_display_next_serial(m_wlDisplay);
+        wl_keyboard_send_key(keyboard->focus_resource,
+                             serial, time, code - 8, 1);
+    }
+}
+
+void
+WaylandInputDevice::sendKeyReleaseEvent(struct wl_surface* surface,
+                                        uint32_t time, uint32_t code)
+{
+    wl_keyboard *keyboard = keyboardDevice();
+    if (keyboard->focus_resource){
+        uint32_t serial = wl_display_next_serial(m_wlDisplay);
+        wl_keyboard_send_key(keyboard->focus_resource,
+                             serial, time, code - 8, 0);
+    }
+}
+
+void
+WaylandInputDevice::sendTouchPointEvent()
+{
+}
+
+void
+WaylandInputDevice::sendTouchFrameEvent()
+{
+}
+
+void
+WaylandInputDevice::sendTouchCancelEvent()
+{
+}
+
+void
+WaylandInputDevice::setMouseFocus(struct wl_surface* surface,
+                                  const Point& globalPos,
+                                  const Point& localPos)
+{
+    wl_pointer* pointer = pointerDevice();
+    pointer->x = wl_fixed_from_double(globalPos.x);
+    pointer->y = wl_fixed_from_double(globalPos.y);
+    pointer->current = surface;
+    pointer->current_x = wl_fixed_from_double(localPos.x);
+    pointer->current_y = wl_fixed_from_double(localPos.y);
+    pointer->grab->interface->focus(pointer->grab,
+                                    surface,
+                                    wl_fixed_from_double(localPos.x),
+                                    wl_fixed_from_double(localPos.y));
+}
+
+void
+WaylandInputDevice::setKeyboardFocus(struct wl_surface* surface)
+{
+    wl_keyboard_set_focus(keyboardDevice(), surface);
+}
diff --git a/LayerManagerPlugins/Renderers/Graphic/src/WindowSystems/WaylandInputEvent.cpp b/LayerManagerPlugins/Renderers/Graphic/src/WindowSystems/WaylandInputEvent.cpp
new file mode 100644 (file)
index 0000000..aeeee6b
--- /dev/null
@@ -0,0 +1,152 @@
+/***************************************************************************
+*
+* Copyright 2010, 2011 BMW Car IT GmbH
+* Copyright (C) 2011 DENSO CORPORATION and Robert Bosch Car Multimedia Gmbh
+*
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*        http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*
+*
+* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+* FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
+* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+* CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*
+****************************************************************************/
+#include <time.h>
+#include <sys/time.h>
+#include <sys/wait.h>
+#include <linux/input.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include "WindowSystems/WaylandInputEvent.h"
+#include "WindowSystems/WaylandBaseWindowSystem.h"
+
+#define HAVE_MKOSTEMP 1
+
+/////////////////////////////////////////////////////////////////////////////
+
+static int
+setCloexecOrClose(int fd)
+{
+    long flags;
+    if (fd == -1)
+        return -1;
+
+    flags = fcntl(fd, F_GETFD);
+    if (flags == -1)
+        goto err;
+
+    if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1)
+        goto err;
+
+    return fd;
+err:
+    close(fd);
+    return -1;
+}
+
+static int
+createTmpFileCloexec(char *tmpname)
+{
+    int fd;
+#ifdef HAVE_MKOSTEMP
+    fd = mkostemp(tmpname, O_CLOEXEC);
+    if (fd >= 0){
+        unlink(tmpname);
+    }
+#else
+    fd = mkstemp(tmpname);
+    if (fd >= 0){
+        fd = setCloexecOrClose(fd);
+        unlink(tmpname);
+    }
+#endif
+    return fd;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+WaylandInputEvent::WaylandInputEvent(WaylandBaseWindowSystem *windowSystem)
+: m_windowSystem(windowSystem)
+, m_inputDevice(NULL)
+, m_wlEventSource(NULL)
+, m_fd(0)
+{
+    initInputEvent();
+}
+
+WaylandInputEvent::~WaylandInputEvent()
+{
+    if (!m_wlEventSource)
+        wl_event_source_remove(m_wlEventSource);
+}
+
+void
+WaylandInputEvent::initInputEvent()
+{
+    LOG_DEBUG("WaylandInputEvent", "initInputEvent IN");
+    m_inputDevice = new WaylandInputDevice(m_windowSystem->getNativeDisplayHandle());
+    if (!m_inputDevice){
+        LOG_ERROR("WaylandInputEvent", "Failed to create WaylandInputDevice");
+        return;
+    }
+    LOG_DEBUG("WaylandInputEvent", "initInputEvent OUT");
+}
+
+void
+WaylandInputEvent::setupInputEvent()
+{
+    LOG_ERROR("WaylandInputEvent", "Called setupInputEvent()");
+}
+
+int
+WaylandInputEvent::createAnonymousFile(off_t size)
+{
+    static const char temp[] = "/weston-shared-XXXXXX";
+    const char *path;
+    char *name;
+    int fd;
+
+    path = getenv("XDG_RUNTIME_DIR");
+    if (!path){
+        return -1;
+    }
+
+    name = (char*)malloc(strlen(path) + sizeof(temp));
+    if (!name){
+        return -1;
+    }
+
+    strcpy(name, path);
+    strcat(name, temp);
+    fd = createTmpFileCloexec(name);
+
+    free(name);
+    if (fd < 0){
+        return -1;
+    }
+
+    if (ftruncate(fd, size) < 0){
+        close(fd);
+        return -1;
+    }
+
+    return fd;
+}
diff --git a/LayerManagerPlugins/Renderers/Graphic/src/WindowSystems/WaylandX11InputEvent.cpp b/LayerManagerPlugins/Renderers/Graphic/src/WindowSystems/WaylandX11InputEvent.cpp
new file mode 100644 (file)
index 0000000..5d6035d
--- /dev/null
@@ -0,0 +1,543 @@
+/***************************************************************************
+*
+* Copyright 2010, 2011 BMW Car IT GmbH
+* Copyright (C) 2011 DENSO CORPORATION and Robert Bosch Car Multimedia Gmbh
+*
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*        http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*
+*
+* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+* FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
+* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+* CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*
+****************************************************************************/
+#include <time.h>
+#include <sys/time.h>
+#include <sys/wait.h>
+#include <sys/mman.h>
+#include <linux/input.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "WindowSystems/WaylandX11InputEvent.h"
+#include "WindowSystems/WaylandX11WindowSystem.h"
+
+extern "C"
+{
+    static int
+    x11GetNextEvent(xcb_connection_t *conn, xcb_generic_event_t **event, uint32_t mask)
+    {
+        if (mask & WL_EVENT_READABLE){
+            *event = xcb_poll_for_event(conn);
+        } else {
+#ifdef HAVE_XCB_POLL_FOR_QUEUED_EVENT
+            *event = xcb_poll_for_queued_event(conn);
+#else
+            *event = xcb_poll_for_event(conn);
+#endif
+        }
+        return *event != NULL;
+    }
+
+    static bool
+    getButtonEvent(xcb_generic_event_t *event, WLEvent *wlEvent, int /*state*/)
+    {
+        xcb_button_press_event_t *buttonEvent = (xcb_button_press_event_t*)event;
+        switch (buttonEvent->detail){
+        default:
+            wlEvent->button = buttonEvent->detail + BTN_LEFT - 1;
+            break;
+        case 2:
+            wlEvent->button = BTN_MIDDLE;
+            break;
+        case 3:
+            wlEvent->button = BTN_RIGHT;
+            break;
+        case 4:
+        case 5:
+        case 6:
+        case 7:
+            return false;
+        }
+        return true;
+    }
+};
+
+/////////////////////////////////////////////////////////////////////////////
+
+WaylandX11InputEvent::WaylandX11InputEvent(WaylandBaseWindowSystem *windowSystem)
+: WaylandInputEvent(windowSystem)
+, m_x11Display(NULL)
+, m_xcbConn(NULL)
+, m_hasXkb(false)
+, m_xkbEventBase(0)
+, m_xkbContext(NULL)
+{
+    memset(&m_xkbNames, 0x00, sizeof(m_xkbNames));
+}
+
+WaylandX11InputEvent::~WaylandX11InputEvent()
+{
+#if 0
+    // WaylandX11WindowSystem should do this
+    if (m_x11Display)
+        XCloseDisplay(m_x11Display);
+#endif
+    if (m_xkbContext)
+        xkb_context_unref(m_xkbContext);
+}
+
+#define F(field) offsetof(struct atom_, field)
+
+void
+WaylandX11InputEvent::setupInputEvent()
+{
+    LOG_DEBUG("WaylandX11InputEvent", "setupInputEvent IN");
+
+    if (!initXkb()){
+        LOG_ERROR("WaylandX11InputEvent", "ERROR: Failed to init XKB");
+        return;
+    }
+
+    WaylandX11WindowSystem* x11WindowSystem
+        = dynamic_cast<WaylandX11WindowSystem*>(m_windowSystem);
+    if (!x11WindowSystem){
+        LOG_ERROR("WaylandX11InputEvent", "Invalid window system");
+        return;
+    }
+
+    m_x11Display = x11WindowSystem->x11Display();
+    if (!m_x11Display){
+        LOG_ERROR("WaylandX11InputEvent", "ERROR: WindowSystem has not x11 display");
+        return;
+    }
+
+    m_xcbConn = XGetXCBConnection(m_x11Display);
+    XSetEventQueueOwner(m_x11Display, XCBOwnsEventQueue);
+    if (xcb_connection_has_error(m_xcbConn)){
+        LOG_ERROR("WaylandX11InputEvent", "ERROR: xcb connection has error.");
+        XCloseDisplay(m_x11Display);
+        return;
+    }
+
+    xcb_screen_iterator_t iter = xcb_setup_roots_iterator(xcb_get_setup(m_xcbConn));
+    m_xcbScreen = iter.data;
+
+    // Get resources
+    {
+        static const struct {
+            const char *name;
+            int offset;
+        } atoms[] = {
+            { "STRING",           F(string)   },
+            { "_XKB_RULES_NAMES", F(xkbNames) }
+        };
+        xcb_intern_atom_cookie_t cookies[2];
+        xcb_intern_atom_reply_t *reply;
+        unsigned int i = 0;
+        for (i = 0; i < ARRAY_LENGTH(atoms); ++i){
+            cookies[i] = xcb_intern_atom(m_xcbConn, 0,
+                                         strlen(atoms[i].name),
+                                         atoms[i].name);
+        }
+        for (i = 0; i < ARRAY_LENGTH(atoms); ++i){
+            reply = xcb_intern_atom_reply(m_xcbConn, cookies[i], NULL);
+            *(xcb_atom_t*)((char *)(&m_atom) + atoms[i].offset) = reply->atom;
+            free(reply);
+        }
+    }
+
+    // Initialize pointer device
+    m_inputDevice->initPointerDevice();
+
+    setupXkb();
+    struct xkb_keymap *keymap = getKeymap();
+    if (!keymap){
+        m_xkbInfo.keymap = xkb_map_ref(keymap);
+        createNewKeymap();
+    }
+    else {
+        buildGlobalKeymap();
+        m_xkbInfo.keymap = xkb_map_ref(m_xkbInfo.keymap);
+    }
+    m_xkbState = xkb_state_new(m_xkbInfo.keymap);
+    if (m_xkbState == NULL){
+        LOG_ERROR("WaylandX11InputEvent", "Failed to initialise XKB state");
+        return;
+    }
+
+    // Initialize keyboard device
+    m_inputDevice->initKeyboardDevice();
+    if (keymap){
+        xkb_map_unref(keymap);
+    }
+
+    // Regist event loop callback
+    m_fd = xcb_get_file_descriptor(m_xcbConn);
+    wl_event_loop *eventLoop = wl_display_get_event_loop(
+        m_windowSystem->getNativeDisplayHandle());
+    m_wlEventSource = wl_event_loop_add_fd(eventLoop,
+                                           m_fd,
+                                           WL_EVENT_READABLE,
+                                           WaylandX11InputEvent::handleInputEvent,
+                                           this);
+    wl_event_source_check(m_wlEventSource);
+
+    LOG_DEBUG("WaylandX11InputEvent", "setupInputEvent OUT");
+}
+
+bool
+WaylandX11InputEvent::initXkb()
+{
+    m_xkbContext = xkb_context_new(static_cast<xkb_context_flags>(0));
+    if (m_xkbContext == NULL){
+        LOG_ERROR("WaylandX11InputEvent", "ERROR: Failed to init XKB context");
+        return false;
+    }
+
+    // TODO: set specified configuration
+    m_xkbNames.rules  = strdup("evdev");
+    m_xkbNames.model  = strdup("pc105");
+    m_xkbNames.layout = strdup("us");
+
+    return true;
+}
+
+void
+WaylandX11InputEvent::setupXkb()
+{
+#ifndef HAVE_XCB_XKB
+    return;
+#else
+    const xcb_query_extension_reply_t *ext;
+    xcb_generic_error_t *error;
+    xcb_void_cookie_t select;
+    xcb_xkb_per_client_flags_cookie_t pcf;
+    xcb_xkb_per_client_flags_reply_t *pcf_reply;
+
+    ext = xcb_get_extension_data(m_xcbConn, &xcb_xkb_id);
+    if (!ext){
+        LOG_ERROR("WaylandX11InputEvent", "ERROR: XKB extension not available on "
+                                          "host X11 server");
+        return;
+    }
+    m_xkbEventBase = ext->first_event;
+
+    select = xcb_xkb_select_events(m_xcbConn,
+                                   XCB_XKB_ID_USE_CORE_KBD,
+                                   XCB_XKB_EVENT_TYPE_STATE_NOTIFY,
+                                   0,
+                                   XCB_XKB_EVENT_TYPE_STATE_NOTIFY,
+                                   0,
+                                   0,
+                                   NULL);
+    error = xcb_request_check(m_xcbConn, select);
+    if (error){
+        LOG_ERROR("WaylandX11InputEvent", "ERROR: Failed to select XKB state events");
+        return;
+    }
+
+    pcf = xcb_xkb_per_client_flags(m_xcbConn,
+                                   XCB_XKB_ID_USE_CORE_KBD,
+                                   XCB_XKB_PER_CLIENT_FLAG_DETECTABLE_AUTO_REPEAT,
+                                   XCB_XKB_PER_CLIENT_FLAG_DETECTABLE_AUTO_REPEAT,
+                                   0, 0, 0);
+    pcf_reply = xcb_xkb_per_client_flags_reply(m_xcbConn, pcf, &error);
+    free(pcf_reply);
+    if (error){
+        LOG_ERROR("WaylandX11InputEvent", "ERROR: Failed to set XKB per-client flags, "
+                                          "not using detectable repeat");
+        return;
+    }
+
+    m_hasXkb = true;
+#endif
+}
+
+struct xkb_keymap*
+WaylandX11InputEvent::getKeymap()
+{
+    xcb_get_property_cookie_t cookie;
+    xcb_get_property_reply_t *reply;
+    xcb_generic_error_t *error;
+    struct xkb_rule_names names;
+    struct xkb_keymap *ret;
+    char *value_all, *value_part;
+    int length_all, length_part;
+
+    memset(&names, 0x00, sizeof(names));
+
+    cookie = xcb_get_property(m_xcbConn,
+                              0,
+                              m_xcbScreen->root,
+                              m_atom.xkbNames,
+                              m_atom.string,
+                              0, 1024);
+    reply = xcb_get_property_reply(m_xcbConn, cookie, &error);
+    if (reply == NULL){
+        LOG_ERROR("WaylandX11InputEvent", "ERROR: xcb_get_property_reply");
+        return NULL;
+    }
+
+    value_all  = static_cast<char*>(xcb_get_property_value(reply));
+    length_all = xcb_get_property_value_length(reply);
+    value_part = value_all;
+
+#define copy_prop_value(to) \
+    length_part = strlen(value_part); \
+    if (value_part + length_part < (value_all + length_all) && \
+        length_part > 0) \
+        names.to = value_part; \
+    value_part += length_part + 1;
+
+    copy_prop_value(rules);
+    copy_prop_value(model);
+    copy_prop_value(layout);
+    copy_prop_value(variant);
+    copy_prop_value(options);
+#undef copy_prop_value
+
+    ret = xkb_map_new_from_names(m_xkbContext,
+                                 &names,
+                                 static_cast<xkb_map_compile_flags>(0));
+
+    free(reply);
+    return ret;
+}
+
+void
+WaylandX11InputEvent::createNewKeymap()
+{
+    m_xkbInfo.shift_mod  = xkb_map_mod_get_index(m_xkbInfo.keymap, XKB_MOD_NAME_SHIFT);
+    m_xkbInfo.caps_mod   = xkb_map_mod_get_index(m_xkbInfo.keymap, XKB_MOD_NAME_CAPS);
+    m_xkbInfo.ctrl_mod   = xkb_map_mod_get_index(m_xkbInfo.keymap, XKB_MOD_NAME_CTRL);
+    m_xkbInfo.alt_mod    = xkb_map_mod_get_index(m_xkbInfo.keymap, XKB_MOD_NAME_ALT);
+    m_xkbInfo.mod2_mod   = xkb_map_mod_get_index(m_xkbInfo.keymap, "Mod2");
+    m_xkbInfo.mod3_mod   = xkb_map_mod_get_index(m_xkbInfo.keymap, "Mod3");
+    m_xkbInfo.super_mod  = xkb_map_mod_get_index(m_xkbInfo.keymap, XKB_MOD_NAME_LOGO);
+    m_xkbInfo.mod5_mod   = xkb_map_mod_get_index(m_xkbInfo.keymap, "Mod5");
+    m_xkbInfo.num_led    = xkb_map_led_get_index(m_xkbInfo.keymap, XKB_LED_NAME_NUM);
+    m_xkbInfo.caps_led   = xkb_map_led_get_index(m_xkbInfo.keymap, XKB_LED_NAME_CAPS);
+    m_xkbInfo.scroll_led = xkb_map_led_get_index(m_xkbInfo.keymap, XKB_LED_NAME_SCROLL);
+
+    char *keymapStr = xkb_map_get_as_string(m_xkbInfo.keymap);
+    if (keymapStr == NULL){
+        LOG_ERROR("WaylandX11InputEvent", "Failed to get string version of keymap");
+        return;
+    }
+    m_xkbInfo.keymap_size = strlen(keymapStr) + 1;
+
+    m_xkbInfo.keymap_fd = createAnonymousFile(m_xkbInfo.keymap_size);
+    if (m_xkbInfo.keymap_fd < 0){
+        LOG_WARNING("WaylandX11InputEvent", "Creating a keymap file for " <<
+                    (unsigned long)m_xkbInfo.keymap_size <<
+                    " bytes failed");
+        goto err_keymapStr;
+    }
+
+    m_xkbInfo.keymap_area = (char*)mmap(NULL,
+                                        m_xkbInfo.keymap_size,
+                                        PROT_READ | PROT_WRITE,
+                                        MAP_SHARED,
+                                        m_xkbInfo.keymap_fd,
+                                        0);
+    if (m_xkbInfo.keymap_area == MAP_FAILED){
+        LOG_WARNING("WaylandX11InputEvent", "Failed to mmap() " <<
+                    (unsigned long) m_xkbInfo.keymap_size <<
+                    " bytes");
+        goto err_dev_zero;
+    }
+    strcpy(m_xkbInfo.keymap_area, keymapStr);
+    free(keymapStr);
+
+    return;
+
+err_dev_zero:
+    close(m_xkbInfo.keymap_fd);
+    m_xkbInfo.keymap_fd = -1;
+
+err_keymapStr:
+    free(keymapStr);
+    exit(EXIT_FAILURE);
+}
+
+void
+WaylandX11InputEvent::buildGlobalKeymap()
+{
+    if (m_xkbInfo.keymap != NULL)
+        return;
+
+    m_xkbInfo.keymap = xkb_map_new_from_names(m_xkbContext,
+                                              &m_xkbNames,
+                                              static_cast<xkb_map_compile_flags>(0));
+    if (m_xkbInfo.keymap == NULL){
+        LOG_ERROR("WaylandX11InputEvent", "Failed to compile global XKB keymap");
+        LOG_ERROR("WaylandX11InputEvent", "  tried rules: " << m_xkbNames.rules <<
+                                          ", model: "       << m_xkbNames.model <<
+                                          ", layout: "      << m_xkbNames.layout);
+        return;
+    }
+
+    createNewKeymap();
+}
+
+int
+WaylandX11InputEvent::handleInputEvent(int /*fd*/, uint32_t mask, void *data)
+{
+    LOG_DEBUG("WaylandX11InputEvent", "handleInputEvent IN");
+
+    WaylandX11InputEvent *ins = static_cast<WaylandX11InputEvent*>(data);
+    WLEvent                    wlEvent;
+    xcb_generic_event_t       *event;
+    xcb_motion_notify_event_t *motionNotify;
+    xcb_button_press_event_t  *buttonEvent;
+    xcb_key_press_event_t     *keyPress, *keyRelease;
+    InputDevice                deviceType = INPUT_DEVICE_POINTER;
+    InputEventState            state      = INPUT_STATE_MOTION;
+
+    int count = 0;
+    xcb_generic_event_t *prev = NULL;
+    while (x11GetNextEvent(ins->connection(), &event, mask)){
+        switch (prev ? prev->response_type & ~0x80 : 0x80){
+        case XCB_KEY_RELEASE:
+            keyRelease = (xcb_key_press_event_t*)prev;
+            keyPress   = (xcb_key_press_event_t*)event;
+            if ((event->response_type & ~0x80) == XCB_KEY_PRESS &&
+                keyRelease->time == keyPress->time &&
+                keyRelease->detail == keyPress->detail){
+                // Don't deliver the held key release event or
+                // the new key press even.
+                free(event);
+                free(prev);
+                prev = NULL;
+                continue;
+            } else {
+                free(prev);
+                prev = NULL;
+                break;
+            }
+        case XCB_FOCUS_IN:
+            free(prev);
+            prev = NULL;
+            break;
+        default:
+            // No previous event held
+            break;
+        }
+
+        memset(&wlEvent, 0x00, sizeof(WLEvent));
+
+        switch (event->response_type & ~0x80){
+        case XCB_KEY_PRESS:
+            LOG_DEBUG("WaylandX11InputEvent", "[EVENT] XCB_KEY_PRESS");
+            keyPress = (xcb_key_press_event_t *)event;
+            wlEvent.keyCode  = keyPress->detail - 8;
+            wlEvent.keyState = WL_KEYBOARD_KEY_STATE_PRESSED;
+
+            deviceType = INPUT_DEVICE_KEYBOARD;
+            state      = INPUT_STATE_PRESSED;
+            break;
+        case XCB_KEY_RELEASE:
+            LOG_DEBUG("WaylandX11InputEvent", "[EVENT] XCB_KEY_RELEASE");
+            keyRelease = (xcb_key_press_event_t *)event;
+            wlEvent.keyCode = keyRelease->detail - 8;
+            wlEvent.keyState = WL_KEYBOARD_KEY_STATE_RELEASED;
+
+            deviceType = INPUT_DEVICE_KEYBOARD;
+            state      = INPUT_STATE_RELEASED;
+            break;
+        case XCB_BUTTON_PRESS:
+            LOG_DEBUG("WaylandX11InputEvent", "[EVENT] XCB_BUTTON_PRESS");
+            if (!getButtonEvent(event, &wlEvent, 1)){
+                continue; // not supported button event
+            }
+            buttonEvent = (xcb_button_press_event_t *)event;
+            wlEvent.x = buttonEvent->event_x;
+            wlEvent.y = buttonEvent->event_y;
+            wlEvent.buttonState = WL_POINTER_BUTTON_STATE_PRESSED;
+
+            deviceType = INPUT_DEVICE_POINTER;
+            state      = INPUT_STATE_PRESSED;
+            break;
+        case XCB_BUTTON_RELEASE:
+            LOG_DEBUG("WaylandX11InputEvent", "[EVENT] XCB_BUTTON_RELEASE");
+            if (!getButtonEvent(event, &wlEvent, 0)){
+                continue; // not suported button event
+            }
+            buttonEvent = (xcb_button_press_event_t *)event;
+            wlEvent.x = buttonEvent->event_x;
+            wlEvent.y = buttonEvent->event_y;
+            wlEvent.buttonState = WL_POINTER_BUTTON_STATE_RELEASED;
+
+            deviceType = INPUT_DEVICE_POINTER;
+            state      = INPUT_STATE_RELEASED;
+            break;
+        case XCB_MOTION_NOTIFY:
+            LOG_DEBUG("WaylandX11InputEvent", "[EVENT] XCB_MOTION_NOTIFY");
+            motionNotify = (xcb_motion_notify_event_t *)event;
+            wlEvent.x = motionNotify->event_x;
+            wlEvent.y = motionNotify->event_y;
+
+            deviceType = INPUT_DEVICE_POINTER;
+            state      = INPUT_STATE_MOTION;
+            break;
+        case XCB_EXPOSE:
+        case XCB_ENTER_NOTIFY:
+        case XCB_LEAVE_NOTIFY:
+        case XCB_CLIENT_MESSAGE:
+        case XCB_FOCUS_OUT:
+        default:
+            LOG_DEBUG("WaylandX11InputEvent", "[EVENT] Not supported (" <<
+                      (event->response_type & ~0x80) << ")");
+            if (prev != event){
+                free(event);
+            }
+            continue;
+        }
+
+        ++count;
+        if (prev != event){
+            free(event);
+        }
+    }
+
+    if (count == 0){
+        goto rtn;
+    }
+
+    switch (prev ? prev->response_type & ~0x80 : 0x80){
+    case XCB_KEY_RELEASE:
+        keyRelease = (xcb_key_press_event_t*)prev;
+        wlEvent.keyCode  = keyRelease->detail - 8;
+        wlEvent.keyState = WL_KEYBOARD_KEY_STATE_RELEASED;
+        deviceType = INPUT_DEVICE_KEYBOARD;
+        state      = INPUT_STATE_RELEASED;
+        free(prev);
+        prev = NULL;
+        break;
+    default:
+        break;
+    }
+
+    ins->windowSystem().manageWLInputEvent(deviceType, state, &wlEvent);
+
+rtn:
+    LOG_DEBUG("WaylandX11InputEvent", "handleInputEvent OUT");
+    return count;
+}
index d82177a..da8bf42 100644 (file)
@@ -50,6 +50,15 @@ NAMES ffi
 PATHS /usr/lib /usr/local/lib
 )
 
+FIND_PATH(XKB_INCLUDE_DIR /xkbcommon.h
+/usr/include/xkbcommon /usr/local/include/xkbcommon
+)
+
+FIND_LIBRARY(XKB_LIBRARIES
+NAMES xkbcommon
+PATHS /usr/lib /usr/local/lib
+)
+
 SET( WAYLAND_FOUND "NO" )
 IF(WAYLAND_CLIENT_LIBRARIES AND WAYLAND_SERVER_LIBRARIES)
     SET( WAYLAND_FOUND "YES" )
@@ -60,6 +69,8 @@ IF(WAYLAND_CLIENT_LIBRARIES AND WAYLAND_SERVER_LIBRARIES)
     message(STATUS "Found Wayland-Egl libs: ${WAYLAND_EGL_LIBRARIES}")
     message(STATUS "Found ffi need by Wayland libs: ${FFI_LIBRARIES}")
     message(STATUS "Found ffi need by Wayland includes: ${FFI_INCLUDE_DIR}")
+    message(STATUS "Found xkbcommon need by Wayland libs: ${XKB_LIBRARIES}")
+    message(STATUS "Found xkbcommon need by Wayland includes: ${XKB_INCLUDE_DIR}")
 ENDIF(WAYLAND_CLIENT_LIBRARIES AND WAYLAND_SERVER_LIBRARIES)
 
 MARK_AS_ADVANCED(
@@ -70,4 +81,6 @@ MARK_AS_ADVANCED(
   WAYLAND_EGL_LIBRARIES
   FFI_INCLUDE_DIR
   FFI_LIBRARIES
+  XKB_LIBRARIES
+  XKB_INCLUDE_DIR
 )