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