1 /****************************************************************************
3 ** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
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 Digia Plc and its Subsidiary(-ies) nor the names
21 ** of its contributors may be used to endorse or promote products derived
22 ** from this software without specific prior written permission.
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>
52 #ifndef QT_NO_WAYLAND_XKB
54 #include <sys/types.h>
55 #include <sys/socket.h>
56 #include <sys/epoll.h>
65 static QImage *currentCursor;
67 InputDevice::InputDevice(WaylandInputDevice *handle, Compositor *compositor)
69 , m_compositor(compositor)
73 wl_display_add_global(compositor->wl_display(),
76 InputDevice::bind_func);
78 #ifndef QT_NO_WAYLAND_XKB
79 xkb_rule_names xkb_names;
80 xkb_context *context = xkb_context_new(xkb_context_flags(0));
82 memset(&xkb_names, 0, sizeof(xkb_names));
83 xkb_names.rules = strdup("evdev");
84 xkb_names.model = strdup("pc105");
85 xkb_names.layout = strdup("us");
87 xkb_keymap *keymap = xkb_map_new_from_names(context, &xkb_names, xkb_map_compile_flags(0));
89 qFatal("Failed to compile global XKB keymap");
91 char *keymap_str_data = xkb_map_get_as_string(keymap);
92 QByteArray keymap_str = keymap_str_data;
93 m_keymap_size = keymap_str.size() + 1;
94 free(keymap_str_data);
96 const char *path = getenv("XDG_RUNTIME_DIR");
98 qFatal("XDG_RUNTIME_DIR not set");
100 QByteArray name = QByteArray(path) + "/qtwayland-xkb-map-XXXXXX";
102 int fd = mkstemp(name.data());
104 long flags = fcntl(fd, F_GETFD);
105 if (flags == -1 || fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1) {
107 qFatal("Failed to set FD_CLOEXEC on anonymous file");
111 qFatal("Failed to create anonymous file with name %s", name.constData());
114 if (ftruncate(fd, m_keymap_size) < 0)
115 qFatal("Failed to create anonymous file of size %lu", (unsigned long)m_keymap_size);
119 m_keymap_area = (char *)mmap(0, m_keymap_size, PROT_READ | PROT_WRITE, MAP_SHARED, m_keymap_fd, 0);
120 if (m_keymap_area == MAP_FAILED) {
122 qFatal("Failed to map shared memory segment");
125 strcpy(m_keymap_area, keymap_str.constData());
127 m_state = xkb_state_new(keymap);
129 free((char *)xkb_names.rules);
130 free((char *)xkb_names.model);
131 free((char *)xkb_names.layout);
132 xkb_map_unref(keymap);
133 xkb_context_unref(context);
137 InputDevice::~InputDevice()
139 qDeleteAll(m_data_devices);
142 #ifndef QT_NO_WAYLAND_XKB
144 munmap(m_keymap_area, m_keymap_size);
146 xkb_state_unref(m_state);
150 void InputDevice::initDevices()
152 wl_pointer_init(&m_device_interfaces.pointer);
153 wl_seat_set_pointer(base(), &m_device_interfaces.pointer);
155 wl_keyboard_init(&m_device_interfaces.keyboard);
156 wl_seat_set_keyboard(base(), &m_device_interfaces.keyboard);
158 wl_touch_init(&m_device_interfaces.touch);
159 wl_seat_set_touch(base(), &m_device_interfaces.touch);
162 void InputDevice::releaseDevices()
164 wl_pointer_release(&m_device_interfaces.pointer);
165 wl_keyboard_release(&m_device_interfaces.keyboard);
166 wl_touch_release(&m_device_interfaces.touch);
169 wl_pointer *InputDevice::pointerDevice()
171 return &m_device_interfaces.pointer;
174 wl_keyboard *InputDevice::keyboardDevice()
176 return &m_device_interfaces.keyboard;
179 wl_touch *InputDevice::touchDevice()
181 return &m_device_interfaces.touch;
184 const wl_pointer *InputDevice::pointerDevice() const
186 return &m_device_interfaces.pointer;
189 const wl_keyboard *InputDevice::keyboardDevice() const
191 return &m_device_interfaces.keyboard;
194 const wl_touch *InputDevice::touchDevice() const
196 return &m_device_interfaces.touch;
199 void InputDevice::destroy_resource(wl_resource *resource)
201 InputDevice *input_device = static_cast<InputDevice *>(resource->data);
202 if (input_device->keyboardDevice()->focus_resource == resource) {
203 input_device->keyboardDevice()->focus_resource = 0;
205 if (input_device->pointerDevice()->focus_resource == resource) {
206 input_device->pointerDevice()->focus_resource = 0;
209 input_device->cleanupDataDeviceForClient(resource->client, true);
211 wl_list_remove(&resource->link);
216 void InputDevice::bind_func(struct wl_client *client, void *data,
217 uint32_t version, uint32_t id)
220 struct wl_resource *resource = wl_client_add_object(client,
226 struct wl_seat *seat = static_cast<struct wl_seat *>(data);
227 resource->destroy = destroy_resource;
228 wl_list_insert(&seat->base_resource_list, &resource->link);
230 uint32_t caps = WL_SEAT_CAPABILITY_POINTER | WL_SEAT_CAPABILITY_KEYBOARD;
231 if (!QTouchDevice::devices().isEmpty())
232 caps |= WL_SEAT_CAPABILITY_TOUCH;
234 wl_seat_send_capabilities(resource, caps);
237 const struct wl_seat_interface InputDevice::seat_interface = {
243 void InputDevice::destroy_device_resource(wl_resource *resource)
245 wl_list_remove(&resource->link);
249 void InputDevice::get_pointer(struct wl_client *client,
250 struct wl_resource *resource,
253 InputDevice *inputDevice = static_cast<InputDevice *>(resource->data);
254 wl_pointer *pointer = inputDevice->pointerDevice();
255 wl_resource *clientResource = wl_client_add_object(client,
256 &wl_pointer_interface,
260 wl_list_insert(&pointer->resource_list, &clientResource->link);
261 clientResource->destroy = InputDevice::destroy_device_resource;
264 void InputDevice::get_keyboard(struct wl_client *client,
265 struct wl_resource *resource,
268 InputDevice *inputDevice = static_cast<InputDevice *>(resource->data);
269 wl_keyboard *keyboard = inputDevice->keyboardDevice();
270 wl_resource *clientResource = wl_client_add_object(client,
271 &wl_keyboard_interface,
275 wl_list_insert(&keyboard->resource_list, &clientResource->link);
276 clientResource->destroy = InputDevice::destroy_device_resource;
278 #ifndef QT_NO_WAYLAND_XKB
279 wl_keyboard_send_keymap(clientResource, WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1,
280 inputDevice->m_keymap_fd, inputDevice->m_keymap_size);
284 void InputDevice::get_touch(struct wl_client *client,
285 struct wl_resource *resource,
288 InputDevice *inputDevice = static_cast<InputDevice *>(resource->data);
289 wl_touch *touch = inputDevice->touchDevice();
290 wl_resource *clientResource = wl_client_add_object(client,
295 wl_list_insert(&touch->resource_list, &clientResource->link);
296 clientResource->destroy = InputDevice::destroy_device_resource;
299 void InputDevice::sendMousePressEvent(Qt::MouseButton button, const QPointF &localPos, const QPointF &globalPos)
301 sendMouseMoveEvent(localPos,globalPos);
302 wl_pointer *pointer = pointerDevice();
303 pointer->button_count++;
304 uint32_t time = m_compositor->currentTimeMsecs();
305 const struct wl_pointer_grab_interface *interface = pointer->grab->interface;
306 interface->button(pointer->grab, time, toWaylandButton(button), 1);
309 void InputDevice::sendMouseReleaseEvent(Qt::MouseButton button, const QPointF &localPos, const QPointF &globalPos)
311 sendMouseMoveEvent(localPos,globalPos);
312 wl_pointer *pointer = pointerDevice();
313 pointer->button_count--;
314 uint32_t time = m_compositor->currentTimeMsecs();
315 const struct wl_pointer_grab_interface *interface = pointer->grab->interface;
316 interface->button(pointer->grab, time, toWaylandButton(button), 0);
319 void InputDevice::sendMouseMoveEvent(const QPointF &localPos, const QPointF &globalPos)
322 uint32_t time = m_compositor->currentTimeMsecs();
323 wl_pointer *pointer = pointerDevice();
324 const struct wl_pointer_grab_interface *interface = pointer->grab->interface;
325 pointer->x = wl_fixed_from_double(globalPos.x());
326 pointer->y = wl_fixed_from_double(globalPos.y());
327 interface->motion(pointer->grab,
329 wl_fixed_from_double(localPos.x()), wl_fixed_from_double(localPos.y()));
332 void InputDevice::sendMouseMoveEvent(Surface *surface, const QPointF &localPos, const QPointF &globalPos)
334 setMouseFocus(surface,localPos,globalPos);
335 sendMouseMoveEvent(localPos,globalPos);
338 void InputDevice::sendMouseWheelEvent(Qt::Orientation orientation, int delta)
340 wl_pointer *pointer = pointerDevice();
341 struct wl_resource *resource = pointer->focus_resource;
344 uint32_t time = m_compositor->currentTimeMsecs();
345 uint32_t axis = orientation == Qt::Horizontal ? WL_POINTER_AXIS_HORIZONTAL_SCROLL
346 : WL_POINTER_AXIS_VERTICAL_SCROLL;
347 wl_pointer_send_axis(resource, time, axis, wl_fixed_from_double(delta / 120.0));
350 void InputDevice::updateModifierState(uint code, int state)
352 #ifndef QT_NO_WAYLAND_XKB
353 xkb_state_update_key(m_state, code, state ? XKB_KEY_DOWN : XKB_KEY_UP);
355 uint32_t mods_depressed = xkb_state_serialize_mods(m_state, XKB_STATE_DEPRESSED);
356 uint32_t mods_latched = xkb_state_serialize_mods(m_state, XKB_STATE_LATCHED);
357 uint32_t mods_locked = xkb_state_serialize_mods(m_state, XKB_STATE_LATCHED);
358 uint32_t group = xkb_state_serialize_group(m_state, XKB_STATE_EFFECTIVE);
360 wl_keyboard *keyboard = keyboardDevice();
362 if (mods_depressed == keyboard->modifiers.mods_depressed
363 && mods_latched == keyboard->modifiers.mods_latched
364 && mods_locked == keyboard->modifiers.mods_locked
365 && group == keyboard->modifiers.group)
370 keyboard->modifiers.mods_depressed = mods_depressed;
371 keyboard->modifiers.mods_latched = mods_latched;
372 keyboard->modifiers.mods_locked = mods_locked;
373 keyboard->modifiers.group = group;
375 if (keyboard->focus_resource)
376 sendKeyModifiers(keyboard->focus_resource);
383 void InputDevice::sendKeyModifiers(wl_resource *resource)
385 wl_keyboard *keyboard = keyboardDevice();
386 uint32_t serial = wl_display_next_serial(m_compositor->wl_display());
387 wl_keyboard_send_modifiers(resource, serial, keyboard->modifiers.mods_depressed,
388 keyboard->modifiers.mods_latched, keyboard->modifiers.mods_locked, keyboard->modifiers.group);
391 void InputDevice::sendKeyPressEvent(uint code)
393 wl_keyboard *keyboard = keyboardDevice();
394 if (keyboard->focus_resource) {
395 uint32_t time = m_compositor->currentTimeMsecs();
396 uint32_t serial = wl_display_next_serial(m_compositor->wl_display());
397 wl_keyboard_send_key(keyboard->focus_resource,
398 serial, time, code - 8, 1);
400 updateModifierState(code, 1);
403 void InputDevice::sendKeyReleaseEvent(uint code)
405 wl_keyboard *keyboard = keyboardDevice();
406 if (keyboard->focus_resource) {
407 uint32_t time = m_compositor->currentTimeMsecs();
408 uint32_t serial = wl_display_next_serial(m_compositor->wl_display());
409 wl_keyboard_send_key(keyboard->focus_resource,
410 serial, time, code - 8, 0);
412 updateModifierState(code, 0);
415 void InputDevice::sendTouchPointEvent(int id, double x, double y, Qt::TouchPointState state)
417 uint32_t time = m_compositor->currentTimeMsecs();
419 wl_touch *touch = touchDevice();
420 wl_resource *resource = touch->focus_resource;
424 case Qt::TouchPointPressed:
425 wl_touch_send_down(resource, serial, time, &touch->focus->resource, id,
426 wl_fixed_from_double(x), wl_fixed_from_double(y));
428 case Qt::TouchPointMoved:
429 wl_touch_send_motion(resource, time, id,
430 wl_fixed_from_double(x), wl_fixed_from_double(y));
432 case Qt::TouchPointReleased:
433 wl_touch_send_up(resource, serial, time, id);
435 case Qt::TouchPointStationary:
436 // stationary points are not sent through wayland, the client must cache them
443 void InputDevice::sendTouchFrameEvent()
445 wl_touch *touch = touchDevice();
446 wl_resource *resource = touch->focus_resource;
448 wl_touch_send_frame(resource);
451 void InputDevice::sendTouchCancelEvent()
453 wl_touch *touch = touchDevice();
454 wl_resource *resource = touch->focus_resource;
456 wl_touch_send_cancel(resource);
459 void InputDevice::sendFullKeyEvent(QKeyEvent *event)
461 if (!keyboardFocus()) {
462 qWarning("Cannot send key event, no keyboard focus, fix the compositor");
466 QtKeyExtensionGlobal *ext = m_compositor->qtkeyExtension();
467 if (ext && ext->postQtKeyEvent(event, keyboardFocus()))
470 if (event->type() == QEvent::KeyPress)
471 sendKeyPressEvent(event->nativeScanCode());
472 else if (event->type() == QEvent::KeyRelease)
473 sendKeyReleaseEvent(event->nativeScanCode());
476 void InputDevice::sendFullTouchEvent(QTouchEvent *event)
479 qWarning("Cannot send touch event, no pointer focus, fix the compositor");
483 if (event->type() == QEvent::TouchCancel) {
484 sendTouchCancelEvent();
488 TouchExtensionGlobal *ext = m_compositor->touchExtension();
489 if (ext && ext->postTouchEvent(event, mouseFocus()))
492 const QList<QTouchEvent::TouchPoint> points = event->touchPoints();
493 if (points.isEmpty())
496 const int pointCount = points.count();
497 QPointF pos = mouseFocus()->pos();
498 for (int i = 0; i < pointCount; ++i) {
499 const QTouchEvent::TouchPoint &tp(points.at(i));
500 // Convert the local pos in the compositor window to surface-relative.
501 QPointF p = tp.pos() - pos;
502 sendTouchPointEvent(tp.id(), p.x(), p.y(), tp.state());
504 sendTouchFrameEvent();
507 Surface *InputDevice::keyboardFocus() const
509 return wayland_cast<Surface>(keyboardDevice()->focus);
513 * \return True if the keyboard focus is changed successfully. False for inactive transient surfaces.
515 bool InputDevice::setKeyboardFocus(Surface *surface)
517 if (surface && surface->transientInactive())
520 sendSelectionFocus(surface);
521 wl_keyboard_set_focus(keyboardDevice(), surface ? surface->base() : 0);
525 Surface *InputDevice::mouseFocus() const
527 return wayland_cast<Surface>(pointerDevice()->focus);
530 void InputDevice::setMouseFocus(Surface *surface, const QPointF &localPos, const QPointF &globalPos)
532 wl_pointer *pointer = pointerDevice();
533 pointer->x = wl_fixed_from_double(globalPos.x());
534 pointer->y = wl_fixed_from_double(globalPos.y());
535 pointer->current = surface ? surface->base() : 0;
536 pointer->current_x = wl_fixed_from_double(localPos.x());
537 pointer->current_y = wl_fixed_from_double(localPos.y());
538 pointer->grab->interface->focus(pointer->grab,
539 surface ? surface->base() : 0,
540 wl_fixed_from_double(localPos.x()), wl_fixed_from_double(localPos.y()));
542 // We have no separate touch focus management so make it match the pointer focus always.
543 // No wl_touch_set_focus() is available so set it manually.
544 wl_touch *touch = touchDevice();
545 touch->focus = surface ? surface->base() : 0;
546 touch->focus_resource = Compositor::resourceForSurface(&touch->resource_list, surface);
549 void InputDevice::cleanupDataDeviceForClient(struct wl_client *client, bool destroyDev)
551 for (int i = 0; i < m_data_devices.size(); i++) {
552 struct wl_resource *data_device_resource =
553 m_data_devices.at(i)->dataDeviceResource();
554 if (data_device_resource->client == client) {
556 delete m_data_devices.at(i);
557 m_data_devices.removeAt(i);
563 void InputDevice::clientRequestedDataDevice(DataDeviceManager *data_device_manager, struct wl_client *client, uint32_t id)
565 cleanupDataDeviceForClient(client, false);
566 DataDevice *dataDevice = new DataDevice(data_device_manager,client,id);
567 m_data_devices.append(dataDevice);
570 void InputDevice::sendSelectionFocus(Surface *surface)
574 DataDevice *device = dataDevice(surface->base()->resource.client);
576 device->sendSelectionFocus();
580 Compositor *InputDevice::compositor() const
585 WaylandInputDevice *InputDevice::handle() const
590 uint32_t InputDevice::toWaylandButton(Qt::MouseButton button)
593 uint32_t BTN_LEFT = 0x110;
595 // the range of valid buttons (evdev module) is from 0x110
596 // through 0x11f. 0x120 is the first 'Joystick' button.
598 case Qt::LeftButton: return BTN_LEFT;
599 case Qt::RightButton: return uint32_t(0x111);
600 case Qt::MiddleButton: return uint32_t(0x112);
601 case Qt::ExtraButton1: return uint32_t(0x113); // AKA Qt::BackButton, Qt::XButton1
602 case Qt::ExtraButton2: return uint32_t(0x114); // AKA Qt::ForwardButton, Qt::XButton2
603 case Qt::ExtraButton3: return uint32_t(0x115);
604 case Qt::ExtraButton4: return uint32_t(0x116);
605 case Qt::ExtraButton5: return uint32_t(0x117);
606 case Qt::ExtraButton6: return uint32_t(0x118);
607 case Qt::ExtraButton7: return uint32_t(0x119);
608 case Qt::ExtraButton8: return uint32_t(0x11a);
609 case Qt::ExtraButton9: return uint32_t(0x11b);
610 case Qt::ExtraButton10: return uint32_t(0x11c);
611 case Qt::ExtraButton11: return uint32_t(0x11d);
612 case Qt::ExtraButton12: return uint32_t(0x11e);
613 case Qt::ExtraButton13: return uint32_t(0x11f);
614 // default should not occur; but if it does, then return Wayland's highest possible button number.
615 default: return uint32_t(0x11f);
619 DataDevice *InputDevice::dataDevice(struct wl_client *client) const
621 for (int i = 0; i < m_data_devices.size();i++) {
622 if (m_data_devices.at(i)->dataDeviceResource()->client == client) {
623 return m_data_devices.at(i);
629 const struct wl_pointer_interface InputDevice::pointer_interface = {
630 InputDevice::pointer_attach
633 void InputDevice::pointer_attach(struct wl_client *client,
634 struct wl_resource *device_resource,
636 struct wl_resource *buffer_resource, int32_t x, int32_t y)
641 wl_pointer *pointer = reinterpret_cast<wl_pointer *>(device_resource->data);
642 InputDevice *inputDevice = wayland_cast<InputDevice>(pointer->seat);
643 wl_buffer *buffer = reinterpret_cast<wl_buffer *>(buffer_resource);
645 if (buffer && wl_buffer_is_shm(buffer)) {
646 int stride = wl_shm_buffer_get_stride(buffer);
647 uint format = wl_shm_buffer_get_format(buffer);
649 void *data = wl_shm_buffer_get_data(buffer);
650 const uchar *char_data = static_cast<const uchar *>(data);
652 QImage *img = new QImage(char_data, buffer->width, buffer->height, stride, QImage::Format_ARGB32_Premultiplied);
653 inputDevice->m_compositor->waylandCompositor()->changeCursor(*img, x, y);
654 delete currentCursor;
658 inputDevice->m_compositor->waylandCompositor()->changeCursor(QImage(), x, y);