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