Use new xkbcommon includepath
[profile/ivi/qtwayland.git] / src / plugins / platforms / wayland / qwaylandinputdevice.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
5 **
6 ** This file is part of the plugins of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
16 **
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
20 **
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
28 **
29 ** Other Usage
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
32 **
33 **
34 **
35 **
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 "qwaylanddatadevicemanager.h"
48 #include "qwaylandtouch.h"
49
50 #include <QtGui/private/qpixmap_raster_p.h>
51 #include <QtGui/QPlatformWindow>
52 #include <QDebug>
53
54 #include <unistd.h>
55 #include <fcntl.h>
56
57 #include <QtGui/QGuiApplication>
58
59 #ifndef QT_NO_WAYLAND_XKB
60 #include <xkbcommon/xkbcommon.h>
61 #include <X11/keysym.h>
62 #endif
63
64 QWaylandInputDevice::QWaylandInputDevice(QWaylandDisplay *display,
65                                          uint32_t id)
66     : mQDisplay(display)
67     , mDisplay(display->wl_display())
68     , mTransferDevice(0)
69     , mPointerFocus(0)
70     , mKeyboardFocus(0)
71     , mTouchFocus(0)
72     , mButtons(0)
73 {
74     mInputDevice = static_cast<struct wl_input_device *>
75             (wl_display_bind(mDisplay,id,&wl_input_device_interface));
76     wl_input_device_add_listener(mInputDevice,
77                                  &inputDeviceListener,
78                                  this);
79     wl_input_device_set_user_data(mInputDevice, this);
80
81 #ifndef QT_NO_WAYLAND_XKB
82     struct xkb_rule_names names;
83     names.rules = "evdev";
84     names.model = "pc105";
85     names.layout = "us";
86     names.variant = "";
87     names.options = "";
88
89     mXkb = xkb_compile_keymap_from_rules(&names);
90
91     if (!mXkb)
92         qWarning() << "xkb_compile_keymap_from_rules failed, no key input";
93 #endif
94
95     if (mQDisplay->dndSelectionHandler()) {
96         mTransferDevice = mQDisplay->dndSelectionHandler()->getDataDevice(this);
97     }
98
99     mTouchDevice = new QTouchDevice;
100     mTouchDevice->setType(QTouchDevice::TouchScreen);
101     mTouchDevice->setCapabilities(QTouchDevice::Position);
102     QWindowSystemInterface::registerTouchDevice(mTouchDevice);
103 }
104
105 void QWaylandInputDevice::handleWindowDestroyed(QWaylandWindow *window)
106 {
107     if (window == mPointerFocus)
108         mPointerFocus = 0;
109     if (window == mKeyboardFocus)
110         mKeyboardFocus = 0;
111 }
112
113 void QWaylandInputDevice::setTransferDevice(struct wl_data_device *device)
114 {
115    mTransferDevice =  device;
116 }
117
118 struct wl_data_device *QWaylandInputDevice::transferDevice() const
119 {
120     Q_ASSERT(mTransferDevice);
121     return mTransferDevice;
122 }
123
124 void QWaylandInputDevice::inputHandleMotion(void *data,
125                                             struct wl_input_device *input_device,
126                                             uint32_t time,
127                                             int32_t surface_x, int32_t surface_y)
128 {
129     Q_UNUSED(input_device);
130     QWaylandInputDevice *inputDevice = (QWaylandInputDevice *) data;
131     QWaylandWindow *window = inputDevice->mPointerFocus;
132
133     if (window == NULL) {
134         /* We destroyed the pointer focus surface, but the server
135          * didn't get the message yet. */
136         return;
137     }
138
139     QPoint pos(surface_x, surface_y);
140     QPoint global = window->window()->mapToGlobal(pos);
141
142     inputDevice->mSurfacePos = pos;
143     inputDevice->mGlobalPos = global;
144     inputDevice->mTime = time;
145     QWindowSystemInterface::handleMouseEvent(window->window(),
146                                              time, pos, global,
147                                              inputDevice->mButtons);
148 }
149
150 void QWaylandInputDevice::inputHandleButton(void *data,
151                                             struct wl_input_device *input_device,
152                                             uint32_t time, uint32_t button, uint32_t state)
153 {
154     Q_UNUSED(input_device);
155     QWaylandInputDevice *inputDevice = (QWaylandInputDevice *) data;
156     QWaylandWindow *window = inputDevice->mPointerFocus;
157     Qt::MouseButton qt_button;
158
159     if (window == NULL) {
160         /* We destroyed the pointer focus surface, but the server
161          * didn't get the message yet. */
162         return;
163     }
164
165     // translate from kernel (input.h) 'button' to corresponding Qt:MouseButton.
166     // The range of mouse values is 0x110 <= mouse_button < 0x120, the first Joystick button.
167     switch (button) {
168         case 0x110: qt_button = Qt::LeftButton; break;    // kernel BTN_LEFT
169         case 0x111: qt_button = Qt::RightButton; break;
170         case 0x112: qt_button = Qt::MiddleButton; break;
171         case 0x113: qt_button = Qt::ExtraButton1; break;  // AKA Qt::BackButton
172         case 0x114: qt_button = Qt::ExtraButton2; break;  // AKA Qt::ForwardButton
173         case 0x115: qt_button = Qt::ExtraButton3; break;  // AKA Qt::TaskButton
174         case 0x116: qt_button = Qt::ExtraButton4; break;
175         case 0x117: qt_button = Qt::ExtraButton5; break;
176         case 0x118: qt_button = Qt::ExtraButton6; break;
177         case 0x119: qt_button = Qt::ExtraButton7; break;
178         case 0x11a: qt_button = Qt::ExtraButton8; break;
179         case 0x11b: qt_button = Qt::ExtraButton9; break;
180         case 0x11c: qt_button = Qt::ExtraButton10; break;
181         case 0x11d: qt_button = Qt::ExtraButton11; break;
182         case 0x11e: qt_button = Qt::ExtraButton12; break;
183         case 0x11f: qt_button = Qt::ExtraButton13; break;
184         default: return; // invalid button number (as far as Qt is concerned)
185     }
186
187     if (state)
188         inputDevice->mButtons |= qt_button;
189     else
190         inputDevice->mButtons &= ~qt_button;
191
192     inputDevice->mTime = time;
193     QWindowSystemInterface::handleMouseEvent(window->window(),
194                                              time,
195                                              inputDevice->mSurfacePos,
196                                              inputDevice->mGlobalPos,
197                                              inputDevice->mButtons);
198 }
199
200 #ifndef QT_NO_WAYLAND_XKB
201 static Qt::KeyboardModifiers translateModifiers(int s)
202 {
203     const uchar qt_alt_mask = XKB_COMMON_MOD1_MASK;
204     const uchar qt_meta_mask = XKB_COMMON_MOD4_MASK;
205
206     Qt::KeyboardModifiers ret = 0;
207     if (s & XKB_COMMON_SHIFT_MASK)
208         ret |= Qt::ShiftModifier;
209     if (s & XKB_COMMON_CONTROL_MASK)
210         ret |= Qt::ControlModifier;
211     if (s & qt_alt_mask)
212         ret |= Qt::AltModifier;
213     if (s & qt_meta_mask)
214         ret |= Qt::MetaModifier;
215
216     return ret;
217 }
218
219 static uint32_t translateKey(uint32_t sym, char *string, size_t size)
220 {
221     Q_UNUSED(size);
222     string[0] = '\0';
223
224     switch (sym) {
225     case XK_Escape:             return Qt::Key_Escape;
226     case XK_Tab:                return Qt::Key_Tab;
227     case XK_ISO_Left_Tab:       return Qt::Key_Backtab;
228     case XK_BackSpace:          return Qt::Key_Backspace;
229     case XK_Return:             return Qt::Key_Return;
230     case XK_Insert:             return Qt::Key_Insert;
231     case XK_Delete:             return Qt::Key_Delete;
232     case XK_Clear:              return Qt::Key_Delete;
233     case XK_Pause:              return Qt::Key_Pause;
234     case XK_Print:              return Qt::Key_Print;
235
236     case XK_Home:               return Qt::Key_Home;
237     case XK_End:                return Qt::Key_End;
238     case XK_Left:               return Qt::Key_Left;
239     case XK_Up:                 return Qt::Key_Up;
240     case XK_Right:              return Qt::Key_Right;
241     case XK_Down:               return Qt::Key_Down;
242     case XK_Prior:              return Qt::Key_PageUp;
243     case XK_Next:               return Qt::Key_PageDown;
244
245     case XK_Shift_L:            return Qt::Key_Shift;
246     case XK_Shift_R:            return Qt::Key_Shift;
247     case XK_Shift_Lock:         return Qt::Key_Shift;
248     case XK_Control_L:          return Qt::Key_Control;
249     case XK_Control_R:          return Qt::Key_Control;
250     case XK_Meta_L:             return Qt::Key_Meta;
251     case XK_Meta_R:             return Qt::Key_Meta;
252     case XK_Alt_L:              return Qt::Key_Alt;
253     case XK_Alt_R:              return Qt::Key_Alt;
254     case XK_Caps_Lock:          return Qt::Key_CapsLock;
255     case XK_Num_Lock:           return Qt::Key_NumLock;
256     case XK_Scroll_Lock:        return Qt::Key_ScrollLock;
257     case XK_Super_L:            return Qt::Key_Super_L;
258     case XK_Super_R:            return Qt::Key_Super_R;
259     case XK_Menu:               return Qt::Key_Menu;
260
261     default:
262         string[0] = sym;
263         string[1] = '\0';
264         return toupper(sym);
265     }
266 }
267 #endif
268
269 void QWaylandInputDevice::inputHandleKey(void *data,
270                                          struct wl_input_device *input_device,
271                                          uint32_t time, uint32_t key, uint32_t state)
272 {
273     Q_UNUSED(input_device);
274     QWaylandInputDevice *inputDevice = (QWaylandInputDevice *) data;
275     QWaylandWindow *window = inputDevice->mKeyboardFocus;
276 #ifndef QT_NO_WAYLAND_XKB
277     uint32_t code, sym, level;
278     Qt::KeyboardModifiers modifiers;
279     QEvent::Type type;
280     char s[2];
281
282     if (window == NULL || !inputDevice->mXkb) {
283         /* We destroyed the keyboard focus surface, but the server
284          * didn't get the message yet. */
285         return;
286     }
287
288     code = key + inputDevice->mXkb->min_key_code;
289
290     level = 0;
291     if (inputDevice->mModifiers & Qt::ShiftModifier &&
292         XkbKeyGroupWidth(inputDevice->mXkb, code, 0) > 1)
293         level = 1;
294
295     sym = XkbKeySymEntry(inputDevice->mXkb, code, level, 0);
296
297     modifiers = translateModifiers(inputDevice->mXkb->map->modmap[code]);
298
299     if (state) {
300         inputDevice->mModifiers |= modifiers;
301         type = QEvent::KeyPress;
302     } else {
303         inputDevice->mModifiers &= ~modifiers;
304         type = QEvent::KeyRelease;
305     }
306
307     sym = translateKey(sym, s, sizeof s);
308
309     if (window) {
310         QWindowSystemInterface::handleExtendedKeyEvent(window->window(),
311                                                        time, type, sym,
312                                                        inputDevice->mModifiers,
313                                                        code, 0, 0,
314                                                        QString::fromLatin1(s));
315     }
316 #else
317     // Generic fallback for single hard keys: Assume 'key' is a Qt key code.
318     if (window) {
319         QWindowSystemInterface::handleExtendedKeyEvent(window->window(),
320                                                        time, state ? QEvent::KeyPress : QEvent::KeyRelease,
321                                                        key + 8, // qt-compositor substracts 8 for some reason
322                                                        inputDevice->mModifiers,
323                                                        key + 8, 0, 0);
324     }
325 #endif
326 }
327
328 void QWaylandInputDevice::inputHandlePointerEnter(void *data,
329                                                   struct wl_input_device *input_device,
330                                                   uint32_t time, struct wl_surface *surface,
331                                                   int32_t sx, int32_t sy)
332 {
333     Q_UNUSED(input_device);
334     Q_UNUSED(sx);
335     Q_UNUSED(sy);
336     QWaylandInputDevice *inputDevice = (QWaylandInputDevice *) data;
337
338     // shouldn't get pointer leave with no surface
339     Q_ASSERT(surface);
340
341     QWaylandWindow *window = (QWaylandWindow *) wl_surface_get_user_data(surface);
342     QWindowSystemInterface::handleEnterEvent(window->window());
343     inputDevice->mPointerFocus = window;
344
345     inputDevice->mTime = time;
346 }
347
348 void QWaylandInputDevice::inputHandlePointerLeave(void *data,
349                                                   struct wl_input_device *input_device,
350                                                   uint32_t time, struct wl_surface *surface)
351 {
352     Q_UNUSED(input_device);
353     QWaylandInputDevice *inputDevice = (QWaylandInputDevice *) data;
354
355     // shouldn't get pointer leave with no surface
356     Q_ASSERT(surface);
357
358     QWaylandWindow *window = (QWaylandWindow *) wl_surface_get_user_data(surface);
359     QWindowSystemInterface::handleLeaveEvent(window->window());
360     inputDevice->mPointerFocus = 0;
361
362     inputDevice->mTime = time;
363 }
364
365 void QWaylandInputDevice::inputHandleKeyboardEnter(void *data,
366                                                    struct wl_input_device *input_device,
367                                                    uint32_t time,
368                                                    struct wl_surface *surface,
369                                                    struct wl_array *keys)
370 {
371     Q_UNUSED(input_device);
372     Q_UNUSED(time);
373     QWaylandInputDevice *inputDevice = (QWaylandInputDevice *) data;
374     QWaylandWindow *window;
375
376     inputDevice->mModifiers = 0;
377
378 #ifndef QT_NO_WAYLAND_XKB
379     uint32_t *k, *end;
380     uint32_t code;
381
382     end = (uint32_t *) ((char *) keys->data + keys->size);
383     for (k = (uint32_t *) keys->data; k < end; k++) {
384         code = *k + inputDevice->mXkb->min_key_code;
385         inputDevice->mModifiers |=
386             translateModifiers(inputDevice->mXkb->map->modmap[code]);
387     }
388 #else
389     Q_UNUSED(keys);
390 #endif
391
392     // shouldn't get keyboard enter with no surface
393     Q_ASSERT(surface);
394
395     window = (QWaylandWindow *) wl_surface_get_user_data(surface);
396     inputDevice->mKeyboardFocus = window;
397     inputDevice->mQDisplay->setLastKeyboardFocusInputDevice(inputDevice);
398     QWindowSystemInterface::handleWindowActivated(window->window());
399 }
400
401 void QWaylandInputDevice::inputHandleKeyboardLeave(void *data,
402                                                    struct wl_input_device *input_device,
403                                                    uint32_t time,
404                                                    struct wl_surface *surface)
405 {
406     Q_UNUSED(input_device);
407     Q_UNUSED(time);
408     Q_UNUSED(surface);
409
410     QWaylandInputDevice *inputDevice = (QWaylandInputDevice *) data;
411
412     inputDevice->mKeyboardFocus = NULL;
413     inputDevice->mQDisplay->setLastKeyboardFocusInputDevice(0);
414     QWindowSystemInterface::handleWindowActivated(0);
415 }
416
417 void QWaylandInputDevice::inputHandleTouchDown(void *data,
418                                                struct wl_input_device *wl_input_device,
419                                                uint32_t time,
420                                                struct wl_surface *surface,
421                                                int id,
422                                                int x,
423                                                int y)
424 {
425     Q_UNUSED(wl_input_device);
426     Q_UNUSED(time);
427     QWaylandInputDevice *inputDevice = (QWaylandInputDevice *) data;
428     inputDevice->mTouchFocus = static_cast<QWaylandWindow *>(wl_surface_get_user_data(surface));
429     inputDevice->handleTouchPoint(id, x, y, Qt::TouchPointPressed);
430 }
431
432 void QWaylandInputDevice::inputHandleTouchUp(void *data,
433                                              struct wl_input_device *wl_input_device,
434                                              uint32_t time,
435                                              int id)
436 {
437     Q_UNUSED(wl_input_device);
438     Q_UNUSED(time);
439     QWaylandInputDevice *inputDevice = (QWaylandInputDevice *) data;
440     inputDevice->mTouchFocus = 0;
441     inputDevice->handleTouchPoint(id, 0, 0, Qt::TouchPointReleased);
442 }
443
444 void QWaylandInputDevice::inputHandleTouchMotion(void *data,
445                                                  struct wl_input_device *wl_input_device,
446                                                  uint32_t time,
447                                                  int id,
448                                                  int x,
449                                                  int y)
450 {
451     Q_UNUSED(wl_input_device);
452     Q_UNUSED(time);
453     QWaylandInputDevice *inputDevice = (QWaylandInputDevice *) data;
454     inputDevice->handleTouchPoint(id, x, y, Qt::TouchPointMoved);
455 }
456
457 void QWaylandInputDevice::handleTouchPoint(int id, int x, int y, Qt::TouchPointState state)
458 {
459     QWindowSystemInterface::TouchPoint tp;
460
461     // Find out the coordinates for Released events.
462     bool coordsOk = false;
463     if (state == Qt::TouchPointReleased)
464         for (int i = 0; i < mPrevTouchPoints.count(); ++i)
465             if (mPrevTouchPoints.at(i).id == id) {
466                 tp.area = mPrevTouchPoints.at(i).area;
467                 coordsOk = true;
468                 break;
469             }
470
471     if (!coordsOk) {
472         // x and y are surface relative.
473         // We need a global (screen) position.
474         QWaylandWindow *win = mTouchFocus;
475
476         //is it possible that mTouchFocus is null;
477         if (!win)
478             win = mPointerFocus;
479         if (!win)
480             win = mKeyboardFocus;
481         if (!win || !win->window())
482             return;
483
484         tp.area = QRectF(0, 0, 8, 8);
485         tp.area.moveCenter(win->window()->mapToGlobal(QPoint(x, y)));
486     }
487
488     tp.state = state;
489     tp.id = id;
490     tp.pressure = tp.state == Qt::TouchPointReleased ? 0 : 1;
491     mTouchPoints.append(tp);
492 }
493
494 void QWaylandInputDevice::inputHandleTouchFrame(void *data, struct wl_input_device *wl_input_device)
495 {
496     Q_UNUSED(wl_input_device);
497     QWaylandInputDevice *inputDevice = (QWaylandInputDevice *) data;
498     inputDevice->handleTouchFrame();
499 }
500
501 void QWaylandInputDevice::handleTouchFrame()
502 {
503     // Copy all points, that are in the previous but not in the current list, as stationary.
504     for (int i = 0; i < mPrevTouchPoints.count(); ++i) {
505         const QWindowSystemInterface::TouchPoint &prevPoint(mPrevTouchPoints.at(i));
506         if (prevPoint.state == Qt::TouchPointReleased)
507             continue;
508         bool found = false;
509         for (int j = 0; j < mTouchPoints.count(); ++j)
510             if (mTouchPoints.at(j).id == prevPoint.id) {
511                 found = true;
512                 break;
513             }
514         if (!found) {
515             QWindowSystemInterface::TouchPoint p = prevPoint;
516             p.state = Qt::TouchPointStationary;
517             mTouchPoints.append(p);
518         }
519     }
520
521     if (mTouchPoints.isEmpty()) {
522         mPrevTouchPoints.clear();
523         return;
524     }
525
526     QWindowSystemInterface::handleTouchEvent(0, mTouchDevice, mTouchPoints);
527
528     bool allReleased = true;
529     for (int i = 0; i < mTouchPoints.count(); ++i)
530         if (mTouchPoints.at(i).state != Qt::TouchPointReleased) {
531             allReleased = false;
532             break;
533         }
534
535     mPrevTouchPoints = mTouchPoints;
536     mTouchPoints.clear();
537
538     if (allReleased) {
539         QWindowSystemInterface::handleTouchEvent(0, mTouchDevice, mTouchPoints);
540         mPrevTouchPoints.clear();
541     }
542 }
543
544 void QWaylandInputDevice::inputHandleTouchCancel(void *data, struct wl_input_device *wl_input_device)
545 {
546     Q_UNUSED(wl_input_device);
547     QWaylandInputDevice *self = static_cast<QWaylandInputDevice *>(data);
548
549     self->mPrevTouchPoints.clear();
550     self->mTouchPoints.clear();
551
552     QWaylandTouchExtension *touchExt = self->mQDisplay->touchExtension();
553     if (touchExt)
554         touchExt->touchCanceled();
555
556     QWindowSystemInterface::handleTouchCancelEvent(0, self->mTouchDevice);
557 }
558
559 const struct wl_input_device_listener QWaylandInputDevice::inputDeviceListener = {
560     QWaylandInputDevice::inputHandleMotion,
561     QWaylandInputDevice::inputHandleButton,
562     QWaylandInputDevice::inputHandleKey,
563     QWaylandInputDevice::inputHandlePointerEnter,
564     QWaylandInputDevice::inputHandlePointerLeave,
565     QWaylandInputDevice::inputHandleKeyboardEnter,
566     QWaylandInputDevice::inputHandleKeyboardLeave,
567     QWaylandInputDevice::inputHandleTouchDown,
568     QWaylandInputDevice::inputHandleTouchUp,
569     QWaylandInputDevice::inputHandleTouchMotion,
570     QWaylandInputDevice::inputHandleTouchFrame,
571     QWaylandInputDevice::inputHandleTouchCancel
572 };
573
574 void QWaylandInputDevice::attach(QWaylandBuffer *buffer, int x, int y)
575 {
576     wl_input_device_attach(mInputDevice, mTime, buffer->buffer(), x, y);
577 }