Support for global pointer shortcut activation

Sharing most of the code with keyboard shortcuts allowing to trigger a
QAction with holding modifiers and clicking a mouse button.
This commit is contained in:
Martin Gräßlin 2013-07-14 22:52:58 +02:00
parent 38201a8295
commit 28406d153d
4 changed files with 103 additions and 7 deletions

View file

@ -32,6 +32,15 @@ namespace KWin
GlobalShortcut::GlobalShortcut(const QKeySequence &shortcut) GlobalShortcut::GlobalShortcut(const QKeySequence &shortcut)
: m_shortcut(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() InternalGlobalShortcut::~InternalGlobalShortcut()
{ {
} }
@ -61,16 +76,24 @@ GlobalShortcutsManager::GlobalShortcutsManager(QObject *parent)
{ {
} }
GlobalShortcutsManager::~GlobalShortcutsManager() template <typename T>
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)); 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 <typename T>
void handleDestroyedAction(QObject *object, T &shortcuts)
{
for (auto it = shortcuts.begin(); it != shortcuts.end(); ++it) {
auto list = (*it); auto list = (*it);
for (auto it2 = list.begin(); it2 != list.end(); ++it2) { for (auto it2 = list.begin(); it2 != list.end(); ++it2) {
if (InternalGlobalShortcut *shortcut = dynamic_cast<InternalGlobalShortcut*>((*it2))) { if (InternalGlobalShortcut *shortcut = dynamic_cast<InternalGlobalShortcut*>((*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) void GlobalShortcutsManager::registerShortcut(QAction *action, const QKeySequence &shortcut)
{ {
QKeySequence s = getShortcutForAction(KWIN_NAME, action->objectName(), 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); 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<Qt::MouseButtons, GlobalShortcut*> 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) QKeySequence GlobalShortcutsManager::getShortcutForAction(const QString &componentName, const QString &actionName, const QKeySequence &defaultShortcut)
{ {
if (!m_config->hasGroup(componentName)) { if (!m_config->hasGroup(componentName)) {
@ -141,10 +185,11 @@ QKeySequence GlobalShortcutsManager::getShortcutForAction(const QString &compone
return QKeySequence(parts.first()); return QKeySequence(parts.first());
} }
bool GlobalShortcutsManager::processKey(Qt::KeyboardModifiers mods, uint32_t key) template <typename T, typename U>
bool processShortcut(Qt::KeyboardModifiers mods, T key, U &shortcuts)
{ {
auto it = m_shortcuts.find(mods); auto it = shortcuts.find(mods);
if (it == m_shortcuts.end()) { if (it == shortcuts.end()) {
return false; return false;
} }
auto it2 = (*it).find(key); auto it2 = (*it).find(key);
@ -155,4 +200,14 @@ bool GlobalShortcutsManager::processKey(Qt::KeyboardModifiers mods, uint32_t key
return true; 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 } // namespace

View file

@ -53,6 +53,14 @@ public:
* @param shortcut The key sequence which triggers this shortcut * @param shortcut The key sequence which triggers this shortcut
*/ */
void registerShortcut(QAction *action, const QKeySequence &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. * @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 * @return @c true if a shortcut triggered, @c false otherwise
*/ */
bool processKey(Qt::KeyboardModifiers modifiers, uint32_t key); bool processKey(Qt::KeyboardModifiers modifiers, uint32_t key);
bool processPointerPressed(Qt::KeyboardModifiers modifiers, Qt::MouseButtons pointerButtons);
private: private:
void objectDeleted(QObject *object); void objectDeleted(QObject *object);
QKeySequence getShortcutForAction(const QString &componentName, const QString &actionName, const QKeySequence &defaultShortcut); QKeySequence getShortcutForAction(const QString &componentName, const QString &actionName, const QKeySequence &defaultShortcut);
QHash<Qt::KeyboardModifiers, QHash<uint32_t, GlobalShortcut*> > m_shortcuts; QHash<Qt::KeyboardModifiers, QHash<uint32_t, GlobalShortcut*> > m_shortcuts;
QHash<Qt::KeyboardModifiers, QHash<Qt::MouseButtons, GlobalShortcut*> > m_pointerShortcuts;
KSharedConfigPtr m_config; KSharedConfigPtr m_config;
}; };
@ -79,19 +89,25 @@ public:
virtual ~GlobalShortcut(); virtual ~GlobalShortcut();
const QKeySequence &shortcut() const; const QKeySequence &shortcut() const;
Qt::KeyboardModifiers pointerButtonModifiers() const;
Qt::MouseButtons pointerButtons() const;
virtual void invoke() = 0; virtual void invoke() = 0;
protected: protected:
GlobalShortcut(const QKeySequence &shortcut); GlobalShortcut(const QKeySequence &shortcut);
GlobalShortcut(Qt::KeyboardModifiers pointerButtonModifiers, Qt::MouseButtons pointerButtons);
private: private:
QKeySequence m_shortcut; QKeySequence m_shortcut;
Qt::KeyboardModifiers m_pointerModifiers;
Qt::MouseButtons m_pointerButtons;
}; };
class InternalGlobalShortcut : public GlobalShortcut class InternalGlobalShortcut : public GlobalShortcut
{ {
public: public:
InternalGlobalShortcut(const QKeySequence &shortcut, QAction *action); InternalGlobalShortcut(const QKeySequence &shortcut, QAction *action);
InternalGlobalShortcut(Qt::KeyboardModifiers pointerButtonModifiers, Qt::MouseButtons pointerButtons, QAction *action);
virtual ~InternalGlobalShortcut(); virtual ~InternalGlobalShortcut();
void invoke() override; void invoke() override;
@ -113,6 +129,18 @@ const QKeySequence &GlobalShortcut::shortcut() const
return m_shortcut; return m_shortcut;
} }
inline
Qt::KeyboardModifiers GlobalShortcut::pointerButtonModifiers() const
{
return m_pointerModifiers;
}
inline
Qt::MouseButtons GlobalShortcut::pointerButtons() const
{
return m_pointerButtons;
}
} // namespace } // namespace
#endif #endif

View file

@ -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 // an effect grabbed the pointer, we do not forward the event to surfaces
return; 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 // TODO: check which part of KWin would like to intercept the event
if (m_pointerWindow.isNull()) { if (m_pointerWindow.isNull()) {
// there is no window which can receive the // 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); m_shortcuts->registerShortcut(action, shortcut);
} }
void InputRedirection::registerPointerShortcut(Qt::KeyboardModifiers modifiers, Qt::MouseButton pointerButtons, QAction *action)
{
m_shortcuts->registerPointerShortcut(action, modifiers, pointerButtons);
}
} // namespace } // namespace

View file

@ -82,6 +82,7 @@ public:
Qt::KeyboardModifiers keyboardModifiers() const; Qt::KeyboardModifiers keyboardModifiers() const;
void registerShortcut(const QKeySequence &shortcut, QAction *action); void registerShortcut(const QKeySequence &shortcut, QAction *action);
void registerPointerShortcut(Qt::KeyboardModifiers modifiers, Qt::MouseButton pointerButtons, QAction *action);
/** /**
* @internal * @internal