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

KDE's Doxygen guidelines are available online.