Commit 4bb40ab2 authored by David Redondo's avatar David Redondo 🏎 Committed by Aleix Pol Gonzalez
Browse files

Allow rebinding of extra mouse buttons on Wayland

Some mice have more than the three standard buttons. While some applications
can use a subset of those (mostly the backwards and forwards buttons) in many
cases pressing them will do nothing.  Allow users to assign key combinations
to those buttons that are triggered when the button is pressed.
parent 15a7f382
Pipeline #221934 passed with stage
in 4 minutes and 9 seconds
......@@ -9,11 +9,14 @@
#include <algorithm>
#include <KConfigGroup>
#include <KLocalizedString>
#include <KSharedConfig>
#include <QDBusInterface>
#include <QDBusMessage>
#include <QDBusReply>
#include <QKeySequence>
#include <QStringList>
#include "logging.h"
......@@ -91,6 +94,15 @@ void KWinWaylandBackend::findDevices()
bool KWinWaylandBackend::applyConfig()
{
KConfigGroup buttonGroup = KSharedConfig::openConfig("kcminputrc")->group("ButtonRebinds").group("Mouse");
for (auto it = m_buttonMapping.cbegin(); it != m_buttonMapping.cend(); ++it) {
if (auto keys = it.value().value<QKeySequence>(); !keys.isEmpty()) {
buttonGroup.writeEntry(it.key(), QStringList{"Key", keys.toString(QKeySequence::PortableText)}, KConfig::Notify);
} else {
buttonGroup.deleteEntry(it.key());
}
}
return std::all_of(m_devices.constBegin(), m_devices.constEnd(), [](QObject *t) {
return static_cast<KWinWaylandDevice *>(t)->applyConfig();
});
......@@ -98,6 +110,20 @@ bool KWinWaylandBackend::applyConfig()
bool KWinWaylandBackend::getConfig()
{
m_loadedButtonMapping.clear();
const KConfigGroup buttonGroup = KSharedConfig::openConfig("kcminputrc")->group("ButtonRebinds").group("Mouse");
for (int i = 1; i <= 24; ++i) {
const QString buttonName = QLatin1String("ExtraButton%1").arg(QString::number(i));
auto entry = buttonGroup.readEntry(buttonName, QStringList());
if (entry.size() == 2 && entry.first() == QLatin1String("Key")) {
auto keys = QKeySequence::fromString(entry.at(1), QKeySequence::PortableText);
if (!keys.isEmpty()) {
m_loadedButtonMapping.insert(buttonName, keys);
}
}
}
m_buttonMapping = m_loadedButtonMapping;
return std::all_of(m_devices.constBegin(), m_devices.constEnd(), [](QObject *t) {
return static_cast<KWinWaylandDevice *>(t)->init();
});
......@@ -112,11 +138,24 @@ bool KWinWaylandBackend::getDefaultConfig()
bool KWinWaylandBackend::isChangedConfig() const
{
return std::any_of(m_devices.constBegin(), m_devices.constEnd(), [](QObject *t) {
return m_buttonMapping != m_loadedButtonMapping || std::any_of(m_devices.constBegin(), m_devices.constEnd(), [](QObject *t) {
return static_cast<KWinWaylandDevice *>(t)->isChangedConfig();
});
}
QVariantMap KWinWaylandBackend::buttonMapping()
{
return m_buttonMapping;
}
void KWinWaylandBackend::setButtonMapping(const QVariantMap &mapping)
{
if (m_buttonMapping != mapping) {
m_buttonMapping = mapping;
Q_EMIT buttonMappingChanged();
}
}
void KWinWaylandBackend::onDeviceAdded(QString sysName)
{
if (std::any_of(m_devices.constBegin(), m_devices.constEnd(), [sysName](QObject *t) {
......
......@@ -18,6 +18,7 @@ class KWinWaylandBackend : public InputBackend
Q_OBJECT
Q_PROPERTY(int deviceCount READ deviceCount CONSTANT)
Q_PROPERTY(QVariantMap buttonMapping READ buttonMapping WRITE setButtonMapping NOTIFY buttonMappingChanged)
public:
explicit KWinWaylandBackend(QObject *parent = nullptr);
......@@ -41,6 +42,12 @@ public:
return m_devices;
}
QVariantMap buttonMapping();
void setButtonMapping(const QVariantMap &mapping);
Q_SIGNALS:
void buttonMappingChanged();
private Q_SLOTS:
void onDeviceAdded(QString);
void onDeviceRemoved(QString);
......@@ -50,6 +57,8 @@ private:
QDBusInterface *m_deviceManager;
QVector<QObject *> m_devices;
QVariantMap m_buttonMapping;
QVariantMap m_loadedButtonMapping;
QString m_errorString = QString();
};
......
......@@ -27,6 +27,7 @@ Qt::MouseButtons valueLoaderPart(QVariant const &reply)
{
return static_cast<Qt::MouseButtons>(reply.toInt());
}
}
KWinWaylandDevice::KWinWaylandDevice(const QString &dbusName)
......@@ -121,7 +122,6 @@ bool KWinWaylandDevice::applyConfig()
msgs << valueWriter(m_enabled) << valueWriter(m_leftHanded) << valueWriter(m_pointerAcceleration) << valueWriter(m_pointerAccelerationProfileFlat)
<< valueWriter(m_pointerAccelerationProfileAdaptive) << valueWriter(m_middleEmulation) << valueWriter(m_naturalScroll) << valueWriter(m_scrollFactor);
bool success = true;
QString error_msg;
......
This diff is collapsed.
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment