Add support for modifier only shortcuts on Wayland
On popular demand! This change tracks how modifiers are used and detects a modifier only key press/release. That is: * no other key is pressed when the modifier gets pressed * no other key gets pressed before the modifier gets released If such a press/release is detected, we call a configurable dbus call. The possible shortcuts can be configured in kwinrc, group "ModifierOnlyShortcuts". The following keys are supported: * Shift * Control * Alt * Meta As value it takes a QStringList (comma seperated string) with service,path,interface,method,additionalargs E.g. to invoke Desktop Grid effect on Meta key: [ModifierOnlyShortcuts] Meta=org.kde.kglobalaccel,/component/kwin/,org.kde.kglobalaccel.Component,invokeShortcut,ShowDesktopGrid I do not intend to add a config interface for it. Let's keep it a hidden way. REVIEW: 124954
This commit is contained in:
parent
f6f555d688
commit
07414e88a5
4 changed files with 57 additions and 0 deletions
28
input.cpp
28
input.cpp
|
@ -42,6 +42,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
#include <decorations/decoratedclient.h>
|
||||
#include <KDecoration2/Decoration>
|
||||
// Qt
|
||||
#include <QDBusMessage>
|
||||
#include <QDBusPendingCall>
|
||||
#include <QKeyEvent>
|
||||
#include <QMouseEvent>
|
||||
#include <QTemporaryFile>
|
||||
|
@ -183,6 +185,32 @@ void Xkb::updateKey(uint32_t key, InputRedirection::KeyboardKeyState state)
|
|||
}
|
||||
xkb_state_update_key(m_state, key + 8, static_cast<xkb_key_direction>(state));
|
||||
updateModifiers();
|
||||
if (state == InputRedirection::KeyboardKeyPressed) {
|
||||
m_modOnlyShortcut.pressCount++;
|
||||
if (m_modOnlyShortcut.pressCount == 1) {
|
||||
m_modOnlyShortcut.modifier = Qt::KeyboardModifier(int(m_modifiers));
|
||||
} else {
|
||||
m_modOnlyShortcut.modifier = Qt::NoModifier;
|
||||
}
|
||||
} else {
|
||||
m_modOnlyShortcut.pressCount--;
|
||||
// TODO: ignore on lock screen
|
||||
if (m_modOnlyShortcut.pressCount == 0) {
|
||||
if (m_modOnlyShortcut.modifier != Qt::NoModifier) {
|
||||
const auto list = options->modifierOnlyDBusShortcut(m_modOnlyShortcut.modifier);
|
||||
if (list.size() >= 4) {
|
||||
auto call = QDBusMessage::createMethodCall(list.at(0), list.at(1), list.at(2), list.at(3));
|
||||
QVariantList args;
|
||||
for (int i = 4; i < list.size(); ++i) {
|
||||
args << list.at(i);
|
||||
}
|
||||
call.setArguments(args);
|
||||
QDBusConnection::sessionBus().asyncCall(call);
|
||||
}
|
||||
}
|
||||
}
|
||||
m_modOnlyShortcut.modifier = Qt::NoModifier;
|
||||
}
|
||||
}
|
||||
|
||||
void Xkb::updateModifiers()
|
||||
|
|
4
input.h
4
input.h
|
@ -262,6 +262,10 @@ private:
|
|||
xkb_mod_index_t m_altModifier;
|
||||
xkb_mod_index_t m_metaModifier;
|
||||
Qt::KeyboardModifiers m_modifiers;
|
||||
struct {
|
||||
uint pressCount = 0;
|
||||
Qt::KeyboardModifier modifier = Qt::NoModifier;
|
||||
} m_modOnlyShortcut;
|
||||
};
|
||||
|
||||
inline
|
||||
|
|
21
options.cpp
21
options.cpp
|
@ -838,6 +838,22 @@ void Options::loadConfig()
|
|||
setMaxFpsInterval(1 * 1000 * 1000 * 1000 / config.readEntry("MaxFPS", Options::defaultMaxFps()));
|
||||
setRefreshRate(config.readEntry("RefreshRate", Options::defaultRefreshRate()));
|
||||
setVBlankTime(config.readEntry("VBlankTime", Options::defaultVBlankTime()) * 1000); // config in micro, value in nano resolution
|
||||
|
||||
// Modifier Only Shortcuts
|
||||
config = KConfigGroup(m_settings->config(), "ModifierOnlyShortcuts");
|
||||
m_modifierOnlyShortcuts.clear();
|
||||
if (config.hasKey("Shift")) {
|
||||
m_modifierOnlyShortcuts.insert(Qt::ShiftModifier, config.readEntry("Shift", QStringList()));
|
||||
}
|
||||
if (config.hasKey("Control")) {
|
||||
m_modifierOnlyShortcuts.insert(Qt::ControlModifier, config.readEntry("Control", QStringList()));
|
||||
}
|
||||
if (config.hasKey("Alt")) {
|
||||
m_modifierOnlyShortcuts.insert(Qt::AltModifier, config.readEntry("Alt", QStringList()));
|
||||
}
|
||||
if (config.hasKey("Meta")) {
|
||||
m_modifierOnlyShortcuts.insert(Qt::MetaModifier, config.readEntry("Meta", QStringList()));
|
||||
}
|
||||
}
|
||||
|
||||
void Options::syncFromKcfgc()
|
||||
|
@ -1124,4 +1140,9 @@ Options::WindowOperation Options::operationMaxButtonClick(Qt::MouseButtons butto
|
|||
opMaxButtonLeftClick;
|
||||
}
|
||||
|
||||
QStringList Options::modifierOnlyDBusShortcut(Qt::KeyboardModifier mod) const
|
||||
{
|
||||
return m_modifierOnlyShortcuts.value(mod);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
|
|
@ -589,6 +589,8 @@ public:
|
|||
return m_glPreferBufferSwap;
|
||||
}
|
||||
|
||||
QStringList modifierOnlyDBusShortcut(Qt::KeyboardModifier mod) const;
|
||||
|
||||
// setters
|
||||
void setFocusPolicy(FocusPolicy focusPolicy);
|
||||
void setNextFocusPrefersMouse(bool nextFocusPrefersMouse);
|
||||
|
@ -929,6 +931,8 @@ private:
|
|||
bool condensed_title;
|
||||
int animationSpeed; // 0 - instant, 5 - very slow
|
||||
|
||||
QHash<Qt::KeyboardModifier, QStringList> m_modifierOnlyShortcuts;
|
||||
|
||||
MouseCommand wheelToMouseCommand(MouseWheelCommand com, int delta) const;
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue