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

Provided by KDAB

Privacy Policy
Learn to use CMake with our Intro Training
Find out more

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