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