KWin
Loading...
Searching...
No Matches
input.cpp
Go to the documentation of this file.
1/*
2 KWin - the KDE window manager
3 This file is part of the KDE project.
4
5 SPDX-FileCopyrightText: 2013 Martin Gräßlin <mgraesslin@kde.org>
6 SPDX-FileCopyrightText: 2018 Roman Gilg <subdiff@gmail.com>
7 SPDX-FileCopyrightText: 2019 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
8
9 SPDX-License-Identifier: GPL-2.0-or-later
10*/
11#include "input.h"
12
16#include "core/inputbackend.h"
17#include "core/session.h"
19#include "gestures.h"
20#include "globalshortcuts.h"
21#include "hide_cursor_spy.h"
22#include "idledetector.h"
23#include "input_event.h"
24#include "input_event_spy.h"
25#include "inputmethod.h"
26#include "keyboard_input.h"
27#include "main.h"
28#include "mousebuttons.h"
29#include "pointer_input.h"
30#include "tablet_input.h"
31#include "touch_input.h"
33#include "x11window.h"
34#if KWIN_BUILD_TABBOX
35#include "tabbox/tabbox.h"
36#endif
37#include "core/output.h"
38#include "core/outputbackend.h"
39#include "cursor.h"
40#include "cursorsource.h"
41#include "internalwindow.h"
42#include "popup_input_filter.h"
43#include "screenedge.h"
44#include "virtualdesktops.h"
45#include "wayland/display.h"
47#include "wayland/seat.h"
48#include "wayland/surface.h"
49#include "wayland/tablet_v2.h"
50#include "wayland_server.h"
51#include "workspace.h"
52#include "xkb.h"
54
55#include <KDecoration2/Decoration>
56#include <KGlobalAccel>
57#include <KLocalizedString>
59
60// screenlocker
61#if KWIN_BUILD_SCREENLOCKER
62#include <KScreenLocker/KsldApp>
63#endif
64// Qt
65#include <QAction>
66#include <QDBusConnection>
67#include <QDBusMessage>
68#include <QDBusPendingCall>
69#include <QKeyEvent>
70#include <QThread>
71#include <qpa/qwindowsysteminterface.h>
72
73#include <xkbcommon/xkbcommon.h>
74
75#include "osd.h"
76#include "wayland/xdgshell.h"
77#include <cmath>
78
79using namespace std::literals;
80
81namespace KWin
82{
83
84static PointerAxisSource kwinAxisSourceToKWaylandAxisSource(InputRedirection::PointerAxisSource source)
85{
86 switch (source) {
96 default:
98 }
99}
100
102
109
110bool InputEventFilter::pointerEvent(MouseEvent *event, quint32 nativeButton)
111{
112 return false;
113}
114
116{
117 return false;
118}
119
121{
122 return false;
123}
124
126{
127 return false;
128}
129
130bool InputEventFilter::touchDown(qint32 id, const QPointF &point, std::chrono::microseconds time)
131{
132 return false;
133}
134
135bool InputEventFilter::touchMotion(qint32 id, const QPointF &point, std::chrono::microseconds time)
136{
137 return false;
138}
139
140bool InputEventFilter::touchUp(qint32 id, std::chrono::microseconds time)
141{
142 return false;
143}
144
146{
147 return false;
148}
149
151{
152 return false;
153}
154
155bool InputEventFilter::pinchGestureBegin(int fingerCount, std::chrono::microseconds time)
156{
157 return false;
158}
159
160bool InputEventFilter::pinchGestureUpdate(qreal scale, qreal angleDelta, const QPointF &delta, std::chrono::microseconds time)
161{
162 return false;
163}
164
165bool InputEventFilter::pinchGestureEnd(std::chrono::microseconds time)
166{
167 return false;
168}
169
170bool InputEventFilter::pinchGestureCancelled(std::chrono::microseconds time)
171{
172 return false;
173}
174
175bool InputEventFilter::swipeGestureBegin(int fingerCount, std::chrono::microseconds time)
176{
177 return false;
178}
179
180bool InputEventFilter::swipeGestureUpdate(const QPointF &delta, std::chrono::microseconds time)
181{
182 return false;
183}
184
185bool InputEventFilter::swipeGestureEnd(std::chrono::microseconds time)
186{
187 return false;
188}
189
190bool InputEventFilter::swipeGestureCancelled(std::chrono::microseconds time)
191{
192 return false;
193}
194
195bool InputEventFilter::holdGestureBegin(int fingerCount, std::chrono::microseconds time)
196{
197 return false;
198}
199
200bool InputEventFilter::holdGestureEnd(std::chrono::microseconds time)
201{
202 return false;
203}
204
205bool InputEventFilter::holdGestureCancelled(std::chrono::microseconds time)
206{
207 return false;
208}
209
211{
212 return false;
213}
214
216{
217 return false;
218}
219
220bool InputEventFilter::tabletToolButtonEvent(uint button, bool pressed, const TabletToolId &tabletId, std::chrono::microseconds time)
221{
222 return false;
223}
224
225bool InputEventFilter::tabletPadButtonEvent(uint button, bool pressed, const TabletPadId &tabletPadId, std::chrono::microseconds time)
226{
227 return false;
228}
229
230bool InputEventFilter::tabletPadStripEvent(int number, int position, bool isFinger, const TabletPadId &tabletPadId, std::chrono::microseconds time)
231{
232 return false;
233}
234
235bool InputEventFilter::tabletPadRingEvent(int number, int position, bool isFinger, const TabletPadId &tabletPadId, std::chrono::microseconds time)
236{
237 return false;
238}
239
241{
242 Q_ASSERT(waylandServer());
243 if (event->isAutoRepeat()) {
244 return;
245 }
246
247 SeatInterface *seat = waylandServer()->seat();
248 const int keyCode = event->nativeScanCode();
249 switch (event->type()) {
250 case QEvent::KeyPress:
251 seat->notifyKeyboardKey(keyCode, KeyboardKeyState::Pressed);
252 break;
253 case QEvent::KeyRelease:
254 seat->notifyKeyboardKey(keyCode, KeyboardKeyState::Released);
255 break;
256 default:
257 break;
258 }
259}
260
262{
263 if (!kwinApp()->inputMethod()) {
264 return false;
265 }
266 if (auto keyboardGrab = kwinApp()->inputMethod()->keyboardGrab()) {
267 if (event->isAutoRepeat()) {
268 return true;
269 }
270 auto newState = event->type() == QEvent::KeyPress ? KeyboardKeyState::Pressed : KeyboardKeyState::Released;
271 keyboardGrab->sendKey(waylandServer()->display()->nextSerial(), event->timestamp(), event->nativeScanCode(), newState);
272 return true;
273 } else {
274 return false;
275 }
276}
277
279{
280public:
281 bool keyEvent(KeyEvent *event) override
282 {
283 // really on press and not on release? X11 switches on press.
284 if (event->type() == QEvent::KeyPress && !event->isAutoRepeat()) {
285 const xkb_keysym_t keysym = event->nativeVirtualKey();
286 if (keysym >= XKB_KEY_XF86Switch_VT_1 && keysym <= XKB_KEY_XF86Switch_VT_12) {
287 kwinApp()->session()->switchTo(keysym - XKB_KEY_XF86Switch_VT_1 + 1);
288 return true;
289 }
290 }
291 return false;
292 }
293};
294
296{
297public:
298 bool pointerEvent(MouseEvent *event, quint32 nativeButton) override
299 {
300 if (!waylandServer()->isScreenLocked()) {
301 return false;
302 }
303
304 auto window = input()->findToplevel(event->globalPosition());
305 if (window && window->isClient() && window->isLockScreen()) {
306 workspace()->activateWindow(window);
307 }
308
309 auto seat = waylandServer()->seat();
310 seat->setTimestamp(event->timestamp());
311 if (event->type() == QEvent::MouseMove) {
312 if (pointerSurfaceAllowed()) {
313 // TODO: should the pointer position always stay in sync, i.e. not do the check?
314 seat->notifyPointerMotion(event->screenPos());
315 }
316 } else if (event->type() == QEvent::MouseButtonPress || event->type() == QEvent::MouseButtonRelease) {
317 if (pointerSurfaceAllowed()) {
318 // TODO: can we leak presses/releases here when we move the mouse in between from an allowed surface to
319 // disallowed one or vice versa?
320 const auto state = event->type() == QEvent::MouseButtonPress
323 seat->notifyPointerButton(nativeButton, state);
324 }
325 }
326 return true;
327 }
328 bool pointerFrame() override
329 {
330 if (!waylandServer()->isScreenLocked()) {
331 return false;
332 }
333 auto seat = waylandServer()->seat();
334 if (pointerSurfaceAllowed()) {
335 seat->notifyPointerFrame();
336 }
337 return true;
338 }
339 bool wheelEvent(WheelEvent *event) override
340 {
341 if (!waylandServer()->isScreenLocked()) {
342 return false;
343 }
344 auto seat = waylandServer()->seat();
345 if (pointerSurfaceAllowed()) {
346 const WheelEvent *wheelEvent = static_cast<WheelEvent *>(event);
347 seat->setTimestamp(wheelEvent->timestamp());
348 seat->notifyPointerAxis(wheelEvent->orientation(), wheelEvent->delta(),
349 wheelEvent->deltaV120(),
350 kwinAxisSourceToKWaylandAxisSource(wheelEvent->axisSource()),
352 }
353 return true;
354 }
355 bool keyEvent(KeyEvent *event) override
356 {
357 if (!waylandServer()->isScreenLocked()) {
358 return false;
359 }
360 if (event->isAutoRepeat()) {
361 // wayland client takes care of it
362 return true;
363 }
364 // send event to KSldApp for global accel
365 // if event is set to accepted it means a whitelisted shortcut was triggered
366 // in that case we filter it out and don't process it further
367#if KWIN_BUILD_SCREENLOCKER
368 event->setAccepted(false);
369 QCoreApplication::sendEvent(ScreenLocker::KSldApp::self(), event);
370 if (event->isAccepted()) {
371 return true;
372 }
373#endif
374
375 // continue normal processing
376 input()->keyboard()->update();
377 auto seat = waylandServer()->seat();
378 seat->setTimestamp(event->timestamp());
379 if (!keyboardSurfaceAllowed()) {
380 // don't pass event to seat
381 return true;
382 }
383 switch (event->type()) {
384 case QEvent::KeyPress:
385 seat->notifyKeyboardKey(event->nativeScanCode(), KeyboardKeyState::Pressed);
386 break;
387 case QEvent::KeyRelease:
388 seat->notifyKeyboardKey(event->nativeScanCode(), KeyboardKeyState::Released);
389 break;
390 default:
391 break;
392 }
393 return true;
394 }
395 bool touchDown(qint32 id, const QPointF &pos, std::chrono::microseconds time) override
396 {
397 if (!waylandServer()->isScreenLocked()) {
398 return false;
399 }
400 auto seat = waylandServer()->seat();
401 seat->setTimestamp(time);
402 if (touchSurfaceAllowed()) {
403 seat->notifyTouchDown(id, pos);
404 }
405 return true;
406 }
407 bool touchMotion(qint32 id, const QPointF &pos, std::chrono::microseconds time) override
408 {
409 if (!waylandServer()->isScreenLocked()) {
410 return false;
411 }
412 auto seat = waylandServer()->seat();
413 seat->setTimestamp(time);
414 if (touchSurfaceAllowed()) {
415 seat->notifyTouchMotion(id, pos);
416 }
417 return true;
418 }
419 bool touchUp(qint32 id, std::chrono::microseconds time) override
420 {
421 if (!waylandServer()->isScreenLocked()) {
422 return false;
423 }
424 auto seat = waylandServer()->seat();
425 seat->setTimestamp(time);
426 if (touchSurfaceAllowed()) {
427 seat->notifyTouchUp(id);
428 }
429 return true;
430 }
431 bool pinchGestureBegin(int fingerCount, std::chrono::microseconds time) override
432 {
433 // no touchpad multi-finger gestures on lock screen
434 return waylandServer()->isScreenLocked();
435 }
436 bool pinchGestureUpdate(qreal scale, qreal angleDelta, const QPointF &delta, std::chrono::microseconds time) override
437 {
438 // no touchpad multi-finger gestures on lock screen
439 return waylandServer()->isScreenLocked();
440 }
441 bool pinchGestureEnd(std::chrono::microseconds time) override
442 {
443 // no touchpad multi-finger gestures on lock screen
444 return waylandServer()->isScreenLocked();
445 }
446 bool pinchGestureCancelled(std::chrono::microseconds time) override
447 {
448 // no touchpad multi-finger gestures on lock screen
449 return waylandServer()->isScreenLocked();
450 }
451
452 bool swipeGestureBegin(int fingerCount, std::chrono::microseconds time) override
453 {
454 // no touchpad multi-finger gestures on lock screen
455 return waylandServer()->isScreenLocked();
456 }
457 bool swipeGestureUpdate(const QPointF &delta, std::chrono::microseconds time) override
458 {
459 // no touchpad multi-finger gestures on lock screen
460 return waylandServer()->isScreenLocked();
461 }
462 bool swipeGestureEnd(std::chrono::microseconds time) override
463 {
464 // no touchpad multi-finger gestures on lock screen
465 return waylandServer()->isScreenLocked();
466 }
467 bool swipeGestureCancelled(std::chrono::microseconds time) override
468 {
469 // no touchpad multi-finger gestures on lock screen
470 return waylandServer()->isScreenLocked();
471 }
472 bool holdGestureBegin(int fingerCount, std::chrono::microseconds time) override
473 {
474 // no touchpad multi-finger gestures on lock screen
475 return waylandServer()->isScreenLocked();
476 }
477 bool holdGestureEnd(std::chrono::microseconds time) override
478 {
479 // no touchpad multi-finger gestures on lock screen
480 return waylandServer()->isScreenLocked();
481 }
482
483private:
484 bool surfaceAllowed(SurfaceInterface *(SeatInterface::*method)() const) const
485 {
486 if (SurfaceInterface *s = (waylandServer()->seat()->*method)()) {
487 if (Window *t = waylandServer()->findWindow(s)) {
488 return t->isLockScreen() || t->isInputMethod() || t->isLockScreenOverlay();
489 }
490 return false;
491 }
492 return true;
493 }
494 bool pointerSurfaceAllowed() const
495 {
496 return surfaceAllowed(&SeatInterface::focusedPointerSurface);
497 }
498 bool keyboardSurfaceAllowed() const
499 {
500 return surfaceAllowed(&SeatInterface::focusedKeyboardSurface);
501 }
502 bool touchSurfaceAllowed() const
503 {
504 return surfaceAllowed(&SeatInterface::focusedTouchSurface);
505 }
506};
507
509{
510public:
511 bool pointerEvent(MouseEvent *event, quint32 nativeButton) override
512 {
513 if (!effects) {
514 return false;
515 }
516 return effects->checkInputWindowEvent(event);
517 }
518 bool wheelEvent(WheelEvent *event) override
519 {
520 if (!effects) {
521 return false;
522 }
523 return effects->checkInputWindowEvent(event);
524 }
525 bool keyEvent(KeyEvent *event) override
526 {
527 if (!effects || !effects->hasKeyboardGrab()) {
528 return false;
529 }
531 passToWaylandServer(event);
533 return true;
534 }
535 bool touchDown(qint32 id, const QPointF &pos, std::chrono::microseconds time) override
536 {
537 if (!effects) {
538 return false;
539 }
540 return effects->touchDown(id, pos, time);
541 }
542 bool touchMotion(qint32 id, const QPointF &pos, std::chrono::microseconds time) override
543 {
544 if (!effects) {
545 return false;
546 }
547 return effects->touchMotion(id, pos, time);
548 }
549 bool touchUp(qint32 id, std::chrono::microseconds time) override
550 {
551 if (!effects) {
552 return false;
553 }
554 return effects->touchUp(id, time);
555 }
556 bool tabletToolEvent(TabletEvent *event) override
557 {
558 if (!effects) {
559 return false;
560 }
561 return effects->tabletToolEvent(event);
562 }
563 bool tabletToolButtonEvent(uint button, bool pressed, const TabletToolId &tabletToolId, std::chrono::microseconds time) override
564 {
565 if (!effects) {
566 return false;
567 }
568 return effects->tabletToolButtonEvent(button, pressed, tabletToolId, time);
569 }
570 bool tabletPadButtonEvent(uint button, bool pressed, const TabletPadId &tabletPadId, std::chrono::microseconds time) override
571 {
572 if (!effects) {
573 return false;
574 }
575 return effects->tabletPadButtonEvent(button, pressed, tabletPadId, time);
576 }
577 bool tabletPadStripEvent(int number, int position, bool isFinger, const TabletPadId &tabletPadId, std::chrono::microseconds time) override
578 {
579 if (!effects) {
580 return false;
581 }
582 return effects->tabletPadStripEvent(number, position, isFinger, tabletPadId, time);
583 }
584 bool tabletPadRingEvent(int number, int position, bool isFinger, const TabletPadId &tabletPadId, std::chrono::microseconds time) override
585 {
586 if (!effects) {
587 return false;
588 }
589 return effects->tabletPadRingEvent(number, position, isFinger, tabletPadId, time);
590 }
591};
592
594{
595public:
596 bool pointerEvent(MouseEvent *event, quint32 nativeButton) override
597 {
598 Window *window = workspace()->moveResizeWindow();
599 if (!window) {
600 return false;
601 }
602 switch (event->type()) {
603 case QEvent::MouseMove:
604 window->updateInteractiveMoveResize(event->screenPos());
605 break;
606 case QEvent::MouseButtonRelease:
607 if (event->buttons() == Qt::NoButton) {
608 window->endInteractiveMoveResize();
609 }
610 break;
611 default:
612 break;
613 }
614 return true;
615 }
616 bool wheelEvent(WheelEvent *event) override
617 {
618 // filter out while moving a window
619 return workspace()->moveResizeWindow() != nullptr;
620 }
621 bool keyEvent(KeyEvent *event) override
622 {
623 Window *window = workspace()->moveResizeWindow();
624 if (!window) {
625 return false;
626 }
627 if (event->type() == QEvent::KeyPress) {
628 window->keyPressEvent(event->key() | event->modifiers());
629 }
630 if (window->isInteractiveMove() || window->isInteractiveResize()) {
631 // only update if mode didn't end
632 window->updateInteractiveMoveResize(input()->globalPointer());
633 }
634 return true;
635 }
636
637 bool touchDown(qint32 id, const QPointF &pos, std::chrono::microseconds time) override
638 {
639 Window *window = workspace()->moveResizeWindow();
640 if (!window) {
641 return false;
642 }
643 return true;
644 }
645
646 bool touchMotion(qint32 id, const QPointF &pos, std::chrono::microseconds time) override
647 {
648 Window *window = workspace()->moveResizeWindow();
649 if (!window) {
650 return false;
651 }
652 if (!m_set) {
653 m_id = id;
654 m_set = true;
655 }
656 if (m_id == id) {
657 window->updateInteractiveMoveResize(pos);
658 }
659 return true;
660 }
661
662 bool touchUp(qint32 id, std::chrono::microseconds time) override
663 {
664 Window *window = workspace()->moveResizeWindow();
665 if (!window) {
666 return false;
667 }
668 if (m_id == id || !m_set) {
669 window->endInteractiveMoveResize();
670 m_set = false;
671 // pass through to update decoration filter later on
672 return false;
673 }
674 m_set = false;
675 return true;
676 }
677
678 bool tabletToolEvent(TabletEvent *event) override
679 {
680 Window *window = workspace()->moveResizeWindow();
681 if (!window) {
682 return false;
683 }
684 switch (event->type()) {
685 case QEvent::TabletMove:
686 window->updateInteractiveMoveResize(event->globalPosF());
687 break;
688 case QEvent::TabletRelease:
689 window->endInteractiveMoveResize();
690 break;
691 default:
692 break;
693 }
694 // Let TabletInputFilter receive the event, so the cursor position can be updated.
695 return false;
696 }
697
698private:
699 qint32 m_id = 0;
700 bool m_set = false;
701};
702
704{
705public:
706 bool pointerEvent(MouseEvent *event, quint32 nativeButton) override
707 {
708 if (!m_active) {
709 return false;
710 }
711 switch (event->type()) {
712 case QEvent::MouseButtonRelease:
713 if (event->buttons() == Qt::NoButton) {
714 if (event->button() == Qt::RightButton) {
715 cancel();
716 } else {
717 accept(event->globalPosition());
718 }
719 }
720 break;
721 default:
722 break;
723 }
724 return true;
725 }
726 bool wheelEvent(WheelEvent *event) override
727 {
728 // filter out while selecting a window
729 return m_active;
730 }
731 bool keyEvent(KeyEvent *event) override
732 {
733 if (!m_active) {
734 return false;
735 }
737 passToWaylandServer(event);
738
739 if (event->type() == QEvent::KeyPress) {
740 // x11 variant does this on key press, so do the same
741 if (event->key() == Qt::Key_Escape) {
742 cancel();
743 } else if (event->key() == Qt::Key_Enter || event->key() == Qt::Key_Return || event->key() == Qt::Key_Space) {
744 accept(input()->globalPointer());
745 }
746 if (input()->supportsPointerWarping()) {
747 int mx = 0;
748 int my = 0;
749 if (event->key() == Qt::Key_Left) {
750 mx = -10;
751 }
752 if (event->key() == Qt::Key_Right) {
753 mx = 10;
754 }
755 if (event->key() == Qt::Key_Up) {
756 my = -10;
757 }
758 if (event->key() == Qt::Key_Down) {
759 my = 10;
760 }
761 if (event->modifiers() & Qt::ControlModifier) {
762 mx /= 10;
763 my /= 10;
764 }
765 input()->warpPointer(input()->globalPointer() + QPointF(mx, my));
766 }
767 }
768 // filter out while selecting a window
769 return true;
770 }
771
772 bool touchDown(qint32 id, const QPointF &pos, std::chrono::microseconds time) override
773 {
774 if (!isActive()) {
775 return false;
776 }
777 m_touchPoints.insert(id, pos);
778 return true;
779 }
780
781 bool touchMotion(qint32 id, const QPointF &pos, std::chrono::microseconds time) override
782 {
783 if (!isActive()) {
784 return false;
785 }
786 auto it = m_touchPoints.find(id);
787 if (it != m_touchPoints.end()) {
788 *it = pos;
789 }
790 return true;
791 }
792
793 bool touchUp(qint32 id, std::chrono::microseconds time) override
794 {
795 if (!isActive()) {
796 return false;
797 }
798 auto it = m_touchPoints.find(id);
799 if (it != m_touchPoints.end()) {
800 const auto pos = it.value();
801 m_touchPoints.erase(it);
802 if (m_touchPoints.isEmpty()) {
803 accept(pos);
804 }
805 }
806 return true;
807 }
808
809 bool isActive() const
810 {
811 return m_active;
812 }
813 void start(std::function<void(Window *)> callback)
814 {
815 Q_ASSERT(!m_active);
816 m_active = true;
817 m_callback = callback;
818 input()->keyboard()->update();
819 input()->touch()->cancel();
820 }
821 void start(std::function<void(const QPoint &)> callback)
822 {
823 Q_ASSERT(!m_active);
824 m_active = true;
825 m_pointSelectionFallback = callback;
826 input()->keyboard()->update();
827 input()->touch()->cancel();
828 }
829
830private:
831 void deactivate()
832 {
833 m_active = false;
834 m_callback = std::function<void(Window *)>();
835 m_pointSelectionFallback = std::function<void(const QPoint &)>();
837 input()->keyboard()->update();
838 m_touchPoints.clear();
839 }
840 void cancel()
841 {
842 if (m_callback) {
843 m_callback(nullptr);
844 }
845 if (m_pointSelectionFallback) {
846 m_pointSelectionFallback(QPoint(-1, -1));
847 }
848 deactivate();
849 }
850 void accept(const QPointF &pos)
851 {
852 if (m_callback) {
853 // TODO: this ignores shaped windows
854 m_callback(input()->findToplevel(pos));
855 }
856 if (m_pointSelectionFallback) {
857 m_pointSelectionFallback(pos.toPoint());
858 }
859 deactivate();
860 }
861
862 bool m_active = false;
863 std::function<void(Window *)> m_callback;
864 std::function<void(const QPoint &)> m_pointSelectionFallback;
865 QMap<quint32, QPointF> m_touchPoints;
866};
867
868#if KWIN_BUILD_GLOBALSHORTCUTS
869class GlobalShortcutFilter : public InputEventFilter
870{
871public:
872 GlobalShortcutFilter()
873 {
874 m_powerDown.setSingleShot(true);
875 m_powerDown.setInterval(1000);
876 }
877
878 bool pointerEvent(MouseEvent *event, quint32 nativeButton) override
879 {
880 if (event->type() == QEvent::MouseButtonPress) {
881 if (input()->shortcuts()->processPointerPressed(event->modifiers(), event->buttons())) {
882 return true;
883 }
884 }
885 return false;
886 }
887 bool wheelEvent(WheelEvent *event) override
888 {
889 if (event->modifiers() == Qt::NoModifier) {
890 return false;
891 }
893 if (event->angleDelta().x() < 0) {
894 direction = PointerAxisRight;
895 } else if (event->angleDelta().x() > 0) {
896 direction = PointerAxisLeft;
897 } else if (event->angleDelta().y() < 0) {
898 direction = PointerAxisDown;
899 } else if (event->angleDelta().y() > 0) {
900 direction = PointerAxisUp;
901 }
902 return input()->shortcuts()->processAxis(event->modifiers(), direction);
903 }
904 bool keyEvent(KeyEvent *event) override
905 {
906 if (event->key() == Qt::Key_PowerOff) {
907 const auto modifiers = static_cast<KeyEvent *>(event)->modifiersRelevantForGlobalShortcuts();
908 if (event->type() == QEvent::KeyPress && !event->isAutoRepeat()) {
909 auto passToShortcuts = [modifiers] {
910 input()->shortcuts()->processKey(modifiers, Qt::Key_PowerDown);
911 };
912 QObject::connect(&m_powerDown, &QTimer::timeout, input()->shortcuts(), passToShortcuts, Qt::SingleShotConnection);
913 m_powerDown.start();
914 return true;
915 } else if (event->type() == QEvent::KeyRelease) {
916 const bool ret = !m_powerDown.isActive() || input()->shortcuts()->processKey(modifiers, event->key());
917 m_powerDown.stop();
918 return ret;
919 }
920 } else if (event->type() == QEvent::KeyPress) {
921 if (!waylandServer()->isKeyboardShortcutsInhibited()) {
922 return input()->shortcuts()->processKey(static_cast<KeyEvent *>(event)->modifiersRelevantForGlobalShortcuts(), event->key());
923 }
924 } else if (event->type() == QEvent::KeyRelease) {
925 if (!waylandServer()->isKeyboardShortcutsInhibited()) {
926 return input()->shortcuts()->processKeyRelease(static_cast<KeyEvent *>(event)->modifiersRelevantForGlobalShortcuts(), event->key());
927 }
928 }
929 return false;
930 }
931 bool swipeGestureBegin(int fingerCount, std::chrono::microseconds time) override
932 {
933 m_touchpadGestureFingerCount = fingerCount;
934 if (m_touchpadGestureFingerCount >= 3) {
935 input()->shortcuts()->processSwipeStart(DeviceType::Touchpad, fingerCount);
936 return true;
937 } else {
938 return false;
939 }
940 }
941 bool swipeGestureUpdate(const QPointF &delta, std::chrono::microseconds time) override
942 {
943 if (m_touchpadGestureFingerCount >= 3) {
944 input()->shortcuts()->processSwipeUpdate(DeviceType::Touchpad, delta);
945 return true;
946 } else {
947 return false;
948 }
949 }
950 bool swipeGestureCancelled(std::chrono::microseconds time) override
951 {
952 if (m_touchpadGestureFingerCount >= 3) {
953 input()->shortcuts()->processSwipeCancel(DeviceType::Touchpad);
954 return true;
955 } else {
956 return false;
957 }
958 }
959 bool swipeGestureEnd(std::chrono::microseconds time) override
960 {
961 if (m_touchpadGestureFingerCount >= 3) {
962 input()->shortcuts()->processSwipeEnd(DeviceType::Touchpad);
963 return true;
964 } else {
965 return false;
966 }
967 }
968 bool pinchGestureBegin(int fingerCount, std::chrono::microseconds time) override
969 {
970 m_touchpadGestureFingerCount = fingerCount;
971 if (m_touchpadGestureFingerCount >= 3) {
972 input()->shortcuts()->processPinchStart(fingerCount);
973 return true;
974 } else {
975 return false;
976 }
977 }
978 bool pinchGestureUpdate(qreal scale, qreal angleDelta, const QPointF &delta, std::chrono::microseconds time) override
979 {
980 if (m_touchpadGestureFingerCount >= 3) {
981 input()->shortcuts()->processPinchUpdate(scale, angleDelta, delta);
982 return true;
983 } else {
984 return false;
985 }
986 }
987 bool pinchGestureEnd(std::chrono::microseconds time) override
988 {
989 if (m_touchpadGestureFingerCount >= 3) {
990 input()->shortcuts()->processPinchEnd();
991 return true;
992 } else {
993 return false;
994 }
995 }
996 bool pinchGestureCancelled(std::chrono::microseconds time) override
997 {
998 if (m_touchpadGestureFingerCount >= 3) {
999 input()->shortcuts()->processPinchCancel();
1000 return true;
1001 } else {
1002 return false;
1003 }
1004 }
1005 bool touchDown(qint32 id, const QPointF &pos, std::chrono::microseconds time) override
1006 {
1007 if (m_gestureTaken) {
1008 input()->shortcuts()->processSwipeCancel(DeviceType::Touchscreen);
1009 m_gestureCancelled = true;
1010 return true;
1011 } else {
1012 m_touchPoints.insert(id, pos);
1013 if (m_touchPoints.count() == 1) {
1014 m_lastTouchDownTime = time;
1015 } else {
1016 if (time - m_lastTouchDownTime > 250ms) {
1017 m_gestureCancelled = true;
1018 return false;
1019 }
1020 m_lastTouchDownTime = time;
1021 auto output = workspace()->outputAt(pos);
1022 auto physicalSize = output->orientateSize(output->physicalSize());
1023 if (!physicalSize.isValid()) {
1024 physicalSize = QSize(190, 100);
1025 }
1026 float xfactor = physicalSize.width() / (float)output->geometry().width();
1027 float yfactor = physicalSize.height() / (float)output->geometry().height();
1028 bool distanceMatch = std::any_of(m_touchPoints.constBegin(), m_touchPoints.constEnd(), [pos, xfactor, yfactor](const auto &point) {
1029 QPointF p = pos - point;
1030 return std::abs(xfactor * p.x()) + std::abs(yfactor * p.y()) < 50;
1031 });
1032 if (!distanceMatch) {
1033 m_gestureCancelled = true;
1034 return false;
1035 }
1036 }
1037 if (m_touchPoints.count() >= 3 && !m_gestureCancelled) {
1038 m_gestureTaken = true;
1039 m_syntheticCancel = true;
1040 input()->processFilters(std::bind(&InputEventFilter::touchCancel, std::placeholders::_1));
1041 m_syntheticCancel = false;
1042 input()->shortcuts()->processSwipeStart(DeviceType::Touchscreen, m_touchPoints.count());
1043 return true;
1044 }
1045 }
1046 return false;
1047 }
1048
1049 bool touchMotion(qint32 id, const QPointF &pos, std::chrono::microseconds time) override
1050 {
1051 if (m_gestureTaken) {
1052 if (m_gestureCancelled) {
1053 return true;
1054 }
1055 auto output = workspace()->outputAt(pos);
1056 const auto physicalSize = output->orientateSize(output->physicalSize());
1057 const float xfactor = physicalSize.width() / (float)output->geometry().width();
1058 const float yfactor = physicalSize.height() / (float)output->geometry().height();
1059
1060 auto &point = m_touchPoints[id];
1061 const QPointF dist = pos - point;
1062 const QPointF delta = QPointF(xfactor * dist.x(), yfactor * dist.y());
1063 input()->shortcuts()->processSwipeUpdate(DeviceType::Touchscreen, 5 * delta / m_touchPoints.size());
1064 point = pos;
1065 return true;
1066 }
1067 return false;
1068 }
1069
1070 bool touchUp(qint32 id, std::chrono::microseconds time) override
1071 {
1072 m_touchPoints.remove(id);
1073 if (m_gestureTaken) {
1074 if (!m_gestureCancelled) {
1075 input()->shortcuts()->processSwipeEnd(DeviceType::Touchscreen);
1076 m_gestureCancelled = true;
1077 }
1078 m_gestureTaken &= m_touchPoints.count() > 0;
1079 m_gestureCancelled &= m_gestureTaken;
1080 return true;
1081 } else {
1082 m_gestureCancelled &= m_touchPoints.count() > 0;
1083 return false;
1084 }
1085 }
1086
1087 bool touchCancel() override
1088 {
1089 if (m_syntheticCancel) {
1090 return false;
1091 }
1092 const bool oldGestureTaken = m_gestureTaken;
1093 m_gestureTaken = false;
1094 m_gestureCancelled = false;
1095 m_touchPoints.clear();
1096 return oldGestureTaken;
1097 }
1098
1099 bool touchFrame() override
1100 {
1101 return m_gestureTaken;
1102 }
1103
1104private:
1105 bool m_gestureTaken = false;
1106 bool m_gestureCancelled = false;
1107 bool m_syntheticCancel = false;
1108 std::chrono::microseconds m_lastTouchDownTime = std::chrono::microseconds::zero();
1109 QPointF m_lastAverageDistance;
1110 QMap<int32_t, QPointF> m_touchPoints;
1111 int m_touchpadGestureFingerCount = 0;
1112
1113 QTimer m_powerDown;
1114};
1115#endif
1116
1117namespace
1118{
1119
1120enum class MouseAction {
1121 ModifierOnly,
1122 ModifierAndWindow
1123};
1124std::pair<bool, bool> performWindowMouseAction(QMouseEvent *event, Window *window, MouseAction action = MouseAction::ModifierOnly)
1125{
1127 bool wasAction = false;
1128 if (static_cast<MouseEvent *>(event)->modifiersRelevantForGlobalShortcuts() == options->commandAllModifier()) {
1129 if (!input()->pointer()->isConstrained() && !workspace()->globalShortcutsDisabled()) {
1130 wasAction = true;
1131 switch (event->button()) {
1132 case Qt::LeftButton:
1133 command = options->commandAll1();
1134 break;
1135 case Qt::MiddleButton:
1136 command = options->commandAll2();
1137 break;
1138 case Qt::RightButton:
1139 command = options->commandAll3();
1140 break;
1141 default:
1142 // nothing
1143 break;
1144 }
1145 }
1146 } else {
1147 if (action == MouseAction::ModifierAndWindow) {
1148 command = window->getMouseCommand(event->button(), &wasAction);
1149 }
1150 }
1151 if (wasAction) {
1152 return std::make_pair(wasAction, !window->performMouseCommand(command, event->globalPosition()));
1153 }
1154 return std::make_pair(wasAction, false);
1155}
1156
1157std::pair<bool, bool> performWindowWheelAction(QWheelEvent *event, Window *window, MouseAction action = MouseAction::ModifierOnly)
1158{
1159 bool wasAction = false;
1161 if (static_cast<WheelEvent *>(event)->modifiersRelevantForGlobalShortcuts() == options->commandAllModifier()) {
1162 if (!input()->pointer()->isConstrained() && !workspace()->globalShortcutsDisabled()) {
1163 wasAction = true;
1164 command = options->operationWindowMouseWheel(-1 * event->angleDelta().y());
1165 }
1166 } else {
1167 if (action == MouseAction::ModifierAndWindow) {
1168 command = window->getWheelCommand(Qt::Vertical, &wasAction);
1169 }
1170 }
1171 if (wasAction) {
1172 return std::make_pair(wasAction, !window->performMouseCommand(command, event->globalPosition()));
1173 }
1174 return std::make_pair(wasAction, false);
1175}
1176
1177}
1178
1180{
1181 bool pointerEvent(MouseEvent *event, quint32 nativeButton) override
1182 {
1183 if (!input()->pointer()->focus() || !input()->pointer()->focus()->isInternal()) {
1184 return false;
1185 }
1186 QWindow *internal = static_cast<InternalWindow *>(input()->pointer()->focus())->handle();
1187 if (!internal) {
1188 // the handle can be nullptr if the tooltip gets closed while focus updates are blocked
1189 return false;
1190 }
1191 const bool isAccepted = QWindowSystemInterface::handleMouseEvent<QWindowSystemInterface::SynchronousDelivery>(internal,
1192 event->position() - internal->position(),
1193 event->globalPosition(),
1194 event->buttons(),
1195 event->button(),
1196 event->type(),
1197 event->modifiers());
1198 return isAccepted;
1199 }
1200 bool wheelEvent(WheelEvent *event) override
1201 {
1202 if (!input()->pointer()->focus() || !input()->pointer()->focus()->isInternal()) {
1203 return false;
1204 }
1205 QWindow *internal = static_cast<InternalWindow *>(input()->pointer()->focus())->handle();
1206 const QPointF localPos = event->globalPosition() - internal->position();
1207 QWheelEvent wheelEvent(localPos, event->globalPosition(), QPoint(),
1208 event->angleDelta() * -1,
1209 event->buttons(),
1210 event->modifiers(),
1211 Qt::NoScrollPhase,
1212 false);
1213 QCoreApplication::sendEvent(internal, &wheelEvent);
1214 return wheelEvent.isAccepted();
1215 }
1216 bool keyEvent(KeyEvent *event) override
1217 {
1218 const QList<Window *> windows = workspace()->windows();
1219 QWindow *found = nullptr;
1220 for (auto it = windows.crbegin(); it != windows.crend(); ++it) {
1221 auto internal = qobject_cast<InternalWindow *>(*it);
1222 if (!internal) {
1223 continue;
1224 }
1225 if (QWindow *w = internal->handle()) {
1226 if (!w->isVisible()) {
1227 continue;
1228 }
1229 if (!workspace()->geometry().contains(w->geometry())) {
1230 continue;
1231 }
1232 if (w->property("_q_showWithoutActivating").toBool()) {
1233 continue;
1234 }
1235 if (w->property("outputOnly").toBool()) {
1236 continue;
1237 }
1238 if (w->flags().testFlag(Qt::ToolTip)) {
1239 continue;
1240 }
1241 found = w;
1242 break;
1243 }
1244 }
1245 if (QGuiApplication::focusWindow() != found) {
1246#if QT_VERSION < QT_VERSION_CHECK(6, 7, 0)
1247 QWindowSystemInterface::handleWindowActivated(found);
1248#else
1249 QWindowSystemInterface::handleFocusWindowChanged(found);
1250#endif
1251 }
1252 if (!found) {
1253 return false;
1254 }
1255 auto xkb = input()->keyboard()->xkb();
1256 Qt::Key key = xkb->toQtKey(xkb->toKeysym(event->nativeScanCode()),
1257 event->nativeScanCode(),
1258 Qt::KeyboardModifiers(),
1259 true /* workaround for QTBUG-62102 */);
1260 QKeyEvent internalEvent(event->type(), key,
1261 event->modifiers(), event->nativeScanCode(), event->nativeVirtualKey(),
1262 event->nativeModifiers(), event->text());
1263 internalEvent.setAccepted(false);
1264 if (QCoreApplication::sendEvent(found, &internalEvent)) {
1266 passToWaylandServer(event);
1267 return true;
1268 }
1269 return false;
1270 }
1271
1272 bool touchDown(qint32 id, const QPointF &pos, std::chrono::microseconds time) override
1273 {
1274 auto seat = waylandServer()->seat();
1275 if (seat->isTouchSequence()) {
1276 // something else is getting the events
1277 return false;
1278 }
1279 auto touch = input()->touch();
1280 if (touch->internalPressId() != -1) {
1281 // already on internal window, ignore further touch points, but filter out
1282 m_pressedIds.insert(id);
1283 return true;
1284 }
1285 // a new touch point
1286 seat->setTimestamp(time);
1287 if (!input()->touch()->focus() || !input()->touch()->focus()->isInternal()) {
1288 return false;
1289 }
1290 touch->setInternalPressId(id);
1291 // Qt's touch event API is rather complex, let's do fake mouse events instead
1292 QWindow *internal = static_cast<InternalWindow *>(input()->touch()->focus())->handle();
1293 m_lastGlobalTouchPos = pos;
1294 m_lastLocalTouchPos = pos - internal->position();
1295
1296 QEnterEvent enterEvent(m_lastLocalTouchPos, m_lastLocalTouchPos, pos);
1297 QCoreApplication::sendEvent(internal, &enterEvent);
1298
1299 QMouseEvent e(QEvent::MouseButtonPress, m_lastLocalTouchPos, pos, Qt::LeftButton, Qt::LeftButton, input()->keyboardModifiers());
1300 e.setAccepted(false);
1301 QCoreApplication::sendEvent(internal, &e);
1302 return true;
1303 }
1304 bool touchMotion(qint32 id, const QPointF &pos, std::chrono::microseconds time) override
1305 {
1306 auto touch = input()->touch();
1307 if (!input()->touch()->focus() || !input()->touch()->focus()->isInternal()) {
1308 return false;
1309 }
1310 if (touch->internalPressId() == -1) {
1311 return false;
1312 }
1313 waylandServer()->seat()->setTimestamp(time);
1314 if (touch->internalPressId() != qint32(id) || m_pressedIds.contains(id)) {
1315 // ignore, but filter out
1316 return true;
1317 }
1318 QWindow *internal = static_cast<InternalWindow *>(input()->touch()->focus())->handle();
1319 m_lastGlobalTouchPos = pos;
1320 m_lastLocalTouchPos = pos - QPointF(internal->x(), internal->y());
1321
1322 QMouseEvent e(QEvent::MouseMove, m_lastLocalTouchPos, m_lastGlobalTouchPos, Qt::LeftButton, Qt::LeftButton, input()->keyboardModifiers());
1323 QCoreApplication::instance()->sendEvent(internal, &e);
1324 return true;
1325 }
1326 bool touchUp(qint32 id, std::chrono::microseconds time) override
1327 {
1328 auto touch = input()->touch();
1329 const bool removed = m_pressedIds.remove(id);
1330 if (touch->internalPressId() == -1) {
1331 return removed;
1332 }
1333 waylandServer()->seat()->setTimestamp(time);
1334 if (touch->internalPressId() != qint32(id)) {
1335 // ignore, but filter out
1336 return true;
1337 }
1338 if (!input()->touch()->focus() || !input()->touch()->focus()->isInternal()) {
1339 return removed;
1340 }
1341 QWindow *internal = static_cast<InternalWindow *>(input()->touch()->focus())->handle();
1342 // send mouse up
1343 QMouseEvent e(QEvent::MouseButtonRelease, m_lastLocalTouchPos, m_lastGlobalTouchPos, Qt::LeftButton, Qt::MouseButtons(), input()->keyboardModifiers());
1344 e.setAccepted(false);
1345 QCoreApplication::sendEvent(internal, &e);
1346
1347 QEvent leaveEvent(QEvent::Leave);
1348 QCoreApplication::sendEvent(internal, &leaveEvent);
1349
1350 m_lastGlobalTouchPos = QPointF();
1351 m_lastLocalTouchPos = QPointF();
1352 input()->touch()->setInternalPressId(-1);
1353 return true;
1354 }
1355
1356private:
1357 QSet<qint32> m_pressedIds;
1358 QPointF m_lastGlobalTouchPos;
1359 QPointF m_lastLocalTouchPos;
1360};
1361
1363{
1364public:
1366 {
1367 m_scrollV120 += event->deltaV120();
1368 m_scrollDistance += event->delta();
1369 if (std::abs(m_scrollV120) >= 120 || (!event->deltaV120() && std::abs(m_scrollDistance) >= 15)) {
1370 float ret = m_scrollDistance;
1371 m_scrollV120 = 0;
1372 m_scrollDistance = 0;
1373 return ret;
1374 } else {
1375 return 0;
1376 }
1377 }
1378
1379private:
1380 float m_scrollDistance = 0;
1381 int m_scrollV120 = 0;
1382};
1383
1385{
1386public:
1387 bool pointerEvent(MouseEvent *event, quint32 nativeButton) override
1388 {
1389 auto decoration = input()->pointer()->decoration();
1390 if (!decoration) {
1391 return false;
1392 }
1393 const QPointF p = event->screenPos() - decoration->window()->pos();
1394 switch (event->type()) {
1395 case QEvent::MouseMove: {
1396 QHoverEvent e(QEvent::HoverMove, p, p);
1397 QCoreApplication::instance()->sendEvent(decoration->decoration(), &e);
1398 decoration->window()->processDecorationMove(p, event->screenPos());
1399 return true;
1400 }
1401 case QEvent::MouseButtonPress:
1402 case QEvent::MouseButtonRelease: {
1403 const auto actionResult = performWindowMouseAction(event, decoration->window());
1404 if (actionResult.first) {
1405 return actionResult.second;
1406 }
1407 QMouseEvent e(event->type(), p, event->screenPos(), event->button(), event->buttons(), event->modifiers());
1408 e.setTimestamp(std::chrono::duration_cast<std::chrono::milliseconds>(event->timestamp()).count());
1409 e.setAccepted(false);
1410 QCoreApplication::sendEvent(decoration->decoration(), &e);
1411 if (!e.isAccepted() && event->type() == QEvent::MouseButtonPress) {
1412 decoration->window()->processDecorationButtonPress(&e);
1413 }
1414 if (event->type() == QEvent::MouseButtonRelease) {
1415 decoration->window()->processDecorationButtonRelease(&e);
1416 }
1417 return true;
1418 }
1419 default:
1420 break;
1421 }
1422 return false;
1423 }
1424 bool wheelEvent(WheelEvent *event) override
1425 {
1426 auto decoration = input()->pointer()->decoration();
1427 if (!decoration) {
1428 return false;
1429 }
1430 if (event->angleDelta().y() != 0) {
1431 // client window action only on vertical scrolling
1432 const auto actionResult = performWindowWheelAction(event, decoration->window());
1433 if (actionResult.first) {
1434 return actionResult.second;
1435 }
1436 }
1437 const QPointF localPos = event->globalPosition() - decoration->window()->pos();
1438 const Qt::Orientation orientation = (event->angleDelta().x() != 0) ? Qt::Horizontal : Qt::Vertical;
1439 QWheelEvent e(localPos, event->globalPosition(), QPoint(),
1440 event->angleDelta(),
1441 event->buttons(),
1442 event->modifiers(),
1443 Qt::NoScrollPhase,
1444 false);
1445 e.setAccepted(false);
1446 QCoreApplication::sendEvent(decoration, &e);
1447 if (e.isAccepted()) {
1448 return true;
1449 }
1450 if ((orientation == Qt::Vertical) && decoration->window()->titlebarPositionUnderMouse()) {
1451 if (float delta = m_accumulator.accumulate(event)) {
1452 decoration->window()->performMouseCommand(options->operationTitlebarMouseWheel(delta * -1),
1453 event->globalPosition());
1454 }
1455 }
1456 return true;
1457 }
1458 bool touchDown(qint32 id, const QPointF &pos, std::chrono::microseconds time) override
1459 {
1460 auto seat = waylandServer()->seat();
1461 if (seat->isTouchSequence()) {
1462 return false;
1463 }
1464 if (input()->touch()->decorationPressId() != -1) {
1465 // already on a decoration, ignore further touch points, but filter out
1466 return true;
1467 }
1468 seat->setTimestamp(time);
1469 auto decoration = input()->touch()->decoration();
1470 if (!decoration) {
1471 return false;
1472 }
1473
1475 m_lastGlobalTouchPos = pos;
1476 m_lastLocalTouchPos = pos - decoration->window()->pos();
1477
1478 QHoverEvent hoverEvent(QEvent::HoverMove, m_lastLocalTouchPos, m_lastLocalTouchPos);
1479 QCoreApplication::sendEvent(decoration->decoration(), &hoverEvent);
1480
1481 QMouseEvent e(QEvent::MouseButtonPress, m_lastLocalTouchPos, pos, Qt::LeftButton, Qt::LeftButton, input()->keyboardModifiers());
1482 e.setAccepted(false);
1483 QCoreApplication::sendEvent(decoration->decoration(), &e);
1484 if (!e.isAccepted()) {
1485 decoration->window()->processDecorationButtonPress(&e);
1486 }
1487 return true;
1488 }
1489 bool touchMotion(qint32 id, const QPointF &pos, std::chrono::microseconds time) override
1490 {
1491 auto decoration = input()->touch()->decoration();
1492 if (!decoration) {
1493 return false;
1494 }
1495 if (input()->touch()->decorationPressId() == -1) {
1496 return false;
1497 }
1498 if (input()->touch()->decorationPressId() != qint32(id)) {
1499 // ignore, but filter out
1500 return true;
1501 }
1502 m_lastGlobalTouchPos = pos;
1503 m_lastLocalTouchPos = pos - decoration->window()->pos();
1504
1505 QHoverEvent e(QEvent::HoverMove, m_lastLocalTouchPos, m_lastLocalTouchPos);
1506 QCoreApplication::instance()->sendEvent(decoration->decoration(), &e);
1507 decoration->window()->processDecorationMove(m_lastLocalTouchPos, pos);
1508 return true;
1509 }
1510 bool touchUp(qint32 id, std::chrono::microseconds time) override
1511 {
1512 auto decoration = input()->touch()->decoration();
1513 if (!decoration) {
1514 // can happen when quick tiling
1515 if (input()->touch()->decorationPressId() == id) {
1516 m_lastGlobalTouchPos = QPointF();
1517 m_lastLocalTouchPos = QPointF();
1519 return true;
1520 }
1521 return false;
1522 }
1523 if (input()->touch()->decorationPressId() == -1) {
1524 return false;
1525 }
1526 if (input()->touch()->decorationPressId() != qint32(id)) {
1527 // ignore, but filter out
1528 return true;
1529 }
1530
1531 // send mouse up
1532 QMouseEvent e(QEvent::MouseButtonRelease, m_lastLocalTouchPos, m_lastGlobalTouchPos, Qt::LeftButton, Qt::MouseButtons(), input()->keyboardModifiers());
1533 e.setAccepted(false);
1534 QCoreApplication::sendEvent(decoration->decoration(), &e);
1535 decoration->window()->processDecorationButtonRelease(&e);
1536
1537 QHoverEvent leaveEvent(QEvent::HoverLeave, QPointF(), QPointF());
1538 QCoreApplication::sendEvent(decoration->decoration(), &leaveEvent);
1539
1540 m_lastGlobalTouchPos = QPointF();
1541 m_lastLocalTouchPos = QPointF();
1543 return true;
1544 }
1545 bool tabletToolEvent(TabletEvent *event) override
1546 {
1547 auto decoration = input()->tablet()->decoration();
1548 if (!decoration) {
1549 return false;
1550 }
1551 const QPointF p = event->globalPosF() - decoration->window()->pos();
1552 switch (event->type()) {
1553 case QEvent::TabletMove:
1554 case QEvent::TabletEnterProximity: {
1555 QHoverEvent e(QEvent::HoverMove, p, p);
1556 QCoreApplication::instance()->sendEvent(decoration->decoration(), &e);
1557 decoration->window()->processDecorationMove(p, event->globalPosF());
1558 break;
1559 }
1560 case QEvent::TabletPress:
1561 case QEvent::TabletRelease: {
1562 const bool isPressed = event->type() == QEvent::TabletPress;
1563 QMouseEvent e(isPressed ? QEvent::MouseButtonPress : QEvent::MouseButtonRelease,
1564 p,
1565 event->globalPosF(),
1566 Qt::LeftButton,
1567 isPressed ? Qt::LeftButton : Qt::MouseButtons(),
1569 e.setAccepted(false);
1570 QCoreApplication::sendEvent(decoration->decoration(), &e);
1571 if (!e.isAccepted() && isPressed) {
1572 decoration->window()->processDecorationButtonPress(&e);
1573 }
1574 if (event->type() == QEvent::TabletRelease) {
1575 decoration->window()->processDecorationButtonRelease(&e);
1576 }
1577 break;
1578 }
1579 case QEvent::TabletLeaveProximity: {
1580 QHoverEvent leaveEvent(QEvent::HoverLeave, QPointF(), QPointF());
1581 QCoreApplication::sendEvent(decoration->decoration(), &leaveEvent);
1582 break;
1583 }
1584 default:
1585 break;
1586 }
1587 // Let TabletInputFilter receive the event, so the tablet can be registered and the cursor position can be updated.
1588 return false;
1589 }
1590
1591private:
1592 QPointF m_lastGlobalTouchPos;
1593 QPointF m_lastLocalTouchPos;
1594 MouseWheelAccumulator m_accumulator;
1595};
1596
1597#if KWIN_BUILD_TABBOX
1598class TabBoxInputFilter : public InputEventFilter
1599{
1600public:
1601 bool pointerEvent(MouseEvent *event, quint32 button) override
1602 {
1603 if (!workspace()->tabbox() || !workspace()->tabbox()->isGrabbed()) {
1604 return false;
1605 }
1606 return workspace()->tabbox()->handleMouseEvent(event);
1607 }
1608 bool keyEvent(KeyEvent *event) override
1609 {
1610 if (!workspace()->tabbox() || !workspace()->tabbox()->isGrabbed()) {
1611 return false;
1612 }
1613 auto seat = waylandServer()->seat();
1614 seat->setFocusedKeyboardSurface(nullptr);
1615 input()->pointer()->setEnableConstraints(false);
1616 // pass the key event to the seat, so that it has a proper model of the currently hold keys
1617 // this is important for combinations like alt+shift to ensure that shift is not considered pressed
1618 passToWaylandServer(event);
1619
1620 if (event->type() == QEvent::KeyPress) {
1621 workspace()->tabbox()->keyPress(event->modifiers() | event->key());
1622 } else if (static_cast<KeyEvent *>(event)->modifiersRelevantForGlobalShortcuts() == Qt::NoModifier) {
1623 workspace()->tabbox()->modifiersReleased();
1624 // update keyboard facus if the tabbox no longer grabs keys
1625 if (!workspace()->tabbox() || !workspace()->tabbox()->isGrabbed()) {
1626 input()->keyboard()->update();
1627 }
1628 }
1629 return true;
1630 }
1631 bool wheelEvent(WheelEvent *event) override
1632 {
1633 if (!workspace()->tabbox() || !workspace()->tabbox()->isGrabbed()) {
1634 return false;
1635 }
1636 return workspace()->tabbox()->handleWheelEvent(event);
1637 }
1638};
1639#endif
1640
1642{
1643public:
1644 bool pointerEvent(MouseEvent *event, quint32 nativeButton) override
1645 {
1646 workspace()->screenEdges()->isEntered(event);
1647 // always forward
1648 return false;
1649 }
1650 bool touchDown(qint32 id, const QPointF &pos, std::chrono::microseconds time) override
1651 {
1652 // TODO: better check whether a touch sequence is in progress
1653 if (m_touchInProgress || waylandServer()->seat()->isTouchSequence()) {
1654 // cancel existing touch
1656 m_touchInProgress = false;
1657 m_id = 0;
1658 return false;
1659 }
1660 if (workspace()->screenEdges()->gestureRecognizer()->startSwipeGesture(pos) > 0) {
1661 m_touchInProgress = true;
1662 m_id = id;
1663 m_lastPos = pos;
1664 return true;
1665 }
1666 return false;
1667 }
1668 bool touchMotion(qint32 id, const QPointF &pos, std::chrono::microseconds time) override
1669 {
1670 if (m_touchInProgress && m_id == id) {
1672 m_lastPos = pos;
1673 return true;
1674 }
1675 return false;
1676 }
1677 bool touchUp(qint32 id, std::chrono::microseconds time) override
1678 {
1679 if (m_touchInProgress && m_id == id) {
1681 m_touchInProgress = false;
1682 return true;
1683 }
1684 return false;
1685 }
1686
1687private:
1688 bool m_touchInProgress = false;
1689 qint32 m_id = 0;
1690 QPointF m_lastPos;
1691};
1692
1698{
1699public:
1700 bool pointerEvent(MouseEvent *event, quint32 nativeButton) override
1701 {
1702 if (event->type() != QEvent::MouseButtonPress) {
1703 return false;
1704 }
1705 Window *window = input()->pointer()->focus();
1706 if (!window || !window->isClient()) {
1707 return false;
1708 }
1709 const auto actionResult = performWindowMouseAction(event, window, MouseAction::ModifierAndWindow);
1710 if (actionResult.first) {
1711 return actionResult.second;
1712 }
1713 return false;
1714 }
1715 bool wheelEvent(WheelEvent *event) override
1716 {
1717 if (event->angleDelta().y() == 0) {
1718 // only actions on vertical scroll
1719 return false;
1720 }
1721 Window *window = input()->pointer()->focus();
1722 if (!window || !window->isClient()) {
1723 return false;
1724 }
1725 const auto actionResult = performWindowWheelAction(event, window, MouseAction::ModifierAndWindow);
1726 if (actionResult.first) {
1727 return actionResult.second;
1728 }
1729 return false;
1730 }
1731 bool touchDown(qint32 id, const QPointF &pos, std::chrono::microseconds time) override
1732 {
1733 auto seat = waylandServer()->seat();
1734 if (seat->isTouchSequence()) {
1735 return false;
1736 }
1737 Window *window = input()->touch()->focus();
1738 if (!window || !window->isClient()) {
1739 return false;
1740 }
1741 bool wasAction = false;
1742 const Options::MouseCommand command = window->getMouseCommand(Qt::LeftButton, &wasAction);
1743 if (wasAction) {
1744 return !window->performMouseCommand(command, pos);
1745 }
1746 return false;
1747 }
1748 bool tabletToolEvent(TabletEvent *event) override
1749 {
1750 if (event->type() != QEvent::TabletPress) {
1751 return false;
1752 }
1753 Window *window = input()->tablet()->focus();
1754 if (!window || !window->isClient()) {
1755 return false;
1756 }
1757 bool wasAction = false;
1758 const Options::MouseCommand command = window->getMouseCommand(Qt::LeftButton, &wasAction);
1759 if (wasAction) {
1760 return !window->performMouseCommand(command, event->globalPosF());
1761 }
1762 return false;
1763 }
1764};
1765
1767{
1768public:
1769 bool keyEvent(KeyEvent *event) override
1770 {
1771 return passToInputMethod(event);
1772 }
1773};
1774
1779{
1780public:
1781 bool pointerEvent(MouseEvent *event, quint32 nativeButton) override
1782 {
1783 auto seat = waylandServer()->seat();
1784 seat->setTimestamp(event->timestamp());
1785 switch (event->type()) {
1786 case QEvent::MouseMove: {
1787 seat->notifyPointerMotion(event->globalPosition());
1788 MouseEvent *e = static_cast<MouseEvent *>(event);
1789 if (!e->delta().isNull()) {
1790 seat->relativePointerMotion(e->delta(), e->deltaUnaccelerated(), e->timestamp());
1791 }
1792 break;
1793 }
1794 case QEvent::MouseButtonPress:
1795 seat->notifyPointerButton(nativeButton, PointerButtonState::Pressed);
1796 break;
1797 case QEvent::MouseButtonRelease:
1798 seat->notifyPointerButton(nativeButton, PointerButtonState::Released);
1799 break;
1800 default:
1801 break;
1802 }
1803 return true;
1804 }
1805 bool pointerFrame() override
1806 {
1807 auto seat = waylandServer()->seat();
1808 seat->notifyPointerFrame();
1809 return true;
1810 }
1811 bool wheelEvent(WheelEvent *event) override
1812 {
1813 auto seat = waylandServer()->seat();
1814 seat->setTimestamp(event->timestamp());
1815 auto _event = static_cast<WheelEvent *>(event);
1816 seat->notifyPointerAxis(_event->orientation(), _event->delta(), _event->deltaV120(),
1817 kwinAxisSourceToKWaylandAxisSource(_event->axisSource()),
1819 return true;
1820 }
1821 bool keyEvent(KeyEvent *event) override
1822 {
1823 if (event->isAutoRepeat()) {
1824 // handled by Wayland client
1825 return false;
1826 }
1827 auto seat = waylandServer()->seat();
1828 input()->keyboard()->update();
1829 seat->setTimestamp(event->timestamp());
1830 passToWaylandServer(event);
1831 return true;
1832 }
1833 bool touchDown(qint32 id, const QPointF &pos, std::chrono::microseconds time) override
1834 {
1835 auto seat = waylandServer()->seat();
1836 seat->setTimestamp(time);
1837 seat->notifyTouchDown(id, pos);
1838 return true;
1839 }
1840 bool touchMotion(qint32 id, const QPointF &pos, std::chrono::microseconds time) override
1841 {
1842 auto seat = waylandServer()->seat();
1843 seat->setTimestamp(time);
1844 seat->notifyTouchMotion(id, pos);
1845 return true;
1846 }
1847 bool touchUp(qint32 id, std::chrono::microseconds time) override
1848 {
1849 auto seat = waylandServer()->seat();
1850 seat->setTimestamp(time);
1851 seat->notifyTouchUp(id);
1852 return true;
1853 }
1854 bool touchCancel() override
1855 {
1857 return true;
1858 }
1859 bool touchFrame() override
1860 {
1862 return true;
1863 }
1864 bool pinchGestureBegin(int fingerCount, std::chrono::microseconds time) override
1865 {
1866 auto seat = waylandServer()->seat();
1867 seat->setTimestamp(time);
1868 seat->startPointerPinchGesture(fingerCount);
1869 return true;
1870 }
1871 bool pinchGestureUpdate(qreal scale, qreal angleDelta, const QPointF &delta, std::chrono::microseconds time) override
1872 {
1873 auto seat = waylandServer()->seat();
1874 seat->setTimestamp(time);
1875 seat->updatePointerPinchGesture(delta, scale, angleDelta);
1876 return true;
1877 }
1878 bool pinchGestureEnd(std::chrono::microseconds time) override
1879 {
1880 auto seat = waylandServer()->seat();
1881 seat->setTimestamp(time);
1882 seat->endPointerPinchGesture();
1883 return true;
1884 }
1885 bool pinchGestureCancelled(std::chrono::microseconds time) override
1886 {
1887 auto seat = waylandServer()->seat();
1888 seat->setTimestamp(time);
1889 seat->cancelPointerPinchGesture();
1890 return true;
1891 }
1892
1893 bool swipeGestureBegin(int fingerCount, std::chrono::microseconds time) override
1894 {
1895 auto seat = waylandServer()->seat();
1896 seat->setTimestamp(time);
1897 seat->startPointerSwipeGesture(fingerCount);
1898 return true;
1899 }
1900 bool swipeGestureUpdate(const QPointF &delta, std::chrono::microseconds time) override
1901 {
1902 auto seat = waylandServer()->seat();
1903 seat->setTimestamp(time);
1904 seat->updatePointerSwipeGesture(delta);
1905 return true;
1906 }
1907 bool swipeGestureEnd(std::chrono::microseconds time) override
1908 {
1909 auto seat = waylandServer()->seat();
1910 seat->setTimestamp(time);
1911 seat->endPointerSwipeGesture();
1912 return true;
1913 }
1914 bool swipeGestureCancelled(std::chrono::microseconds time) override
1915 {
1916 auto seat = waylandServer()->seat();
1917 seat->setTimestamp(time);
1918 seat->cancelPointerSwipeGesture();
1919 return true;
1920 }
1921 bool holdGestureBegin(int fingerCount, std::chrono::microseconds time) override
1922 {
1923 auto seat = waylandServer()->seat();
1924 seat->setTimestamp(time);
1925 seat->startPointerHoldGesture(fingerCount);
1926 return true;
1927 }
1928 bool holdGestureEnd(std::chrono::microseconds time) override
1929 {
1930 auto seat = waylandServer()->seat();
1931 seat->setTimestamp(time);
1932 seat->endPointerHoldGesture();
1933 return true;
1934 }
1935 bool holdGestureCancelled(std::chrono::microseconds time) override
1936 {
1937 auto seat = waylandServer()->seat();
1938 seat->setTimestamp(time);
1939 seat->cancelPointerHoldGesture();
1940 return true;
1941 }
1942};
1943
1944static SeatInterface *findSeat()
1945{
1946 auto server = waylandServer();
1947 if (!server) {
1948 return nullptr;
1949 }
1950 return server->seat();
1951}
1952
1953class SurfaceCursor : public Cursor
1954{
1955public:
1957 : Cursor()
1958 {
1959 setParent(tool);
1960 connect(tool, &TabletToolV2Interface::cursorChanged, this, [this](const TabletCursorSourceV2 &cursor) {
1961 if (auto surfaceCursor = std::get_if<TabletSurfaceCursorV2 *>(&cursor)) {
1962 // If the cursor is unset, fallback to the cross cursor.
1963 if ((*surfaceCursor) && (*surfaceCursor)->enteredSerial()) {
1964 if (!m_surfaceSource) {
1965 m_surfaceSource = std::make_unique<SurfaceCursorSource>();
1966 }
1967 m_surfaceSource->update((*surfaceCursor)->surface(), (*surfaceCursor)->hotspot());
1968 setSource(m_surfaceSource.get());
1969 return;
1970 }
1971 }
1972
1973 QByteArray shape;
1974 if (auto shapeCursor = std::get_if<QByteArray>(&cursor)) {
1975 shape = *shapeCursor;
1976 } else {
1977 shape = QByteArrayLiteral("cross");
1978 }
1979
1980 static WaylandCursorImage defaultCursor;
1981 if (!m_shapeSource) {
1982 m_shapeSource = std::make_unique<ShapeCursorSource>();
1983 }
1984 m_shapeSource->setTheme(defaultCursor.theme());
1985 m_shapeSource->setShape(shape);
1986 setSource(m_shapeSource.get());
1987 });
1988 }
1989
1990private:
1991 std::unique_ptr<ShapeCursorSource> m_shapeSource;
1992 std::unique_ptr<SurfaceCursorSource> m_surfaceSource;
1993};
1994
1998class TabletInputFilter : public QObject, public InputEventFilter
1999{
2000public:
2002 {
2003 const auto devices = input()->devices();
2004 for (InputDevice *device : devices) {
2005 integrateDevice(device);
2006 }
2007 connect(input(), &InputRedirection::deviceAdded, this, &TabletInputFilter::integrateDevice);
2008 connect(input(), &InputRedirection::deviceRemoved, this, &TabletInputFilter::removeDevice);
2009
2010 auto tabletNextOutput = new QAction(this);
2011 tabletNextOutput->setProperty("componentName", QStringLiteral("kwin"));
2012 tabletNextOutput->setText(i18n("Move the tablet to the next output"));
2013 tabletNextOutput->setObjectName(QStringLiteral("Move Tablet to Next Output"));
2014 KGlobalAccel::setGlobalShortcut(tabletNextOutput, QList<QKeySequence>());
2015 connect(tabletNextOutput, &QAction::triggered, this, &TabletInputFilter::trackNextOutput);
2016 }
2017
2019 {
2020 auto server = waylandServer();
2021 if (!server) {
2022 return nullptr;
2023 }
2024 TabletManagerV2Interface *manager = server->tabletManagerV2();
2025 return manager->seat(findSeat());
2026 }
2027
2028 void integrateDevice(InputDevice *inputDevice)
2029 {
2030 auto device = qobject_cast<LibInput::Device *>(inputDevice);
2031 if (!device || (!device->isTabletTool() && !device->isTabletPad())) {
2032 return;
2033 }
2034
2035 TabletSeatV2Interface *tabletSeat = findTabletSeat();
2036 if (!tabletSeat) {
2037 qCCritical(KWIN_CORE) << "Could not find tablet seat";
2038 return;
2039 }
2040 struct udev_device *const udev_device = libinput_device_get_udev_device(device->device());
2041 const char *devnode = udev_device_get_syspath(udev_device);
2042
2043 auto deviceGroup = libinput_device_get_device_group(device->device());
2044 auto tablet = static_cast<TabletV2Interface *>(libinput_device_group_get_user_data(deviceGroup));
2045 if (!tablet) {
2046 tablet = tabletSeat->addTablet(device->vendor(), device->product(), device->sysName(), device->name(), {QString::fromUtf8(devnode)});
2047 libinput_device_group_set_user_data(deviceGroup, tablet);
2048 }
2049
2050 if (device->isTabletPad()) {
2051 const int buttonsCount = libinput_device_tablet_pad_get_num_buttons(device->device());
2052 const int ringsCount = libinput_device_tablet_pad_get_num_rings(device->device());
2053 const int stripsCount = libinput_device_tablet_pad_get_num_strips(device->device());
2054 const int modes = libinput_device_tablet_pad_get_num_mode_groups(device->device());
2055
2056 auto firstGroup = libinput_device_tablet_pad_get_mode_group(device->device(), 0);
2057 tabletSeat->addTabletPad(device->sysName(), device->name(), {QString::fromUtf8(devnode)}, buttonsCount, ringsCount, stripsCount, modes, libinput_tablet_pad_mode_group_get_mode(firstGroup), tablet);
2058 }
2059 }
2060
2061 static void trackNextOutput()
2062 {
2063 const auto outputs = workspace()->outputs();
2064 if (outputs.isEmpty()) {
2065 return;
2066 }
2067
2068 int tabletToolCount = 0;
2069 InputDevice *changedDevice = nullptr;
2070 const auto devices = input()->devices();
2071 for (const auto device : devices) {
2072 if (!device->isTabletTool()) {
2073 continue;
2074 }
2075
2076 tabletToolCount++;
2077 if (device->outputName().isEmpty()) {
2078 device->setOutputName(outputs.constFirst()->name());
2079 changedDevice = device;
2080 continue;
2081 }
2082
2083 auto it = std::find_if(outputs.begin(), outputs.end(), [device](const auto &output) {
2084 return output->name() == device->outputName();
2085 });
2086 ++it;
2087 auto nextOutput = it == outputs.end() ? outputs.first() : *it;
2088 device->setOutputName(nextOutput->name());
2089 changedDevice = device;
2090 }
2091 const QString message = tabletToolCount == 1 ? i18n("Tablet moved to %1", changedDevice->outputName()) : i18n("Tablets switched outputs");
2092 OSD::show(message, QStringLiteral("input-tablet"), 5000);
2093 }
2094
2095 void removeDevice(InputDevice *inputDevice)
2096 {
2097 auto device = qobject_cast<LibInput::Device *>(inputDevice);
2098 if (device) {
2099 auto deviceGroup = libinput_device_get_device_group(device->device());
2100 libinput_device_group_set_user_data(deviceGroup, nullptr);
2101
2102 TabletSeatV2Interface *tabletSeat = findTabletSeat();
2103 if (tabletSeat) {
2104 tabletSeat->removeDevice(device->sysName());
2105 } else {
2106 qCCritical(KWIN_CORE) << "Could not find tablet to remove" << device->sysName();
2107 }
2108 }
2109 }
2110
2112 {
2113 using Type = TabletToolV2Interface::Type;
2114 switch (tabletToolId.m_toolType) {
2115 case InputRedirection::Pen:
2116 return Type::Pen;
2117 case InputRedirection::Eraser:
2118 return Type::Eraser;
2119 case InputRedirection::Brush:
2120 return Type::Brush;
2121 case InputRedirection::Pencil:
2122 return Type::Pencil;
2123 case InputRedirection::Airbrush:
2124 return Type::Airbrush;
2125 case InputRedirection::Finger:
2126 return Type::Finger;
2127 case InputRedirection::Mouse:
2128 return Type::Mouse;
2129 case InputRedirection::Lens:
2130 return Type::Lens;
2131 case InputRedirection::Totem:
2132 return Type::Totem;
2133 }
2134 return Type::Pen;
2135 }
2136
2138 {
2139 TabletSeatV2Interface *tabletSeat = findTabletSeat();
2140
2141 const auto f = [](InputRedirection::Capability cap) {
2142 switch (cap) {
2143 case InputRedirection::Tilt:
2144 return TabletToolV2Interface::Tilt;
2145 case InputRedirection::Pressure:
2146 return TabletToolV2Interface::Pressure;
2147 case InputRedirection::Distance:
2148 return TabletToolV2Interface::Distance;
2149 case InputRedirection::Rotation:
2150 return TabletToolV2Interface::Rotation;
2151 case InputRedirection::Slider:
2152 return TabletToolV2Interface::Slider;
2153 case InputRedirection::Wheel:
2154 return TabletToolV2Interface::Wheel;
2155 }
2156 return TabletToolV2Interface::Wheel;
2157 };
2158 QList<TabletToolV2Interface::Capability> ifaceCapabilities;
2159 ifaceCapabilities.resize(tabletToolId.m_capabilities.size());
2160 std::transform(tabletToolId.m_capabilities.constBegin(), tabletToolId.m_capabilities.constEnd(), ifaceCapabilities.begin(), f);
2161
2162 TabletToolV2Interface *tool = tabletSeat->addTool(getType(tabletToolId), tabletToolId.m_serialId, tabletToolId.m_uniqueId, ifaceCapabilities, tabletToolId.deviceSysName);
2163
2164 const auto cursor = new SurfaceCursor(tool);
2165 Cursors::self()->addCursor(cursor);
2166 m_cursorByTool[tool] = cursor;
2167
2168 return tool;
2169 }
2170
2171 bool tabletToolEvent(TabletEvent *event) override
2172 {
2173 if (!workspace()) {
2174 return false;
2175 }
2176
2177 TabletSeatV2Interface *tabletSeat = findTabletSeat();
2178 if (!tabletSeat) {
2179 qCCritical(KWIN_CORE) << "Could not find tablet manager";
2180 return false;
2181 }
2182 auto tool = tabletSeat->toolByHardwareSerial(event->tabletId().m_serialId, getType(event->tabletId()));
2183 if (!tool) {
2184 tool = createTool(event->tabletId());
2185 }
2186
2187 // NOTE: tablet will be nullptr as the device is removed (see ::removeDevice) but events from the tool
2188 // may still happen (e.g. Release or ProximityOut events)
2189 auto tablet = static_cast<TabletV2Interface *>(event->tabletId().m_deviceGroupData);
2190
2191 Window *window = input()->findToplevel(event->globalPosF());
2192 if (!window || !window->surface()) {
2193 return false;
2194 }
2195
2196 SurfaceInterface *surface = window->surface();
2197 tool->setCurrentSurface(surface);
2198
2199 if (!tool->isClientSupported() || (tablet && !tablet->isSurfaceSupported(surface))) {
2200 return emulateTabletEvent(event);
2201 }
2202
2203 switch (event->type()) {
2204 case QEvent::TabletMove: {
2205 const auto pos = window->mapToLocal(event->globalPosF());
2206 tool->sendMotion(pos);
2207 m_cursorByTool[tool]->setPos(event->globalPosF());
2208 break;
2209 }
2210 case QEvent::TabletEnterProximity: {
2211 const QPointF pos = event->globalPosF();
2212 m_cursorByTool[tool]->setPos(pos);
2213 tool->sendProximityIn(tablet);
2214 tool->sendMotion(window->mapToLocal(event->globalPosF()));
2215 break;
2216 }
2217 case QEvent::TabletLeaveProximity:
2218 tool->sendProximityOut();
2219 break;
2220 case QEvent::TabletPress: {
2221 const auto pos = window->mapToLocal(event->globalPosF());
2222 tool->sendMotion(pos);
2223 m_cursorByTool[tool]->setPos(event->globalPosF());
2224 tool->sendDown();
2225 break;
2226 }
2227 case QEvent::TabletRelease:
2228 tool->sendUp();
2229 break;
2230 default:
2231 qCWarning(KWIN_CORE) << "Unexpected tablet event type" << event;
2232 break;
2233 }
2234 const quint32 MAX_VAL = 65535;
2235
2236 if (tool->hasCapability(TabletToolV2Interface::Pressure)) {
2237 tool->sendPressure(MAX_VAL * event->pressure());
2238 }
2239 if (tool->hasCapability(TabletToolV2Interface::Tilt)) {
2240 tool->sendTilt(event->xTilt(), event->yTilt());
2241 }
2242 if (tool->hasCapability(TabletToolV2Interface::Rotation)) {
2243 tool->sendRotation(event->rotation());
2244 }
2245
2246 tool->sendFrame(event->timestamp());
2247 return true;
2248 }
2249
2251 {
2252 if (!workspace()) {
2253 return false;
2254 }
2255
2256 switch (event->type()) {
2257 case QEvent::TabletMove:
2258 case QEvent::TabletEnterProximity:
2259 input()->pointer()->processMotionAbsolute(event->globalPosF(), std::chrono::milliseconds(event->timestamp()));
2260 break;
2261 case QEvent::TabletPress:
2262 input()->pointer()->processButton(qtMouseButtonToButton(Qt::LeftButton),
2263 InputRedirection::PointerButtonPressed, std::chrono::milliseconds(event->timestamp()));
2264 break;
2265 case QEvent::TabletRelease:
2266 input()->pointer()->processButton(qtMouseButtonToButton(Qt::LeftButton),
2267 InputRedirection::PointerButtonReleased, std::chrono::milliseconds(event->timestamp()));
2268 break;
2269 case QEvent::TabletLeaveProximity:
2270 break;
2271 default:
2272 qCWarning(KWIN_CORE) << "Unexpected tablet event type" << event;
2273 break;
2274 }
2275 return true;
2276 }
2277
2278 bool tabletToolButtonEvent(uint button, bool pressed, const TabletToolId &tabletToolId, std::chrono::microseconds time) override
2279 {
2280 TabletSeatV2Interface *tabletSeat = findTabletSeat();
2281 auto tool = tabletSeat->toolByHardwareSerial(tabletToolId.m_serialId, getType(tabletToolId));
2282 if (!tool) {
2283 tool = createTool(tabletToolId);
2284 }
2285 if (!tool->isClientSupported()) {
2286 return false;
2287 }
2288 tool->sendButton(button, pressed);
2289 return true;
2290 }
2291
2293 {
2294 Window *window = workspace()->activeWindow();
2295 auto seat = findTabletSeat();
2296 if (!window || !window->surface() || !seat->isClientSupported(window->surface()->client())) {
2297 return nullptr;
2298 }
2299
2300 auto tablet = static_cast<TabletV2Interface *>(tabletPadId.data);
2301 SurfaceInterface *surface = window->surface();
2302 auto pad = tablet->pad();
2303 if (!pad) {
2304 return nullptr;
2305 }
2306 pad->setCurrentSurface(surface, tablet);
2307 return pad;
2308 }
2309
2310 bool tabletPadButtonEvent(uint button, bool pressed, const TabletPadId &tabletPadId, std::chrono::microseconds time) override
2311 {
2312 auto pad = findAndAdoptPad(tabletPadId);
2313 if (!pad) {
2314 return false;
2315 }
2316 pad->sendButton(time, button, pressed);
2317 return true;
2318 }
2319
2320 bool tabletPadRingEvent(int number, int angle, bool isFinger, const TabletPadId &tabletPadId, std::chrono::microseconds time) override
2321 {
2322 auto pad = findAndAdoptPad(tabletPadId);
2323 if (!pad) {
2324 return false;
2325 }
2326 auto ring = pad->ring(number);
2327
2328 ring->sendAngle(angle);
2329 if (isFinger) {
2330 ring->sendSource(TabletPadRingV2Interface::SourceFinger);
2331 }
2332 ring->sendFrame(std::chrono::duration_cast<std::chrono::milliseconds>(time).count());
2333 return true;
2334 }
2335
2336 bool tabletPadStripEvent(int number, int position, bool isFinger, const TabletPadId &tabletPadId, std::chrono::microseconds time) override
2337 {
2338 auto pad = findAndAdoptPad(tabletPadId);
2339 if (!pad) {
2340 return false;
2341 }
2342 auto strip = pad->strip(number);
2343
2344 strip->sendPosition(position);
2345 if (isFinger) {
2346 strip->sendSource(TabletPadStripV2Interface::SourceFinger);
2347 }
2348 strip->sendFrame(std::chrono::duration_cast<std::chrono::milliseconds>(time).count());
2349 return true;
2350 }
2351
2352 QHash<TabletToolV2Interface *, Cursor *> m_cursorByTool;
2353};
2354
2355static AbstractDropHandler *dropHandler(Window *window)
2356{
2357 auto surface = window->surface();
2358 if (!surface) {
2359 return nullptr;
2360 }
2361 auto seat = waylandServer()->seat();
2362 auto dropTarget = seat->dropHandlerForSurface(surface);
2363 if (dropTarget) {
2364 return dropTarget;
2365 }
2366
2367 if (qobject_cast<X11Window *>(window) && kwinApp()->xwayland()) {
2368 return kwinApp()->xwayland()->xwlDropHandler();
2369 }
2370
2371 return nullptr;
2372}
2373
2374class DragAndDropInputFilter : public QObject, public InputEventFilter
2375{
2376 Q_OBJECT
2377public:
2379 {
2380 m_raiseTimer.setSingleShot(true);
2381 m_raiseTimer.setInterval(1000);
2382 connect(&m_raiseTimer, &QTimer::timeout, this, &DragAndDropInputFilter::raiseDragTarget);
2383
2384 connect(waylandServer()->seat(), &SeatInterface::dragEnded, this, [this] {
2385 if (!m_currentToplevelDragWindow) {
2386 return;
2387 }
2388 m_currentToplevelDragWindow->setKeepAbove(m_wasKeepAbove);
2389 workspace()->takeActivity(m_currentToplevelDragWindow, Workspace::ActivityFlag::ActivityFocus | Workspace::ActivityFlag::ActivityRaise);
2390 m_currentToplevelDragWindow = nullptr;
2391 });
2392 }
2393
2394 bool pointerEvent(MouseEvent *event, quint32 nativeButton) override
2395 {
2396 auto seat = waylandServer()->seat();
2397 if (!seat->isDragPointer()) {
2398 return false;
2399 }
2400 if (seat->isDragTouch()) {
2401 return true;
2402 }
2403 seat->setTimestamp(event->timestamp());
2404 switch (event->type()) {
2405 case QEvent::MouseMove: {
2406 const auto pos = input()->globalPointer();
2407
2408 if (seat->xdgTopleveldrag()) {
2409 dragToplevel(pos, seat->xdgTopleveldrag());
2410 }
2411
2412 seat->notifyPointerMotion(pos);
2413
2414 Window *dragTarget = pickDragTarget(pos);
2415 if (dragTarget) {
2416 if (dragTarget != m_dragTarget) {
2417 workspace()->takeActivity(dragTarget, Workspace::ActivityFlag::ActivityFocus);
2418 m_raiseTimer.start();
2419 }
2420 if ((pos - m_lastPos).manhattanLength() > 10) {
2421 m_lastPos = pos;
2422 // reset timer to delay raising the window
2423 m_raiseTimer.start();
2424 }
2425 }
2426 m_dragTarget = dragTarget;
2427
2428 if (auto *xwl = kwinApp()->xwayland()) {
2429 const auto ret = xwl->dragMoveFilter(dragTarget);
2430 if (ret == Xwl::DragEventReply::Ignore) {
2431 return false;
2432 } else if (ret == Xwl::DragEventReply::Take) {
2433 break;
2434 }
2435 }
2436
2437 if (dragTarget) {
2438 // TODO: consider decorations
2439 if (dragTarget->surface() != seat->dragSurface()) {
2440 seat->setDragTarget(dropHandler(dragTarget), dragTarget->surface(), dragTarget->inputTransformation());
2441 }
2442 } else {
2443 // no window at that place, if we have a surface we need to reset
2444 seat->setDragTarget(nullptr, nullptr);
2445 m_dragTarget = nullptr;
2446 }
2447 break;
2448 }
2449 case QEvent::MouseButtonPress:
2450 seat->notifyPointerButton(nativeButton, PointerButtonState::Pressed);
2451 break;
2452 case QEvent::MouseButtonRelease:
2453 raiseDragTarget();
2454 m_dragTarget = nullptr;
2455 seat->notifyPointerButton(nativeButton, PointerButtonState::Released);
2456 break;
2457 default:
2458 break;
2459 }
2460 // TODO: should we pass through effects?
2461 return true;
2462 }
2463
2464 bool pointerFrame() override
2465 {
2466 auto seat = waylandServer()->seat();
2467 if (!seat->isDragPointer()) {
2468 return false;
2469 }
2470 if (seat->isDragTouch()) {
2471 return true;
2472 }
2473
2474 seat->notifyPointerFrame();
2475 return true;
2476 }
2477
2478 bool touchDown(qint32 id, const QPointF &pos, std::chrono::microseconds time) override
2479 {
2480 auto seat = waylandServer()->seat();
2481 if (seat->isDragPointer()) {
2482 return true;
2483 }
2484 if (!seat->isDragTouch()) {
2485 return false;
2486 }
2487 if (m_touchId != id) {
2488 return true;
2489 }
2490 seat->setTimestamp(time);
2491 seat->notifyTouchDown(id, pos);
2492 m_lastPos = pos;
2493 return true;
2494 }
2495 bool touchMotion(qint32 id, const QPointF &pos, std::chrono::microseconds time) override
2496 {
2497 auto seat = waylandServer()->seat();
2498 if (seat->isDragPointer()) {
2499 return true;
2500 }
2501 if (!seat->isDragTouch()) {
2502 return false;
2503 }
2504 if (m_touchId < 0) {
2505 // We take for now the first id appearing as a move after a drag
2506 // started. We can optimize by specifying the id the drag is
2507 // associated with by implementing a key-value getter in KWayland.
2508 m_touchId = id;
2509 }
2510 if (m_touchId != id) {
2511 return true;
2512 }
2513
2514 if (seat->xdgTopleveldrag()) {
2515 dragToplevel(pos, seat->xdgTopleveldrag());
2516 }
2517
2518 seat->setTimestamp(time);
2519 seat->notifyTouchMotion(id, pos);
2520
2521 if (Window *t = pickDragTarget(pos)) {
2522 // TODO: consider decorations
2523 if (t->surface() != seat->dragSurface()) {
2524 if ((m_dragTarget = static_cast<Window *>(t->isClient() ? t : nullptr))) {
2525 workspace()->takeActivity(m_dragTarget, Workspace::ActivityFlag::ActivityFocus);
2526 m_raiseTimer.start();
2527 }
2528 seat->setDragTarget(dropHandler(t), t->surface(), pos, t->inputTransformation());
2529 }
2530 if ((pos - m_lastPos).manhattanLength() > 10) {
2531 m_lastPos = pos;
2532 // reset timer to delay raising the window
2533 m_raiseTimer.start();
2534 }
2535 } else {
2536 // no window at that place, if we have a surface we need to reset
2537 seat->setDragTarget(nullptr, nullptr);
2538 m_dragTarget = nullptr;
2539 }
2540 return true;
2541 }
2542 bool touchUp(qint32 id, std::chrono::microseconds time) override
2543 {
2544 auto seat = waylandServer()->seat();
2545 if (!seat->isDragTouch()) {
2546 return false;
2547 }
2548 seat->setTimestamp(time);
2549 seat->notifyTouchUp(id);
2550 if (m_touchId == id) {
2551 m_touchId = -1;
2552 raiseDragTarget();
2553 }
2554 return true;
2555 }
2556 bool keyEvent(KeyEvent *event) override
2557 {
2558 if (event->key() != Qt::Key_Escape) {
2559 return false;
2560 }
2561
2562 auto seat = waylandServer()->seat();
2563 if (!seat->isDrag()) {
2564 return false;
2565 }
2566 seat->setTimestamp(event->timestamp());
2567
2568 seat->cancelDrag();
2569
2570 return true;
2571 }
2572
2573private:
2574 void raiseDragTarget()
2575 {
2576 m_raiseTimer.stop();
2577 if (m_dragTarget) {
2578 workspace()->takeActivity(m_dragTarget, Workspace::ActivityFlag::ActivityRaise);
2579 }
2580 }
2581
2582 Window *pickDragTarget(const QPointF &pos) const
2583 {
2584 const QList<Window *> stacking = workspace()->stackingOrder();
2585 if (stacking.isEmpty()) {
2586 return nullptr;
2587 }
2588 auto it = stacking.end();
2589 do {
2590 --it;
2591 Window *window = (*it);
2592 if (auto toplevelDrag = waylandServer()->seat()->xdgTopleveldrag(); toplevelDrag && toplevelDrag->toplevel() && toplevelDrag->toplevel()->surface() == window->surface()) {
2593 continue;
2594 }
2595 if (window->isDeleted()) {
2596 continue;
2597 }
2598 if (!window->isClient()) {
2599 continue;
2600 }
2601 if (!window->isOnCurrentActivity() || !window->isOnCurrentDesktop() || window->isMinimized() || window->isHidden() || window->isHiddenByShowDesktop()) {
2602 continue;
2603 }
2604 if (!window->readyForPainting()) {
2605 continue;
2606 }
2607 if (window->hitTest(pos)) {
2608 return window;
2609 }
2610 } while (it != stacking.begin());
2611 return nullptr;
2612 }
2613
2614 void dragToplevel(const QPointF &pos, const XdgToplevelDragV1Interface *toplevelDrag)
2615 {
2616
2617 auto window = toplevelDrag->toplevel() ? waylandServer()->findWindow(toplevelDrag->toplevel()->surface()) : nullptr;
2618
2619 if (m_currentToplevelDragWindow != window) {
2620 if (m_currentToplevelDragWindow) {
2621 m_currentToplevelDragWindow->setKeepAbove(m_wasKeepAbove);
2622 }
2623 m_currentToplevelDragWindow = window;
2624 if (window) {
2625 m_wasKeepAbove = window->keepAbove();
2626 window->setKeepAbove(true);
2627 }
2628 }
2629
2630 if (window) {
2631 window->move(pos - toplevelDrag->offset());
2632 }
2633 }
2634
2635 qint32 m_touchId = -1;
2636 QPointF m_lastPos = QPointF(-1, -1);
2637 QPointer<Window> m_dragTarget;
2638 QTimer m_raiseTimer;
2639 QPointer<Window> m_currentToplevelDragWindow = nullptr;
2640 bool m_wasKeepAbove = false;
2641};
2642
2643KWIN_SINGLETON_FACTORY(InputRedirection)
2644
2645static const QString s_touchpadComponent = QStringLiteral("kcm_touchpad");
2646
2647InputRedirection::InputRedirection(QObject *parent)
2648 : QObject(parent)
2649 , m_keyboard(new KeyboardInputRedirection(this))
2650 , m_pointer(new PointerInputRedirection(this))
2651 , m_tablet(new TabletInputRedirection(this))
2652 , m_touch(new TouchInputRedirection(this))
2653#if KWIN_BUILD_GLOBALSHORTCUTS
2654 , m_shortcuts(new GlobalShortcutsManager(this))
2655#endif
2656{
2657 qRegisterMetaType<InputRedirection::KeyboardKeyState>();
2658 qRegisterMetaType<InputRedirection::PointerButtonState>();
2659 qRegisterMetaType<InputRedirection::PointerAxis>();
2660 setupInputBackends();
2661 connect(kwinApp(), &Application::workspaceCreated, this, &InputRedirection::setupWorkspace);
2662}
2663
2665{
2666 m_inputBackends.clear();
2667 m_inputDevices.clear();
2668
2669 s_self = nullptr;
2670}
2671
2672void InputRedirection::installInputEventFilter(InputEventFilter *filter)
2673{
2674 Q_ASSERT(!m_filters.contains(filter));
2675 m_filters << filter;
2676}
2677
2679{
2680 Q_ASSERT(!m_filters.contains(filter));
2681 m_filters.prepend(filter);
2682}
2683
2685{
2686 m_filters.removeOne(filter);
2687}
2688
2690{
2691 m_spies << spy;
2692}
2693
2694void InputRedirection::uninstallInputEventSpy(InputEventSpy *spy)
2695{
2696 m_spies.removeOne(spy);
2697}
2698
2700{
2701 m_inputConfigWatcher = KConfigWatcher::create(kwinApp()->inputConfig());
2702 connect(m_inputConfigWatcher.data(), &KConfigWatcher::configChanged,
2703 this, &InputRedirection::handleInputConfigChanged);
2704#if KWIN_BUILD_GLOBALSHORTCUTS
2705 m_shortcuts->init();
2706#endif
2707}
2708
2709void InputRedirection::setupWorkspace()
2710{
2711 connect(workspace(), &Workspace::outputsChanged, this, &InputRedirection::updateScreens);
2712 if (waylandServer()) {
2713 m_keyboard->init();
2714 m_pointer->init();
2715 m_touch->init();
2716 m_tablet->init();
2717
2718 updateLeds(m_keyboard->xkb()->leds());
2719 connect(m_keyboard, &KeyboardInputRedirection::ledsChanged, this, &InputRedirection::updateLeds);
2720
2721 setupTouchpadShortcuts();
2722 setupInputFilters();
2723 updateScreens();
2724 }
2725}
2726
2727void InputRedirection::updateScreens()
2728{
2729 for (const auto &backend : m_inputBackends) {
2730 backend->updateScreens();
2731 }
2732}
2733
2735{
2736 return m_lastInputDevice;
2737}
2738
2740{
2741 m_lastInputDevice = device;
2742}
2743
2745{
2746public:
2747 void keyEvent(KeyEvent *event) override
2748 {
2749 if (event->isAutoRepeat() || event->type() != QEvent::KeyPress) {
2750 return;
2751 }
2752 update();
2753 }
2754
2755 void pointerEvent(MouseEvent *event) override
2756 {
2757 if (event->type() != QEvent::MouseButtonPress) {
2758 return;
2759 }
2760 update();
2761 }
2762
2763 void tabletPadButtonEvent(uint, bool pressed, const TabletPadId &, std::chrono::microseconds time) override
2764 {
2765 if (!pressed) {
2766 return;
2767 }
2768 update();
2769 }
2770
2771 void tabletToolButtonEvent(uint, bool pressed, const TabletToolId &, std::chrono::microseconds time) override
2772 {
2773 if (!pressed) {
2774 return;
2775 }
2776 update();
2777 }
2778
2779 void tabletToolEvent(TabletEvent *event) override
2780 {
2781 if (event->type() != QEvent::TabletPress) {
2782 return;
2783 }
2784 update();
2785 }
2786
2787 void touchDown(qint32, const QPointF &, std::chrono::microseconds time) override
2788 {
2789 update();
2790 }
2791
2792 void update()
2793 {
2794 auto window = workspace()->activeWindow();
2795 if (!window) {
2796 return;
2797 }
2798 window->setLastUsageSerial(waylandServer()->seat()->display()->serial());
2799 }
2800};
2801
2803{
2804public:
2805 void pointerEvent(MouseEvent *event) override
2806 {
2807 notifyActivity();
2808 }
2809 void wheelEvent(WheelEvent *event) override
2810 {
2811 notifyActivity();
2812 }
2813
2814 void keyEvent(KeyEvent *event) override
2815 {
2816 notifyActivity();
2817 }
2818
2819 void touchDown(qint32 id, const QPointF &pos, std::chrono::microseconds time) override
2820 {
2821 notifyActivity();
2822 }
2823 void touchMotion(qint32 id, const QPointF &pos, std::chrono::microseconds time) override
2824 {
2825 notifyActivity();
2826 }
2827 void touchUp(qint32 id, std::chrono::microseconds time) override
2828 {
2829 notifyActivity();
2830 }
2831
2832 void pinchGestureBegin(int fingerCount, std::chrono::microseconds time) override
2833 {
2834 notifyActivity();
2835 }
2836 void pinchGestureUpdate(qreal scale, qreal angleDelta, const QPointF &delta, std::chrono::microseconds time) override
2837 {
2838 notifyActivity();
2839 }
2840 void pinchGestureEnd(std::chrono::microseconds time) override
2841 {
2842 notifyActivity();
2843 }
2844 void pinchGestureCancelled(std::chrono::microseconds time) override
2845 {
2846 notifyActivity();
2847 }
2848
2849 void swipeGestureBegin(int fingerCount, std::chrono::microseconds time) override
2850 {
2851 notifyActivity();
2852 }
2853 void swipeGestureUpdate(const QPointF &delta, std::chrono::microseconds time) override
2854 {
2855 notifyActivity();
2856 }
2857 void swipeGestureEnd(std::chrono::microseconds time) override
2858 {
2859 notifyActivity();
2860 }
2861 void swipeGestureCancelled(std::chrono::microseconds time) override
2862 {
2863 notifyActivity();
2864 }
2865
2866 void holdGestureBegin(int fingerCount, std::chrono::microseconds time) override
2867 {
2868 notifyActivity();
2869 }
2870 void holdGestureEnd(std::chrono::microseconds time) override
2871 {
2872 notifyActivity();
2873 }
2874 void holdGestureCancelled(std::chrono::microseconds time) override
2875 {
2876 notifyActivity();
2877 }
2878
2879 void tabletToolEvent(TabletEvent *event) override
2880 {
2881 notifyActivity();
2882 }
2883 void tabletToolButtonEvent(uint button, bool pressed, const TabletToolId &tabletToolId, std::chrono::microseconds time) override
2884 {
2885 notifyActivity();
2886 }
2887 void tabletPadButtonEvent(uint button, bool pressed, const TabletPadId &tabletPadId, std::chrono::microseconds time) override
2888 {
2889 notifyActivity();
2890 }
2891 void tabletPadStripEvent(int number, int position, bool isFinger, const TabletPadId &tabletPadId, std::chrono::microseconds time) override
2892 {
2893 notifyActivity();
2894 }
2895 void tabletPadRingEvent(int number, int position, bool isFinger, const TabletPadId &tabletPadId, std::chrono::microseconds time) override
2896 {
2897 notifyActivity();
2898 }
2899
2900private:
2901 void notifyActivity()
2902 {
2904 }
2905};
2906
2907void InputRedirection::setupInputFilters()
2908{
2909 const bool hasGlobalShortcutSupport = waylandServer()->hasGlobalShortcutSupport();
2910 if (kwinApp()->session()->capabilities() & Session::Capability::SwitchTerminal) {
2911 m_virtualTerminalFilter = std::make_unique<VirtualTerminalFilter>();
2912 installInputEventFilter(m_virtualTerminalFilter.get());
2913 }
2914
2915 m_hideCursorSpy = std::make_unique<HideCursorSpy>();
2916 installInputEventSpy(m_hideCursorSpy.get());
2917
2918 m_userActivitySpy = std::make_unique<UserActivitySpy>();
2919 installInputEventSpy(m_userActivitySpy.get());
2920
2921 m_windowInteractedSpy = std::make_unique<WindowInteractedSpy>();
2922 installInputEventSpy(m_windowInteractedSpy.get());
2923
2924 m_lockscreenFilter = std::make_unique<LockScreenFilter>();
2925 installInputEventFilter(m_lockscreenFilter.get());
2926
2927 if (hasGlobalShortcutSupport) {
2928 m_screenEdgeFilter = std::make_unique<ScreenEdgeInputFilter>();
2929 installInputEventFilter(m_screenEdgeFilter.get());
2930 }
2931
2932 m_dragAndDropFilter = std::make_unique<DragAndDropInputFilter>();
2933 installInputEventFilter(m_dragAndDropFilter.get());
2934
2935 m_windowSelector = std::make_unique<WindowSelectorFilter>();
2936 installInputEventFilter(m_windowSelector.get());
2937
2938#if KWIN_BUILD_TABBOX
2939 m_tabboxFilter = std::make_unique<TabBoxInputFilter>();
2940 installInputEventFilter(m_tabboxFilter.get());
2941#endif
2942#if KWIN_BUILD_GLOBALSHORTCUTS
2943 if (hasGlobalShortcutSupport) {
2944 m_globalShortcutFilter = std::make_unique<GlobalShortcutFilter>();
2945 installInputEventFilter(m_globalShortcutFilter.get());
2946 }
2947#endif
2948
2949 m_effectsFilter = std::make_unique<EffectsFilter>();
2950 installInputEventFilter(m_effectsFilter.get());
2951
2952 m_interactiveMoveResizeFilter = std::make_unique<MoveResizeFilter>();
2953 installInputEventFilter(m_interactiveMoveResizeFilter.get());
2954
2955 m_popupFilter = std::make_unique<PopupInputFilter>();
2956 installInputEventFilter(m_popupFilter.get());
2957
2958 m_decorationFilter = std::make_unique<DecorationEventFilter>();
2959 installInputEventFilter(m_decorationFilter.get());
2960
2961 m_windowActionFilter = std::make_unique<WindowActionInputFilter>();
2962 installInputEventFilter(m_windowActionFilter.get());
2963
2964 m_internalWindowFilter = std::make_unique<InternalWindowEventFilter>();
2965 installInputEventFilter(m_internalWindowFilter.get());
2966
2967 m_inputKeyboardFilter = std::make_unique<InputKeyboardFilter>();
2968 installInputEventFilter(m_inputKeyboardFilter.get());
2969
2970 m_forwardFilter = std::make_unique<ForwardInputFilter>();
2971 installInputEventFilter(m_forwardFilter.get());
2972
2973 m_tabletFilter = std::make_unique<TabletInputFilter>();
2974 installInputEventFilter(m_tabletFilter.get());
2975}
2976
2977void InputRedirection::handleInputConfigChanged(const KConfigGroup &group)
2978{
2979 if (group.name() == QLatin1String("Keyboard")) {
2980 m_keyboard->reconfigure();
2981 }
2982}
2983
2984void InputRedirection::updateLeds(LEDs leds)
2985{
2986 if (m_leds != leds) {
2987 m_leds = leds;
2988
2989 for (InputDevice *device : std::as_const(m_inputDevices)) {
2990 device->setLeds(leds);
2991 }
2992 }
2993}
2994
2996{
2997 connect(device, &InputDevice::keyChanged, m_keyboard, &KeyboardInputRedirection::processKey);
2998
2999 connect(device, &InputDevice::pointerMotionAbsolute,
3001 connect(device, &InputDevice::pointerMotion,
3003 connect(device, &InputDevice::pointerButtonChanged,
3005 connect(device, &InputDevice::pointerAxisChanged,
3007 connect(device, &InputDevice::pointerFrame,
3009 connect(device, &InputDevice::pinchGestureBegin,
3011 connect(device, &InputDevice::pinchGestureUpdate,
3013 connect(device, &InputDevice::pinchGestureEnd,
3015 connect(device, &InputDevice::pinchGestureCancelled,
3017 connect(device, &InputDevice::swipeGestureBegin,
3019 connect(device, &InputDevice::swipeGestureUpdate,
3021 connect(device, &InputDevice::swipeGestureEnd,
3023 connect(device, &InputDevice::swipeGestureCancelled,
3025 connect(device, &InputDevice::holdGestureBegin,
3027 connect(device, &InputDevice::holdGestureEnd,
3029 connect(device, &InputDevice::holdGestureCancelled,
3031
3033 connect(device, &InputDevice::touchUp, m_touch, &TouchInputRedirection::processUp);
3035 connect(device, &InputDevice::touchCanceled, m_touch, &TouchInputRedirection::cancel);
3036 connect(device, &InputDevice::touchFrame, m_touch, &TouchInputRedirection::frame);
3037
3038 auto handleSwitchEvent = [this](SwitchEvent::State state, std::chrono::microseconds time, InputDevice *device) {
3039 SwitchEvent event(state, time, device);
3040 processSpies(std::bind(&InputEventSpy::switchEvent, std::placeholders::_1, &event));
3041 processFilters(std::bind(&InputEventFilter::switchEvent, std::placeholders::_1, &event));
3042 };
3043 connect(device, &InputDevice::switchToggledOn, this,
3044 std::bind(handleSwitchEvent, SwitchEvent::State::On, std::placeholders::_1, std::placeholders::_2));
3045 connect(device, &InputDevice::switchToggledOff, this,
3046 std::bind(handleSwitchEvent, SwitchEvent::State::Off, std::placeholders::_1, std::placeholders::_2));
3047
3048 connect(device, &InputDevice::tabletToolEvent,
3050 connect(device, &InputDevice::tabletToolButtonEvent,
3052 connect(device, &InputDevice::tabletPadButtonEvent,
3054 connect(device, &InputDevice::tabletPadRingEvent,
3056 connect(device, &InputDevice::tabletPadStripEvent,
3058
3059 device->setLeds(m_leds);
3060
3061 m_inputDevices.append(device);
3062 Q_EMIT deviceAdded(device);
3063
3064 updateAvailableInputDevices();
3065}
3066
3068{
3069 m_inputDevices.removeOne(device);
3070 Q_EMIT deviceRemoved(device);
3071
3072 updateAvailableInputDevices();
3073}
3074
3075void InputRedirection::updateAvailableInputDevices()
3076{
3077 const bool hasKeyboard = std::any_of(m_inputDevices.constBegin(), m_inputDevices.constEnd(), [](InputDevice *device) {
3078 return device->isKeyboard();
3079 });
3080 if (m_hasKeyboard != hasKeyboard) {
3081 m_hasKeyboard = hasKeyboard;
3082 Q_EMIT hasKeyboardChanged(hasKeyboard);
3083 }
3084
3085 const bool hasPointer = std::any_of(m_inputDevices.constBegin(), m_inputDevices.constEnd(), [](InputDevice *device) {
3086 return device->isPointer();
3087 });
3088 if (m_hasPointer != hasPointer) {
3089 m_hasPointer = hasPointer;
3091 }
3092
3093 const bool hasTouch = std::any_of(m_inputDevices.constBegin(), m_inputDevices.constEnd(), [](InputDevice *device) {
3094 return device->isTouch();
3095 });
3096 if (m_hasTouch != hasTouch) {
3097 m_hasTouch = hasTouch;
3098 Q_EMIT hasTouchChanged(hasTouch);
3099 }
3100
3101 const bool hasTabletModeSwitch = std::any_of(m_inputDevices.constBegin(), m_inputDevices.constEnd(), [](InputDevice *device) {
3102 return device->isTabletModeSwitch();
3103 });
3104 if (m_hasTabletModeSwitch != hasTabletModeSwitch) {
3105 m_hasTabletModeSwitch = hasTabletModeSwitch;
3107 }
3108}
3109
3111{
3112 bool changed = false;
3113 m_touchpadsEnabled = !m_touchpadsEnabled;
3114 for (InputDevice *device : std::as_const(m_inputDevices)) {
3115 if (!device->isTouchpad()) {
3116 continue;
3117 }
3118 const bool old = device->isEnabled();
3119 device->setEnabled(m_touchpadsEnabled);
3120 if (old != device->isEnabled()) {
3121 changed = true;
3122 }
3123 }
3124 if (changed) {
3125 // send OSD message
3126 QDBusMessage msg = QDBusMessage::createMethodCall(QStringLiteral("org.kde.plasmashell"),
3127 QStringLiteral("/org/kde/osdService"),
3128 QStringLiteral("org.kde.osdService"),
3129 QStringLiteral("touchpadEnabledChanged"));
3130 msg.setArguments({m_touchpadsEnabled});
3131 QDBusConnection::sessionBus().asyncCall(msg);
3132 }
3133}
3134
3136{
3137 if (!m_touchpadsEnabled) {
3139 }
3140}
3141
3143{
3144 if (m_touchpadsEnabled) {
3146 }
3147}
3148
3149void InputRedirection::addInputBackend(std::unique_ptr<InputBackend> &&inputBackend)
3150{
3151 connect(inputBackend.get(), &InputBackend::deviceAdded, this, &InputRedirection::addInputDevice);
3152 connect(inputBackend.get(), &InputBackend::deviceRemoved, this, &InputRedirection::removeInputDevice);
3153
3154 inputBackend->setConfig(kwinApp()->inputConfig());
3155 inputBackend->initialize();
3156
3157 m_inputBackends.push_back(std::move(inputBackend));
3158}
3159
3160void InputRedirection::setupInputBackends()
3161{
3162 std::unique_ptr<InputBackend> inputBackend = kwinApp()->outputBackend()->createInputBackend();
3163 if (inputBackend) {
3164 addInputBackend(std::move(inputBackend));
3165 }
3166 if (waylandServer()) {
3167 addInputBackend(std::make_unique<FakeInputBackend>(waylandServer()->display()));
3168 }
3169}
3170
3171void InputRedirection::setupTouchpadShortcuts()
3172{
3173 QAction *touchpadToggleAction = new QAction(this);
3174 QAction *touchpadOnAction = new QAction(this);
3175 QAction *touchpadOffAction = new QAction(this);
3176
3177 const QString touchpadDisplayName = i18n("Touchpad");
3178
3179 touchpadToggleAction->setObjectName(QStringLiteral("Toggle Touchpad"));
3180 touchpadToggleAction->setProperty("componentName", s_touchpadComponent);
3181 touchpadToggleAction->setProperty("componentDisplayName", touchpadDisplayName);
3182 touchpadOnAction->setObjectName(QStringLiteral("Enable Touchpad"));
3183 touchpadOnAction->setProperty("componentName", s_touchpadComponent);
3184 touchpadOnAction->setProperty("componentDisplayName", touchpadDisplayName);
3185 touchpadOffAction->setObjectName(QStringLiteral("Disable Touchpad"));
3186 touchpadOffAction->setProperty("componentName", s_touchpadComponent);
3187 touchpadOffAction->setProperty("componentDisplayName", touchpadDisplayName);
3188 KGlobalAccel::self()->setDefaultShortcut(touchpadToggleAction, QList<QKeySequence>{Qt::Key_TouchpadToggle, Qt::ControlModifier | Qt::MetaModifier | Qt::Key_Zenkaku_Hankaku});
3189 KGlobalAccel::self()->setShortcut(touchpadToggleAction, QList<QKeySequence>{Qt::Key_TouchpadToggle, Qt::ControlModifier | Qt::MetaModifier | Qt::Key_Zenkaku_Hankaku});
3190 KGlobalAccel::self()->setDefaultShortcut(touchpadOnAction, QList<QKeySequence>{Qt::Key_TouchpadOn});
3191 KGlobalAccel::self()->setShortcut(touchpadOnAction, QList<QKeySequence>{Qt::Key_TouchpadOn});
3192 KGlobalAccel::self()->setDefaultShortcut(touchpadOffAction, QList<QKeySequence>{Qt::Key_TouchpadOff});
3193 KGlobalAccel::self()->setShortcut(touchpadOffAction, QList<QKeySequence>{Qt::Key_TouchpadOff});
3194 connect(touchpadToggleAction, &QAction::triggered, this, &InputRedirection::toggleTouchpads);
3195 connect(touchpadOnAction, &QAction::triggered, this, &InputRedirection::enableTouchpads);
3196 connect(touchpadOffAction, &QAction::triggered, this, &InputRedirection::disableTouchpads);
3197}
3198
3200{
3201 return m_hasPointer;
3202}
3203
3205{
3206 return m_hasTouch;
3207}
3208
3210{
3211 return m_hasTabletModeSwitch;
3212}
3213
3214Qt::MouseButtons InputRedirection::qtButtonStates() const
3215{
3216 return m_pointer->buttons();
3217}
3218
3220{
3221 for (IdleDetector *idleDetector : std::as_const(m_idleDetectors)) {
3222 idleDetector->activity();
3223 }
3224}
3225
3227{
3228 Q_ASSERT(!m_idleDetectors.contains(detector));
3229 detector->setInhibited(!m_idleInhibitors.isEmpty());
3230 m_idleDetectors.append(detector);
3231}
3232
3234{
3235 m_idleDetectors.removeOne(detector);
3236}
3237
3239{
3240 return m_idleInhibitors;
3241}
3242
3244{
3245 if (!m_idleInhibitors.contains(inhibitor)) {
3246 m_idleInhibitors.append(inhibitor);
3247 for (IdleDetector *idleDetector : std::as_const(m_idleDetectors)) {
3248 idleDetector->setInhibited(true);
3249 }
3250 }
3251}
3252
3254{
3255 if (m_idleInhibitors.removeOne(inhibitor) && m_idleInhibitors.isEmpty()) {
3256 for (IdleDetector *idleDetector : std::as_const(m_idleDetectors)) {
3257 idleDetector->setInhibited(false);
3258 }
3259 }
3260}
3261
3263{
3264 if (!Workspace::self()) {
3265 return nullptr;
3266 }
3267 const bool isScreenLocked = waylandServer() && waylandServer()->isScreenLocked();
3268 if (!isScreenLocked) {
3269 // if an effect overrides the cursor we don't have a window to focus
3271 return nullptr;
3272 }
3273 }
3274 const QList<Window *> &stacking = Workspace::self()->stackingOrder();
3275 if (stacking.isEmpty()) {
3276 return nullptr;
3277 }
3278 auto it = stacking.end();
3279 do {
3280 --it;
3281 Window *window = (*it);
3282 if (window->isDeleted()) {
3283 // a deleted window doesn't get mouse events
3284 continue;
3285 }
3286 if (!window->isOnCurrentActivity() || !window->isOnCurrentDesktop() || window->isMinimized() || window->isHidden() || window->isHiddenByShowDesktop()) {
3287 continue;
3288 }
3289 if (!window->readyForPainting()) {
3290 continue;
3291 }
3292 if (isScreenLocked) {
3293 if (!window->isLockScreen() && !window->isInputMethod() && !window->isLockScreenOverlay()) {
3294 continue;
3295 }
3296 }
3297 if (window->hitTest(pos)) {
3298 return window;
3299 }
3300 } while (it != stacking.begin());
3301 return nullptr;
3302}
3303
3304Qt::KeyboardModifiers InputRedirection::keyboardModifiers() const
3305{
3306 return m_keyboard->modifiers();
3307}
3308
3310{
3311 return m_keyboard->modifiersRelevantForGlobalShortcuts();
3312}
3313
3314void InputRedirection::registerPointerShortcut(Qt::KeyboardModifiers modifiers, Qt::MouseButton pointerButtons, QAction *action)
3315{
3316#if KWIN_BUILD_GLOBALSHORTCUTS
3317 m_shortcuts->registerPointerShortcut(action, modifiers, pointerButtons);
3318#endif
3319}
3320
3321void InputRedirection::registerAxisShortcut(Qt::KeyboardModifiers modifiers, PointerAxisDirection axis, QAction *action)
3322{
3323#if KWIN_BUILD_GLOBALSHORTCUTS
3324 m_shortcuts->registerAxisShortcut(action, modifiers, axis);
3325#endif
3326}
3327
3328void InputRedirection::registerTouchpadSwipeShortcut(SwipeDirection direction, uint fingerCount, QAction *action, std::function<void(qreal)> cb)
3329{
3330#if KWIN_BUILD_GLOBALSHORTCUTS
3331 m_shortcuts->registerTouchpadSwipe(direction, fingerCount, action, cb);
3332#endif
3333}
3334
3335void InputRedirection::registerTouchpadPinchShortcut(PinchDirection direction, uint fingerCount, QAction *onUp, std::function<void(qreal)> progressCallback)
3336{
3337#if KWIN_BUILD_GLOBALSHORTCUTS
3338 m_shortcuts->registerTouchpadPinch(direction, fingerCount, onUp, progressCallback);
3339#endif
3340}
3341
3342void InputRedirection::registerGlobalAccel(KGlobalAccelInterface *interface)
3343{
3344#if KWIN_BUILD_GLOBALSHORTCUTS
3345 m_shortcuts->setKGlobalAccelInterface(interface);
3346#endif
3347}
3348
3349void InputRedirection::registerTouchscreenSwipeShortcut(SwipeDirection direction, uint fingerCount, QAction *action, std::function<void(qreal)> progressCallback)
3350{
3351#if KWIN_BUILD_GLOBALSHORTCUTS
3352 m_shortcuts->registerTouchscreenSwipe(direction, fingerCount, action, progressCallback);
3353#endif
3354}
3355
3356void InputRedirection::forceRegisterTouchscreenSwipeShortcut(SwipeDirection direction, uint fingerCount, QAction *action, std::function<void(qreal)> progressCallback)
3357{
3358#if KWIN_BUILD_GLOBALSHORTCUTS
3359 m_shortcuts->forceRegisterTouchscreenSwipe(direction, fingerCount, action, progressCallback);
3360#endif
3361}
3362
3363void InputRedirection::warpPointer(const QPointF &pos)
3364{
3365 m_pointer->warp(pos);
3366}
3367
3369{
3370 return m_pointer->supportsWarping();
3371}
3372
3374{
3375 return m_pointer->pos();
3376}
3377
3378void InputRedirection::startInteractiveWindowSelection(std::function<void(Window *)> callback, const QByteArray &cursorName)
3379{
3380 if (!m_windowSelector || m_windowSelector->isActive()) {
3381 callback(nullptr);
3382 return;
3383 }
3384 m_windowSelector->start(callback);
3385 m_pointer->setWindowSelectionCursor(cursorName);
3386}
3387
3388void InputRedirection::startInteractivePositionSelection(std::function<void(const QPoint &)> callback)
3389{
3390 if (!m_windowSelector || m_windowSelector->isActive()) {
3391 callback(QPoint(-1, -1));
3392 return;
3393 }
3394 m_windowSelector->start(callback);
3395 m_pointer->setWindowSelectionCursor(QByteArray());
3396}
3397
3399{
3400 return m_windowSelector ? m_windowSelector->isActive() : false;
3401}
3402
3407
3409
3416
3417bool InputDeviceHandler::setHover(Window *window)
3418{
3419 if (m_hover.window == window) {
3420 return false;
3421 }
3422 auto old = m_hover.window;
3423 disconnect(m_hover.surfaceCreatedConnection);
3424 m_hover.surfaceCreatedConnection = QMetaObject::Connection();
3425
3426 m_hover.window = window;
3427 return true;
3428}
3429
3431{
3432 if (m_focus.window == window) {
3433 return;
3434 }
3435
3436 Window *oldFocus = m_focus.window;
3437 if (oldFocus) {
3438 disconnect(oldFocus, &Window::closed, this, &InputDeviceHandler::update);
3439 }
3440
3441 m_focus.window = window;
3442 if (window) {
3444 }
3445
3446 focusUpdate(oldFocus, window);
3447}
3448
3450{
3451 if (m_focus.decoration != decoration) {
3452 auto oldDeco = m_focus.decoration;
3453 m_focus.decoration = decoration;
3454 cleanupDecoration(oldDeco.data(), m_focus.decoration.data());
3455 Q_EMIT decorationChanged();
3456 }
3457}
3458
3459void InputDeviceHandler::updateFocus()
3460{
3461 Window *focus = m_hover.window;
3462
3463 if (m_focus.decoration) {
3464 focus = nullptr;
3465 } else if (m_hover.window && !m_hover.window->surface() && !m_hover.window->isInternal()) {
3466 // The surface has not yet been created (special XWayland case).
3467 // Therefore listen for its creation.
3468 if (!m_hover.surfaceCreatedConnection) {
3469 m_hover.surfaceCreatedConnection = connect(m_hover.window, &Window::surfaceChanged,
3471 }
3472 focus = nullptr;
3473 }
3474
3475 setFocus(focus);
3476}
3477
3478void InputDeviceHandler::updateDecoration()
3479{
3480 Decoration::DecoratedClientImpl *decoration = nullptr;
3481 auto hover = m_hover.window.data();
3482 if (hover && hover->decoratedClient()) {
3483 if (!hover->clientGeometry().toRect().contains(flooredPoint(position()))) {
3484 // input device above decoration
3486 }
3487 }
3488
3490}
3491
3493{
3494 if (!m_inited) {
3495 return;
3496 }
3497
3498 Window *window = nullptr;
3499 if (positionValid()) {
3501 }
3502 // Always set the window at the position of the input device.
3503 setHover(window);
3504
3505 if (focusUpdatesBlocked()) {
3507 return;
3508 }
3509
3510 updateDecoration();
3511 updateFocus();
3512
3514}
3515
3517{
3518 return m_hover.window.data();
3519}
3520
3522{
3523 return m_focus.window.data();
3524}
3525
3527{
3528 return m_focus.decoration;
3529}
3530
3531} // namespace
3532
3533#include "input.moc"
3534
3535#include "moc_input.cpp"
Replacement for QCursor.
Definition cursor.h:102
void setSource(CursorSource *source)
Definition cursor.cpp:703
bool touchDown(qint32 id, const QPointF &pos, std::chrono::microseconds time) override
Definition input.cpp:1458
bool touchUp(qint32 id, std::chrono::microseconds time) override
Definition input.cpp:1510
bool touchMotion(qint32 id, const QPointF &pos, std::chrono::microseconds time) override
Definition input.cpp:1489
bool wheelEvent(WheelEvent *event) override
Definition input.cpp:1424
bool pointerEvent(MouseEvent *event, quint32 nativeButton) override
Definition input.cpp:1387
bool tabletToolEvent(TabletEvent *event) override
Definition input.cpp:1545
bool touchMotion(qint32 id, const QPointF &pos, std::chrono::microseconds time) override
Definition input.cpp:2495
bool touchUp(qint32 id, std::chrono::microseconds time) override
Definition input.cpp:2542
bool touchDown(qint32 id, const QPointF &pos, std::chrono::microseconds time) override
Definition input.cpp:2478
bool pointerEvent(MouseEvent *event, quint32 nativeButton) override
Definition input.cpp:2394
bool pointerFrame() override
Definition input.cpp:2464
bool keyEvent(KeyEvent *event) override
Definition input.cpp:2556
bool wheelEvent(WheelEvent *event) override
Definition input.cpp:518
bool touchMotion(qint32 id, const QPointF &pos, std::chrono::microseconds time) override
Definition input.cpp:542
bool tabletToolButtonEvent(uint button, bool pressed, const TabletToolId &tabletToolId, std::chrono::microseconds time) override
Definition input.cpp:563
bool tabletToolEvent(TabletEvent *event) override
Definition input.cpp:556
bool pointerEvent(MouseEvent *event, quint32 nativeButton) override
Definition input.cpp:511
bool tabletPadStripEvent(int number, int position, bool isFinger, const TabletPadId &tabletPadId, std::chrono::microseconds time) override
Definition input.cpp:577
bool touchDown(qint32 id, const QPointF &pos, std::chrono::microseconds time) override
Definition input.cpp:535
bool tabletPadButtonEvent(uint button, bool pressed, const TabletPadId &tabletPadId, std::chrono::microseconds time) override
Definition input.cpp:570
bool touchUp(qint32 id, std::chrono::microseconds time) override
Definition input.cpp:549
bool keyEvent(KeyEvent *event) override
Definition input.cpp:525
bool tabletPadRingEvent(int number, int position, bool isFinger, const TabletPadId &tabletPadId, std::chrono::microseconds time) override
Definition input.cpp:584
bool hasKeyboardGrab() const
bool isMouseInterception() const
void grabbedKeyboardEvent(QKeyEvent *e)
bool tabletPadButtonEvent(uint button, bool pressed, const KWin::TabletPadId &tabletPadId, std::chrono::microseconds time)
bool tabletToolEvent(KWin::TabletEvent *event)
bool checkInputWindowEvent(QMouseEvent *e)
bool touchMotion(qint32 id, const QPointF &pos, std::chrono::microseconds time)
bool touchUp(qint32 id, std::chrono::microseconds time)
bool tabletPadRingEvent(int number, int position, bool isFinger, const KWin::TabletPadId &tabletPadId, std::chrono::microseconds time)
bool tabletToolButtonEvent(uint button, bool pressed, const KWin::TabletToolId &tabletToolId, std::chrono::microseconds time)
bool touchDown(qint32 id, const QPointF &pos, std::chrono::microseconds time)
bool tabletPadStripEvent(int number, int position, bool isFinger, const KWin::TabletPadId &tabletPadId, std::chrono::microseconds time)
bool holdGestureCancelled(std::chrono::microseconds time) override
Definition input.cpp:1935
bool touchUp(qint32 id, std::chrono::microseconds time) override
Definition input.cpp:1847
bool swipeGestureEnd(std::chrono::microseconds time) override
Definition input.cpp:1907
bool pinchGestureUpdate(qreal scale, qreal angleDelta, const QPointF &delta, std::chrono::microseconds time) override
Definition input.cpp:1871
bool holdGestureEnd(std::chrono::microseconds time) override
Definition input.cpp:1928
bool pointerEvent(MouseEvent *event, quint32 nativeButton) override
Definition input.cpp:1781
bool touchMotion(qint32 id, const QPointF &pos, std::chrono::microseconds time) override
Definition input.cpp:1840
bool touchFrame() override
Definition input.cpp:1859
bool pinchGestureBegin(int fingerCount, std::chrono::microseconds time) override
Definition input.cpp:1864
bool touchDown(qint32 id, const QPointF &pos, std::chrono::microseconds time) override
Definition input.cpp:1833
bool pinchGestureEnd(std::chrono::microseconds time) override
Definition input.cpp:1878
bool swipeGestureCancelled(std::chrono::microseconds time) override
Definition input.cpp:1914
bool pinchGestureCancelled(std::chrono::microseconds time) override
Definition input.cpp:1885
bool pointerFrame() override
Definition input.cpp:1805
bool keyEvent(KeyEvent *event) override
Definition input.cpp:1821
bool swipeGestureUpdate(const QPointF &delta, std::chrono::microseconds time) override
Definition input.cpp:1900
bool holdGestureBegin(int fingerCount, std::chrono::microseconds time) override
Definition input.cpp:1921
bool wheelEvent(WheelEvent *event) override
Definition input.cpp:1811
bool swipeGestureBegin(int fingerCount, std::chrono::microseconds time) override
Definition input.cpp:1893
bool touchCancel() override
Definition input.cpp:1854
void updateSwipeGesture(const QPointF &delta)
Definition gestures.cpp:199
void setInhibited(bool inhibited)
void deviceAdded(InputDevice *device)
void deviceRemoved(InputDevice *device)
QPointer< Window > window
Definition input.h:536
virtual bool positionValid() const
Definition input.h:511
void setDecoration(Decoration::DecoratedClientImpl *decoration)
Definition input.cpp:3449
void setFocus(Window *window)
Definition input.cpp:3430
virtual void cleanupDecoration(Decoration::DecoratedClientImpl *old, Decoration::DecoratedClientImpl *now)=0
virtual void focusUpdate(Window *old, Window *now)=0
Window * hover() const
First Window currently at the position of the input device according to the stacking order.
Definition input.cpp:3516
virtual bool focusUpdatesBlocked()
Definition input.h:515
virtual QPointF position() const =0
InputDeviceHandler(InputRedirection *parent)
Definition input.cpp:3403
Window * focus() const
Window currently having pointer input focus (this might be different from the Window at the position ...
Definition input.cpp:3521
virtual void init()
Definition input.cpp:3410
~InputDeviceHandler() override
QPointer< Decoration::DecoratedClientImpl > decoration
Definition input.h:543
void tabletPadButtonEvent(uint button, bool isPressed, const TabletPadId &tabletPadId, std::chrono::microseconds time)
void touchFrame(InputDevice *device)
void touchMotion(qint32 id, const QPointF &absolutePos, std::chrono::microseconds time, InputDevice *device)
void touchCanceled(InputDevice *device)
void swipeGestureUpdate(const QPointF &delta, std::chrono::microseconds time, InputDevice *device)
void pointerMotion(const QPointF &delta, const QPointF &deltaNonAccelerated, std::chrono::microseconds time, InputDevice *device)
void pointerFrame(InputDevice *device)
void swipeGestureCancelled(std::chrono::microseconds time, InputDevice *device)
void switchToggledOn(std::chrono::microseconds time, InputDevice *device)
void holdGestureBegin(int fingerCount, std::chrono::microseconds time, InputDevice *device)
void pinchGestureBegin(int fingerCount, std::chrono::microseconds time, InputDevice *device)
void pointerButtonChanged(quint32 button, InputRedirection::PointerButtonState state, std::chrono::microseconds time, InputDevice *device)
void pinchGestureCancelled(std::chrono::microseconds time, InputDevice *device)
void holdGestureCancelled(std::chrono::microseconds time, InputDevice *device)
void switchToggledOff(std::chrono::microseconds time, InputDevice *device)
void tabletToolEvent(InputRedirection::TabletEventType type, const QPointF &pos, qreal pressure, int xTilt, int yTilt, qreal rotation, bool tipDown, bool tipNear, const TabletToolId &tabletToolId, std::chrono::microseconds time)
void pinchGestureUpdate(qreal scale, qreal angleDelta, const QPointF &delta, std::chrono::microseconds time, InputDevice *device)
void touchDown(qint32 id, const QPointF &absolutePos, std::chrono::microseconds time, InputDevice *device)
void tabletPadStripEvent(int number, int position, bool isFinger, const TabletPadId &tabletPadId, std::chrono::microseconds time)
void tabletToolButtonEvent(uint button, bool isPressed, const TabletToolId &tabletToolId, std::chrono::microseconds time)
void pointerMotionAbsolute(const QPointF &position, std::chrono::microseconds time, InputDevice *device)
void holdGestureEnd(std::chrono::microseconds time, InputDevice *device)
virtual void setLeds(LEDs leds)=0
void tabletPadRingEvent(int number, int position, bool isFinger, const TabletPadId &tabletPadId, std::chrono::microseconds time)
void swipeGestureEnd(std::chrono::microseconds time, InputDevice *device)
void swipeGestureBegin(int fingerCount, std::chrono::microseconds time, InputDevice *device)
void keyChanged(quint32 key, InputRedirection::KeyboardKeyState, std::chrono::microseconds time, InputDevice *device)
virtual QString outputName() const
void pinchGestureEnd(std::chrono::microseconds time, InputDevice *device)
void touchUp(qint32 id, std::chrono::microseconds time, InputDevice *device)
void pointerAxisChanged(InputRedirection::PointerAxis axis, qreal delta, qint32 deltaV120, InputRedirection::PointerAxisSource source, std::chrono::microseconds time, InputDevice *device)
virtual bool pinchGestureEnd(std::chrono::microseconds time)
Definition input.cpp:165
virtual bool tabletToolButtonEvent(uint button, bool pressed, const TabletToolId &tabletToolId, std::chrono::microseconds time)
Definition input.cpp:220
virtual bool keyEvent(KeyEvent *event)
Definition input.cpp:125
virtual bool tabletPadButtonEvent(uint button, bool pressed, const TabletPadId &tabletPadId, std::chrono::microseconds time)
Definition input.cpp:225
virtual bool pinchGestureUpdate(qreal scale, qreal angleDelta, const QPointF &delta, std::chrono::microseconds time)
Definition input.cpp:160
virtual bool touchUp(qint32 id, std::chrono::microseconds time)
Definition input.cpp:140
virtual bool swipeGestureCancelled(std::chrono::microseconds time)
Definition input.cpp:190
void passToWaylandServer(QKeyEvent *event)
Definition input.cpp:240
virtual bool pointerEvent(MouseEvent *event, quint32 nativeButton)
Definition input.cpp:110
bool passToInputMethod(QKeyEvent *event)
Definition input.cpp:261
virtual bool pointerFrame()
Definition input.cpp:115
virtual bool swipeGestureUpdate(const QPointF &delta, std::chrono::microseconds time)
Definition input.cpp:180
virtual bool touchDown(qint32 id, const QPointF &pos, std::chrono::microseconds time)
Definition input.cpp:130
virtual bool wheelEvent(WheelEvent *event)
Definition input.cpp:120
virtual bool holdGestureEnd(std::chrono::microseconds time)
Definition input.cpp:200
virtual bool swipeGestureEnd(std::chrono::microseconds time)
Definition input.cpp:185
virtual bool pinchGestureCancelled(std::chrono::microseconds time)
Definition input.cpp:170
virtual ~InputEventFilter()
Definition input.cpp:103
virtual bool touchMotion(qint32 id, const QPointF &pos, std::chrono::microseconds time)
Definition input.cpp:135
virtual bool holdGestureBegin(int fingerCount, std::chrono::microseconds time)
Definition input.cpp:195
virtual bool tabletPadRingEvent(int number, int position, bool isFinger, const TabletPadId &tabletPadId, std::chrono::microseconds time)
Definition input.cpp:235
virtual bool pinchGestureBegin(int fingerCount, std::chrono::microseconds time)
Definition input.cpp:155
virtual bool holdGestureCancelled(std::chrono::microseconds time)
Definition input.cpp:205
virtual bool touchCancel()
Definition input.cpp:145
virtual bool touchFrame()
Definition input.cpp:150
virtual bool switchEvent(SwitchEvent *event)
Definition input.cpp:210
virtual bool swipeGestureBegin(int fingerCount, std::chrono::microseconds time)
Definition input.cpp:175
virtual bool tabletPadStripEvent(int number, int position, bool isFinger, const TabletPadId &tabletPadId, std::chrono::microseconds time)
Definition input.cpp:230
virtual bool tabletToolEvent(TabletEvent *event)
Definition input.cpp:215
virtual void switchEvent(SwitchEvent *event)
bool keyEvent(KeyEvent *event) override
Definition input.cpp:1769
This class is responsible for redirecting incoming input to the surface which currently has input or ...
Definition input.h:70
void addIdleDetector(IdleDetector *detector)
Definition input.cpp:3226
void registerPointerShortcut(Qt::KeyboardModifiers modifiers, Qt::MouseButton pointerButtons, QAction *action)
Definition input.cpp:3314
void registerTouchscreenSwipeShortcut(SwipeDirection direction, uint32_t fingerCount, QAction *action, std::function< void(qreal)> progressCallback={})
void installInputEventSpy(InputEventSpy *spy)
void deviceAdded(InputDevice *device)
QList< InputDevice * > devices() const
Definition input.h:554
void removeInputDevice(InputDevice *device)
Definition input.cpp:3067
KeyboardInputRedirection * keyboard() const
Definition input.h:216
TabletInputRedirection * tablet() const
Definition input.h:224
void hasTabletModeSwitchChanged(bool set)
bool supportsPointerWarping() const
Definition input.cpp:3368
void deviceRemoved(InputDevice *device)
void addIdleInhibitor(Window *inhibitor)
Definition input.cpp:3243
void removeIdleDetector(IdleDetector *detector)
Definition input.cpp:3233
TouchInputRedirection * touch() const
Definition input.h:228
QList< Window * > idleInhibitors() const
Definition input.cpp:3238
void processSpies(UnaryFunction function)
Definition input.h:211
void registerAxisShortcut(Qt::KeyboardModifiers modifiers, PointerAxisDirection axis, QAction *action)
void registerTouchpadPinchShortcut(PinchDirection direction, uint32_t fingerCount, QAction *onUp, std::function< void(qreal)> progressCallback={})
void addInputDevice(InputDevice *device)
Definition input.cpp:2995
void hasPointerChanged(bool set)
void uninstallInputEventFilter(InputEventFilter *filter)
Definition input.cpp:2684
void processFilters(UnaryPredicate function)
Definition input.h:192
PointerInputRedirection * pointer() const
Definition input.h:220
QObject * lastInputHandler() const
Definition input.cpp:2734
void registerTouchpadSwipeShortcut(SwipeDirection direction, uint32_t fingerCount, QAction *onUp, std::function< void(qreal)> progressCallback={})
Qt::MouseButtons qtButtonStates() const
Definition input.cpp:3214
~InputRedirection() override
Definition input.cpp:2664
void hasTouchChanged(bool set)
void hasKeyboardChanged(bool set)
Qt::KeyboardModifiers keyboardModifiers() const
Definition input.cpp:3304
bool hasPointer() const
Definition input.cpp:3199
void forceRegisterTouchscreenSwipeShortcut(SwipeDirection direction, uint32_t fingerCount, QAction *action, std::function< void(qreal)> progressCallback={})
Definition input.cpp:3356
void prependInputEventFilter(InputEventFilter *filter)
Definition input.cpp:2678
void setLastInputHandler(QObject *device)
Definition input.cpp:2739
void warpPointer(const QPointF &pos)
Definition input.cpp:3363
void uninstallInputEventSpy(InputEventSpy *spy)
void registerGlobalAccel(KGlobalAccelInterface *interface)
Definition input.cpp:3342
Qt::KeyboardModifiers modifiersRelevantForGlobalShortcuts() const
Definition input.cpp:3309
Window * findToplevel(const QPointF &pos)
Definition input.cpp:3262
void startInteractivePositionSelection(std::function< void(const QPoint &)> callback)
Definition input.cpp:3388
bool hasTouch() const
Definition input.cpp:3204
bool isSelectingWindow() const
Definition input.cpp:3398
void startInteractiveWindowSelection(std::function< void(KWin::Window *)> callback, const QByteArray &cursorName)
Definition input.cpp:3378
QPointF globalPointer() const
Definition input.cpp:3373
void removeIdleInhibitor(Window *inhibitor)
Definition input.cpp:3253
std::chrono::microseconds timestamp() const
Qt::KeyboardModifiers modifiersRelevantForGlobalShortcuts() const
void processKey(uint32_t key, InputRedirection::KeyboardKeyState state, std::chrono::microseconds time, InputDevice *device=nullptr)
Qt::KeyboardModifiers modifiers() const
bool swipeGestureCancelled(std::chrono::microseconds time) override
Definition input.cpp:467
bool pinchGestureEnd(std::chrono::microseconds time) override
Definition input.cpp:441
bool swipeGestureBegin(int fingerCount, std::chrono::microseconds time) override
Definition input.cpp:452
bool wheelEvent(WheelEvent *event) override
Definition input.cpp:339
bool pointerFrame() override
Definition input.cpp:328
bool touchDown(qint32 id, const QPointF &pos, std::chrono::microseconds time) override
Definition input.cpp:395
bool swipeGestureUpdate(const QPointF &delta, std::chrono::microseconds time) override
Definition input.cpp:457
bool pinchGestureBegin(int fingerCount, std::chrono::microseconds time) override
Definition input.cpp:431
bool pinchGestureUpdate(qreal scale, qreal angleDelta, const QPointF &delta, std::chrono::microseconds time) override
Definition input.cpp:436
bool holdGestureEnd(std::chrono::microseconds time) override
Definition input.cpp:477
bool holdGestureBegin(int fingerCount, std::chrono::microseconds time) override
Definition input.cpp:472
bool touchUp(qint32 id, std::chrono::microseconds time) override
Definition input.cpp:419
bool swipeGestureEnd(std::chrono::microseconds time) override
Definition input.cpp:462
bool touchMotion(qint32 id, const QPointF &pos, std::chrono::microseconds time) override
Definition input.cpp:407
bool pinchGestureCancelled(std::chrono::microseconds time) override
Definition input.cpp:446
bool pointerEvent(MouseEvent *event, quint32 nativeButton) override
Definition input.cpp:298
bool keyEvent(KeyEvent *event) override
Definition input.cpp:355
QPointF deltaUnaccelerated() const
Definition input_event.h:33
QPointF delta() const
Definition input_event.h:28
std::chrono::microseconds timestamp() const
Definition input_event.h:38
float accumulate(WheelEvent *event)
Definition input.cpp:1365
bool tabletToolEvent(TabletEvent *event) override
Definition input.cpp:678
bool touchDown(qint32 id, const QPointF &pos, std::chrono::microseconds time) override
Definition input.cpp:637
bool pointerEvent(MouseEvent *event, quint32 nativeButton) override
Definition input.cpp:596
bool touchMotion(qint32 id, const QPointF &pos, std::chrono::microseconds time) override
Definition input.cpp:646
bool keyEvent(KeyEvent *event) override
Definition input.cpp:621
bool wheelEvent(WheelEvent *event) override
Definition input.cpp:616
bool touchUp(qint32 id, std::chrono::microseconds time) override
Definition input.cpp:662
Qt::KeyboardModifier commandAllModifier() const
Definition options.h:558
MouseCommand commandAll2
Definition options.h:153
MouseCommand commandAll3
Definition options.h:154
MouseCommand commandAll1
Definition options.h:152
MouseCommand operationWindowMouseWheel(int delta) const
Definition options.h:493
MouseCommand operationTitlebarMouseWheel(int delta) const
Definition options.h:489
QSize orientateSize(const QSize &size) const
Definition output.cpp:630
void processPinchGestureCancelled(std::chrono::microseconds time, KWin::InputDevice *device=nullptr)
void processSwipeGestureUpdate(const QPointF &delta, std::chrono::microseconds time, KWin::InputDevice *device=nullptr)
void processPinchGestureBegin(int fingerCount, std::chrono::microseconds time, KWin::InputDevice *device=nullptr)
void processPinchGestureUpdate(qreal scale, qreal angleDelta, const QPointF &delta, std::chrono::microseconds time, KWin::InputDevice *device=nullptr)
void processHoldGestureEnd(std::chrono::microseconds time, KWin::InputDevice *device=nullptr)
void processHoldGestureBegin(int fingerCount, std::chrono::microseconds time, KWin::InputDevice *device=nullptr)
void processMotionAbsolute(const QPointF &pos, std::chrono::microseconds time, InputDevice *device=nullptr)
void setWindowSelectionCursor(const QByteArray &shape)
void processSwipeGestureCancelled(std::chrono::microseconds time, KWin::InputDevice *device=nullptr)
void processSwipeGestureEnd(std::chrono::microseconds time, KWin::InputDevice *device=nullptr)
void processAxis(InputRedirection::PointerAxis axis, qreal delta, qint32 deltaV120, InputRedirection::PointerAxisSource source, std::chrono::microseconds time, InputDevice *device=nullptr)
void processHoldGestureCancelled(std::chrono::microseconds time, KWin::InputDevice *device=nullptr)
void processPinchGestureEnd(std::chrono::microseconds time, KWin::InputDevice *device=nullptr)
void processSwipeGestureBegin(int fingerCount, std::chrono::microseconds time, KWin::InputDevice *device=nullptr)
Qt::MouseButtons buttons() const
void processMotion(const QPointF &delta, const QPointF &deltaNonAccelerated, std::chrono::microseconds time, InputDevice *device)
void warp(const QPointF &pos)
void processFrame(KWin::InputDevice *device=nullptr)
void processButton(uint32_t button, InputRedirection::PointerButtonState state, std::chrono::microseconds time, InputDevice *device=nullptr)
bool pointerEvent(MouseEvent *event, quint32 nativeButton) override
Definition input.cpp:1644
bool touchDown(qint32 id, const QPointF &pos, std::chrono::microseconds time) override
Definition input.cpp:1650
bool touchUp(qint32 id, std::chrono::microseconds time) override
Definition input.cpp:1677
bool touchMotion(qint32 id, const QPointF &pos, std::chrono::microseconds time) override
Definition input.cpp:1668
bool isEntered(QMouseEvent *event)
GestureRecognizer * gestureRecognizer() const
Definition screenedge.h:362
Represents a Seat on the Wayland Display.
Definition seat.h:134
SurfaceInterface * focusedTouchSurface() const
Definition seat.cpp:998
void setTimestamp(std::chrono::microseconds time)
Definition seat.cpp:488
void notifyTouchCancel()
Definition seat.cpp:984
SurfaceInterface * focusedPointerSurface() const
Definition seat.cpp:550
SurfaceInterface * focusedKeyboardSurface() const
Definition seat.cpp:910
void notifyTouchFrame()
Definition seat.cpp:1165
void setFocusedKeyboardSurface(SurfaceInterface *surface)
Definition seat.cpp:915
SurfaceCursor(TabletToolV2Interface *tool)
Definition input.cpp:1956
Resource representing a wl_surface.
Definition surface.h:80
ClientConnection * client() const
Definition surface.cpp:444
const TabletToolId & tabletId() const
static void trackNextOutput()
Definition input.cpp:2061
bool tabletToolEvent(TabletEvent *event) override
Definition input.cpp:2171
static TabletSeatV2Interface * findTabletSeat()
Definition input.cpp:2018
bool emulateTabletEvent(TabletEvent *event)
Definition input.cpp:2250
bool tabletToolButtonEvent(uint button, bool pressed, const TabletToolId &tabletToolId, std::chrono::microseconds time) override
Definition input.cpp:2278
TabletPadV2Interface * findAndAdoptPad(const TabletPadId &tabletPadId) const
Definition input.cpp:2292
bool tabletPadStripEvent(int number, int position, bool isFinger, const TabletPadId &tabletPadId, std::chrono::microseconds time) override
Definition input.cpp:2336
bool tabletPadButtonEvent(uint button, bool pressed, const TabletPadId &tabletPadId, std::chrono::microseconds time) override
Definition input.cpp:2310
bool tabletPadRingEvent(int number, int angle, bool isFinger, const TabletPadId &tabletPadId, std::chrono::microseconds time) override
Definition input.cpp:2320
TabletToolV2Interface * createTool(const TabletToolId &tabletToolId)
Definition input.cpp:2137
TabletToolV2Interface::Type getType(const TabletToolId &tabletToolId)
Definition input.cpp:2111
QHash< TabletToolV2Interface *, Cursor * > m_cursorByTool
Definition input.cpp:2352
void integrateDevice(InputDevice *inputDevice)
Definition input.cpp:2028
void removeDevice(InputDevice *inputDevice)
Definition input.cpp:2095
void tabletPadButtonEvent(uint button, bool isPressed, const TabletPadId &tabletPadId, std::chrono::microseconds time)
void tabletPadStripEvent(int number, int position, bool isFinger, const TabletPadId &tabletPadId, std::chrono::microseconds time)
void tabletToolButtonEvent(uint button, bool isPressed, const TabletToolId &tabletToolId, std::chrono::microseconds time)
void tabletToolEvent(KWin::InputRedirection::TabletEventType type, const QPointF &pos, qreal pressure, int xTilt, int yTilt, qreal rotation, bool tipDown, bool tipNear, const TabletToolId &tabletToolId, std::chrono::microseconds time)
void tabletPadRingEvent(int number, int position, bool isFinger, const TabletPadId &tabletPadId, std::chrono::microseconds time)
TabletSeatV2Interface * seat(SeatInterface *seat) const
TabletPadV2Interface * addTabletPad(const QString &sysname, const QString &name, const QStringList &paths, quint32 buttons, quint32 rings, quint32 strips, quint32 modes, quint32 currentMode, TabletV2Interface *tablet)
TabletToolV2Interface * toolByHardwareSerial(quint64 hardwareSerial, TabletToolV2Interface::Type type) const
TabletToolV2Interface * addTool(TabletToolV2Interface::Type type, quint64 hardwareSerial, quint64 hardwareId, const QList< TabletToolV2Interface::Capability > &capabilities, const QString &deviceSysName)
void removeDevice(const QString &sysname)
TabletV2Interface * addTablet(quint32 vendorId, quint32 productId, const QString &sysname, const QString &name, const QStringList &paths)
QList< InputRedirection::Capability > m_capabilities
InputRedirection::TabletToolType m_toolType
void cursorChanged(const TabletCursorSourceV2 &cursor)
void processMotion(qint32 id, const QPointF &pos, std::chrono::microseconds time, InputDevice *device=nullptr)
void setDecorationPressId(qint32 id)
Definition touch_input.h:47
void processUp(qint32 id, std::chrono::microseconds time, InputDevice *device=nullptr)
void processDown(qint32 id, const QPointF &pos, std::chrono::microseconds time, InputDevice *device=nullptr)
void setInternalPressId(qint32 id)
Definition touch_input.h:55
void tabletPadRingEvent(int number, int position, bool isFinger, const TabletPadId &tabletPadId, std::chrono::microseconds time) override
Definition input.cpp:2895
void holdGestureBegin(int fingerCount, std::chrono::microseconds time) override
Definition input.cpp:2866
void keyEvent(KeyEvent *event) override
Definition input.cpp:2814
void holdGestureCancelled(std::chrono::microseconds time) override
Definition input.cpp:2874
void touchDown(qint32 id, const QPointF &pos, std::chrono::microseconds time) override
Definition input.cpp:2819
void touchUp(qint32 id, std::chrono::microseconds time) override
Definition input.cpp:2827
void holdGestureEnd(std::chrono::microseconds time) override
Definition input.cpp:2870
void pointerEvent(MouseEvent *event) override
Definition input.cpp:2805
void pinchGestureBegin(int fingerCount, std::chrono::microseconds time) override
Definition input.cpp:2832
void tabletToolEvent(TabletEvent *event) override
Definition input.cpp:2879
void tabletPadStripEvent(int number, int position, bool isFinger, const TabletPadId &tabletPadId, std::chrono::microseconds time) override
Definition input.cpp:2891
void swipeGestureCancelled(std::chrono::microseconds time) override
Definition input.cpp:2861
void touchMotion(qint32 id, const QPointF &pos, std::chrono::microseconds time) override
Definition input.cpp:2823
void swipeGestureEnd(std::chrono::microseconds time) override
Definition input.cpp:2857
void pinchGestureCancelled(std::chrono::microseconds time) override
Definition input.cpp:2844
void swipeGestureUpdate(const QPointF &delta, std::chrono::microseconds time) override
Definition input.cpp:2853
void pinchGestureUpdate(qreal scale, qreal angleDelta, const QPointF &delta, std::chrono::microseconds time) override
Definition input.cpp:2836
void pinchGestureEnd(std::chrono::microseconds time) override
Definition input.cpp:2840
void tabletPadButtonEvent(uint button, bool pressed, const TabletPadId &tabletPadId, std::chrono::microseconds time) override
Definition input.cpp:2887
void wheelEvent(WheelEvent *event) override
Definition input.cpp:2809
void swipeGestureBegin(int fingerCount, std::chrono::microseconds time) override
Definition input.cpp:2849
void tabletToolButtonEvent(uint button, bool pressed, const TabletToolId &tabletToolId, std::chrono::microseconds time) override
Definition input.cpp:2883
void currentChanged(KWin::VirtualDesktop *previousDesktop, KWin::VirtualDesktop *newDesktop)
bool keyEvent(KeyEvent *event) override
Definition input.cpp:281
KXcursorTheme theme() const
bool hasGlobalShortcutSupport() const
bool isScreenLocked() const
Window * findWindow(const SurfaceInterface *surface) const
SeatInterface * seat() const
qint32 deltaV120() const
Definition input_event.h:95
std::chrono::microseconds timestamp() const
bool wheelEvent(WheelEvent *event) override
Definition input.cpp:1715
bool tabletToolEvent(TabletEvent *event) override
Definition input.cpp:1748
bool touchDown(qint32 id, const QPointF &pos, std::chrono::microseconds time) override
Definition input.cpp:1731
bool pointerEvent(MouseEvent *event, quint32 nativeButton) override
Definition input.cpp:1700
QMatrix4x4 inputTransformation() const
Definition window.cpp:374
QPointF mapToLocal(const QPointF &point) const
Definition window.cpp:399
virtual bool isClient() const
Definition window.cpp:302
bool isInteractiveMove() const
Definition window.h:1107
void updateInteractiveMoveResize(const QPointF &currentGlobalCursor)
Definition window.cpp:1378
void keyPressEvent(uint key_code)
Definition window.cpp:2531
void endInteractiveMoveResize()
Definition window.cpp:2614
SurfaceInterface * surface() const
Definition window.cpp:342
bool isHidden() const
Definition window.cpp:4237
bool readyForPainting() const
Definition window.h:1917
bool isOnCurrentActivity() const
Definition window.cpp:3097
bool isHiddenByShowDesktop() const
Definition window.cpp:4257
void surfaceChanged()
Options::MouseCommand getMouseCommand(Qt::MouseButton button, bool *handled) const
Definition window.cpp:1981
Decoration::DecoratedClientImpl * decoratedClient() const
Definition window.cpp:2811
bool isInteractiveResize() const
Definition window.h:1114
bool isOnCurrentDesktop() const
Definition window.cpp:848
bool isLockScreenOverlay() const
Definition window.cpp:4181
bool isMinimized() const
Definition window.h:988
bool performMouseCommand(Options::MouseCommand, const QPointF &globalPos)
Definition window.cpp:2022
virtual bool isLockScreen() const
Definition window.h:2007
virtual bool isInputMethod() const
Definition window.h:2012
virtual bool hitTest(const QPointF &point) const
Definition window.cpp:381
void setKeepAbove(bool)
Definition window.cpp:628
QRectF clientGeometry
Definition window.h:74
bool isDeleted() const
Definition window.cpp:540
void tabletToolButtonEvent(uint, bool pressed, const TabletToolId &, std::chrono::microseconds time) override
Definition input.cpp:2771
void tabletPadButtonEvent(uint, bool pressed, const TabletPadId &, std::chrono::microseconds time) override
Definition input.cpp:2763
void keyEvent(KeyEvent *event) override
Definition input.cpp:2747
void touchDown(qint32, const QPointF &, std::chrono::microseconds time) override
Definition input.cpp:2787
void tabletToolEvent(TabletEvent *event) override
Definition input.cpp:2779
void pointerEvent(MouseEvent *event) override
Definition input.cpp:2755
bool keyEvent(KeyEvent *event) override
Definition input.cpp:731
bool wheelEvent(WheelEvent *event) override
Definition input.cpp:726
void start(std::function< void(const QPoint &)> callback)
Definition input.cpp:821
bool pointerEvent(MouseEvent *event, quint32 nativeButton) override
Definition input.cpp:706
bool touchUp(qint32 id, std::chrono::microseconds time) override
Definition input.cpp:793
bool touchMotion(qint32 id, const QPointF &pos, std::chrono::microseconds time) override
Definition input.cpp:781
bool touchDown(qint32 id, const QPointF &pos, std::chrono::microseconds time) override
Definition input.cpp:772
void start(std::function< void(Window *)> callback)
Definition input.cpp:813
Window * activeWindow() const
Definition workspace.h:767
ScreenEdges * screenEdges() const
void activateWindow(Window *window, bool force=false)
const QList< Window * > & stackingOrder() const
Definition workspace.h:788
void stackingOrderChanged()
Window * moveResizeWindow()
Definition workspace.h:396
static Workspace * self()
Definition workspace.h:91
void updateFocusMousePosition(const QPointF &pos)
Definition workspace.h:820
QList< Output * > outputs() const
Definition workspace.h:762
const QList< Window * > windows() const
Definition workspace.h:248
bool takeActivity(Window *window, ActivityFlags flags)
void windowMinimizedChanged(KWin::Window *)
Output * outputAt(const QPointF &pos) const
void outputsChanged()
LEDs leds() const
Definition xkb.h:70
Qt::Key toQtKey(xkb_keysym_t keysym, uint32_t scanCode=0, Qt::KeyboardModifiers modifiers=Qt::KeyboardModifiers(), bool superAsMeta=false) const
Definition xkb.cpp:583
#define KWIN_SINGLETON_FACTORY(ClassName)
Definition globals.h:335
uint32_t xkb_keysym_t
int libinput_device_tablet_pad_get_num_buttons(struct libinput_device *device)
void * libinput_device_group_get_user_data(struct libinput_device_group *group)
int libinput_device_tablet_pad_get_num_rings(struct libinput_device *device)
struct libinput_device_group * libinput_device_get_device_group(struct libinput_device *device)
int libinput_device_tablet_pad_get_num_strips(struct libinput_device *device)
KWayland::Client::Seat * seat
void touchDown(qint32 id, const QPointF &pos, quint32 time)
void touchMotion(qint32 id, const QPointF &pos, quint32 time)
void touchUp(qint32 id, quint32 time)
PointerAxisDirection
The direction in which a pointer axis is moved.
Definition globals.h:104
@ PointerAxisUp
Definition globals.h:105
@ PointerAxisLeft
Definition globals.h:107
@ PointerAxisDown
Definition globals.h:106
@ PointerAxisRight
Definition globals.h:108
PointerAxisSource
Definition seat.h:53
uint32_t qtMouseButtonToButton(Qt::MouseButton button)
WaylandServer * waylandServer()
Workspace * workspace()
Definition workspace.h:830
PinchDirection
Definition globals.h:123
Options * options
Definition main.cpp:73
SwipeDirection
Directions for swipe gestures.
Definition globals.h:115
InputRedirection * input()
Definition input.h:549
KWIN_EXPORT QPoint flooredPoint(const QPointF &point)
Definition globals.h:262
EffectsHandler * effects
std::variant< TabletSurfaceCursorV2 *, QByteArray > TabletCursorSourceV2
Definition tablet_v2.h:77
#define dist(a, b)
Definition xcursor.c:384