File indexing completed on 2024-06-23 05:29:34
0001 /* 0002 SPDX-FileCopyrightText: 2018 Roman Gilg <subdiff@gmail.com> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "kwin_wl_backend.h" 0008 #include "kwin_wl_device.h" 0009 0010 #include <algorithm> 0011 0012 #include <KConfigGroup> 0013 #include <KLocalizedString> 0014 #include <KSharedConfig> 0015 0016 #include <QDBusInterface> 0017 #include <QDBusMessage> 0018 #include <QDBusReply> 0019 #include <QKeySequence> 0020 #include <QStringList> 0021 0022 #include "logging.h" 0023 0024 KWinWaylandBackend::KWinWaylandBackend(QObject *parent) 0025 : InputBackend(parent) 0026 { 0027 m_mode = InputBackendMode::KWinWayland; 0028 0029 m_deviceManager = new QDBusInterface(QStringLiteral("org.kde.KWin"), 0030 QStringLiteral("/org/kde/KWin/InputDevice"), 0031 QStringLiteral("org.kde.KWin.InputDeviceManager"), 0032 QDBusConnection::sessionBus(), 0033 this); 0034 0035 findDevices(); 0036 0037 m_deviceManager->connection().connect(QStringLiteral("org.kde.KWin"), 0038 QStringLiteral("/org/kde/KWin/InputDevice"), 0039 QStringLiteral("org.kde.KWin.InputDeviceManager"), 0040 QStringLiteral("deviceAdded"), 0041 this, 0042 SLOT(onDeviceAdded(QString))); 0043 m_deviceManager->connection().connect(QStringLiteral("org.kde.KWin"), 0044 QStringLiteral("/org/kde/KWin/InputDevice"), 0045 QStringLiteral("org.kde.KWin.InputDeviceManager"), 0046 QStringLiteral("deviceRemoved"), 0047 this, 0048 SLOT(onDeviceRemoved(QString))); 0049 } 0050 0051 KWinWaylandBackend::~KWinWaylandBackend() 0052 { 0053 qDeleteAll(m_devices); 0054 delete m_deviceManager; 0055 } 0056 0057 void KWinWaylandBackend::findDevices() 0058 { 0059 QStringList devicesSysNames; 0060 const QVariant replyDevicesSysNames = m_deviceManager->property("devicesSysNames"); 0061 if (replyDevicesSysNames.isValid()) { 0062 qCDebug(KCM_MOUSE) << "Devices list received successfully from KWin."; 0063 devicesSysNames = replyDevicesSysNames.toStringList(); 0064 } else { 0065 qCCritical(KCM_MOUSE) << "Error on receiving device list from KWin."; 0066 m_errorString = i18n("Querying input devices failed. Please reopen this settings module."); 0067 return; 0068 } 0069 0070 for (const QString &sn : std::as_const(devicesSysNames)) { 0071 QDBusInterface deviceIface(QStringLiteral("org.kde.KWin"), 0072 QStringLiteral("/org/kde/KWin/InputDevice/") + sn, 0073 QStringLiteral("org.kde.KWin.InputDevice"), 0074 QDBusConnection::sessionBus(), 0075 this); 0076 QVariant reply = deviceIface.property("pointer"); 0077 if (reply.isValid() && reply.toBool()) { 0078 reply = deviceIface.property("touchpad"); 0079 if (reply.isValid() && reply.toBool()) { 0080 continue; 0081 } 0082 0083 KWinWaylandDevice *dev = new KWinWaylandDevice(sn); 0084 if (!dev->init()) { 0085 qCCritical(KCM_MOUSE) << "Error on creating device object" << sn; 0086 m_errorString = i18n("Critical error on reading fundamental device infos of %1.", sn); 0087 return; 0088 } 0089 m_devices.append(dev); 0090 qCDebug(KCM_MOUSE).nospace() << "Device found: " << dev->name() << " (" << dev->sysName() << ")"; 0091 } 0092 } 0093 } 0094 0095 bool KWinWaylandBackend::applyConfig() 0096 { 0097 KConfigGroup buttonGroup = KSharedConfig::openConfig(QStringLiteral("kcminputrc"))->group(QStringLiteral("ButtonRebinds")).group(QStringLiteral("Mouse")); 0098 for (auto it = m_buttonMapping.cbegin(); it != m_buttonMapping.cend(); ++it) { 0099 if (auto keys = it.value().value<QKeySequence>(); !keys.isEmpty()) { 0100 buttonGroup.writeEntry(it.key(), QStringList{"Key", keys.toString(QKeySequence::PortableText)}, KConfig::Notify); 0101 } else { 0102 buttonGroup.deleteEntry(it.key(), KConfig::Notify); 0103 } 0104 } 0105 0106 return std::all_of(m_devices.constBegin(), m_devices.constEnd(), [](QObject *t) { 0107 return static_cast<KWinWaylandDevice *>(t)->applyConfig(); 0108 }); 0109 } 0110 0111 bool KWinWaylandBackend::getConfig() 0112 { 0113 m_loadedButtonMapping.clear(); 0114 const KConfigGroup buttonGroup = KSharedConfig::openConfig(QStringLiteral("kcminputrc"))->group(QStringLiteral("ButtonRebinds")).group(QStringLiteral("Mouse")); 0115 for (int i = 1; i <= 24; ++i) { 0116 const QString buttonName = QLatin1String("ExtraButton%1").arg(QString::number(i)); 0117 auto entry = buttonGroup.readEntry(buttonName, QStringList()); 0118 if (entry.size() == 2 && entry.first() == QLatin1String("Key")) { 0119 auto keys = QKeySequence::fromString(entry.at(1), QKeySequence::PortableText); 0120 if (!keys.isEmpty()) { 0121 m_loadedButtonMapping.insert(buttonName, keys); 0122 } 0123 } 0124 } 0125 m_buttonMapping = m_loadedButtonMapping; 0126 0127 return std::all_of(m_devices.constBegin(), m_devices.constEnd(), [](QObject *t) { 0128 return static_cast<KWinWaylandDevice *>(t)->init(); 0129 }); 0130 } 0131 0132 bool KWinWaylandBackend::getDefaultConfig() 0133 { 0134 return std::all_of(m_devices.constBegin(), m_devices.constEnd(), [](QObject *t) { 0135 return static_cast<KWinWaylandDevice *>(t)->getDefaultConfig(); 0136 }); 0137 } 0138 0139 bool KWinWaylandBackend::isChangedConfig() const 0140 { 0141 return m_buttonMapping != m_loadedButtonMapping || std::any_of(m_devices.constBegin(), m_devices.constEnd(), [](QObject *t) { 0142 return static_cast<KWinWaylandDevice *>(t)->isChangedConfig(); 0143 }); 0144 } 0145 0146 QVariantMap KWinWaylandBackend::buttonMapping() 0147 { 0148 return m_buttonMapping; 0149 } 0150 0151 void KWinWaylandBackend::setButtonMapping(const QVariantMap &mapping) 0152 { 0153 if (m_buttonMapping != mapping) { 0154 m_buttonMapping = mapping; 0155 Q_EMIT buttonMappingChanged(); 0156 } 0157 } 0158 0159 void KWinWaylandBackend::onDeviceAdded(QString sysName) 0160 { 0161 if (std::any_of(m_devices.constBegin(), m_devices.constEnd(), [sysName](QObject *t) { 0162 return static_cast<KWinWaylandDevice *>(t)->sysName() == sysName; 0163 })) { 0164 return; 0165 } 0166 0167 QDBusInterface deviceIface(QStringLiteral("org.kde.KWin"), 0168 QStringLiteral("/org/kde/KWin/InputDevice/") + sysName, 0169 QStringLiteral("org.kde.KWin.InputDevice"), 0170 QDBusConnection::sessionBus(), 0171 this); 0172 QVariant reply = deviceIface.property("pointer"); 0173 0174 if (reply.isValid() && reply.toBool()) { 0175 reply = deviceIface.property("touchpad"); 0176 if (reply.isValid() && reply.toBool()) { 0177 return; 0178 } 0179 0180 KWinWaylandDevice *dev = new KWinWaylandDevice(sysName); 0181 if (!dev->init()) { 0182 Q_EMIT deviceAdded(false); 0183 return; 0184 } 0185 0186 m_devices.append(dev); 0187 qCDebug(KCM_MOUSE).nospace() << "Device connected: " << dev->name() << " (" << dev->sysName() << ")"; 0188 Q_EMIT deviceAdded(true); 0189 } 0190 } 0191 0192 void KWinWaylandBackend::onDeviceRemoved(QString sysName) 0193 { 0194 QList<QObject *>::const_iterator it = std::find_if(m_devices.constBegin(), m_devices.constEnd(), [sysName](QObject *t) { 0195 return static_cast<KWinWaylandDevice *>(t)->sysName() == sysName; 0196 }); 0197 if (it == m_devices.cend()) { 0198 return; 0199 } 0200 0201 KWinWaylandDevice *dev = static_cast<KWinWaylandDevice *>(*it); 0202 qCDebug(KCM_MOUSE).nospace() << "Device disconnected: " << dev->name() << " (" << dev->sysName() << ")"; 0203 0204 int index = it - m_devices.cbegin(); 0205 m_devices.removeAt(index); 0206 Q_EMIT deviceRemoved(index); 0207 }