KWaylandServer

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

KDE's Doxygen guidelines are available online.