KWayland

pointer.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.h"
7 #include "surface.h"
8 #include "wayland_pointer_p.h"
9 // Qt
10 #include <QPointF>
11 #include <QPointer>
12 // wayland
13 #include <wayland-client-protocol.h>
14 
15 namespace KWayland
16 {
17 namespace Client
18 {
19 static Pointer::Axis wlAxisToPointerAxis(uint32_t axis)
20 {
21  switch (axis) {
22  case WL_POINTER_AXIS_VERTICAL_SCROLL:
23  return Pointer::Axis::Vertical;
24  case WL_POINTER_AXIS_HORIZONTAL_SCROLL:
25  return Pointer::Axis::Horizontal;
26  }
27 
28  Q_UNREACHABLE();
29 }
30 
31 class Q_DECL_HIDDEN Pointer::Private
32 {
33 public:
34  Private(Pointer *q);
35  void setup(wl_pointer *p);
36 
37  WaylandPointer<wl_pointer, wl_pointer_release> pointer;
38  QPointer<Surface> enteredSurface;
39  quint32 enteredSerial = 0;
40 
41 private:
42  void enter(uint32_t serial, wl_surface *surface, const QPointF &relativeToSurface);
43  void leave(uint32_t serial);
44  static void enterCallback(void *data, wl_pointer *pointer, uint32_t serial, wl_surface *surface, wl_fixed_t sx, wl_fixed_t sy);
45  static void leaveCallback(void *data, wl_pointer *pointer, uint32_t serial, wl_surface *surface);
46  static void motionCallback(void *data, wl_pointer *pointer, uint32_t time, wl_fixed_t sx, wl_fixed_t sy);
47  static void buttonCallback(void *data, wl_pointer *pointer, uint32_t serial, uint32_t time, uint32_t button, uint32_t state);
48  static void axisCallback(void *data, wl_pointer *pointer, uint32_t time, uint32_t axis, wl_fixed_t value);
49  static void frameCallback(void *data, wl_pointer *pointer);
50  static void axisSourceCallback(void *data, wl_pointer *pointer, uint32_t axis_source);
51  static void axisStopCallback(void *data, wl_pointer *pointer, uint32_t time, uint32_t axis);
52  static void axisDiscreteCallback(void *data, wl_pointer *pointer, uint32_t axis, int32_t discrete);
53 
54  Pointer *q;
55  static const wl_pointer_listener s_listener;
56 };
57 
58 Pointer::Private::Private(Pointer *q)
59  : q(q)
60 {
61 }
62 
63 void Pointer::Private::setup(wl_pointer *p)
64 {
65  Q_ASSERT(p);
66  Q_ASSERT(!pointer);
67  pointer.setup(p);
68  wl_pointer_add_listener(pointer, &s_listener, this);
69 }
70 
71 const wl_pointer_listener Pointer::Private::s_listener =
72  {enterCallback, leaveCallback, motionCallback, buttonCallback, axisCallback, frameCallback, axisSourceCallback, axisStopCallback, axisDiscreteCallback};
73 
74 Pointer::Pointer(QObject *parent)
75  : QObject(parent)
76  , d(new Private(this))
77 {
78 }
79 
80 Pointer::~Pointer()
81 {
82  release();
83 }
84 
86 {
87  d->pointer.release();
88 }
89 
91 {
92  d->pointer.destroy();
93 }
94 
95 void Pointer::setup(wl_pointer *pointer)
96 {
97  d->setup(pointer);
98 }
99 
100 void Pointer::Private::enterCallback(void *data, wl_pointer *pointer, uint32_t serial, wl_surface *surface, wl_fixed_t sx, wl_fixed_t sy)
101 {
102  auto p = reinterpret_cast<Pointer::Private *>(data);
103  Q_ASSERT(p->pointer == pointer);
104  p->enter(serial, surface, QPointF(wl_fixed_to_double(sx), wl_fixed_to_double(sy)));
105 }
106 
107 void Pointer::Private::enter(uint32_t serial, wl_surface *surface, const QPointF &relativeToSurface)
108 {
109  enteredSurface = QPointer<Surface>(Surface::get(surface));
110  enteredSerial = serial;
111  Q_EMIT q->entered(serial, relativeToSurface);
112 }
113 
114 void Pointer::Private::leaveCallback(void *data, wl_pointer *pointer, uint32_t serial, wl_surface *surface)
115 {
116  auto p = reinterpret_cast<Pointer::Private *>(data);
117  Q_ASSERT(p->pointer == pointer);
118  Q_UNUSED(surface)
119  p->leave(serial);
120 }
121 
122 void Pointer::Private::leave(uint32_t serial)
123 {
124  enteredSurface.clear();
125  Q_EMIT q->left(serial);
126 }
127 
128 void Pointer::Private::motionCallback(void *data, wl_pointer *pointer, uint32_t time, wl_fixed_t sx, wl_fixed_t sy)
129 {
130  auto p = reinterpret_cast<Pointer::Private *>(data);
131  Q_ASSERT(p->pointer == pointer);
132  Q_EMIT p->q->motion(QPointF(wl_fixed_to_double(sx), wl_fixed_to_double(sy)), time);
133 }
134 
135 void Pointer::Private::buttonCallback(void *data, wl_pointer *pointer, uint32_t serial, uint32_t time, uint32_t button, uint32_t state)
136 {
137  auto p = reinterpret_cast<Pointer::Private *>(data);
138  Q_ASSERT(p->pointer == pointer);
139  auto toState = [state] {
140  if (state == WL_POINTER_BUTTON_STATE_RELEASED) {
141  return ButtonState::Released;
142  } else {
143  return ButtonState::Pressed;
144  }
145  };
146  Q_EMIT p->q->buttonStateChanged(serial, time, button, toState());
147 }
148 
149 void Pointer::Private::axisCallback(void *data, wl_pointer *pointer, uint32_t time, uint32_t axis, wl_fixed_t value)
150 {
151  auto p = reinterpret_cast<Pointer::Private *>(data);
152  Q_ASSERT(p->pointer == pointer);
153  Q_EMIT p->q->axisChanged(time, wlAxisToPointerAxis(axis), wl_fixed_to_double(value));
154 }
155 
156 void Pointer::Private::frameCallback(void *data, wl_pointer *pointer)
157 {
158  auto p = reinterpret_cast<Pointer::Private *>(data);
159  Q_ASSERT(p->pointer == pointer);
160  Q_EMIT p->q->frame();
161 }
162 
163 void Pointer::Private::axisSourceCallback(void *data, wl_pointer *pointer, uint32_t axis_source)
164 {
165  auto p = reinterpret_cast<Pointer::Private *>(data);
166  Q_ASSERT(p->pointer == pointer);
167  AxisSource source;
168  switch (axis_source) {
169  case WL_POINTER_AXIS_SOURCE_WHEEL:
170  source = AxisSource::Wheel;
171  break;
172  case WL_POINTER_AXIS_SOURCE_FINGER:
173  source = AxisSource::Finger;
174  break;
175  case WL_POINTER_AXIS_SOURCE_CONTINUOUS:
176  source = AxisSource::Continuous;
177  break;
178  case WL_POINTER_AXIS_SOURCE_WHEEL_TILT:
179  source = AxisSource::WheelTilt;
180  break;
181  default:
182  Q_UNREACHABLE();
183  break;
184  }
185  Q_EMIT p->q->axisSourceChanged(source);
186 }
187 
188 void Pointer::Private::axisStopCallback(void *data, wl_pointer *pointer, uint32_t time, uint32_t axis)
189 {
190  auto p = reinterpret_cast<Pointer::Private *>(data);
191  Q_ASSERT(p->pointer == pointer);
192  Q_EMIT p->q->axisStopped(time, wlAxisToPointerAxis(axis));
193 }
194 
195 void Pointer::Private::axisDiscreteCallback(void *data, wl_pointer *pointer, uint32_t axis, int32_t discrete)
196 {
197  auto p = reinterpret_cast<Pointer::Private *>(data);
198  Q_ASSERT(p->pointer == pointer);
199  Q_EMIT p->q->axisDiscreteChanged(wlAxisToPointerAxis(axis), discrete);
200 }
201 
202 void Pointer::setCursor(Surface *surface, const QPoint &hotspot)
203 {
204  Q_ASSERT(isValid());
205  wl_surface *s = nullptr;
206  if (surface) {
207  s = *surface;
208  }
209  wl_pointer_set_cursor(d->pointer, d->enteredSerial, s, hotspot.x(), hotspot.y());
210 }
211 
213 {
214  setCursor(nullptr);
215 }
216 
218 {
219  return d->enteredSurface.data();
220 }
221 
223 {
224  return d->enteredSurface.data();
225 }
226 
227 bool Pointer::isValid() const
228 {
229  return d->pointer.isValid();
230 }
231 
232 Pointer::operator wl_pointer *() const
233 {
234  return d->pointer;
235 }
236 
237 Pointer::operator wl_pointer *()
238 {
239  return d->pointer;
240 }
241 
242 }
243 }
Wrapper for the wl_surface interface.
Definition: surface.h:43
static Surface * get(wl_surface *native)
Definition: surface.cpp:212
void release()
Releases the wl_pointer interface.
Definition: pointer.cpp:85
int x() const const
int y() const const
void destroy()
Destroys the data held by this Pointer.
Definition: pointer.cpp:90
T * data() const const
void setCursor(Surface *surface, const QPoint &hotspot=QPoint())
Sets the cursor image for this Pointer.
Definition: pointer.cpp:202
void hideCursor()
Hides the cursor.
Definition: pointer.cpp:212
void setup(wl_pointer *pointer)
Setup this Pointer to manage the pointer.
Definition: pointer.cpp:95
Surface * enteredSurface() const
Definition: pointer.cpp:217
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Wed Feb 8 2023 03:59:21 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.