KWayland

seat_interface.cpp
1 /*
2  SPDX-FileCopyrightText: 2014 Martin Gräßlin <[email protected]>
3 
4  SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
5 */
6 #include "seat_interface.h"
7 #include "seat_interface_p.h"
8 #include "display.h"
9 #include "datadevice_interface.h"
10 #include "datasource_interface.h"
11 #include "keyboard_interface.h"
12 #include "keyboard_interface_p.h"
13 #include "pointer_interface.h"
14 #include "pointer_interface_p.h"
15 #include "surface_interface.h"
16 #include "textinput_interface_p.h"
17 // Qt
18 #include <QFile>
19 // Wayland
20 #ifndef WL_SEAT_NAME_SINCE_VERSION
21 #define WL_SEAT_NAME_SINCE_VERSION 2
22 #endif
23 // linux
24 #include <config-kwayland.h>
25 #if HAVE_LINUX_INPUT_H
26 #include <linux/input.h>
27 #endif
28 
29 #include <functional>
30 
31 namespace KWayland
32 {
33 
34 namespace Server
35 {
36 
37 const quint32 SeatInterface::Private::s_version = 5;
38 const qint32 SeatInterface::Private::s_pointerVersion = 5;
39 const qint32 SeatInterface::Private::s_touchVersion = 5;
40 const qint32 SeatInterface::Private::s_keyboardVersion = 5;
41 
42 SeatInterface::Private::Private(SeatInterface *q, Display *display)
43  : Global::Private(display, &wl_seat_interface, s_version)
44  , q(q)
45 {
46 }
47 
48 #ifndef K_DOXYGEN
49 const struct wl_seat_interface SeatInterface::Private::s_interface = {
50  getPointerCallback,
51  getKeyboardCallback,
52  getTouchCallback,
53  releaseCallback
54 };
55 #endif
56 
57 SeatInterface::SeatInterface(Display *display, QObject *parent)
58  : Global(new Private(this, display), parent)
59 {
60  Q_D();
61  connect(this, &SeatInterface::nameChanged, this,
62  [d] {
63  for (auto it = d->resources.constBegin(); it != d->resources.constEnd(); ++it) {
64  d->sendName(*it);
65  }
66  }
67  );
68  auto sendCapabilitiesAll = [d] {
69  for (auto it = d->resources.constBegin(); it != d->resources.constEnd(); ++it) {
70  d->sendCapabilities(*it);
71  }
72  };
73  connect(this, &SeatInterface::hasPointerChanged, this, sendCapabilitiesAll);
74  connect(this, &SeatInterface::hasKeyboardChanged, this, sendCapabilitiesAll);
75  connect(this, &SeatInterface::hasTouchChanged, this, sendCapabilitiesAll);
76 }
77 
78 SeatInterface::~SeatInterface()
79 {
80  Q_D();
81  while (!d->resources.isEmpty()) {
82  wl_resource_destroy(d->resources.takeLast());
83  }
84 }
85 
86 void SeatInterface::Private::bind(wl_client *client, uint32_t version, uint32_t id)
87 {
88  wl_resource *r = wl_resource_create(client, &wl_seat_interface, qMin(s_version, version), id);
89  if (!r) {
90  wl_client_post_no_memory(client);
91  return;
92  }
93  resources << r;
94 
95  wl_resource_set_implementation(r, &s_interface, this, unbind);
96 
97  sendCapabilities(r);
98  sendName(r);
99 }
100 
101 void SeatInterface::Private::unbind(wl_resource *r)
102 {
103  cast(r)->resources.removeAll(r);
104 }
105 
106 void SeatInterface::Private::releaseCallback(wl_client *client, wl_resource *resource)
107 {
108  Q_UNUSED(client)
109  wl_resource_destroy(resource);
110 }
111 
112 void SeatInterface::Private::updatePointerButtonSerial(quint32 button, quint32 serial)
113 {
114  auto it = globalPointer.buttonSerials.find(button);
115  if (it == globalPointer.buttonSerials.end()) {
116  globalPointer.buttonSerials.insert(button, serial);
117  return;
118  }
119  it.value() = serial;
120 }
121 
122 void SeatInterface::Private::updatePointerButtonState(quint32 button, Pointer::State state)
123 {
124  auto it = globalPointer.buttonStates.find(button);
125  if (it == globalPointer.buttonStates.end()) {
126  globalPointer.buttonStates.insert(button, state);
127  return;
128  }
129  it.value() = state;
130 }
131 
132 bool SeatInterface::Private::updateKey(quint32 key, Keyboard::State state)
133 {
134  auto it = keys.states.find(key);
135  if (it == keys.states.end()) {
136  keys.states.insert(key, state);
137  return true;
138  }
139  if (it.value() == state) {
140  return false;
141  }
142  it.value() = state;
143  return true;
144 }
145 
146 void SeatInterface::Private::sendName(wl_resource *r)
147 {
148  if (wl_resource_get_version(r) < WL_SEAT_NAME_SINCE_VERSION) {
149  return;
150  }
151  wl_seat_send_name(r, name.toUtf8().constData());
152 }
153 
154 void SeatInterface::Private::sendCapabilities(wl_resource *r)
155 {
156  uint32_t capabilities = 0;
157  if (pointer) {
158  capabilities |= WL_SEAT_CAPABILITY_POINTER;
159  }
160  if (keyboard) {
161  capabilities |= WL_SEAT_CAPABILITY_KEYBOARD;
162  }
163  if (touch) {
164  capabilities |= WL_SEAT_CAPABILITY_TOUCH;
165  }
166  wl_seat_send_capabilities(r, capabilities);
167 }
168 
169 SeatInterface::Private *SeatInterface::Private::cast(wl_resource *r)
170 {
171  return r ? reinterpret_cast<SeatInterface::Private*>(wl_resource_get_user_data(r)) : nullptr;
172 }
173 
174 namespace {
175 template <typename T>
176 static
177 T *interfaceForSurface(SurfaceInterface *surface, const QVector<T*> &interfaces)
178 {
179  if (!surface) {
180  return nullptr;
181  }
182 
183  for (auto it = interfaces.constBegin(); it != interfaces.constEnd(); ++it) {
184  if ((*it)->client() == surface->client()) {
185  return (*it);
186  }
187  }
188  return nullptr;
189 }
190 
191 template <typename T>
192 static
193 QVector<T *> interfacesForSurface(SurfaceInterface *surface, const QVector<T*> &interfaces)
194 {
195  QVector<T *> ret;
196  if (!surface) {
197  return ret;
198  }
199 
200  for (auto it = interfaces.constBegin(); it != interfaces.constEnd(); ++it) {
201  if ((*it)->client() == surface->client() && (*it)->resource()) {
202  ret << *it;
203  }
204  }
205  return ret;
206 }
207 
208 template <typename T>
209 static
210 bool forEachInterface(SurfaceInterface *surface, const QVector<T*> &interfaces, std::function<void (T*)> method)
211 {
212  if (!surface) {
213  return false;
214  }
215  bool calledAtLeastOne = false;
216  for (auto it = interfaces.constBegin(); it != interfaces.constEnd(); ++it) {
217  if ((*it)->client() == surface->client() && (*it)->resource()) {
218  method(*it);
219  calledAtLeastOne = true;
220  }
221  }
222  return calledAtLeastOne;
223 }
224 
225 }
226 
227 QVector<PointerInterface *> SeatInterface::Private::pointersForSurface(SurfaceInterface *surface) const
228 {
229  return interfacesForSurface(surface, pointers);
230 }
231 
232 QVector<KeyboardInterface *> SeatInterface::Private::keyboardsForSurface(SurfaceInterface *surface) const
233 {
234  return interfacesForSurface(surface, keyboards);
235 }
236 
237 QVector<TouchInterface *> SeatInterface::Private::touchsForSurface(SurfaceInterface *surface) const
238 {
239  return interfacesForSurface(surface, touchs);
240 }
241 
242 DataDeviceInterface *SeatInterface::Private::dataDeviceForSurface(SurfaceInterface *surface) const
243 {
244  return interfaceForSurface(surface, dataDevices);
245 }
246 
247 TextInputInterface *SeatInterface::Private::textInputForSurface(SurfaceInterface *surface) const
248 {
249  return interfaceForSurface(surface, textInputs);
250 }
251 
252 void SeatInterface::Private::registerDataDevice(DataDeviceInterface *dataDevice)
253 {
254  Q_ASSERT(dataDevice->seat() == q);
255  dataDevices << dataDevice;
256  auto dataDeviceCleanup = [this, dataDevice] {
257  dataDevices.removeOne(dataDevice);
258  if (keys.focus.selection == dataDevice) {
259  keys.focus.selection = nullptr;
260  }
261  if (currentSelection == dataDevice) {
262  // current selection is cleared
263  currentSelection = nullptr;
264  emit q->selectionChanged(nullptr);
265  if (keys.focus.selection) {
266  keys.focus.selection->sendClearSelection();
267  }
268  }
269  };
270  QObject::connect(dataDevice, &QObject::destroyed, q, dataDeviceCleanup);
271  QObject::connect(dataDevice, &Resource::unbound, q, dataDeviceCleanup);
272  QObject::connect(dataDevice, &DataDeviceInterface::selectionChanged, q,
273  [this, dataDevice] {
274  updateSelection(dataDevice, true);
275  }
276  );
277  QObject::connect(dataDevice, &DataDeviceInterface::selectionCleared, q,
278  [this, dataDevice] {
279  updateSelection(dataDevice, false);
280  }
281  );
282  QObject::connect(dataDevice, &DataDeviceInterface::dragStarted, q,
283  [this, dataDevice] {
284  const auto dragSerial = dataDevice->dragImplicitGrabSerial();
285  auto *dragSurface = dataDevice->origin();
286  if (q->hasImplicitPointerGrab(dragSerial)) {
287  drag.mode = Drag::Mode::Pointer;
288  drag.sourcePointer = interfaceForSurface(dragSurface, pointers);
289  drag.transformation = globalPointer.focus.transformation;
290  } else if (q->hasImplicitTouchGrab(dragSerial)) {
291  drag.mode = Drag::Mode::Touch;
292  drag.sourceTouch = interfaceForSurface(dragSurface, touchs);
293  // TODO: touch transformation
294  } else {
295  // no implicit grab, abort drag
296  return;
297  }
298  auto *originSurface = dataDevice->origin();
299  const bool proxied = originSurface->dataProxy();
300  if (!proxied) {
301  // origin surface
302  drag.target = dataDevice;
303  drag.surface = originSurface;
304  // TODO: transformation needs to be either pointer or touch
305  drag.transformation = globalPointer.focus.transformation;
306  }
307  drag.source = dataDevice;
308  drag.sourcePointer = interfaceForSurface(originSurface, pointers);
309  drag.destroyConnection = QObject::connect(dataDevice, &QObject::destroyed, q,
310  [this] {
311  endDrag(display->nextSerial());
312  }
313  );
314  if (dataDevice->dragSource()) {
315  drag.dragSourceDestroyConnection = QObject::connect(dataDevice->dragSource(), &Resource::aboutToBeUnbound, q,
316  [this] {
317  const auto serial = display->nextSerial();
318  if (drag.target) {
319  drag.target->updateDragTarget(nullptr, serial);
320  drag.target = nullptr;
321  }
322  endDrag(serial);
323  }
324  );
325  } else {
326  drag.dragSourceDestroyConnection = QMetaObject::Connection();
327  }
328  dataDevice->updateDragTarget(proxied ? nullptr : originSurface, dataDevice->dragImplicitGrabSerial());
329  emit q->dragStarted();
330  emit q->dragSurfaceChanged();
331  }
332  );
333  // is the new DataDevice for the current keyoard focus?
334  if (keys.focus.surface && !keys.focus.selection) {
335  // same client?
336  if (keys.focus.surface->client() == dataDevice->client()) {
337  keys.focus.selection = dataDevice;
338  if (currentSelection && currentSelection->selection()) {
339  dataDevice->sendSelection(currentSelection);
340  }
341  }
342  }
343 }
344 
345 
346 void SeatInterface::Private::registerTextInput(TextInputInterface *ti)
347 {
348  // text input version 0 might call this multiple times
349  if (textInputs.contains(ti)) {
350  return;
351  }
352  textInputs << ti;
353  if (textInput.focus.surface && textInput.focus.surface->client() == ti->client()) {
354  // this is a text input for the currently focused text input surface
355  if (!textInput.focus.textInput) {
356  textInput.focus.textInput = ti;
357  ti->d_func()->sendEnter(textInput.focus.surface, textInput.focus.serial);
358  emit q->focusedTextInputChanged();
359  }
360  }
362  [this, ti] {
363  textInputs.removeAt(textInputs.indexOf(ti));
364  if (textInput.focus.textInput == ti) {
365  textInput.focus.textInput = nullptr;
366  emit q->focusedTextInputChanged();
367  }
368  }
369  );
370 }
371 
372 void SeatInterface::Private::endDrag(quint32 serial)
373 {
374  auto target = drag.target;
375  QObject::disconnect(drag.destroyConnection);
376  QObject::disconnect(drag.dragSourceDestroyConnection);
377  if (drag.source && drag.source->dragSource()) {
378  drag.source->dragSource()->dropPerformed();
379  }
380  if (target) {
381  target->drop();
382  target->updateDragTarget(nullptr, serial);
383  }
384  drag = Drag();
385  emit q->dragSurfaceChanged();
386  emit q->dragEnded();
387 }
388 
389 void SeatInterface::Private::cancelPreviousSelection(DataDeviceInterface *dataDevice)
390 {
391  if (!currentSelection) {
392  return;
393  }
394  if (auto s = currentSelection->selection()) {
395  if (currentSelection != dataDevice) {
396  // only if current selection is not on the same device
397  // that would cancel the newly set source
398  s->cancel();
399  }
400  }
401 }
402 
403 void SeatInterface::Private::updateSelection(DataDeviceInterface *dataDevice, bool set)
404 {
405  bool selChanged = currentSelection != dataDevice;
406  if (keys.focus.surface && (keys.focus.surface->client() == dataDevice->client())) {
407  // cancel the previous selection
408  cancelPreviousSelection(dataDevice);
409  // new selection on a data device belonging to current keyboard focus
410  currentSelection = dataDevice;
411  }
412  if (dataDevice == currentSelection) {
413  // need to send out the selection
414  if (keys.focus.selection) {
415  if (set) {
416  keys.focus.selection->sendSelection(dataDevice);
417  } else {
418  keys.focus.selection->sendClearSelection();
419  currentSelection = nullptr;
420  selChanged = true;
421  }
422  }
423  }
424  if (selChanged) {
425  emit q->selectionChanged(currentSelection);
426  }
427 }
428 
429 void SeatInterface::setHasKeyboard(bool has)
430 {
431  Q_D();
432  if (d->keyboard == has) {
433  return;
434  }
435  d->keyboard = has;
436  emit hasKeyboardChanged(d->keyboard);
437 }
438 
439 void SeatInterface::setHasPointer(bool has)
440 {
441  Q_D();
442  if (d->pointer == has) {
443  return;
444  }
445  d->pointer = has;
446  emit hasPointerChanged(d->pointer);
447 }
448 
449 void SeatInterface::setHasTouch(bool has)
450 {
451  Q_D();
452  if (d->touch == has) {
453  return;
454  }
455  d->touch = has;
456  emit hasTouchChanged(d->touch);
457 }
458 
459 void SeatInterface::setName(const QString &name)
460 {
461  Q_D();
462  if (d->name == name) {
463  return;
464  }
465  d->name = name;
466  emit nameChanged(d->name);
467 }
468 
469 void SeatInterface::Private::getPointerCallback(wl_client *client, wl_resource *resource, uint32_t id)
470 {
471  cast(resource)->getPointer(client, resource, id);
472 }
473 
474 void SeatInterface::Private::getPointer(wl_client *client, wl_resource *resource, uint32_t id)
475 {
476  // TODO: only create if seat has pointer?
477  PointerInterface *pointer = new PointerInterface(q, resource);
478  auto clientConnection = display->getConnection(client);
479  pointer->create(clientConnection, qMin(wl_resource_get_version(resource), s_pointerVersion), id);
480  if (!pointer->resource()) {
481  wl_resource_post_no_memory(resource);
482  delete pointer;
483  return;
484  }
485  pointers << pointer;
486  if (globalPointer.focus.surface && globalPointer.focus.surface->client() == clientConnection) {
487  // this is a pointer for the currently focused pointer surface
488  globalPointer.focus.pointers << pointer;
489  pointer->setFocusedSurface(globalPointer.focus.surface, globalPointer.focus.serial);
490  pointer->d_func()->sendFrame();
491  if (globalPointer.focus.pointers.count() == 1) {
492  // got a new pointer
493  emit q->focusedPointerChanged(pointer);
494  }
495  }
497  [pointer,this] {
498  pointers.removeAt(pointers.indexOf(pointer));
499  if (globalPointer.focus.pointers.removeOne(pointer)) {
500  if (globalPointer.focus.pointers.isEmpty()) {
501  emit q->focusedPointerChanged(nullptr);
502  }
503  }
504  }
505  );
506  emit q->pointerCreated(pointer);
507 }
508 
509 void SeatInterface::Private::getKeyboardCallback(wl_client *client, wl_resource *resource, uint32_t id)
510 {
511  cast(resource)->getKeyboard(client, resource, id);
512 }
513 
514 void SeatInterface::Private::getKeyboard(wl_client *client, wl_resource *resource, uint32_t id)
515 {
516  // TODO: only create if seat has keyboard?
517  KeyboardInterface *keyboard = new KeyboardInterface(q, resource);
518  auto clientConnection = display->getConnection(client);
519  keyboard->create(clientConnection, qMin(wl_resource_get_version(resource), s_keyboardVersion) , id);
520  if (!keyboard->resource()) {
521  wl_resource_post_no_memory(resource);
522  delete keyboard;
523  return;
524  }
525  keyboard->repeatInfo(keys.keyRepeat.charactersPerSecond, keys.keyRepeat.delay);
526  if (keys.keymap.xkbcommonCompatible) {
527  keyboard->setKeymap(keys.keymap.content);
528  }
529  keyboards << keyboard;
530  if (keys.focus.surface && keys.focus.surface->client() == clientConnection) {
531  // this is a keyboard for the currently focused keyboard surface
532  keys.focus.keyboards << keyboard;
533  keyboard->setFocusedSurface(keys.focus.surface, keys.focus.serial);
534  }
535  QObject::connect(keyboard, &QObject::destroyed, q,
536  [keyboard,this] {
537  keyboards.removeAt(keyboards.indexOf(keyboard));
538  keys.focus.keyboards.removeOne(keyboard);
539  }
540  );
541  emit q->keyboardCreated(keyboard);
542 }
543 
544 void SeatInterface::Private::getTouchCallback(wl_client *client, wl_resource *resource, uint32_t id)
545 {
546  cast(resource)->getTouch(client, resource, id);
547 }
548 
549 void SeatInterface::Private::getTouch(wl_client *client, wl_resource *resource, uint32_t id)
550 {
551  // TODO: only create if seat has touch?
552  TouchInterface *touch = new TouchInterface(q, resource);
553  auto clientConnection = display->getConnection(client);
554  touch->create(clientConnection, qMin(wl_resource_get_version(resource), s_touchVersion), id);
555  if (!touch->resource()) {
556  wl_resource_post_no_memory(resource);
557  delete touch;
558  return;
559  }
560  touchs << touch;
561  if (globalTouch.focus.surface && globalTouch.focus.surface->client() == clientConnection) {
562  // this is a touch for the currently focused touch surface
563  globalTouch.focus.touchs << touch;
564  if (!globalTouch.ids.isEmpty()) {
565  // TODO: send out all the points
566  }
567  }
569  [touch,this] {
570  touchs.removeAt(touchs.indexOf(touch));
571  globalTouch.focus.touchs.removeOne(touch);
572  }
573  );
574  emit q->touchCreated(touch);
575 }
576 
577 QString SeatInterface::name() const
578 {
579  Q_D();
580  return d->name;
581 }
582 
583 bool SeatInterface::hasPointer() const
584 {
585  Q_D();
586  return d->pointer;
587 }
588 
589 bool SeatInterface::hasKeyboard() const
590 {
591  Q_D();
592  return d->keyboard;
593 }
594 
595 bool SeatInterface::hasTouch() const
596 {
597  Q_D();
598  return d->touch;
599 }
600 
601 SeatInterface *SeatInterface::get(wl_resource *native)
602 {
603  return Private::get(native);
604 }
605 
606 SeatInterface::Private *SeatInterface::d_func() const
607 {
608  return reinterpret_cast<Private*>(d.data());
609 }
610 
611 QPointF SeatInterface::pointerPos() const
612 {
613  Q_D();
614  return d->globalPointer.pos;
615 }
616 
617 void SeatInterface::setPointerPos(const QPointF &pos)
618 {
619  Q_D();
620  if (d->globalPointer.pos == pos) {
621  return;
622  }
623  d->globalPointer.pos = pos;
624  emit pointerPosChanged(pos);
625 }
626 
627 quint32 SeatInterface::timestamp() const
628 {
629  Q_D();
630  return d->timestamp;
631 }
632 
633 void SeatInterface::setTimestamp(quint32 time)
634 {
635  Q_D();
636  if (d->timestamp == time) {
637  return;
638  }
639  d->timestamp = time;
640  emit timestampChanged(time);
641 }
642 
643 void SeatInterface::setDragTarget(SurfaceInterface *surface, const QPointF &globalPosition, const QMatrix4x4 &inputTransformation)
644 {
645  Q_D();
646  if (surface == d->drag.surface) {
647  // no change
648  return;
649  }
650  const quint32 serial = d->display->nextSerial();
651  if (d->drag.target) {
652  d->drag.target->updateDragTarget(nullptr, serial);
653  }
654  d->drag.target = d->dataDeviceForSurface(surface);
655  if (d->drag.mode == Private::Drag::Mode::Pointer) {
656  setPointerPos(globalPosition);
657  } else if (d->drag.mode == Private::Drag::Mode::Touch &&
658  d->globalTouch.focus.firstTouchPos != globalPosition) {
659  touchMove(d->globalTouch.ids.first(), globalPosition);
660  }
661  if (d->drag.target) {
662  d->drag.surface = surface;
663  d->drag.transformation = inputTransformation;
664  d->drag.target->updateDragTarget(surface, serial);
665  } else {
666  d->drag.surface = nullptr;
667  }
668  emit dragSurfaceChanged();
669  return;
670 }
671 
672 void SeatInterface::setDragTarget(SurfaceInterface *surface, const QMatrix4x4 &inputTransformation)
673 {
674  Q_D();
675  if (d->drag.mode == Private::Drag::Mode::Pointer) {
676  setDragTarget(surface, pointerPos(), inputTransformation);
677  } else {
678  Q_ASSERT(d->drag.mode == Private::Drag::Mode::Touch);
679  setDragTarget(surface, d->globalTouch.focus.firstTouchPos, inputTransformation);
680  }
681 
682 }
683 
684 SurfaceInterface *SeatInterface::focusedPointerSurface() const
685 {
686  Q_D();
687  return d->globalPointer.focus.surface;
688 }
689 
690 void SeatInterface::setFocusedPointerSurface(SurfaceInterface *surface, const QPointF &surfacePosition)
691 {
692  QMatrix4x4 m;
693  m.translate(-surfacePosition.x(), -surfacePosition.y());
694  setFocusedPointerSurface(surface, m);
695  Q_D();
696  if (d->globalPointer.focus.surface) {
697  d->globalPointer.focus.offset = surfacePosition;
698  }
699 }
700 
701 void SeatInterface::setFocusedPointerSurface(SurfaceInterface *surface, const QMatrix4x4 &transformation)
702 {
703  Q_D();
704  if (d->drag.mode == Private::Drag::Mode::Pointer) {
705  // ignore
706  return;
707  }
708  const quint32 serial = d->display->nextSerial();
709  QSet<PointerInterface *> framePointers;
710  for (auto it = d->globalPointer.focus.pointers.constBegin(), end = d->globalPointer.focus.pointers.constEnd(); it != end; ++it) {
711  (*it)->setFocusedSurface(nullptr, serial);
712  framePointers << *it;
713  }
714  if (d->globalPointer.focus.surface) {
715  disconnect(d->globalPointer.focus.destroyConnection);
716  }
717  d->globalPointer.focus = Private::Pointer::Focus();
718  d->globalPointer.focus.surface = surface;
719  auto p = d->pointersForSurface(surface);
720  d->globalPointer.focus.pointers = p;
721  if (d->globalPointer.focus.surface) {
722  d->globalPointer.focus.destroyConnection = connect(surface, &QObject::destroyed, this,
723  [this] {
724  Q_D();
725  d->globalPointer.focus = Private::Pointer::Focus();
726  emit focusedPointerChanged(nullptr);
727  }
728  );
729  d->globalPointer.focus.offset = QPointF();
730  d->globalPointer.focus.transformation = transformation;
731  d->globalPointer.focus.serial = serial;
732  }
733  if (p.isEmpty()) {
734  emit focusedPointerChanged(nullptr);
735  for (auto p : qAsConst(framePointers))
736  {
737  p->d_func()->sendFrame();
738  }
739  return;
740  }
741  // TODO: signal with all pointers
742  emit focusedPointerChanged(p.first());
743  for (auto it = p.constBegin(), end = p.constEnd(); it != end; ++it) {
744  (*it)->setFocusedSurface(surface, serial);
745  framePointers << *it;
746  }
747  for (auto p : qAsConst(framePointers))
748  {
749  p->d_func()->sendFrame();
750  }
751 }
752 
753 PointerInterface *SeatInterface::focusedPointer() const
754 {
755  Q_D();
756  if (d->globalPointer.focus.pointers.isEmpty()) {
757  return nullptr;
758  }
759  return d->globalPointer.focus.pointers.first();
760 }
761 
762 void SeatInterface::setFocusedPointerSurfacePosition(const QPointF &surfacePosition)
763 {
764  Q_D();
765  if (d->globalPointer.focus.surface) {
766  d->globalPointer.focus.offset = surfacePosition;
767  d->globalPointer.focus.transformation = QMatrix4x4();
768  d->globalPointer.focus.transformation.translate(-surfacePosition.x(), -surfacePosition.y());
769  }
770 }
771 
772 QPointF SeatInterface::focusedPointerSurfacePosition() const
773 {
774  Q_D();
775  return d->globalPointer.focus.offset;
776 }
777 
778 void SeatInterface::setFocusedPointerSurfaceTransformation(const QMatrix4x4 &transformation)
779 {
780  Q_D();
781  if (d->globalPointer.focus.surface) {
782  d->globalPointer.focus.transformation = transformation;
783  }
784 }
785 
786 QMatrix4x4 SeatInterface::focusedPointerSurfaceTransformation() const
787 {
788  Q_D();
789  return d->globalPointer.focus.transformation;
790 }
791 
792 namespace {
793 static quint32 qtToWaylandButton(Qt::MouseButton button)
794 {
795 #if HAVE_LINUX_INPUT_H
796  static const QHash<Qt::MouseButton, quint32> s_buttons({
797  {Qt::LeftButton, BTN_LEFT},
798  {Qt::RightButton, BTN_RIGHT},
799  {Qt::MiddleButton, BTN_MIDDLE},
800  {Qt::ExtraButton1, BTN_BACK}, // note: QtWayland maps BTN_SIDE
801  {Qt::ExtraButton2, BTN_FORWARD}, // note: QtWayland maps BTN_EXTRA
802  {Qt::ExtraButton3, BTN_TASK}, // note: QtWayland maps BTN_FORWARD
803  {Qt::ExtraButton4, BTN_EXTRA}, // note: QtWayland maps BTN_BACK
804  {Qt::ExtraButton5, BTN_SIDE}, // note: QtWayland maps BTN_TASK
805  {Qt::ExtraButton6, BTN_TASK + 1},
806  {Qt::ExtraButton7, BTN_TASK + 2},
807  {Qt::ExtraButton8, BTN_TASK + 3},
808  {Qt::ExtraButton9, BTN_TASK + 4},
809  {Qt::ExtraButton10, BTN_TASK + 5},
810  {Qt::ExtraButton11, BTN_TASK + 6},
811  {Qt::ExtraButton12, BTN_TASK + 7},
812  {Qt::ExtraButton13, BTN_TASK + 8}
813  // further mapping not possible, 0x120 is BTN_JOYSTICK
814  });
815  return s_buttons.value(button, 0);
816 #else
817  return 0;
818 #endif
819 }
820 }
821 
822 bool SeatInterface::isPointerButtonPressed(Qt::MouseButton button) const
823 {
824  return isPointerButtonPressed(qtToWaylandButton(button));
825 }
826 
827 bool SeatInterface::isPointerButtonPressed(quint32 button) const
828 {
829  Q_D();
830  auto it = d->globalPointer.buttonStates.constFind(button);
831  if (it == d->globalPointer.buttonStates.constEnd()) {
832  return false;
833  }
834  return it.value() == Private::Pointer::State::Pressed ? true : false;
835 }
836 
837 void SeatInterface::pointerAxisV5(Qt::Orientation orientation, qreal delta, qint32 discreteDelta, PointerAxisSource source)
838 {
839  Q_D();
840  if (d->drag.mode == Private::Drag::Mode::Pointer) {
841  // ignore
842  return;
843  }
844  if (d->globalPointer.focus.surface) {
845  for (auto it = d->globalPointer.focus.pointers.constBegin(), end = d->globalPointer.focus.pointers.constEnd(); it != end; ++it) {
846  (*it)->axis(orientation, delta, discreteDelta, source);
847  }
848  }
849 }
850 
851 void SeatInterface::pointerAxis(Qt::Orientation orientation, quint32 delta)
852 {
853  Q_D();
854  if (d->drag.mode == Private::Drag::Mode::Pointer) {
855  // ignore
856  return;
857  }
858  if (d->globalPointer.focus.surface) {
859  for (auto it = d->globalPointer.focus.pointers.constBegin(), end = d->globalPointer.focus.pointers.constEnd(); it != end; ++it) {
860  (*it)->axis(orientation, delta);
861  }
862  }
863 }
864 
865 void SeatInterface::pointerButtonPressed(Qt::MouseButton button)
866 {
867  const quint32 nativeButton = qtToWaylandButton(button);
868  if (nativeButton == 0) {
869  return;
870  }
871  pointerButtonPressed(nativeButton);
872 }
873 
874 void SeatInterface::pointerButtonPressed(quint32 button)
875 {
876  Q_D();
877  const quint32 serial = d->display->nextSerial();
878  d->updatePointerButtonSerial(button, serial);
879  d->updatePointerButtonState(button, Private::Pointer::State::Pressed);
880  if (d->drag.mode == Private::Drag::Mode::Pointer) {
881  // ignore
882  return;
883  }
884  if (auto *focusSurface = d->globalPointer.focus.surface) {
885  for (auto it = d->globalPointer.focus.pointers.constBegin(), end = d->globalPointer.focus.pointers.constEnd(); it != end; ++it) {
886  (*it)->buttonPressed(button, serial);
887  }
888  if (focusSurface == d->keys.focus.surface) {
889  // update the focused child surface
890  auto p = focusedPointer();
891  if (p) {
892  for (auto it = d->keys.focus.keyboards.constBegin(), end = d->keys.focus.keyboards.constEnd(); it != end; ++it) {
893  (*it)->d_func()->focusChildSurface(p->d_func()->focusedChildSurface, serial);
894  }
895  }
896  }
897  }
898 }
899 
900 void SeatInterface::pointerButtonReleased(Qt::MouseButton button)
901 {
902  const quint32 nativeButton = qtToWaylandButton(button);
903  if (nativeButton == 0) {
904  return;
905  }
906  pointerButtonReleased(nativeButton);
907 }
908 
909 void SeatInterface::pointerButtonReleased(quint32 button)
910 {
911  Q_D();
912  const quint32 serial = d->display->nextSerial();
913  const quint32 currentButtonSerial = pointerButtonSerial(button);
914  d->updatePointerButtonSerial(button, serial);
915  d->updatePointerButtonState(button, Private::Pointer::State::Released);
916  if (d->drag.mode == Private::Drag::Mode::Pointer) {
917  if (d->drag.source->dragImplicitGrabSerial() != currentButtonSerial) {
918  // not our drag button - ignore
919  return;
920  }
921  d->endDrag(serial);
922  return;
923  }
924  if (d->globalPointer.focus.surface) {
925  for (auto it = d->globalPointer.focus.pointers.constBegin(), end = d->globalPointer.focus.pointers.constEnd(); it != end; ++it) {
926  (*it)->buttonReleased(button, serial);
927  }
928  }
929 }
930 
931 quint32 SeatInterface::pointerButtonSerial(Qt::MouseButton button) const
932 {
933  return pointerButtonSerial(qtToWaylandButton(button));
934 }
935 
936 quint32 SeatInterface::pointerButtonSerial(quint32 button) const
937 {
938  Q_D();
939  auto it = d->globalPointer.buttonSerials.constFind(button);
940  if (it == d->globalPointer.buttonSerials.constEnd()) {
941  return 0;
942  }
943  return it.value();
944 }
945 
946 void SeatInterface::relativePointerMotion(const QSizeF &delta, const QSizeF &deltaNonAccelerated, quint64 microseconds)
947 {
948  Q_D();
949  if (d->globalPointer.focus.surface) {
950  for (auto it = d->globalPointer.focus.pointers.constBegin(), end = d->globalPointer.focus.pointers.constEnd(); it != end; ++it) {
951  (*it)->relativeMotion(delta, deltaNonAccelerated, microseconds);
952  }
953  }
954 }
955 
956 void SeatInterface::startPointerSwipeGesture(quint32 fingerCount)
957 {
958  Q_D();
959  if (!d->globalPointer.gestureSurface.isNull()) {
960  return;
961  }
962  d->globalPointer.gestureSurface = QPointer<SurfaceInterface>(d->globalPointer.focus.surface);
963  if (d->globalPointer.gestureSurface.isNull()) {
964  return;
965  }
966  const quint32 serial = d->display->nextSerial();
967  forEachInterface<PointerInterface>(d->globalPointer.gestureSurface.data(), d->pointers,
968  [serial, fingerCount] (PointerInterface *p) {
969  p->d_func()->startSwipeGesture(serial, fingerCount);
970  }
971  );
972 }
973 
974 void SeatInterface::updatePointerSwipeGesture(const QSizeF &delta)
975 {
976  Q_D();
977  if (d->globalPointer.gestureSurface.isNull()) {
978  return;
979  }
980  forEachInterface<PointerInterface>(d->globalPointer.gestureSurface.data(), d->pointers,
981  [delta] (PointerInterface *p) {
982  p->d_func()->updateSwipeGesture(delta);
983  }
984  );
985 }
986 
987 void SeatInterface::endPointerSwipeGesture()
988 {
989  Q_D();
990  if (d->globalPointer.gestureSurface.isNull()) {
991  return;
992  }
993  const quint32 serial = d->display->nextSerial();
994  forEachInterface<PointerInterface>(d->globalPointer.gestureSurface.data(), d->pointers,
995  [serial] (PointerInterface *p) {
996  p->d_func()->endSwipeGesture(serial);
997  }
998  );
999  d->globalPointer.gestureSurface.clear();
1000 }
1001 
1002 void SeatInterface::cancelPointerSwipeGesture()
1003 {
1004  Q_D();
1005  if (d->globalPointer.gestureSurface.isNull()) {
1006  return;
1007  }
1008  const quint32 serial = d->display->nextSerial();
1009  forEachInterface<PointerInterface>(d->globalPointer.gestureSurface.data(), d->pointers,
1010  [serial] (PointerInterface *p) {
1011  p->d_func()->cancelSwipeGesture(serial);
1012  }
1013  );
1014  d->globalPointer.gestureSurface.clear();
1015 }
1016 
1017 void SeatInterface::startPointerPinchGesture(quint32 fingerCount)
1018 {
1019  Q_D();
1020  if (!d->globalPointer.gestureSurface.isNull()) {
1021  return;
1022  }
1023  d->globalPointer.gestureSurface = QPointer<SurfaceInterface>(d->globalPointer.focus.surface);
1024  if (d->globalPointer.gestureSurface.isNull()) {
1025  return;
1026  }
1027  const quint32 serial = d->display->nextSerial();
1028  forEachInterface<PointerInterface>(d->globalPointer.gestureSurface.data(), d->pointers,
1029  [serial, fingerCount] (PointerInterface *p) {
1030  p->d_func()->startPinchGesture(serial, fingerCount);
1031  }
1032  );
1033 }
1034 
1035 void SeatInterface::updatePointerPinchGesture(const QSizeF &delta, qreal scale, qreal rotation)
1036 {
1037  Q_D();
1038  if (d->globalPointer.gestureSurface.isNull()) {
1039  return;
1040  }
1041  forEachInterface<PointerInterface>(d->globalPointer.gestureSurface.data(), d->pointers,
1042  [delta, scale, rotation] (PointerInterface *p) {
1043  p->d_func()->updatePinchGesture(delta, scale, rotation);
1044  }
1045  );
1046 }
1047 
1048 void SeatInterface::endPointerPinchGesture()
1049 {
1050  Q_D();
1051  if (d->globalPointer.gestureSurface.isNull()) {
1052  return;
1053  }
1054  const quint32 serial = d->display->nextSerial();
1055  forEachInterface<PointerInterface>(d->globalPointer.gestureSurface.data(), d->pointers,
1056  [serial] (PointerInterface *p) {
1057  p->d_func()->endPinchGesture(serial);
1058  }
1059  );
1060  d->globalPointer.gestureSurface.clear();
1061 }
1062 
1063 void SeatInterface::cancelPointerPinchGesture()
1064 {
1065  Q_D();
1066  if (d->globalPointer.gestureSurface.isNull()) {
1067  return;
1068  }
1069  const quint32 serial = d->display->nextSerial();
1070  forEachInterface<PointerInterface>(d->globalPointer.gestureSurface.data(), d->pointers,
1071  [serial] (PointerInterface *p) {
1072  p->d_func()->cancelPinchGesture(serial);
1073  }
1074  );
1075  d->globalPointer.gestureSurface.clear();
1076 }
1077 
1078 void SeatInterface::keyPressed(quint32 key)
1079 {
1080  Q_D();
1081  d->keys.lastStateSerial = d->display->nextSerial();
1082  if (!d->updateKey(key, Private::Keyboard::State::Pressed)) {
1083  return;
1084  }
1085  if (d->keys.focus.surface) {
1086  for (auto it = d->keys.focus.keyboards.constBegin(), end = d->keys.focus.keyboards.constEnd(); it != end; ++it) {
1087  (*it)->keyPressed(key, d->keys.lastStateSerial);
1088  }
1089  }
1090 }
1091 
1092 void SeatInterface::keyReleased(quint32 key)
1093 {
1094  Q_D();
1095  d->keys.lastStateSerial = d->display->nextSerial();
1096  if (!d->updateKey(key, Private::Keyboard::State::Released)) {
1097  return;
1098  }
1099  if (d->keys.focus.surface) {
1100  for (auto it = d->keys.focus.keyboards.constBegin(), end = d->keys.focus.keyboards.constEnd(); it != end; ++it) {
1101  (*it)->keyReleased(key, d->keys.lastStateSerial);
1102  }
1103  }
1104 }
1105 
1106 SurfaceInterface *SeatInterface::focusedKeyboardSurface() const
1107 {
1108  Q_D();
1109  return d->keys.focus.surface;
1110 }
1111 
1112 void SeatInterface::setFocusedKeyboardSurface(SurfaceInterface *surface)
1113 {
1114  Q_D();
1115  const quint32 serial = d->display->nextSerial();
1116  for (auto it = d->keys.focus.keyboards.constBegin(), end = d->keys.focus.keyboards.constEnd(); it != end; ++it) {
1117  (*it)->setFocusedSurface(nullptr, serial);
1118  }
1119  if (d->keys.focus.surface) {
1120  disconnect(d->keys.focus.destroyConnection);
1121  }
1122  d->keys.focus = Private::Keyboard::Focus();
1123  d->keys.focus.surface = surface;
1124  d->keys.focus.keyboards = d->keyboardsForSurface(surface);
1125  if (d->keys.focus.surface) {
1126  d->keys.focus.destroyConnection = connect(surface, &QObject::destroyed, this,
1127  [this] {
1128  Q_D();
1129  d->keys.focus = Private::Keyboard::Focus();
1130  }
1131  );
1132  d->keys.focus.serial = serial;
1133  // selection?
1134  d->keys.focus.selection = d->dataDeviceForSurface(surface);
1135  if (d->keys.focus.selection) {
1136  if (d->currentSelection && d->currentSelection->selection()) {
1137  d->keys.focus.selection->sendSelection(d->currentSelection);
1138  } else {
1139  d->keys.focus.selection->sendClearSelection();
1140  }
1141  }
1142  }
1143  for (auto it = d->keys.focus.keyboards.constBegin(), end = d->keys.focus.keyboards.constEnd(); it != end; ++it) {
1144  (*it)->setFocusedSurface(surface, serial);
1145  }
1146  // focused text input surface follows keyboard
1147  if (hasKeyboard()) {
1148  setFocusedTextInputSurface(surface);
1149  }
1150 }
1151 
1152 #if KWAYLANDSERVER_BUILD_DEPRECATED_SINCE(5, 69)
1153 void SeatInterface::setKeymap(int fd, quint32 size)
1154 {
1155  QFile file;
1156  if (!file.open(fd, QIODevice::ReadOnly)) {
1157  return;
1158  }
1159  const char *address = reinterpret_cast<char*>(file.map(0, size));
1160  if (!address) {
1161  return;
1162  }
1163  setKeymapData(QByteArray(address, size));
1164 }
1165 #endif
1166 
1167 void SeatInterface::setKeymapData(const QByteArray &content)
1168 {
1169  Q_D();
1170  d->keys.keymap.xkbcommonCompatible = true;
1171  d->keys.keymap.content = content;
1172  for (auto it = d->keyboards.constBegin(); it != d->keyboards.constEnd(); ++it) {
1173  (*it)->setKeymap(content);
1174  }
1175 }
1176 
1177 void SeatInterface::updateKeyboardModifiers(quint32 depressed, quint32 latched, quint32 locked, quint32 group)
1178 {
1179  Q_D();
1180  bool changed = false;
1181 #define UPDATE( value ) \
1182  if (d->keys.modifiers.value != value) { \
1183  d->keys.modifiers.value = value; \
1184  changed = true; \
1185  }
1186  UPDATE(depressed)
1187  UPDATE(latched)
1188  UPDATE(locked)
1189  UPDATE(group)
1190  if (!changed) {
1191  return;
1192  }
1193  const quint32 serial = d->display->nextSerial();
1194  d->keys.modifiers.serial = serial;
1195  if (d->keys.focus.surface) {
1196  for (auto it = d->keys.focus.keyboards.constBegin(), end = d->keys.focus.keyboards.constEnd(); it != end; ++it) {
1197  (*it)->updateModifiers(depressed, latched, locked, group, serial);
1198  }
1199  }
1200 }
1201 
1202 void SeatInterface::setKeyRepeatInfo(qint32 charactersPerSecond, qint32 delay)
1203 {
1204  Q_D();
1205  d->keys.keyRepeat.charactersPerSecond = qMax(charactersPerSecond, 0);
1206  d->keys.keyRepeat.delay = qMax(delay, 0);
1207  for (auto it = d->keyboards.constBegin(); it != d->keyboards.constEnd(); ++it) {
1208  (*it)->repeatInfo(d->keys.keyRepeat.charactersPerSecond, d->keys.keyRepeat.delay);
1209  }
1210 }
1211 
1212 qint32 SeatInterface::keyRepeatDelay() const
1213 {
1214  Q_D();
1215  return d->keys.keyRepeat.delay;
1216 }
1217 
1218 qint32 SeatInterface::keyRepeatRate() const
1219 {
1220  Q_D();
1221  return d->keys.keyRepeat.charactersPerSecond;
1222 }
1223 
1224 bool SeatInterface::isKeymapXkbCompatible() const
1225 {
1226  Q_D();
1227  return d->keys.keymap.xkbcommonCompatible;
1228 }
1229 
1230 #if KWAYLANDSERVER_BUILD_DEPRECATED_SINCE(5, 69)
1231 int SeatInterface::keymapFileDescriptor() const
1232 {
1233  return -1;
1234 }
1235 #endif
1236 
1237 #if KWAYLANDSERVER_BUILD_DEPRECATED_SINCE(5, 69)
1238 quint32 SeatInterface::keymapSize() const
1239 {
1240  return 0;
1241 }
1242 #endif
1243 
1244 quint32 SeatInterface::depressedModifiers() const
1245 {
1246  Q_D();
1247  return d->keys.modifiers.depressed;
1248 }
1249 
1250 quint32 SeatInterface::groupModifiers() const
1251 {
1252  Q_D();
1253  return d->keys.modifiers.group;
1254 }
1255 
1256 quint32 SeatInterface::latchedModifiers() const
1257 {
1258  Q_D();
1259  return d->keys.modifiers.latched;
1260 }
1261 
1262 quint32 SeatInterface::lockedModifiers() const
1263 {
1264  Q_D();
1265  return d->keys.modifiers.locked;
1266 }
1267 
1268 quint32 SeatInterface::lastModifiersSerial() const
1269 {
1270  Q_D();
1271  return d->keys.modifiers.serial;
1272 }
1273 
1274 QVector< quint32 > SeatInterface::pressedKeys() const
1275 {
1276  Q_D();
1277  QVector<quint32> keys;
1278  for (auto it = d->keys.states.constBegin(); it != d->keys.states.constEnd(); ++it) {
1279  if (it.value() == Private::Keyboard::State::Pressed) {
1280  keys << it.key();
1281  }
1282  }
1283  return keys;
1284 }
1285 
1286 KeyboardInterface *SeatInterface::focusedKeyboard() const
1287 {
1288  Q_D();
1289  if (d->keys.focus.keyboards.isEmpty()) {
1290  return nullptr;
1291  }
1292  return d->keys.focus.keyboards.first();
1293 }
1294 
1295 void SeatInterface::cancelTouchSequence()
1296 {
1297  Q_D();
1298  for (auto it = d->globalTouch.focus.touchs.constBegin(), end = d->globalTouch.focus.touchs.constEnd(); it != end; ++it) {
1299  (*it)->cancel();
1300  }
1301  if (d->drag.mode == Private::Drag::Mode::Touch) {
1302  // cancel the drag, don't drop.
1303  if (d->drag.target) {
1304  // remove the current target
1305  d->drag.target->updateDragTarget(nullptr, 0);
1306  d->drag.target = nullptr;
1307  }
1308  // and end the drag for the source, serial does not matter
1309  d->endDrag(0);
1310  }
1311  d->globalTouch.ids.clear();
1312 }
1313 
1314 TouchInterface *SeatInterface::focusedTouch() const
1315 {
1316  Q_D();
1317  if (d->globalTouch.focus.touchs.isEmpty()) {
1318  return nullptr;
1319  }
1320  return d->globalTouch.focus.touchs.first();
1321 }
1322 
1323 SurfaceInterface *SeatInterface::focusedTouchSurface() const
1324 {
1325  Q_D();
1326  return d->globalTouch.focus.surface;
1327 }
1328 
1329 QPointF SeatInterface::focusedTouchSurfacePosition() const
1330 {
1331  Q_D();
1332  return d->globalTouch.focus.offset;
1333 }
1334 
1335 bool SeatInterface::isTouchSequence() const
1336 {
1337  Q_D();
1338  return !d->globalTouch.ids.isEmpty();
1339 }
1340 
1341 void SeatInterface::setFocusedTouchSurface(SurfaceInterface *surface, const QPointF &surfacePosition)
1342 {
1343  if (isTouchSequence()) {
1344  // changing surface not allowed during a touch sequence
1345  return;
1346  }
1347  Q_ASSERT(!isDragTouch());
1348  Q_D();
1349  if (d->globalTouch.focus.surface) {
1350  disconnect(d->globalTouch.focus.destroyConnection);
1351  }
1352  d->globalTouch.focus = Private::Touch::Focus();
1353  d->globalTouch.focus.surface = surface;
1354  d->globalTouch.focus.offset = surfacePosition;
1355  d->globalTouch.focus.touchs = d->touchsForSurface(surface);
1356  if (d->globalTouch.focus.surface) {
1357  d->globalTouch.focus.destroyConnection = connect(surface, &QObject::destroyed, this,
1358  [this] {
1359  Q_D();
1360  if (isTouchSequence()) {
1361  // Surface destroyed during touch sequence - send a cancel
1362  for (auto it = d->globalTouch.focus.touchs.constBegin(), end = d->globalTouch.focus.touchs.constEnd(); it != end; ++it) {
1363  (*it)->cancel();
1364  }
1365  }
1366  d->globalTouch.focus = Private::Touch::Focus();
1367  }
1368  );
1369  }
1370 }
1371 
1372 void SeatInterface::setFocusedTouchSurfacePosition(const QPointF &surfacePosition)
1373 {
1374  Q_D();
1375  d->globalTouch.focus.offset = surfacePosition;
1376 }
1377 
1378 qint32 SeatInterface::touchDown(const QPointF &globalPosition)
1379 {
1380  Q_D();
1381  const qint32 id = d->globalTouch.ids.isEmpty() ? 0 : d->globalTouch.ids.lastKey() + 1;
1382  const qint32 serial = display()->nextSerial();
1383  const auto pos = globalPosition - d->globalTouch.focus.offset;
1384  for (auto it = d->globalTouch.focus.touchs.constBegin(), end = d->globalTouch.focus.touchs.constEnd(); it != end; ++it) {
1385  (*it)->down(id, serial, pos);
1386  }
1387 
1388  if (id == 0) {
1389  d->globalTouch.focus.firstTouchPos = globalPosition;
1390  }
1391 
1392 #if HAVE_LINUX_INPUT_H
1393  if (id == 0 && d->globalTouch.focus.touchs.isEmpty()) {
1394  // If the client did not bind the touch interface fall back
1395  // to at least emulating touch through pointer events.
1396  forEachInterface<PointerInterface>(focusedTouchSurface(), d->pointers,
1397  [this, pos, serial] (PointerInterface *p) {
1398  wl_pointer_send_enter(p->resource(), serial,
1399  focusedTouchSurface()->resource(),
1400  wl_fixed_from_double(pos.x()), wl_fixed_from_double(pos.y()));
1401  wl_pointer_send_motion(p->resource(), timestamp(),
1402  wl_fixed_from_double(pos.x()), wl_fixed_from_double(pos.y()));
1403 
1404  wl_pointer_send_button(p->resource(), serial, timestamp(), BTN_LEFT, WL_POINTER_BUTTON_STATE_PRESSED);
1405  p->d_func()->sendFrame();
1406  }
1407  );
1408  }
1409 #endif
1410 
1411  d->globalTouch.ids[id] = serial;
1412  return id;
1413 }
1414 
1415 void SeatInterface::touchMove(qint32 id, const QPointF &globalPosition)
1416 {
1417  Q_D();
1418  Q_ASSERT(d->globalTouch.ids.contains(id));
1419  const auto pos = globalPosition - d->globalTouch.focus.offset;
1420  for (auto it = d->globalTouch.focus.touchs.constBegin(), end = d->globalTouch.focus.touchs.constEnd(); it != end; ++it) {
1421  (*it)->move(id, pos);
1422  }
1423 
1424  if (id == 0) {
1425  d->globalTouch.focus.firstTouchPos = globalPosition;
1426  }
1427 
1428  if (id == 0 && d->globalTouch.focus.touchs.isEmpty()) {
1429  // Client did not bind touch, fall back to emulating with pointer events.
1430  forEachInterface<PointerInterface>(focusedTouchSurface(), d->pointers,
1431  [this, pos] (PointerInterface *p) {
1432  wl_pointer_send_motion(p->resource(), timestamp(),
1433  wl_fixed_from_double(pos.x()), wl_fixed_from_double(pos.y()));
1434  }
1435  );
1436  }
1437  emit touchMoved(id, d->globalTouch.ids[id], globalPosition);
1438 }
1439 
1440 void SeatInterface::touchUp(qint32 id)
1441 {
1442  Q_D();
1443  Q_ASSERT(d->globalTouch.ids.contains(id));
1444  const qint32 serial = display()->nextSerial();
1445  if (d->drag.mode == Private::Drag::Mode::Touch &&
1446  d->drag.source->dragImplicitGrabSerial() == d->globalTouch.ids.value(id)) {
1447  // the implicitly grabbing touch point has been upped
1448  d->endDrag(serial);
1449  }
1450  for (auto it = d->globalTouch.focus.touchs.constBegin(), end = d->globalTouch.focus.touchs.constEnd(); it != end; ++it) {
1451  (*it)->up(id, serial);
1452  }
1453 
1454 #if HAVE_LINUX_INPUT_H
1455  if (id == 0 && d->globalTouch.focus.touchs.isEmpty()) {
1456  // Client did not bind touch, fall back to emulating with pointer events.
1457  const quint32 serial = display()->nextSerial();
1458  forEachInterface<PointerInterface>(focusedTouchSurface(), d->pointers,
1459  [this, serial] (PointerInterface *p) {
1460  wl_pointer_send_button(p->resource(), serial, timestamp(), BTN_LEFT, WL_POINTER_BUTTON_STATE_RELEASED);
1461  }
1462  );
1463  }
1464 #endif
1465 
1466  d->globalTouch.ids.remove(id);
1467 }
1468 
1469 void SeatInterface::touchFrame()
1470 {
1471  Q_D();
1472  for (auto it = d->globalTouch.focus.touchs.constBegin(), end = d->globalTouch.focus.touchs.constEnd(); it != end; ++it) {
1473  (*it)->frame();
1474  }
1475 }
1476 
1477 bool SeatInterface::hasImplicitTouchGrab(quint32 serial) const
1478 {
1479  Q_D();
1480  if (!d->globalTouch.focus.surface) {
1481  // origin surface has been destroyed
1482  return false;
1483  }
1484  return d->globalTouch.ids.key(serial, -1) != -1;
1485 }
1486 
1487 bool SeatInterface::isDrag() const
1488 {
1489  Q_D();
1490  return d->drag.mode != Private::Drag::Mode::None;
1491 }
1492 
1493 bool SeatInterface::isDragPointer() const
1494 {
1495  Q_D();
1496  return d->drag.mode == Private::Drag::Mode::Pointer;
1497 }
1498 
1499 bool SeatInterface::isDragTouch() const
1500 {
1501  Q_D();
1502  return d->drag.mode == Private::Drag::Mode::Touch;
1503 }
1504 
1505 bool SeatInterface::hasImplicitPointerGrab(quint32 serial) const
1506 {
1507  Q_D();
1508  const auto &serials = d->globalPointer.buttonSerials;
1509  for (auto it = serials.constBegin(), end = serials.constEnd(); it != end; it++) {
1510  if (it.value() == serial) {
1511  return isPointerButtonPressed(it.key());
1512  }
1513  }
1514  return false;
1515 }
1516 
1517 QMatrix4x4 SeatInterface::dragSurfaceTransformation() const
1518 {
1519  Q_D();
1520  return d->drag.transformation;
1521 }
1522 
1523 SurfaceInterface *SeatInterface::dragSurface() const
1524 {
1525  Q_D();
1526  return d->drag.surface;
1527 }
1528 
1529 PointerInterface *SeatInterface::dragPointer() const
1530 {
1531  Q_D();
1532  if (d->drag.mode != Private::Drag::Mode::Pointer) {
1533  return nullptr;
1534  }
1535 
1536  return d->drag.sourcePointer;
1537 }
1538 
1539 DataDeviceInterface *SeatInterface::dragSource() const
1540 {
1541  Q_D();
1542  return d->drag.source;
1543 }
1544 
1545 void SeatInterface::setFocusedTextInputSurface(SurfaceInterface *surface)
1546 {
1547  Q_D();
1548  const quint32 serial = d->display->nextSerial();
1549  const auto old = d->textInput.focus.textInput;
1550  if (d->textInput.focus.textInput) {
1551  // TODO: setFocusedSurface like in other interfaces
1552  d->textInput.focus.textInput->d_func()->sendLeave(serial, d->textInput.focus.surface);
1553  }
1554  if (d->textInput.focus.surface) {
1555  disconnect(d->textInput.focus.destroyConnection);
1556  }
1557  d->textInput.focus = Private::TextInput::Focus();
1558  d->textInput.focus.surface = surface;
1559  TextInputInterface *t = d->textInputForSurface(surface);
1560  if (t && !t->resource()) {
1561  t = nullptr;
1562  }
1563  d->textInput.focus.textInput = t;
1564  if (d->textInput.focus.surface) {
1565  d->textInput.focus.destroyConnection = connect(surface, &Resource::aboutToBeUnbound, this,
1566  [this] {
1567  setFocusedTextInputSurface(nullptr);
1568  }
1569  );
1570  d->textInput.focus.serial = serial;
1571  }
1572  if (t) {
1573  // TODO: setFocusedSurface like in other interfaces
1574  t->d_func()->sendEnter(surface, serial);
1575  }
1576  if (old != t) {
1577  emit focusedTextInputChanged();
1578  }
1579 }
1580 
1581 SurfaceInterface *SeatInterface::focusedTextInputSurface() const
1582 {
1583  Q_D();
1584  return d->textInput.focus.surface;
1585 }
1586 
1587 TextInputInterface *SeatInterface::focusedTextInput() const
1588 {
1589  Q_D();
1590  return d->textInput.focus.textInput;
1591 }
1592 
1593 DataDeviceInterface *SeatInterface::selection() const
1594 {
1595  Q_D();
1596  return d->currentSelection;
1597 }
1598 
1599 void SeatInterface::setSelection(DataDeviceInterface *dataDevice)
1600 {
1601  Q_D();
1602  if (d->currentSelection == dataDevice) {
1603  return;
1604  }
1605  // cancel the previous selection
1606  d->cancelPreviousSelection(dataDevice);
1607  d->currentSelection = dataDevice;
1608  if (d->keys.focus.selection) {
1609  if (dataDevice && dataDevice->selection()) {
1610  d->keys.focus.selection->sendSelection(dataDevice);
1611  } else {
1612  d->keys.focus.selection->sendClearSelection();
1613  }
1614  }
1615  emit selectionChanged(dataDevice);
1616 }
1617 
1618 }
1619 }
PointerAxisSource
Describes the source types for axis events.
void translate(const QVector3D &vector)
QString name
In a multiseat configuration this can be used by the client to help identify which physical devices t...
Definition: seat.h:72
bool touch
The seat has touch devices.
Definition: seat.h:66
DataDeviceInterface allows clients to share data by copy-and-paste and drag-and-drop.
Resource for the wl_keyboard interface.
QVector::const_iterator constEnd() const const
MouseButton
Represents a generic Resource for a text input object.
bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *method)
uchar * map(qint64 offset, qint64 size, QFileDevice::MemoryMapFlags flags)
qreal x() const const
qreal y() const const
wl_resource * resource()
Definition: resource.cpp:88
Resource representing a wl_surface.
const char * constData() const const
virtual bool open(QIODevice::OpenMode mode) override
T * data() const const
const T value(const Key &key) const const
Resource for the wl_touch interface.
bool isNull() const const
QVector::const_iterator constBegin() const const
bool pointer
The seat has pointer devices.
Definition: seat.h:62
KDEGAMES_EXPORT Capabilities capabilities()
Orientation
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
QObject * parent() const const
void destroyed(QObject *obj)
bool keyboard
The seat has pointer devices.
Definition: seat.h:58
Resource for the wl_pointer interface.
QByteArray toUtf8() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Fri Aug 14 2020 22:49:58 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.