1 /****************************************************************************
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the plugins of the Qt Toolkit.
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** 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"
48 #include <QtGui/private/qpixmap_raster_p.h>
49 #include <QtGui/QPlatformWindow>
55 #ifndef QT_NO_WAYLAND_XKB
56 #include <X11/extensions/XKBcommon.h>
57 #include <X11/keysym.h>
62 QWaylandInputDevice::QWaylandInputDevice(QWaylandDisplay *display,
65 , mDisplay(display->wl_display())
66 , mInputDevice(wl_input_device_create(mDisplay, id, 1))
68 , mKeyboardFocus(NULL)
70 , mTouchState(QEvent::TouchBegin)
72 wl_input_device_add_listener(mInputDevice,
75 wl_input_device_set_user_data(mInputDevice, this);
77 #ifndef QT_NO_WAYLAND_XKB
78 struct xkb_rule_names names;
79 names.rules = "evdev";
80 names.model = "pc105";
85 mXkb = xkb_compile_keymap_from_rules(&names);
89 void QWaylandInputDevice::handleWindowDestroyed(QWaylandWindow *window)
91 if (window == mPointerFocus)
93 if (window == mKeyboardFocus)
97 void QWaylandInputDevice::inputHandleMotion(void *data,
98 struct wl_input_device *input_device,
100 int32_t x, int32_t y,
101 int32_t surface_x, int32_t surface_y)
103 Q_UNUSED(input_device);
104 QWaylandInputDevice *inputDevice = (QWaylandInputDevice *) data;
105 QWaylandWindow *window = inputDevice->mPointerFocus;
107 if (window == NULL) {
108 /* We destroyed the pointer focus surface, but the server
109 * didn't get the message yet. */
113 inputDevice->mSurfacePos = QPoint(surface_x, surface_y);
114 inputDevice->mGlobalPos = QPoint(x, y);
115 inputDevice->mTime = time;
116 QWindowSystemInterface::handleMouseEvent(window->widget(),
118 inputDevice->mSurfacePos,
119 inputDevice->mGlobalPos,
120 inputDevice->mButtons);
123 void QWaylandInputDevice::inputHandleButton(void *data,
124 struct wl_input_device *input_device,
125 uint32_t time, uint32_t button, uint32_t state)
127 Q_UNUSED(input_device);
128 QWaylandInputDevice *inputDevice = (QWaylandInputDevice *) data;
129 QWaylandWindow *window = inputDevice->mPointerFocus;
130 Qt::MouseButton qt_button;
132 if (window == NULL) {
133 /* We destroyed the pointer focus surface, but the server
134 * didn't get the message yet. */
140 qt_button = Qt::LeftButton;
143 qt_button = Qt::RightButton;
146 qt_button = Qt::MiddleButton;
153 inputDevice->mButtons |= qt_button;
155 inputDevice->mButtons &= ~qt_button;
157 inputDevice->mTime = time;
158 QWindowSystemInterface::handleMouseEvent(window->widget(),
160 inputDevice->mSurfacePos,
161 inputDevice->mGlobalPos,
162 inputDevice->mButtons);
165 #ifndef QT_NO_WAYLAND_XKB
166 static Qt::KeyboardModifiers translateModifiers(int s)
168 const uchar qt_alt_mask = XKB_COMMON_MOD1_MASK;
169 const uchar qt_meta_mask = XKB_COMMON_MOD4_MASK;
171 Qt::KeyboardModifiers ret = 0;
172 if (s & XKB_COMMON_SHIFT_MASK)
173 ret |= Qt::ShiftModifier;
174 if (s & XKB_COMMON_CONTROL_MASK)
175 ret |= Qt::ControlModifier;
177 ret |= Qt::AltModifier;
178 if (s & qt_meta_mask)
179 ret |= Qt::MetaModifier;
184 static uint32_t translateKey(uint32_t sym, char *string, size_t size)
190 case XK_Escape: return Qt::Key_Escape;
191 case XK_Tab: return Qt::Key_Tab;
192 case XK_ISO_Left_Tab: return Qt::Key_Backtab;
193 case XK_BackSpace: return Qt::Key_Backspace;
194 case XK_Return: return Qt::Key_Return;
195 case XK_Insert: return Qt::Key_Insert;
196 case XK_Delete: return Qt::Key_Delete;
197 case XK_Clear: return Qt::Key_Delete;
198 case XK_Pause: return Qt::Key_Pause;
199 case XK_Print: return Qt::Key_Print;
201 case XK_Home: return Qt::Key_Home;
202 case XK_End: return Qt::Key_End;
203 case XK_Left: return Qt::Key_Left;
204 case XK_Up: return Qt::Key_Up;
205 case XK_Right: return Qt::Key_Right;
206 case XK_Down: return Qt::Key_Down;
207 case XK_Prior: return Qt::Key_PageUp;
208 case XK_Next: return Qt::Key_PageDown;
210 case XK_Shift_L: return Qt::Key_Shift;
211 case XK_Shift_R: return Qt::Key_Shift;
212 case XK_Shift_Lock: return Qt::Key_Shift;
213 case XK_Control_L: return Qt::Key_Control;
214 case XK_Control_R: return Qt::Key_Control;
215 case XK_Meta_L: return Qt::Key_Meta;
216 case XK_Meta_R: return Qt::Key_Meta;
217 case XK_Alt_L: return Qt::Key_Alt;
218 case XK_Alt_R: return Qt::Key_Alt;
219 case XK_Caps_Lock: return Qt::Key_CapsLock;
220 case XK_Num_Lock: return Qt::Key_NumLock;
221 case XK_Scroll_Lock: return Qt::Key_ScrollLock;
222 case XK_Super_L: return Qt::Key_Super_L;
223 case XK_Super_R: return Qt::Key_Super_R;
224 case XK_Menu: return Qt::Key_Menu;
234 void QWaylandInputDevice::inputHandleKey(void *data,
235 struct wl_input_device *input_device,
236 uint32_t time, uint32_t key, uint32_t state)
238 #ifndef QT_NO_WAYLAND_XKB
239 Q_UNUSED(input_device);
240 QWaylandInputDevice *inputDevice = (QWaylandInputDevice *) data;
241 QWaylandWindow *window = inputDevice->mKeyboardFocus;
242 uint32_t code, sym, level;
243 Qt::KeyboardModifiers modifiers;
247 if (window == NULL) {
248 /* We destroyed the keyboard focus surface, but the server
249 * didn't get the message yet. */
253 code = key + inputDevice->mXkb->min_key_code;
256 if (inputDevice->mModifiers & Qt::ShiftModifier &&
257 XkbKeyGroupWidth(inputDevice->mXkb, code, 0) > 1)
260 sym = XkbKeySymEntry(inputDevice->mXkb, code, level, 0);
262 modifiers = translateModifiers(inputDevice->mXkb->map->modmap[code]);
265 inputDevice->mModifiers |= modifiers;
266 type = QEvent::KeyPress;
268 inputDevice->mModifiers &= ~modifiers;
269 type = QEvent::KeyRelease;
272 sym = translateKey(sym, s, sizeof s);
275 QWindowSystemInterface::handleKeyEvent(window->widget(),
277 inputDevice->mModifiers,
278 QString::fromLatin1(s));
283 void QWaylandInputDevice::inputHandlePointerFocus(void *data,
284 struct wl_input_device *input_device,
285 uint32_t time, struct wl_surface *surface,
286 int32_t x, int32_t y, int32_t sx, int32_t sy)
288 Q_UNUSED(input_device);
293 QWaylandInputDevice *inputDevice = (QWaylandInputDevice *) data;
294 QWaylandWindow *window;
296 if (inputDevice->mPointerFocus) {
297 window = inputDevice->mPointerFocus;
298 QWindowSystemInterface::handleLeaveEvent(window->widget());
299 inputDevice->mPointerFocus = NULL;
303 window = (QWaylandWindow *) wl_surface_get_user_data(surface);
304 QWindowSystemInterface::handleEnterEvent(window->widget());
305 inputDevice->mPointerFocus = window;
308 inputDevice->mTime = time;
311 void QWaylandInputDevice::inputHandleKeyboardFocus(void *data,
312 struct wl_input_device *input_device,
314 struct wl_surface *surface,
315 struct wl_array *keys)
317 #ifndef QT_NO_WAYLAND_XKB
318 Q_UNUSED(input_device);
320 QWaylandInputDevice *inputDevice = (QWaylandInputDevice *) data;
321 QWaylandWindow *window;
325 end = (uint32_t *) ((char *) keys->data + keys->size);
326 inputDevice->mModifiers = 0;
327 for (k = (uint32_t *) keys->data; k < end; k++) {
328 code = *k + inputDevice->mXkb->min_key_code;
329 inputDevice->mModifiers |=
330 translateModifiers(inputDevice->mXkb->map->modmap[code]);
334 window = (QWaylandWindow *) wl_surface_get_user_data(surface);
335 inputDevice->mKeyboardFocus = window;
336 QWindowSystemInterface::handleWindowActivated(window->widget());
338 inputDevice->mKeyboardFocus = NULL;
339 QWindowSystemInterface::handleWindowActivated(0);
344 void QWaylandInputDevice::inputHandleTouchDown(void *data,
345 struct wl_input_device *wl_input_device,
351 QWaylandInputDevice *inputDevice = (QWaylandInputDevice *) data;
352 inputDevice->handleTouchPoint(id, x, y, Qt::TouchPointPressed);
355 void QWaylandInputDevice::inputHandleTouchUp(void *data,
356 struct wl_input_device *wl_input_device,
360 QWaylandInputDevice *inputDevice = (QWaylandInputDevice *) data;
361 inputDevice->handleTouchPoint(id, 0, 0, Qt::TouchPointReleased);
364 void QWaylandInputDevice::inputHandleTouchMotion(void *data,
365 struct wl_input_device *wl_input_device,
371 QWaylandInputDevice *inputDevice = (QWaylandInputDevice *) data;
372 inputDevice->handleTouchPoint(id, x, y, Qt::TouchPointMoved);
375 void QWaylandInputDevice::handleTouchPoint(int id, int x, int y, Qt::TouchPointState state)
377 QWindowSystemInterface::TouchPoint tp;
379 // Find out the coordinates for Released events.
380 bool coordsOk = false;
381 if (state == Qt::TouchPointReleased)
382 for (int i = 0; i < mPrevTouchPoints.count(); ++i)
383 if (mPrevTouchPoints.at(i).id == id) {
384 tp.area = mPrevTouchPoints.at(i).area;
390 // x and y are surface relative.
391 // We need a global (screen) position.
393 QWaylandWindow *win = mPointerFocus;
395 win = mKeyboardFocus;
397 qDebug() << "surface relative coords" << x << y << "using window" << win;
402 QRect winRect = win->geometry();
404 // Get a normalized position (0..1).
405 const qreal nx = x / qreal(winRect.width());
406 const qreal ny = y / qreal(winRect.height());
407 tp.normalPosition = QPointF(nx, ny);
410 QPlatformScreen *screen = mQDisplay->screens().at(0);
411 QRect screenRect = screen->geometry();
412 x = int(nx * screenRect.width());
413 y = int(ny * screenRect.height());
416 qDebug() << "normalized position" << nx << ny
417 << "win rect" << winRect << "screen rect" << screenRect;
418 qDebug() << "mapped to screen position" << x << y;
421 tp.area = QRectF(x, y, 1, 1);
426 tp.isPrimary = mTouchPoints.isEmpty();
427 tp.pressure = tp.state == Qt::TouchPointReleased ? 0 : 1;
428 mTouchPoints.append(tp);
431 void QWaylandInputDevice::inputHandleTouchFrame(void *data, struct wl_input_device *wl_input_device)
433 QWaylandInputDevice *inputDevice = (QWaylandInputDevice *) data;
434 inputDevice->handleTouchFrame();
437 void QWaylandInputDevice::handleTouchFrame()
439 // Copy all points, that are in the previous but not in the current list, as stationary.
440 for (int i = 0; i < mPrevTouchPoints.count(); ++i) {
441 const QWindowSystemInterface::TouchPoint &prevPoint(mPrevTouchPoints.at(i));
442 if (prevPoint.state == Qt::TouchPointReleased)
445 for (int j = 0; j < mTouchPoints.count(); ++j)
446 if (mTouchPoints.at(j).id == prevPoint.id) {
451 QWindowSystemInterface::TouchPoint p = prevPoint;
452 p.state = Qt::TouchPointStationary;
453 mTouchPoints.append(p);
457 if (mTouchPoints.isEmpty()) {
458 mPrevTouchPoints.clear();
463 qDebug() << mTouchPoints.count() << "touchpoints, event type" << mTouchState;
464 for (int i = 0; i < mTouchPoints.count(); ++i)
465 qDebug() << " " << mTouchPoints[i].id << mTouchPoints[i].state << mTouchPoints[i].area;
468 QWindowSystemInterface::handleTouchEvent(0, mTouchState, QTouchEvent::TouchScreen, mTouchPoints);
470 bool allReleased = true;
471 for (int i = 0; i < mTouchPoints.count(); ++i)
472 if (mTouchPoints.at(i).state != Qt::TouchPointReleased) {
477 mPrevTouchPoints = mTouchPoints;
478 mTouchPoints.clear();
482 qDebug() << mTouchPoints.count() << "touchpoints, event type" << QEvent::TouchEnd;
484 QWindowSystemInterface::handleTouchEvent(0, QEvent::TouchEnd, QTouchEvent::TouchScreen, mTouchPoints);
485 mTouchState = QEvent::TouchBegin;
486 mPrevTouchPoints.clear();
487 } else if (mTouchState == QEvent::TouchBegin)
488 mTouchState = QEvent::TouchUpdate;
491 void QWaylandInputDevice::inputHandleTouchCancel(void *data, struct wl_input_device *wl_input_device)
495 const struct wl_input_device_listener QWaylandInputDevice::inputDeviceListener = {
496 QWaylandInputDevice::inputHandleMotion,
497 QWaylandInputDevice::inputHandleButton,
498 QWaylandInputDevice::inputHandleKey,
499 QWaylandInputDevice::inputHandlePointerFocus,
500 QWaylandInputDevice::inputHandleKeyboardFocus,
501 QWaylandInputDevice::inputHandleTouchDown,
502 QWaylandInputDevice::inputHandleTouchUp,
503 QWaylandInputDevice::inputHandleTouchMotion,
504 QWaylandInputDevice::inputHandleTouchFrame,
505 QWaylandInputDevice::inputHandleTouchCancel
508 void QWaylandInputDevice::attach(QWaylandBuffer *buffer, int x, int y)
510 wl_input_device_attach(mInputDevice, mTime, buffer->buffer(), x, y);