qtwayland: correct order of parameters in setMouseFocus()
[profile/ivi/qtwayland.git] / src / compositor / wayland_wrapper / wlinputdevice.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 Qt Compositor.
7 **
8 ** $QT_BEGIN_LICENSE:BSD$
9 ** You may use this file under the terms of the BSD license as follows:
10 **
11 ** "Redistribution and use in source and binary forms, with or without
12 ** modification, are permitted provided that the following conditions are
13 ** met:
14 **   * Redistributions of source code must retain the above copyright
15 **     notice, this list of conditions and the following disclaimer.
16 **   * Redistributions in binary form must reproduce the above copyright
17 **     notice, this list of conditions and the following disclaimer in
18 **     the documentation and/or other materials provided with the
19 **     distribution.
20 **   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
21 **     the names of its contributors may be used to endorse or promote
22 **     products derived from this software without specific prior written
23 **     permission.
24 **
25 ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28 ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29 ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30 ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31 ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35 ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
36 **
37 ** $QT_END_LICENSE$
38 **
39 ****************************************************************************/
40
41 #include "wlinputdevice.h"
42
43 #include "wlcompositor.h"
44 #include "wldatadevice.h"
45 #include "wlsurface.h"
46 #include "wltouch.h"
47 #include "wlqtkey.h"
48 #include "waylandcompositor.h"
49
50 #include <QtGui/QTouchEvent>
51
52 namespace Wayland {
53
54 static QImage *currentCursor;
55
56 InputDevice::InputDevice(WaylandInputDevice *handle, Compositor *compositor)
57     : m_handle(handle)
58     , m_compositor(compositor)
59 {
60     wl_seat_init(base());
61     initDevices();
62     wl_display_add_global(compositor->wl_display(),
63                           &wl_seat_interface,
64                           this,
65                           InputDevice::bind_func);
66 }
67
68 InputDevice::~InputDevice()
69 {
70     qDeleteAll(m_data_devices);
71     releaseDevices();
72 }
73
74 void InputDevice::initDevices()
75 {
76     wl_pointer_init(&m_device_interfaces.pointer);
77     wl_seat_set_pointer(base(), &m_device_interfaces.pointer);
78
79     wl_keyboard_init(&m_device_interfaces.keyboard);
80     wl_seat_set_keyboard(base(), &m_device_interfaces.keyboard);
81
82     wl_touch_init(&m_device_interfaces.touch);
83     wl_seat_set_touch(base(), &m_device_interfaces.touch);
84 }
85
86 void InputDevice::releaseDevices()
87 {
88     wl_pointer_release(&m_device_interfaces.pointer);
89     wl_keyboard_release(&m_device_interfaces.keyboard);
90     wl_touch_release(&m_device_interfaces.touch);
91 }
92
93 wl_pointer *InputDevice::pointerDevice()
94 {
95     return &m_device_interfaces.pointer;
96 }
97
98 wl_keyboard *InputDevice::keyboardDevice()
99 {
100     return &m_device_interfaces.keyboard;
101 }
102
103 wl_touch *InputDevice::touchDevice()
104 {
105     return &m_device_interfaces.touch;
106 }
107
108 const wl_pointer *InputDevice::pointerDevice() const
109 {
110     return &m_device_interfaces.pointer;
111 }
112
113 const wl_keyboard *InputDevice::keyboardDevice() const
114 {
115     return &m_device_interfaces.keyboard;
116 }
117
118 const wl_touch *InputDevice::touchDevice() const
119 {
120     return &m_device_interfaces.touch;
121 }
122
123 void InputDevice::destroy_resource(wl_resource *resource)
124 {
125     InputDevice *input_device = static_cast<InputDevice *>(resource->data);
126     if (input_device->keyboardDevice()->focus_resource == resource) {
127         input_device->keyboardDevice()->focus_resource = 0;
128     }
129     if (input_device->pointerDevice()->focus_resource == resource) {
130         input_device->pointerDevice()->focus_resource = 0;
131     }
132
133     input_device->cleanupDataDeviceForClient(resource->client, true);
134
135     wl_list_remove(&resource->link);
136
137     free(resource);
138 }
139
140 void InputDevice::bind_func(struct wl_client *client, void *data,
141                             uint32_t version, uint32_t id)
142 {
143     Q_UNUSED(version);
144     struct wl_resource *resource = wl_client_add_object(client,
145                                                         &wl_seat_interface,
146                                                         &seat_interface,
147                                                         id,
148                                                         data);
149
150     struct wl_seat *seat = static_cast<struct wl_seat *>(data);
151     resource->destroy = destroy_resource;
152     wl_list_insert(&seat->base_resource_list, &resource->link);
153
154     uint32_t caps = WL_SEAT_CAPABILITY_POINTER | WL_SEAT_CAPABILITY_KEYBOARD;
155     if (!QTouchDevice::devices().isEmpty())
156         caps |= WL_SEAT_CAPABILITY_TOUCH;
157
158     wl_seat_send_capabilities(resource, caps);
159 }
160
161 const struct wl_seat_interface InputDevice::seat_interface = {
162     get_pointer,
163     get_keyboard,
164     get_touch
165 };
166
167 void InputDevice::destroy_device_resource(wl_resource *resource)
168 {
169     wl_list_remove(&resource->link);
170     free(resource);
171 }
172
173 void InputDevice::get_pointer(struct wl_client *client,
174                               struct wl_resource *resource,
175                               uint32_t id)
176 {
177     InputDevice *inputDevice = static_cast<InputDevice *>(resource->data);
178     wl_pointer *pointer = inputDevice->pointerDevice();
179     wl_resource *clientResource = wl_client_add_object(client,
180                                                        &wl_pointer_interface,
181                                                        &pointer_interface,
182                                                        id,
183                                                        pointer);
184     wl_list_insert(&pointer->resource_list, &clientResource->link);
185     clientResource->destroy = InputDevice::destroy_device_resource;
186 }
187
188 void InputDevice::get_keyboard(struct wl_client *client,
189                                struct wl_resource *resource,
190                                uint32_t id)
191 {
192     InputDevice *inputDevice = static_cast<InputDevice *>(resource->data);
193     wl_keyboard *keyboard = inputDevice->keyboardDevice();
194     wl_resource *clientResource = wl_client_add_object(client,
195                                                        &wl_keyboard_interface,
196                                                        0,
197                                                        id,
198                                                        keyboard);
199     wl_list_insert(&keyboard->resource_list, &clientResource->link);
200     clientResource->destroy = InputDevice::destroy_device_resource;
201 }
202
203 void InputDevice::get_touch(struct wl_client *client,
204                             struct wl_resource *resource,
205                             uint32_t id)
206 {
207     InputDevice *inputDevice = static_cast<InputDevice *>(resource->data);
208     wl_touch *touch = inputDevice->touchDevice();
209     wl_resource *clientResource = wl_client_add_object(client,
210                                                        &wl_touch_interface,
211                                                        0,
212                                                        id,
213                                                        touch);
214     wl_list_insert(&touch->resource_list, &clientResource->link);
215     clientResource->destroy = InputDevice::destroy_device_resource;
216 }
217
218 void InputDevice::sendMousePressEvent(Qt::MouseButton button, const QPointF &localPos, const QPointF &globalPos)
219 {
220     sendMouseMoveEvent(localPos,globalPos);
221     wl_pointer *pointer = pointerDevice();
222     pointer->button_count++;
223     uint32_t time = m_compositor->currentTimeMsecs();
224     const struct wl_pointer_grab_interface *interface = pointer->grab->interface;
225     interface->button(pointer->grab, time, toWaylandButton(button), 1);
226 }
227
228 void InputDevice::sendMouseReleaseEvent(Qt::MouseButton button, const QPointF &localPos, const QPointF &globalPos)
229 {
230     sendMouseMoveEvent(localPos,globalPos);
231     wl_pointer *pointer = pointerDevice();
232     pointer->button_count--;
233     uint32_t time = m_compositor->currentTimeMsecs();
234     const struct wl_pointer_grab_interface *interface = pointer->grab->interface;
235     interface->button(pointer->grab, time, toWaylandButton(button), 0);
236 }
237
238 void InputDevice::sendMouseMoveEvent(const QPointF &localPos, const QPointF &globalPos)
239 {
240     Q_UNUSED(globalPos);
241     uint32_t time = m_compositor->currentTimeMsecs();
242     wl_pointer *pointer = pointerDevice();
243     const struct wl_pointer_grab_interface *interface = pointer->grab->interface;
244     pointer->x = wl_fixed_from_double(globalPos.x());
245     pointer->y = wl_fixed_from_double(globalPos.y());
246     interface->motion(pointer->grab,
247                       time,
248                       wl_fixed_from_double(localPos.x()), wl_fixed_from_double(localPos.y()));
249 }
250
251 void InputDevice::sendMouseMoveEvent(Surface *surface, const QPointF &localPos, const QPointF &globalPos)
252 {
253     setMouseFocus(surface,localPos,globalPos);
254     sendMouseMoveEvent(localPos,globalPos);
255 }
256
257 void InputDevice::sendMouseWheelEvent(Qt::Orientation orientation, int delta)
258 {
259     wl_pointer *pointer = pointerDevice();
260     struct wl_resource *resource = pointer->focus_resource;
261     if (!resource)
262         return;
263     uint32_t time = m_compositor->currentTimeMsecs();
264     uint32_t axis = orientation == Qt::Horizontal ? WL_POINTER_AXIS_HORIZONTAL_SCROLL
265                                                   : WL_POINTER_AXIS_VERTICAL_SCROLL;
266     wl_pointer_send_axis(resource, time, axis, wl_fixed_from_double(delta / 120.0));
267 }
268
269 void InputDevice::sendKeyPressEvent(uint code)
270 {
271     wl_keyboard *keyboard = keyboardDevice();
272     if (keyboard->focus_resource) {
273         uint32_t time = m_compositor->currentTimeMsecs();
274         uint32_t serial = wl_display_next_serial(m_compositor->wl_display());
275         wl_keyboard_send_key(keyboard->focus_resource,
276                              serial, time, code - 8, 1);
277     }
278 }
279
280 void InputDevice::sendKeyReleaseEvent(uint code)
281 {
282     wl_keyboard *keyboard = keyboardDevice();
283     if (keyboard->focus_resource) {
284         uint32_t time = m_compositor->currentTimeMsecs();
285         uint32_t serial = wl_display_next_serial(m_compositor->wl_display());
286         wl_keyboard_send_key(keyboard->focus_resource,
287                              serial, time, code - 8, 0);
288     }
289 }
290
291 void InputDevice::sendTouchPointEvent(int id, double x, double y, Qt::TouchPointState state)
292 {
293     uint32_t time = m_compositor->currentTimeMsecs();
294     uint32_t serial = 0;
295     wl_touch *touch = touchDevice();
296     wl_resource *resource = touch->focus_resource;
297     if (!resource)
298         return;
299     switch (state) {
300     case Qt::TouchPointPressed:
301         wl_touch_send_down(resource, serial, time, &touch->focus->resource, id,
302                            wl_fixed_from_double(x), wl_fixed_from_double(y));
303         break;
304     case Qt::TouchPointMoved:
305         wl_touch_send_motion(resource, time, id,
306                              wl_fixed_from_double(x), wl_fixed_from_double(y));
307         break;
308     case Qt::TouchPointReleased:
309         wl_touch_send_up(resource, serial, time, id);
310         break;
311     case Qt::TouchPointStationary:
312         // stationary points are not sent through wayland, the client must cache them
313         break;
314     default:
315         break;
316     }
317 }
318
319 void InputDevice::sendTouchFrameEvent()
320 {
321     wl_touch *touch = touchDevice();
322     wl_resource *resource = touch->focus_resource;
323     if (resource)
324         wl_touch_send_frame(resource);
325 }
326
327 void InputDevice::sendTouchCancelEvent()
328 {
329     wl_touch *touch = touchDevice();
330     wl_resource *resource = touch->focus_resource;
331     if (resource)
332         wl_touch_send_cancel(resource);
333 }
334
335 void InputDevice::sendFullKeyEvent(QKeyEvent *event)
336 {
337     if (!keyboardFocus()) {
338         qWarning("Cannot send key event, no keyboard focus, fix the compositor");
339         return;
340     }
341
342     QtKeyExtensionGlobal *ext = m_compositor->qtkeyExtension();
343     if (ext && ext->postQtKeyEvent(event, keyboardFocus()))
344         return;
345
346     if (event->type() == QEvent::KeyPress)
347         sendKeyPressEvent(event->nativeScanCode());
348     else if (event->type() == QEvent::KeyRelease)
349         sendKeyReleaseEvent(event->nativeScanCode());
350 }
351
352 void InputDevice::sendFullTouchEvent(QTouchEvent *event)
353 {
354     if (!mouseFocus()) {
355         qWarning("Cannot send touch event, no pointer focus, fix the compositor");
356         return;
357     }
358
359     if (event->type() == QEvent::TouchCancel) {
360         sendTouchCancelEvent();
361         return;
362     }
363
364     TouchExtensionGlobal *ext = m_compositor->touchExtension();
365     if (ext && ext->postTouchEvent(event, mouseFocus()))
366         return;
367
368     const QList<QTouchEvent::TouchPoint> points = event->touchPoints();
369     if (points.isEmpty())
370         return;
371
372     const int pointCount = points.count();
373     QPointF pos = mouseFocus()->pos();
374     for (int i = 0; i < pointCount; ++i) {
375         const QTouchEvent::TouchPoint &tp(points.at(i));
376         // Convert the local pos in the compositor window to surface-relative.
377         QPointF p = tp.pos() - pos;
378         sendTouchPointEvent(tp.id(), p.x(), p.y(), tp.state());
379     }
380     sendTouchFrameEvent();
381 }
382
383 Surface *InputDevice::keyboardFocus() const
384 {
385     return wayland_cast<Surface>(keyboardDevice()->focus);
386 }
387
388 /*!
389  * \return True if the keyboard focus is changed successfully. False for inactive transient surfaces.
390  */
391 bool InputDevice::setKeyboardFocus(Surface *surface)
392 {
393     if (surface && surface->transientInactive())
394         return false;
395
396     sendSelectionFocus(surface);
397     wl_keyboard_set_focus(keyboardDevice(), surface ? surface->base() : 0);
398     return true;
399 }
400
401 Surface *InputDevice::mouseFocus() const
402 {
403     return wayland_cast<Surface>(pointerDevice()->focus);
404 }
405
406 void InputDevice::setMouseFocus(Surface *surface, const QPointF &localPos, const QPointF &globalPos)
407 {
408     wl_pointer *pointer = pointerDevice();
409     pointer->x = wl_fixed_from_double(globalPos.x());
410     pointer->y = wl_fixed_from_double(globalPos.y());
411     pointer->current = surface ? surface->base() : 0;
412     pointer->current_x = wl_fixed_from_double(localPos.x());
413     pointer->current_y = wl_fixed_from_double(localPos.y());
414     pointer->grab->interface->focus(pointer->grab,
415                                     surface ? surface->base() : 0,
416                                     wl_fixed_from_double(localPos.x()), wl_fixed_from_double(localPos.y()));
417
418     // We have no separate touch focus management so make it match the pointer focus always.
419     // No wl_touch_set_focus() is available so set it manually.
420     wl_touch *touch = touchDevice();
421     touch->focus = surface ? surface->base() : 0;
422     touch->focus_resource = Compositor::resourceForSurface(&touch->resource_list, surface);
423 }
424
425 void InputDevice::cleanupDataDeviceForClient(struct wl_client *client, bool destroyDev)
426 {
427     for (int i = 0; i < m_data_devices.size(); i++) {
428         struct wl_resource *data_device_resource =
429                 m_data_devices.at(i)->dataDeviceResource();
430         if (data_device_resource->client == client) {
431             if (destroyDev)
432                 delete m_data_devices.at(i);
433             m_data_devices.removeAt(i);
434             break;
435         }
436     }
437 }
438
439 void InputDevice::clientRequestedDataDevice(DataDeviceManager *data_device_manager, struct wl_client *client, uint32_t id)
440 {
441     cleanupDataDeviceForClient(client, false);
442     DataDevice *dataDevice = new DataDevice(data_device_manager,client,id);
443     m_data_devices.append(dataDevice);
444 }
445
446 void InputDevice::sendSelectionFocus(Surface *surface)
447 {
448     if (!surface)
449         return;
450     DataDevice *device = dataDevice(surface->base()->resource.client);
451     if (device) {
452         device->sendSelectionFocus();
453     }
454 }
455
456 Compositor *InputDevice::compositor() const
457 {
458     return m_compositor;
459 }
460
461 WaylandInputDevice *InputDevice::handle() const
462 {
463     return m_handle;
464 }
465
466 uint32_t InputDevice::toWaylandButton(Qt::MouseButton button)
467 {
468 #ifndef BTN_LEFT
469     uint32_t BTN_LEFT = 0x110;
470 #endif
471     // the range of valid buttons (evdev module) is from 0x110
472     // through 0x11f. 0x120 is the first 'Joystick' button.
473     switch (button) {
474     case Qt::LeftButton: return BTN_LEFT;
475     case Qt::RightButton: return uint32_t(0x111);
476     case Qt::MiddleButton: return uint32_t(0x112);
477     case Qt::ExtraButton1: return uint32_t(0x113);  // AKA Qt::BackButton, Qt::XButton1
478     case Qt::ExtraButton2: return uint32_t(0x114);  // AKA Qt::ForwardButton, Qt::XButton2
479     case Qt::ExtraButton3: return uint32_t(0x115);
480     case Qt::ExtraButton4: return uint32_t(0x116);
481     case Qt::ExtraButton5: return uint32_t(0x117);
482     case Qt::ExtraButton6: return uint32_t(0x118);
483     case Qt::ExtraButton7: return uint32_t(0x119);
484     case Qt::ExtraButton8: return uint32_t(0x11a);
485     case Qt::ExtraButton9: return uint32_t(0x11b);
486     case Qt::ExtraButton10: return uint32_t(0x11c);
487     case Qt::ExtraButton11: return uint32_t(0x11d);
488     case Qt::ExtraButton12: return uint32_t(0x11e);
489     case Qt::ExtraButton13: return uint32_t(0x11f);
490         // default should not occur; but if it does, then return Wayland's highest possible button number.
491     default: return uint32_t(0x11f);
492     }
493 }
494
495 DataDevice *InputDevice::dataDevice(struct wl_client *client) const
496 {
497     for (int i = 0; i < m_data_devices.size();i++) {
498         if (m_data_devices.at(i)->dataDeviceResource()->client == client) {
499             return m_data_devices.at(i);
500         }
501     }
502     return 0;
503 }
504
505 const struct wl_pointer_interface InputDevice::pointer_interface = {
506     InputDevice::pointer_attach
507 };
508
509 void InputDevice::pointer_attach(struct wl_client *client,
510                                  struct wl_resource *device_resource,
511                                  uint32_t serial,
512                                  struct wl_resource *buffer_resource, int32_t x, int32_t y)
513 {
514     Q_UNUSED(client);
515     Q_UNUSED(serial);
516
517     wl_pointer *pointer = reinterpret_cast<wl_pointer *>(device_resource->data);
518     InputDevice *inputDevice = wayland_cast<InputDevice>(pointer->seat);
519     wl_buffer *buffer = reinterpret_cast<wl_buffer *>(buffer_resource);
520
521     if (wl_buffer_is_shm(buffer)) {
522         int stride = wl_shm_buffer_get_stride(buffer);
523         uint format = wl_shm_buffer_get_format(buffer);
524         (void) format;
525         void *data = wl_shm_buffer_get_data(buffer);
526         const uchar *char_data = static_cast<const uchar *>(data);
527         if (char_data) {
528             QImage *img = new QImage(char_data, buffer->width, buffer->height, stride, QImage::Format_ARGB32_Premultiplied);
529             inputDevice->m_compositor->waylandCompositor()->changeCursor(*img, x, y);
530             delete currentCursor;
531             currentCursor = img;
532         }
533     }
534 }
535
536
537 }