KWayland

pointer_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 "pointer_interface.h"
7 #include "pointer_interface_p.h"
8 #include "pointerconstraints_interface.h"
9 #include "pointergestures_interface_p.h"
10 #include "resource_p.h"
11 #include "relativepointer_interface_p.h"
12 #include "seat_interface.h"
13 #include "display.h"
14 #include "subcompositor_interface.h"
15 #include "surface_interface.h"
16 #include "datadevice_interface.h"
17 // Wayland
18 #include <wayland-server.h>
19 
20 namespace KWayland
21 {
22 
23 namespace Server
24 {
25 
26 class Cursor::Private
27 {
28 public:
29  Private(Cursor *q, PointerInterface *pointer);
30  PointerInterface *pointer;
31  quint32 enteredSerial = 0;
34 
35  void update(const QPointer<SurfaceInterface> &surface, quint32 serial, const QPoint &hotspot);
36 
37 private:
38  Cursor *q;
39 };
40 
41 PointerInterface::Private::Private(SeatInterface *parent, wl_resource *parentResource, PointerInterface *q)
42  : Resource::Private(q, parent, parentResource, &wl_pointer_interface, &s_interface)
43  , seat(parent)
44 {
45 }
46 
47 void PointerInterface::Private::setCursor(quint32 serial, SurfaceInterface *surface, const QPoint &hotspot)
48 {
49  if (!cursor) {
50  Q_Q(PointerInterface);
51  cursor = new Cursor(q);
52  cursor->d->update(QPointer<SurfaceInterface>(surface), serial, hotspot);
53  QObject::connect(cursor, &Cursor::changed, q, &PointerInterface::cursorChanged);
54  emit q->cursorChanged();
55  } else {
56  cursor->d->update(QPointer<SurfaceInterface>(surface), serial, hotspot);
57  }
58 }
59 
60 void PointerInterface::Private::sendLeave(SurfaceInterface *surface, quint32 serial)
61 {
62  if (!surface) {
63  return;
64  }
65  if (resource && surface->resource()) {
66  wl_pointer_send_leave(resource, serial, surface->resource());
67  }
68 }
69 
70 void PointerInterface::Private::registerRelativePointer(RelativePointerInterface *relativePointer)
71 {
72  relativePointers << relativePointer;
73  QObject::connect(relativePointer, &QObject::destroyed, q,
74  [this, relativePointer] {
75  relativePointers.removeOne(relativePointer);
76  }
77  );
78 }
79 
80 
81 void PointerInterface::Private::registerSwipeGesture(PointerSwipeGestureInterface *gesture)
82 {
83  swipeGestures << gesture;
85  [this, gesture] {
86  swipeGestures.removeOne(gesture);
87  }
88  );
89 }
90 
91 void PointerInterface::Private::registerPinchGesture(PointerPinchGestureInterface *gesture)
92 {
93  pinchGestures << gesture;
95  [this, gesture] {
96  pinchGestures.removeOne(gesture);
97  }
98  );
99 }
100 
101 namespace {
102 static QPointF surfacePosition(SurfaceInterface *surface) {
103  if (surface && surface->subSurface()) {
104  return surface->subSurface()->position() + surfacePosition(surface->subSurface()->parentSurface().data());
105  }
106  return QPointF();
107 }
108 }
109 
110 void PointerInterface::Private::sendEnter(SurfaceInterface *surface, const QPointF &parentSurfacePosition, quint32 serial)
111 {
112  if (!surface || !surface->resource()) {
113  return;
114  }
115  const QPointF adjustedPos = parentSurfacePosition - surfacePosition(surface);
116  wl_pointer_send_enter(resource, serial,
117  surface->resource(),
118  wl_fixed_from_double(adjustedPos.x()), wl_fixed_from_double(adjustedPos.y()));
119 }
120 
121 void PointerInterface::Private::startSwipeGesture(quint32 serial, quint32 fingerCount)
122 {
123  if (swipeGestures.isEmpty()) {
124  return;
125  }
126  for (auto it = swipeGestures.constBegin(), end = swipeGestures.constEnd(); it != end; it++) {
127  (*it)->start(serial, fingerCount);
128  }
129 }
130 
131 void PointerInterface::Private::updateSwipeGesture(const QSizeF &delta)
132 {
133  if (swipeGestures.isEmpty()) {
134  return;
135  }
136  for (auto it = swipeGestures.constBegin(), end = swipeGestures.constEnd(); it != end; it++) {
137  (*it)->update(delta);
138  }
139 }
140 
141 void PointerInterface::Private::endSwipeGesture(quint32 serial)
142 {
143  if (swipeGestures.isEmpty()) {
144  return;
145  }
146  for (auto it = swipeGestures.constBegin(), end = swipeGestures.constEnd(); it != end; it++) {
147  (*it)->end(serial);
148  }
149 }
150 
151 void PointerInterface::Private::cancelSwipeGesture(quint32 serial)
152 {
153  if (swipeGestures.isEmpty()) {
154  return;
155  }
156  for (auto it = swipeGestures.constBegin(), end = swipeGestures.constEnd(); it != end; it++) {
157  (*it)->cancel(serial);
158  }
159 }
160 
161 void PointerInterface::Private::startPinchGesture(quint32 serial, quint32 fingerCount)
162 {
163  if (pinchGestures.isEmpty()) {
164  return;
165  }
166  for (auto it = pinchGestures.constBegin(), end = pinchGestures.constEnd(); it != end; it++) {
167  (*it)->start(serial, fingerCount);
168  }
169 }
170 
171 void PointerInterface::Private::updatePinchGesture(const QSizeF &delta, qreal scale, qreal rotation)
172 {
173  if (pinchGestures.isEmpty()) {
174  return;
175  }
176  for (auto it = pinchGestures.constBegin(), end = pinchGestures.constEnd(); it != end; it++) {
177  (*it)->update(delta, scale, rotation);
178  }
179 }
180 
181 void PointerInterface::Private::endPinchGesture(quint32 serial)
182 {
183  if (pinchGestures.isEmpty()) {
184  return;
185  }
186  for (auto it = pinchGestures.constBegin(), end = pinchGestures.constEnd(); it != end; it++) {
187  (*it)->end(serial);
188  }
189 }
190 
191 void PointerInterface::Private::cancelPinchGesture(quint32 serial)
192 {
193  if (pinchGestures.isEmpty()) {
194  return;
195  }
196  for (auto it = pinchGestures.constBegin(), end = pinchGestures.constEnd(); it != end; it++) {
197  (*it)->cancel(serial);
198  }
199 }
200 
201 void PointerInterface::Private::sendFrame()
202 {
203  if (!resource || wl_resource_get_version(resource) < WL_POINTER_FRAME_SINCE_VERSION) {
204  return;
205  }
206  wl_pointer_send_frame(resource);
207 }
208 
209 #ifndef K_DOXYGEN
210 const struct wl_pointer_interface PointerInterface::Private::s_interface = {
211  setCursorCallback,
212  resourceDestroyedCallback
213 };
214 #endif
215 
216 PointerInterface::PointerInterface(SeatInterface *parent, wl_resource *parentResource)
217  : Resource(new Private(parent, parentResource, this))
218 {
219  // TODO: handle touch
220  connect(parent, &SeatInterface::pointerPosChanged, this, [this] {
221  Q_D();
222  if (!d->focusedSurface || !d->resource) {
223  return;
224  }
225  if (d->seat->isDragPointer()) {
226  const auto *originSurface = d->seat->dragSource()->origin();
227  const bool proxyRemoteFocused = originSurface->dataProxy() && originSurface == d->focusedSurface;
228  if (!proxyRemoteFocused) {
229  // handled by DataDevice
230  return;
231  }
232  }
233  if (!d->focusedSurface->lockedPointer().isNull() && d->focusedSurface->lockedPointer()->isLocked()) {
234  return;
235  }
236  const QPointF pos = d->seat->focusedPointerSurfaceTransformation().map(d->seat->pointerPos());
237  auto targetSurface = d->focusedSurface->inputSurfaceAt(pos);
238  if (!targetSurface) {
239  targetSurface = d->focusedSurface;
240  }
241  if (targetSurface != d->focusedChildSurface.data()) {
242  const quint32 serial = d->seat->display()->nextSerial();
243  d->sendLeave(d->focusedChildSurface.data(), serial);
244  d->focusedChildSurface = QPointer<SurfaceInterface>(targetSurface);
245  d->sendEnter(targetSurface, pos, serial);
246  d->sendFrame();
247  d->client->flush();
248  } else {
249  const QPointF adjustedPos = pos - surfacePosition(d->focusedChildSurface);
250  wl_pointer_send_motion(d->resource, d->seat->timestamp(),
251  wl_fixed_from_double(adjustedPos.x()), wl_fixed_from_double(adjustedPos.y()));
252  d->sendFrame();
253  }
254  });
255 }
256 
257 PointerInterface::~PointerInterface() = default;
258 
259 void PointerInterface::setFocusedSurface(SurfaceInterface *surface, quint32 serial)
260 {
261  Q_D();
262  d->sendLeave(d->focusedChildSurface.data(), serial);
263  disconnect(d->destroyConnection);
264  if (!surface) {
265  d->focusedSurface = nullptr;
266  d->focusedChildSurface.clear();
267  return;
268  }
269  d->focusedSurface = surface;
270  d->destroyConnection = connect(d->focusedSurface, &Resource::aboutToBeUnbound, this,
271  [this] {
272  Q_D();
273  d->sendLeave(d->focusedChildSurface.data(), d->global->display()->nextSerial());
274  d->sendFrame();
275  d->focusedSurface = nullptr;
276  d->focusedChildSurface.clear();
277  }
278  );
279 
280  const QPointF pos = d->seat->focusedPointerSurfaceTransformation().map(d->seat->pointerPos());
281  d->focusedChildSurface = QPointer<SurfaceInterface>(d->focusedSurface->inputSurfaceAt(pos));
282  if (!d->focusedChildSurface) {
283  d->focusedChildSurface = QPointer<SurfaceInterface>(d->focusedSurface);
284  }
285  d->sendEnter(d->focusedChildSurface.data(), pos, serial);
286  d->client->flush();
287 }
288 
289 void PointerInterface::buttonPressed(quint32 button, quint32 serial)
290 {
291  Q_D();
292  Q_ASSERT(d->focusedSurface);
293  if (!d->resource) {
294  return;
295  }
296  wl_pointer_send_button(d->resource, serial, d->seat->timestamp(), button, WL_POINTER_BUTTON_STATE_PRESSED);
297  d->sendFrame();
298 }
299 
300 void PointerInterface::buttonReleased(quint32 button, quint32 serial)
301 {
302  Q_D();
303  Q_ASSERT(d->focusedSurface);
304  if (!d->resource) {
305  return;
306  }
307  wl_pointer_send_button(d->resource, serial, d->seat->timestamp(), button, WL_POINTER_BUTTON_STATE_RELEASED);
308  d->sendFrame();
309 }
310 
311 void PointerInterface::axis(Qt::Orientation orientation, qreal delta, qint32 discreteDelta, PointerAxisSource source)
312 {
313  Q_D();
314  Q_ASSERT(d->focusedSurface);
315  if (!d->resource) {
316  return;
317  }
318 
319  const quint32 version = wl_resource_get_version(d->resource);
320 
321  const auto wlOrientation = (orientation == Qt::Vertical)
322  ? WL_POINTER_AXIS_VERTICAL_SCROLL
323  : WL_POINTER_AXIS_HORIZONTAL_SCROLL;
324 
325  if (source != PointerAxisSource::Unknown && version >= WL_POINTER_AXIS_SOURCE_SINCE_VERSION) {
326  wl_pointer_axis_source wlSource;
327  switch (source) {
328  case PointerAxisSource::Wheel:
329  wlSource = WL_POINTER_AXIS_SOURCE_WHEEL;
330  break;
331  case PointerAxisSource::Finger:
332  wlSource = WL_POINTER_AXIS_SOURCE_FINGER;
333  break;
334  case PointerAxisSource::Continuous:
335  wlSource = WL_POINTER_AXIS_SOURCE_CONTINUOUS;
336  break;
337  case PointerAxisSource::WheelTilt:
338  wlSource = WL_POINTER_AXIS_SOURCE_WHEEL_TILT;
339  break;
340  default:
341  Q_UNREACHABLE();
342  break;
343  }
344  wl_pointer_send_axis_source(d->resource, wlSource);
345  }
346 
347  if (delta != 0.0) {
348  if (discreteDelta && version >= WL_POINTER_AXIS_DISCRETE_SINCE_VERSION) {
349  wl_pointer_send_axis_discrete(d->resource, wlOrientation, discreteDelta);
350  }
351  wl_pointer_send_axis(d->resource, d->seat->timestamp(), wlOrientation, wl_fixed_from_double(delta));
352  } else if (version >= WL_POINTER_AXIS_STOP_SINCE_VERSION) {
353  wl_pointer_send_axis_stop(d->resource, d->seat->timestamp(), wlOrientation);
354  }
355 
356  d->sendFrame();
357 }
358 
359 void PointerInterface::axis(Qt::Orientation orientation, quint32 delta)
360 {
361  Q_D();
362  Q_ASSERT(d->focusedSurface);
363  if (!d->resource) {
364  return;
365  }
366  wl_pointer_send_axis(d->resource, d->seat->timestamp(),
367  (orientation == Qt::Vertical) ? WL_POINTER_AXIS_VERTICAL_SCROLL : WL_POINTER_AXIS_HORIZONTAL_SCROLL,
368  wl_fixed_from_int(delta));
369  d->sendFrame();
370 }
371 
372 void PointerInterface::Private::setCursorCallback(wl_client *client, wl_resource *resource, uint32_t serial,
373  wl_resource *surface, int32_t hotspot_x, int32_t hotspot_y)
374 {
375  auto p = cast<Private>(resource);
376  Q_ASSERT(p->client->client() == client);
377  p->setCursor(serial, SurfaceInterface::get(surface), QPoint(hotspot_x, hotspot_y));
378 }
379 
380 Cursor *PointerInterface::cursor() const
381 {
382  Q_D();
383  return d->cursor;
384 }
385 
386 void PointerInterface::relativeMotion(const QSizeF &delta, const QSizeF &deltaNonAccelerated, quint64 microseconds)
387 {
388  Q_D();
389  if (d->relativePointers.isEmpty()) {
390  return;
391  }
392  for (auto it = d->relativePointers.constBegin(), end = d->relativePointers.constEnd(); it != end; it++) {
393  (*it)->relativeMotion(delta, deltaNonAccelerated, microseconds);
394  }
395  d->sendFrame();
396 }
397 
398 PointerInterface::Private *PointerInterface::d_func() const
399 {
400  return reinterpret_cast<Private*>(d.data());
401 }
402 
403 PointerInterface *PointerInterface::get(wl_resource *native)
404 {
405  return Private::get<PointerInterface>(native);
406 }
407 
408 Cursor::Private::Private(Cursor *q, PointerInterface *pointer)
409  : pointer(pointer)
410  , q(q)
411 {
412 }
413 
414 void Cursor::Private::update(const QPointer< SurfaceInterface > &s, quint32 serial, const QPoint &p)
415 {
416  bool emitChanged = false;
417  if (enteredSerial != serial) {
418  enteredSerial = serial;
419  emitChanged = true;
420  emit q->enteredSerialChanged();
421  }
422  if (hotspot != p) {
423  hotspot = p;
424  emitChanged = true;
425  emit q->hotspotChanged();
426  }
427  if (surface != s) {
428  if (!surface.isNull()) {
429  QObject::disconnect(surface.data(), &SurfaceInterface::damaged, q, &Cursor::changed);
430  }
431  surface = s;
432  if (!surface.isNull()) {
433  QObject::connect(surface.data(), &SurfaceInterface::damaged, q, &Cursor::changed);
434  }
435  emitChanged = true;
436  emit q->surfaceChanged();
437  }
438  if (emitChanged) {
439  emit q->changed();
440  }
441 }
442 
443 Cursor::Cursor(PointerInterface *parent)
444  : QObject(parent)
445  , d(new Private(this, parent))
446 {
447 }
448 
449 Cursor::~Cursor() = default;
450 
451 quint32 Cursor::enteredSerial() const
452 {
453  return d->enteredSerial;
454 }
455 
456 QPoint Cursor::hotspot() const
457 {
458  return d->hotspot;
459 }
460 
461 PointerInterface *Cursor::pointer() const
462 {
463  return d->pointer;
464 }
465 
466 QPointer< SurfaceInterface > Cursor::surface() const
467 {
468  return d->surface;
469 }
470 
471 }
472 }
quint32 enteredSerial() const
The entered serial when the Cursor got set.
bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *method)
qreal x() const const
qreal y() const const
Class encapsulating a Cursor image.
T * data() const const
bool isNull() const const
const QList< QKeySequence > & end()
QObject(QObject *parent)
void update(Part *part, const QByteArray &data, qint64 dataSize)
Orientation
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
QPoint hotspot() const
The hotspot of the cursor image in surface-relative coordinates.
QObject * parent() const const
QPointer< SurfaceInterface > surface() const
The SurfaceInterface for the image content of the Cursor.
void destroyed(QObject *obj)
PointerInterface * pointer() const
The PointerInterface this Cursor belongs to.
KDB_EXPORT KDbVersionInfo version()
Resource for the wl_pointer interface.
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.