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 Qt Compositor.
8 ** $QT_BEGIN_LICENSE:BSD$
9 ** You may use this file under the terms of the BSD license as follows:
11 ** "Redistribution and use in source and binary forms, with or without
12 ** modification, are permitted provided that the following conditions are
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
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
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."
39 ****************************************************************************/
41 #include "wlinputdevice.h"
43 #include "wlcompositor.h"
44 #include "wldatadevice.h"
45 #include "wlsurface.h"
48 #include "waylandcompositor.h"
50 #include <QtGui/QTouchEvent>
54 static QImage *currentCursor;
56 InputDevice::InputDevice(WaylandInputDevice *handle, Compositor *compositor)
58 , m_compositor(compositor)
62 wl_display_add_global(compositor->wl_display(),
65 InputDevice::bind_func);
68 InputDevice::~InputDevice()
70 qDeleteAll(m_data_devices);
74 void InputDevice::initDevices()
76 wl_pointer_init(&m_device_interfaces.pointer);
77 wl_seat_set_pointer(base(), &m_device_interfaces.pointer);
79 wl_keyboard_init(&m_device_interfaces.keyboard);
80 wl_seat_set_keyboard(base(), &m_device_interfaces.keyboard);
82 wl_touch_init(&m_device_interfaces.touch);
83 wl_seat_set_touch(base(), &m_device_interfaces.touch);
86 void InputDevice::releaseDevices()
88 wl_pointer_release(&m_device_interfaces.pointer);
89 wl_keyboard_release(&m_device_interfaces.keyboard);
90 wl_touch_release(&m_device_interfaces.touch);
93 wl_pointer *InputDevice::pointerDevice()
95 return &m_device_interfaces.pointer;
98 wl_keyboard *InputDevice::keyboardDevice()
100 return &m_device_interfaces.keyboard;
103 wl_touch *InputDevice::touchDevice()
105 return &m_device_interfaces.touch;
108 const wl_pointer *InputDevice::pointerDevice() const
110 return &m_device_interfaces.pointer;
113 const wl_keyboard *InputDevice::keyboardDevice() const
115 return &m_device_interfaces.keyboard;
118 const wl_touch *InputDevice::touchDevice() const
120 return &m_device_interfaces.touch;
123 void InputDevice::destroy_resource(wl_resource *resource)
125 InputDevice *input_device = static_cast<InputDevice *>(resource->data);
126 if (input_device->keyboardDevice()->focus_resource == resource) {
127 input_device->keyboardDevice()->focus_resource = 0;
129 if (input_device->pointerDevice()->focus_resource == resource) {
130 input_device->pointerDevice()->focus_resource = 0;
133 input_device->cleanupDataDeviceForClient(resource->client, true);
135 wl_list_remove(&resource->link);
140 void InputDevice::bind_func(struct wl_client *client, void *data,
141 uint32_t version, uint32_t id)
144 struct wl_resource *resource = wl_client_add_object(client,
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);
154 uint32_t caps = WL_SEAT_CAPABILITY_POINTER | WL_SEAT_CAPABILITY_KEYBOARD;
155 if (!QTouchDevice::devices().isEmpty())
156 caps |= WL_SEAT_CAPABILITY_TOUCH;
158 wl_seat_send_capabilities(resource, caps);
161 const struct wl_seat_interface InputDevice::seat_interface = {
167 void InputDevice::destroy_device_resource(wl_resource *resource)
169 wl_list_remove(&resource->link);
173 void InputDevice::get_pointer(struct wl_client *client,
174 struct wl_resource *resource,
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,
184 wl_list_insert(&pointer->resource_list, &clientResource->link);
185 clientResource->destroy = InputDevice::destroy_device_resource;
188 void InputDevice::get_keyboard(struct wl_client *client,
189 struct wl_resource *resource,
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,
199 wl_list_insert(&keyboard->resource_list, &clientResource->link);
200 clientResource->destroy = InputDevice::destroy_device_resource;
203 void InputDevice::get_touch(struct wl_client *client,
204 struct wl_resource *resource,
207 InputDevice *inputDevice = static_cast<InputDevice *>(resource->data);
208 wl_touch *touch = inputDevice->touchDevice();
209 wl_resource *clientResource = wl_client_add_object(client,
214 wl_list_insert(&touch->resource_list, &clientResource->link);
215 clientResource->destroy = InputDevice::destroy_device_resource;
218 void InputDevice::sendMousePressEvent(Qt::MouseButton button, const QPointF &localPos, const QPointF &globalPos)
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);
228 void InputDevice::sendMouseReleaseEvent(Qt::MouseButton button, const QPointF &localPos, const QPointF &globalPos)
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);
238 void InputDevice::sendMouseMoveEvent(const QPointF &localPos, const QPointF &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,
248 wl_fixed_from_double(localPos.x()), wl_fixed_from_double(localPos.y()));
251 void InputDevice::sendMouseMoveEvent(Surface *surface, const QPointF &localPos, const QPointF &globalPos)
253 setMouseFocus(surface,localPos,globalPos);
254 sendMouseMoveEvent(localPos,globalPos);
257 void InputDevice::sendMouseWheelEvent(Qt::Orientation orientation, int delta)
259 wl_pointer *pointer = pointerDevice();
260 struct wl_resource *resource = pointer->focus_resource;
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));
269 void InputDevice::sendKeyPressEvent(uint code)
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);
280 void InputDevice::sendKeyReleaseEvent(uint code)
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);
291 void InputDevice::sendTouchPointEvent(int id, double x, double y, Qt::TouchPointState state)
293 uint32_t time = m_compositor->currentTimeMsecs();
295 wl_touch *touch = touchDevice();
296 wl_resource *resource = touch->focus_resource;
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));
304 case Qt::TouchPointMoved:
305 wl_touch_send_motion(resource, time, id,
306 wl_fixed_from_double(x), wl_fixed_from_double(y));
308 case Qt::TouchPointReleased:
309 wl_touch_send_up(resource, serial, time, id);
311 case Qt::TouchPointStationary:
312 // stationary points are not sent through wayland, the client must cache them
319 void InputDevice::sendTouchFrameEvent()
321 wl_touch *touch = touchDevice();
322 wl_resource *resource = touch->focus_resource;
324 wl_touch_send_frame(resource);
327 void InputDevice::sendTouchCancelEvent()
329 wl_touch *touch = touchDevice();
330 wl_resource *resource = touch->focus_resource;
332 wl_touch_send_cancel(resource);
335 void InputDevice::sendFullKeyEvent(QKeyEvent *event)
337 if (!keyboardFocus()) {
338 qWarning("Cannot send key event, no keyboard focus, fix the compositor");
342 QtKeyExtensionGlobal *ext = m_compositor->qtkeyExtension();
343 if (ext && ext->postQtKeyEvent(event, keyboardFocus()))
346 if (event->type() == QEvent::KeyPress)
347 sendKeyPressEvent(event->nativeScanCode());
348 else if (event->type() == QEvent::KeyRelease)
349 sendKeyReleaseEvent(event->nativeScanCode());
352 void InputDevice::sendFullTouchEvent(QTouchEvent *event)
355 qWarning("Cannot send touch event, no pointer focus, fix the compositor");
359 if (event->type() == QEvent::TouchCancel) {
360 sendTouchCancelEvent();
364 TouchExtensionGlobal *ext = m_compositor->touchExtension();
365 if (ext && ext->postTouchEvent(event, mouseFocus()))
368 const QList<QTouchEvent::TouchPoint> points = event->touchPoints();
369 if (points.isEmpty())
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());
380 sendTouchFrameEvent();
383 Surface *InputDevice::keyboardFocus() const
385 return wayland_cast<Surface>(keyboardDevice()->focus);
389 * \return True if the keyboard focus is changed successfully. False for inactive transient surfaces.
391 bool InputDevice::setKeyboardFocus(Surface *surface)
393 if (surface && surface->transientInactive())
396 sendSelectionFocus(surface);
397 wl_keyboard_set_focus(keyboardDevice(), surface ? surface->base() : 0);
401 Surface *InputDevice::mouseFocus() const
403 return wayland_cast<Surface>(pointerDevice()->focus);
406 void InputDevice::setMouseFocus(Surface *surface, const QPointF &localPos, const QPointF &globalPos)
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()));
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);
425 void InputDevice::cleanupDataDeviceForClient(struct wl_client *client, bool destroyDev)
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) {
432 delete m_data_devices.at(i);
433 m_data_devices.removeAt(i);
439 void InputDevice::clientRequestedDataDevice(DataDeviceManager *data_device_manager, struct wl_client *client, uint32_t id)
441 cleanupDataDeviceForClient(client, false);
442 DataDevice *dataDevice = new DataDevice(data_device_manager,client,id);
443 m_data_devices.append(dataDevice);
446 void InputDevice::sendSelectionFocus(Surface *surface)
450 DataDevice *device = dataDevice(surface->base()->resource.client);
452 device->sendSelectionFocus();
456 Compositor *InputDevice::compositor() const
461 WaylandInputDevice *InputDevice::handle() const
466 uint32_t InputDevice::toWaylandButton(Qt::MouseButton button)
469 uint32_t BTN_LEFT = 0x110;
471 // the range of valid buttons (evdev module) is from 0x110
472 // through 0x11f. 0x120 is the first 'Joystick' 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);
495 DataDevice *InputDevice::dataDevice(struct wl_client *client) const
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);
505 const struct wl_pointer_interface InputDevice::pointer_interface = {
506 InputDevice::pointer_attach
509 void InputDevice::pointer_attach(struct wl_client *client,
510 struct wl_resource *device_resource,
512 struct wl_resource *buffer_resource, int32_t x, int32_t y)
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);
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);
525 void *data = wl_shm_buffer_get_data(buffer);
526 const uchar *char_data = static_cast<const uchar *>(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;