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
qwaylandseat.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 "qwaylandseat.h"
5#include "qwaylandseat_p.h"
6
9#include "qwaylandview.h"
10#if QT_CONFIG(draganddrop)
11#include <QtWaylandCompositor/QWaylandDrag>
12#endif
13#include <QtWaylandCompositor/QWaylandTouch>
14#include <QtWaylandCompositor/QWaylandPointer>
15#include <QtWaylandCompositor/QWaylandKeymap>
16#include <QtWaylandCompositor/private/qwaylandseat_p.h>
17#include <QtWaylandCompositor/private/qwaylandcompositor_p.h>
18#include <QtWaylandCompositor/private/qwaylandkeyboard_p.h>
19#if QT_CONFIG(wayland_datadevice)
20#include <QtWaylandCompositor/private/qwldatadevice_p.h>
21#endif
22#include <QtWaylandCompositor/private/qwaylandutils_p.h>
23
28
30
32#if QT_CONFIG(wayland_datadevice)
33 drag_handle(new QWaylandDrag(seat)),
34#endif
35 keymap(new QWaylandKeymap())
36{
37}
38
42
43void QWaylandSeatPrivate::setCapabilities(QWaylandSeat::CapabilityFlags caps)
44{
45 Q_Q(QWaylandSeat);
46 if (capabilities != caps) {
47 QWaylandSeat::CapabilityFlags changed = caps ^ capabilities;
48
49 if (changed & QWaylandSeat::Pointer) {
50 pointer.reset(pointer.isNull() ? QWaylandCompositorPrivate::get(compositor)->callCreatePointerDevice(q) : nullptr);
51 }
52
53 if (changed & QWaylandSeat::Keyboard) {
54 keyboard.reset(keyboard.isNull() ? QWaylandCompositorPrivate::get(compositor)->callCreateKeyboardDevice(q) : nullptr);
55 }
56
57 if (changed & QWaylandSeat::Touch) {
58 touch.reset(touch.isNull() ? QWaylandCompositorPrivate::get(compositor)->callCreateTouchDevice(q) : nullptr);
59 }
60
61 capabilities = caps;
62 QList<Resource *> resources = resourceMap().values();
63 for (int i = 0; i < resources.size(); i++) {
64 wl_seat::send_capabilities(resources.at(i)->handle, (uint32_t)capabilities);
65 }
66
67 if ((changed & caps & QWaylandSeat::Keyboard) && keyboardFocus != nullptr)
68 keyboard->setFocus(keyboardFocus);
69 }
70}
71
72#if QT_CONFIG(wayland_datadevice)
73void QWaylandSeatPrivate::clientRequestedDataDevice(QtWayland::DataDeviceManager *, struct wl_client *client, uint32_t id)
74{
75 Q_Q(QWaylandSeat);
76 if (!data_device)
77 data_device.reset(new QtWayland::DataDevice(q));
78 data_device->add(client, id, 1);
79}
80#endif
81
83{
84// cleanupDataDeviceForClient(resource->client(), true);
85}
86
87void QWaylandSeatPrivate::seat_bind_resource(wl_seat::Resource *resource)
88{
89 // The order of capabilities matches the order defined in the wayland protocol
90 wl_seat::send_capabilities(resource->handle, (uint32_t)capabilities);
91}
92
93void QWaylandSeatPrivate::seat_get_pointer(wl_seat::Resource *resource, uint32_t id)
94{
95 if (!pointer.isNull()) {
96 pointer->addClient(QWaylandClient::fromWlClient(compositor, resource->client()), id, resource->version());
97 }
98}
99
100void QWaylandSeatPrivate::seat_get_keyboard(wl_seat::Resource *resource, uint32_t id)
101{
102 if (!keyboard.isNull()) {
103 keyboard->addClient(QWaylandClient::fromWlClient(compositor, resource->client()), id, resource->version());
104 }
105}
106
107void QWaylandSeatPrivate::seat_get_touch(wl_seat::Resource *resource, uint32_t id)
108{
109 if (!touch.isNull()) {
110 touch->addClient(QWaylandClient::fromWlClient(compositor, resource->client()), id, resource->version());
111 }
112}
113
152{
153 Q_D(QWaylandSeat);
154 d->compositor = compositor;
155 d->capabilities = capabilityFlags;
156 if (compositor->isCreated())
157 initialize();
158
159 // Support deprecated signal for backward compatibility
160 connect(this, &QWaylandSeat::cursorSurfaceRequested, this, &QWaylandSeat::cursorSurfaceRequest);
161}
162
169
179{
180 Q_D(QWaylandSeat);
181 d->init(d->compositor->display(), 4);
182
183 if (d->capabilities & QWaylandSeat::Pointer)
184 d->pointer.reset(QWaylandCompositorPrivate::get(d->compositor)->callCreatePointerDevice(this));
185 if (d->capabilities & QWaylandSeat::Touch)
186 d->touch.reset(QWaylandCompositorPrivate::get(d->compositor)->callCreateTouchDevice(this));
187 if (d->capabilities & QWaylandSeat::Keyboard)
188 d->keyboard.reset(QWaylandCompositorPrivate::get(d->compositor)->callCreateKeyboardDevice(this));
189
190 d->isInitialized = true;
191}
192
199{
200 Q_D(const QWaylandSeat);
201 return d->isInitialized;
202}
203
208{
209 Q_D(QWaylandSeat);
210 d->pointer->sendMousePressEvent(button);
211}
212
217{
218 Q_D(QWaylandSeat);
219 d->pointer->sendMouseReleaseEvent(button);
220}
221
226void QWaylandSeat::sendMouseMoveEvent(QWaylandView *view, const QPointF &localPos, const QPointF &outputSpacePos)
227{
228 Q_D(QWaylandSeat);
229 d->pointer->sendMouseMoveEvent(view, localPos, outputSpacePos);
230}
231
236{
237 Q_D(QWaylandSeat);
238 d->pointer->sendMouseWheelEvent(orientation, delta);
239}
240
245{
246 Q_D(QWaylandSeat);
247 d->keyboard->sendKeyPressEvent(code);
248}
249
254{
255 Q_D(QWaylandSeat);
256 d->keyboard->sendKeyReleaseEvent(code);
257}
258
270{
271 Q_D(QWaylandSeat);
272
273 if (d->touch.isNull())
274 return 0;
275
276 return d->touch->sendTouchPointEvent(surface, id, point,state);
277}
278
312
346
380
393{
394 Q_D(QWaylandSeat);
395 if (!d->touch.isNull())
396 d->touch->sendFrameEvent(client);
397}
398
409{
410 Q_D(QWaylandSeat);
411 if (!d->touch.isNull())
412 d->touch->sendCancelEvent(client);
413}
414
424{
425 Q_D(QWaylandSeat);
426
427 if (!d->touch)
428 return;
429
430 d->touch->sendFullTouchEvent(surface, event);
431}
432
442{
443 Q_D(QWaylandSeat);
444
445 if (!keyboardFocus()) {
446 qWarning("Cannot send key event, no keyboard focus, fix the compositor");
447 return;
448 }
449
450#if QT_CONFIG(im)
451 if (keyboardFocus()->inputMethodControl()->enabled()
452 && event->nativeScanCode() == 0) {
453 if (keyboardFocus()->client()->textInputProtocols().testFlag(QWaylandClient::TextInputProtocol::TextInputV2)) {
455 if (textInput) {
456 textInput->sendKeyEvent(event);
457 return;
458 }
459 }
460
463 if (textInputMethod) {
464 textInputMethod->sendKeyEvent(event);
465 return;
466 }
467 }
468
469 if (keyboardFocus()->client()->textInputProtocols().testFlag(QWaylandClient::TextInputProtocol::TextInputV3)) {
471 if (textInputV3 && !event->text().isEmpty()) {
472 // it will just commit the text for text-input-unstable-v3 when keyPress
473 if (event->type() == QEvent::KeyPress)
474 textInputV3->sendKeyEvent(event);
475 return;
476 }
477 }
478 }
479#endif
480
482 if (ext && ext->postQtKeyEvent(event, keyboardFocus()))
483 return;
484
485 if (!d->keyboard.isNull() && !event->isAutoRepeat()) {
486
487 uint scanCode = event->nativeScanCode();
488 if (scanCode == 0)
489 scanCode = d->keyboard->keyToScanCode(event->key());
490
491 if (scanCode == 0) {
492 qWarning() << "Can't send Wayland key event: Unable to get a valid scan code";
493 return;
494 }
495
496 if (event->type() == QEvent::KeyPress) {
497 QWaylandKeyboardPrivate::get(d->keyboard.data())->checkAndRepairModifierState(event);
498 d->keyboard->sendKeyPressEvent(scanCode);
499 } else if (event->type() == QEvent::KeyRelease) {
500 d->keyboard->sendKeyReleaseEvent(scanCode);
501 }
502 }
503}
504
522void QWaylandSeat::sendKeyEvent(int qtKey, bool pressed)
523{
524 Q_D(QWaylandSeat);
525 if (!keyboardFocus()) {
526 qWarning("Cannot send Wayland key event, no keyboard focus, fix the compositor");
527 return;
528 }
529
530 if (auto scanCode = d->keyboard->keyToScanCode(qtKey)) {
531 if (pressed)
532 d->keyboard->sendKeyPressEvent(scanCode);
533 else
534 d->keyboard->sendKeyReleaseEvent(scanCode);
535 } else {
536 qWarning() << "Can't send Wayland key event: Unable to get scan code for" << Qt::Key(qtKey);
537 }
538}
539
560void QWaylandSeat::sendUnicodeKeyPressEvent(uint unicode)
561{
562 sendUnicodeKeyEvent(unicode, QEvent::KeyPress);
563}
564
585void QWaylandSeat::sendUnicodeKeyReleaseEvent(uint unicode)
586{
587 sendUnicodeKeyEvent(unicode, QEvent::KeyRelease);
588}
589
595void QWaylandSeat::sendUnicodeKeyEvent(uint unicode, QEvent::Type eventType)
596{
597 if (!keyboardFocus()) {
598 qWarning("Can't send a unicode key event, no keyboard focus, fix the compositor");
599 return;
600 }
601#if QT_CONFIG(im)
603 text += QChar::fromUcs4(static_cast<char32_t>(unicode));
604
605 QKeyEvent event(eventType, Qt::Key_unknown, Qt::KeyboardModifiers{}, text);
606 if (keyboardFocus()->client()->textInputProtocols().testFlag(QWaylandClient::TextInputProtocol::TextInputV2)) {
608 if (textInput) {
609 textInput->sendKeyEvent(&event);
610 return;
611 }
612 }
613
616 if (textInputMethod) {
617 textInputMethod->sendKeyEvent(&event);
618 return;
619 }
620 }
621
622 if (keyboardFocus()->client()->textInputProtocols().testFlag(QWaylandClient::TextInputProtocol::TextInputV3)) {
624 if (textInputV3 && !text.isEmpty()) {
625 // it will just commit the text for text-input-unstable-v3 when keyPress
626 if (eventType == QEvent::KeyPress)
627 textInputV3->sendKeyEvent(&event);
628 return;
629 }
630 }
631#else
632 Q_UNUSED(unicode);
633 Q_UNUSED(eventType);
634 qWarning() << "Can't send a unicode key event: Unable to find a text-input protocol.";
635#endif
636}
637
642{
643 Q_D(const QWaylandSeat);
644 return d->keyboard.data();
645}
646
651{
652 Q_D(const QWaylandSeat);
653 if (d->keyboard.isNull() || !d->keyboard->focus())
654 return nullptr;
655
656 return d->keyboard->focus();
657}
658
665{
666 Q_D(QWaylandSeat);
667 if (surface && surface->isDestroyed())
668 return false;
669
670 QWaylandSurface *oldSurface = keyboardFocus();
671 if (surface == oldSurface)
672 return true;
673
674 d->keyboardFocus = surface;
675 if (!d->keyboard.isNull())
676 d->keyboard->setFocus(surface);
677#if QT_CONFIG(wayland_datadevice)
678 if (d->data_device)
679 d->data_device->setFocus(surface ? surface->client() : nullptr);
680#endif
681 emit keyboardFocusChanged(surface, oldSurface);
682 return true;
683}
684
685
691{
692 Q_D(const QWaylandSeat);
693 return d->keymap.data();
694}
695
700{
701 Q_D(const QWaylandSeat);
702 return d->pointer.data();
703}
704
709{
710 Q_D(const QWaylandSeat);
711 return d->touch.data();
712}
713
718{
719 Q_D(const QWaylandSeat);
720 return d->mouseFocus;
721}
722
727{
728 Q_D(QWaylandSeat);
729 if (view == d->mouseFocus)
730 return;
731
732 QWaylandView *oldFocus = d->mouseFocus;
733 d->mouseFocus = view;
734
735 if (oldFocus)
736 disconnect(oldFocus, &QObject::destroyed, this, &QWaylandSeat::handleMouseFocusDestroyed);
737 if (d->mouseFocus)
738 connect(d->mouseFocus, &QObject::destroyed, this, &QWaylandSeat::handleMouseFocusDestroyed);
739
740 emit mouseFocusChanged(d->mouseFocus, oldFocus);
741}
742
747{
748 Q_D(const QWaylandSeat);
749 return d->compositor;
750}
751
755#if QT_CONFIG(draganddrop)
756QWaylandDrag *QWaylandSeat::drag() const
757{
758 Q_D(const QWaylandSeat);
759 return d->drag_handle.data();
760}
761#endif
762
766QWaylandSeat::CapabilityFlags QWaylandSeat::capabilities() const
767{
768 Q_D(const QWaylandSeat);
769 return d->capabilities;
770}
771
775bool QWaylandSeat::isOwner(QInputEvent *inputEvent) const
776{
777 Q_UNUSED(inputEvent);
778 return true;
779}
780
785QWaylandSeat *QWaylandSeat::fromSeatResource(struct ::wl_resource *resource)
786{
787 if (auto p = QtWayland::fromResource<QWaylandSeatPrivate *>(resource))
788 return p->q_func();
789 return nullptr;
790}
791
798void QWaylandSeat::handleMouseFocusDestroyed()
799{
800 // This is triggered when the QWaylandView is destroyed, NOT the surface.
801 // ... so this is for the rare case when the view that currently holds the mouse focus is
802 // destroyed before its surface
803 Q_D(QWaylandSeat);
804 d->mouseFocus = nullptr;
805 QWaylandView *oldFocus = nullptr; // we have to send nullptr because the old focus is already destroyed at this point
806 emit mouseFocusChanged(d->mouseFocus, oldFocus);
807}
808
809
875
876#include "moc_qwaylandseat.cpp"
Type
This enum type defines the valid event types in Qt.
Definition qcoreevent.h:51
@ KeyRelease
Definition qcoreevent.h:65
@ KeyPress
Definition qcoreevent.h:64
\inmodule QtGui
Definition qevent.h:49
The QKeyEvent class describes a key event.
Definition qevent.h:424
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
void destroyed(QObject *=nullptr)
This signal is emitted immediately before the object obj is destroyed, after any instances of QPointe...
\inmodule QtCore\reentrant
Definition qpoint.h:217
bool isNull() const noexcept
Returns true if this object refers to \nullptr.
void reset(T *other=nullptr) noexcept(noexcept(Cleanup::cleanup(std::declval< T * >())))
Deletes the existing object it is pointing to (if any), and sets its pointer to other.
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
bool isEmpty() const noexcept
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:192
The QTouchEvent class contains parameters that describe a touch event.
Definition qevent.h:917
\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.
static QWaylandTextInput * findIn(QWaylandObject *container)
If any instance of the interface has been registered with container, this is returned.
static QWaylandCompositorPrivate * get(QWaylandCompositor *compositor)
\qmltype WaylandCompositor \instantiates QWaylandCompositor \inqmlmodule QtWayland....
static QWaylandKeyboardPrivate * get(QWaylandKeyboard *keyboard)
\inmodule QtWaylandCompositor
virtual void setFocus(QWaylandSurface *surface)
Sets the current focus to surface.
virtual void addClient(QWaylandClient *client, uint32_t id, uint32_t version)
\inmodule QtWaylandCompositor
\inmodule QtWaylandCompositor
~QWaylandSeatPrivate() override
void seat_get_keyboard(wl_seat::Resource *resource, uint32_t id) override
void seat_get_pointer(wl_seat::Resource *resource, uint32_t id) override
QWaylandSeatPrivate(QWaylandSeat *seat)
void seat_destroy_resource(wl_seat::Resource *resource) override
void seat_get_touch(wl_seat::Resource *resource, uint32_t id) override
void seat_bind_resource(wl_seat::Resource *resource) override
void setCapabilities(QWaylandSeat::CapabilityFlags caps)
\qmltype WaylandSeat \instantiates QWaylandSeat \inqmlmodule QtWayland.Compositor
~QWaylandSeat() override
Destroys the QWaylandSeat.
QWaylandSeat::CapabilityFlags capabilities() const
Returns the drag object for this QWaylandSeat.
void keyboardFocusChanged(QWaylandSurface *newFocus, QWaylandSurface *oldFocus)
\qmlsignal void QtWayland.Compositor::WaylandSeat::keyboardFocusChanged(QWaylandSurface newFocus,...
QWaylandKeymap * keymap
Returns the keymap object for this QWaylandSeat.
QWaylandSeat(QWaylandCompositor *compositor, CapabilityFlags capabilityFlags=DefaultCapabilities)
Constructs a QWaylandSeat for the given compositor and capabilityFlags.
void sendMouseMoveEvent(QWaylandView *surface, const QPointF &localPos, const QPointF &outputSpacePos=QPointF())
Sets the mouse focus to view and sends a mouse move event to the pointer device with the local positi...
Q_INVOKABLE uint sendTouchPointReleased(QWaylandSurface *surface, int id, const QPointF &position)
\qmlmethod void QtWayland.Compositor::WaylandSeat::sendTouchPointReleased(WaylandSurface surface,...
void sendMouseReleaseEvent(Qt::MouseButton button)
Sends a mouse release event for button to the QWaylandSeat's pointer device.
void setMouseFocus(QWaylandView *view)
Sets the current mouse focus to view.
void sendFullTouchEvent(QWaylandSurface *surface, QTouchEvent *event)
Sends the event to the specified surface on the touch device.
void sendMousePressEvent(Qt::MouseButton button)
Sends a mouse press event for button to the QWaylandSeat's pointer device.
QWaylandKeyboard * keyboard() const
Returns the keyboard for this input device.
void sendKeyReleaseEvent(uint code)
Sends a key release event with the key code to the keyboard device.
Q_INVOKABLE void sendKeyEvent(int qtKey, bool pressed)
\qmlmethod void QtWayland.Compositor::WaylandSeat::sendKeyEvent(int qtKey, bool pressed)
bool isInitialized() const
Returns true if the QWaylandSeat is initialized; false otherwise.
void cursorSurfaceRequested(QWaylandSurface *surface, int hotspotX, int hotspotY, QWaylandClient *client)
QWaylandPointer * pointer() const
Returns the pointer device for this QWaylandSeat.
static QWaylandSeat * fromSeatResource(struct ::wl_resource *resource)
Returns the QWaylandSeat corresponding to the resource.
void sendFullKeyEvent(QKeyEvent *event)
Sends the event to the keyboard device.
QWaylandSurface * keyboardFocus() const
Returns the current focused surface for keyboard input.
QWaylandTouch * touch() const
Returns the touch device for this QWaylandSeat.
QWaylandView * mouseFocus() const
Returns the view that currently has mouse focus.
bool setKeyboardFocus(QWaylandSurface *surface)
Sets the current keyboard focus to surface.
void sendMouseWheelEvent(Qt::Orientation orientation, int delta)
Sends a mouse wheel event to the QWaylandSeat's pointer device with the given orientation and delta.
Q_INVOKABLE void sendTouchFrameEvent(QWaylandClient *client)
\qmlmethod void QtWayland.Compositor::WaylandSeat::sendTouchFrameEvent(WaylandClient client)
Q_INVOKABLE uint sendTouchPointPressed(QWaylandSurface *surface, int id, const QPointF &position)
\qmlmethod uint QtWayland.Compositor::WaylandSeat::sendTouchPointPressed(WaylandSurface surface,...
virtual void initialize()
Initializes parts of the seat corresponding to the capabilities set in the constructor,...
uint sendTouchPointEvent(QWaylandSurface *surface, int id, const QPointF &point, Qt::TouchPointState state)
Sends a touch point event to the surface on a touch device with the given id, point and state.
QWaylandCompositor * compositor() const
Returns the compositor for this QWaylandSeat.
virtual bool isOwner(QInputEvent *inputEvent) const
Q_INVOKABLE void sendTouchCancelEvent(QWaylandClient *client)
\qmlmethod void QtWayland.Compositor::WaylandSeat::sendTouchCancelEvent(WaylandClient client)
Q_INVOKABLE uint sendTouchPointMoved(QWaylandSurface *surface, int id, const QPointF &position)
\qmlmethod void QtWayland.Compositor::WaylandSeat::sendTouchPointMoved(WaylandSurface surface,...
void sendKeyPressEvent(uint code)
Sends a key press event with the key code to the keyboard device.
void mouseFocusChanged(QWaylandView *newFocus, QWaylandView *oldFocus)
This signal is emitted when the mouse focus has changed from oldFocus to newFocus.
\qmltype WaylandSurface \instantiates QWaylandSurface \inqmlmodule QtWayland.Compositor
QWaylandClient * client
\qmlproperty WaylandClient QtWayland.Compositor::WaylandSurface::client
Q_INVOKABLE bool isDestroyed() const
\qmlmethod bool QtWayland.Compositor::WaylandSurface::isDestroyed()
void sendKeyEvent(QKeyEvent *event)
void sendKeyEvent(QKeyEvent *event)
\inmodule QtWaylandCompositor
virtual void addClient(QWaylandClient *client, uint32_t id, uint32_t version)
\qmltype WaylandView \instantiates QWaylandView \inqmlmodule QtWayland.Compositor
bool postQtKeyEvent(QKeyEvent *event, QWaylandSurface *surface)
Definition qwlqtkey.cpp:20
#define this
Definition dialogs.cpp:9
QString text
QPushButton * button
[2]
else opt state
[0]
Combined button and popup list for selecting options.
MouseButton
Definition qnamespace.h:56
Orientation
Definition qnamespace.h:98
@ Key_unknown
TouchPointState
@ TouchPointReleased
@ TouchPointPressed
@ TouchPointMoved
#define qWarning
Definition qlogging.h:166
static QOpenGLCompositor * compositor
struct _cl_event * event
GLsizei const void * pointer
Definition qopenglext.h:384
GLdouble GLdouble GLdouble GLdouble q
Definition qopenglext.h:259
GLfloat GLfloat p
[1]
static qreal position(const QQuickItem *item, QQuickAnchors::Anchor anchorLine)
static QString qtKey(CFStringRef cfkey)
#define QT_CONFIG(feature)
#define emit
#define Q_UNUSED(x)
unsigned int uint
Definition qtypes.h:34
bool testFlag(MaskType mask, FlagType flag)
#define enabled
if(qFloatDistance(a, b)<(1<< 7))
[0]
myObject disconnect()
[26]
QQuickView * view
[0]