KWin
Loading...
Searching...
No Matches
seat.cpp
Go to the documentation of this file.
1/*
2 SPDX-FileCopyrightText: 2014 Martin Gräßlin <mgraesslin@kde.org>
3 SPDX-FileCopyrightText: 2020 David Edmundson <davidedmundson@kde.org>
4 SPDX-FileCopyrightText: 2021 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
5
6 SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
7*/
8#include "seat.h"
12#include "datadevice.h"
13#include "datadevice_p.h"
14#include "datasource.h"
15#include "display.h"
16#include "display_p.h"
17#include "keyboard.h"
18#include "keyboard_p.h"
19#include "pointer.h"
20#include "pointer_p.h"
26#include "seat_p.h"
27#include "surface.h"
28#include "textinput_v1_p.h"
29#include "textinput_v2_p.h"
30#include "textinput_v3_p.h"
31#include "touch_p.h"
32#include "utils/common.h"
33#include "utils/resource.h"
34#include "xdgtopleveldrag_v1.h"
35
36#include <linux/input.h>
37
38#include <functional>
39
40namespace KWin
41{
42static const int s_version = 9;
43
45{
46 return seat->d.get();
47}
48
50 : QtWaylandServer::wl_seat(*display, s_version)
51 , q(q)
52 , display(display)
53{
57 pointer.reset(new PointerInterface(q));
58 keyboard.reset(new KeyboardInterface(q));
59 touch.reset(new TouchInterface(q));
60}
61
63{
64 send_capabilities(resource->handle, capabilities);
65
66 if (resource->version() >= WL_SEAT_NAME_SINCE_VERSION) {
67 send_name(resource->handle, name);
68 }
69}
70
71void SeatInterfacePrivate::seat_get_pointer(Resource *resource, uint32_t id)
72{
74 pointerPrivate->add(resource->client(), id, resource->version());
75}
76
77void SeatInterfacePrivate::seat_get_keyboard(Resource *resource, uint32_t id)
78{
80 keyboardPrivate->add(resource->client(), id, resource->version());
81}
82
83void SeatInterfacePrivate::seat_get_touch(Resource *resource, uint32_t id)
84{
86 touchPrivate->add(resource->client(), id, resource->version());
87}
88
89void SeatInterfacePrivate::seat_release(Resource *resource)
90{
91 wl_resource_destroy(resource->handle);
92}
93
94SeatInterface::SeatInterface(Display *display, QObject *parent)
95 : QObject(parent)
96 , d(new SeatInterfacePrivate(this, display))
97{
98 DisplayPrivate *displayPrivate = DisplayPrivate::get(d->display);
99 displayPrivate->seats.append(this);
100}
101
103{
104 if (d->display) {
105 DisplayPrivate *displayPrivate = DisplayPrivate::get(d->display);
106 displayPrivate->seats.removeOne(this);
107 }
108}
109
110void SeatInterfacePrivate::updatePointerButtonSerial(quint32 button, quint32 serial)
111{
112 auto it = globalPointer.buttonSerials.find(button);
113 if (it == globalPointer.buttonSerials.end()) {
114 globalPointer.buttonSerials.insert(button, serial);
115 return;
116 }
117 it.value() = serial;
118}
119
121{
122 auto it = globalPointer.buttonStates.find(button);
123 if (it == globalPointer.buttonStates.end()) {
124 globalPointer.buttonStates.insert(button, state);
125 return;
126 }
127 it.value() = state;
128}
129
130QList<DataDeviceInterface *> SeatInterfacePrivate::dataDevicesForSurface(SurfaceInterface *surface) const
131{
132 if (!surface) {
133 return {};
134 }
135 QList<DataDeviceInterface *> primarySelectionDevices;
136 for (auto it = dataDevices.constBegin(); it != dataDevices.constEnd(); ++it) {
137 if ((*it)->client() == *surface->client()) {
139 }
140 }
142}
143
145{
146 Q_ASSERT(dataDevice->seat() == q);
147 dataDevices << dataDevice;
148 auto dataDeviceCleanup = [this, dataDevice] {
149 dataDevices.removeOne(dataDevice);
150 globalKeyboard.focus.selections.removeOne(dataDevice);
151 };
152 QObject::connect(dataDevice, &QObject::destroyed, q, dataDeviceCleanup);
153 QObject::connect(dataDevice, &DataDeviceInterface::selectionChanged, q, [this, dataDevice] {
154 updateSelection(dataDevice);
155 });
156 QObject::connect(dataDevice,
158 q,
159 [this](AbstractDataSource *source, SurfaceInterface *origin, quint32 serial, DragAndDropIcon *dragIcon) {
160 q->startDrag(source, origin, serial, dragIcon);
161 });
162 // is the new DataDevice for the current keyoard focus?
164 // same client?
165 if (*globalKeyboard.focus.surface->client() == dataDevice->client()) {
166 globalKeyboard.focus.selections.append(dataDevice);
167 if (currentSelection) {
168 dataDevice->sendSelection(currentSelection);
169 }
170 }
171 }
172}
173
175{
176 auto list = d->dataDevicesForSurface(surface);
177 if (list.isEmpty()) {
178 return nullptr;
179 };
180 return list.first();
181}
182
184{
185 if (d->drag.mode != SeatInterfacePrivate::Drag::Mode::None) {
186 // cancel the drag, don't drop. serial does not matter
187 d->cancelDrag();
188 }
189}
190
192{
193 Q_ASSERT(dataDevice->seat() == q);
194 dataControlDevices << dataDevice;
195 auto dataDeviceCleanup = [this, dataDevice] {
196 dataControlDevices.removeOne(dataDevice);
197 };
198 QObject::connect(dataDevice, &QObject::destroyed, q, dataDeviceCleanup);
199
200 QObject::connect(dataDevice, &DataControlDeviceV1Interface::selectionChanged, q, [this, dataDevice] {
201 // Special klipper workaround to avoid a race
202 // If the mimetype x-kde-onlyReplaceEmpty is set, and we've had another update in the meantime, do nothing
203 // but resend selection to mimic normal event flow upon cancel and not confuse the client
204 // See https://github.com/swaywm/wlr-protocols/issues/92
205 if (dataDevice->selection() && dataDevice->selection()->mimeTypes().contains(QLatin1String("application/x-kde-onlyReplaceEmpty")) && currentSelection) {
206 dataDevice->selection()->cancel();
207 dataDevice->sendSelection(currentSelection);
208 return;
209 }
210 q->setSelection(dataDevice->selection());
211 });
212
213 QObject::connect(dataDevice, &DataControlDeviceV1Interface::primarySelectionChanged, q, [this, dataDevice] {
214 // Special klipper workaround to avoid a race
215 // If the mimetype x-kde-onlyReplaceEmpty is set, and we've had another update in the meantime, do nothing
216 // but resend selection to mimic normal event flow upon cancel and not confuse the client
217 // See https://github.com/swaywm/wlr-protocols/issues/92
218 if (dataDevice->primarySelection() && dataDevice->primarySelection()->mimeTypes().contains(QLatin1String("application/x-kde-onlyReplaceEmpty"))
220 dataDevice->primarySelection()->cancel();
222 return;
223 }
224 q->setPrimarySelection(dataDevice->primarySelection());
225 });
226
227 dataDevice->sendSelection(currentSelection);
229}
230
232{
233 Q_ASSERT(primarySelectionDevice->seat() == q);
234
235 primarySelectionDevices << primarySelectionDevice;
236 auto dataDeviceCleanup = [this, primarySelectionDevice] {
237 primarySelectionDevices.removeOne(primarySelectionDevice);
238 globalKeyboard.focus.primarySelections.removeOne(primarySelectionDevice);
239 };
240 QObject::connect(primarySelectionDevice, &QObject::destroyed, q, dataDeviceCleanup);
241 QObject::connect(primarySelectionDevice, &PrimarySelectionDeviceV1Interface::selectionChanged, q, [this, primarySelectionDevice] {
242 updatePrimarySelection(primarySelectionDevice);
243 });
244 // is the new DataDevice for the current keyoard focus?
246 // same client?
247 if (*globalKeyboard.focus.surface->client() == primarySelectionDevice->client()) {
248 globalKeyboard.focus.primarySelections.append(primarySelectionDevice);
250 primarySelectionDevice->sendSelection(currentPrimarySelection);
251 }
252 }
253 }
254}
255
257{
258 if (drag.target) {
259 drag.target->updateDragTarget(nullptr, 0);
260 drag.target = nullptr;
261 }
262 QObject::disconnect(drag.dragSourceDestroyConnection);
263 if (drag.source) {
265 }
266 drag = Drag();
267 Q_EMIT q->dragSurfaceChanged();
268 Q_EMIT q->dragEnded();
269}
270
272{
274 return false;
275 }
276 const bool targetHasDataDevice = !dataDevicesForSurface(surface).isEmpty();
277 return targetHasDataDevice;
278}
279
281{
282 QObject::disconnect(drag.dragSourceDestroyConnection);
283
284 AbstractDropHandler *dragTargetDevice = drag.target.data();
285 AbstractDataSource *dragSource = drag.source;
286
287 if (dragSource) {
288 // TODO: Also check the current drag-and-drop action.
289 if (dragTargetDevice && dragSource->isAccepted()) {
290 Q_EMIT q->dragDropped();
291 dragTargetDevice->drop();
292 dragSource->dropPerformed();
293 } else {
294 dragSource->dropPerformed();
295 dragSource->dndCancelled();
296 }
297 }
298
299 if (dragTargetDevice) {
300 dragTargetDevice->updateDragTarget(nullptr, 0);
301 }
302
303 drag = Drag();
304 Q_EMIT q->dragSurfaceChanged();
305 Q_EMIT q->dragEnded();
306}
307
308void SeatInterfacePrivate::updateSelection(DataDeviceInterface *dataDevice)
309{
310 DataSourceInterface *selection = dataDevice->selection();
311 // if the update is from the focussed window we should inform the active client
312 if (!(globalKeyboard.focus.surface && (*globalKeyboard.focus.surface->client() == dataDevice->client()))) {
313 if (selection) {
314 selection->cancel();
315 }
316 return;
317 }
318 q->setSelection(selection);
319}
320
321void SeatInterfacePrivate::updatePrimarySelection(PrimarySelectionDeviceV1Interface *primarySelectionDevice)
322{
323 PrimarySelectionSourceV1Interface *selection = primarySelectionDevice->selection();
324 // if the update is from the focussed window we should inform the active client
325 if (!(globalKeyboard.focus.surface && (*globalKeyboard.focus.surface->client() == primarySelectionDevice->client()))) {
326 if (selection) {
327 selection->cancel();
328 }
329 return;
330 }
331 q->setPrimarySelection(selection);
332}
333
335{
336 const auto seatResources = resourceMap();
337 for (SeatInterfacePrivate::Resource *resource : seatResources) {
338 send_capabilities(resource->handle, capabilities);
339 }
340}
341
343{
344 if (hasKeyboard() == has) {
345 return;
346 }
347 if (has) {
348 d->capabilities |= SeatInterfacePrivate::capability_keyboard;
349 } else {
350 d->capabilities &= ~SeatInterfacePrivate::capability_keyboard;
351 }
352
353 d->sendCapabilities();
354 Q_EMIT hasKeyboardChanged(has);
355}
356
358{
359 if (hasPointer() == has) {
360 return;
361 }
362 if (has) {
363 d->capabilities |= SeatInterfacePrivate::capability_pointer;
364 } else {
365 d->capabilities &= ~SeatInterfacePrivate::capability_pointer;
366 }
367
368 d->sendCapabilities();
369 Q_EMIT hasPointerChanged(has);
370}
371
373{
374 if (hasTouch() == has) {
375 return;
376 }
377 if (has) {
378 d->capabilities |= SeatInterfacePrivate::capability_touch;
379 } else {
380 d->capabilities &= ~SeatInterfacePrivate::capability_touch;
381 }
382
383 d->sendCapabilities();
384 Q_EMIT hasTouchChanged(has);
385}
386
387void SeatInterface::setName(const QString &name)
388{
389 if (d->name == name) {
390 return;
391 }
392 d->name = name;
393
394 const auto seatResources = d->resourceMap();
395 for (SeatInterfacePrivate::Resource *resource : seatResources) {
396 if (resource->version() >= WL_SEAT_NAME_SINCE_VERSION) {
397 d->send_name(resource->handle, d->name);
398 }
399 }
400
401 Q_EMIT nameChanged(d->name);
402}
403
404QString SeatInterface::name() const
405{
406 return d->name;
407}
408
410{
411 return d->capabilities & SeatInterfacePrivate::capability_pointer;
412}
413
415{
416 return d->capabilities & SeatInterfacePrivate::capability_keyboard;
417}
418
420{
421 return d->capabilities & SeatInterfacePrivate::capability_touch;
422}
423
425{
426 return d->display;
427}
428
430{
431 if (SeatInterfacePrivate *seatPrivate = resource_cast<SeatInterfacePrivate *>(native)) {
432 return seatPrivate->q;
433 }
434 return nullptr;
435}
436
438{
439 return d->globalPointer.pos;
440}
441
443{
444 if (!d->pointer) {
445 return;
446 }
447 if (d->globalPointer.pos == pos) {
448 return;
449 }
450 d->globalPointer.pos = pos;
451 Q_EMIT pointerPosChanged(pos);
452
453 SurfaceInterface *focusedSurface = focusedPointerSurface();
454 if (!focusedSurface) {
455 return;
456 }
457 if (d->dragInhibitsPointer(focusedSurface)) {
458 return;
459 }
460 if (focusedSurface->lockedPointer() && focusedSurface->lockedPointer()->isLocked()) {
461 return;
462 }
463
464 QPointF localPosition = focusedPointerSurfaceTransformation().map(pos);
465 SurfaceInterface *effectiveFocusedSurface = focusedSurface->inputSurfaceAt(localPosition);
466 if (!effectiveFocusedSurface) {
467 effectiveFocusedSurface = focusedSurface;
468 }
469 if (focusedSurface != effectiveFocusedSurface) {
470 localPosition = focusedSurface->mapToChild(effectiveFocusedSurface, localPosition);
471 }
472
473 if (d->pointer->focusedSurface() != effectiveFocusedSurface) {
474 d->pointer->sendEnter(effectiveFocusedSurface, localPosition, display()->nextSerial());
475 if (d->keyboard) {
476 d->keyboard->setModifierFocusSurface(effectiveFocusedSurface);
477 }
478 }
479
480 d->pointer->sendMotion(localPosition);
481}
482
483std::chrono::milliseconds SeatInterface::timestamp() const
484{
485 return d->timestamp;
486}
487
488void SeatInterface::setTimestamp(std::chrono::microseconds time)
489{
490 const auto milliseconds = std::chrono::duration_cast<std::chrono::milliseconds>(time);
491 if (d->timestamp == milliseconds) {
492 return;
493 }
494 d->timestamp = milliseconds;
495 Q_EMIT timestampChanged();
496}
497
499 SurfaceInterface *surface,
500 const QPointF &globalPosition,
501 const QMatrix4x4 &inputTransformation)
502{
503 if (surface == d->drag.surface) {
504 // no change
505 return;
506 }
507 const quint32 serial = d->display->nextSerial();
508 if (d->drag.target) {
509 d->drag.target->updateDragTarget(nullptr, serial);
510 }
511
512 // TODO: technically we can have mulitple data devices
513 // and we should send the drag to all of them, but that seems overly complicated
514 // in practice so far the only case for mulitple data devices is for clipboard overriding
515 d->drag.target = dropTarget;
516
517 if (d->drag.mode == SeatInterfacePrivate::Drag::Mode::Pointer) {
518 notifyPointerMotion(globalPosition);
520 } else if (d->drag.mode == SeatInterfacePrivate::Drag::Mode::Touch && d->globalTouch.focus.firstTouchPos != globalPosition) {
521 notifyTouchMotion(d->globalTouch.ids.first(), globalPosition);
522 }
523
524 if (d->drag.target) {
525 QMatrix4x4 surfaceInputTransformation = inputTransformation;
526 surfaceInputTransformation.scale(surface->scaleOverride());
527 d->drag.surface = surface;
528 d->drag.transformation = surfaceInputTransformation;
529 if (d->dragInhibitsPointer(surface)) {
531 }
532 d->drag.target->updateDragTarget(surface, serial);
533 } else {
534 d->drag.surface = nullptr;
535 }
536 Q_EMIT dragSurfaceChanged();
537 return;
538}
539
540void SeatInterface::setDragTarget(AbstractDropHandler *target, SurfaceInterface *surface, const QMatrix4x4 &inputTransformation)
541{
542 if (d->drag.mode == SeatInterfacePrivate::Drag::Mode::Pointer) {
543 setDragTarget(target, surface, pointerPos(), inputTransformation);
544 } else {
545 Q_ASSERT(d->drag.mode == SeatInterfacePrivate::Drag::Mode::Touch);
546 setDragTarget(target, surface, d->globalTouch.focus.firstTouchPos, inputTransformation);
547 }
548}
549
551{
552 return d->globalPointer.focus.surface;
553}
554
555void SeatInterface::notifyPointerEnter(SurfaceInterface *surface, const QPointF &position, const QPointF &surfacePosition)
556{
557 QMatrix4x4 m;
558 m.translate(-surfacePosition.x(), -surfacePosition.y());
559 notifyPointerEnter(surface, position, m);
560 if (d->globalPointer.focus.surface) {
561 d->globalPointer.focus.offset = surfacePosition;
562 }
563}
564
565void SeatInterface::notifyPointerEnter(SurfaceInterface *surface, const QPointF &position, const QMatrix4x4 &transformation)
566{
567 if (!d->pointer) {
568 return;
569 }
570 if (d->dragInhibitsPointer(surface)) {
571 // ignore
572 return;
573 }
574
575 const quint32 serial = d->display->nextSerial();
576
577 if (d->globalPointer.focus.surface) {
578 disconnect(d->globalPointer.focus.destroyConnection);
579 }
580 d->globalPointer.focus = SeatInterfacePrivate::Pointer::Focus();
581 d->globalPointer.focus.surface = surface;
582 d->globalPointer.focus.destroyConnection = connect(surface, &QObject::destroyed, this, [this] {
583 d->globalPointer.focus = SeatInterfacePrivate::Pointer::Focus();
584 });
585 d->globalPointer.focus.serial = serial;
586 d->globalPointer.focus.transformation = transformation;
587 d->globalPointer.focus.offset = QPointF();
588
589 d->globalPointer.pos = position;
590 QPointF localPosition = focusedPointerSurfaceTransformation().map(position);
591 SurfaceInterface *effectiveFocusedSurface = surface->inputSurfaceAt(localPosition);
592 if (!effectiveFocusedSurface) {
593 effectiveFocusedSurface = surface;
594 }
595 if (surface != effectiveFocusedSurface) {
596 localPosition = surface->mapToChild(effectiveFocusedSurface, localPosition);
597 }
598 d->pointer->sendEnter(effectiveFocusedSurface, localPosition, serial);
599 if (d->keyboard) {
600 d->keyboard->setModifierFocusSurface(effectiveFocusedSurface);
601 }
602}
603
605{
606 if (!d->pointer) {
607 return;
608 }
609
610 if (d->globalPointer.focus.surface) {
611 disconnect(d->globalPointer.focus.destroyConnection);
612 }
613 d->globalPointer.focus = SeatInterfacePrivate::Pointer::Focus();
614
615 const quint32 serial = d->display->nextSerial();
616 d->pointer->sendLeave(serial);
617 if (d->keyboard) {
618 d->keyboard->setModifierFocusSurface(nullptr);
619 }
620}
621
622void SeatInterface::setFocusedPointerSurfacePosition(const QPointF &surfacePosition)
623{
624 if (d->globalPointer.focus.surface) {
625 d->globalPointer.focus.offset = surfacePosition;
626 d->globalPointer.focus.transformation = QMatrix4x4();
627 d->globalPointer.focus.transformation.translate(-surfacePosition.x(), -surfacePosition.y());
628 }
629}
630
632{
633 return d->globalPointer.focus.offset;
634}
635
636void SeatInterface::setFocusedPointerSurfaceTransformation(const QMatrix4x4 &transformation)
637{
638 if (d->globalPointer.focus.surface) {
639 d->globalPointer.focus.transformation = transformation;
640 }
641}
642
644{
645 return d->globalPointer.focus.transformation;
646}
647
649{
650 return d->pointer.get();
651}
652
653static quint32 qtToWaylandButton(Qt::MouseButton button)
654{
655 static const QHash<Qt::MouseButton, quint32> s_buttons({
656 {Qt::LeftButton, BTN_LEFT},
657 {Qt::RightButton, BTN_RIGHT},
658 {Qt::MiddleButton, BTN_MIDDLE},
659 {Qt::ExtraButton1, BTN_BACK}, // note: QtWayland maps BTN_SIDE
660 {Qt::ExtraButton2, BTN_FORWARD}, // note: QtWayland maps BTN_EXTRA
661 {Qt::ExtraButton3, BTN_TASK}, // note: QtWayland maps BTN_FORWARD
662 {Qt::ExtraButton4, BTN_EXTRA}, // note: QtWayland maps BTN_BACK
663 {Qt::ExtraButton5, BTN_SIDE}, // note: QtWayland maps BTN_TASK
664 {Qt::ExtraButton6, BTN_TASK + 1},
665 {Qt::ExtraButton7, BTN_TASK + 2},
666 {Qt::ExtraButton8, BTN_TASK + 3},
667 {Qt::ExtraButton9, BTN_TASK + 4},
668 {Qt::ExtraButton10, BTN_TASK + 5},
669 {Qt::ExtraButton11, BTN_TASK + 6},
670 {Qt::ExtraButton12, BTN_TASK + 7},
671 {Qt::ExtraButton13, BTN_TASK + 8}
672 // further mapping not possible, 0x120 is BTN_JOYSTICK
673 });
674 return s_buttons.value(button, 0);
675}
676
677bool SeatInterface::isPointerButtonPressed(Qt::MouseButton button) const
678{
679 return isPointerButtonPressed(qtToWaylandButton(button));
680}
681
683{
684 auto it = d->globalPointer.buttonStates.constFind(button);
685 if (it == d->globalPointer.buttonStates.constEnd()) {
686 return false;
687 }
689}
690
691void SeatInterface::notifyPointerAxis(Qt::Orientation orientation, qreal delta, qint32 deltaV120, PointerAxisSource source, PointerAxisRelativeDirection direction)
692{
693 if (!d->pointer) {
694 return;
695 }
696 if (d->drag.mode == SeatInterfacePrivate::Drag::Mode::Pointer) {
697 // ignore
698 return;
699 }
700 d->pointer->sendAxis(orientation, delta, deltaV120, source, direction);
701}
702
704{
705 const quint32 nativeButton = qtToWaylandButton(button);
706 if (nativeButton == 0) {
707 return;
708 }
709 notifyPointerButton(nativeButton, state);
710}
711
713{
714 if (!d->pointer) {
715 return;
716 }
717 const quint32 serial = d->display->nextSerial();
718
719 if (state == PointerButtonState::Pressed) {
720 d->updatePointerButtonSerial(button, serial);
721 d->updatePointerButtonState(button, SeatInterfacePrivate::Pointer::State::Pressed);
722 if (d->drag.mode == SeatInterfacePrivate::Drag::Mode::Pointer) {
723 // ignore
724 return;
725 }
726 } else {
727 const quint32 currentButtonSerial = pointerButtonSerial(button);
728 d->updatePointerButtonSerial(button, serial);
729 d->updatePointerButtonState(button, SeatInterfacePrivate::Pointer::State::Released);
730 if (d->drag.mode == SeatInterfacePrivate::Drag::Mode::Pointer) {
731 if (d->drag.dragImplicitGrabSerial != currentButtonSerial) {
732 // not our drag button - ignore
733 return;
734 }
735 d->pointer->sendButton(button, state, serial);
736 d->endDrag();
737 return;
738 }
739 }
740
741 d->pointer->sendButton(button, state, serial);
742}
743
745{
746 if (!d->pointer) {
747 return;
748 }
749 d->pointer->sendFrame();
750}
751
752quint32 SeatInterface::pointerButtonSerial(Qt::MouseButton button) const
753{
754 return pointerButtonSerial(qtToWaylandButton(button));
755}
756
757quint32 SeatInterface::pointerButtonSerial(quint32 button) const
758{
759 auto it = d->globalPointer.buttonSerials.constFind(button);
760 if (it == d->globalPointer.buttonSerials.constEnd()) {
761 return 0;
762 }
763 return it.value();
764}
765
766void SeatInterface::relativePointerMotion(const QPointF &delta, const QPointF &deltaNonAccelerated, std::chrono::microseconds time)
767{
768 if (!d->pointer) {
769 return;
770 }
771
772 auto relativePointer = RelativePointerV1Interface::get(pointer());
773 if (relativePointer) {
774 relativePointer->sendRelativeMotion(delta, deltaNonAccelerated, time);
775 }
776}
777
779{
780 if (!d->pointer) {
781 return;
782 }
783
784 auto swipeGesture = PointerSwipeGestureV1Interface::get(pointer());
785 if (swipeGesture) {
786 swipeGesture->sendBegin(d->display->nextSerial(), fingerCount);
787 }
788}
789
791{
792 if (!d->pointer) {
793 return;
794 }
795
796 auto swipeGesture = PointerSwipeGestureV1Interface::get(pointer());
797 if (swipeGesture) {
798 swipeGesture->sendUpdate(delta);
799 }
800}
801
803{
804 if (!d->pointer) {
805 return;
806 }
807
808 auto swipeGesture = PointerSwipeGestureV1Interface::get(pointer());
809 if (swipeGesture) {
810 swipeGesture->sendEnd(d->display->nextSerial());
811 }
812}
813
815{
816 if (!d->pointer) {
817 return;
818 }
819
820 auto swipeGesture = PointerSwipeGestureV1Interface::get(pointer());
821 if (swipeGesture) {
822 swipeGesture->sendCancel(d->display->nextSerial());
823 }
824}
825
827{
828 if (!d->pointer) {
829 return;
830 }
831
832 auto pinchGesture = PointerPinchGestureV1Interface::get(pointer());
833 if (pinchGesture) {
834 pinchGesture->sendBegin(d->display->nextSerial(), fingerCount);
835 }
836}
837
838void SeatInterface::updatePointerPinchGesture(const QPointF &delta, qreal scale, qreal rotation)
839{
840 if (!d->pointer) {
841 return;
842 }
843
844 auto pinchGesture = PointerPinchGestureV1Interface::get(pointer());
845 if (pinchGesture) {
846 pinchGesture->sendUpdate(delta, scale, rotation);
847 }
848}
849
851{
852 if (!d->pointer) {
853 return;
854 }
855
856 auto pinchGesture = PointerPinchGestureV1Interface::get(pointer());
857 if (pinchGesture) {
858 pinchGesture->sendEnd(d->display->nextSerial());
859 }
860}
861
863{
864 if (!d->pointer) {
865 return;
866 }
867
868 auto pinchGesture = PointerPinchGestureV1Interface::get(pointer());
869 if (pinchGesture) {
870 pinchGesture->sendCancel(d->display->nextSerial());
871 }
872}
873
875{
876 if (!d->pointer) {
877 return;
878 }
879
880 auto holdGesture = PointerHoldGestureV1Interface::get(pointer());
881 if (holdGesture) {
882 holdGesture->sendBegin(d->display->nextSerial(), fingerCount);
883 }
884}
885
887{
888 if (!d->pointer) {
889 return;
890 }
891
892 auto holdGesture = PointerHoldGestureV1Interface::get(pointer());
893 if (holdGesture) {
894 holdGesture->sendEnd(d->display->nextSerial());
895 }
896}
897
899{
900 if (!d->pointer) {
901 return;
902 }
903
904 auto holdGesture = PointerHoldGestureV1Interface::get(pointer());
905 if (holdGesture) {
906 holdGesture->sendCancel(d->display->nextSerial());
907 }
908}
909
911{
912 return d->globalKeyboard.focus.surface;
913}
914
916{
917 if (!d->keyboard) {
918 return;
919 }
920
922 const quint32 serial = d->display->nextSerial();
923
924 if (d->globalKeyboard.focus.surface) {
925 disconnect(d->globalKeyboard.focus.destroyConnection);
926 }
927 d->globalKeyboard.focus = SeatInterfacePrivate::Keyboard::Focus();
928 d->globalKeyboard.focus.surface = surface;
929
930 d->keyboard->setFocusedSurface(surface, serial);
931
932 if (d->globalKeyboard.focus.surface) {
933 d->globalKeyboard.focus.destroyConnection = connect(surface, &QObject::destroyed, this, [this]() {
934 d->globalKeyboard.focus = SeatInterfacePrivate::Keyboard::Focus();
935 });
936 d->globalKeyboard.focus.serial = serial;
937 // selection?
938 const QList<DataDeviceInterface *> dataDevices = d->dataDevicesForSurface(surface);
939 d->globalKeyboard.focus.selections = dataDevices;
940 for (auto dataDevice : dataDevices) {
941 dataDevice->sendSelection(d->currentSelection);
942 }
943 // primary selection
944 QList<PrimarySelectionDeviceV1Interface *> primarySelectionDevices;
945 for (auto it = d->primarySelectionDevices.constBegin(); it != d->primarySelectionDevices.constEnd(); ++it) {
946 if ((*it)->client() == *surface->client()) {
947 primarySelectionDevices << *it;
948 }
949 }
950
951 d->globalKeyboard.focus.primarySelections = primarySelectionDevices;
952 for (auto primaryDataDevice : primarySelectionDevices) {
953 primaryDataDevice->sendSelection(d->currentPrimarySelection);
954 }
955 }
956
957 // focused text input surface follows keyboard
958 if (hasKeyboard()) {
960 }
961}
962
964{
965 return d->keyboard.get();
966}
967
969{
970 if (!d->keyboard) {
971 return;
972 }
973 d->keyboard->sendKey(keyCode, state);
974}
975
976void SeatInterface::notifyKeyboardModifiers(quint32 depressed, quint32 latched, quint32 locked, quint32 group)
977{
978 if (!d->keyboard) {
979 return;
980 }
981 d->keyboard->sendModifiers(depressed, latched, locked, group);
982}
983
985{
986 if (!d->touch) {
987 return;
988 }
989 d->touch->sendCancel();
990
991 if (d->drag.mode == SeatInterfacePrivate::Drag::Mode::Touch) {
992 // cancel the drag, don't drop. serial does not matter
993 d->cancelDrag();
994 }
995 d->globalTouch.ids.clear();
996}
997
999{
1000 return d->globalTouch.focus.surface;
1001}
1002
1004{
1005 return d->globalTouch.focus.offset;
1006}
1007
1009{
1010 return !d->globalTouch.ids.isEmpty();
1011}
1012
1014{
1015 return d->touch.get();
1016}
1017
1019{
1020 return d->globalTouch.focus.firstTouchPos;
1021}
1022
1023void SeatInterface::setFocusedTouchSurface(SurfaceInterface *surface, const QPointF &surfacePosition)
1024{
1025 if (!d->touch) {
1026 return;
1027 }
1028 if (isTouchSequence()) {
1029 // changing surface not allowed during a touch sequence
1030 return;
1031 }
1032 if (isDragTouch()) {
1033 return;
1034 }
1035 if (d->globalTouch.focus.surface) {
1036 disconnect(d->globalTouch.focus.destroyConnection);
1037 }
1038 d->globalTouch.focus = SeatInterfacePrivate::Touch::Focus();
1039 d->globalTouch.focus.surface = surface;
1040 setFocusedTouchSurfacePosition(surfacePosition);
1041
1042 if (d->globalTouch.focus.surface) {
1043 d->globalTouch.focus.destroyConnection = connect(surface, &QObject::destroyed, this, [this]() {
1044 if (isTouchSequence()) {
1045 // Surface destroyed during touch sequence - send a cancel
1046 d->touch->sendCancel();
1047 }
1048 d->globalTouch.focus = SeatInterfacePrivate::Touch::Focus();
1049 });
1050 }
1051}
1052
1053void SeatInterface::setFocusedTouchSurfacePosition(const QPointF &surfacePosition)
1054{
1055 d->globalTouch.focus.offset = surfacePosition;
1056 d->globalTouch.focus.transformation = QMatrix4x4();
1057 d->globalTouch.focus.transformation.translate(-surfacePosition.x(), -surfacePosition.y());
1058}
1059
1060void SeatInterface::notifyTouchDown(qint32 id, const QPointF &globalPosition)
1061{
1062 if (!d->touch || !focusedTouchSurface()) {
1063 return;
1064 }
1065 const qint32 serial = display()->nextSerial();
1066 auto pos = globalPosition - d->globalTouch.focus.offset;
1067
1068 SurfaceInterface *effectiveFocusedSurface = focusedTouchSurface()->inputSurfaceAt(pos);
1069 if (effectiveFocusedSurface && effectiveFocusedSurface != focusedTouchSurface()) {
1070 pos = focusedTouchSurface()->mapToChild(effectiveFocusedSurface, pos);
1071 } else if (!effectiveFocusedSurface) {
1072 effectiveFocusedSurface = focusedTouchSurface();
1073 }
1074 d->touch->sendDown(id, serial, pos, effectiveFocusedSurface);
1075
1076 if (id == 0) {
1077 d->globalTouch.focus.firstTouchPos = globalPosition;
1078 }
1079
1080 if (id == 0 && hasPointer() && focusedTouchSurface()) {
1081 TouchInterfacePrivate *touchPrivate = TouchInterfacePrivate::get(d->touch.get());
1082 if (!touchPrivate->hasTouchesForClient(effectiveFocusedSurface->client())) {
1083 // If the client did not bind the touch interface fall back
1084 // to at least emulating touch through pointer events.
1085 d->pointer->sendEnter(effectiveFocusedSurface, pos, serial);
1086 d->pointer->sendMotion(pos);
1087 d->pointer->sendFrame();
1088 }
1089 }
1090
1091 d->globalTouch.ids[id] = serial;
1092}
1093
1094void SeatInterface::notifyTouchMotion(qint32 id, const QPointF &globalPosition)
1095{
1096 if (!d->touch) {
1097 return;
1098 }
1099 auto itTouch = d->globalTouch.ids.constFind(id);
1100 if (itTouch == d->globalTouch.ids.constEnd()) {
1101 // This can happen in cases where the interaction started while the device was asleep
1102 qCWarning(KWIN_CORE) << "Detected a touch move that never has been down, discarding";
1103 return;
1104 }
1105
1106 auto pos = globalPosition - d->globalTouch.focus.offset;
1107 SurfaceInterface *effectiveFocusedSurface = d->touch->focusedSurface();
1108 if (effectiveFocusedSurface && focusedTouchSurface() != effectiveFocusedSurface) {
1109 pos = focusedTouchSurface()->mapToChild(effectiveFocusedSurface, pos);
1110 }
1111
1112 if (isDragTouch()) {
1113 // handled by DataDevice
1114 } else {
1115 d->touch->sendMotion(id, pos);
1116 }
1117
1118 if (id == 0) {
1119 d->globalTouch.focus.firstTouchPos = globalPosition;
1120
1121 if (hasPointer() && focusedTouchSurface()) {
1122 TouchInterfacePrivate *touchPrivate = TouchInterfacePrivate::get(d->touch.get());
1123 if (!touchPrivate->hasTouchesForClient(focusedTouchSurface()->client())) {
1124 // Client did not bind touch, fall back to emulating with pointer events.
1125 d->pointer->sendMotion(pos);
1126 d->pointer->sendFrame();
1127 }
1128 }
1129 }
1130 Q_EMIT touchMoved(id, *itTouch, globalPosition);
1131}
1132
1134{
1135 if (!d->touch) {
1136 return;
1137 }
1138
1139 auto itTouch = d->globalTouch.ids.find(id);
1140 if (itTouch == d->globalTouch.ids.end()) {
1141 // This can happen in cases where the interaction started while the device was asleep
1142 qCWarning(KWIN_CORE) << "Detected a touch that never started, discarding";
1143 return;
1144 }
1145 const qint32 serial = d->display->nextSerial();
1146 if (d->drag.mode == SeatInterfacePrivate::Drag::Mode::Touch && d->drag.dragImplicitGrabSerial == d->globalTouch.ids.value(id)) {
1147 // the implicitly grabbing touch point has been upped
1148 d->endDrag();
1149 }
1150 d->touch->sendUp(id, serial);
1151
1152 if (id == 0 && hasPointer() && focusedTouchSurface()) {
1153 TouchInterfacePrivate *touchPrivate = TouchInterfacePrivate::get(d->touch.get());
1154 if (!touchPrivate->hasTouchesForClient(focusedTouchSurface()->client())) {
1155 // Client did not bind touch, fall back to emulating with pointer events.
1156 const quint32 serial = display()->nextSerial();
1157 d->pointer->sendButton(BTN_LEFT, PointerButtonState::Released, serial);
1158 d->pointer->sendFrame();
1159 }
1160 }
1161
1162 d->globalTouch.ids.erase(itTouch);
1163}
1164
1166{
1167 if (!d->touch) {
1168 return;
1169 }
1170 d->touch->sendFrame();
1171}
1172
1173bool SeatInterface::hasImplicitTouchGrab(quint32 serial) const
1174{
1175 if (!d->globalTouch.focus.surface) {
1176 // origin surface has been destroyed
1177 return false;
1178 }
1179 return d->globalTouch.ids.key(serial, -1) != -1;
1180}
1181
1183{
1184 return d->drag.mode != SeatInterfacePrivate::Drag::Mode::None;
1185}
1186
1188{
1189 return d->drag.mode == SeatInterfacePrivate::Drag::Mode::Pointer;
1190}
1191
1193{
1194 return d->drag.mode == SeatInterfacePrivate::Drag::Mode::Touch;
1195}
1196
1198{
1199 const auto &serials = d->globalPointer.buttonSerials;
1200 for (auto it = serials.constBegin(), end = serials.constEnd(); it != end; it++) {
1201 if (it.value() == serial) {
1202 return isPointerButtonPressed(it.key());
1203 }
1204 }
1205 return false;
1206}
1207
1209{
1210 return d->drag.transformation;
1211}
1212
1214{
1215 return d->drag.surface;
1216}
1217
1219{
1220 return d->drag.source;
1221}
1222
1224{
1225 if (auto source = qobject_cast<DataSourceInterface *>(d->drag.source)) {
1226 return source->xdgToplevelDrag();
1227 }
1228 return nullptr;
1229}
1230
1232{
1233 const quint32 serial = d->display->nextSerial();
1234
1235 if (d->focusedTextInputSurface == surface) {
1236 return;
1237 }
1238
1239 if (d->focusedTextInputSurface) {
1240 disconnect(d->focusedSurfaceDestroyConnection);
1241 d->textInputV1->d->sendLeave(d->focusedTextInputSurface);
1242 d->textInputV2->d->sendLeave(serial, d->focusedTextInputSurface);
1243 d->textInputV3->d->sendLeave(d->focusedTextInputSurface);
1244 }
1245 d->focusedTextInputSurface = surface;
1246
1247 if (surface) {
1248 d->focusedSurfaceDestroyConnection = connect(surface, &SurfaceInterface::aboutToBeDestroyed, this, [this] {
1250 });
1251 d->textInputV1->d->sendEnter(surface);
1252 d->textInputV2->d->sendEnter(surface, serial);
1253 d->textInputV3->d->sendEnter(surface);
1254 }
1255
1257}
1258
1260{
1261 return d->focusedTextInputSurface;
1262}
1263
1265{
1266 return d->textInputV1;
1267}
1268
1270{
1271 return d->textInputV2;
1272}
1273
1275{
1276 return d->textInputV3;
1277}
1279{
1280 return d->currentSelection;
1281}
1282
1284{
1285 if (d->currentSelection == selection) {
1286 return;
1287 }
1288
1289 if (d->currentSelection) {
1290 d->currentSelection->cancel();
1291 disconnect(d->currentSelection, nullptr, this, nullptr);
1292 }
1293
1294 if (selection) {
1295 auto cleanup = [this]() {
1296 setSelection(nullptr);
1297 };
1298 connect(selection, &AbstractDataSource::aboutToBeDestroyed, this, cleanup);
1299 }
1300
1301 d->currentSelection = selection;
1302
1303 for (auto focussedSelection : std::as_const(d->globalKeyboard.focus.selections)) {
1304 focussedSelection->sendSelection(selection);
1305 }
1306
1307 for (auto control : std::as_const(d->dataControlDevices)) {
1308 control->sendSelection(selection);
1309 }
1310
1312}
1313
1315{
1316 return d->currentPrimarySelection;
1317}
1318
1320{
1321 if (d->currentPrimarySelection == selection) {
1322 return;
1323 }
1324 if (d->currentPrimarySelection) {
1325 d->currentPrimarySelection->cancel();
1326 disconnect(d->currentPrimarySelection, nullptr, this, nullptr);
1327 }
1328
1329 if (selection) {
1330 auto cleanup = [this]() {
1331 setPrimarySelection(nullptr);
1332 };
1333 connect(selection, &AbstractDataSource::aboutToBeDestroyed, this, cleanup);
1334 }
1335
1336 d->currentPrimarySelection = selection;
1337
1338 for (auto focussedSelection : std::as_const(d->globalKeyboard.focus.primarySelections)) {
1339 focussedSelection->sendSelection(selection);
1340 }
1341 for (auto control : std::as_const(d->dataControlDevices)) {
1342 control->sendPrimarySelection(selection);
1343 }
1344
1346}
1347
1348void SeatInterface::startDrag(AbstractDataSource *dragSource, SurfaceInterface *originSurface, int dragSerial, DragAndDropIcon *dragIcon)
1349{
1350 if (hasImplicitPointerGrab(dragSerial)) {
1352 d->drag.transformation = d->globalPointer.focus.transformation;
1353 } else if (hasImplicitTouchGrab(dragSerial)) {
1355 d->drag.transformation = d->globalTouch.focus.transformation;
1356 } else {
1357 // no implicit grab, abort drag
1358 return;
1359 }
1360
1361 d->drag.dragImplicitGrabSerial = dragSerial;
1362
1363 // set initial drag target to ourself
1364 d->drag.surface = originSurface;
1365
1366 d->drag.source = dragSource;
1367 if (dragSource) {
1368 d->drag.dragSourceDestroyConnection = QObject::connect(dragSource, &AbstractDataSource::aboutToBeDestroyed, this, [this] {
1369 d->cancelDrag();
1370 });
1371 }
1372 d->drag.dragIcon = dragIcon;
1373
1374 if (!d->dataDevicesForSurface(originSurface).isEmpty()) {
1375 d->drag.target = d->dataDevicesForSurface(originSurface)[0];
1376 }
1377 if (d->drag.target) {
1378 if (d->dragInhibitsPointer(originSurface)) {
1380 }
1381 d->drag.target->updateDragTarget(originSurface, display()->nextSerial());
1382 }
1383 Q_EMIT dragStarted();
1384 Q_EMIT dragSurfaceChanged();
1385}
1386
1388{
1389 return d->drag.dragIcon;
1390}
1391}
1392
1393#include "moc_seat.cpp"
The AbstractDataSource class abstracts the data that can be transferred to another client.
virtual bool isAccepted() const
virtual void updateDragTarget(SurfaceInterface *surface, quint32 serial)=0
virtual void drop()=0
wl_client * client() const
DataControlSourceV1Interface * selection() const
void primarySelectionChanged(KWin::DataControlSourceV1Interface *dataSource)
void sendPrimarySelection(AbstractDataSource *other)
void sendSelection(AbstractDataSource *other)
void selectionChanged(KWin::DataControlSourceV1Interface *dataSource)
DataControlSourceV1Interface * primarySelection() const
QStringList mimeTypes() const override
DataDeviceInterface allows clients to share data by copy-and-paste and drag-and-drop.
Definition datadevice.h:80
void selectionChanged(KWin::DataSourceInterface *)
void dragStarted(AbstractDataSource *source, SurfaceInterface *originSurface, quint32 serial, DragAndDropIcon *dragIcon)
SeatInterface * seat() const
DataSourceInterface * selection() const
void sendSelection(KWin::AbstractDataSource *other)
Represents the Resource for the wl_data_source interface.
Definition datasource.h:23
Class holding the Wayland server display loop.
Definition display.h:34
quint32 nextSerial()
Definition display.cpp:134
QList< SeatInterface * > seats
Definition display_p.h:42
static DisplayPrivate * get(Display *display)
Definition display.cpp:26
Resource for the wl_keyboard interface.
Definition keyboard.h:25
static KeyboardInterfacePrivate * get(KeyboardInterface *keyboard)
Definition keyboard_p.h:33
static PointerHoldGestureV1Interface * get(PointerInterface *pointer)
static PointerInterfacePrivate * get(PointerInterface *pointer)
Definition pointer.cpp:29
static PointerPinchGestureV1Interface * get(PointerInterface *pointer)
static PointerSwipeGestureV1Interface * get(PointerInterface *pointer)
Represents the Resource for the wl_data_device interface.
void selectionChanged(KWin::PrimarySelectionSourceV1Interface *)
static RelativePointerV1Interface * get(PointerInterface *pointer)
Represents a Seat on the Wayland Display.
Definition seat.h:134
SeatInterface(Display *display, QObject *parent=nullptr)
Definition seat.cpp:94
SurfaceInterface * focusedTextInputSurface() const
Definition seat.cpp:1259
void endPointerHoldGesture()
Definition seat.cpp:886
void setFocusedTouchSurface(SurfaceInterface *surface, const QPointF &surfacePosition=QPointF())
Definition seat.cpp:1023
quint32 pointerButtonSerial(quint32 button) const
Definition seat.cpp:757
void setHasTouch(bool has)
Definition seat.cpp:372
void setFocusedPointerSurfacePosition(const QPointF &surfacePosition)
Definition seat.cpp:622
virtual ~SeatInterface()
Definition seat.cpp:102
bool hasPointer() const
Definition seat.cpp:409
void cancelPointerHoldGesture()
Definition seat.cpp:898
Display * display() const
Definition seat.cpp:424
void updatePointerSwipeGesture(const QPointF &delta)
Definition seat.cpp:790
QPointF pointerPos() const
Definition seat.cpp:437
TextInputV1Interface * textInputV1() const
Definition seat.cpp:1264
SurfaceInterface * focusedTouchSurface() const
Definition seat.cpp:998
bool hasKeyboard() const
Definition seat.cpp:414
void endPointerPinchGesture()
Definition seat.cpp:850
void setHasKeyboard(bool has)
Definition seat.cpp:342
void setTimestamp(std::chrono::microseconds time)
Definition seat.cpp:488
void focusedKeyboardSurfaceAboutToChange(SurfaceInterface *nextSurface)
void setDragTarget(AbstractDropHandler *dropTarget, SurfaceInterface *surface, const QPointF &globalPosition, const QMatrix4x4 &inputTransformation)
Definition seat.cpp:498
SurfaceInterface * dragSurface() const
Definition seat.cpp:1213
void setSelection(AbstractDataSource *selection)
Definition seat.cpp:1283
void notifyTouchCancel()
Definition seat.cpp:984
bool hasTouch() const
Definition seat.cpp:419
XdgToplevelDragV1Interface * xdgTopleveldrag() const
Definition seat.cpp:1223
bool isTouchSequence() const
Definition seat.cpp:1008
bool hasImplicitTouchGrab(quint32 serial) const
Definition seat.cpp:1173
void notifyKeyboardKey(quint32 keyCode, KeyboardKeyState state)
Definition seat.cpp:968
void notifyPointerMotion(const QPointF &pos)
Definition seat.cpp:442
void touchMoved(qint32 id, quint32 serial, const QPointF &globalPosition)
void setPrimarySelection(AbstractDataSource *selection)
Definition seat.cpp:1319
bool isDrag() const
Definition seat.cpp:1182
void cancelPointerSwipeGesture()
Definition seat.cpp:814
void setName(const QString &name)
Definition seat.cpp:387
void focusedTextInputSurfaceChanged()
void startPointerHoldGesture(quint32 fingerCount)
Definition seat.cpp:874
void setHasPointer(bool has)
Definition seat.cpp:357
void notifyTouchMotion(qint32 id, const QPointF &globalPosition)
Definition seat.cpp:1094
SurfaceInterface * focusedPointerSurface() const
Definition seat.cpp:550
SurfaceInterface * focusedKeyboardSurface() const
Definition seat.cpp:910
void updatePointerPinchGesture(const QPointF &delta, qreal scale, qreal rotation)
Definition seat.cpp:838
PointerInterface * pointer() const
Definition seat.cpp:648
QPointF focusedPointerSurfacePosition() const
Definition seat.cpp:631
static SeatInterface * get(wl_resource *native)
Definition seat.cpp:429
QPointF firstTouchPointPosition() const
Definition seat.cpp:1018
void setFocusedTextInputSurface(SurfaceInterface *surface)
Definition seat.cpp:1231
void notifyPointerEnter(SurfaceInterface *surface, const QPointF &position, const QPointF &surfacePosition=QPointF())
Definition seat.cpp:555
TextInputV2Interface * textInputV2() const
Definition seat.cpp:1269
void hasTouchChanged(bool)
void setFocusedPointerSurfaceTransformation(const QMatrix4x4 &transformation)
Definition seat.cpp:636
void notifyTouchFrame()
Definition seat.cpp:1165
void notifyPointerLeave()
Definition seat.cpp:604
bool isDragPointer() const
Definition seat.cpp:1187
bool hasImplicitPointerGrab(quint32 serial) const
Definition seat.cpp:1197
bool isPointerButtonPressed(quint32 button) const
Definition seat.cpp:682
void hasKeyboardChanged(bool)
void startPointerPinchGesture(quint32 fingerCount)
Definition seat.cpp:826
std::chrono::milliseconds timestamp() const
Definition seat.cpp:483
bool isDragTouch() const
Definition seat.cpp:1192
void endPointerSwipeGesture()
Definition seat.cpp:802
void selectionChanged(KWin::AbstractDataSource *)
void primarySelectionChanged(KWin::AbstractDataSource *)
AbstractDropHandler * dropHandlerForSurface(SurfaceInterface *surface) const
Definition seat.cpp:174
void pointerPosChanged(const QPointF &pos)
void notifyPointerAxis(Qt::Orientation orientation, qreal delta, qint32 deltaV120, PointerAxisSource source, PointerAxisRelativeDirection direction=PointerAxisRelativeDirection::Normal)
Definition seat.cpp:691
KeyboardInterface * keyboard() const
Definition seat.cpp:963
void notifyKeyboardModifiers(quint32 depressed, quint32 latched, quint32 locked, quint32 group)
Definition seat.cpp:976
TouchInterface * touch() const
Definition seat.cpp:1013
QPointF focusedTouchSurfacePosition() const
Definition seat.cpp:1003
void notifyPointerFrame()
Definition seat.cpp:744
void startPointerSwipeGesture(quint32 fingerCount)
Definition seat.cpp:778
void notifyTouchUp(qint32 id)
Definition seat.cpp:1133
void startDrag(AbstractDataSource *source, SurfaceInterface *sourceSurface, int dragSerial=-1, DragAndDropIcon *dragIcon=nullptr)
Definition seat.cpp:1348
void relativePointerMotion(const QPointF &delta, const QPointF &deltaNonAccelerated, std::chrono::microseconds timestamp)
Definition seat.cpp:766
AbstractDataSource * selection() const
Definition seat.cpp:1278
QMatrix4x4 dragSurfaceTransformation() const
Definition seat.cpp:1208
void setFocusedTouchSurfacePosition(const QPointF &surfacePosition)
Definition seat.cpp:1053
void nameChanged(const QString &)
QMatrix4x4 focusedPointerSurfaceTransformation() const
Definition seat.cpp:643
void hasPointerChanged(bool)
AbstractDataSource * primarySelection() const
Definition seat.cpp:1314
void notifyPointerButton(quint32 button, PointerButtonState state)
Definition seat.cpp:712
QString name() const
Definition seat.cpp:404
void setFocusedKeyboardSurface(SurfaceInterface *surface)
Definition seat.cpp:915
DragAndDropIcon * dragIcon() const
Definition seat.cpp:1387
void cancelPointerPinchGesture()
Definition seat.cpp:862
TextInputV3Interface * textInputV3() const
Definition seat.cpp:1274
AbstractDataSource * dragSource() const
Definition seat.cpp:1218
void notifyTouchDown(qint32 id, const QPointF &globalPosition)
Definition seat.cpp:1060
void seat_release(Resource *resource) override
Definition seat.cpp:89
void registerPrimarySelectionDevice(PrimarySelectionDeviceV1Interface *primarySelectionDevice)
Definition seat.cpp:231
void registerDataControlDevice(DataControlDeviceV1Interface *dataDevice)
Definition seat.cpp:191
bool dragInhibitsPointer(SurfaceInterface *surface) const
Definition seat.cpp:271
void seat_get_keyboard(Resource *resource, uint32_t id) override
Definition seat.cpp:77
void seat_get_touch(Resource *resource, uint32_t id) override
Definition seat.cpp:83
void updatePointerButtonSerial(quint32 button, quint32 serial)
Definition seat.cpp:110
SeatInterfacePrivate(SeatInterface *q, Display *display)
Definition seat.cpp:49
void seat_bind_resource(Resource *resource) override
Definition seat.cpp:62
static KWIN_EXPORT SeatInterfacePrivate * get(SeatInterface *seat)
Definition seat.cpp:44
SeatInterface * q
Definition seat_p.h:49
void registerDataDevice(DataDeviceInterface *dataDevice)
Definition seat.cpp:144
std::unique_ptr< PointerInterface > pointer
Definition seat_p.h:55
QList< DataDeviceInterface * > dataDevicesForSurface(SurfaceInterface *surface) const
Definition seat.cpp:130
void seat_get_pointer(Resource *resource, uint32_t id) override
Definition seat.cpp:71
void updatePointerButtonState(quint32 button, Pointer::State state)
Definition seat.cpp:120
std::unique_ptr< TouchInterface > touch
Definition seat_p.h:56
AbstractDataSource * currentSelection
Definition seat_p.h:70
QList< DataControlDeviceV1Interface * > dataControlDevices
Definition seat_p.h:59
QList< PrimarySelectionDeviceV1Interface * > primarySelectionDevices
Definition seat_p.h:58
QPointer< TextInputV3Interface > textInputV3
Definition seat_p.h:64
QList< DataDeviceInterface * > dataDevices
Definition seat_p.h:57
QPointer< TextInputV2Interface > textInputV2
Definition seat_p.h:63
AbstractDataSource * currentPrimarySelection
Definition seat_p.h:71
QPointer< TextInputV1Interface > textInputV1
Definition seat_p.h:61
std::unique_ptr< KeyboardInterface > keyboard
Definition seat_p.h:54
Resource representing a wl_surface.
Definition surface.h:80
ClientConnection * client() const
Definition surface.cpp:444
QPointF mapToChild(SurfaceInterface *child, const QPointF &point) const
Definition surface.cpp:1039
LockedPointerV1Interface * lockedPointer() const
Definition surface.cpp:1014
qreal scaleOverride() const
Definition surface.cpp:1066
SurfaceInterface * inputSurfaceAt(const QPointF &position)
Definition surface.cpp:982
Represents a generic Resource for a text input object.
Represents a generic Resource for a text input object.
Represents a generic Resource for a text input object.A TextInputV3Interface gets created by the Text...
static TouchInterfacePrivate * get(TouchInterface *touch)
Definition touch.cpp:17
bool hasTouchesForClient(ClientConnection *client) const
Definition touch.cpp:38
PointerAxisSource
Definition seat.h:53
PointerButtonState
Definition seat.h:73
PointerAxisRelativeDirection
Definition seat.h:64
KeyboardKeyState
Definition seat.h:82
QMetaObject::Connection dragSourceDestroyConnection
Definition seat_p.h:142
QPointer< AbstractDropHandler > target
Definition seat_p.h:138
AbstractDataSource * source
Definition seat_p.h:136
QList< PrimarySelectionDeviceV1Interface * > primarySelections
Definition seat_p.h:106
QList< DataDeviceInterface * > selections
Definition seat_p.h:105
QHash< quint32, State > buttonStates
Definition seat_p.h:81
QHash< quint32, quint32 > buttonSerials
Definition seat_p.h:80