File indexing completed on 2024-12-08 13:21:52

0001 /*
0002     KWin - the KDE window manager
0003     This file is part of the KDE project.
0004 
0005     SPDX-FileCopyrightText: 2013 Martin Gräßlin <mgraesslin@kde.org>
0006     SPDX-FileCopyrightText: 2018 Roman Gilg <subdiff@gmail.com>
0007     SPDX-FileCopyrightText: 2019 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
0008 
0009     SPDX-License-Identifier: GPL-2.0-or-later
0010 */
0011 #pragma once
0012 #include <config-kwin.h>
0013 
0014 #include <QObject>
0015 #include <QPoint>
0016 #include <QPointer>
0017 #include <kwinglobals.h>
0018 
0019 #include <KConfigWatcher>
0020 #include <KSharedConfig>
0021 #include <QSet>
0022 
0023 #include <functional>
0024 
0025 class KGlobalAccelInterface;
0026 class QAction;
0027 class QKeySequence;
0028 class QMouseEvent;
0029 class QKeyEvent;
0030 class QWheelEvent;
0031 
0032 namespace KWin
0033 {
0034 class IdleDetector;
0035 class Window;
0036 class GlobalShortcutsManager;
0037 class InputEventFilter;
0038 class InputEventSpy;
0039 class KeyboardInputRedirection;
0040 class PointerInputRedirection;
0041 class TabletInputRedirection;
0042 class TouchInputRedirection;
0043 class WindowSelectorFilter;
0044 class SwitchEvent;
0045 class TabletEvent;
0046 class TabletToolId;
0047 class TabletPadId;
0048 class MouseEvent;
0049 class WheelEvent;
0050 class KeyEvent;
0051 
0052 namespace Decoration
0053 {
0054 class DecoratedClientImpl;
0055 }
0056 
0057 class InputBackend;
0058 class InputDevice;
0059 
0060 /**
0061  * @brief This class is responsible for redirecting incoming input to the surface which currently
0062  * has input or send enter/leave events.
0063  *
0064  * In addition input is intercepted before passed to the surfaces to have KWin internal areas
0065  * getting input first (e.g. screen edges) and filter the input event out if we currently have
0066  * a full input grab.
0067  */
0068 class KWIN_EXPORT InputRedirection : public QObject
0069 {
0070     Q_OBJECT
0071 public:
0072     enum PointerButtonState {
0073         PointerButtonReleased,
0074         PointerButtonPressed
0075     };
0076     enum PointerAxis {
0077         PointerAxisVertical,
0078         PointerAxisHorizontal
0079     };
0080     enum PointerAxisSource {
0081         PointerAxisSourceUnknown,
0082         PointerAxisSourceWheel,
0083         PointerAxisSourceFinger,
0084         PointerAxisSourceContinuous,
0085         PointerAxisSourceWheelTilt
0086     };
0087     enum KeyboardKeyState {
0088         KeyboardKeyReleased,
0089         KeyboardKeyPressed,
0090         KeyboardKeyAutoRepeat
0091     };
0092     enum TabletEventType {
0093         Axis,
0094         Proximity,
0095         Tip
0096     };
0097     enum TabletToolType {
0098         Pen,
0099         Eraser,
0100         Brush,
0101         Pencil,
0102         Airbrush,
0103         Finger,
0104         Mouse,
0105         Lens,
0106         Totem,
0107     };
0108     enum Capability {
0109         Tilt,
0110         Pressure,
0111         Distance,
0112         Rotation,
0113         Slider,
0114         Wheel,
0115     };
0116 
0117     ~InputRedirection() override;
0118     void init();
0119 
0120     /**
0121      * @return const QPointF& The current global pointer position
0122      */
0123     QPointF globalPointer() const;
0124     Qt::MouseButtons qtButtonStates() const;
0125     Qt::KeyboardModifiers keyboardModifiers() const;
0126     Qt::KeyboardModifiers modifiersRelevantForGlobalShortcuts() const;
0127 
0128     void registerPointerShortcut(Qt::KeyboardModifiers modifiers, Qt::MouseButton pointerButtons, QAction *action);
0129     void registerAxisShortcut(Qt::KeyboardModifiers modifiers, PointerAxisDirection axis, QAction *action);
0130     void registerTouchpadSwipeShortcut(SwipeDirection direction, uint fingerCount, QAction *action);
0131     void registerRealtimeTouchpadSwipeShortcut(SwipeDirection direction, uint fingerCount, QAction *onUp, std::function<void(qreal)> progressCallback);
0132     void registerTouchpadPinchShortcut(PinchDirection direction, uint fingerCount, QAction *action);
0133     void registerRealtimeTouchpadPinchShortcut(PinchDirection direction, uint fingerCount, QAction *onUp, std::function<void(qreal)> progressCallback);
0134     void registerTouchscreenSwipeShortcut(SwipeDirection direction, uint fingerCount, QAction *action, std::function<void(qreal)> progressCallback);
0135     void forceRegisterTouchscreenSwipeShortcut(SwipeDirection direction, uint fingerCount, QAction *action, std::function<void(qreal)> progressCallback);
0136     void registerGlobalAccel(KGlobalAccelInterface *interface);
0137 
0138     bool supportsPointerWarping() const;
0139     void warpPointer(const QPointF &pos);
0140 
0141     /**
0142      * Adds the @p filter to the list of event filters and makes it the first
0143      * event filter in processing.
0144      *
0145      * Note: the event filter will get events before the lock screen can get them, thus
0146      * this is a security relevant method.
0147      */
0148     void prependInputEventFilter(InputEventFilter *filter);
0149     void uninstallInputEventFilter(InputEventFilter *filter);
0150 
0151     /**
0152      * Installs the @p spy for spying on events.
0153      */
0154     void installInputEventSpy(InputEventSpy *spy);
0155 
0156     /**
0157      * Uninstalls the @p spy. This happens automatically when deleting an InputEventSpy.
0158      */
0159     void uninstallInputEventSpy(InputEventSpy *spy);
0160 
0161     void simulateUserActivity();
0162 
0163     void addIdleDetector(IdleDetector *detector);
0164     void removeIdleDetector(IdleDetector *detector);
0165 
0166     QList<Window *> idleInhibitors() const;
0167     void addIdleInhibitor(Window *inhibitor);
0168     void removeIdleInhibitor(Window *inhibitor);
0169 
0170     Window *findToplevel(const QPointF &pos);
0171     GlobalShortcutsManager *shortcuts() const
0172     {
0173         return m_shortcuts;
0174     }
0175 
0176     /**
0177      * Sends an event through all InputFilters.
0178      * The method @p function is invoked on each input filter. Processing is stopped if
0179      * a filter returns @c true for @p function.
0180      *
0181      * The UnaryPredicate is defined like the UnaryPredicate of std::any_of.
0182      * The signature of the function should be equivalent to the following:
0183      * @code
0184      * bool function(const InputEventFilter *spy);
0185      * @endcode
0186      *
0187      * The intended usage is to std::bind the method to invoke on the filter with all arguments
0188      * bind.
0189      */
0190     template<class UnaryPredicate>
0191     void processFilters(UnaryPredicate function)
0192     {
0193         std::any_of(m_filters.constBegin(), m_filters.constEnd(), function);
0194     }
0195 
0196     /**
0197      * Sends an event through all input event spies.
0198      * The @p function is invoked on each InputEventSpy.
0199      *
0200      * The UnaryFunction is defined like the UnaryFunction of std::for_each.
0201      * The signature of the function should be equivalent to the following:
0202      * @code
0203      * void function(const InputEventSpy *spy);
0204      * @endcode
0205      *
0206      * The intended usage is to std::bind the method to invoke on the spies with all arguments
0207      * bind.
0208      */
0209     template<class UnaryFunction>
0210     void processSpies(UnaryFunction function)
0211     {
0212         std::for_each(m_spies.constBegin(), m_spies.constEnd(), function);
0213     }
0214 
0215     KeyboardInputRedirection *keyboard() const
0216     {
0217         return m_keyboard;
0218     }
0219     PointerInputRedirection *pointer() const
0220     {
0221         return m_pointer;
0222     }
0223     TabletInputRedirection *tablet() const
0224     {
0225         return m_tablet;
0226     }
0227     TouchInputRedirection *touch() const
0228     {
0229         return m_touch;
0230     }
0231 
0232     /**
0233      * Specifies which was the device that triggered the last input event
0234      */
0235     void setLastInputHandler(QObject *device);
0236     QObject *lastInputHandler() const;
0237 
0238     QList<InputDevice *> devices() const;
0239 
0240     bool hasAlphaNumericKeyboard();
0241     bool hasPointer() const;
0242     bool hasTouch() const;
0243     bool hasTabletModeSwitch();
0244 
0245     void startInteractiveWindowSelection(std::function<void(KWin::Window *)> callback, const QByteArray &cursorName);
0246     void startInteractivePositionSelection(std::function<void(const QPoint &)> callback);
0247     bool isSelectingWindow() const;
0248 
0249     void toggleTouchpads();
0250     void enableTouchpads();
0251     void disableTouchpads();
0252 
0253 Q_SIGNALS:
0254     void deviceAdded(InputDevice *device);
0255     void deviceRemoved(InputDevice *device);
0256     /**
0257      * @brief Emitted when the global pointer position changed
0258      *
0259      * @param pos The new global pointer position.
0260      */
0261     void globalPointerChanged(const QPointF &pos);
0262     /**
0263      * @brief Emitted when the state of a pointer button changed.
0264      *
0265      * @param button The button which changed
0266      * @param state The new button state
0267      */
0268     void pointerButtonStateChanged(uint32_t button, InputRedirection::PointerButtonState state);
0269     /**
0270      * @brief Emitted when a pointer axis changed
0271      *
0272      * @param axis The axis on which the even occurred
0273      * @param delta The delta of the event.
0274      */
0275     void pointerAxisChanged(InputRedirection::PointerAxis axis, qreal delta);
0276     /**
0277      * @brief Emitted when the modifiers changes.
0278      *
0279      * Only emitted for the mask which is provided by Qt::KeyboardModifiers, if other modifiers
0280      * change signal is not emitted
0281      *
0282      * @param newMods The new modifiers state
0283      * @param oldMods The previous modifiers state
0284      */
0285     void keyboardModifiersChanged(Qt::KeyboardModifiers newMods, Qt::KeyboardModifiers oldMods);
0286     /**
0287      * @brief Emitted when the state of a key changed.
0288      *
0289      * @param keyCode The keycode of the key which changed
0290      * @param state The new key state
0291      */
0292     void keyStateChanged(quint32 keyCode, InputRedirection::KeyboardKeyState state);
0293 
0294     void hasKeyboardChanged(bool set);
0295     void hasAlphaNumericKeyboardChanged(bool set);
0296     void hasPointerChanged(bool set);
0297     void hasTouchChanged(bool set);
0298     void hasTabletModeSwitchChanged(bool set);
0299 
0300 public Q_SLOTS:
0301     void addInputDevice(InputDevice *device);
0302     void removeInputDevice(InputDevice *device);
0303 
0304 private Q_SLOTS:
0305     void handleInputConfigChanged(const KConfigGroup &group);
0306     void updateScreens();
0307 
0308 private:
0309     void setupInputBackends();
0310     void setupTouchpadShortcuts();
0311     void setupWorkspace();
0312     void setupInputFilters();
0313     void installInputEventFilter(InputEventFilter *filter);
0314     void updateLeds(LEDs leds);
0315     void updateAvailableInputDevices();
0316     void addInputBackend(std::unique_ptr<InputBackend> &&inputBackend);
0317     KeyboardInputRedirection *m_keyboard;
0318     PointerInputRedirection *m_pointer;
0319     TabletInputRedirection *m_tablet;
0320     TouchInputRedirection *m_touch;
0321     QObject *m_lastInputDevice = nullptr;
0322 
0323     GlobalShortcutsManager *m_shortcuts;
0324 
0325     std::vector<std::unique_ptr<InputBackend>> m_inputBackends;
0326     QList<InputDevice *> m_inputDevices;
0327 
0328     QList<IdleDetector *> m_idleDetectors;
0329     QList<Window *> m_idleInhibitors;
0330     WindowSelectorFilter *m_windowSelector = nullptr;
0331 
0332     QVector<InputEventFilter *> m_filters;
0333     QVector<InputEventSpy *> m_spies;
0334     KConfigWatcher::Ptr m_inputConfigWatcher;
0335 
0336     LEDs m_leds;
0337     bool m_hasKeyboard = false;
0338     bool m_hasAlphaNumericKeyboard = false;
0339     bool m_hasPointer = false;
0340     bool m_hasTouch = false;
0341     bool m_hasTabletModeSwitch = false;
0342     bool m_touchpadsEnabled = true;
0343 
0344     KWIN_SINGLETON(InputRedirection)
0345     friend InputRedirection *input();
0346     friend class DecorationEventFilter;
0347     friend class InternalWindowEventFilter;
0348     friend class ForwardInputFilter;
0349 };
0350 
0351 /**
0352  * Base class for filtering input events inside InputRedirection.
0353  *
0354  * The idea behind the InputEventFilter is to have task oriented
0355  * filters. E.g. there is one filter taking care of a locked screen,
0356  * one to take care of interacting with window decorations, etc.
0357  *
0358  * A concrete subclass can reimplement the virtual methods and decide
0359  * whether an event should be filtered out or not by returning either
0360  * @c true or @c false. E.g. the lock screen filter can easily ensure
0361  * that all events are filtered out.
0362  *
0363  * As soon as a filter returns @c true the processing is stopped. If
0364  * a filter returns @c false the next one is invoked. This means a filter
0365  * installed early gets to see more events than a filter installed later on.
0366  *
0367  * Deleting an instance of InputEventFilter automatically uninstalls it from
0368  * InputRedirection.
0369  */
0370 class KWIN_EXPORT InputEventFilter
0371 {
0372 public:
0373     InputEventFilter();
0374     virtual ~InputEventFilter();
0375 
0376     /**
0377      * Event filter for pointer events which can be described by a QMouseEvent.
0378      *
0379      * Please note that the button translation in QMouseEvent cannot cover all
0380      * possible buttons. Because of that also the @p nativeButton code is passed
0381      * through the filter. For internal areas it's fine to use @p event, but for
0382      * passing to client windows the @p nativeButton should be used.
0383      *
0384      * @param event The event information about the move or button press/release
0385      * @param nativeButton The native key code of the button, for move events 0
0386      * @return @c true to stop further event processing, @c false to pass to next filter
0387      */
0388     virtual bool pointerEvent(MouseEvent *event, quint32 nativeButton);
0389     /**
0390      * Event filter for pointer axis events.
0391      *
0392      * @param event The event information about the axis event
0393      * @return @c true to stop further event processing, @c false to pass to next filter
0394      */
0395     virtual bool wheelEvent(WheelEvent *event);
0396     /**
0397      * Event filter for keyboard events.
0398      *
0399      * @param event The event information about the key event
0400      * @return @c true to stop further event processing, @c false to pass to next filter.
0401      */
0402     virtual bool keyEvent(KeyEvent *event);
0403     virtual bool touchDown(qint32 id, const QPointF &pos, std::chrono::microseconds time);
0404     virtual bool touchMotion(qint32 id, const QPointF &pos, std::chrono::microseconds time);
0405     virtual bool touchUp(qint32 id, std::chrono::microseconds time);
0406     virtual bool touchCancel();
0407     virtual bool touchFrame();
0408 
0409     virtual bool pinchGestureBegin(int fingerCount, std::chrono::microseconds time);
0410     virtual bool pinchGestureUpdate(qreal scale, qreal angleDelta, const QPointF &delta, std::chrono::microseconds time);
0411     virtual bool pinchGestureEnd(std::chrono::microseconds time);
0412     virtual bool pinchGestureCancelled(std::chrono::microseconds time);
0413 
0414     virtual bool swipeGestureBegin(int fingerCount, std::chrono::microseconds time);
0415     virtual bool swipeGestureUpdate(const QPointF &delta, std::chrono::microseconds time);
0416     virtual bool swipeGestureEnd(std::chrono::microseconds time);
0417     virtual bool swipeGestureCancelled(std::chrono::microseconds time);
0418 
0419     virtual bool holdGestureBegin(int fingerCount, std::chrono::microseconds time);
0420     virtual bool holdGestureEnd(std::chrono::microseconds time);
0421     virtual bool holdGestureCancelled(std::chrono::microseconds time);
0422 
0423     virtual bool switchEvent(SwitchEvent *event);
0424 
0425     virtual bool tabletToolEvent(TabletEvent *event);
0426     virtual bool tabletToolButtonEvent(uint button, bool pressed, const TabletToolId &tabletToolId, std::chrono::microseconds time);
0427     virtual bool tabletPadButtonEvent(uint button, bool pressed, const TabletPadId &tabletPadId, std::chrono::microseconds time);
0428     virtual bool tabletPadStripEvent(int number, int position, bool isFinger, const TabletPadId &tabletPadId, std::chrono::microseconds time);
0429     virtual bool tabletPadRingEvent(int number, int position, bool isFinger, const TabletPadId &tabletPadId, std::chrono::microseconds time);
0430 
0431 protected:
0432     void passToWaylandServer(QKeyEvent *event);
0433     bool passToInputMethod(QKeyEvent *event);
0434 };
0435 
0436 class KWIN_EXPORT InputDeviceHandler : public QObject
0437 {
0438     Q_OBJECT
0439 public:
0440     ~InputDeviceHandler() override;
0441     virtual void init();
0442 
0443     void update();
0444 
0445     /**
0446      * @brief First Window currently at the position of the input device
0447      * according to the stacking order.
0448      * @return Window* at device position.
0449      *
0450      * This will be null if no window is at the position
0451      */
0452     Window *hover() const;
0453     /**
0454      * @brief Window currently having pointer input focus (this might
0455      * be different from the Window at the position of the pointer).
0456      * @return Window* with pointer focus.
0457      *
0458      * This will be null if no window has focus
0459      */
0460     Window *focus() const;
0461 
0462     /**
0463      * @brief The Decoration currently receiving events.
0464      * @return decoration with pointer focus.
0465      */
0466     Decoration::DecoratedClientImpl *decoration() const;
0467 
0468     virtual QPointF position() const = 0;
0469 
0470     void setFocus(Window *window);
0471     void setDecoration(Decoration::DecoratedClientImpl *decoration);
0472 
0473 Q_SIGNALS:
0474     void decorationChanged();
0475 
0476 protected:
0477     explicit InputDeviceHandler(InputRedirection *parent);
0478 
0479     virtual void cleanupDecoration(Decoration::DecoratedClientImpl *old, Decoration::DecoratedClientImpl *now) = 0;
0480 
0481     virtual void focusUpdate(Window *old, Window *now) = 0;
0482 
0483     /**
0484      * Certain input devices can be in a state of having no valid
0485      * position. An example are touch screens when no finger/pen
0486      * is resting on the surface (no touch point).
0487      */
0488     virtual bool positionValid() const
0489     {
0490         return true;
0491     }
0492     virtual bool focusUpdatesBlocked()
0493     {
0494         return false;
0495     }
0496 
0497     inline bool inited() const
0498     {
0499         return m_inited;
0500     }
0501     inline void setInited(bool set)
0502     {
0503         m_inited = set;
0504     }
0505 
0506 private:
0507     bool setHover(Window *window);
0508     void updateFocus();
0509     void updateDecoration();
0510 
0511     struct
0512     {
0513         QPointer<Window> window;
0514         QMetaObject::Connection surfaceCreatedConnection;
0515     } m_hover;
0516 
0517     struct
0518     {
0519         QPointer<Window> window;
0520         QPointer<Decoration::DecoratedClientImpl> decoration;
0521     } m_focus;
0522 
0523     bool m_inited = false;
0524 };
0525 
0526 inline InputRedirection *input()
0527 {
0528     return InputRedirection::s_self;
0529 }
0530 
0531 inline QList<InputDevice *> InputRedirection::devices() const
0532 {
0533     return m_inputDevices;
0534 }
0535 
0536 } // namespace KWin
0537 
0538 Q_DECLARE_METATYPE(KWin::InputRedirection::KeyboardKeyState)
0539 Q_DECLARE_METATYPE(KWin::InputRedirection::PointerButtonState)
0540 Q_DECLARE_METATYPE(KWin::InputRedirection::PointerAxis)
0541 Q_DECLARE_METATYPE(KWin::InputRedirection::PointerAxisSource)