Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qwaylandpointer.cpp
Go to the documentation of this file.
1// Copyright (C) 2017 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
3
4#include "qwaylandpointer.h"
5#include "qwaylandpointer_p.h"
6#include <QtWaylandCompositor/QWaylandClient>
7#include <QtWaylandCompositor/QWaylandCompositor>
8
10
11QWaylandSurfaceRole QWaylandPointerPrivate::s_role("wl_pointer");
12
18
19uint QWaylandPointerPrivate::sendButton(Qt::MouseButton button, uint32_t state)
20{
21 Q_Q(QWaylandPointer);
22 if (!q->mouseFocus() || !q->mouseFocus()->surface())
23 return 0;
24
25 wl_client *client = q->mouseFocus()->surface()->waylandClient();
26 uint32_t time = compositor()->currentTimeMsecs();
27 uint32_t serial = compositor()->nextSerial();
28 for (auto resource : resourceMap().values(client))
29 send_button(resource->handle, serial, time, q->toWaylandButton(button), state);
30 return serial;
31}
32
33void QWaylandPointerPrivate::sendMotion()
34{
35 Q_ASSERT(enteredSurface);
36 uint32_t time = compositor()->currentTimeMsecs();
37 wl_fixed_t x = wl_fixed_from_double(localPosition.x());
38 wl_fixed_t y = wl_fixed_from_double(localPosition.y());
39 for (auto resource : resourceMap().values(enteredSurface->waylandClient()))
40 wl_pointer_send_motion(resource->handle, time, x, y);
41}
42
43void QWaylandPointerPrivate::sendEnter(QWaylandSurface *surface)
44{
45 Q_ASSERT(surface && !enteredSurface);
46 enterSerial = compositor()->nextSerial();
47
48 QWaylandKeyboard *keyboard = seat->keyboard();
49 if (keyboard)
50 keyboard->sendKeyModifiers(surface->client(), enterSerial);
51
52 wl_fixed_t x = wl_fixed_from_double(localPosition.x());
53 wl_fixed_t y = wl_fixed_from_double(localPosition.y());
54 for (auto resource : resourceMap().values(surface->waylandClient()))
55 send_enter(resource->handle, enterSerial, surface->resource(), x, y);
56
57 enteredSurface = surface;
58 enteredSurfaceDestroyListener.listenForDestruction(surface->resource());
59}
60
61void QWaylandPointerPrivate::sendLeave()
62{
63 Q_ASSERT(enteredSurface);
64 uint32_t serial = compositor()->nextSerial();
65 for (auto resource : resourceMap().values(enteredSurface->waylandClient()))
66 send_leave(resource->handle, serial, enteredSurface->resource());
67 localPosition = QPointF();
68 enteredSurfaceDestroyListener.reset();
69 enteredSurface = nullptr;
70}
71
72void QWaylandPointerPrivate::ensureEntered(QWaylandSurface *surface)
73{
74 if (enteredSurface == surface)
75 return;
76
77 if (enteredSurface)
78 sendLeave();
79
80 if (surface)
81 sendEnter(surface);
82}
83
84void QWaylandPointerPrivate::pointer_release(wl_pointer::Resource *resource)
85{
86 wl_resource_destroy(resource->handle);
87}
88
89void QWaylandPointerPrivate::pointer_set_cursor(wl_pointer::Resource *resource, uint32_t serial, wl_resource *surface, int32_t hotspot_x, int32_t hotspot_y)
90{
91 Q_UNUSED(serial);
92
93 if (!surface) {
94 seat->cursorSurfaceRequested(nullptr, 0, 0, QWaylandClient::fromWlClient(compositor(), resource->client()));
95 return;
96 }
97
99 // XXX FIXME
100 // The role concept was formalized in wayland 1.7, so that release adds one error
101 // code for each interface that implements a role, and we are supposed to pass here
102 // the newly constructed resource and the correct error code so that if setting the
103 // role fails, a proper error can be sent to the client.
104 // However we're still using wayland 1.4, which doesn't have interface specific role
105 // errors, so the best we can do is to use wl_display's object_id error.
106 wl_resource *displayRes = wl_client_get_object(resource->client(), 1);
107 if (s->setRole(&QWaylandPointerPrivate::s_role, displayRes, WL_DISPLAY_ERROR_INVALID_OBJECT)) {
108 s->markAsCursorSurface(true);
109 seat->cursorSurfaceRequested(s, hotspot_x, hotspot_y, QWaylandClient::fromWlClient(compositor(), resource->client()));
110 }
111}
112
127 : QWaylandObject(* new QWaylandPointerPrivate(this, seat), parent)
128{
129 connect(&d_func()->enteredSurfaceDestroyListener, &QWaylandDestroyListener::fired, this, &QWaylandPointer::enteredSurfaceDestroyed);
130 connect(seat, &QWaylandSeat::mouseFocusChanged, this, &QWaylandPointer::pointerFocusChanged);
131}
132
137{
138 Q_D(const QWaylandPointer);
139 return d->seat;
140}
141
146{
147 Q_D(const QWaylandPointer);
148 return d->compositor();
149}
150
155{
156 Q_D(const QWaylandPointer);
157 return d->output;
158}
159
164{
165 Q_D(QWaylandPointer);
166 if (d->output == output) return;
167 d->output = output;
169}
170
177{
178 Q_D(QWaylandPointer);
179 d->buttonCount++;
180
181 if (d->buttonCount == 1)
183
184 return d->sendButton(button, WL_POINTER_BUTTON_STATE_PRESSED);
185}
186
193{
194 Q_D(QWaylandPointer);
195 d->buttonCount--;
196
197 if (d->buttonCount == 0)
199
200 return d->sendButton(button, WL_POINTER_BUTTON_STATE_RELEASED);
201}
202
207void QWaylandPointer::sendMouseMoveEvent(QWaylandView *view, const QPointF &localPos, const QPointF &outputSpacePos)
208{
209 Q_D(QWaylandPointer);
210 if (view && (!view->surface() || view->surface()->isCursorSurface()))
211 view = nullptr;
212 d->seat->setMouseFocus(view);
213 d->localPosition = localPos;
214 d->spacePosition = outputSpacePos;
215
216 if (view) {
217 // We adjust if the mouse position is on the edge
218 // to work around Qt's event propagation
219 QSizeF size(view->surface()->destinationSize());
220 if (d->localPosition.x() == size.width())
221 d->localPosition.rx() -= 0.01;
222 if (d->localPosition.y() == size.height())
223 d->localPosition.ry() -= 0.01;
224
225 d->ensureEntered(view->surface());
226 d->sendMotion();
227
228 if (view->output())
229 setOutput(view->output());
230 }
231}
232
237{
238 Q_D(QWaylandPointer);
239 if (!d->enteredSurface)
240 return;
241
242 uint32_t time = d->compositor()->currentTimeMsecs();
243 uint32_t axis = orientation == Qt::Horizontal ? WL_POINTER_AXIS_HORIZONTAL_SCROLL
244 : WL_POINTER_AXIS_VERTICAL_SCROLL;
245
246 for (auto resource : d->resourceMap().values(d->enteredSurface->waylandClient()))
247 d->send_axis(resource->handle, time, axis, wl_fixed_from_int(-delta / 12));
248}
249
254{
255 Q_D(const QWaylandPointer);
256 return d->seat->mouseFocus();
257}
258
263{
264 Q_D(const QWaylandPointer);
265 return d->localPosition;
266}
267
272{
273 Q_D(const QWaylandPointer);
274 return d->spacePosition;
275}
276
281{
282 Q_D(const QWaylandPointer);
283 return d->buttonCount > 0;
284}
285
289void QWaylandPointer::addClient(QWaylandClient *client, uint32_t id, uint32_t version)
290{
291 Q_D(QWaylandPointer);
292 wl_resource *resource = d->add(client->client(), id, qMin<uint32_t>(QtWaylandServer::wl_pointer::interfaceVersion(), version))->handle;
293 if (d->enteredSurface && client == d->enteredSurface->client()) {
294 d->send_enter(resource, d->enterSerial, d->enteredSurface->resource(),
295 wl_fixed_from_double(d->localPosition.x()),
296 wl_fixed_from_double(d->localPosition.y()));
297 }
298}
299
306struct wl_resource *QWaylandPointer::focusResource() const
307{
308 Q_D(const QWaylandPointer);
309 QWaylandView *focus = d->seat->mouseFocus();
310 if (!focus)
311 return nullptr;
312
313 // Just return the first resource we can find.
314 return d->resourceMap().value(focus->surface()->waylandClient())->handle;
315}
316
320uint QWaylandPointer::sendButton(struct wl_resource *resource, uint32_t time, Qt::MouseButton button, uint32_t state)
321{
322 // This method is here for compatibility reasons only, since it usually doesn't make sense to
323 // send button events to just one of the pointer resources for a client.
324 Q_D(QWaylandPointer);
325 uint32_t serial = d->compositor()->nextSerial();
326 d->send_button(resource, serial, time, toWaylandButton(button), state);
327 return serial;
328}
329
334{
335#ifndef BTN_LEFT
336 uint32_t BTN_LEFT = 0x110;
337#endif
338 // the range of valid buttons (evdev module) is from 0x110
339 // through 0x11f. 0x120 is the first 'Joystick' button.
340 switch (button) {
341 case Qt::LeftButton: return BTN_LEFT;
342 case Qt::RightButton: return uint32_t(0x111);
343 case Qt::MiddleButton: return uint32_t(0x112);
344 case Qt::ExtraButton1: return uint32_t(0x113); // AKA Qt::BackButton, Qt::XButton1
345 case Qt::ExtraButton2: return uint32_t(0x114); // AKA Qt::ForwardButton, Qt::XButton2
346 case Qt::ExtraButton3: return uint32_t(0x115);
347 case Qt::ExtraButton4: return uint32_t(0x116);
348 case Qt::ExtraButton5: return uint32_t(0x117);
349 case Qt::ExtraButton6: return uint32_t(0x118);
350 case Qt::ExtraButton7: return uint32_t(0x119);
351 case Qt::ExtraButton8: return uint32_t(0x11a);
352 case Qt::ExtraButton9: return uint32_t(0x11b);
353 case Qt::ExtraButton10: return uint32_t(0x11c);
354 case Qt::ExtraButton11: return uint32_t(0x11d);
355 case Qt::ExtraButton12: return uint32_t(0x11e);
356 case Qt::ExtraButton13: return uint32_t(0x11f);
357 // default should not occur; but if it does, then return Wayland's highest possible button number.
358 default: return uint32_t(0x11f);
359 }
360}
361
365void QWaylandPointer::enteredSurfaceDestroyed(void *data)
366{
367 Q_D(QWaylandPointer);
368 Q_UNUSED(data);
369 d->enteredSurfaceDestroyListener.reset();
370 d->enteredSurface = nullptr;
371
372 d->seat->setMouseFocus(nullptr);
373
374 if (d->buttonCount != 0) {
375 d->buttonCount = 0;
377 }
378}
379
383void QWaylandPointer::pointerFocusChanged(QWaylandView *newFocus, QWaylandView *oldFocus)
384{
385 Q_D(QWaylandPointer);
386 Q_UNUSED(oldFocus);
387 bool wasSameSurface = newFocus && newFocus->surface() == d->enteredSurface;
388 if (d->enteredSurface && !wasSameSurface)
389 d->sendLeave();
390}
391
393
394#include "moc_qwaylandpointer.cpp"
\inmodule QtCore
Definition qobject.h:103
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
Definition qobject.cpp:2960
\inmodule QtCore\reentrant
Definition qpoint.h:217
constexpr qreal x() const noexcept
Returns the x coordinate of this point.
Definition qpoint.h:343
constexpr qreal y() const noexcept
Returns the y coordinate of this point.
Definition qpoint.h:348
\inmodule QtCore
Definition qsize.h:208
\qmltype WaylandClient \instantiates QWaylandClient \inqmlmodule QtWayland.Compositor
static QWaylandClient * fromWlClient(QWaylandCompositor *compositor, wl_client *wlClient)
Returns the QWaylandClient corresponding to the Wayland client wlClient and compositor.
wl_client * client() const
Returns the Wayland client of this QWaylandClient.
\qmltype WaylandCompositor \instantiates QWaylandCompositor \inqmlmodule QtWayland....
void fired(void *data)
void listenForDestruction(struct wl_resource *resource)
\inmodule QtWaylandCompositor
virtual void sendKeyModifiers(QWaylandClient *client, uint32_t serial)
Sends the current key modifiers to client with the given serial.
\inmodule QtWaylandCompositor
\qmltype WaylandOutput \instantiates QWaylandOutput \inqmlmodule QtWayland.Compositor
void pointer_set_cursor(Resource *resource, uint32_t serial, wl_resource *surface, int32_t hotspot_x, int32_t hotspot_y) override
void pointer_release(Resource *resource) override
QWaylandPointerPrivate(QWaylandPointer *pointer, QWaylandSeat *seat)
QWaylandCompositor * compositor() const
\inmodule QtWaylandCompositor
virtual void addClient(QWaylandClient *client, uint32_t id, uint32_t version)
QPointF currentSpacePosition() const
Returns the current output space position of the QWaylandPointer.
virtual uint sendMouseReleaseEvent(Qt::MouseButton button)
Sends a mouse release event for button to the view currently holding mouse focus.
uint sendButton(struct wl_resource *resource, uint32_t time, Qt::MouseButton button, uint32_t state)
static uint32_t toWaylandButton(Qt::MouseButton button)
QWaylandView * mouseFocus() const
Returns the view that currently holds mouse focus.
virtual void sendMouseMoveEvent(QWaylandView *view, const QPointF &localPos, const QPointF &outputSpacePos)
Sets the current mouse focus to view and sends a mouse move event to it with the local position local...
QWaylandCompositor * compositor() const
Returns the compositor for this QWaylandPointer.
virtual uint sendMousePressEvent(Qt::MouseButton button)
Sends a mouse press event for button to the view currently holding mouse focus.
QWaylandPointer(QWaylandSeat *seat, QObject *parent=nullptr)
Constructs a QWaylandPointer for the given seat and with the given parent.
virtual void sendMouseWheelEvent(Qt::Orientation orientation, int delta)
Sends a mouse wheel event with the given orientation and delta to the view that currently holds mouse...
QWaylandSeat * seat() const
Returns the input device for this QWaylandPointer.
void setOutput(QWaylandOutput *output)
Sets the output for this QWaylandPointer to output.
QPointF currentLocalPosition() const
Returns the current local position of the QWaylandPointer in surface coordinates.
wl_resource * focusResource() const
Returns a Wayland resource for this QWaylandPointer.
QWaylandOutput * output() const
Returns the output for this QWaylandPointer.
void buttonPressedChanged()
void outputChanged()
\qmltype WaylandSeat \instantiates QWaylandSeat \inqmlmodule QtWayland.Compositor
QWaylandKeyboard * keyboard() const
Returns the keyboard for this input device.
void cursorSurfaceRequested(QWaylandSurface *surface, int hotspotX, int hotspotY, QWaylandClient *client)
void mouseFocusChanged(QWaylandView *newFocus, QWaylandView *oldFocus)
This signal is emitted when the mouse focus has changed from oldFocus to newFocus.
\inmodule QtWaylandCompositor
\qmltype WaylandSurface \instantiates QWaylandSurface \inqmlmodule QtWayland.Compositor
struct wl_resource * resource() const
Returns the Wayland resource corresponding to this QWaylandSurface.
static QWaylandSurface * fromResource(::wl_resource *resource)
Returns the QWaylandSurface corresponding to the Wayland resource resource.
QWaylandClient * client
\qmlproperty WaylandClient QtWayland.Compositor::WaylandSurface::client
\qmltype WaylandView \instantiates QWaylandView \inqmlmodule QtWayland.Compositor
#define this
Definition dialogs.cpp:9
QPushButton * button
[2]
bool focus
[0]
else opt state
[0]
Combined button and popup list for selecting options.
MouseButton
Definition qnamespace.h:56
@ ExtraButton9
Definition qnamespace.h:74
@ LeftButton
Definition qnamespace.h:58
@ ExtraButton5
Definition qnamespace.h:70
@ ExtraButton6
Definition qnamespace.h:71
@ RightButton
Definition qnamespace.h:59
@ ExtraButton12
Definition qnamespace.h:77
@ ExtraButton10
Definition qnamespace.h:75
@ MiddleButton
Definition qnamespace.h:60
@ ExtraButton2
Definition qnamespace.h:66
@ ExtraButton1
Definition qnamespace.h:63
@ ExtraButton11
Definition qnamespace.h:76
@ ExtraButton13
Definition qnamespace.h:78
@ ExtraButton8
Definition qnamespace.h:73
@ ExtraButton3
Definition qnamespace.h:68
@ ExtraButton7
Definition qnamespace.h:72
@ ExtraButton4
Definition qnamespace.h:69
Orientation
Definition qnamespace.h:98
@ Horizontal
Definition qnamespace.h:99
GLenum GLsizei GLsizei GLint * values
[15]
GLuint64 GLenum void * handle
GLint GLint GLint GLint GLint x
[0]
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLint y
GLdouble s
[6]
Definition qopenglext.h:235
GLsizei const void * pointer
Definition qopenglext.h:384
GLdouble GLdouble GLdouble GLdouble q
Definition qopenglext.h:259
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
#define emit
#define Q_UNUSED(x)
unsigned int uint
Definition qtypes.h:34
QT_BEGIN_NAMESPACE typedef uchar * output
QQuickView * view
[0]