File indexing completed on 2024-04-28 16:48:47

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 
0007     SPDX-License-Identifier: GPL-2.0-or-later
0008 */
0009 #pragma once
0010 // KWin
0011 #include <kwinglobals.h>
0012 // Qt
0013 #include <QKeySequence>
0014 
0015 #include <memory>
0016 
0017 class QAction;
0018 class KGlobalAccelD;
0019 class KGlobalAccelInterface;
0020 
0021 namespace KWin
0022 {
0023 class GlobalShortcut;
0024 class SwipeGesture;
0025 class PinchGesture;
0026 class GestureRecognizer;
0027 
0028 enum class DeviceType {
0029     Touchpad,
0030     Touchscreen
0031 };
0032 
0033 /**
0034  * @brief Manager for the global shortcut system inside KWin.
0035  *
0036  * This class is responsible for holding all the global shortcuts and to process a key press event.
0037  * That is trigger a shortcut if there is a match.
0038  *
0039  * For internal shortcut handling (those which are delivered inside KWin) QActions are used and
0040  * triggered if the shortcut matches. For external shortcut handling a DBus interface is used.
0041  */
0042 class GlobalShortcutsManager : public QObject
0043 {
0044     Q_OBJECT
0045 public:
0046     explicit GlobalShortcutsManager(QObject *parent = nullptr);
0047     ~GlobalShortcutsManager() override;
0048     void init();
0049 
0050     /**
0051      * @brief Registers an internal global pointer shortcut
0052      *
0053      * @param action The action to trigger if the shortcut is pressed
0054      * @param modifiers The modifiers which need to be hold to trigger the action
0055      * @param pointerButtons The pointer button which needs to be pressed
0056      */
0057     void registerPointerShortcut(QAction *action, Qt::KeyboardModifiers modifiers, Qt::MouseButtons pointerButtons);
0058     /**
0059      * @brief Registers an internal global axis shortcut
0060      *
0061      * @param action The action to trigger if the shortcut is triggered
0062      * @param modifiers The modifiers which need to be hold to trigger the action
0063      * @param axis The pointer axis
0064      */
0065     void registerAxisShortcut(QAction *action, Qt::KeyboardModifiers modifiers, PointerAxisDirection axis);
0066 
0067     void registerTouchpadSwipe(QAction *action, SwipeDirection direction, uint fingerCount = 4);
0068 
0069     void registerRealtimeTouchpadSwipe(QAction *onUp, std::function<void(qreal)> progressCallback, SwipeDirection direction, uint fingerCount = 4);
0070 
0071     void registerTouchpadPinch(QAction *action, PinchDirection direction, uint fingerCount = 4);
0072 
0073     void registerRealtimeTouchpadPinch(QAction *onUp, std::function<void(qreal)> progressCallback, PinchDirection direction, uint fingerCount = 4);
0074 
0075     void registerTouchscreenSwipe(QAction *action, std::function<void(qreal)> progressCallback, SwipeDirection direction, uint fingerCount);
0076     void forceRegisterTouchscreenSwipe(QAction *action, std::function<void(qreal)> progressCallback, SwipeDirection direction, uint fingerCount);
0077 
0078     /**
0079      * @brief Processes a key event to decide whether a shortcut needs to be triggered.
0080      *
0081      * If a shortcut triggered this method returns @c true to indicate to the caller that the event
0082      * should not be further processed. If there is no shortcut which triggered for the key, then
0083      * @c false is returned.
0084      *
0085      * @param modifiers The current hold modifiers
0086      * @param keyQt The Qt::Key which got pressed
0087      * @return @c true if a shortcut triggered, @c false otherwise
0088      */
0089     bool processKey(Qt::KeyboardModifiers modifiers, int keyQt);
0090     bool processKeyRelease(Qt::KeyboardModifiers modifiers, int keyQt);
0091     bool processPointerPressed(Qt::KeyboardModifiers modifiers, Qt::MouseButtons pointerButtons);
0092     /**
0093      * @brief Processes a pointer axis event to decide whether a shortcut needs to be triggered.
0094      *
0095      * If a shortcut triggered this method returns @c true to indicate to the caller that the event
0096      * should not be further processed. If there is no shortcut which triggered for the key, then
0097      * @c false is returned.
0098      *
0099      * @param modifiers The current hold modifiers
0100      * @param axis The axis direction which has triggered this event
0101      * @return @c true if a shortcut triggered, @c false otherwise
0102      */
0103     bool processAxis(Qt::KeyboardModifiers modifiers, PointerAxisDirection axis);
0104 
0105     void processSwipeStart(DeviceType device, uint fingerCount);
0106     void processSwipeUpdate(DeviceType device, const QPointF &delta);
0107     void processSwipeCancel(DeviceType device);
0108     void processSwipeEnd(DeviceType device);
0109 
0110     void processPinchStart(uint fingerCount);
0111     void processPinchUpdate(qreal scale, qreal angleDelta, const QPointF &delta);
0112     void processPinchCancel();
0113     void processPinchEnd();
0114 
0115     void setKGlobalAccelInterface(KGlobalAccelInterface *interface)
0116     {
0117         m_kglobalAccelInterface = interface;
0118     }
0119 
0120 private:
0121     void objectDeleted(QObject *object);
0122     bool addIfNotExists(GlobalShortcut sc, DeviceType device = DeviceType::Touchpad);
0123 
0124     QVector<GlobalShortcut> m_shortcuts;
0125 
0126     std::unique_ptr<KGlobalAccelD> m_kglobalAccel;
0127     KGlobalAccelInterface *m_kglobalAccelInterface = nullptr;
0128     std::unique_ptr<GestureRecognizer> m_touchpadGestureRecognizer;
0129     std::unique_ptr<GestureRecognizer> m_touchscreenGestureRecognizer;
0130 };
0131 
0132 struct KeyboardShortcut
0133 {
0134     QKeySequence sequence;
0135     bool operator==(const KeyboardShortcut &rhs) const
0136     {
0137         return sequence == rhs.sequence;
0138     }
0139 };
0140 struct PointerButtonShortcut
0141 {
0142     Qt::KeyboardModifiers pointerModifiers;
0143     Qt::MouseButtons pointerButtons;
0144     bool operator==(const PointerButtonShortcut &rhs) const
0145     {
0146         return pointerModifiers == rhs.pointerModifiers && pointerButtons == rhs.pointerButtons;
0147     }
0148 };
0149 struct PointerAxisShortcut
0150 {
0151     Qt::KeyboardModifiers axisModifiers;
0152     PointerAxisDirection axisDirection;
0153     bool operator==(const PointerAxisShortcut &rhs) const
0154     {
0155         return axisModifiers == rhs.axisModifiers && axisDirection == rhs.axisDirection;
0156     }
0157 };
0158 struct SwipeShortcut
0159 {
0160     DeviceType device;
0161     SwipeDirection direction;
0162     uint fingerCount;
0163     bool operator==(const SwipeShortcut &rhs) const
0164     {
0165         return direction == rhs.direction && fingerCount == rhs.fingerCount && device == rhs.device;
0166     }
0167 };
0168 struct RealtimeFeedbackSwipeShortcut
0169 {
0170     DeviceType device;
0171     SwipeDirection direction;
0172     std::function<void(qreal)> progressCallback;
0173     uint fingerCount;
0174 
0175     template<typename T>
0176     bool operator==(const T &rhs) const
0177     {
0178         return direction == rhs.direction && fingerCount == rhs.fingerCount && device == rhs.device;
0179     }
0180 };
0181 
0182 struct PinchShortcut
0183 {
0184     PinchDirection direction;
0185     uint fingerCount;
0186     bool operator==(const PinchShortcut &rhs) const
0187     {
0188         return direction == rhs.direction && fingerCount == rhs.fingerCount;
0189     }
0190 };
0191 
0192 struct RealtimeFeedbackPinchShortcut
0193 {
0194     PinchDirection direction;
0195     std::function<void(qreal)> scaleCallback;
0196     uint fingerCount;
0197 
0198     template<typename T>
0199     bool operator==(const T &rhs) const
0200     {
0201         return direction == rhs.direction && fingerCount == rhs.fingerCount;
0202     }
0203 };
0204 
0205 using Shortcut = std::variant<KeyboardShortcut, PointerButtonShortcut, PointerAxisShortcut, SwipeShortcut, RealtimeFeedbackSwipeShortcut, PinchShortcut, RealtimeFeedbackPinchShortcut>;
0206 
0207 class GlobalShortcut
0208 {
0209 public:
0210     GlobalShortcut(Shortcut &&shortcut, QAction *action);
0211     ~GlobalShortcut();
0212 
0213     void invoke() const;
0214     QAction *action() const;
0215     const Shortcut &shortcut() const;
0216     SwipeGesture *swipeGesture() const;
0217     PinchGesture *pinchGesture() const;
0218 
0219 private:
0220     std::shared_ptr<SwipeGesture> m_swipeGesture;
0221     std::shared_ptr<PinchGesture> m_pinchGesture;
0222     Shortcut m_shortcut = {};
0223     QAction *m_action = nullptr;
0224 };
0225 
0226 } // namespace