47f9c91fd8c64bda294533bb4e1bbe92911acb65
[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 ** No Commercial Usage
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
14 ** this package.
15 **
16 ** GNU Lesser General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU Lesser
18 ** General Public License version 2.1 as published by the Free Software
19 ** Foundation and appearing in the file LICENSE.LGPL included in the
20 ** packaging of this file.  Please review the following information to
21 ** ensure the GNU Lesser General Public License version 2.1 requirements
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23 **
24 ** In addition, as a special exception, Nokia gives you certain additional
25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27 **
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
30 **
31 **
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
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))
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::inputHandleMotion(void *data,
87                                             struct wl_input_device *input_device,
88                                             uint32_t time,
89                                             int32_t x, int32_t y,
90                                             int32_t surface_x, int32_t surface_y)
91 {
92     Q_UNUSED(input_device);
93     QWaylandInputDevice *inputDevice = (QWaylandInputDevice *) data;
94     QWaylandWindow *window = inputDevice->mPointerFocus;
95
96     inputDevice->mSurfacePos = QPoint(surface_x, surface_y);
97     inputDevice->mGlobalPos = QPoint(x, y);
98     inputDevice->mTime = time;
99     QWindowSystemInterface::handleMouseEvent(window->widget(),
100                                              time,
101                                              inputDevice->mSurfacePos,
102                                              inputDevice->mGlobalPos,
103                                              inputDevice->mButtons);
104 }
105
106 void QWaylandInputDevice::inputHandleButton(void *data,
107                                             struct wl_input_device *input_device,
108                                             uint32_t time, uint32_t button, uint32_t state)
109 {
110     Q_UNUSED(input_device);
111     QWaylandInputDevice *inputDevice = (QWaylandInputDevice *) data;
112     QWaylandWindow *window = inputDevice->mPointerFocus;
113     Qt::MouseButton qt_button;
114
115     switch (button) {
116     case 272:
117         qt_button = Qt::LeftButton;
118         break;
119     case 273:
120         qt_button = Qt::RightButton;
121         break;
122     case 274:
123         qt_button = Qt::MiddleButton;
124         break;
125     default:
126         return;
127     }
128
129     if (state)
130         inputDevice->mButtons |= qt_button;
131     else
132         inputDevice->mButtons &= ~qt_button;
133
134     inputDevice->mTime = time;
135     QWindowSystemInterface::handleMouseEvent(window->widget(),
136                                              time,
137                                              inputDevice->mSurfacePos,
138                                              inputDevice->mGlobalPos,
139                                              inputDevice->mButtons);
140 }
141
142 #ifndef QT_NO_WAYLAND_XKB
143 static Qt::KeyboardModifiers translateModifiers(int s)
144 {
145     const uchar qt_alt_mask = XKB_COMMON_MOD1_MASK;
146     const uchar qt_meta_mask = XKB_COMMON_MOD4_MASK;
147
148     Qt::KeyboardModifiers ret = 0;
149     if (s & XKB_COMMON_SHIFT_MASK)
150         ret |= Qt::ShiftModifier;
151     if (s & XKB_COMMON_CONTROL_MASK)
152         ret |= Qt::ControlModifier;
153     if (s & qt_alt_mask)
154         ret |= Qt::AltModifier;
155     if (s & qt_meta_mask)
156         ret |= Qt::MetaModifier;
157
158     return ret;
159 }
160
161 static uint32_t translateKey(uint32_t sym, char *string, size_t size)
162 {
163     Q_UNUSED(size);
164     string[0] = '\0';
165
166     switch (sym) {
167     case XK_Escape:             return Qt::Key_Escape;
168     case XK_Tab:                return Qt::Key_Tab;
169     case XK_ISO_Left_Tab:       return Qt::Key_Backtab;
170     case XK_BackSpace:          return Qt::Key_Backspace;
171     case XK_Return:             return Qt::Key_Return;
172     case XK_Insert:             return Qt::Key_Insert;
173     case XK_Delete:             return Qt::Key_Delete;
174     case XK_Clear:              return Qt::Key_Delete;
175     case XK_Pause:              return Qt::Key_Pause;
176     case XK_Print:              return Qt::Key_Print;
177
178     case XK_Home:               return Qt::Key_Home;
179     case XK_End:                return Qt::Key_End;
180     case XK_Left:               return Qt::Key_Left;
181     case XK_Up:                 return Qt::Key_Up;
182     case XK_Right:              return Qt::Key_Right;
183     case XK_Down:               return Qt::Key_Down;
184     case XK_Prior:              return Qt::Key_PageUp;
185     case XK_Next:               return Qt::Key_PageDown;
186
187     case XK_Shift_L:            return Qt::Key_Shift;
188     case XK_Shift_R:            return Qt::Key_Shift;
189     case XK_Shift_Lock:         return Qt::Key_Shift;
190     case XK_Control_L:          return Qt::Key_Control;
191     case XK_Control_R:          return Qt::Key_Control;
192     case XK_Meta_L:             return Qt::Key_Meta;
193     case XK_Meta_R:             return Qt::Key_Meta;
194     case XK_Alt_L:              return Qt::Key_Alt;
195     case XK_Alt_R:              return Qt::Key_Alt;
196     case XK_Caps_Lock:          return Qt::Key_CapsLock;
197     case XK_Num_Lock:           return Qt::Key_NumLock;
198     case XK_Scroll_Lock:        return Qt::Key_ScrollLock;
199     case XK_Super_L:            return Qt::Key_Super_L;
200     case XK_Super_R:            return Qt::Key_Super_R;
201     case XK_Menu:               return Qt::Key_Menu;
202
203     default:
204         string[0] = sym;
205         string[1] = '\0';
206         return toupper(sym);
207     }
208 }
209 #endif
210
211 void QWaylandInputDevice::inputHandleKey(void *data,
212                                          struct wl_input_device *input_device,
213                                          uint32_t time, uint32_t key, uint32_t state)
214 {
215 #ifndef QT_NO_WAYLAND_XKB
216     Q_UNUSED(input_device);
217     QWaylandInputDevice *inputDevice = (QWaylandInputDevice *) data;
218     QWaylandWindow *window = inputDevice->mKeyboardFocus;
219     uint32_t code, sym, level;
220     Qt::KeyboardModifiers modifiers;
221     QEvent::Type type;
222     char s[2];
223
224     code = key + inputDevice->mXkb->min_key_code;
225
226     level = 0;
227     if (inputDevice->mModifiers & Qt::ShiftModifier &&
228         XkbKeyGroupWidth(inputDevice->mXkb, code, 0) > 1)
229         level = 1;
230
231     sym = XkbKeySymEntry(inputDevice->mXkb, code, level, 0);
232
233     modifiers = translateModifiers(inputDevice->mXkb->map->modmap[code]);
234
235     if (state) {
236         inputDevice->mModifiers |= modifiers;
237         type = QEvent::KeyPress;
238     } else {
239         inputDevice->mModifiers &= ~modifiers;
240         type = QEvent::KeyRelease;
241     }
242
243     sym = translateKey(sym, s, sizeof s);
244
245     qWarning("keycode %d, sym %d, string %d, modifiers 0x%x",
246              code, sym, s[0], (int) inputDevice->mModifiers);
247
248     if (window) {
249         QWindowSystemInterface::handleKeyEvent(window->widget(),
250                                                time, type, sym,
251                                                inputDevice->mModifiers,
252                                                QString::fromLatin1(s));
253     }
254 #endif
255 }
256
257 void QWaylandInputDevice::inputHandlePointerFocus(void *data,
258                                                   struct wl_input_device *input_device,
259                                                   uint32_t time, struct wl_surface *surface,
260                                                   int32_t x, int32_t y, int32_t sx, int32_t sy)
261 {
262     Q_UNUSED(input_device);
263     Q_UNUSED(x);
264     Q_UNUSED(y);
265     Q_UNUSED(sx);
266     Q_UNUSED(sy);
267     QWaylandInputDevice *inputDevice = (QWaylandInputDevice *) data;
268     QWaylandWindow *window;
269
270     if (inputDevice->mPointerFocus) {
271         window = inputDevice->mPointerFocus;
272         QWindowSystemInterface::handleLeaveEvent(window->widget());
273         inputDevice->mPointerFocus = NULL;
274     }
275
276     if (surface) {
277         window = (QWaylandWindow *) wl_surface_get_user_data(surface);
278         QWindowSystemInterface::handleEnterEvent(window->widget());
279         inputDevice->mPointerFocus = window;
280     }
281
282     inputDevice->mTime = time;
283 }
284
285 void QWaylandInputDevice::inputHandleKeyboardFocus(void *data,
286                                                    struct wl_input_device *input_device,
287                                                    uint32_t time,
288                                                    struct wl_surface *surface,
289                                                    struct wl_array *keys)
290 {
291 #ifndef QT_NO_WAYLAND_XKB
292     Q_UNUSED(input_device);
293     Q_UNUSED(time);
294     QWaylandInputDevice *inputDevice = (QWaylandInputDevice *) data;
295     QWaylandWindow *window;
296     uint32_t *k, *end;
297     uint32_t code;
298
299     end = (uint32_t *) ((char *) keys->data + keys->size);
300     inputDevice->mModifiers = 0;
301     for (k = (uint32_t *) keys->data; k < end; k++) {
302         code = *k + inputDevice->mXkb->min_key_code;
303         inputDevice->mModifiers |=
304             translateModifiers(inputDevice->mXkb->map->modmap[code]);
305     }
306
307     if (surface) {
308         window = (QWaylandWindow *) wl_surface_get_user_data(surface);
309         inputDevice->mKeyboardFocus = window;
310         QWindowSystemInterface::handleWindowActivated(window->widget());
311     } else {
312         inputDevice->mKeyboardFocus = NULL;
313         QWindowSystemInterface::handleWindowActivated(0);
314     }
315 #endif
316 }
317
318 const struct wl_input_device_listener QWaylandInputDevice::inputDeviceListener = {
319     QWaylandInputDevice::inputHandleMotion,
320     QWaylandInputDevice::inputHandleButton,
321     QWaylandInputDevice::inputHandleKey,
322     QWaylandInputDevice::inputHandlePointerFocus,
323     QWaylandInputDevice::inputHandleKeyboardFocus,
324 };
325
326 void QWaylandInputDevice::attach(QWaylandBuffer *buffer, int x, int y)
327 {
328     wl_input_device_attach(mInputDevice, mTime, buffer->buffer(), x, y);
329 }