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)