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
7#include "qwaylandcompositor.h"
8#include "qwaylandinputmethodcontrol.h"
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
24#include "extensions/qwlqtkey_p.h"
25#include "extensions/qwaylandtextinput.h"
26#if QT_WAYLAND_TEXT_INPUT_V4_WIP
27#include "extensions/qwaylandtextinputv4.h"
28#endif // QT_WAYLAND_TEXT_INPUT_V4_WIP
29#include "extensions/qwaylandqttextinputmethod.h"
30
31QT_BEGIN_NAMESPACE
32
33QWaylandSeatPrivate::QWaylandSeatPrivate(QWaylandSeat *seat) :
34#if QT_CONFIG(wayland_datadevice)
35 drag_handle(new QWaylandDrag(seat)),
36#endif
37 keymap(new QWaylandKeymap())
38{
39}
40
41QWaylandSeatPrivate::~QWaylandSeatPrivate()
42{
43}
44
45void QWaylandSeatPrivate::setCapabilities(QWaylandSeat::CapabilityFlags caps)
46{
47 Q_Q(QWaylandSeat);
48 if (capabilities != caps) {
49 QWaylandSeat::CapabilityFlags changed = caps ^ capabilities;
50
51 if (changed & QWaylandSeat::Pointer) {
52 pointer.reset(pointer.isNull() ? QWaylandCompositorPrivate::get(compositor)->callCreatePointerDevice(q) : nullptr);
53 }
54
55 if (changed & QWaylandSeat::Keyboard) {
56 keyboard.reset(keyboard.isNull() ? QWaylandCompositorPrivate::get(compositor)->callCreateKeyboardDevice(q) : nullptr);
57 }
58
59 if (changed & QWaylandSeat::Touch) {
60 touch.reset(touch.isNull() ? QWaylandCompositorPrivate::get(compositor)->callCreateTouchDevice(q) : nullptr);
61 }
62
63 capabilities = caps;
64 QList<Resource *> resources = resourceMap().values();
65 for (int i = 0; i < resources.size(); i++) {
66 wl_seat::send_capabilities(resources.at(i)->handle, (uint32_t)capabilities);
67 }
68
69 if ((changed & caps & QWaylandSeat::Keyboard) && keyboardFocus != nullptr)
70 keyboard->setFocus(keyboardFocus);
71 }
72}
73
74#if QT_CONFIG(wayland_datadevice)
75void QWaylandSeatPrivate::clientRequestedDataDevice(QtWayland::DataDeviceManager *, struct wl_client *client, uint32_t id)
76{
77 Q_Q(QWaylandSeat);
78 if (!data_device)
79 data_device.reset(new QtWayland::DataDevice(q));
80 data_device->add(client, id, 1);
81}
82#endif
83
84void QWaylandSeatPrivate::seat_destroy_resource(wl_seat::Resource *)
85{
86// cleanupDataDeviceForClient(resource->client(), true);
87}
88
89void QWaylandSeatPrivate::seat_bind_resource(wl_seat::Resource *resource)
90{
91 // The order of capabilities matches the order defined in the wayland protocol
92 wl_seat::send_capabilities(resource->handle, (uint32_t)capabilities);
93}
94
95void QWaylandSeatPrivate::seat_get_pointer(wl_seat::Resource *resource, uint32_t id)
96{
97 if (!pointer.isNull()) {
98 pointer->addClient(QWaylandClient::fromWlClient(compositor, resource->client()), id, resource->version());
99 }
100}
101
102void QWaylandSeatPrivate::seat_get_keyboard(wl_seat::Resource *resource, uint32_t id)
103{
104 if (!keyboard.isNull()) {
105 keyboard->addClient(QWaylandClient::fromWlClient(compositor, resource->client()), id, resource->version());
106 }
107}
108
109void QWaylandSeatPrivate::seat_get_touch(wl_seat::Resource *resource, uint32_t id)
110{
111 if (!touch.isNull()) {
112 touch->addClient(QWaylandClient::fromWlClient(compositor, resource->client()), id, resource->version());
113 }
114}
115
116/*!
117 * \qmltype WaylandSeat
118 * \instantiates QWaylandSeat
119 * \inqmlmodule QtWayland.Compositor
120 * \since 5.8
121 * \brief Provides access to keyboard, mouse, and touch input.
122 *
123 * The WaylandSeat type provides access to different types of user input and maintains
124 * a keyboard focus and a mouse pointer. It corresponds to the wl_seat interface in the Wayland
125 * protocol.
126 */
127
128/*!
129 * \class QWaylandSeat
130 * \inmodule QtWaylandCompositor
131 * \since 5.8
132 * \brief The QWaylandSeat class provides access to keyboard, mouse, and touch input.
133 *
134 * The QWaylandSeat provides access to different types of user input and maintains
135 * a keyboard focus and a mouse pointer. It corresponds to the wl_seat interface in the Wayland protocol.
136 */
137
138/*!
139 * \enum QWaylandSeat::CapabilityFlag
140 *
141 * This enum type describes the capabilities of a QWaylandSeat.
142 *
143 * \value Pointer The QWaylandSeat supports pointer input.
144 * \value Keyboard The QWaylandSeat supports keyboard input.
145 * \value Touch The QWaylandSeat supports touch input.
146 * \value DefaultCapabilities The QWaylandSeat has the default capabilities.
147 */
148
149/*!
150 * Constructs a QWaylandSeat for the given \a compositor and \a capabilityFlags.
151 */
152QWaylandSeat::QWaylandSeat(QWaylandCompositor *compositor, CapabilityFlags capabilityFlags)
153 : QWaylandObject(*new QWaylandSeatPrivate(this))
154{
155 Q_D(QWaylandSeat);
156 d->compositor = compositor;
157 d->capabilities = capabilityFlags;
158 if (compositor->isCreated())
159 initialize();
160
161 // Support deprecated signal for backward compatibility
162 connect(sender: this, signal: &QWaylandSeat::cursorSurfaceRequested, context: this, slot: &QWaylandSeat::cursorSurfaceRequest);
163}
164
165/*!
166 * Destroys the QWaylandSeat
167 */
168QWaylandSeat::~QWaylandSeat()
169{
170}
171
172/*!
173 * Initializes parts of the seat corresponding to the capabilities set in the constructor, or
174 * through setCapabilities().
175 *
176 * \note Normally, this function is called automatically after the seat and compositor have been
177 * created, so calling it manually is usually unnecessary.
178 */
179
180void QWaylandSeat::initialize()
181{
182 Q_D(QWaylandSeat);
183 d->init(d->compositor->display(), 4);
184
185 if (d->capabilities & QWaylandSeat::Pointer)
186 d->pointer.reset(QWaylandCompositorPrivate::get(compositor: d->compositor)->callCreatePointerDevice(seat: this));
187 if (d->capabilities & QWaylandSeat::Touch)
188 d->touch.reset(QWaylandCompositorPrivate::get(compositor: d->compositor)->callCreateTouchDevice(seat: this));
189 if (d->capabilities & QWaylandSeat::Keyboard)
190 d->keyboard.reset(QWaylandCompositorPrivate::get(compositor: d->compositor)->callCreateKeyboardDevice(seat: this));
191
192 d->isInitialized = true;
193}
194
195/*!
196 * Returns true if the QWaylandSeat is initialized; false otherwise.
197 *
198 * The value \c true indicates that it's now possible for clients to start using the seat.
199 */
200bool QWaylandSeat::isInitialized() const
201{
202 Q_D(const QWaylandSeat);
203 return d->isInitialized;
204}
205
206/*!
207 * Sends a mouse press event for \a button to the QWaylandSeat's pointer device.
208 */
209void QWaylandSeat::sendMousePressEvent(Qt::MouseButton button)
210{
211 Q_D(QWaylandSeat);
212 d->pointer->sendMousePressEvent(button);
213}
214
215/*!
216 * Sends a mouse release event for \a button to the QWaylandSeat's pointer device.
217 */
218void QWaylandSeat::sendMouseReleaseEvent(Qt::MouseButton button)
219{
220 Q_D(QWaylandSeat);
221 d->pointer->sendMouseReleaseEvent(button);
222}
223
224/*!
225 * Sets the mouse focus to \a view and sends a mouse move event to the pointer device with the
226 * local position \a localPos and output space position \a outputSpacePos.
227 **/
228void QWaylandSeat::sendMouseMoveEvent(QWaylandView *view, const QPointF &localPos, const QPointF &outputSpacePos)
229{
230 Q_D(QWaylandSeat);
231 d->pointer->sendMouseMoveEvent(view, localPos, outputSpacePos);
232}
233
234/*!
235 * Sends a mouse wheel event to the QWaylandSeat's pointer device with the given \a orientation and \a delta.
236 */
237void QWaylandSeat::sendMouseWheelEvent(Qt::Orientation orientation, int delta)
238{
239 Q_D(QWaylandSeat);
240 d->pointer->sendMouseWheelEvent(orientation, delta);
241}
242
243/*!
244 * Sends a key press event with the key \a code to the keyboard device.
245 */
246void QWaylandSeat::sendKeyPressEvent(uint code)
247{
248 Q_D(QWaylandSeat);
249 d->keyboard->sendKeyPressEvent(code);
250}
251
252/*!
253 * Sends a key release event with the key \a code to the keyboard device.
254 */
255void QWaylandSeat::sendKeyReleaseEvent(uint code)
256{
257 Q_D(QWaylandSeat);
258 d->keyboard->sendKeyReleaseEvent(code);
259}
260
261/*!
262 * Sends a touch point event to the \a surface on a touch device with the given
263 * \a id, \a point and \a state.
264 *
265 * \warning This API should not be used in combination with forwarding of touch
266 * events using \l QWaylandQuickItem::touchEventsEnabled or \l sendFullTouchEvent,
267 * as it might lead to conflicting touch ids.
268 *
269 * Returns the serial for the touch up or touch down event.
270 */
271uint QWaylandSeat::sendTouchPointEvent(QWaylandSurface *surface, int id, const QPointF &point, Qt::TouchPointState state)
272{
273 Q_D(QWaylandSeat);
274
275 if (d->touch.isNull())
276 return 0;
277
278 return d->touch->sendTouchPointEvent(surface, id, point,state);
279}
280
281/*!
282 * \qmlmethod uint QtWayland.Compositor::WaylandSeat::sendTouchPointPressed(WaylandSurface surface, int id, point position)
283 *
284 * Sends a touch pressed event for the touch point \a id on \a surface with
285 * position \a position.
286 *
287 * \note You need to send a touch frame event when you are done sending touch
288 * events.
289 *
290 * \warning This API should not be used in combination with forwarding of touch
291 * events using \l WaylandQuickItem::touchEventsEnabled, as it might lead to
292 * conflicting touch ids.
293 *
294 * Returns the serial for the touch down event.
295 */
296
297/*!
298 * Sends a touch pressed event for the touch point \a id on \a surface with
299 * position \a position.
300 *
301 * \note You need to send a touch frame event when you are done sending touch
302 * events.
303 *
304 * \warning This API should not be used in combination with forwarding of touch
305 * events using \l QWaylandQuickItem::touchEventsEnabled or \l sendFullTouchEvent,
306 * as it might lead to conflicting touch ids.
307 *
308 * Returns the serial for the touch down event.
309 */
310uint QWaylandSeat::sendTouchPointPressed(QWaylandSurface *surface, int id, const QPointF &position)
311{
312 return sendTouchPointEvent(surface, id, point: position, state: Qt::TouchPointPressed);
313}
314
315/*!
316 * \qmlmethod void QtWayland.Compositor::WaylandSeat::sendTouchPointReleased(WaylandSurface surface, int id, point position)
317 *
318 * Sends a touch released event for the touch point \a id on \a surface with
319 * position \a position.
320 *
321 * \note You need to send a touch frame event when you are done sending touch
322 * events.
323 *
324 * \warning This API should not be used in combination with forwarding of touch
325 * events using \l WaylandQuickItem::touchEventsEnabled, as it might lead to
326 * conflicting touch ids.
327 *
328 * Returns the serial for the touch up event.
329 */
330
331/*!
332 * Sends a touch released event for the touch point \a id on \a surface with
333 * position \a position.
334 *
335 * \note You need to send a touch frame event when you are done sending touch
336 * events.
337 *
338 * \warning This API should not be used in combination with forwarding of touch
339 * events using \l QWaylandQuickItem::touchEventsEnabled or \l sendFullTouchEvent,
340 * as it might lead to conflicting touch ids.
341 *
342 * Returns the serial for the touch up event.
343 */
344uint QWaylandSeat::sendTouchPointReleased(QWaylandSurface *surface, int id, const QPointF &position)
345{
346 return sendTouchPointEvent(surface, id, point: position, state: Qt::TouchPointReleased);
347}
348
349/*!
350 * \qmlmethod void QtWayland.Compositor::WaylandSeat::sendTouchPointMoved(WaylandSurface surface, int id, point position)
351 *
352 * Sends a touch moved event for the touch point \a id on \a surface with
353 * position \a position.
354 *
355 * \note You need to send a touch frame event when you are done sending touch
356 * events.
357 *
358 * \warning This API should not be used in combination with forwarding of touch
359 * events using \l WaylandQuickItem::touchEventsEnabled, as it might lead to
360 * conflicting touch ids.
361 *
362 * Returns the serial for the touch motion event.
363 */
364
365/*!
366 * Sends a touch moved event for the touch point \a id on \a surface with
367 * position \a position.
368 *
369 * \note You need to send a touch frame event when you are done sending touch
370 * events.
371 *
372 * \warning This API should not be used in combination with forwarding of touch
373 * events using \l QWaylandQuickItem::touchEventsEnabled or \l sendFullTouchEvent,
374 * as it might lead to conflicting touch ids.
375 *
376 * Returns the serial for the touch motion event.
377 */
378uint QWaylandSeat::sendTouchPointMoved(QWaylandSurface *surface, int id, const QPointF &position)
379{
380 return sendTouchPointEvent(surface, id, point: position, state: Qt::TouchPointMoved);
381}
382
383/*!
384 * \qmlmethod void QtWayland.Compositor::WaylandSeat::sendTouchFrameEvent(WaylandClient client)
385 *
386 * Sends a frame event to the touch device of a \a client to indicate the end
387 * of a series of touch up, down, and motion events.
388 */
389
390/*!
391 * Sends a frame event to the touch device of a \a client to indicate the end
392 * of a series of touch up, down, and motion events.
393 */
394void QWaylandSeat::sendTouchFrameEvent(QWaylandClient *client)
395{
396 Q_D(QWaylandSeat);
397 if (!d->touch.isNull())
398 d->touch->sendFrameEvent(client);
399}
400
401/*!
402 * \qmlmethod void QtWayland.Compositor::WaylandSeat::sendTouchCancelEvent(WaylandClient client)
403 *
404 * Sends a cancel event to the touch device of a \a client.
405 */
406
407/*!
408 * Sends a cancel event to the touch device of a \a client.
409 */
410void QWaylandSeat::sendTouchCancelEvent(QWaylandClient *client)
411{
412 Q_D(QWaylandSeat);
413 if (!d->touch.isNull())
414 d->touch->sendCancelEvent(client);
415}
416
417/*!
418 * Sends the \a event to the specified \a surface on the touch device.
419 *
420 * \warning This API will automatically map \l QEventPoint::id() to a
421 * sequential id before sending it to the client. It should therefore not be
422 * used in combination with the other API using explicit ids, as collisions
423 * might occur.
424 */
425void QWaylandSeat::sendFullTouchEvent(QWaylandSurface *surface, QTouchEvent *event)
426{
427 Q_D(QWaylandSeat);
428
429 if (!d->touch)
430 return;
431
432 d->touch->sendFullTouchEvent(surface, event);
433}
434
435/*!
436 * Sends the \a event to the keyboard device.
437 *
438 * \note The \a event should correspond to an actual keyboard key in the current mapping.
439 * For example, \c Qt::Key_Exclam is normally not a separate key: with most keyboards the
440 * exclamation mark is produced with Shift + 1. In that case, to send an exclamation mark
441 * key press event, use \c{QKeyEvent(QEvent::KeyPress, Qt::Key_1, Qt::ShiftModifier)}.
442 */
443void QWaylandSeat::sendFullKeyEvent(QKeyEvent *event)
444{
445 Q_D(QWaylandSeat);
446
447 if (!keyboardFocus()) {
448 qWarning(msg: "Cannot send key event, no keyboard focus, fix the compositor");
449 return;
450 }
451
452#if QT_CONFIG(im)
453 if (keyboardFocus()->inputMethodControl()->enabled()
454 && event->nativeScanCode() == 0) {
455 if (keyboardFocus()->client()->textInputProtocols().testFlag(flag: QWaylandClient::TextInputProtocol::TextInputV2)) {
456 QWaylandTextInput *textInput = QWaylandTextInput::findIn(container: this);
457 if (textInput) {
458 textInput->sendKeyEvent(event);
459 return;
460 }
461 }
462
463 if (keyboardFocus()->client()->textInputProtocols().testFlag(flag: QWaylandClient::TextInputProtocol::QtTextInputMethodV1)) {
464 QWaylandQtTextInputMethod *textInputMethod = QWaylandQtTextInputMethod::findIn(container: this);
465 if (textInputMethod) {
466 textInputMethod->sendKeyEvent(event);
467 return;
468 }
469 }
470
471#if QT_WAYLAND_TEXT_INPUT_V4_WIP
472 if (keyboardFocus()->client()->textInputProtocols().testFlag(QWaylandClient::TextInputProtocol::TextInputV4)) {
473 QWaylandTextInputV4 *textInputV4 = QWaylandTextInputV4::findIn(this);
474 if (textInputV4 && !event->text().isEmpty()) {
475 // it will just commit the text for text-input-unstable-v4-wip when keyPress
476 if (event->type() == QEvent::KeyPress)
477 textInputV4->sendKeyEvent(event);
478 return;
479 }
480 }
481#endif // QT_WAYLAND_TEXT_INPUT_V4_WIP
482 }
483#endif
484
485 QtWayland::QtKeyExtensionGlobal *ext = QtWayland::QtKeyExtensionGlobal::findIn(container: d->compositor);
486 if (ext && ext->postQtKeyEvent(event, surface: keyboardFocus()))
487 return;
488
489 if (!d->keyboard.isNull() && !event->isAutoRepeat()) {
490
491 uint scanCode = event->nativeScanCode();
492 if (scanCode == 0)
493 scanCode = d->keyboard->keyToScanCode(event->key());
494
495 if (scanCode == 0) {
496 qWarning() << "Can't send Wayland key event: Unable to get a valid scan code";
497 return;
498 }
499
500 if (event->type() == QEvent::KeyPress) {
501 QWaylandKeyboardPrivate::get(keyboard: d->keyboard.data())->checkAndRepairModifierState(event);
502 d->keyboard->sendKeyPressEvent(scanCode);
503 } else if (event->type() == QEvent::KeyRelease) {
504 d->keyboard->sendKeyReleaseEvent(scanCode);
505 }
506 }
507}
508
509/*!
510 * \qmlmethod void QtWayland.Compositor::WaylandSeat::sendKeyEvent(int qtKey, bool pressed)
511 * \since 5.12
512 *
513 * Sends a key press (if \a pressed is \c true) or release (if \a pressed is \c false)
514 * event of a key \a qtKey to the keyboard device.
515 */
516
517/*!
518 * Sends a key press (if \a pressed is \c true) or release (if \a pressed is \c false)
519 * event of a key \a qtKey to the keyboard device.
520 *
521 * \note This function does not support key events that require modifiers, such as \c Qt::Key_Exclam.
522 * Use \l{sendFullKeyEvent} instead.
523 *
524 * \since 5.12
525 */
526void QWaylandSeat::sendKeyEvent(int qtKey, bool pressed)
527{
528 Q_D(QWaylandSeat);
529 if (!keyboardFocus()) {
530 qWarning(msg: "Cannot send Wayland key event, no keyboard focus, fix the compositor");
531 return;
532 }
533
534 if (auto scanCode = d->keyboard->keyToScanCode(qtKey)) {
535 if (pressed)
536 d->keyboard->sendKeyPressEvent(scanCode);
537 else
538 d->keyboard->sendKeyReleaseEvent(scanCode);
539 } else {
540 qWarning() << "Can't send Wayland key event: Unable to get scan code for" << Qt::Key(qtKey);
541 }
542}
543
544/*!
545 * Returns the keyboard for this input device.
546 */
547QWaylandKeyboard *QWaylandSeat::keyboard() const
548{
549 Q_D(const QWaylandSeat);
550 return d->keyboard.data();
551}
552
553/*!
554 * Returns the current focused surface for keyboard input.
555 */
556QWaylandSurface *QWaylandSeat::keyboardFocus() const
557{
558 Q_D(const QWaylandSeat);
559 if (d->keyboard.isNull() || !d->keyboard->focus())
560 return nullptr;
561
562 return d->keyboard->focus();
563}
564
565/*!
566 * Sets the current keyboard focus to \a surface.
567 * Returns a boolean indicating if the operation
568 * was successful.
569 */
570bool QWaylandSeat::setKeyboardFocus(QWaylandSurface *surface)
571{
572 Q_D(QWaylandSeat);
573 if (surface && surface->isDestroyed())
574 return false;
575
576 QWaylandSurface *oldSurface = keyboardFocus();
577 if (surface == oldSurface)
578 return true;
579
580 d->keyboardFocus = surface;
581 if (!d->keyboard.isNull())
582 d->keyboard->setFocus(surface);
583#if QT_CONFIG(wayland_datadevice)
584 if (d->data_device)
585 d->data_device->setFocus(surface ? surface->client() : nullptr);
586#endif
587 emit keyboardFocusChanged(newFocus: surface, oldFocus: oldSurface);
588 return true;
589}
590
591
592/*!
593 * Returns the keymap object for this QWaylandSeat.
594 */
595
596QWaylandKeymap *QWaylandSeat::keymap()
597{
598 Q_D(const QWaylandSeat);
599 return d->keymap.data();
600}
601
602/*!
603 * Returns the pointer device for this QWaylandSeat.
604 */
605QWaylandPointer *QWaylandSeat::pointer() const
606{
607 Q_D(const QWaylandSeat);
608 return d->pointer.data();
609}
610
611/*!
612 * Returns the touch device for this QWaylandSeat.
613 */
614QWaylandTouch *QWaylandSeat::touch() const
615{
616 Q_D(const QWaylandSeat);
617 return d->touch.data();
618}
619
620/*!
621 * Returns the view that currently has mouse focus.
622 */
623QWaylandView *QWaylandSeat::mouseFocus() const
624{
625 Q_D(const QWaylandSeat);
626 return d->mouseFocus;
627}
628
629/*!
630 * Sets the current mouse focus to \a view.
631 */
632void QWaylandSeat::setMouseFocus(QWaylandView *view)
633{
634 Q_D(QWaylandSeat);
635 if (view == d->mouseFocus)
636 return;
637
638 QWaylandView *oldFocus = d->mouseFocus;
639 d->mouseFocus = view;
640
641 if (oldFocus)
642 disconnect(sender: oldFocus, signal: &QObject::destroyed, receiver: this, slot: &QWaylandSeat::handleMouseFocusDestroyed);
643 if (d->mouseFocus)
644 connect(sender: d->mouseFocus, signal: &QObject::destroyed, context: this, slot: &QWaylandSeat::handleMouseFocusDestroyed);
645
646 emit mouseFocusChanged(newFocus: d->mouseFocus, oldFocus);
647}
648
649/*!
650 * Returns the compositor for this QWaylandSeat.
651 */
652QWaylandCompositor *QWaylandSeat::compositor() const
653{
654 Q_D(const QWaylandSeat);
655 return d->compositor;
656}
657
658/*!
659 * Returns the drag object for this QWaylandSeat.
660 */
661#if QT_CONFIG(draganddrop)
662QWaylandDrag *QWaylandSeat::drag() const
663{
664 Q_D(const QWaylandSeat);
665 return d->drag_handle.data();
666}
667#endif
668
669/*!
670 * Returns the capability flags for this QWaylandSeat.
671 */
672QWaylandSeat::CapabilityFlags QWaylandSeat::capabilities() const
673{
674 Q_D(const QWaylandSeat);
675 return d->capabilities;
676}
677
678/*!
679 * \internal
680 */
681bool QWaylandSeat::isOwner(QInputEvent *inputEvent) const
682{
683 Q_UNUSED(inputEvent);
684 return true;
685}
686
687/*!
688 * Returns the QWaylandSeat corresponding to the \a resource. The \a resource is expected
689 * to have the type wl_seat.
690 */
691QWaylandSeat *QWaylandSeat::fromSeatResource(struct ::wl_resource *resource)
692{
693 if (auto p = QtWayland::fromResource<QWaylandSeatPrivate *>(resource))
694 return p->q_func();
695 return nullptr;
696}
697
698/*!
699 * \fn void QWaylandSeat::mouseFocusChanged(QWaylandView *newFocus, QWaylandView *oldFocus)
700 *
701 * This signal is emitted when the mouse focus has changed from \a oldFocus to \a newFocus.
702 */
703
704void QWaylandSeat::handleMouseFocusDestroyed()
705{
706 // This is triggered when the QWaylandView is destroyed, NOT the surface.
707 // ... so this is for the rare case when the view that currently holds the mouse focus is
708 // destroyed before its surface
709 Q_D(QWaylandSeat);
710 d->mouseFocus = nullptr;
711 QWaylandView *oldFocus = nullptr; // we have to send nullptr because the old focus is already destroyed at this point
712 emit mouseFocusChanged(newFocus: d->mouseFocus, oldFocus);
713}
714
715
716/*! \qmlsignal void QtWayland.Compositor::WaylandSeat::keyboardFocusChanged(QWaylandSurface newFocus, QWaylandSurface oldFocus)
717 *
718 * This signal is emitted when setKeyboardFocus() is called or when a WaylandQuickItem has focus
719 * and the user starts pressing keys.
720 *
721 * \a newFocus has the surface that received keyboard focus; or \c nullptr if no surface has
722 * focus.
723 * \a oldFocus has the surface that lost keyboard focus; or \c nullptr if no surface had focus.
724 */
725
726/*!
727 * \fn void QWaylandSeat::keyboardFocusChanged(QWaylandSurface *newFocus, QWaylandSurface *oldFocus)
728 *
729 * This signal is emitted when setKeyboardFocus() is called.
730 *
731 * \a newFocus has the surface that received keyboard focus; or \c nullptr if no surface has
732 * focus.
733 * \a oldFocus has the surface that lost keyboard focus; or \c nullptr if no surface had focus.
734 */
735
736/*! \qmlsignal void QtWayland.Compositor::WaylandSeat::cursorSurfaceRequest(QWaylandSurface surface, int hotspotX, int hotspotY)
737 *
738 * This signal is emitted when the client has requested for a specific \a surface to be the mouse
739 * cursor. For example, when the user hovers over a particular surface, and you want the cursor
740 * to change into a resize arrow.
741 *
742 * Both \a hotspotX and \a hotspotY are offsets from the top-left of a pointer surface, where a
743 * click should happen. For example, if the requested cursor surface is an arrow, the parameters
744 * indicate where the arrow's tip is, on that surface.
745 */
746
747
748/*!
749 * \fn void QWaylandSeat::cursorSurfaceRequest(QWaylandSurface *surface, int hotspotX, int hotspotY)
750 *
751 * This signal is emitted when the client has requested for a specific \a surface to be the mouse
752 * cursor. For example, when the user hovers over a particular surface, and you want the cursor
753 * to change into a resize arrow.
754 *
755 * Both \a hotspotX and \a hotspotY are offsets from the top-left of a pointer surface, where a
756 * click should happen. For example, if the requested cursor surface is an arrow, the parameters
757 * indicate where the arrow's tip is, on that surface.
758 */
759
760/*!
761 * \property QWaylandSeat::drag
762 *
763 * This property holds the drag and drop operations and sends signals when they start and end.
764 * The property stores details like what image should be under the mouse cursor when the user
765 * drags it.
766 */
767
768/*!
769 * \property QWaylandSeat::keymap
770 * This property holds the keymap object.
771 *
772 * A keymap provides a way to translate actual key scan codes into a meaningful value.
773 * For example, if you use a keymap with a Norwegian layout, the key to the right of
774 * the letter L produces an Ø.
775 *
776 * Keymaps can also be used to customize key functions, such as to specify whether
777 * Control and CAPS lock should be swapped, and so on.
778 */
779
780QT_END_NAMESPACE
781
782#include "moc_qwaylandseat.cpp"
783

source code of qtwayland/src/compositor/compositor_api/qwaylandseat.cpp