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