1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
6 ** This file is part of the plugins of the Qt Toolkit.
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.
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.
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.
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.
40 ****************************************************************************/
42 #include "qwaylandinputdevice.h"
44 #include "qwaylandintegration.h"
45 #include "qwaylandwindow.h"
46 #include "qwaylandbuffer.h"
47 #include "qwaylanddatadevicemanager.h"
48 #include "qwaylandtouch.h"
50 #include <QtGui/private/qpixmap_raster_p.h>
51 #include <QtGui/QPlatformWindow>
57 #include <QtGui/QGuiApplication>
59 #ifndef QT_NO_WAYLAND_XKB
60 #include <xkbcommon/xkbcommon.h>
61 #include <X11/keysym.h>
64 QWaylandInputDevice::QWaylandInputDevice(QWaylandDisplay *display,
67 , mDisplay(display->wl_display())
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,
79 wl_input_device_set_user_data(mInputDevice, this);
81 #ifndef QT_NO_WAYLAND_XKB
82 struct xkb_rule_names names;
83 names.rules = "evdev";
84 names.model = "pc105";
89 mXkb = xkb_compile_keymap_from_rules(&names);
92 qWarning() << "xkb_compile_keymap_from_rules failed, no key input";
95 if (mQDisplay->dndSelectionHandler()) {
96 mTransferDevice = mQDisplay->dndSelectionHandler()->getDataDevice(this);
99 mTouchDevice = new QTouchDevice;
100 mTouchDevice->setType(QTouchDevice::TouchScreen);
101 mTouchDevice->setCapabilities(QTouchDevice::Position);
102 QWindowSystemInterface::registerTouchDevice(mTouchDevice);
105 void QWaylandInputDevice::handleWindowDestroyed(QWaylandWindow *window)
107 if (window == mPointerFocus)
109 if (window == mKeyboardFocus)
113 void QWaylandInputDevice::setTransferDevice(struct wl_data_device *device)
115 mTransferDevice = device;
118 struct wl_data_device *QWaylandInputDevice::transferDevice() const
120 Q_ASSERT(mTransferDevice);
121 return mTransferDevice;
124 void QWaylandInputDevice::inputHandleMotion(void *data,
125 struct wl_input_device *input_device,
127 int32_t surface_x, int32_t surface_y)
129 Q_UNUSED(input_device);
130 QWaylandInputDevice *inputDevice = (QWaylandInputDevice *) data;
131 QWaylandWindow *window = inputDevice->mPointerFocus;
133 if (window == NULL) {
134 /* We destroyed the pointer focus surface, but the server
135 * didn't get the message yet. */
139 QPoint pos(surface_x, surface_y);
140 QPoint global = window->window()->mapToGlobal(pos);
142 inputDevice->mSurfacePos = pos;
143 inputDevice->mGlobalPos = global;
144 inputDevice->mTime = time;
145 QWindowSystemInterface::handleMouseEvent(window->window(),
147 inputDevice->mButtons);
150 void QWaylandInputDevice::inputHandleButton(void *data,
151 struct wl_input_device *input_device,
152 uint32_t time, uint32_t button, uint32_t state)
154 Q_UNUSED(input_device);
155 QWaylandInputDevice *inputDevice = (QWaylandInputDevice *) data;
156 QWaylandWindow *window = inputDevice->mPointerFocus;
157 Qt::MouseButton qt_button;
159 if (window == NULL) {
160 /* We destroyed the pointer focus surface, but the server
161 * didn't get the message yet. */
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.
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)
188 inputDevice->mButtons |= qt_button;
190 inputDevice->mButtons &= ~qt_button;
192 inputDevice->mTime = time;
193 QWindowSystemInterface::handleMouseEvent(window->window(),
195 inputDevice->mSurfacePos,
196 inputDevice->mGlobalPos,
197 inputDevice->mButtons);
200 #ifndef QT_NO_WAYLAND_XKB
201 static Qt::KeyboardModifiers translateModifiers(int s)
203 const uchar qt_alt_mask = XKB_COMMON_MOD1_MASK;
204 const uchar qt_meta_mask = XKB_COMMON_MOD4_MASK;
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;
212 ret |= Qt::AltModifier;
213 if (s & qt_meta_mask)
214 ret |= Qt::MetaModifier;
219 static uint32_t translateKey(uint32_t sym, char *string, size_t size)
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;
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;
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;
269 void QWaylandInputDevice::inputHandleKey(void *data,
270 struct wl_input_device *input_device,
271 uint32_t time, uint32_t key, uint32_t state)
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;
282 if (window == NULL || !inputDevice->mXkb) {
283 /* We destroyed the keyboard focus surface, but the server
284 * didn't get the message yet. */
288 code = key + inputDevice->mXkb->min_key_code;
291 if (inputDevice->mModifiers & Qt::ShiftModifier &&
292 XkbKeyGroupWidth(inputDevice->mXkb, code, 0) > 1)
295 sym = XkbKeySymEntry(inputDevice->mXkb, code, level, 0);
297 modifiers = translateModifiers(inputDevice->mXkb->map->modmap[code]);
300 inputDevice->mModifiers |= modifiers;
301 type = QEvent::KeyPress;
303 inputDevice->mModifiers &= ~modifiers;
304 type = QEvent::KeyRelease;
307 sym = translateKey(sym, s, sizeof s);
310 QWindowSystemInterface::handleExtendedKeyEvent(window->window(),
312 inputDevice->mModifiers,
314 QString::fromLatin1(s));
317 // Generic fallback for single hard keys: Assume 'key' is a Qt key code.
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,
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)
333 Q_UNUSED(input_device);
336 QWaylandInputDevice *inputDevice = (QWaylandInputDevice *) data;
338 // shouldn't get pointer leave with no surface
341 QWaylandWindow *window = (QWaylandWindow *) wl_surface_get_user_data(surface);
342 QWindowSystemInterface::handleEnterEvent(window->window());
343 inputDevice->mPointerFocus = window;
345 inputDevice->mTime = time;
348 void QWaylandInputDevice::inputHandlePointerLeave(void *data,
349 struct wl_input_device *input_device,
350 uint32_t time, struct wl_surface *surface)
352 Q_UNUSED(input_device);
353 QWaylandInputDevice *inputDevice = (QWaylandInputDevice *) data;
355 // shouldn't get pointer leave with no surface
358 QWaylandWindow *window = (QWaylandWindow *) wl_surface_get_user_data(surface);
359 QWindowSystemInterface::handleLeaveEvent(window->window());
360 inputDevice->mPointerFocus = 0;
362 inputDevice->mTime = time;
365 void QWaylandInputDevice::inputHandleKeyboardEnter(void *data,
366 struct wl_input_device *input_device,
368 struct wl_surface *surface,
369 struct wl_array *keys)
371 Q_UNUSED(input_device);
373 QWaylandInputDevice *inputDevice = (QWaylandInputDevice *) data;
374 QWaylandWindow *window;
376 inputDevice->mModifiers = 0;
378 #ifndef QT_NO_WAYLAND_XKB
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]);
392 // shouldn't get keyboard enter with no surface
395 window = (QWaylandWindow *) wl_surface_get_user_data(surface);
396 inputDevice->mKeyboardFocus = window;
397 inputDevice->mQDisplay->setLastKeyboardFocusInputDevice(inputDevice);
398 QWindowSystemInterface::handleWindowActivated(window->window());
401 void QWaylandInputDevice::inputHandleKeyboardLeave(void *data,
402 struct wl_input_device *input_device,
404 struct wl_surface *surface)
406 Q_UNUSED(input_device);
410 QWaylandInputDevice *inputDevice = (QWaylandInputDevice *) data;
412 inputDevice->mKeyboardFocus = NULL;
413 inputDevice->mQDisplay->setLastKeyboardFocusInputDevice(0);
414 QWindowSystemInterface::handleWindowActivated(0);
417 void QWaylandInputDevice::inputHandleTouchDown(void *data,
418 struct wl_input_device *wl_input_device,
420 struct wl_surface *surface,
425 Q_UNUSED(wl_input_device);
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);
432 void QWaylandInputDevice::inputHandleTouchUp(void *data,
433 struct wl_input_device *wl_input_device,
437 Q_UNUSED(wl_input_device);
439 QWaylandInputDevice *inputDevice = (QWaylandInputDevice *) data;
440 inputDevice->mTouchFocus = 0;
441 inputDevice->handleTouchPoint(id, 0, 0, Qt::TouchPointReleased);
444 void QWaylandInputDevice::inputHandleTouchMotion(void *data,
445 struct wl_input_device *wl_input_device,
451 Q_UNUSED(wl_input_device);
453 QWaylandInputDevice *inputDevice = (QWaylandInputDevice *) data;
454 inputDevice->handleTouchPoint(id, x, y, Qt::TouchPointMoved);
457 void QWaylandInputDevice::handleTouchPoint(int id, int x, int y, Qt::TouchPointState state)
459 QWindowSystemInterface::TouchPoint tp;
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;
472 // x and y are surface relative.
473 // We need a global (screen) position.
474 QWaylandWindow *win = mTouchFocus;
476 //is it possible that mTouchFocus is null;
480 win = mKeyboardFocus;
481 if (!win || !win->window())
484 tp.area = QRectF(0, 0, 8, 8);
485 tp.area.moveCenter(win->window()->mapToGlobal(QPoint(x, y)));
490 tp.pressure = tp.state == Qt::TouchPointReleased ? 0 : 1;
491 mTouchPoints.append(tp);
494 void QWaylandInputDevice::inputHandleTouchFrame(void *data, struct wl_input_device *wl_input_device)
496 Q_UNUSED(wl_input_device);
497 QWaylandInputDevice *inputDevice = (QWaylandInputDevice *) data;
498 inputDevice->handleTouchFrame();
501 void QWaylandInputDevice::handleTouchFrame()
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)
509 for (int j = 0; j < mTouchPoints.count(); ++j)
510 if (mTouchPoints.at(j).id == prevPoint.id) {
515 QWindowSystemInterface::TouchPoint p = prevPoint;
516 p.state = Qt::TouchPointStationary;
517 mTouchPoints.append(p);
521 if (mTouchPoints.isEmpty()) {
522 mPrevTouchPoints.clear();
526 QWindowSystemInterface::handleTouchEvent(0, mTouchDevice, mTouchPoints);
528 bool allReleased = true;
529 for (int i = 0; i < mTouchPoints.count(); ++i)
530 if (mTouchPoints.at(i).state != Qt::TouchPointReleased) {
535 mPrevTouchPoints = mTouchPoints;
536 mTouchPoints.clear();
539 QWindowSystemInterface::handleTouchEvent(0, mTouchDevice, mTouchPoints);
540 mPrevTouchPoints.clear();
544 void QWaylandInputDevice::inputHandleTouchCancel(void *data, struct wl_input_device *wl_input_device)
546 Q_UNUSED(wl_input_device);
547 QWaylandInputDevice *self = static_cast<QWaylandInputDevice *>(data);
549 self->mPrevTouchPoints.clear();
550 self->mTouchPoints.clear();
552 QWaylandTouchExtension *touchExt = self->mQDisplay->touchExtension();
554 touchExt->touchCanceled();
556 QWindowSystemInterface::handleTouchCancelEvent(0, self->mTouchDevice);
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
574 void QWaylandInputDevice::attach(QWaylandBuffer *buffer, int x, int y)
576 wl_input_device_attach(mInputDevice, mTime, buffer->buffer(), x, y);