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)
: 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 <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));
}
}
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);
for (auto it2 = list.begin(); it2 != list.end(); ++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)
{
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<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)
{
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 <typename T, typename U>
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

View file

@ -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<Qt::KeyboardModifiers, QHash<uint32_t, GlobalShortcut*> > m_shortcuts;
QHash<Qt::KeyboardModifiers, QHash<Qt::MouseButtons, GlobalShortcut*> > 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

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
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

View file

@ -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