Implement keyboard auto-repeat
[qt:qtwayland.git] / src / plugins / platforms / wayland_common / qwaylandinputdevice.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the plugins of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia.  For licensing terms and
14 ** conditions see http://qt.digia.com/licensing.  For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file.  Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights.  These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file.  Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "qwaylandinputdevice.h"
43
44 #include "qwaylandintegration.h"
45 #include "qwaylandwindow.h"
46 #include "qwaylandbuffer.h"
47 #include "qwaylanddatadevice.h"
48 #include "qwaylanddatadevicemanager.h"
49 #include "qwaylandtouch.h"
50 #include "qwaylandscreen.h"
51 #include "qwaylandcursor.h"
52
53 #include <QtGui/private/qpixmap_raster_p.h>
54 #include <qpa/qplatformwindow.h>
55 #include <QDebug>
56
57 #include <unistd.h>
58 #include <fcntl.h>
59 #include <sys/mman.h>
60
61 #include <wayland-cursor.h>
62
63 #include <QtGui/QGuiApplication>
64
65 #ifndef QT_NO_WAYLAND_XKB
66 #include <xkbcommon/xkbcommon.h>
67 #include <X11/keysym.h>
68 #endif
69
70 QT_BEGIN_NAMESPACE
71
72 QWaylandInputDevice::QWaylandInputDevice(QWaylandDisplay *display, uint32_t id)
73     : QObject()
74     , QtWayland::wl_seat(display->wl_registry(), id)
75     , mQDisplay(display)
76     , mDisplay(display->wl_display())
77     , mFocusCallback(0)
78     , mCaps(0)
79     , mDataDevice(0)
80     , mPointerFocus(0)
81     , mKeyboardFocus(0)
82     , mTouchFocus(0)
83     , mButtons(0)
84     , mTime(0)
85     , mSerial(0)
86     , mEnterSerial(0)
87     , mCursorSerial(0)
88     , mTouchDevice(0)
89     #ifndef QT_NO_WAYLAND_XKB
90     , mXkbContext(0)
91     , mXkbMap(0)
92     , mXkbState(0)
93     #endif
94 {
95 #ifndef QT_NO_WAYLAND_XKB
96     xkb_rule_names names;
97     names.rules = strdup("evdev");
98     names.model = strdup("pc105");
99     names.layout = strdup("us");
100     names.variant = strdup("");
101     names.options = strdup("");
102
103     mXkbContext = xkb_context_new(xkb_context_flags(0));
104     if (mXkbContext) {
105         mXkbMap = xkb_map_new_from_names(mXkbContext, &names, xkb_map_compile_flags(0));
106         if (mXkbMap) {
107             mXkbState = xkb_state_new(mXkbMap);
108         }
109     }
110
111     if (!mXkbContext || !mXkbMap || !mXkbState)
112         qWarning() << "xkb_map_new_from_names failed, no key input";
113 #endif
114
115     if (mQDisplay->dndSelectionHandler()) {
116         mDataDevice = mQDisplay->dndSelectionHandler()->getDataDevice(this);
117     }
118
119     connect(&mRepeatTimer, SIGNAL(timeout()), this, SLOT(repeatKey()));
120 }
121
122 QWaylandInputDevice::~QWaylandInputDevice()
123 {
124 #ifndef QT_NO_WAYLAND_XKB
125     if (mXkbState)
126         xkb_state_unref(mXkbState);
127     if (mXkbMap)
128         xkb_map_unref(mXkbMap);
129     if (mXkbContext)
130         xkb_context_unref(mXkbContext);
131 #endif
132 }
133
134 void QWaylandInputDevice::seat_capabilities(uint32_t caps)
135 {
136     mCaps = caps;
137
138     if (caps & WL_SEAT_CAPABILITY_KEYBOARD)
139         QtWayland::wl_keyboard::init(get_keyboard());
140
141     if (caps & WL_SEAT_CAPABILITY_POINTER) {
142         QtWayland::wl_pointer::init(get_pointer());
143         pointerSurface = mQDisplay->createSurface(this);
144     }
145
146     if (caps & WL_SEAT_CAPABILITY_TOUCH) {
147         QtWayland::wl_touch::init(get_touch());
148
149         if (!mTouchDevice) {
150             mTouchDevice = new QTouchDevice;
151             mTouchDevice->setType(QTouchDevice::TouchScreen);
152             mTouchDevice->setCapabilities(QTouchDevice::Position);
153             QWindowSystemInterface::registerTouchDevice(mTouchDevice);
154         }
155     }
156 }
157
158 void QWaylandInputDevice::handleWindowDestroyed(QWaylandWindow *window)
159 {
160     if (window == mPointerFocus)
161         mPointerFocus = 0;
162     if (window == mKeyboardFocus) {
163         mKeyboardFocus = 0;
164         mRepeatTimer.stop();
165     }
166 }
167
168 void QWaylandInputDevice::setDataDevice(QWaylandDataDevice *device)
169 {
170     mDataDevice = device;
171 }
172
173 QWaylandDataDevice *QWaylandInputDevice::dataDevice() const
174 {
175     Q_ASSERT(mDataDevice);
176     return mDataDevice;
177 }
178
179 void QWaylandInputDevice::removeMouseButtonFromState(Qt::MouseButton button)
180 {
181     mButtons = mButtons & !button;
182 }
183
184 QWaylandWindow *QWaylandInputDevice::pointerFocus() const
185 {
186     return mPointerFocus;
187 }
188
189 Qt::KeyboardModifiers QWaylandInputDevice::modifiers() const
190 {
191     Qt::KeyboardModifiers ret = Qt::NoModifier;
192
193 #ifndef QT_NO_WAYLAND_XKB
194     xkb_state_component cstate = static_cast<xkb_state_component>(XKB_STATE_DEPRESSED | XKB_STATE_LATCHED);
195
196     if (xkb_state_mod_name_is_active(mXkbState, "Shift", cstate))
197         ret |= Qt::ShiftModifier;
198     if (xkb_state_mod_name_is_active(mXkbState, "Control", cstate))
199         ret |= Qt::ControlModifier;
200     if (xkb_state_mod_name_is_active(mXkbState, "Alt", cstate))
201         ret |= Qt::AltModifier;
202     if (xkb_state_mod_name_is_active(mXkbState, "Mod1", cstate))
203         ret |= Qt::AltModifier;
204     if (xkb_state_mod_name_is_active(mXkbState, "Mod4", cstate))
205         ret |= Qt::MetaModifier;
206 #endif
207
208     return ret;
209 }
210
211 void QWaylandInputDevice::setCursor(Qt::CursorShape newShape, QWaylandScreen *screen)
212 {
213     struct wl_cursor_image *image = screen->waylandCursor()->cursorImage(newShape);
214     if (!image) {
215         return;
216     }
217
218     struct wl_buffer *buffer = wl_cursor_image_get_buffer(image);
219     setCursor(buffer, image);
220 }
221
222 void QWaylandInputDevice::setCursor(struct wl_buffer *buffer, struct wl_cursor_image *image)
223 {
224     if (mCaps & WL_SEAT_CAPABILITY_POINTER) {
225         mCursorSerial = mEnterSerial;
226         /* Hide cursor */
227         if (!buffer)
228         {
229             set_cursor(mEnterSerial, NULL, 0, 0);
230             return;
231         }
232
233         set_cursor(mEnterSerial, pointerSurface,
234                    image->hotspot_x, image->hotspot_y);
235         wl_surface_attach(pointerSurface, buffer, 0, 0);
236         wl_surface_damage(pointerSurface, 0, 0, image->width, image->height);
237         wl_surface_commit(pointerSurface);
238     }
239 }
240
241 void QWaylandInputDevice::pointer_enter(uint32_t serial, struct wl_surface *surface,
242                                         wl_fixed_t sx, wl_fixed_t sy)
243 {
244     Q_UNUSED(sx);
245     Q_UNUSED(sy);
246
247     if (!surface)
248         return;
249
250     QWaylandWindow *window = QWaylandWindow::fromWlSurface(surface);
251     window->window()->setCursor(window->window()->cursor());
252
253     mPointerFocus = window;
254
255     mTime = QWaylandDisplay::currentTimeMillisec();
256     mSerial = serial;
257     mEnterSerial = serial;
258
259     QWaylandWindow *grab = QWaylandWindow::mouseGrab();
260     if (!grab) {
261         window->handleMouseEnter(this);
262         window->handleMouse(this, mTime, mSurfacePos, mGlobalPos, mButtons, Qt::NoModifier);
263     }
264 }
265
266 void QWaylandInputDevice::pointer_leave(uint32_t time, struct wl_surface *surface)
267 {
268     // The event may arrive after destroying the window, indicated by
269     // a null surface.
270     if (!surface)
271         return;
272
273     if (!QWaylandWindow::mouseGrab()) {
274         QWaylandWindow *window = QWaylandWindow::fromWlSurface(surface);
275         window->handleMouseLeave(this);
276     }
277     mPointerFocus = 0;
278     mButtons = Qt::NoButton;
279
280     mTime = time;
281 }
282
283 void QWaylandInputDevice::pointer_motion(uint32_t time, wl_fixed_t surface_x, wl_fixed_t surface_y)
284 {
285     Q_UNUSED(surface_x);
286     Q_UNUSED(surface_y);
287
288     QWaylandWindow *window = mPointerFocus;
289
290     if (window == NULL) {
291         // We destroyed the pointer focus surface, but the server
292         // didn't get the message yet.
293         return;
294     }
295
296     QPointF pos(wl_fixed_to_double(surface_x), wl_fixed_to_double(surface_y));
297     QPointF delta = pos - pos.toPoint();
298     QPointF global = window->window()->mapToGlobal(pos.toPoint());
299     global += delta;
300
301     mSurfacePos = pos;
302     mGlobalPos = global;
303     mTime = time;
304
305     QWaylandWindow *grab = QWaylandWindow::mouseGrab();
306     if (grab && grab != window) {
307         // We can't know the true position since we're getting events for another surface,
308         // so we just set it outside of the window boundaries.
309         pos = QPointF(-1, -1);
310         global = grab->window()->mapToGlobal(pos.toPoint());
311         grab->handleMouse(this, time, pos, global, mButtons, Qt::NoModifier);
312     } else
313         window->handleMouse(this, time, mSurfacePos, mGlobalPos, mButtons, Qt::NoModifier);
314 }
315
316 void QWaylandInputDevice::pointer_button(uint32_t serial, uint32_t time,
317                                          uint32_t button, uint32_t state)
318 {
319     Q_UNUSED(serial);
320     QWaylandWindow *window = mPointerFocus;
321     Qt::MouseButton qt_button;
322
323     // translate from kernel (input.h) 'button' to corresponding Qt:MouseButton.
324     // The range of mouse values is 0x110 <= mouse_button < 0x120, the first Joystick button.
325     switch (button) {
326     case 0x110: qt_button = Qt::LeftButton; break;    // kernel BTN_LEFT
327     case 0x111: qt_button = Qt::RightButton; break;
328     case 0x112: qt_button = Qt::MiddleButton; break;
329     case 0x113: qt_button = Qt::ExtraButton1; break;  // AKA Qt::BackButton
330     case 0x114: qt_button = Qt::ExtraButton2; break;  // AKA Qt::ForwardButton
331     case 0x115: qt_button = Qt::ExtraButton3; break;  // AKA Qt::TaskButton
332     case 0x116: qt_button = Qt::ExtraButton4; break;
333     case 0x117: qt_button = Qt::ExtraButton5; break;
334     case 0x118: qt_button = Qt::ExtraButton6; break;
335     case 0x119: qt_button = Qt::ExtraButton7; break;
336     case 0x11a: qt_button = Qt::ExtraButton8; break;
337     case 0x11b: qt_button = Qt::ExtraButton9; break;
338     case 0x11c: qt_button = Qt::ExtraButton10; break;
339     case 0x11d: qt_button = Qt::ExtraButton11; break;
340     case 0x11e: qt_button = Qt::ExtraButton12; break;
341     case 0x11f: qt_button = Qt::ExtraButton13; break;
342     default: return; // invalid button number (as far as Qt is concerned)
343     }
344
345     if (state)
346         mButtons |= qt_button;
347     else
348         mButtons &= ~qt_button;
349
350     mTime = time;
351     mSerial = serial;
352
353     QWaylandWindow *grab = QWaylandWindow::mouseGrab();
354     if (grab && grab != mPointerFocus) {
355         QPointF pos = QPointF(-1, -1);
356         QPointF global = grab->window()->mapToGlobal(pos.toPoint());
357         grab->handleMouse(this, time, pos, global, mButtons, Qt::NoModifier);
358     } else if (window)
359         window->handleMouse(this, time, mSurfacePos, mGlobalPos, mButtons, Qt::NoModifier);
360 }
361
362 void QWaylandInputDevice::pointer_axis(uint32_t time, uint32_t axis, int32_t value)
363 {
364     QWaylandWindow *window = mPointerFocus;
365     QPoint pixelDelta;
366     QPoint angleDelta;
367
368     //normalize value and inverse axis
369     int valueDelta = wl_fixed_to_int(value) * -12;
370
371     if (axis == WL_POINTER_AXIS_HORIZONTAL_SCROLL) {
372         pixelDelta = QPoint();
373         angleDelta.setX(valueDelta);
374     } else {
375         pixelDelta = QPoint();
376         angleDelta.setY(valueDelta);
377     }
378
379     QWindowSystemInterface::handleWheelEvent(window->window(),
380                                              time, mSurfacePos,
381                                              mGlobalPos, pixelDelta,
382                                              angleDelta);
383 }
384
385 #ifndef QT_NO_WAYLAND_XKB
386
387 static const uint32_t KeyTbl[] = {
388     XK_Escape,                  Qt::Key_Escape,
389     XK_Tab,                     Qt::Key_Tab,
390     XK_ISO_Left_Tab,            Qt::Key_Backtab,
391     XK_BackSpace,               Qt::Key_Backspace,
392     XK_Return,                  Qt::Key_Return,
393     XK_Insert,                  Qt::Key_Insert,
394     XK_Delete,                  Qt::Key_Delete,
395     XK_Clear,                   Qt::Key_Delete,
396     XK_Pause,                   Qt::Key_Pause,
397     XK_Print,                   Qt::Key_Print,
398
399     XK_Home,                    Qt::Key_Home,
400     XK_End,                     Qt::Key_End,
401     XK_Left,                    Qt::Key_Left,
402     XK_Up,                      Qt::Key_Up,
403     XK_Right,                   Qt::Key_Right,
404     XK_Down,                    Qt::Key_Down,
405     XK_Prior,                   Qt::Key_PageUp,
406     XK_Next,                    Qt::Key_PageDown,
407
408     XK_Shift_L,                 Qt::Key_Shift,
409     XK_Shift_R,                 Qt::Key_Shift,
410     XK_Shift_Lock,              Qt::Key_Shift,
411     XK_Control_L,               Qt::Key_Control,
412     XK_Control_R,               Qt::Key_Control,
413     XK_Meta_L,                  Qt::Key_Meta,
414     XK_Meta_R,                  Qt::Key_Meta,
415     XK_Alt_L,                   Qt::Key_Alt,
416     XK_Alt_R,                   Qt::Key_Alt,
417     XK_Caps_Lock,               Qt::Key_CapsLock,
418     XK_Num_Lock,                Qt::Key_NumLock,
419     XK_Scroll_Lock,             Qt::Key_ScrollLock,
420     XK_Super_L,                 Qt::Key_Super_L,
421     XK_Super_R,                 Qt::Key_Super_R,
422     XK_Menu,                    Qt::Key_Menu,
423     XK_Hyper_L,                 Qt::Key_Hyper_L,
424     XK_Hyper_R,                 Qt::Key_Hyper_R,
425     XK_Help,                    Qt::Key_Help,
426
427     XK_KP_Space,                Qt::Key_Space,
428     XK_KP_Tab,                  Qt::Key_Tab,
429     XK_KP_Enter,                Qt::Key_Enter,
430     XK_KP_Home,                 Qt::Key_Home,
431     XK_KP_Left,                 Qt::Key_Left,
432     XK_KP_Up,                   Qt::Key_Up,
433     XK_KP_Right,                Qt::Key_Right,
434     XK_KP_Down,                 Qt::Key_Down,
435     XK_KP_Prior,                Qt::Key_PageUp,
436     XK_KP_Next,                 Qt::Key_PageDown,
437     XK_KP_End,                  Qt::Key_End,
438     XK_KP_Begin,                Qt::Key_Clear,
439     XK_KP_Insert,               Qt::Key_Insert,
440     XK_KP_Delete,               Qt::Key_Delete,
441     XK_KP_Equal,                Qt::Key_Equal,
442     XK_KP_Multiply,             Qt::Key_Asterisk,
443     XK_KP_Add,                  Qt::Key_Plus,
444     XK_KP_Separator,            Qt::Key_Comma,
445     XK_KP_Subtract,             Qt::Key_Minus,
446     XK_KP_Decimal,              Qt::Key_Period,
447     XK_KP_Divide,               Qt::Key_Slash,
448
449     XK_ISO_Level3_Shift,        Qt::Key_AltGr,
450     XK_Multi_key,               Qt::Key_Multi_key,
451     XK_Codeinput,               Qt::Key_Codeinput,
452     XK_SingleCandidate,         Qt::Key_SingleCandidate,
453     XK_MultipleCandidate,       Qt::Key_MultipleCandidate,
454     XK_PreviousCandidate,       Qt::Key_PreviousCandidate,
455
456     XK_Mode_switch,             Qt::Key_Mode_switch,
457     XK_script_switch,           Qt::Key_Mode_switch,
458
459     0,                          0
460 };
461
462 static int keysymToQtKey(xkb_keysym_t key)
463 {
464     int code = 0;
465     int i = 0;
466     while (KeyTbl[i]) {
467         if (key == KeyTbl[i]) {
468             code = (int)KeyTbl[i+1];
469             break;
470         }
471         i += 2;
472     }
473
474     return code;
475 }
476
477 static int keysymToQtKey(xkb_keysym_t keysym, Qt::KeyboardModifiers &modifiers, const QString &text)
478 {
479     int code = 0;
480
481     if (keysym >= XKB_KEY_F1 && keysym <= XKB_KEY_F35) {
482         code =  Qt::Key_F1 + (int(keysym) - XKB_KEY_F1);
483     } else if (keysym >= XKB_KEY_KP_Space && keysym <= XKB_KEY_KP_9) {
484         if (keysym >= XKB_KEY_KP_0) {
485             // numeric keypad keys
486             code = Qt::Key_0 + ((int)keysym - XKB_KEY_KP_0);
487         } else {
488             code = keysymToQtKey(keysym);
489         }
490         modifiers |= Qt::KeypadModifier;
491     } else if (text.length() == 1 && text.unicode()->unicode() > 0x1f
492         && text.unicode()->unicode() != 0x7f
493         && !(keysym >= XKB_KEY_dead_grave && keysym <= XKB_KEY_dead_currency)) {
494         code = text.unicode()->toUpper().unicode();
495     } else {
496         // any other keys
497         code = keysymToQtKey(keysym);
498     }
499
500     return code;
501 }
502
503 #endif // QT_NO_WAYLAND_XKB
504
505 void QWaylandInputDevice::keyboard_keymap(uint32_t format, int32_t fd, uint32_t size)
506 {
507 #ifndef QT_NO_WAYLAND_XKB
508     if (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1) {
509         close(fd);
510         return;
511     }
512
513     char *map_str = (char *)mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
514     if (map_str == MAP_FAILED) {
515         close(fd);
516         return;
517     }
518
519     mXkbMap = xkb_map_new_from_string(mXkbContext, map_str, XKB_KEYMAP_FORMAT_TEXT_V1, (xkb_keymap_compile_flags)0);
520     munmap(map_str, size);
521     close(fd);
522
523     mXkbState = xkb_state_new(mXkbMap);
524 #else
525     Q_UNUSED(format);
526     Q_UNUSED(fd);
527     Q_UNUSED(size);
528 #endif
529 }
530
531 void QWaylandInputDevice::keyboard_enter(uint32_t time, struct wl_surface *surface, struct wl_array *keys)
532 {
533     Q_UNUSED(time);
534     Q_UNUSED(keys);
535
536     if (!surface)
537         return;
538
539
540     QWaylandWindow *window = QWaylandWindow::fromWlSurface(surface);
541     mKeyboardFocus = window;
542
543     if (!mFocusCallback) {
544         mFocusCallback = wl_display_sync(mDisplay);
545         wl_callback_add_listener(mFocusCallback, &QWaylandInputDevice::callback, this);
546     }
547 }
548
549 void QWaylandInputDevice::keyboard_leave(uint32_t time, struct wl_surface *surface)
550 {
551     Q_UNUSED(time);
552     Q_UNUSED(surface);
553
554     mKeyboardFocus = NULL;
555
556     // Use a callback to set the focus because we may get a leave/enter pair, and
557     // the latter one would be lost in the QWindowSystemInterface queue, if
558     // we issue the handleWindowActivated() calls immediately.
559     if (!mFocusCallback) {
560         mFocusCallback = wl_display_sync(mDisplay);
561         wl_callback_add_listener(mFocusCallback, &QWaylandInputDevice::callback, this);
562     }
563     mRepeatTimer.stop();
564 }
565
566 const wl_callback_listener QWaylandInputDevice::callback = {
567     QWaylandInputDevice::focusCallback
568 };
569
570 void QWaylandInputDevice::focusCallback(void *data, struct wl_callback *callback, uint32_t time)
571 {
572     Q_UNUSED(time);
573     Q_UNUSED(callback);
574     QWaylandInputDevice *self = static_cast<QWaylandInputDevice *>(data);
575     if (self->mFocusCallback) {
576         wl_callback_destroy(self->mFocusCallback);
577         self->mFocusCallback = 0;
578     }
579
580     self->mQDisplay->setLastKeyboardFocusInputDevice(self->mKeyboardFocus ? self : 0);
581     QWindowSystemInterface::handleWindowActivated(self->mKeyboardFocus ? self->mKeyboardFocus->window() : 0);
582 }
583
584 void QWaylandInputDevice::keyboard_key(uint32_t serial, uint32_t time, uint32_t key, uint32_t state)
585 {
586     Q_UNUSED(serial);
587     QWaylandWindow *window = mKeyboardFocus;
588 #ifndef QT_NO_WAYLAND_XKB
589     if (!mXkbMap)
590         return;
591
592     uint32_t code = key + 8;
593     bool isDown = state != 0;
594     const xkb_keysym_t *syms;
595     uint32_t numSyms = xkb_key_get_syms(mXkbState, code, &syms);
596     xkb_state_update_key(mXkbState, code,
597                          isDown ? XKB_KEY_DOWN : XKB_KEY_UP);
598     QEvent::Type type = isDown ? QEvent::KeyPress : QEvent::KeyRelease;
599
600     if (!window) {
601         // We destroyed the keyboard focus surface, but the server
602         // didn't get the message yet.
603         return;
604     }
605
606     int qtkey = key + 8;  // qt-compositor substracts 8 for some reason
607     QString text;
608
609     if (numSyms == 1) {
610         xkb_keysym_t sym = syms[0];
611         Qt::KeyboardModifiers modifiers = this->modifiers();
612
613         uint utf32 = xkb_keysym_to_utf32(sym);
614         text = QString::fromUcs4(&utf32, 1);
615
616         qtkey = keysymToQtKey(sym, modifiers, text);
617
618         QWindowSystemInterface::handleExtendedKeyEvent(window->window(),
619                                                        time, type, qtkey,
620                                                        modifiers,
621                                                        code, 0, 0, text);
622     }
623 #else
624     // Generic fallback for single hard keys: Assume 'key' is a Qt key code.
625     if (window) {
626         QWindowSystemInterface::handleExtendedKeyEvent(window->window(),
627                                                        time, type,
628                                                        qtkey,
629                                                        Qt::NoModifier,
630                                                        code, 0, 0);
631     }
632 #endif
633
634     if (state == WL_KEYBOARD_KEY_STATE_PRESSED) {
635         mRepeatKey = qtkey;
636         mRepeatCode = code;
637         mRepeatTime = time;
638         mRepeatText = text;
639         mRepeatTimer.setInterval(400);
640         mRepeatTimer.start();
641     } else {
642         mRepeatTimer.stop();
643     }
644 }
645
646 void QWaylandInputDevice::repeatKey()
647 {
648     mRepeatTimer.setInterval(25);
649     QWindowSystemInterface::handleExtendedKeyEvent(mKeyboardFocus->window(),
650                                                    mRepeatTime, QEvent::KeyPress, mRepeatKey,
651                                                    Qt::NoModifier,
652                                                    mRepeatCode, 0, 0, mRepeatText);
653 }
654
655 void QWaylandInputDevice::keyboard_modifiers(uint32_t serial,
656                                              uint32_t mods_depressed,
657                                              uint32_t mods_latched,
658                                              uint32_t mods_locked,
659                                              uint32_t group)
660 {
661     Q_UNUSED(serial);
662 #ifndef QT_NO_WAYLAND_XKB
663     if (mXkbState)
664         xkb_state_update_mask(mXkbState,
665                               mods_depressed, mods_latched, mods_locked,
666                               0, 0, group);
667 #else
668     Q_UNUSED(serial);
669     Q_UNUSED(mods_depressed);
670     Q_UNUSED(mods_latched);
671     Q_UNUSED(mods_locked);
672     Q_UNUSED(group);
673 #endif
674 }
675
676 void QWaylandInputDevice::touch_down(uint32_t serial,
677                                      uint32_t time,
678                                      struct wl_surface *surface,
679                                      int32_t id,
680                                      wl_fixed_t x,
681                                      wl_fixed_t y)
682 {
683     Q_UNUSED(serial);
684     Q_UNUSED(time);
685     mTouchFocus = QWaylandWindow::fromWlSurface(surface);
686     handleTouchPoint(id, wl_fixed_to_double(x), wl_fixed_to_double(y), Qt::TouchPointPressed);
687 }
688
689 void QWaylandInputDevice::touch_up(uint32_t serial, uint32_t time, int32_t id)
690 {
691     Q_UNUSED(serial);
692     Q_UNUSED(time);
693     mTouchFocus = 0;
694     handleTouchPoint(id, 0, 0, Qt::TouchPointReleased);
695 }
696
697 void QWaylandInputDevice::touch_motion(uint32_t time, int32_t id, wl_fixed_t x, wl_fixed_t y)
698 {
699     Q_UNUSED(time);
700     handleTouchPoint(id, wl_fixed_to_double(x), wl_fixed_to_double(y), Qt::TouchPointMoved);
701 }
702
703 void QWaylandInputDevice::touch_cancel()
704 {
705     mPrevTouchPoints.clear();
706     mTouchPoints.clear();
707
708     QWaylandTouchExtension *touchExt = mQDisplay->touchExtension();
709     if (touchExt)
710         touchExt->touchCanceled();
711
712     QWindowSystemInterface::handleTouchCancelEvent(0, mTouchDevice);
713 }
714
715 void QWaylandInputDevice::handleTouchPoint(int id, double x, double y, Qt::TouchPointState state)
716 {
717     QWindowSystemInterface::TouchPoint tp;
718
719     // Find out the coordinates for Released events.
720     bool coordsOk = false;
721     if (state == Qt::TouchPointReleased)
722         for (int i = 0; i < mPrevTouchPoints.count(); ++i)
723             if (mPrevTouchPoints.at(i).id == id) {
724                 tp.area = mPrevTouchPoints.at(i).area;
725                 coordsOk = true;
726                 break;
727             }
728
729     if (!coordsOk) {
730         // x and y are surface relative.
731         // We need a global (screen) position.
732         QWaylandWindow *win = mTouchFocus;
733
734         //is it possible that mTouchFocus is null;
735         if (!win)
736             win = mPointerFocus;
737         if (!win)
738             win = mKeyboardFocus;
739         if (!win || !win->window())
740             return;
741
742         tp.area = QRectF(0, 0, 8, 8);
743         QMargins margins = win->frameMargins();
744         tp.area.moveCenter(win->window()->mapToGlobal(QPoint(x+margins.left(), y+margins.top())));
745     }
746
747     tp.state = state;
748     tp.id = id;
749     tp.pressure = tp.state == Qt::TouchPointReleased ? 0 : 1;
750     mTouchPoints.append(tp);
751 }
752
753 void QWaylandInputDevice::touch_frame()
754 {
755     // Copy all points, that are in the previous but not in the current list, as stationary.
756     for (int i = 0; i < mPrevTouchPoints.count(); ++i) {
757         const QWindowSystemInterface::TouchPoint &prevPoint(mPrevTouchPoints.at(i));
758         if (prevPoint.state == Qt::TouchPointReleased)
759             continue;
760         bool found = false;
761         for (int j = 0; j < mTouchPoints.count(); ++j)
762             if (mTouchPoints.at(j).id == prevPoint.id) {
763                 found = true;
764                 break;
765             }
766         if (!found) {
767             QWindowSystemInterface::TouchPoint p = prevPoint;
768             p.state = Qt::TouchPointStationary;
769             mTouchPoints.append(p);
770         }
771     }
772
773     if (mTouchPoints.isEmpty()) {
774         mPrevTouchPoints.clear();
775         return;
776     }
777
778     QWindow *window = mTouchFocus ? mTouchFocus->window() : 0;
779
780     QWindowSystemInterface::handleTouchEvent(window, mTouchDevice, mTouchPoints);
781
782     bool allReleased = true;
783     for (int i = 0; i < mTouchPoints.count(); ++i)
784         if (mTouchPoints.at(i).state != Qt::TouchPointReleased) {
785             allReleased = false;
786             break;
787         }
788
789     mPrevTouchPoints = mTouchPoints;
790     mTouchPoints.clear();
791
792     if (allReleased) {
793         QWindowSystemInterface::handleTouchEvent(window, mTouchDevice, mTouchPoints);
794         mPrevTouchPoints.clear();
795     }
796 }
797
798 QT_END_NAMESPACE