d1da57d81dd2baf19aaf07ab16be2cfce8a19116
[profile/ivi/qtwayland.git] / src / plugins / platforms / wayland / qwaylandinputdevice.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
6 **
7 ** This file is part of the plugins of the Qt Toolkit.
8 **
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.
17 **
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.
21 **
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.
29 **
30 ** Other Usage
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.
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
48 #include <QWindowSystemInterface>
49
50 #include <QtGui/private/qpixmap_raster_p.h>
51 #include <QtGui/QPlatformWindow>
52
53 #include <unistd.h>
54 #include <fcntl.h>
55
56 #ifndef QT_NO_WAYLAND_XKB
57 #include <X11/extensions/XKBcommon.h>
58 #include <X11/keysym.h>
59 #endif
60
61 QWaylandInputDevice::QWaylandInputDevice(struct wl_display *display,
62                                          uint32_t id)
63     : mDisplay(display)
64     , mInputDevice(wl_input_device_create(display, id, 1))
65     , mPointerFocus(NULL)
66     , mKeyboardFocus(NULL)
67     , mButtons(0)
68 {
69     wl_input_device_add_listener(mInputDevice,
70                                  &inputDeviceListener,
71                                  this);
72     wl_input_device_set_user_data(mInputDevice, this);
73
74 #ifndef QT_NO_WAYLAND_XKB
75     struct xkb_rule_names names;
76     names.rules = "evdev";
77     names.model = "pc105";
78     names.layout = "us";
79     names.variant = "";
80     names.options = "";
81
82     mXkb = xkb_compile_keymap_from_rules(&names);
83 #endif
84 }
85
86 void QWaylandInputDevice::handleWindowDestroyed(QWaylandWindow *window)
87 {
88     if (window == mPointerFocus)
89         mPointerFocus = 0;
90     if (window == mKeyboardFocus)
91         mKeyboardFocus = 0;
92 }
93
94 void QWaylandInputDevice::inputHandleMotion(void *data,
95                                             struct wl_input_device *input_device,
96                                             uint32_t time,
97                                             int32_t x, int32_t y,
98                                             int32_t surface_x, int32_t surface_y)
99 {
100     Q_UNUSED(input_device);
101     QWaylandInputDevice *inputDevice = (QWaylandInputDevice *) data;
102     QWaylandWindow *window = inputDevice->mPointerFocus;
103
104     if (window == NULL) {
105         /* We destroyed the pointer focus surface, but the server
106          * didn't get the message yet. */
107         return;
108     }
109
110     inputDevice->mSurfacePos = QPoint(surface_x, surface_y);
111     inputDevice->mGlobalPos = QPoint(x, y);
112     inputDevice->mTime = time;
113     QWindowSystemInterface::handleMouseEvent(window->widget(),
114                                              time,
115                                              inputDevice->mSurfacePos,
116                                              inputDevice->mGlobalPos,
117                                              inputDevice->mButtons);
118 }
119
120 void QWaylandInputDevice::inputHandleButton(void *data,
121                                             struct wl_input_device *input_device,
122                                             uint32_t time, uint32_t button, uint32_t state)
123 {
124     Q_UNUSED(input_device);
125     QWaylandInputDevice *inputDevice = (QWaylandInputDevice *) data;
126     QWaylandWindow *window = inputDevice->mPointerFocus;
127     Qt::MouseButton qt_button;
128
129     if (window == NULL) {
130         /* We destroyed the pointer focus surface, but the server
131          * didn't get the message yet. */
132         return;
133     }
134
135     switch (button) {
136     case 272:
137         qt_button = Qt::LeftButton;
138         break;
139     case 273:
140         qt_button = Qt::RightButton;
141         break;
142     case 274:
143         qt_button = Qt::MiddleButton;
144         break;
145     default:
146         return;
147     }
148
149     if (state)
150         inputDevice->mButtons |= qt_button;
151     else
152         inputDevice->mButtons &= ~qt_button;
153
154     inputDevice->mTime = time;
155     QWindowSystemInterface::handleMouseEvent(window->widget(),
156                                              time,
157                                              inputDevice->mSurfacePos,
158                                              inputDevice->mGlobalPos,
159                                              inputDevice->mButtons);
160 }
161
162 #ifndef QT_NO_WAYLAND_XKB
163 static Qt::KeyboardModifiers translateModifiers(int s)
164 {
165     const uchar qt_alt_mask = XKB_COMMON_MOD1_MASK;
166     const uchar qt_meta_mask = XKB_COMMON_MOD4_MASK;
167
168     Qt::KeyboardModifiers ret = 0;
169     if (s & XKB_COMMON_SHIFT_MASK)
170         ret |= Qt::ShiftModifier;
171     if (s & XKB_COMMON_CONTROL_MASK)
172         ret |= Qt::ControlModifier;
173     if (s & qt_alt_mask)
174         ret |= Qt::AltModifier;
175     if (s & qt_meta_mask)
176         ret |= Qt::MetaModifier;
177
178     return ret;
179 }
180
181 static uint32_t translateKey(uint32_t sym, char *string, size_t size)
182 {
183     Q_UNUSED(size);
184     string[0] = '\0';
185
186     switch (sym) {
187     case XK_Escape:             return Qt::Key_Escape;
188     case XK_Tab:                return Qt::Key_Tab;
189     case XK_ISO_Left_Tab:       return Qt::Key_Backtab;
190     case XK_BackSpace:          return Qt::Key_Backspace;
191     case XK_Return:             return Qt::Key_Return;
192     case XK_Insert:             return Qt::Key_Insert;
193     case XK_Delete:             return Qt::Key_Delete;
194     case XK_Clear:              return Qt::Key_Delete;
195     case XK_Pause:              return Qt::Key_Pause;
196     case XK_Print:              return Qt::Key_Print;
197
198     case XK_Home:               return Qt::Key_Home;
199     case XK_End:                return Qt::Key_End;
200     case XK_Left:               return Qt::Key_Left;
201     case XK_Up:                 return Qt::Key_Up;
202     case XK_Right:              return Qt::Key_Right;
203     case XK_Down:               return Qt::Key_Down;
204     case XK_Prior:              return Qt::Key_PageUp;
205     case XK_Next:               return Qt::Key_PageDown;
206
207     case XK_Shift_L:            return Qt::Key_Shift;
208     case XK_Shift_R:            return Qt::Key_Shift;
209     case XK_Shift_Lock:         return Qt::Key_Shift;
210     case XK_Control_L:          return Qt::Key_Control;
211     case XK_Control_R:          return Qt::Key_Control;
212     case XK_Meta_L:             return Qt::Key_Meta;
213     case XK_Meta_R:             return Qt::Key_Meta;
214     case XK_Alt_L:              return Qt::Key_Alt;
215     case XK_Alt_R:              return Qt::Key_Alt;
216     case XK_Caps_Lock:          return Qt::Key_CapsLock;
217     case XK_Num_Lock:           return Qt::Key_NumLock;
218     case XK_Scroll_Lock:        return Qt::Key_ScrollLock;
219     case XK_Super_L:            return Qt::Key_Super_L;
220     case XK_Super_R:            return Qt::Key_Super_R;
221     case XK_Menu:               return Qt::Key_Menu;
222
223     default:
224         string[0] = sym;
225         string[1] = '\0';
226         return toupper(sym);
227     }
228 }
229 #endif
230
231 void QWaylandInputDevice::inputHandleKey(void *data,
232                                          struct wl_input_device *input_device,
233                                          uint32_t time, uint32_t key, uint32_t state)
234 {
235 #ifndef QT_NO_WAYLAND_XKB
236     Q_UNUSED(input_device);
237     QWaylandInputDevice *inputDevice = (QWaylandInputDevice *) data;
238     QWaylandWindow *window = inputDevice->mKeyboardFocus;
239     uint32_t code, sym, level;
240     Qt::KeyboardModifiers modifiers;
241     QEvent::Type type;
242     char s[2];
243
244     if (window == NULL) {
245         /* We destroyed the keyboard focus surface, but the server
246          * didn't get the message yet. */
247         return;
248     }
249
250     code = key + inputDevice->mXkb->min_key_code;
251
252     level = 0;
253     if (inputDevice->mModifiers & Qt::ShiftModifier &&
254         XkbKeyGroupWidth(inputDevice->mXkb, code, 0) > 1)
255         level = 1;
256
257     sym = XkbKeySymEntry(inputDevice->mXkb, code, level, 0);
258
259     modifiers = translateModifiers(inputDevice->mXkb->map->modmap[code]);
260
261     if (state) {
262         inputDevice->mModifiers |= modifiers;
263         type = QEvent::KeyPress;
264     } else {
265         inputDevice->mModifiers &= ~modifiers;
266         type = QEvent::KeyRelease;
267     }
268
269     sym = translateKey(sym, s, sizeof s);
270
271     if (window) {
272         QWindowSystemInterface::handleKeyEvent(window->widget(),
273                                                time, type, sym,
274                                                inputDevice->mModifiers,
275                                                QString::fromLatin1(s));
276     }
277 #endif
278 }
279
280 void QWaylandInputDevice::inputHandlePointerFocus(void *data,
281                                                   struct wl_input_device *input_device,
282                                                   uint32_t time, struct wl_surface *surface,
283                                                   int32_t x, int32_t y, int32_t sx, int32_t sy)
284 {
285     Q_UNUSED(input_device);
286     Q_UNUSED(x);
287     Q_UNUSED(y);
288     Q_UNUSED(sx);
289     Q_UNUSED(sy);
290     QWaylandInputDevice *inputDevice = (QWaylandInputDevice *) data;
291     QWaylandWindow *window;
292
293     if (inputDevice->mPointerFocus) {
294         window = inputDevice->mPointerFocus;
295         QWindowSystemInterface::handleLeaveEvent(window->widget());
296         inputDevice->mPointerFocus = NULL;
297     }
298
299     if (surface) {
300         window = (QWaylandWindow *) wl_surface_get_user_data(surface);
301         QWindowSystemInterface::handleEnterEvent(window->widget());
302         inputDevice->mPointerFocus = window;
303     }
304
305     inputDevice->mTime = time;
306 }
307
308 void QWaylandInputDevice::inputHandleKeyboardFocus(void *data,
309                                                    struct wl_input_device *input_device,
310                                                    uint32_t time,
311                                                    struct wl_surface *surface,
312                                                    struct wl_array *keys)
313 {
314 #ifndef QT_NO_WAYLAND_XKB
315     Q_UNUSED(input_device);
316     Q_UNUSED(time);
317     QWaylandInputDevice *inputDevice = (QWaylandInputDevice *) data;
318     QWaylandWindow *window;
319     uint32_t *k, *end;
320     uint32_t code;
321
322     end = (uint32_t *) ((char *) keys->data + keys->size);
323     inputDevice->mModifiers = 0;
324     for (k = (uint32_t *) keys->data; k < end; k++) {
325         code = *k + inputDevice->mXkb->min_key_code;
326         inputDevice->mModifiers |=
327             translateModifiers(inputDevice->mXkb->map->modmap[code]);
328     }
329
330     if (surface) {
331         window = (QWaylandWindow *) wl_surface_get_user_data(surface);
332         inputDevice->mKeyboardFocus = window;
333         QWindowSystemInterface::handleWindowActivated(window->widget());
334     } else {
335         inputDevice->mKeyboardFocus = NULL;
336         QWindowSystemInterface::handleWindowActivated(0);
337     }
338 #endif
339 }
340
341 const struct wl_input_device_listener QWaylandInputDevice::inputDeviceListener = {
342     QWaylandInputDevice::inputHandleMotion,
343     QWaylandInputDevice::inputHandleButton,
344     QWaylandInputDevice::inputHandleKey,
345     QWaylandInputDevice::inputHandlePointerFocus,
346     QWaylandInputDevice::inputHandleKeyboardFocus,
347 };
348
349 void QWaylandInputDevice::attach(QWaylandBuffer *buffer, int x, int y)
350 {
351     wl_input_device_attach(mInputDevice, mTime, buffer->buffer(), x, y);
352 }