diff --git a/globalshortcuts.cpp b/globalshortcuts.cpp index 4b96597af0..bd80397019 100644 --- a/globalshortcuts.cpp +++ b/globalshortcuts.cpp @@ -32,6 +32,15 @@ namespace KWin GlobalShortcut::GlobalShortcut(const QKeySequence &shortcut) : m_shortcut(shortcut) + , m_pointerModifiers(Qt::NoModifier) + , m_pointerButtons(Qt::NoButton) +{ +} + +GlobalShortcut::GlobalShortcut(Qt::KeyboardModifiers pointerButtonModifiers, Qt::MouseButtons pointerButtons) + : m_shortcut(QKeySequence()) + , m_pointerModifiers(pointerButtonModifiers) + , m_pointerButtons(pointerButtons) { } @@ -45,6 +54,12 @@ InternalGlobalShortcut::InternalGlobalShortcut(const QKeySequence &shortcut, QAc { } +InternalGlobalShortcut::InternalGlobalShortcut(Qt::KeyboardModifiers pointerButtonModifiers, Qt::MouseButtons pointerButtons, QAction *action) + : GlobalShortcut(pointerButtonModifiers, pointerButtons) + , m_action(action) +{ +} + InternalGlobalShortcut::~InternalGlobalShortcut() { } @@ -61,16 +76,24 @@ GlobalShortcutsManager::GlobalShortcutsManager(QObject *parent) { } -GlobalShortcutsManager::~GlobalShortcutsManager() +template +void clearShortcuts(T &shortcuts) { - for (auto it = m_shortcuts.begin(); it != m_shortcuts.end(); ++it) { + for (auto it = shortcuts.begin(); it != shortcuts.end(); ++it) { qDeleteAll((*it)); } } -void GlobalShortcutsManager::objectDeleted(QObject *object) +GlobalShortcutsManager::~GlobalShortcutsManager() { - for (auto it = m_shortcuts.begin(); it != m_shortcuts.end(); ++it) { + clearShortcuts(m_shortcuts); + clearShortcuts(m_pointerShortcuts); +} + +template +void handleDestroyedAction(QObject *object, T &shortcuts) +{ + for (auto it = shortcuts.begin(); it != shortcuts.end(); ++it) { auto list = (*it); for (auto it2 = list.begin(); it2 != list.end(); ++it2) { if (InternalGlobalShortcut *shortcut = dynamic_cast((*it2))) { @@ -83,6 +106,12 @@ void GlobalShortcutsManager::objectDeleted(QObject *object) } } +void GlobalShortcutsManager::objectDeleted(QObject *object) +{ + handleDestroyedAction(object, m_shortcuts); + handleDestroyedAction(object, m_pointerShortcuts); +} + void GlobalShortcutsManager::registerShortcut(QAction *action, const QKeySequence &shortcut) { QKeySequence s = getShortcutForAction(KWIN_NAME, action->objectName(), shortcut); @@ -121,6 +150,21 @@ void GlobalShortcutsManager::registerShortcut(QAction *action, const QKeySequenc connect(action, &QAction::destroyed, this, &GlobalShortcutsManager::objectDeleted); } +void GlobalShortcutsManager::registerPointerShortcut(QAction *action, Qt::KeyboardModifiers modifiers, Qt::MouseButtons pointerButtons) +{ + GlobalShortcut *cut = new InternalGlobalShortcut(modifiers, pointerButtons, action); + auto it = m_pointerShortcuts.find(modifiers); + if (it != m_pointerShortcuts.end()) { + // TODO: check if shortcut already exists + (*it).insert(pointerButtons, cut); + } else { + QHash shortcuts; + shortcuts.insert(pointerButtons, cut); + m_pointerShortcuts.insert(modifiers, shortcuts); + } + connect(action, &QAction::destroyed, this, &GlobalShortcutsManager::objectDeleted); +} + QKeySequence GlobalShortcutsManager::getShortcutForAction(const QString &componentName, const QString &actionName, const QKeySequence &defaultShortcut) { if (!m_config->hasGroup(componentName)) { @@ -141,10 +185,11 @@ QKeySequence GlobalShortcutsManager::getShortcutForAction(const QString &compone return QKeySequence(parts.first()); } -bool GlobalShortcutsManager::processKey(Qt::KeyboardModifiers mods, uint32_t key) +template +bool processShortcut(Qt::KeyboardModifiers mods, T key, U &shortcuts) { - auto it = m_shortcuts.find(mods); - if (it == m_shortcuts.end()) { + auto it = shortcuts.find(mods); + if (it == shortcuts.end()) { return false; } auto it2 = (*it).find(key); @@ -155,4 +200,14 @@ bool GlobalShortcutsManager::processKey(Qt::KeyboardModifiers mods, uint32_t key return true; } +bool GlobalShortcutsManager::processKey(Qt::KeyboardModifiers mods, uint32_t key) +{ + return processShortcut(mods, key, m_shortcuts); +} + +bool GlobalShortcutsManager::processPointerPressed(Qt::KeyboardModifiers mods, Qt::MouseButtons pointerButtons) +{ + return processShortcut(mods, pointerButtons, m_pointerShortcuts); +} + } // namespace diff --git a/globalshortcuts.h b/globalshortcuts.h index 2c11e9e1d5..9a6f0343ed 100644 --- a/globalshortcuts.h +++ b/globalshortcuts.h @@ -53,6 +53,14 @@ public: * @param shortcut The key sequence which triggers this shortcut */ void registerShortcut(QAction *action, const QKeySequence &shortcut); + /** + * @brief Registers an internal global pointer shortcut + * + * @param action The action to trigger if the shortcut is pressed + * @param modifiers The modifiers which need to be hold to trigger the action + * @param pointerButtons The pointer button which needs to be pressed + */ + void registerPointerShortcut(QAction *action, Qt::KeyboardModifiers modifiers, Qt::MouseButtons pointerButtons); /** * @brief Processes a key event to decide whether a shortcut needs to be triggered. @@ -66,10 +74,12 @@ public: * @return @c true if a shortcut triggered, @c false otherwise */ bool processKey(Qt::KeyboardModifiers modifiers, uint32_t key); + bool processPointerPressed(Qt::KeyboardModifiers modifiers, Qt::MouseButtons pointerButtons); private: void objectDeleted(QObject *object); QKeySequence getShortcutForAction(const QString &componentName, const QString &actionName, const QKeySequence &defaultShortcut); QHash > m_shortcuts; + QHash > m_pointerShortcuts; KSharedConfigPtr m_config; }; @@ -79,19 +89,25 @@ public: virtual ~GlobalShortcut(); const QKeySequence &shortcut() const; + Qt::KeyboardModifiers pointerButtonModifiers() const; + Qt::MouseButtons pointerButtons() const; virtual void invoke() = 0; protected: GlobalShortcut(const QKeySequence &shortcut); + GlobalShortcut(Qt::KeyboardModifiers pointerButtonModifiers, Qt::MouseButtons pointerButtons); private: QKeySequence m_shortcut; + Qt::KeyboardModifiers m_pointerModifiers; + Qt::MouseButtons m_pointerButtons; }; class InternalGlobalShortcut : public GlobalShortcut { public: InternalGlobalShortcut(const QKeySequence &shortcut, QAction *action); + InternalGlobalShortcut(Qt::KeyboardModifiers pointerButtonModifiers, Qt::MouseButtons pointerButtons, QAction *action); virtual ~InternalGlobalShortcut(); void invoke() override; @@ -113,6 +129,18 @@ const QKeySequence &GlobalShortcut::shortcut() const return m_shortcut; } +inline +Qt::KeyboardModifiers GlobalShortcut::pointerButtonModifiers() const +{ + return m_pointerModifiers; +} + +inline +Qt::MouseButtons GlobalShortcut::pointerButtons() const +{ + return m_pointerButtons; +} + } // namespace #endif diff --git a/input.cpp b/input.cpp index 571264417c..31216d92f1 100644 --- a/input.cpp +++ b/input.cpp @@ -230,6 +230,13 @@ void InputRedirection::processPointerButton(uint32_t button, InputRedirection::P // an effect grabbed the pointer, we do not forward the event to surfaces return; } +#if HAVE_XKB + if (state == KWin::InputRedirection::PointerButtonPressed) { + if (m_shortcuts->processPointerPressed(m_xkb->modifiers(), qtButtonStates())) { + return; + } + } +#endif // TODO: check which part of KWin would like to intercept the event if (m_pointerWindow.isNull()) { // there is no window which can receive the @@ -447,4 +454,9 @@ void InputRedirection::registerShortcut(const QKeySequence &shortcut, QAction *a m_shortcuts->registerShortcut(action, shortcut); } +void InputRedirection::registerPointerShortcut(Qt::KeyboardModifiers modifiers, Qt::MouseButton pointerButtons, QAction *action) +{ + m_shortcuts->registerPointerShortcut(action, modifiers, pointerButtons); +} + } // namespace diff --git a/input.h b/input.h index ddcdf5b14b..695d9fa614 100644 --- a/input.h +++ b/input.h @@ -82,6 +82,7 @@ public: Qt::KeyboardModifiers keyboardModifiers() const; void registerShortcut(const QKeySequence &shortcut, QAction *action); + void registerPointerShortcut(Qt::KeyboardModifiers modifiers, Qt::MouseButton pointerButtons, QAction *action); /** * @internal