File indexing completed on 2024-11-24 05:00:46

0001 /*
0002     SPDX-FileCopyrightText: 2017 Roman Gilg <subdiff@gmail.com>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include "kwinwaylandbackend.h"
0008 #include "kwinwaylandtouchpad.h"
0009 
0010 #include <algorithm>
0011 
0012 #include <KLocalizedString>
0013 
0014 #include <QDBusInterface>
0015 #include <QDBusMessage>
0016 #include <QDBusReply>
0017 #include <QStringList>
0018 
0019 #include "logging.h"
0020 
0021 KWinWaylandBackend::KWinWaylandBackend(QObject *parent)
0022     : TouchpadBackend(parent)
0023 {
0024     m_deviceManager = new QDBusInterface(QStringLiteral("org.kde.KWin"),
0025                                          QStringLiteral("/org/kde/KWin/InputDevice"),
0026                                          QStringLiteral("org.kde.KWin.InputDeviceManager"),
0027                                          QDBusConnection::sessionBus(),
0028                                          this);
0029 
0030     setMode(TouchpadInputBackendMode::WaylandLibinput);
0031 
0032     findTouchpads();
0033 
0034     m_deviceManager->connection().connect(QStringLiteral("org.kde.KWin"),
0035                                           QStringLiteral("/org/kde/KWin/InputDevice"),
0036                                           QStringLiteral("org.kde.KWin.InputDeviceManager"),
0037                                           QStringLiteral("deviceAdded"),
0038                                           this,
0039                                           SLOT(onDeviceAdded(QString)));
0040     m_deviceManager->connection().connect(QStringLiteral("org.kde.KWin"),
0041                                           QStringLiteral("/org/kde/KWin/InputDevice"),
0042                                           QStringLiteral("org.kde.KWin.InputDeviceManager"),
0043                                           QStringLiteral("deviceRemoved"),
0044                                           this,
0045                                           SLOT(onDeviceRemoved(QString)));
0046 }
0047 
0048 KWinWaylandBackend::~KWinWaylandBackend()
0049 {
0050     qDeleteAll(m_devices);
0051     delete m_deviceManager;
0052 }
0053 
0054 void KWinWaylandBackend::findTouchpads()
0055 {
0056     const QVariant reply = m_deviceManager->property("devicesSysNames");
0057     if (!reply.isValid()) {
0058         qCCritical(KCM_TOUCHPAD) << "Error on receiving device list from KWin.";
0059         m_errorString = i18n("Querying input devices failed. Please reopen this settings module.");
0060         return;
0061     }
0062     const auto devicesSysNames = reply.toStringList();
0063     for (const QString &sn : devicesSysNames) {
0064         QDBusInterface deviceIface(QStringLiteral("org.kde.KWin"),
0065                                    QStringLiteral("/org/kde/KWin/InputDevice/") + sn,
0066                                    QStringLiteral("org.kde.KWin.InputDevice"),
0067                                    QDBusConnection::sessionBus(),
0068                                    this);
0069         const QVariant reply = deviceIface.property("touchpad");
0070         if (reply.isValid() && reply.toBool()) {
0071             KWinWaylandTouchpad *tp = new KWinWaylandTouchpad(sn);
0072             if (!tp->init() || !tp->getConfig()) {
0073                 qCCritical(KCM_TOUCHPAD) << "Error on creating touchpad object" << sn;
0074                 m_errorString = i18n("Critical error on reading fundamental device infos for touchpad %1.", sn);
0075                 return;
0076             }
0077             m_devices.append(tp);
0078             qCInfo(KCM_TOUCHPAD).nospace() << "Touchpad found: " << tp->name() << " (" << tp->sysName() << ")";
0079         }
0080     }
0081     if (m_devices.isEmpty()) {
0082         qCInfo(KCM_TOUCHPAD) << "No Devices found.";
0083     }
0084 }
0085 
0086 bool KWinWaylandBackend::applyConfig()
0087 {
0088     return std::all_of(m_devices.constBegin(), m_devices.constEnd(), [](QObject *t) {
0089         return static_cast<KWinWaylandTouchpad *>(t)->applyConfig();
0090     });
0091 }
0092 
0093 bool KWinWaylandBackend::getConfig()
0094 {
0095     return std::all_of(m_devices.constBegin(), m_devices.constEnd(), [](QObject *t) {
0096         return static_cast<KWinWaylandTouchpad *>(t)->getConfig();
0097     });
0098 }
0099 
0100 bool KWinWaylandBackend::getDefaultConfig()
0101 {
0102     return std::all_of(m_devices.constBegin(), m_devices.constEnd(), [](QObject *t) {
0103         return static_cast<KWinWaylandTouchpad *>(t)->getDefaultConfig();
0104     });
0105 }
0106 
0107 bool KWinWaylandBackend::isChangedConfig() const
0108 {
0109     return std::any_of(m_devices.constBegin(), m_devices.constEnd(), [](QObject *t) {
0110         return static_cast<KWinWaylandTouchpad *>(t)->isChangedConfig();
0111     });
0112 }
0113 
0114 void KWinWaylandBackend::onDeviceAdded(QString sysName)
0115 {
0116     if (std::any_of(m_devices.constBegin(), m_devices.constEnd(), [sysName](QObject *t) {
0117             return static_cast<KWinWaylandTouchpad *>(t)->sysName() == sysName;
0118         })) {
0119         return;
0120     }
0121 
0122     QDBusInterface deviceIface(QStringLiteral("org.kde.KWin"),
0123                                QStringLiteral("/org/kde/KWin/InputDevice/") + sysName,
0124                                QStringLiteral("org.kde.KWin.InputDevice"),
0125                                QDBusConnection::sessionBus(),
0126                                this);
0127     QVariant reply = deviceIface.property("touchpad");
0128     if (reply.isValid() && reply.toBool()) {
0129         KWinWaylandTouchpad *tp = new KWinWaylandTouchpad(sysName);
0130         if (!tp->init() || !tp->getConfig()) {
0131             Q_EMIT touchpadAdded(false);
0132             return;
0133         }
0134         m_devices.append(tp);
0135         qCDebug(KCM_TOUCHPAD).nospace() << "Touchpad connected: " << tp->name() << " (" << tp->sysName() << ")";
0136         Q_EMIT touchpadAdded(true);
0137     }
0138 }
0139 
0140 void KWinWaylandBackend::onDeviceRemoved(QString sysName)
0141 {
0142     QList<QObject *>::const_iterator it = std::find_if(m_devices.constBegin(), m_devices.constEnd(), [sysName](QObject *t) {
0143         return static_cast<KWinWaylandTouchpad *>(t)->sysName() == sysName;
0144     });
0145     if (it == m_devices.cend()) {
0146         return;
0147     }
0148 
0149     KWinWaylandTouchpad *tp = static_cast<KWinWaylandTouchpad *>(*it);
0150     qCDebug(KCM_TOUCHPAD).nospace() << "Touchpad disconnected: " << tp->name() << " (" << tp->sysName() << ")";
0151 
0152     int index = it - m_devices.cbegin();
0153     m_devices.removeAt(index);
0154     Q_EMIT touchpadRemoved(index);
0155 }