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)