diff --git a/kcms/touchpad/src/backends/kwin_wayland.cmake b/kcms/touchpad/src/backends/kwin_wayland.cmake index 4f8ec0365..f111a231e 100644 --- a/kcms/touchpad/src/backends/kwin_wayland.cmake +++ b/kcms/touchpad/src/backends/kwin_wayland.cmake @@ -1,5 +1,6 @@ SET(backend_SRCS ${backend_SRCS} + backends/libinputcommon.cpp backends/kwin_wayland/kwinwaylandbackend.cpp backends/kwin_wayland/kwinwaylandtouchpad.cpp ) diff --git a/kcms/touchpad/src/backends/kwin_wayland/kwinwaylandbackend.cpp b/kcms/touchpad/src/backends/kwin_wayland/kwinwaylandbackend.cpp index 621064d29..e9bc10a11 100644 --- a/kcms/touchpad/src/backends/kwin_wayland/kwinwaylandbackend.cpp +++ b/kcms/touchpad/src/backends/kwin_wayland/kwinwaylandbackend.cpp @@ -1,164 +1,166 @@ /* * Copyright 2017 Roman Gilg * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kwinwaylandbackend.h" #include "kwinwaylandtouchpad.h" #include #include #include #include #include #include #include "logging.h" KWinWaylandBackend::KWinWaylandBackend(QObject *parent) : TouchpadBackend(parent) { m_deviceManager = new QDBusInterface (QStringLiteral("org.kde.KWin"), QStringLiteral("/org/kde/KWin/InputDevice"), QStringLiteral("org.kde.KWin.InputDeviceManager"), QDBusConnection::sessionBus(), this); + setMode(TouchpadInputBackendMode::WaylandLibinput); + findTouchpads(); m_deviceManager->connection().connect(QStringLiteral("org.kde.KWin"), QStringLiteral("/org/kde/KWin/InputDevice"), QStringLiteral("org.kde.KWin.InputDeviceManager"), QStringLiteral("deviceAdded"), this, SLOT(onDeviceAdded(QString))); m_deviceManager->connection().connect(QStringLiteral("org.kde.KWin"), QStringLiteral("/org/kde/KWin/InputDevice"), QStringLiteral("org.kde.KWin.InputDeviceManager"), QStringLiteral("deviceRemoved"), this, SLOT(onDeviceRemoved(QString))); } KWinWaylandBackend::~KWinWaylandBackend() { qDeleteAll(m_devices); delete m_deviceManager; } void KWinWaylandBackend::findTouchpads() { QStringList devicesSysNames; const QVariant reply = m_deviceManager->property("devicesSysNames"); if (reply.isValid()) { qCDebug(KCM_TOUCHPAD) << "Devices list received successfully from KWin."; devicesSysNames = reply.toStringList(); } else { qCCritical(KCM_TOUCHPAD) << "Error on receiving device list from KWin."; m_errorString = i18n("Querying input devices failed. Please reopen this settings module."); return; } bool touchpadFound = false; for (QString sn : devicesSysNames) { QDBusInterface deviceIface(QStringLiteral("org.kde.KWin"), QStringLiteral("/org/kde/KWin/InputDevice/") + sn, QStringLiteral("org.kde.KWin.InputDevice"), QDBusConnection::sessionBus(), this); const QVariant reply = deviceIface.property("touchpad"); if (reply.isValid() && reply.toBool()) { KWinWaylandTouchpad* tp = new KWinWaylandTouchpad(sn); if (!tp->init()) { qCCritical(KCM_TOUCHPAD) << "Error on creating touchpad object" << sn; m_errorString = i18n("Critical error on reading fundamental device infos for touchpad %1.", sn); return; } m_devices.append(tp); touchpadFound = true; qCDebug(KCM_TOUCHPAD).nospace() << "Touchpad found: " << tp->name() << " (" << tp->sysName() << ")"; } } } bool KWinWaylandBackend::applyConfig() { return std::all_of(m_devices.constBegin(), m_devices.constEnd(), [] (QObject *t) { return static_cast(t)->applyConfig(); }); } bool KWinWaylandBackend::getConfig() { return std::all_of(m_devices.constBegin(), m_devices.constEnd(), [] (QObject *t) { return static_cast(t)->getConfig(); }); } bool KWinWaylandBackend::getDefaultConfig() { return std::all_of(m_devices.constBegin(), m_devices.constEnd(), [] (QObject *t) { return static_cast(t)->getDefaultConfig(); }); } bool KWinWaylandBackend::isChangedConfig() const { return std::any_of(m_devices.constBegin(), m_devices.constEnd(), [] (QObject *t) { return static_cast(t)->isChangedConfig(); }); } void KWinWaylandBackend::onDeviceAdded(QString sysName) { if (std::any_of(m_devices.constBegin(), m_devices.constEnd(), [sysName] (QObject *t) { return static_cast(t)->sysName() == sysName; })) { return; } QDBusInterface deviceIface(QStringLiteral("org.kde.KWin"), QStringLiteral("/org/kde/KWin/InputDevice/") + sysName, QStringLiteral("org.kde.KWin.InputDevice"), QDBusConnection::sessionBus(), this); QVariant reply = deviceIface.property("touchpad"); if (reply.isValid() && reply.toBool()) { KWinWaylandTouchpad* tp = new KWinWaylandTouchpad(sysName); if (!tp->init() || !tp->getConfig()) { emit touchpadAdded(false); return; } m_devices.append(tp); qCDebug(KCM_TOUCHPAD).nospace() << "Touchpad connected: " << tp->name() << " (" << tp->sysName() << ")"; emit touchpadAdded(true); } } void KWinWaylandBackend::onDeviceRemoved(QString sysName) { QVector::const_iterator it = std::find_if(m_devices.constBegin(), m_devices.constEnd(), [sysName] (QObject *t) { return static_cast(t)->sysName() == sysName; }); if (it == m_devices.cend()) { return; } KWinWaylandTouchpad *tp = static_cast(*it); qCDebug(KCM_TOUCHPAD).nospace() << "Touchpad disconnected: " << tp->name() << " (" << tp->sysName() << ")"; int index = it - m_devices.cbegin(); m_devices.removeAt(index); emit touchpadRemoved(index); } diff --git a/kcms/touchpad/src/backends/kwin_wayland/kwinwaylandtouchpad.cpp b/kcms/touchpad/src/backends/kwin_wayland/kwinwaylandtouchpad.cpp index c846341e7..795a775bf 100644 --- a/kcms/touchpad/src/backends/kwin_wayland/kwinwaylandtouchpad.cpp +++ b/kcms/touchpad/src/backends/kwin_wayland/kwinwaylandtouchpad.cpp @@ -1,264 +1,243 @@ /* * Copyright 2017 Roman Gilg * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kwinwaylandtouchpad.h" #include #include #include +#include #include "logging.h" -namespace { -template -T valueLoaderPart(QVariant const &reply) { Q_UNUSED(reply); return T(); } - -template<> -bool valueLoaderPart(QVariant const &reply) { return reply.toBool(); } - -template<> -int valueLoaderPart(QVariant const &reply) { return reply.toInt(); } - -template<> -quint32 valueLoaderPart(QVariant const &reply) { return reply.toInt(); } - -template<> -qreal valueLoaderPart(QVariant const &reply) { return reply.toReal(); } - -template<> -QString valueLoaderPart(QVariant const &reply) { return reply.toString(); } - -template<> -Qt::MouseButtons valueLoaderPart(QVariant const &reply) { return static_cast(reply.toInt()); } -} - -KWinWaylandTouchpad::KWinWaylandTouchpad(QString dbusName) +KWinWaylandTouchpad::KWinWaylandTouchpad(QString dbusName) : + LibinputCommon() { m_iface = new QDBusInterface(QStringLiteral("org.kde.KWin"), QStringLiteral("/org/kde/KWin/InputDevice/") + dbusName, QStringLiteral("org.kde.KWin.InputDevice"), QDBusConnection::sessionBus(), this); } KWinWaylandTouchpad::~KWinWaylandTouchpad() { delete m_iface; } bool KWinWaylandTouchpad::init() { // need to do it here in order to populate combobox and handle events return valueLoader(m_name) && valueLoader(m_sysName); } bool KWinWaylandTouchpad::getConfig() { bool success = true; // general success &= valueLoader(m_supportsDisableEvents); success &= valueLoader(m_supportsLeftHanded); success &= valueLoader(m_supportedButtons); success &= valueLoader(m_leftHandedEnabledByDefault); success &= valueLoader(m_enabled); success &= valueLoader(m_leftHanded); // advanced success &= valueLoader(m_supportsPointerAcceleration); success &= valueLoader(m_supportsPointerAccelerationProfileFlat); success &= valueLoader(m_supportsPointerAccelerationProfileAdaptive); success &= valueLoader(m_supportsDisableWhileTyping); success &= valueLoader(m_supportsDisableEventsOnExternalMouse); success &= valueLoader(m_defaultPointerAcceleration); success &= valueLoader(m_defaultPointerAccelerationProfileFlat); success &= valueLoader(m_defaultPointerAccelerationProfileAdaptive); success &= valueLoader(m_disableWhileTypingEnabledByDefault); success &= valueLoader(m_leftHandedEnabledByDefault); success &= valueLoader(m_pointerAcceleration); success &= valueLoader(m_pointerAccelerationProfileFlat); success &= valueLoader(m_pointerAccelerationProfileAdaptive); success &= valueLoader(m_disableWhileTyping); // tapping success &= valueLoader(m_tapFingerCount); success &= valueLoader(m_supportsMiddleEmulation); success &= valueLoader(m_tapToClickEnabledByDefault); success &= valueLoader(m_tapAndDragEnabledByDefault); success &= valueLoader(m_tapDragLockEnabledByDefault); success &= valueLoader(m_middleEmulationEnabledByDefault); success &= valueLoader(m_tapToClick); success &= valueLoader(m_tapAndDrag); success &= valueLoader(m_tapDragLock); success &= valueLoader(m_middleEmulation); success &= valueLoader(m_lmrTapButtonMapEnabledByDefault); success &= valueLoader(m_lmrTapButtonMap); // scrolling modes avail success &= valueLoader(m_supportsNaturalScroll); success &= valueLoader(m_supportsScrollTwoFinger); success &= valueLoader(m_supportsScrollEdge); success &= valueLoader(m_supportsScrollOnButtonDown); // default scrolling modes success &= valueLoader(m_naturalScrollEnabledByDefault); success &= valueLoader(m_scrollTwoFingerEnabledByDefault); success &= valueLoader(m_scrollEdgeEnabledByDefault); success &= valueLoader(m_scrollOnButtonDownEnabledByDefault); success &= valueLoader(m_defaultScrollButton); // current scrolling mode success &= valueLoader(m_naturalScroll); success &= valueLoader(m_isScrollTwoFinger); success &= valueLoader(m_isScrollEdge); success &= valueLoader(m_isScrollOnButtonDown); success &= valueLoader(m_scrollButton); // click methods success &= valueLoader(m_supportsClickMethodAreas); success &= valueLoader(m_supportsClickMethodClickfinger); success &= valueLoader(m_defaultClickMethodAreas); success &= valueLoader(m_defaultClickMethodClickfinger); success &= valueLoader(m_clickMethodAreas); success &= valueLoader(m_clickMethodClickfinger); return success; } bool KWinWaylandTouchpad::getDefaultConfig() { m_enabled.set(true); m_leftHanded.set(false); m_pointerAcceleration.set(m_defaultPointerAcceleration); m_pointerAccelerationProfileFlat.set(m_defaultPointerAccelerationProfileFlat); m_pointerAccelerationProfileAdaptive.set(m_defaultPointerAccelerationProfileAdaptive); m_disableWhileTyping.set(m_disableWhileTypingEnabledByDefault); m_tapToClick.set(m_tapToClickEnabledByDefault); m_tapAndDrag.set(m_tapAndDragEnabledByDefault); m_tapDragLock.set(m_tapDragLockEnabledByDefault); m_middleEmulation.set(m_middleEmulationEnabledByDefault); m_naturalScroll.set(m_naturalScrollEnabledByDefault); m_isScrollTwoFinger.set(m_scrollTwoFingerEnabledByDefault); m_isScrollEdge.set(m_scrollEdgeEnabledByDefault); m_isScrollOnButtonDown.set(m_scrollOnButtonDownEnabledByDefault); m_clickMethodAreas.set(m_defaultClickMethodAreas); m_clickMethodClickfinger.set(m_defaultClickMethodClickfinger); return true; } bool KWinWaylandTouchpad::applyConfig() { QVector msgs; msgs << valueWriter(m_enabled) << valueWriter(m_leftHanded) << valueWriter(m_pointerAcceleration) << valueWriter(m_defaultPointerAccelerationProfileFlat) << valueWriter(m_defaultPointerAccelerationProfileAdaptive) << valueWriter(m_disableWhileTyping) << valueWriter(m_middleEmulation) << valueWriter(m_tapToClick) << valueWriter(m_tapAndDrag) << valueWriter(m_tapDragLock) << valueWriter(m_lmrTapButtonMap) << valueWriter(m_naturalScroll) << valueWriter(m_isScrollTwoFinger) << valueWriter(m_isScrollEdge) << valueWriter(m_isScrollOnButtonDown) << valueWriter(m_scrollButton) << valueWriter(m_clickMethodAreas) << valueWriter(m_clickMethodClickfinger); bool success = true; QString error_msg; for (QString m : msgs) { if (!m.isNull()) { qCCritical(KCM_TOUCHPAD) << "in error:" << m; if (!success) { error_msg.append("\n"); } error_msg.append(m); success = false; } } if (!success) { qCCritical(KCM_TOUCHPAD) << error_msg; } return success; } bool KWinWaylandTouchpad::isChangedConfig() const { return m_enabled.changed() || m_leftHanded.changed() || m_pointerAcceleration.changed() || m_pointerAccelerationProfileFlat.changed() || m_pointerAccelerationProfileAdaptive.changed() || m_disableWhileTyping.changed() || m_middleEmulation.changed() || m_tapToClick.changed() || m_tapAndDrag.changed() || m_tapDragLock.changed() || m_lmrTapButtonMap.changed() || m_naturalScroll.changed() || m_isScrollTwoFinger.changed() || m_isScrollEdge.changed() || m_isScrollOnButtonDown.changed() || m_scrollButton.changed() || m_clickMethodAreas.changed() || m_clickMethodClickfinger.changed(); } template QString KWinWaylandTouchpad::valueWriter(const Prop &prop) { if (!prop.changed()) { return QString(); } - m_iface->setProperty(prop.dbus, prop.val); + m_iface->setProperty(prop.name, prop.val); QDBusError error = m_iface->lastError(); if (error.isValid()) { qCCritical(KCM_TOUCHPAD) << error.message(); return error.message(); } return QString(); } template bool KWinWaylandTouchpad::valueLoader(Prop &prop) { - QVariant reply = m_iface->property(prop.dbus); + QVariant reply = m_iface->property(prop.name); if (!reply.isValid()) { - qCCritical(KCM_TOUCHPAD) << "Error on d-bus read of" << prop.dbus; + qCCritical(KCM_TOUCHPAD) << "Error on d-bus read of" << prop.name; prop.avail = false; return false; } prop.avail = true; T replyValue = valueLoaderPart(reply); prop.old = replyValue; prop.val = replyValue; return true; } diff --git a/kcms/touchpad/src/backends/kwin_wayland/kwinwaylandtouchpad.h b/kcms/touchpad/src/backends/kwin_wayland/kwinwaylandtouchpad.h index d6cb3a8d2..9f6197ced 100644 --- a/kcms/touchpad/src/backends/kwin_wayland/kwinwaylandtouchpad.h +++ b/kcms/touchpad/src/backends/kwin_wayland/kwinwaylandtouchpad.h @@ -1,502 +1,144 @@ /* * Copyright 2017 Roman Gilg * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KWINWAYLANDTOUCHPAD_H #define KWINWAYLANDTOUCHPAD_H -#include +#include #include class QDBusInterface; -class KWinWaylandTouchpad : public QObject +class KWinWaylandTouchpad : public LibinputCommon { Q_OBJECT - // - // general - Q_PROPERTY(QString name READ name CONSTANT) - Q_PROPERTY(bool supportsDisableEvents READ supportsDisableEvents CONSTANT) - Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled NOTIFY enabledChanged) - - // - // advanced - Q_PROPERTY(Qt::MouseButtons supportedButtons READ supportedButtons CONSTANT) - - Q_PROPERTY(bool supportsLeftHanded READ supportsLeftHanded CONSTANT) - Q_PROPERTY(bool leftHandedEnabledByDefault READ leftHandedEnabledByDefault CONSTANT) - Q_PROPERTY(bool leftHanded READ isLeftHanded WRITE setLeftHanded NOTIFY leftHandedChanged) - - Q_PROPERTY(bool supportsDisableEventsOnExternalMouse READ supportsDisableEventsOnExternalMouse CONSTANT) - - Q_PROPERTY(bool supportsDisableWhileTyping READ supportsDisableWhileTyping CONSTANT) - Q_PROPERTY(bool disableWhileTypingEnabledByDefault READ disableWhileTypingEnabledByDefault CONSTANT) - Q_PROPERTY(bool disableWhileTyping READ isDisableWhileTyping WRITE setDisableWhileTyping NOTIFY disableWhileTypingChanged) - - Q_PROPERTY(bool supportsMiddleEmulation READ supportsMiddleEmulation CONSTANT) - Q_PROPERTY(bool middleEmulationEnabledByDefault READ middleEmulationEnabledByDefault CONSTANT) - Q_PROPERTY(bool middleEmulation READ isMiddleEmulation WRITE setMiddleEmulation NOTIFY middleEmulationChanged) - - // - // acceleration speed and profile - Q_PROPERTY(bool supportsPointerAcceleration READ supportsPointerAcceleration CONSTANT) - Q_PROPERTY(qreal pointerAcceleration READ pointerAcceleration WRITE setPointerAcceleration NOTIFY pointerAccelerationChanged) - - Q_PROPERTY(bool supportsPointerAccelerationProfileFlat READ supportsPointerAccelerationProfileFlat CONSTANT) - Q_PROPERTY(bool defaultPointerAccelerationProfileFlat READ defaultPointerAccelerationProfileFlat CONSTANT) - Q_PROPERTY(bool pointerAccelerationProfileFlat READ pointerAccelerationProfileFlat WRITE setPointerAccelerationProfileFlat NOTIFY pointerAccelerationProfileChanged) - - Q_PROPERTY(bool supportsPointerAccelerationProfileAdaptive READ supportsPointerAccelerationProfileAdaptive CONSTANT) - Q_PROPERTY(bool defaultPointerAccelerationProfileAdaptive READ defaultPointerAccelerationProfileAdaptive CONSTANT) - Q_PROPERTY(bool pointerAccelerationProfileAdaptive READ pointerAccelerationProfileAdaptive WRITE setPointerAccelerationProfileAdaptive NOTIFY pointerAccelerationProfileChanged) - - // - // tapping - Q_PROPERTY(int tapFingerCount READ tapFingerCount CONSTANT) - Q_PROPERTY(bool tapToClickEnabledByDefault READ tapToClickEnabledByDefault CONSTANT) - Q_PROPERTY(bool tapToClick READ isTapToClick WRITE setTapToClick NOTIFY tapToClickChanged) - - Q_PROPERTY(bool supportsLmrTapButtonMap READ supportsLmrTapButtonMap CONSTANT) - Q_PROPERTY(bool lmrTapButtonMapEnabledByDefault READ lmrTapButtonMapEnabledByDefault CONSTANT) - Q_PROPERTY(bool lmrTapButtonMap READ lmrTapButtonMap WRITE setLmrTapButtonMap NOTIFY lmrTapButtonMapChanged) - - Q_PROPERTY(bool tapAndDragEnabledByDefault READ tapAndDragEnabledByDefault CONSTANT) - Q_PROPERTY(bool tapAndDrag READ isTapAndDrag WRITE setTapAndDrag NOTIFY tapAndDragChanged) - - Q_PROPERTY(bool tapDragLockEnabledByDefault READ tapDragLockEnabledByDefault CONSTANT) - Q_PROPERTY(bool tapDragLock READ isTapDragLock WRITE setTapDragLock NOTIFY tapDragLockChanged) - - // - // scrolling - Q_PROPERTY(bool supportsNaturalScroll READ supportsNaturalScroll CONSTANT) - Q_PROPERTY(bool naturalScrollEnabledByDefault READ naturalScrollEnabledByDefault CONSTANT) - Q_PROPERTY(bool naturalScroll READ isNaturalScroll WRITE setNaturalScroll NOTIFY naturalScrollChanged) - - Q_PROPERTY(bool supportsScrollTwoFinger READ supportsScrollTwoFinger CONSTANT) - Q_PROPERTY(bool scrollTwoFingerEnabledByDefault READ scrollTwoFingerEnabledByDefault CONSTANT) - Q_PROPERTY(bool scrollTwoFinger READ isScrollTwoFinger WRITE setScrollTwoFinger NOTIFY scrollMethodChanged) - - Q_PROPERTY(bool supportsScrollEdge READ supportsScrollEdge CONSTANT) - Q_PROPERTY(bool scrollEdgeEnabledByDefault READ scrollEdgeEnabledByDefault CONSTANT) - Q_PROPERTY(bool scrollEdge READ isScrollEdge WRITE setScrollEdge NOTIFY scrollMethodChanged) - - Q_PROPERTY(bool supportsScrollOnButtonDown READ supportsScrollOnButtonDown CONSTANT) - Q_PROPERTY(bool scrollOnButtonDownEnabledByDefault READ scrollOnButtonDownEnabledByDefault CONSTANT) - Q_PROPERTY(bool scrollOnButtonDown READ isScrollOnButtonDown WRITE setScrollOnButtonDown NOTIFY scrollMethodChanged) - - Q_PROPERTY(quint32 defaultScrollButton READ defaultScrollButton CONSTANT) - Q_PROPERTY(quint32 scrollButton READ scrollButton WRITE setScrollButton NOTIFY scrollButtonChanged) - - // Click Methods - Q_PROPERTY(bool supportsClickMethodAreas READ supportsClickMethodAreas CONSTANT) - Q_PROPERTY(bool defaultClickMethodAreas READ defaultClickMethodAreas CONSTANT) - Q_PROPERTY(bool clickMethodAreas READ isClickMethodAreas WRITE setClickMethodAreas NOTIFY clickMethodChanged) - - Q_PROPERTY(bool supportsClickMethodClickfinger READ supportsClickMethodClickfinger CONSTANT) - Q_PROPERTY(bool defaultClickMethodClickfinger READ defaultClickMethodClickfinger CONSTANT) - Q_PROPERTY(bool clickMethodClickfinger READ isClickMethodClickfinger WRITE setClickMethodClickfinger NOTIFY clickMethodChanged) - public: KWinWaylandTouchpad(QString dbusName); ~KWinWaylandTouchpad() override; bool init(); bool getConfig(); bool getDefaultConfig(); bool applyConfig(); bool isChangedConfig() const; // // general - QString name() const { + QString name() const override { return m_name.val; } QString sysName() const { return m_sysName.val; } - bool supportsDisableEvents() const { + bool supportsDisableEvents() const override { return m_supportsDisableEvents.val; } - void setEnabled(bool enabled) { + void setEnabled(bool enabled) override { m_enabled.set(enabled); } - bool isEnabled() const { + bool isEnabled() const override { return m_enabled.val; } - Qt::MouseButtons supportedButtons() const { - return m_supportedButtons.val; - } - // // advanced - bool supportsLeftHanded() const { + bool supportsLeftHanded() const override { return m_supportsLeftHanded.val; } - bool leftHandedEnabledByDefault() const { - return m_leftHandedEnabledByDefault.val; - } - bool isLeftHanded() const { - return m_leftHanded.val; - } - void setLeftHanded(bool set) { - m_leftHanded.set(set); - } - - bool supportsDisableEventsOnExternalMouse() const { + bool supportsDisableEventsOnExternalMouse() const override { return m_supportsDisableEventsOnExternalMouse.val; } - - bool supportsDisableWhileTyping() const { + bool supportsDisableWhileTyping() const override { return m_supportsDisableWhileTyping.val; } - bool disableWhileTypingEnabledByDefault() const { - return m_disableWhileTypingEnabledByDefault.val; - } - bool isDisableWhileTyping() const { - return m_disableWhileTyping.val; - } - void setDisableWhileTyping(bool set) { - m_disableWhileTyping.set(set); - } - - bool supportsMiddleEmulation() const { + bool supportsMiddleEmulation() const override { return m_supportsMiddleEmulation.val; } - bool middleEmulationEnabledByDefault() const { - return m_middleEmulationEnabledByDefault.val; - } - bool isMiddleEmulation() const { - return m_middleEmulation.val; - } - void setMiddleEmulation(bool set) { - m_middleEmulation.set(set); + // + // tapping + void setLmrTapButtonMap(bool set) override { + m_lmrTapButtonMap.set(set); } - // // acceleration speed and profile - bool supportsPointerAcceleration() const { + bool supportsPointerAcceleration() const override { return m_supportsPointerAcceleration.val; } - qreal pointerAcceleration() const { - return m_pointerAcceleration.val; - } - void setPointerAcceleration(qreal acceleration) { - m_pointerAcceleration.set(acceleration); - } - - bool supportsPointerAccelerationProfileFlat() const { + bool supportsPointerAccelerationProfileFlat() const override { return m_supportsPointerAccelerationProfileFlat.val; } - bool defaultPointerAccelerationProfileFlat() const { - return m_defaultPointerAccelerationProfileFlat.val; - } - bool pointerAccelerationProfileFlat() const { - return m_pointerAccelerationProfileFlat.val; - } - void setPointerAccelerationProfileFlat(bool set) { - m_pointerAccelerationProfileFlat.set(set); - } - - bool supportsPointerAccelerationProfileAdaptive() const { + bool supportsPointerAccelerationProfileAdaptive() const override { return m_supportsPointerAccelerationProfileAdaptive.val; } - bool defaultPointerAccelerationProfileAdaptive() const { - return m_defaultPointerAccelerationProfileAdaptive.val; - } - bool pointerAccelerationProfileAdaptive() const { - return m_pointerAccelerationProfileAdaptive.val; - } - void setPointerAccelerationProfileAdaptive(bool set) { - m_pointerAccelerationProfileAdaptive.set(set); - } - - // - // tapping - int tapFingerCount() const { - return m_tapFingerCount.val; - } - bool tapToClickEnabledByDefault() const { - return m_tapToClickEnabledByDefault.val; - } - bool isTapToClick() const { - return m_tapToClick.val; - } - void setTapToClick(bool set) { - m_tapToClick.set(set); - } - - bool supportsLmrTapButtonMap() const { - return m_tapFingerCount.val > 1; - } - bool lmrTapButtonMapEnabledByDefault() const { - return m_lmrTapButtonMapEnabledByDefault.val; - } - bool lmrTapButtonMap() const { - return m_lmrTapButtonMap.val; - } - void setLmrTapButtonMap(bool set) { - m_lmrTapButtonMap.set(set); - } - - bool tapAndDragEnabledByDefault() const { - return m_tapAndDragEnabledByDefault.val; - } - bool isTapAndDrag() const { - return m_tapAndDrag.val; - } - void setTapAndDrag(bool set) { - m_tapAndDrag.set(set); - } - - bool tapDragLockEnabledByDefault() const { - return m_tapDragLockEnabledByDefault.val; - } - bool isTapDragLock() const { - return m_tapDragLock.val; - } - void setTapDragLock(bool set) { - m_tapDragLock.set(set); - } - // // scrolling - bool supportsNaturalScroll() const { + bool supportsNaturalScroll() const override { return m_supportsNaturalScroll.val; } - bool naturalScrollEnabledByDefault() const { - return m_naturalScrollEnabledByDefault.val; - } - bool isNaturalScroll() const { - return m_naturalScroll.val; + bool supportsHorizontalScrolling() const override { + return false; } - void setNaturalScroll(bool set) { - m_naturalScroll.set(set); - } - - bool supportsScrollTwoFinger() const { + bool supportsScrollTwoFinger() const override { return m_supportsScrollTwoFinger.val; } - bool scrollTwoFingerEnabledByDefault() const { - return m_scrollTwoFingerEnabledByDefault.val; - } - bool isScrollTwoFinger() const { - return m_isScrollTwoFinger.val; - } - void setScrollTwoFinger(bool set) { - m_isScrollTwoFinger.set(set); - } - - bool supportsScrollEdge() const { + bool supportsScrollEdge() const override { return m_supportsScrollEdge.val; } - bool scrollEdgeEnabledByDefault() const { - return m_scrollEdgeEnabledByDefault.val; - } - bool isScrollEdge() const { - return m_isScrollEdge.val; - } - void setScrollEdge(bool set) { - m_isScrollEdge.set(set); - } - - bool supportsScrollOnButtonDown() const { + bool supportsScrollOnButtonDown() const override { return m_supportsScrollOnButtonDown.val; } - bool scrollOnButtonDownEnabledByDefault() const { - return m_scrollOnButtonDownEnabledByDefault.val; - } - bool isScrollOnButtonDown() const { - return m_isScrollOnButtonDown.val; - } - void setScrollOnButtonDown(bool set) { - m_isScrollOnButtonDown.set(set); - } - - quint32 defaultScrollButton() const { - return m_defaultScrollButton.val; - } - quint32 scrollButton() const { - return m_scrollButton.val; - } - void setScrollButton(quint32 button) { - m_scrollButton.set(button); - } - - bool supportsClickMethodAreas() const { + // + // Click method + bool supportsClickMethodAreas() const override { return m_supportsClickMethodAreas.val; } - bool defaultClickMethodAreas() const { - return m_defaultClickMethodAreas.val; - } - bool isClickMethodAreas() const { - return m_clickMethodAreas.val; - } - void setClickMethodAreas(bool set) { - m_clickMethodAreas.set(set); - } - - bool supportsClickMethodClickfinger() const { + bool supportsClickMethodClickfinger() const override { return m_supportsClickMethodClickfinger.val; } - bool defaultClickMethodClickfinger() const { - return m_defaultClickMethodClickfinger.val; - } - bool isClickMethodClickfinger() const { - return m_clickMethodClickfinger.val; - } - void setClickMethodClickfinger(bool set) { - m_clickMethodClickfinger.set(set); - } - -Q_SIGNALS: - void leftHandedChanged(); - void pointerAccelerationChanged(); - void pointerAccelerationProfileChanged(); - void enabledChanged(); - void tapToClickChanged(); - void tapAndDragChanged(); - void tapDragLockChanged(); - void lmrTapButtonMapChanged(); - void disableWhileTypingChanged(); - void middleEmulationChanged(); - void naturalScrollChanged(); - void scrollMethodChanged(); - void scrollButtonChanged(); - void clickMethodChanged(); private: - template - struct Prop { - explicit Prop(const QByteArray &dbusName) - : dbus(dbusName) - {} - - void set(T newVal) { - if (avail && val != newVal) { - val = newVal; - } - } - void set(const Prop &p) { - if (avail && val != p.val) { - val = p.val; - } - } - bool changed() const { - return avail && (old != val); - } - - QByteArray dbus; - bool avail; - T old; - T val; - }; template bool valueLoader(Prop &prop); template QString valueWriter(const Prop &prop); - // // general Prop m_name = Prop("name"); Prop m_sysName = Prop("sysName"); - Prop m_supportsDisableEvents = Prop("supportsDisableEvents"); - Prop m_enabled = Prop("enabled"); // // advanced - Prop m_supportedButtons = Prop("supportedButtons"); - Prop m_supportsLeftHanded = Prop("supportsLeftHanded"); - Prop m_leftHandedEnabledByDefault = Prop("leftHandedEnabledByDefault"); - Prop m_leftHanded = Prop("leftHanded"); - - Prop m_supportsDisableEventsOnExternalMouse = Prop("supportsDisableEventsOnExternalMouse"); - Prop m_supportsDisableWhileTyping = Prop("supportsDisableWhileTyping"); - Prop m_disableWhileTypingEnabledByDefault = Prop("disableWhileTypingEnabledByDefault"); - Prop m_disableWhileTyping = Prop("disableWhileTyping"); - Prop m_supportsMiddleEmulation = Prop("supportsMiddleEmulation"); - Prop m_middleEmulationEnabledByDefault = Prop("middleEmulationEnabledByDefault"); - Prop m_middleEmulation = Prop("middleEmulation"); // // acceleration speed and profile Prop m_supportsPointerAcceleration = Prop("supportsPointerAcceleration"); - Prop m_defaultPointerAcceleration = Prop("defaultPointerAcceleration"); - Prop m_pointerAcceleration = Prop("pointerAcceleration"); - - Prop m_supportsPointerAccelerationProfileFlat = Prop("supportsPointerAccelerationProfileFlat"); - Prop m_defaultPointerAccelerationProfileFlat = Prop("defaultPointerAccelerationProfileFlat"); - Prop m_pointerAccelerationProfileFlat = Prop("pointerAccelerationProfileFlat"); - - Prop m_supportsPointerAccelerationProfileAdaptive = Prop("supportsPointerAccelerationProfileAdaptive"); - Prop m_defaultPointerAccelerationProfileAdaptive = Prop("defaultPointerAccelerationProfileAdaptive"); - Prop m_pointerAccelerationProfileAdaptive = Prop("pointerAccelerationProfileAdaptive"); - - // - // tapping - Prop m_tapFingerCount = Prop("tapFingerCount"); - Prop m_tapToClickEnabledByDefault = Prop("tapToClickEnabledByDefault"); - Prop m_tapToClick = Prop("tapToClick"); - - Prop m_lmrTapButtonMapEnabledByDefault = Prop("lmrTapButtonMapEnabledByDefault"); - Prop m_lmrTapButtonMap = Prop("lmrTapButtonMap"); - - Prop m_tapAndDragEnabledByDefault = Prop("tapAndDragEnabledByDefault"); - Prop m_tapAndDrag = Prop("tapAndDrag"); - Prop m_tapDragLockEnabledByDefault = Prop("tapDragLockEnabledByDefault"); - Prop m_tapDragLock = Prop("tapDragLock"); // // scrolling Prop m_supportsNaturalScroll = Prop("supportsNaturalScroll"); - Prop m_naturalScrollEnabledByDefault = Prop("naturalScrollEnabledByDefault"); - Prop m_naturalScroll = Prop("naturalScroll"); - - Prop m_supportsScrollTwoFinger = Prop("supportsScrollTwoFinger"); - Prop m_scrollTwoFingerEnabledByDefault = Prop("scrollTwoFingerEnabledByDefault"); - Prop m_isScrollTwoFinger = Prop("scrollTwoFinger"); - - Prop m_supportsScrollEdge = Prop("supportsScrollEdge"); - Prop m_scrollEdgeEnabledByDefault = Prop("scrollEdgeEnabledByDefault"); - Prop m_isScrollEdge = Prop("scrollEdge"); - - Prop m_supportsScrollOnButtonDown = Prop("supportsScrollOnButtonDown"); - Prop m_scrollOnButtonDownEnabledByDefault = Prop("scrollOnButtonDownEnabledByDefault"); - Prop m_isScrollOnButtonDown = Prop("scrollOnButtonDown"); - - Prop m_defaultScrollButton = Prop("defaultScrollButton"); - Prop m_scrollButton = Prop("scrollButton"); - - Prop m_supportsClickMethodAreas = Prop("supportsClickMethodAreas"); - Prop m_defaultClickMethodAreas = Prop("defaultClickMethodAreas"); - Prop m_clickMethodAreas = Prop("clickMethodAreas"); - - Prop m_supportsClickMethodClickfinger = Prop("supportsClickMethodClickfinger"); - Prop m_defaultClickMethodClickfinger = Prop("defaultClickMethodClickfinger"); - Prop m_clickMethodClickfinger = Prop("clickMethodClickfinger"); - QDBusInterface *m_iface; }; #endif diff --git a/kcms/touchpad/src/kcm/touchpadconfigplugin.cpp b/kcms/touchpad/src/backends/libinputcommon.cpp similarity index 72% copy from kcms/touchpad/src/kcm/touchpadconfigplugin.cpp copy to kcms/touchpad/src/backends/libinputcommon.cpp index 05dbd069a..3bfeab98c 100644 --- a/kcms/touchpad/src/kcm/touchpadconfigplugin.cpp +++ b/kcms/touchpad/src/backends/libinputcommon.cpp @@ -1,26 +1,22 @@ /* - * Copyright 2017 Roman Gilg + * Copyright 2019 Atul Bisht * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#include "touchpadconfigplugin.h" -#include "touchpadconfigcontainer.h" +#include "libinputcommon.h" -TouchpadConfigPlugin::TouchpadConfigPlugin(QWidget *parent) - : QWidget(parent), - m_parent(dynamic_cast(parent)) -{ -} + +#include "moc_libinputcommon.cpp" diff --git a/kcms/touchpad/src/backends/kwin_wayland/kwinwaylandtouchpad.h b/kcms/touchpad/src/backends/libinputcommon.h similarity index 84% copy from kcms/touchpad/src/backends/kwin_wayland/kwinwaylandtouchpad.h copy to kcms/touchpad/src/backends/libinputcommon.h index d6cb3a8d2..ee81288c5 100644 --- a/kcms/touchpad/src/backends/kwin_wayland/kwinwaylandtouchpad.h +++ b/kcms/touchpad/src/backends/libinputcommon.h @@ -1,502 +1,490 @@ /* * Copyright 2017 Roman Gilg + * Copyright 2019 Atul Bisht * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef KWINWAYLANDTOUCHPAD_H -#define KWINWAYLANDTOUCHPAD_H +#ifndef LIBINPUTCOMMON_H +#define LIBINPUTCOMMON_H #include -#include +#include -class QDBusInterface; +namespace { +template +T valueLoaderPart(QVariant const &reply) { Q_UNUSED(reply); return T(); } -class KWinWaylandTouchpad : public QObject +template<> +bool valueLoaderPart(QVariant const &reply) { return reply.toBool(); } + +template<> +int valueLoaderPart(QVariant const &reply) { return reply.toInt(); } + +template<> +quint32 valueLoaderPart(QVariant const &reply) { return reply.toInt(); } + +template<> +qreal valueLoaderPart(QVariant const &reply) { return reply.toReal(); } + +template<> +QString valueLoaderPart(QVariant const &reply) { return reply.toString(); } + +template<> +Qt::MouseButtons valueLoaderPart(QVariant const &reply) { return static_cast(reply.toInt()); } +} + +class LibinputCommon : public QObject { Q_OBJECT // // general Q_PROPERTY(QString name READ name CONSTANT) Q_PROPERTY(bool supportsDisableEvents READ supportsDisableEvents CONSTANT) Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled NOTIFY enabledChanged) // // advanced Q_PROPERTY(Qt::MouseButtons supportedButtons READ supportedButtons CONSTANT) Q_PROPERTY(bool supportsLeftHanded READ supportsLeftHanded CONSTANT) Q_PROPERTY(bool leftHandedEnabledByDefault READ leftHandedEnabledByDefault CONSTANT) Q_PROPERTY(bool leftHanded READ isLeftHanded WRITE setLeftHanded NOTIFY leftHandedChanged) Q_PROPERTY(bool supportsDisableEventsOnExternalMouse READ supportsDisableEventsOnExternalMouse CONSTANT) Q_PROPERTY(bool supportsDisableWhileTyping READ supportsDisableWhileTyping CONSTANT) Q_PROPERTY(bool disableWhileTypingEnabledByDefault READ disableWhileTypingEnabledByDefault CONSTANT) Q_PROPERTY(bool disableWhileTyping READ isDisableWhileTyping WRITE setDisableWhileTyping NOTIFY disableWhileTypingChanged) Q_PROPERTY(bool supportsMiddleEmulation READ supportsMiddleEmulation CONSTANT) Q_PROPERTY(bool middleEmulationEnabledByDefault READ middleEmulationEnabledByDefault CONSTANT) Q_PROPERTY(bool middleEmulation READ isMiddleEmulation WRITE setMiddleEmulation NOTIFY middleEmulationChanged) // // acceleration speed and profile Q_PROPERTY(bool supportsPointerAcceleration READ supportsPointerAcceleration CONSTANT) Q_PROPERTY(qreal pointerAcceleration READ pointerAcceleration WRITE setPointerAcceleration NOTIFY pointerAccelerationChanged) Q_PROPERTY(bool supportsPointerAccelerationProfileFlat READ supportsPointerAccelerationProfileFlat CONSTANT) Q_PROPERTY(bool defaultPointerAccelerationProfileFlat READ defaultPointerAccelerationProfileFlat CONSTANT) Q_PROPERTY(bool pointerAccelerationProfileFlat READ pointerAccelerationProfileFlat WRITE setPointerAccelerationProfileFlat NOTIFY pointerAccelerationProfileChanged) Q_PROPERTY(bool supportsPointerAccelerationProfileAdaptive READ supportsPointerAccelerationProfileAdaptive CONSTANT) Q_PROPERTY(bool defaultPointerAccelerationProfileAdaptive READ defaultPointerAccelerationProfileAdaptive CONSTANT) Q_PROPERTY(bool pointerAccelerationProfileAdaptive READ pointerAccelerationProfileAdaptive WRITE setPointerAccelerationProfileAdaptive NOTIFY pointerAccelerationProfileChanged) // // tapping Q_PROPERTY(int tapFingerCount READ tapFingerCount CONSTANT) Q_PROPERTY(bool tapToClickEnabledByDefault READ tapToClickEnabledByDefault CONSTANT) Q_PROPERTY(bool tapToClick READ isTapToClick WRITE setTapToClick NOTIFY tapToClickChanged) Q_PROPERTY(bool supportsLmrTapButtonMap READ supportsLmrTapButtonMap CONSTANT) Q_PROPERTY(bool lmrTapButtonMapEnabledByDefault READ lmrTapButtonMapEnabledByDefault CONSTANT) Q_PROPERTY(bool lmrTapButtonMap READ lmrTapButtonMap WRITE setLmrTapButtonMap NOTIFY lmrTapButtonMapChanged) Q_PROPERTY(bool tapAndDragEnabledByDefault READ tapAndDragEnabledByDefault CONSTANT) Q_PROPERTY(bool tapAndDrag READ isTapAndDrag WRITE setTapAndDrag NOTIFY tapAndDragChanged) Q_PROPERTY(bool tapDragLockEnabledByDefault READ tapDragLockEnabledByDefault CONSTANT) Q_PROPERTY(bool tapDragLock READ isTapDragLock WRITE setTapDragLock NOTIFY tapDragLockChanged) // // scrolling Q_PROPERTY(bool supportsNaturalScroll READ supportsNaturalScroll CONSTANT) Q_PROPERTY(bool naturalScrollEnabledByDefault READ naturalScrollEnabledByDefault CONSTANT) Q_PROPERTY(bool naturalScroll READ isNaturalScroll WRITE setNaturalScroll NOTIFY naturalScrollChanged) + Q_PROPERTY(bool supportsHorizontalScrolling READ supportsHorizontalScrolling CONSTANT) + Q_PROPERTY(bool horizontalScrollingByDefault READ horizontalScrollingByDefault CONSTANT) + Q_PROPERTY(bool horizontalScrolling READ horizontalScrolling WRITE setHorizontalScrolling NOTIFY horizontalScrollingChanged) + Q_PROPERTY(bool supportsScrollTwoFinger READ supportsScrollTwoFinger CONSTANT) Q_PROPERTY(bool scrollTwoFingerEnabledByDefault READ scrollTwoFingerEnabledByDefault CONSTANT) Q_PROPERTY(bool scrollTwoFinger READ isScrollTwoFinger WRITE setScrollTwoFinger NOTIFY scrollMethodChanged) Q_PROPERTY(bool supportsScrollEdge READ supportsScrollEdge CONSTANT) Q_PROPERTY(bool scrollEdgeEnabledByDefault READ scrollEdgeEnabledByDefault CONSTANT) Q_PROPERTY(bool scrollEdge READ isScrollEdge WRITE setScrollEdge NOTIFY scrollMethodChanged) Q_PROPERTY(bool supportsScrollOnButtonDown READ supportsScrollOnButtonDown CONSTANT) Q_PROPERTY(bool scrollOnButtonDownEnabledByDefault READ scrollOnButtonDownEnabledByDefault CONSTANT) Q_PROPERTY(bool scrollOnButtonDown READ isScrollOnButtonDown WRITE setScrollOnButtonDown NOTIFY scrollMethodChanged) Q_PROPERTY(quint32 defaultScrollButton READ defaultScrollButton CONSTANT) Q_PROPERTY(quint32 scrollButton READ scrollButton WRITE setScrollButton NOTIFY scrollButtonChanged) - // Click Methods + // Click Methods Q_PROPERTY(bool supportsClickMethodAreas READ supportsClickMethodAreas CONSTANT) Q_PROPERTY(bool defaultClickMethodAreas READ defaultClickMethodAreas CONSTANT) Q_PROPERTY(bool clickMethodAreas READ isClickMethodAreas WRITE setClickMethodAreas NOTIFY clickMethodChanged) Q_PROPERTY(bool supportsClickMethodClickfinger READ supportsClickMethodClickfinger CONSTANT) Q_PROPERTY(bool defaultClickMethodClickfinger READ defaultClickMethodClickfinger CONSTANT) Q_PROPERTY(bool clickMethodClickfinger READ isClickMethodClickfinger WRITE setClickMethodClickfinger NOTIFY clickMethodChanged) public: - KWinWaylandTouchpad(QString dbusName); - ~KWinWaylandTouchpad() override; - bool init(); + LibinputCommon() {} + virtual ~LibinputCommon() {} - bool getConfig(); - bool getDefaultConfig(); - bool applyConfig(); - bool isChangedConfig() const; + virtual QString name() const = 0; + virtual bool supportsDisableEvents() const = 0; + virtual bool isEnabled() const = 0; + virtual void setEnabled(bool set) = 0; // - // general - QString name() const { - return m_name.val; - } - QString sysName() const { - return m_sysName.val; - } - bool supportsDisableEvents() const { - return m_supportsDisableEvents.val; - } - void setEnabled(bool enabled) { - m_enabled.set(enabled); - } - bool isEnabled() const { - return m_enabled.val; - } + // advanced Qt::MouseButtons supportedButtons() const { return m_supportedButtons.val; } - // - // advanced - bool supportsLeftHanded() const { - return m_supportsLeftHanded.val; - } + virtual bool supportsLeftHanded() const = 0; bool leftHandedEnabledByDefault() const { return m_leftHandedEnabledByDefault.val; } bool isLeftHanded() const { return m_leftHanded.val; } void setLeftHanded(bool set) { m_leftHanded.set(set); } - bool supportsDisableEventsOnExternalMouse() const { - return m_supportsDisableEventsOnExternalMouse.val; - } + virtual bool supportsDisableEventsOnExternalMouse() const = 0; - bool supportsDisableWhileTyping() const { - return m_supportsDisableWhileTyping.val; - } + virtual bool supportsDisableWhileTyping() const = 0; bool disableWhileTypingEnabledByDefault() const { return m_disableWhileTypingEnabledByDefault.val; } bool isDisableWhileTyping() const { return m_disableWhileTyping.val; } void setDisableWhileTyping(bool set) { m_disableWhileTyping.set(set); } - bool supportsMiddleEmulation() const { - return m_supportsMiddleEmulation.val; - } + virtual bool supportsMiddleEmulation() const = 0; bool middleEmulationEnabledByDefault() const { return m_middleEmulationEnabledByDefault.val; } bool isMiddleEmulation() const { return m_middleEmulation.val; } void setMiddleEmulation(bool set) { m_middleEmulation.set(set); } - // - // acceleration speed and profile - bool supportsPointerAcceleration() const { - return m_supportsPointerAcceleration.val; - } + virtual bool supportsPointerAcceleration() const = 0; qreal pointerAcceleration() const { return m_pointerAcceleration.val; } void setPointerAcceleration(qreal acceleration) { m_pointerAcceleration.set(acceleration); } - bool supportsPointerAccelerationProfileFlat() const { - return m_supportsPointerAccelerationProfileFlat.val; - } + virtual bool supportsPointerAccelerationProfileFlat() const = 0; bool defaultPointerAccelerationProfileFlat() const { return m_defaultPointerAccelerationProfileFlat.val; } bool pointerAccelerationProfileFlat() const { return m_pointerAccelerationProfileFlat.val; } void setPointerAccelerationProfileFlat(bool set) { m_pointerAccelerationProfileFlat.set(set); } - bool supportsPointerAccelerationProfileAdaptive() const { - return m_supportsPointerAccelerationProfileAdaptive.val; - } + virtual bool supportsPointerAccelerationProfileAdaptive() const = 0; bool defaultPointerAccelerationProfileAdaptive() const { return m_defaultPointerAccelerationProfileAdaptive.val; } bool pointerAccelerationProfileAdaptive() const { return m_pointerAccelerationProfileAdaptive.val; } void setPointerAccelerationProfileAdaptive(bool set) { m_pointerAccelerationProfileAdaptive.set(set); } - // - // tapping - int tapFingerCount() const { - return m_tapFingerCount.val; - } - bool tapToClickEnabledByDefault() const { - return m_tapToClickEnabledByDefault.val; - } - bool isTapToClick() const { - return m_tapToClick.val; - } - void setTapToClick(bool set) { - m_tapToClick.set(set); - } - - bool supportsLmrTapButtonMap() const { - return m_tapFingerCount.val > 1; - } - bool lmrTapButtonMapEnabledByDefault() const { - return m_lmrTapButtonMapEnabledByDefault.val; - } - bool lmrTapButtonMap() const { - return m_lmrTapButtonMap.val; - } - void setLmrTapButtonMap(bool set) { - m_lmrTapButtonMap.set(set); - } - - bool tapAndDragEnabledByDefault() const { - return m_tapAndDragEnabledByDefault.val; - } - bool isTapAndDrag() const { - return m_tapAndDrag.val; - } - void setTapAndDrag(bool set) { - m_tapAndDrag.set(set); - } - - bool tapDragLockEnabledByDefault() const { - return m_tapDragLockEnabledByDefault.val; - } - bool isTapDragLock() const { - return m_tapDragLock.val; - } - void setTapDragLock(bool set) { - m_tapDragLock.set(set); - } - // // scrolling - bool supportsNaturalScroll() const { - return m_supportsNaturalScroll.val; - } + virtual bool supportsNaturalScroll() const = 0; bool naturalScrollEnabledByDefault() const { return m_naturalScrollEnabledByDefault.val; } bool isNaturalScroll() const { return m_naturalScroll.val; } void setNaturalScroll(bool set) { m_naturalScroll.set(set); } - bool supportsScrollTwoFinger() const { - return m_supportsScrollTwoFinger.val; + virtual bool supportsHorizontalScrolling() const = 0; + bool horizontalScrollingByDefault() const { + return true; + } + bool horizontalScrolling() const { + return m_horizontalScrolling.val; + } + void setHorizontalScrolling(bool set) { + m_horizontalScrolling.set(set); } + + virtual bool supportsScrollTwoFinger() const = 0; bool scrollTwoFingerEnabledByDefault() const { return m_scrollTwoFingerEnabledByDefault.val; } bool isScrollTwoFinger() const { return m_isScrollTwoFinger.val; } void setScrollTwoFinger(bool set) { m_isScrollTwoFinger.set(set); } - bool supportsScrollEdge() const { - return m_supportsScrollEdge.val; - } + virtual bool supportsScrollEdge() const = 0; bool scrollEdgeEnabledByDefault() const { return m_scrollEdgeEnabledByDefault.val; } bool isScrollEdge() const { return m_isScrollEdge.val; } void setScrollEdge(bool set) { m_isScrollEdge.set(set); } - bool supportsScrollOnButtonDown() const { - return m_supportsScrollOnButtonDown.val; - } + virtual bool supportsScrollOnButtonDown() const = 0; bool scrollOnButtonDownEnabledByDefault() const { return m_scrollOnButtonDownEnabledByDefault.val; } bool isScrollOnButtonDown() const { return m_isScrollOnButtonDown.val; } void setScrollOnButtonDown(bool set) { m_isScrollOnButtonDown.set(set); } quint32 defaultScrollButton() const { return m_defaultScrollButton.val; } quint32 scrollButton() const { return m_scrollButton.val; } void setScrollButton(quint32 button) { m_scrollButton.set(button); } - - bool supportsClickMethodAreas() const { - return m_supportsClickMethodAreas.val; + + // + // tapping + int tapFingerCount() const { + return m_tapFingerCount.val; + } + bool tapToClickEnabledByDefault() const { + return m_tapToClickEnabledByDefault.val; + } + bool isTapToClick() const { + return m_tapToClick.val; + } + void setTapToClick(bool set) { + m_tapToClick.set(set); + } + + bool supportsLmrTapButtonMap() const { + return m_tapFingerCount.val > 1; + } + bool lmrTapButtonMapEnabledByDefault() const { + return m_lmrTapButtonMapEnabledByDefault.val; + } + bool lmrTapButtonMap() const { + return m_lmrTapButtonMap.val; + } + virtual void setLmrTapButtonMap(bool set) = 0; + + bool tapAndDragEnabledByDefault() const { + return m_tapAndDragEnabledByDefault.val; + } + bool isTapAndDrag() const { + return m_tapAndDrag.val; + } + void setTapAndDrag(bool set) { + m_tapAndDrag.set(set); + } + + bool tapDragLockEnabledByDefault() const { + return m_tapDragLockEnabledByDefault.val; + } + bool isTapDragLock() const { + return m_tapDragLock.val; + } + void setTapDragLock(bool set) { + m_tapDragLock.set(set); } + + // + // click method + virtual bool supportsClickMethodAreas() const = 0; bool defaultClickMethodAreas() const { return m_defaultClickMethodAreas.val; } bool isClickMethodAreas() const { return m_clickMethodAreas.val; } void setClickMethodAreas(bool set) { m_clickMethodAreas.set(set); } - bool supportsClickMethodClickfinger() const { - return m_supportsClickMethodClickfinger.val; - } + virtual bool supportsClickMethodClickfinger() const = 0; bool defaultClickMethodClickfinger() const { return m_defaultClickMethodClickfinger.val; } bool isClickMethodClickfinger() const { return m_clickMethodClickfinger.val; } void setClickMethodClickfinger(bool set) { m_clickMethodClickfinger.set(set); } Q_SIGNALS: - void leftHandedChanged(); - void pointerAccelerationChanged(); - void pointerAccelerationProfileChanged(); void enabledChanged(); + // Tapping void tapToClickChanged(); + void lmrTapButtonMapChanged(); void tapAndDragChanged(); void tapDragLockChanged(); - void lmrTapButtonMapChanged(); + // Advanced + void leftHandedChanged(); void disableWhileTypingChanged(); void middleEmulationChanged(); + // acceleration speed and profile + void pointerAccelerationChanged(); + void pointerAccelerationProfileChanged(); + // scrolling void naturalScrollChanged(); + void horizontalScrollingChanged(); void scrollMethodChanged(); void scrollButtonChanged(); + // click methods void clickMethodChanged(); -private: +protected: template struct Prop { - explicit Prop(const QByteArray &dbusName) - : dbus(dbusName) + explicit Prop(const QByteArray &name) + : name(name) {} void set(T newVal) { if (avail && val != newVal) { val = newVal; } } void set(const Prop &p) { if (avail && val != p.val) { val = p.val; } } bool changed() const { return avail && (old != val); } - QByteArray dbus; + // In wayland, name will be dbus name + QByteArray name; bool avail; T old; T val; }; - template - bool valueLoader(Prop &prop); - template - QString valueWriter(const Prop &prop); // // general - Prop m_name = Prop("name"); - Prop m_sysName = Prop("sysName"); Prop m_supportsDisableEvents = Prop("supportsDisableEvents"); + Prop m_enabledDefault = Prop("enabledDefault"); Prop m_enabled = Prop("enabled"); // // advanced Prop m_supportedButtons = Prop("supportedButtons"); - Prop m_supportsLeftHanded = Prop("supportsLeftHanded"); Prop m_leftHandedEnabledByDefault = Prop("leftHandedEnabledByDefault"); Prop m_leftHanded = Prop("leftHanded"); Prop m_supportsDisableEventsOnExternalMouse = Prop("supportsDisableEventsOnExternalMouse"); - Prop m_supportsDisableWhileTyping = Prop("supportsDisableWhileTyping"); Prop m_disableWhileTypingEnabledByDefault = Prop("disableWhileTypingEnabledByDefault"); Prop m_disableWhileTyping = Prop("disableWhileTyping"); - Prop m_supportsMiddleEmulation = Prop("supportsMiddleEmulation"); Prop m_middleEmulationEnabledByDefault = Prop("middleEmulationEnabledByDefault"); Prop m_middleEmulation = Prop("middleEmulation"); // // acceleration speed and profile - Prop m_supportsPointerAcceleration = Prop("supportsPointerAcceleration"); Prop m_defaultPointerAcceleration = Prop("defaultPointerAcceleration"); Prop m_pointerAcceleration = Prop("pointerAcceleration"); Prop m_supportsPointerAccelerationProfileFlat = Prop("supportsPointerAccelerationProfileFlat"); Prop m_defaultPointerAccelerationProfileFlat = Prop("defaultPointerAccelerationProfileFlat"); Prop m_pointerAccelerationProfileFlat = Prop("pointerAccelerationProfileFlat"); Prop m_supportsPointerAccelerationProfileAdaptive = Prop("supportsPointerAccelerationProfileAdaptive"); Prop m_defaultPointerAccelerationProfileAdaptive = Prop("defaultPointerAccelerationProfileAdaptive"); Prop m_pointerAccelerationProfileAdaptive = Prop("pointerAccelerationProfileAdaptive"); // // tapping Prop m_tapFingerCount = Prop("tapFingerCount"); Prop m_tapToClickEnabledByDefault = Prop("tapToClickEnabledByDefault"); Prop m_tapToClick = Prop("tapToClick"); Prop m_lmrTapButtonMapEnabledByDefault = Prop("lmrTapButtonMapEnabledByDefault"); Prop m_lmrTapButtonMap = Prop("lmrTapButtonMap"); Prop m_tapAndDragEnabledByDefault = Prop("tapAndDragEnabledByDefault"); Prop m_tapAndDrag = Prop("tapAndDrag"); Prop m_tapDragLockEnabledByDefault = Prop("tapDragLockEnabledByDefault"); Prop m_tapDragLock = Prop("tapDragLock"); // // scrolling - Prop m_supportsNaturalScroll = Prop("supportsNaturalScroll"); Prop m_naturalScrollEnabledByDefault = Prop("naturalScrollEnabledByDefault"); Prop m_naturalScroll = Prop("naturalScroll"); + Prop m_horizontalScrolling = Prop("horizontalScrolling"); + Prop m_supportsScrollTwoFinger = Prop("supportsScrollTwoFinger"); Prop m_scrollTwoFingerEnabledByDefault = Prop("scrollTwoFingerEnabledByDefault"); Prop m_isScrollTwoFinger = Prop("scrollTwoFinger"); Prop m_supportsScrollEdge = Prop("supportsScrollEdge"); Prop m_scrollEdgeEnabledByDefault = Prop("scrollEdgeEnabledByDefault"); Prop m_isScrollEdge = Prop("scrollEdge"); Prop m_supportsScrollOnButtonDown = Prop("supportsScrollOnButtonDown"); Prop m_scrollOnButtonDownEnabledByDefault = Prop("scrollOnButtonDownEnabledByDefault"); Prop m_isScrollOnButtonDown = Prop("scrollOnButtonDown"); Prop m_defaultScrollButton = Prop("defaultScrollButton"); Prop m_scrollButton = Prop("scrollButton"); + // Click Method Prop m_supportsClickMethodAreas = Prop("supportsClickMethodAreas"); Prop m_defaultClickMethodAreas = Prop("defaultClickMethodAreas"); Prop m_clickMethodAreas = Prop("clickMethodAreas"); Prop m_supportsClickMethodClickfinger = Prop("supportsClickMethodClickfinger"); Prop m_defaultClickMethodClickfinger = Prop("defaultClickMethodClickfinger"); Prop m_clickMethodClickfinger = Prop("clickMethodClickfinger"); - - - QDBusInterface *m_iface; }; -#endif +#endif // LIBINPUTCOMMON_H diff --git a/kcms/touchpad/src/backends/x11.cmake b/kcms/touchpad/src/backends/x11.cmake index 7eb18bc91..db25da464 100644 --- a/kcms/touchpad/src/backends/x11.cmake +++ b/kcms/touchpad/src/backends/x11.cmake @@ -1,45 +1,46 @@ # // krazy:excludeall=copyright,license find_package(X11 REQUIRED) find_package(X11_XCB REQUIRED) find_package(XCB REQUIRED COMPONENTS ATOM RECORD) find_package(PkgConfig REQUIRED) if(NOT X11_Xinput_FOUND) message(FATAL_ERROR "Xinput not found") endif() include_directories(${X11_Xinput_INCLUDE_PATH} ${X11_X11_INCLUDE_PATH} ${Synaptics_INCLUDE_DIRS} ${XORG_INCLUDE_DIRS} ) SET(backend_SRCS ${backend_SRCS} + backends/libinputcommon.cpp backends/x11/propertyinfo.cpp backends/x11/xlibbackend.cpp backends/x11/synapticstouchpad.cpp backends/x11/libinputtouchpad.cpp backends/x11/xlibtouchpad.cpp backends/x11/xcbatom.cpp backends/x11/xlibnotifications.cpp backends/x11/xrecordkeyboardmonitor.cpp ) SET(backend_LIBS ${backend_LIBS} XCB::ATOM XCB::RECORD ${X11_X11_LIB} X11::XCB ${X11_Xinput_LIB} ) add_executable(kcm-touchpad-list-devices backends/x11/listdevices.cpp) target_link_libraries(kcm-touchpad-list-devices ${X11_X11_LIB} ${X11_Xinput_LIB} ) install(TARGETS kcm-touchpad-list-devices DESTINATION ${KDE_INSTALL_TARGETS_DEFAULT_ARGS} ) diff --git a/kcms/touchpad/src/backends/x11/libinputtouchpad.cpp b/kcms/touchpad/src/backends/x11/libinputtouchpad.cpp index fea6e810a..389d85961 100644 --- a/kcms/touchpad/src/backends/x11/libinputtouchpad.cpp +++ b/kcms/touchpad/src/backends/x11/libinputtouchpad.cpp @@ -1,61 +1,404 @@ /* - * Copyright (C) 2015 Red Hat, Inc. + * Copyright (C) 2019 Atul Bisht * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +#include +#include + #include "libinputtouchpad.h" #include #include +#include +#include +#include "logging.h" + const struct Parameter libinputProperties[] = { + + /* libinput disable supports property */ + {"supportsDisableEvents", PT_INT, 0, 1, LIBINPUT_PROP_SENDEVENTS_AVAILABLE, 8, 0}, + {"enabled", PT_INT, 0, 1, LIBINPUT_PROP_SENDEVENTS_ENABLED, 8, 0}, + {"enabledDefault", PT_INT, 0, 1, LIBINPUT_PROP_SENDEVENTS_ENABLED_DEFAULT, 8, 0}, + + /* LeftHandSupport */ + {"leftHandedEnabledByDefault", PT_INT, 0, 1, LIBINPUT_PROP_LEFT_HANDED_DEFAULT, 8, 0}, + {"leftHanded", PT_INT, 0, 1, LIBINPUT_PROP_LEFT_HANDED, 8, 0}, + + /* Disable on external mouse */ + {"supportsDisableEventsOnExternalMouse",PT_INT, 0, 1, LIBINPUT_PROP_SENDEVENTS_AVAILABLE, 8, 1}, + {"disableEventsOnExternalMouse", PT_INT, 0, 1, LIBINPUT_PROP_SENDEVENTS_ENABLED, 8, 1}, + {"disableEventsOnExternalMouseDefault", PT_INT, 0, 1, LIBINPUT_PROP_SENDEVENTS_ENABLED_DEFAULT, 8, 1}, + + /* Disable while typing */ + {"disableWhileTypingEnabledByDefault", PT_INT, 0, 1, LIBINPUT_PROP_DISABLE_WHILE_TYPING_DEFAULT, 8, 0}, + {"disableWhileTyping", PT_INT, 0, 1, LIBINPUT_PROP_DISABLE_WHILE_TYPING, 8, 0}, + + /* Middle Emulation */ + {"middleEmulationEnabledByDefault", PT_INT, 0, 1, LIBINPUT_PROP_MIDDLE_EMULATION_ENABLED_DEFAULT, 8, 0}, + {"middleEmulation", PT_INT, 0, 1, LIBINPUT_PROP_MIDDLE_EMULATION_ENABLED, 8, 0}, + /* This is a boolean for all three fingers, no per-finger config */ - {"Tapping", PT_INT, 0, 1, "libinput Tapping Enabled", 8, 0}, + {"tapToClick", PT_INT, 0, 1, LIBINPUT_PROP_TAP, 8, 0}, + {"tapToClickEnabledByDefault", PT_INT, 0, 1, LIBINPUT_PROP_TAP_DEFAULT, 8, 0}, + + /* LMR */ + {"lrmTapButtonMapEnabledByDefault", PT_INT, 0, 1, LIBINPUT_PROP_TAP_BUTTONMAP_DEFAULT, 8, 0}, + {"lrmTapButtonMap", PT_INT, 0, 1, LIBINPUT_PROP_TAP_BUTTONMAP, 8, 0}, + {"lmrTapButtonMapEnabledByDefault", PT_INT, 0, 1, LIBINPUT_PROP_TAP_BUTTONMAP_DEFAULT, 8, 1}, + {"lmrTapButtonMap", PT_INT, 0, 1, LIBINPUT_PROP_TAP_BUTTONMAP, 8, 1}, + + /* Tap and Drag Enabled */ + {"tapAndDragEnabledByDefault", PT_INT, 0, 1, LIBINPUT_PROP_TAP_DRAG_DEFAULT, 8, 0}, + {"tapAndDrag", PT_INT, 0, 1, LIBINPUT_PROP_TAP_DRAG, 8, 0}, + + /* Tap and Drag Lock Enabled */ + {"tapDragLockEnabledByDefault", PT_INT, 0, 1, LIBINPUT_PROP_TAP_DRAG_LOCK_DEFAULT, 8, 0}, + {"tapDragLock", PT_INT, 0, 1, LIBINPUT_PROP_TAP_DRAG_LOCK, 8, 0}, + /* libinput normalizes the accel to -1/1 */ - {"AccelFactor", PT_DOUBLE, -1.0, 1.0, "libinput Accel Speed", 0 /*float */, 0}, - /* Only one of these may be set at one time */ - {"VertEdgeScroll", PT_INT, 0, 1, "libinput Scroll Method Enabled", 8, 1}, - {"VertTwoFingerScroll", PT_INT, 0, 1, "libinput Scroll Method Enabled", 8, 0}, - {"InvertVertScroll", PT_INT, 0, 1, "libinput Natural Scrolling Enabled", 8, 0}, + {"defaultPointerAcceleration", PT_DOUBLE, -1.0, 1.0, LIBINPUT_PROP_ACCEL_DEFAULT, 0 /*float */, 0}, + {"pointerAcceleration", PT_DOUBLE, -1.0, 1.0, LIBINPUT_PROP_ACCEL, 0 /*float */, 0}, + + /* Libinput Accel Profile */ + {"supportsPointerAccelerationProfileAdaptive", PT_BOOL, 0, 1, LIBINPUT_PROP_ACCEL_PROFILES_AVAILABLE, 8, 0}, + {"defaultPointerAccelerationProfileAdaptive", PT_BOOL, 0, 1, LIBINPUT_PROP_ACCEL_PROFILE_ENABLED_DEFAULT, 8, 0}, + {"pointerAccelerationProfileAdaptive", PT_BOOL, 0, 1, LIBINPUT_PROP_ACCEL_PROFILE_ENABLED, 8, 0}, + {"supportsPointerAccelerationProfileFlat", PT_BOOL, 0, 1, LIBINPUT_PROP_ACCEL_PROFILES_AVAILABLE, 8, 1}, + {"defaultPointerAccelerationProfileFlat", PT_BOOL, 0, 1, LIBINPUT_PROP_ACCEL_PROFILE_ENABLED_DEFAULT, 8, 1}, + {"pointerAccelerationProfileFlat", PT_BOOL, 0, 1, LIBINPUT_PROP_ACCEL_PROFILE_ENABLED, 8, 1}, + + /* Natural Scrolling */ + {"naturalScrollEnabledByDefault", PT_INT, 0, 1, LIBINPUT_PROP_NATURAL_SCROLL_DEFAULT, 8, 0}, + {"naturalScroll", PT_INT, 0, 1, LIBINPUT_PROP_NATURAL_SCROLL, 8, 0}, + + /* Horizontal scrolling */ + {"horizontalScrolling", PT_INT, 0, 1, LIBINPUT_PROP_HORIZ_SCROLL_ENABLED, 8, 0}, + + /* Two-Finger Scrolling */ + {"supportsScrollTwoFinger", PT_INT, 0, 1, LIBINPUT_PROP_SCROLL_METHODS_AVAILABLE, 8, 0}, + {"scrollTwoFingerEnabledByDefault", PT_INT, 0, 1, LIBINPUT_PROP_SCROLL_METHOD_ENABLED_DEFAULT, 8, 0}, + {"scrollTwoFinger", PT_INT, 0, 1, LIBINPUT_PROP_SCROLL_METHOD_ENABLED, 8, 0}, + + /* Edge Scrolling */ + {"supportsScrollEdge", PT_INT, 0, 1, LIBINPUT_PROP_SCROLL_METHODS_AVAILABLE, 8, 1}, + {"scrollEdgeEnabledByDefault", PT_INT, 0, 1, LIBINPUT_PROP_SCROLL_METHOD_ENABLED_DEFAULT, 8, 1}, + {"scrollEdge", PT_INT, 0, 1, LIBINPUT_PROP_SCROLL_METHOD_ENABLED, 8, 1}, + + /* scroll on button */ + {"supportsScrollOnButtonDown", PT_INT, 0, 1, LIBINPUT_PROP_SCROLL_METHODS_AVAILABLE, 8, 2}, + {"scrollOnButtonDownEnabledByDefault", PT_INT, 0, 1, LIBINPUT_PROP_SCROLL_METHOD_ENABLED_DEFAULT, 8, 2}, + {"scrollOnButtonDown", PT_INT, 0, 1, LIBINPUT_PROP_SCROLL_METHOD_ENABLED, 8, 2}, + + /* Scroll Button for scroll on button Down */ + {"defaultScrollButton", PT_INT, 0, INT_MAX, LIBINPUT_PROP_SCROLL_BUTTON_DEFAULT, 32, 0}, + {"scrollButton", PT_INT, 0, INT_MAX, LIBINPUT_PROP_SCROLL_BUTTON, 32, 0}, + + /* Click Methods */ + {"supportsClickMethodAreas", PT_INT, 0, 1, LIBINPUT_PROP_CLICK_METHODS_AVAILABLE, 8, 0}, + {"defaultClickMethodAreas", PT_INT, 0, 1, LIBINPUT_PROP_CLICK_METHOD_ENABLED_DEFAULT, 8, 0}, + {"clickMethodAreas", PT_INT, 0, 1, LIBINPUT_PROP_CLICK_METHOD_ENABLED, 8, 0}, + + {"supportsClickMethodClickfinger", PT_INT, 0, 1, LIBINPUT_PROP_CLICK_METHODS_AVAILABLE, 8, 1}, + {"defaultClickMethodClickfinger", PT_INT, 0, 1, LIBINPUT_PROP_CLICK_METHOD_ENABLED_DEFAULT, 8, 1}, + {"clickMethodClickfinger", PT_INT, 0, 1, LIBINPUT_PROP_CLICK_METHOD_ENABLED, 8, 1}, + /* libinput doesn't have a separate toggle for horiz scrolling */ { NULL, PT_INT, 0, 0, 0, 0, 0 } }; -LibinputTouchpad::LibinputTouchpad(Display *display, int deviceId): XlibTouchpad(display, deviceId) +Qt::MouseButtons maskBtns(Display *display, XIButtonClassInfo *buttonInfo) +{ + Qt::MouseButtons buttons = Qt::NoButton; + for (int i = 0; i < buttonInfo->num_buttons; ++i) { + QByteArray reply = XGetAtomName(display, buttonInfo->labels[i]); + + if (reply == BTN_LABEL_PROP_BTN_LEFT) { + buttons |= Qt::LeftButton; + } + if (reply == BTN_LABEL_PROP_BTN_RIGHT) { + buttons |= Qt::RightButton; + } + if (reply == BTN_LABEL_PROP_BTN_MIDDLE) { + buttons |= Qt::MiddleButton; + } + if (reply == BTN_LABEL_PROP_BTN_SIDE) { + buttons |= Qt::ExtraButton1; + } + if (reply == BTN_LABEL_PROP_BTN_EXTRA) { + buttons |= Qt::ExtraButton2; + } + if (reply == BTN_LABEL_PROP_BTN_FORWARD) { + buttons |= Qt::ForwardButton; + } + if (reply == BTN_LABEL_PROP_BTN_BACK) { + buttons |= Qt::BackButton; + } + if (reply == BTN_LABEL_PROP_BTN_TASK) { + buttons |= Qt::TaskButton; + } + } + return buttons; +} + +LibinputTouchpad::LibinputTouchpad(Display *display, int deviceId): + LibinputCommon(), + XlibTouchpad(display, deviceId) { loadSupportedProperties(libinputProperties); - /* FIXME: has a different format than Synaptics Off but we don't expose - the toggle so this is just to stop it from crashing when we check - m_touchpadOffAtom */ - m_touchpadOffAtom.intern(m_connection, - "libinput Send Events Mode enabled"); - - - XcbAtom scroll_methods(m_connection, - "libinput Scroll Methods Available", - true); - if (scroll_methods.atom() != 0) { - PropertyInfo methods(m_display, - m_deviceId, - scroll_methods.atom(), - 0); - if (!methods.value(0).toInt()) - m_supported.removeAll("VertTwoFingerScroll"); - else if (!methods.value(1).toInt()) - m_supported.removeAll("VertEdgeScroll"); + int nDevices = 0; + XIDeviceInfo *deviceInfo = XIQueryDevice(m_display, m_deviceId, &nDevices); + m_name = deviceInfo->name; + + for (int i = 0; i < deviceInfo->num_classes; ++i) { + XIAnyClassInfo *classInfo = deviceInfo->classes[i]; + + if (classInfo->type == XIButtonClass) { + XIButtonClassInfo *btnInfo = (XIButtonClassInfo*) classInfo; + m_supportedButtons.avail = true; + m_supportedButtons.set(maskBtns(m_display, btnInfo)); + } + if (classInfo->type == XITouchClass) { + XITouchClassInfo *touchInfo = (XITouchClassInfo*) classInfo; + m_tapFingerCount.avail = true; + m_tapFingerCount.set(touchInfo->num_touches); + } + } + XIFreeDeviceInfo(deviceInfo); + + /* FingerCount cannot be zero */ + if (!m_tapFingerCount.val) { + m_tapFingerCount.avail = true; + m_tapFingerCount.set(1); + } +} + +bool LibinputTouchpad::getConfig() +{ + bool success = true; + + success &= valueLoader(m_supportsDisableEvents); + success &= valueLoader(m_enabled); + success &= valueLoader(m_enabledDefault); + + success &= valueLoader(m_tapToClickEnabledByDefault); + success &= valueLoader(m_tapToClick); + success &= valueLoader(m_lrmTapButtonMapEnabledByDefault); + success &= valueLoader(m_lrmTapButtonMap); + success &= valueLoader(m_lmrTapButtonMapEnabledByDefault); + success &= valueLoader(m_lmrTapButtonMap); + success &= valueLoader(m_tapAndDragEnabledByDefault); + success &= valueLoader(m_tapAndDrag); + success &= valueLoader(m_tapDragLockEnabledByDefault); + success &= valueLoader(m_tapDragLock); + + success &= valueLoader(m_leftHandedEnabledByDefault); + success &= valueLoader(m_leftHanded); + + success &= valueLoader(m_supportsDisableEventsOnExternalMouse); + success &= valueLoader(m_disableEventsOnExternalMouse); + success &= valueLoader(m_disableEventsOnExternalMouseDefault); + + success &= valueLoader(m_disableWhileTypingEnabledByDefault); + success &= valueLoader(m_disableWhileTyping); + + success &= valueLoader(m_middleEmulationEnabledByDefault); + success &= valueLoader(m_middleEmulation); + + success &= valueLoader(m_defaultPointerAcceleration); + success &= valueLoader(m_pointerAcceleration); + + success &= valueLoader(m_supportsPointerAccelerationProfileFlat); + success &= valueLoader(m_defaultPointerAccelerationProfileFlat); + success &= valueLoader(m_pointerAccelerationProfileFlat); + success &= valueLoader(m_supportsPointerAccelerationProfileAdaptive); + success &= valueLoader(m_defaultPointerAccelerationProfileAdaptive); + success &= valueLoader(m_pointerAccelerationProfileAdaptive); + + success &= valueLoader(m_naturalScrollEnabledByDefault); + success &= valueLoader(m_naturalScroll); + + success &= valueLoader(m_horizontalScrolling); + + success &= valueLoader(m_supportsScrollTwoFinger); + success &= valueLoader(m_scrollTwoFingerEnabledByDefault); + success &= valueLoader(m_isScrollTwoFinger); + + success &= valueLoader(m_supportsScrollEdge); + success &= valueLoader(m_scrollEdgeEnabledByDefault); + success &= valueLoader(m_isScrollEdge); + + success &= valueLoader(m_supportsScrollOnButtonDown); + success &= valueLoader(m_scrollOnButtonDownEnabledByDefault); + success &= valueLoader(m_isScrollOnButtonDown); + + success &= valueLoader(m_defaultScrollButton); + success &= valueLoader(m_scrollButton); + + // click methods + success &= valueLoader(m_supportsClickMethodAreas); + success &= valueLoader(m_supportsClickMethodClickfinger); + success &= valueLoader(m_defaultClickMethodAreas); + success &= valueLoader(m_defaultClickMethodClickfinger); + success &= valueLoader(m_clickMethodAreas); + success &= valueLoader(m_clickMethodClickfinger); + + return success; +} + +bool LibinputTouchpad::applyConfig() +{ + QVector msgs; + + msgs << valueWriter(m_enabled) + << valueWriter(m_tapToClick) + << valueWriter(m_lrmTapButtonMap) + << valueWriter(m_lmrTapButtonMap) + << valueWriter(m_tapAndDrag) + << valueWriter(m_tapDragLock) + << valueWriter(m_leftHanded) + << valueWriter(m_disableWhileTyping) + << valueWriter(m_middleEmulation) + << valueWriter(m_pointerAcceleration) + << valueWriter(m_pointerAccelerationProfileFlat) + << valueWriter(m_pointerAccelerationProfileAdaptive) + << valueWriter(m_naturalScroll) + << valueWriter(m_horizontalScrolling) + << valueWriter(m_isScrollTwoFinger) + << valueWriter(m_isScrollEdge) + << valueWriter(m_isScrollOnButtonDown) + << valueWriter(m_scrollButton) + << valueWriter(m_clickMethodAreas) + << valueWriter(m_clickMethodClickfinger); + + bool success = true; + QString error_msg; + + for (QString m : msgs) { + if (!m.isNull()) { + qCCritical(KCM_TOUCHPAD) << "in error:" << m; + if (!success) { + error_msg.append("\n"); + } + error_msg.append(m); + success = false; + } + } + + if (!success) { + qCCritical(KCM_TOUCHPAD) << error_msg; + } + + flush(); + return success; +} + +bool LibinputTouchpad::getDefaultConfig() +{ + m_enabled.set(m_enabledDefault); + m_tapToClick.set(m_tapToClickEnabledByDefault); + m_lrmTapButtonMap.set(m_lrmTapButtonMap); + m_lmrTapButtonMap.set(m_lmrTapButtonMapEnabledByDefault); + m_tapAndDrag.set(m_tapAndDragEnabledByDefault); + m_tapDragLock.set(m_tapDragLockEnabledByDefault); + m_leftHanded.set(m_leftHandedEnabledByDefault); + m_disableEventsOnExternalMouse.set(m_disableEventsOnExternalMouseDefault); + m_disableWhileTyping.set(m_disableWhileTypingEnabledByDefault); + m_middleEmulation.set(m_middleEmulationEnabledByDefault); + m_pointerAcceleration.set(m_defaultPointerAcceleration); + m_pointerAccelerationProfileFlat.set(m_defaultPointerAccelerationProfileFlat); + m_pointerAccelerationProfileAdaptive.set(m_defaultPointerAccelerationProfileAdaptive); + m_naturalScroll.set(m_naturalScrollEnabledByDefault); + m_horizontalScrolling.set(true); + m_isScrollTwoFinger.set(m_scrollTwoFingerEnabledByDefault); + m_isScrollEdge.set(m_scrollEdgeEnabledByDefault); + m_isScrollOnButtonDown.set(m_scrollOnButtonDownEnabledByDefault); + m_scrollButton.set(m_defaultScrollButton); + m_clickMethodAreas.set(m_defaultClickMethodAreas); + m_clickMethodClickfinger.set(m_defaultClickMethodClickfinger); + + return true; +} + +bool LibinputTouchpad::isChangedConfig() +{ + + bool changed = m_enabled.changed() || + m_tapToClick.changed() || + m_lrmTapButtonMap.changed() || + m_lmrTapButtonMap.changed() || + m_tapAndDrag.changed() || + m_tapDragLock.changed() || + m_leftHanded.changed() || + m_disableEventsOnExternalMouse.changed() || + m_disableWhileTyping.changed() || + m_middleEmulation.changed() || + m_pointerAcceleration.changed() || + m_pointerAccelerationProfileFlat.changed() || + m_pointerAccelerationProfileAdaptive.changed() || + m_naturalScroll.changed() || + m_horizontalScrolling.changed() || + m_isScrollTwoFinger.changed() || + m_isScrollEdge.changed() || + m_isScrollOnButtonDown.changed() || + m_scrollButton.changed() || + m_clickMethodAreas.changed() || + m_clickMethodClickfinger.changed(); + + return changed; +} + +template +bool LibinputTouchpad::valueLoader(Prop &prop) +{ + const Parameter *p = findParameter(QString::fromAscii(prop.name)); + + if (!p) { + qCCritical(KCM_TOUCHPAD) << "Error on read of " << QString::fromAscii(prop.name); + } + + QVariant reply = getParameter(p); + if (!reply.isValid()) { + prop.avail = false; + return true; + } + prop.avail = true; + + T replyValue = valueLoaderPart(reply); + + prop.old = replyValue; + prop.val = replyValue; + return true; +} + +template +QString LibinputTouchpad::valueWriter(const Prop &prop) +{ + const Parameter *p = findParameter(QString::fromAscii(prop.name)); + + if (!p || !prop.changed()) { + return QString(); + } + + bool error = !setParameter( p, prop.val); + if (error) { + qCCritical(KCM_TOUCHPAD) << "Cannot set property " + QString::fromAscii(prop.name); + return QStringLiteral("Cannot set property ") + QString::fromAscii(prop.name); } + return QString(); } diff --git a/kcms/touchpad/src/backends/x11/libinputtouchpad.h b/kcms/touchpad/src/backends/x11/libinputtouchpad.h index 2de8215b2..eab026025 100644 --- a/kcms/touchpad/src/backends/x11/libinputtouchpad.h +++ b/kcms/touchpad/src/backends/x11/libinputtouchpad.h @@ -1,30 +1,130 @@ /* - * Copyright (C) 2015 Weng Xuetian + * Copyright (C) 2019 Atul Bisht * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef LIBINPUTTOUCHPAD_H #define LIBINPUTTOUCHPAD_H +#include + #include "xlibtouchpad.h" +#include "backends/libinputcommon.h" -class LibinputTouchpad : public XlibTouchpad +class LibinputTouchpad : public LibinputCommon, public XlibTouchpad { + Q_OBJECT + public: LibinputTouchpad(Display *display, int deviceId); + ~LibinputTouchpad() override {} + + bool getConfig() override; + bool applyConfig() override; + bool getDefaultConfig() override; + bool isChangedConfig() override; + +private: + + template + bool valueLoader(Prop &prop); + + template + QString valueWriter(const Prop &prop); + + // + // general + QString name() const override { + return m_name; + } + bool supportsDisableEvents() const override { + return m_supportsDisableEvents.avail && m_supportsDisableEvents.val; + } + bool isEnabled() const override { + return !m_enabled.val; + } + void setEnabled(bool set) override { + m_enabled.set(!set); + } + // + // Tapping + void setLmrTapButtonMap(bool set) override { + m_lrmTapButtonMap.set(!set); + m_lmrTapButtonMap.set(set); + } + // + // advanced + bool supportsLeftHanded() const override { + return m_leftHanded.avail; + } + bool supportsDisableEventsOnExternalMouse() const override { + return m_supportsDisableEventsOnExternalMouse.avail && m_supportsDisableEventsOnExternalMouse.val; + } + bool supportsDisableWhileTyping() const override { + return m_disableWhileTyping.avail; + } + bool supportsMiddleEmulation() const override { + return m_middleEmulation.avail; + } + // + // acceleration speed and profile + bool supportsPointerAcceleration() const override { + return m_pointerAcceleration.avail; + } + bool supportsPointerAccelerationProfileFlat() const override { + return m_supportsPointerAccelerationProfileFlat.avail && m_supportsPointerAccelerationProfileFlat.val; + } + bool supportsPointerAccelerationProfileAdaptive() const override { + return m_supportsPointerAccelerationProfileAdaptive.avail && m_supportsPointerAccelerationProfileAdaptive.val; + } + // + // scrolling + bool supportsNaturalScroll() const override { + return m_naturalScroll.avail; + } + bool supportsHorizontalScrolling() const override { + return true; + } + bool supportsScrollTwoFinger() const override { + return m_supportsScrollTwoFinger.avail && m_supportsScrollTwoFinger.val; + } + bool supportsScrollEdge() const override { + return m_supportsScrollEdge.avail && m_supportsScrollEdge.val; + } + bool supportsScrollOnButtonDown() const override { + return m_supportsScrollOnButtonDown.avail && m_supportsScrollOnButtonDown.val; + } + // + // click method + bool supportsClickMethodAreas() const override { + return m_supportsClickMethodAreas.avail && m_supportsClickMethodAreas.val; + } + bool supportsClickMethodClickfinger() const override { + return m_supportsClickMethodClickfinger.avail && m_supportsClickMethodClickfinger.val; + } + + // Tapping + Prop m_lrmTapButtonMapEnabledByDefault = Prop("lrmTapButtonMapEnabledByDefault"); + Prop m_lrmTapButtonMap = Prop("lrmTapButtonMap"); + // + // advanced + Prop m_disableEventsOnExternalMouse = Prop("disableEventsOnExternalMouse"); + Prop m_disableEventsOnExternalMouseDefault = Prop("disableEventsOnExternalMouseDefault"); + + QString m_name; }; #endif // LIBINPUTTOUCHPAD_H diff --git a/kcms/touchpad/src/backends/x11/synapticstouchpad.h b/kcms/touchpad/src/backends/x11/synapticstouchpad.h index eafc17acd..0f4b30b05 100644 --- a/kcms/touchpad/src/backends/x11/synapticstouchpad.h +++ b/kcms/touchpad/src/backends/x11/synapticstouchpad.h @@ -1,39 +1,41 @@ /* * Copyright (C) 2015 Weng Xuetian * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef SYNAPTICSTOUCHPAD_H #define SYNAPTICSTOUCHPAD_H #include "xlibtouchpad.h" #include "xcbatom.h" -class SynapticsTouchpad : public XlibTouchpad +class SynapticsTouchpad : public QObject, public XlibTouchpad { + Q_OBJECT + public: SynapticsTouchpad(Display *display, int deviceId); protected: double getPropertyScale(const QString &name) const override; private: XcbAtom m_capsAtom; int m_resX, m_resY; QStringList m_scaleByResX, m_scaleByResY, m_toRadians; }; #endif // SYNAPTICSTOUCHPAD_H diff --git a/kcms/touchpad/src/backends/x11/xlibbackend.cpp b/kcms/touchpad/src/backends/x11/xlibbackend.cpp index 5d1d21caf..4d5ffa43d 100644 --- a/kcms/touchpad/src/backends/x11/xlibbackend.cpp +++ b/kcms/touchpad/src/backends/x11/xlibbackend.cpp @@ -1,324 +1,391 @@ /* * Copyright (C) 2013 Alexander Mezin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include #include #include #include #include #include //Includes are ordered this way because of #defines in Xorg's headers #include "xrecordkeyboardmonitor.h" // krazy:exclude=includes #include "xlibbackend.h" // krazy:exclude=includes #include "xlibnotifications.h" // krazy:exclude=includes #include "libinputtouchpad.h" #include "synapticstouchpad.h" #include "propertyinfo.h" #include #include #include #include #include #include struct DeviceListDeleter { static void cleanup(XDeviceInfo *p) { if (p) { XFreeDeviceList(p); } } }; void XlibBackend::XDisplayCleanup::cleanup(Display *p) { if (p) { XCloseDisplay(p); } } XlibBackend* XlibBackend::initialize(QObject *parent) { XlibBackend* backend = new XlibBackend(parent); if (!backend->m_display) { delete backend; return nullptr; } return backend; } XlibBackend::~XlibBackend() { } XlibBackend::XlibBackend(QObject *parent) : TouchpadBackend(parent), m_display(XOpenDisplay(0)), m_connection(0) { if (m_display) { m_connection = XGetXCBConnection(m_display.data()); } if (!m_connection) { m_errorString = i18n("Cannot connect to X server"); return; } m_mouseAtom.intern(m_connection, XI_MOUSE); m_keyboardAtom.intern(m_connection, XI_KEYBOARD); m_touchpadAtom.intern(m_connection, XI_TOUCHPAD); m_enabledAtom.intern(m_connection, XI_PROP_ENABLED); m_synapticsIdentifierAtom.intern(m_connection, SYNAPTICS_PROP_CAPABILITIES); m_libinputIdentifierAtom.intern(m_connection, "libinput Send Events Modes Available"); m_device.reset(findTouchpad()); if (!m_device) { m_errorString = i18n("No touchpad found"); } } XlibTouchpad* XlibBackend::findTouchpad() { int nDevices = 0; QScopedPointer deviceInfo(XListInputDevices(m_display.data(), &nDevices)); for (XDeviceInfo *info = deviceInfo.data(); info < deviceInfo.data() + nDevices; info++) { // Make sure device is touchpad if (info->type != m_touchpadAtom.atom()) { continue; } int nProperties = 0; QSharedPointer properties( XIListProperties(m_display.data(), info->id, &nProperties), XDeleter); Atom *atom = properties.data(), *atomEnd = properties.data() + nProperties; for (; atom != atomEnd; atom++) { if (*atom == m_libinputIdentifierAtom.atom()) { + setMode(TouchpadInputBackendMode::XLibinput); return new LibinputTouchpad(m_display.data(), info->id); } else if (*atom == m_synapticsIdentifierAtom.atom()) { + setMode(TouchpadInputBackendMode::XSynaptics); return new SynapticsTouchpad(m_display.data(), info->id); } } } return nullptr; } bool XlibBackend::applyConfig(const QVariantHash &p) { if (!m_device) { return false; } bool success = m_device->applyConfig(p); if (!success) { m_errorString = i18n("Cannot apply touchpad configuration"); } return success; } +bool XlibBackend::applyConfig() +{ + if (!m_device) { + return false; + } + + bool success = m_device->applyConfig(); + if (!success) { + m_errorString = i18n("Cannot apply touchpad configuration"); + } + + return success; +} + bool XlibBackend::getConfig(QVariantHash &p) { if (!m_device) { return false; } bool success = m_device->getConfig(p); if (!success) { m_errorString = i18n("Cannot read touchpad configuration"); } return success; } +bool XlibBackend::getConfig() +{ + if(!m_device) { + return false; + } + + bool success = m_device->getConfig(); + if (!success) { + m_errorString = i18n("Cannot read touchpad configuration"); + } + return success; +} + +bool XlibBackend::getDefaultConfig() +{ + if (!m_device) { + return false; + } + + bool success = m_device->getDefaultConfig(); + if (!success) { + m_errorString = i18n("Cannot read default touchpad configuration"); + } + return success; +} + +bool XlibBackend::isChangedConfig() const +{ + if (!m_device) { + return false; + } + + return m_device->isChangedConfig(); +} + void XlibBackend::setTouchpadEnabled(bool enable) { if (!m_device) { return; } m_device->setEnabled(enable); // FIXME? This should not be needed, m_notifications should trigger // a propertyChanged signal when we enable/disable the touchpad, // that will emit touchpadStateChanged, but for some reason // XlibNotifications is not getting the property change events // so we just emit touchpadStateChanged from here as a workaround Q_EMIT touchpadStateChanged(); } void XlibBackend::setTouchpadOff(TouchpadBackend::TouchpadOffState state) { if (!m_device) { return; } int touchpadOff = 0; switch (state) { case TouchpadEnabled: touchpadOff = 0; break; case TouchpadFullyDisabled: touchpadOff = 1; break; case TouchpadTapAndScrollDisabled: touchpadOff = 2; break; default: qCritical() << "Unknown TouchpadOffState" << state; return; } m_device->setTouchpadOff(touchpadOff); } bool XlibBackend::isTouchpadAvailable() { return m_device; } bool XlibBackend::isTouchpadEnabled() { if (!m_device) { return false; } return m_device->enabled(); } TouchpadBackend::TouchpadOffState XlibBackend::getTouchpadOff() { if (!m_device) { return TouchpadFullyDisabled; } int value = m_device->touchpadOff(); switch (value) { case 0: return TouchpadEnabled; case 1: return TouchpadFullyDisabled; case 2: return TouchpadTapAndScrollDisabled; default: qCritical() << "Unknown TouchpadOff value" << value; return TouchpadFullyDisabled; } } void XlibBackend::touchpadDetached() { qWarning() << "Touchpad detached"; m_device.reset(); Q_EMIT touchpadReset(); } void XlibBackend::devicePlugged(int device) { if (!m_device) { m_device.reset(findTouchpad()); if (m_device) { qWarning() << "Touchpad reset"; m_notifications.reset(); watchForEvents(m_keyboard); Q_EMIT touchpadReset(); } } if (!m_device || device != m_device->deviceId()) { Q_EMIT mousesChanged(); } } void XlibBackend::propertyChanged(xcb_atom_t prop) { if ((m_device && prop == m_device->touchpadOffAtom().atom()) || prop == m_enabledAtom.atom()) { Q_EMIT touchpadStateChanged(); } } QStringList XlibBackend::listMouses(const QStringList &blacklist) { int nDevices = 0; QScopedPointer info(XListInputDevices(m_display.data(), &nDevices)); QStringList list; for (XDeviceInfo *i = info.data(); i != info.data() + nDevices; i++) { if (m_device && i->id == static_cast(m_device->deviceId())) { continue; } if (i->use != IsXExtensionPointer && i->use != IsXPointer) { continue; } //type = KEYBOARD && use = Pointer means usb receiver for both keyboard //and mouse if (i->type != m_mouseAtom.atom() && i->type != m_keyboardAtom.atom()) { continue; } QString name(i->name); if (blacklist.contains(name, Qt::CaseInsensitive)) { continue; } PropertyInfo enabled(m_display.data(), i->id, m_enabledAtom.atom(), 0); if (enabled.value(0) == false) { continue; } list.append(name); } return list; } +QVector XlibBackend::getDevices() const +{ + QVector touchpads; + + LibinputTouchpad* libinputtouchpad = dynamic_cast (m_device.data()); + SynapticsTouchpad* synaptics = dynamic_cast (m_device.data()); + + if ( libinputtouchpad) { + touchpads.push_back(libinputtouchpad); + } + if (synaptics) { + touchpads.push_back(synaptics); + } + return touchpads; +} + void XlibBackend::watchForEvents(bool keyboard) { if (!m_notifications) { m_notifications.reset(new XlibNotifications(m_display.data(), m_device ? m_device->deviceId() : XIAllDevices)); connect(m_notifications.data(), SIGNAL(devicePlugged(int)), SLOT(devicePlugged(int))); connect(m_notifications.data(), SIGNAL(touchpadDetached()), SLOT(touchpadDetached())); connect(m_notifications.data(), SIGNAL(propertyChanged(xcb_atom_t)), SLOT(propertyChanged(xcb_atom_t))); } if (keyboard == !m_keyboard.isNull()) { return; } if (!keyboard) { m_keyboard.reset(); return; } m_keyboard.reset(new XRecordKeyboardMonitor(m_display.data())); connect(m_keyboard.data(), SIGNAL(keyboardActivityStarted()), SIGNAL(keyboardActivityStarted())); connect(m_keyboard.data(), SIGNAL(keyboardActivityFinished()), SIGNAL(keyboardActivityFinished())); } diff --git a/kcms/touchpad/src/backends/x11/xlibbackend.h b/kcms/touchpad/src/backends/x11/xlibbackend.h index 95a09f58e..4b46e5419 100644 --- a/kcms/touchpad/src/backends/x11/xlibbackend.h +++ b/kcms/touchpad/src/backends/x11/xlibbackend.h @@ -1,96 +1,105 @@ /* * Copyright (C) 2013 Alexander Mezin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef XLIBBACKEND_H #define XLIBBACKEND_H #include #include #include #include #include #include #include #include "touchpadbackend.h" #include "xlibtouchpad.h" +#include "libinputtouchpad.h" +#include "synapticstouchpad.h" #include #include "xcbatom.h" #include "propertyinfo.h" class XlibTouchpad; class XlibNotifications; class XRecordKeyboardMonitor; class XlibBackend : public TouchpadBackend { Q_OBJECT + Q_PROPERTY(int touchpadCount READ touchpadCount CONSTANT) + public: static XlibBackend* initialize(QObject *parent = nullptr); ~XlibBackend(); bool applyConfig(const QVariantHash &) override; + bool applyConfig() override; bool getConfig(QVariantHash &) override; + bool getConfig() override; + bool getDefaultConfig() override; + bool isChangedConfig() const override; QStringList supportedParameters() const override { return m_device ? m_device->supportedParameters() : QStringList(); } QString errorString() const override { return m_errorString; } int touchpadCount() const override { return m_device ? 1 : 0; } void setTouchpadOff(TouchpadOffState) override; TouchpadOffState getTouchpadOff() override; bool isTouchpadAvailable() override; bool isTouchpadEnabled() override; void setTouchpadEnabled(bool) override; void watchForEvents(bool keyboard) override; QStringList listMouses(const QStringList &blacklist) override; + QVector getDevices() const override; private slots: void propertyChanged(xcb_atom_t); void touchpadDetached(); void devicePlugged(int); protected: explicit XlibBackend(QObject *parent); struct XDisplayCleanup { static void cleanup(Display *); }; QScopedPointer m_display; xcb_connection_t *m_connection; XcbAtom m_enabledAtom, m_mouseAtom, m_keyboardAtom, m_touchpadAtom; XcbAtom m_synapticsIdentifierAtom; XcbAtom m_libinputIdentifierAtom; XlibTouchpad *findTouchpad(); QScopedPointer m_device; QString m_errorString; QScopedPointer m_notifications; QScopedPointer m_keyboard; }; #endif // XLIBBACKEND_H diff --git a/kcms/touchpad/src/backends/x11/xlibtouchpad.h b/kcms/touchpad/src/backends/x11/xlibtouchpad.h index 6e72f217b..e6845156f 100644 --- a/kcms/touchpad/src/backends/x11/xlibtouchpad.h +++ b/kcms/touchpad/src/backends/x11/xlibtouchpad.h @@ -1,86 +1,92 @@ /* * Copyright (C) 2015 Weng Xuetian * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef XLIBTOUCHPAD_H #define XLIBTOUCHPAD_H +#include #include #include #include #include "xcbatom.h" #include "propertyinfo.h" enum ParaType { PT_INT, PT_BOOL, PT_DOUBLE }; struct Parameter { const char *name; /* Name of parameter */ enum ParaType type; /* Type of parameter */ double min_val; /* Minimum allowed value */ double max_val; /* Maximum allowed value */ const char *prop_name; /* Property name */ int prop_format; /* Property format (0 for floats) */ unsigned prop_offset; /* Offset inside property */ }; class XlibTouchpad { + public: XlibTouchpad(Display *display, int deviceId); - virtual ~XlibTouchpad() {}; + virtual ~XlibTouchpad() {} int deviceId() { return m_deviceId; } const QStringList &supportedParameters() const { return m_supported; } bool applyConfig(const QVariantHash &p); bool getConfig(QVariantHash &p); + virtual bool getConfig() { return false; } + virtual bool applyConfig() { return false; } + virtual bool getDefaultConfig() { return false; } + virtual bool isChangedConfig() { return false; } void setEnabled(bool enable); bool enabled(); void setTouchpadOff(int touchpadOff); int touchpadOff(); XcbAtom &touchpadOffAtom(); protected: void loadSupportedProperties(const Parameter *props); bool setParameter(const struct Parameter *, const QVariant &); QVariant getParameter(const struct Parameter *); struct PropertyInfo *getDevProperty(const QLatin1String &propName); void flush(); virtual double getPropertyScale(const QString &name) const; const Parameter * findParameter(const QString &name); Display *m_display; xcb_connection_t *m_connection; int m_deviceId; XcbAtom m_floatType, m_enabledAtom, m_touchpadOffAtom; QMap > m_atoms; QMap m_negate; QMap m_props; QSet m_changed; QStringList m_supported; const struct Parameter *m_paramList; }; #endif diff --git a/kcms/touchpad/src/kcm/libinput/main.qml b/kcms/touchpad/src/kcm/libinput/main.qml index 32201352a..d1250c45c 100644 --- a/kcms/touchpad/src/kcm/libinput/main.qml +++ b/kcms/touchpad/src/kcm/libinput/main.qml @@ -1,715 +1,742 @@ /* * Copyright 2017 Roman Gilg * Copyright 2018 Furkan Tokac * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import QtQuick 2.7 import QtQuick.Controls 2.0 as Controls import QtQuick.Layouts 1.3 as Layouts import org.kde.kcm 1.1 as KCM import org.kde.kirigami 2.4 as Kirigami // TODO: Change ScrollablePage as KCM.SimpleKCM // after rewrite the KCM in KConfigModule. Kirigami.ScrollablePage { id: root spacing: Kirigami.Units.smallSpacing property size minimumSizeHint: Qt.size(formLayout.width/2, deviceSelector.height) property alias deviceIndex: deviceSelector.currentIndex signal changeSignal() property QtObject touchpad property int touchpadCount: backend.touchpadCount property bool loading: false function resetModel(index) { touchpadCount = backend.touchpadCount formLayout.enabled = touchpadCount deviceSelector.enabled = touchpadCount > 1 loading = true if (touchpadCount) { touchpad = deviceModel[index] deviceSelector.model = deviceModel deviceSelector.currentIndex = index console.log("Touchpad configuration of device '" + (index + 1) + " : " + touchpad.name + "' opened") } else { deviceSelector.model = [""] console.log("No touchpad found") } loading = false } function syncValuesFromBackend() { loading = true deviceEnabled.load() dwt.load() leftHanded.load() accelSpeed.load() accelProfile.load() tapToClick.load() tapAndDrag.load() tapAndDragLock.load() multiTap.load() scrollMethod.load() naturalScroll.load() rightClickMethod.load() middleClickMethod.load() + disableHorizontalScrolling.load() loading = false } Kirigami.FormLayout { id: formLayout // Device Controls.ComboBox { Kirigami.FormData.label: i18nd("kcm_touchpad", "Device:") id: deviceSelector enabled: touchpadCount > 1 Layouts.Layout.fillWidth: true model: deviceModel textRole: "name" onCurrentIndexChanged: { if (touchpadCount) { touchpad = deviceModel[currentIndex] if (!loading) { changeSignal() } console.log("Touchpad configuration of device '" + (currentIndex+1) + " : " + touchpad.name + "' opened") } root.syncValuesFromBackend() } } Item { Kirigami.FormData.isSection: false } // General settings Controls.CheckBox { Kirigami.FormData.label: i18nd("kcm_touchpad", "General:") id: deviceEnabled text: i18nd("kcm_touchpad", "Device enabled") hoverEnabled: true Controls.ToolTip { text: i18nd("kcm_touchpad", "Accept input through this device.") visible: parent.hovered delay: 1000 } function load() { if (!formLayout.enabled) { checked = false return } enabled = touchpad.supportsDisableEvents checked = enabled && touchpad.enabled } onCheckedChanged: { if (enabled && !root.loading) { touchpad.enabled = checked root.changeSignal() } } } Controls.CheckBox { id: dwt text: i18nd("kcm_touchpad", "Disable while typing") hoverEnabled: true Controls.ToolTip { text: i18nd("kcm_touchpad", "Disable touchpad while typing to prevent accidental inputs.") visible: parent.hovered delay: 1000 } function load() { if (!formLayout.enabled) { checked = false return } enabled = touchpad.supportsDisableWhileTyping checked = enabled && touchpad.disableWhileTyping } onCheckedChanged: { if (enabled && !root.loading) { touchpad.disableWhileTyping = checked root.changeSignal() } } } Controls.CheckBox { id: leftHanded text: i18nd("kcm_touchpad", "Left handed mode") hoverEnabled: true Controls.ToolTip { text: i18nd("kcm_touchpad", "Swap left and right buttons.") visible: parent.hovered delay: 1000 } function load() { if (!formLayout.enabled) { checked = false return } enabled = touchpad.supportsLeftHanded checked = enabled && touchpad.leftHanded } onCheckedChanged: { if (enabled && !root.loading) { touchpad.leftHanded = checked root.changeSignal() } } } Controls.CheckBox { id: middleEmulation text: i18nd("kcm_touchpad", "Press left and right buttons for middle click") hoverEnabled: true Controls.ToolTip { text: i18nd("kcm_touchpad", "Clicking left and right button simultaneously sends middle button click.") visible: parent.hovered delay: 1000 } function load() { if (!formLayout.enabled) { checked = false return } enabled = touchpad.supportsMiddleEmulation checked = enabled && touchpad.middleEmulation } onCheckedChanged: { if (enabled && !root.loading) { touchpad.middleEmulation = checked root.changeSignal() } loading = true middleClickMethod.load() loading = false } } Item { Kirigami.FormData.isSection: false } // Acceleration Controls.Slider { Kirigami.FormData.label: i18nd("kcm_touchpad", "Pointer speed:") id: accelSpeed from: 1 to: 11 stepSize: 1 function load() { enabled = touchpad.supportsPointerAcceleration if (!enabled) { value = 0.1 return } // transform libinput's pointer acceleration range [-1, 1] to slider range [1, 11] value = 6 + touchpad.pointerAcceleration / 0.2 } onValueChanged: { if (touchpad != undefined && enabled && !root.loading) { // transform slider range [1, 11] to libinput's pointer acceleration range [-1, 1] // by *10 and /10, we ignore the floating points after 1 digit. This prevents from // having a libinput value like 0.60000001 touchpad.pointerAcceleration = Math.round(((value-6) * 0.2) * 10) / 10 root.changeSignal() } } } Layouts.ColumnLayout { Kirigami.FormData.label: i18nd("kcm_touchpad", "Acceleration profile:") Kirigami.FormData.buddyFor: accelProfileFlat id: accelProfile spacing: Kirigami.Units.smallSpacing function load() { enabled = touchpad.supportsPointerAccelerationProfileAdaptive if (!enabled) { + accelProfile.visible = false accelProfileFlat.checked = false accelProfileAdaptive.checked = false return } if(touchpad.pointerAccelerationProfileAdaptive) { accelProfileAdaptive.checked = true } else { accelProfileFlat.checked = true } } function syncCurrent() { if (enabled && !root.loading) { touchpad.pointerAccelerationProfileFlat = accelProfileFlat.checked touchpad.pointerAccelerationProfileAdaptive = accelProfileAdaptive.checked root.changeSignal() } } Controls.RadioButton { id: accelProfileFlat text: i18nd("kcm_touchpad", "Flat") hoverEnabled: true Controls.ToolTip { text: i18nd("kcm_touchpad", "Cursor moves the same distance as finger.") visible: parent.hovered delay: 1000 } onCheckedChanged: accelProfile.syncCurrent() } Controls.RadioButton { id: accelProfileAdaptive text: i18nd("kcm_touchpad", "Adaptive") hoverEnabled: true Controls.ToolTip { text: i18nd("kcm_touchpad", "Cursor travel distance depends on movement speed of finger.") visible: parent.hovered delay: 1000 } onCheckedChanged: accelProfile.syncCurrent() } } Item { Kirigami.FormData.isSection: false } // Tapping Controls.CheckBox { Kirigami.FormData.label: i18nd("kcm_touchpad", "Tapping:") id: tapToClick text: i18nd("kcm_touchpad", "Tap-to-click") hoverEnabled: true Controls.ToolTip { text: i18nd("kcm_touchpad", "Single tap is left button click.") visible: parent.hovered delay: 1000 } function load() { enabled = touchpad.tapFingerCount > 0 checked = enabled && touchpad.tapToClick } function updateDependents() { loading = true tapAndDrag.load() tapAndDragLock.load() multiTap.load() loading = false } onCheckedChanged: { if (enabled && !root.loading) { touchpad.tapToClick = checked updateDependents() root.changeSignal() } } } Controls.CheckBox { id: tapAndDrag text: i18nd("kcm_touchpad", "Tap-and-drag") hoverEnabled: true Controls.ToolTip { text: i18nd("kcm_touchpad", "Sliding over touchpad directly after tap drags.") visible: parent.hovered delay: 1000 } function load() { enabled = touchpad.tapFingerCount > 0 && tapToClick.checked checked = enabled && touchpad.tapAndDrag } function updateDependents() { loading = true tapAndDragLock.load() loading = false } onCheckedChanged: { if (enabled && !root.loading) { touchpad.tapAndDrag = checked updateDependents() root.changeSignal() } } } Controls.CheckBox { id: tapAndDragLock text: i18nd("kcm_touchpad", "Tap-and-drag lock") hoverEnabled: true Controls.ToolTip { text: i18nd("kcm_touchpad", "Dragging continues after a short finger lift.") visible: parent.hovered delay: 1000 } function load() { enabled = touchpad.tapFingerCount > 0 && tapAndDrag.checked checked = enabled && touchpad.tapDragLock } onCheckedChanged: { if (enabled && !root.loading) { touchpad.tapDragLock = checked root.changeSignal() } } } Layouts.ColumnLayout { Kirigami.FormData.label: i18nd("kcm_touchpad", "Two-finger tap:") Kirigami.FormData.buddyFor: multiTapRightClick id: multiTap spacing: Kirigami.Units.smallSpacing function load() { enabled = touchpad.supportsLmrTapButtonMap && tapToClick.checked if (touchpad.tapFingerCount > 2) { multiTapRightClick.text = i18nd("kcm_touchpad", "Right-click (three-finger tap to middle-click)") multiTapRightClickToolTip.text = i18nd("kcm_touchpad", "Tap with two fingers to right-click, tap with three fingers to middle-click.") multiTapMiddleClick.text = i18nd("kcm_touchpad", "Middle-click (three-finger tap right-click)") multiTapMiddleClickToolTip.text = i18nd("kcm_touchpad", "Tap with two fingers to middle-click, tap with three fingers to right-click.") } else { multiTapRightClick.text = i18nd("kcm_touchpad", "Right-click") multiTapRightClickToolTip.text = i18nd("kcm_touchpad", "Tap with two fingers to right-click.") multiTapMiddleClick.text = i18nd("kcm_touchpad", "Middle-click") multiTapMiddleClickToolTip.text = i18nd("kcm_touchpad", "Tap with two fingers to middle-click.") } if (!enabled) { multiTapRightClick.checked = false multiTapMiddleClick.checked = false return } if(touchpad.lmrTapButtonMap) { multiTapMiddleClick.checked = true } else { multiTapRightClick.checked = true } } function syncCurrent() { if (enabled && !root.loading) { touchpad.lmrTapButtonMap = multiTapMiddleClick.checked root.changeSignal() } } Controls.RadioButton { id: multiTapRightClick // text: is handled dynamically on load. hoverEnabled: true Controls.ToolTip { id: multiTapRightClickToolTip visible: parent.hovered delay: 1000 // text: is handled dynamically on load. } onCheckedChanged: multiTap.syncCurrent() } Controls.RadioButton { id: multiTapMiddleClick // text: is handled dynamically on load. hoverEnabled: true Controls.ToolTip { id: multiTapMiddleClickToolTip visible: parent.hovered delay: 1000 // text: is handled dynamically on load. } onCheckedChanged: multiTap.syncCurrent() } } Item { Kirigami.FormData.isSection: false } // Scrolling Layouts.ColumnLayout { Kirigami.FormData.label: i18nd("kcm_touchpad", "Scrolling:") Kirigami.FormData.buddyFor: scrollMethodTwoFingers id: scrollMethod spacing: Kirigami.Units.smallSpacing function load() { scrollMethodTwoFingers.enabled = touchpad.supportsScrollTwoFinger scrollMethodTouchpadEdges.enabled = touchpad.supportsScrollEdge if(scrollMethodTouchpadEdges.enabled && touchpad.scrollEdge) { scrollMethodTouchpadEdges.checked = formLayout.enabled } else { scrollMethodTwoFingers.checked = formLayout.enabled } } function syncCurrent() { if (enabled && !root.loading) { touchpad.scrollTwoFinger = scrollMethodTwoFingers.checked touchpad.scrollEdge = scrollMethodTouchpadEdges.checked root.changeSignal() } loading = true naturalScroll.load() loading = false } Controls.RadioButton { id: scrollMethodTwoFingers text: i18nd("kcm_touchpad", "Two fingers") hoverEnabled: true Controls.ToolTip { text: i18nd("kcm_touchpad", "Slide with two fingers scrolls.") visible: parent.hovered delay: 1000 } } Controls.RadioButton { id: scrollMethodTouchpadEdges text: i18nd("kcm_touchpad", "Touchpad edges") hoverEnabled: true Controls.ToolTip { text: i18nd("kcm_touchpad", "Slide on the touchpad edges scrolls.") visible: parent.hovered delay: 1000 } onCheckedChanged: scrollMethod.syncCurrent() } } Controls.CheckBox { id: naturalScroll text: i18nd("kcm_touchpad", "Invert scroll direction (Natural scrolling)") function load() { enabled = touchpad.supportsNaturalScroll checked = enabled && touchpad.naturalScroll } onCheckedChanged: { if (enabled && !root.loading) { touchpad.naturalScroll = checked root.changeSignal() } } hoverEnabled: true Controls.ToolTip { text: i18nd("kcm_touchpad", "Touchscreen like scrolling.") visible: parent.hovered delay: 1000 } } + Controls.CheckBox { + id: disableHorizontalScrolling + text: i18nd("kcm_touchpad", "Disable horizontal scrolling") + + function load() { + visible = touchpad.supportsHorizontalScrolling + enabled = touchpad.supportsHorizontalScrolling + checked = enabled && !touchpad.horizontalScrolling + } + + onCheckedChanged: { + if (enabled && !root.loading) { + touchpad.horizontalScrolling = !checked + root.changeSignal() + } + } + + hoverEnabled: true + Controls.ToolTip { + text: i18nd("kcm_touchpad", "Disable horizontal scrolling") + visible: parent.hovered + delay: 1000 + } + } + Item { Kirigami.FormData.isSection: false } Layouts.ColumnLayout { Kirigami.FormData.label: i18nd("kcm_touchpad", "Right-click :") Kirigami.FormData.buddyFor: rightClickMethodAreas id: rightClickMethod spacing: Kirigami.Units.smallSpacing function load() { visible = (touchpad.supportedButtons & Qt.LeftButton) if (!visible) { rightClickMethodAreas.checked = false rightClickMethodClickfinger.checked = false return; } rightClickMethodAreas.enabled = touchpad.supportsClickMethodAreas rightClickMethodClickfinger.enabled = touchpad.supportsClickMethodClickfinger if (rightClickMethodAreas.enabled && touchpad.clickMethodAreas) { rightClickMethodAreas.checked = true } else if (rightClickMethodClickfinger.enabled && touchpad.clickMethodClickfinger) { rightClickMethodClickfinger.checked = true } } function syncCurrent() { if (enabled && !root.loading) { touchpad.clickMethodAreas = rightClickMethodAreas.checked touchpad.clickMethodClickfinger = rightClickMethodClickfinger.checked root.changeSignal() } loading = true middleClickMethod.load() loading = false } Controls.RadioButton { id: rightClickMethodAreas text: i18nd("kcm_touchpad", "Press bottom-right corner") hoverEnabled: true Controls.ToolTip { text: i18nd("kcm_touchpad", "Software enabled buttons will be added to bottom portion of your touchpad.") visible: parent.hovered delay: 1000 } } Controls.RadioButton { id: rightClickMethodClickfinger text: i18nd("kcm_touchpad", "Press anywhere with two fingers") hoverEnabled: true Controls.ToolTip { text: i18nd("kcm_touchpad", "Tap with two finger to enable right click.") visible: parent.hovered delay: 1000 } onCheckedChanged: rightClickMethod.syncCurrent() } } Item { Kirigami.FormData.isSection: false } Layouts.ColumnLayout { Kirigami.FormData.label: i18nd("kcm_touchpad", "Middle-click: ") Kirigami.FormData.buddyFor: middleSoftwareEmulation id: middleClickMethod spacing: Kirigami.Units.smallSpacing function load() { visible = rightClickMethod.visible if (!visible) { enabled = false return; } enabled = touchpad.supportsMiddleEmulation if (enabled && touchpad.middleEmulation) { middleSoftwareEmulation.checked = true } else { noMiddleSoftwareEmulation.checked = true } } function syncCurrent() { if (enabled && !root.loading) { touchpad.middleEmulation = middleSoftwareEmulation.checked root.changeSignal() } loading = true middleEmulation.load() loading = false } Controls.RadioButton { id: noMiddleSoftwareEmulation text: i18nd("kcm_touchpad", "Press bottom-middle") visible: rightClickMethodAreas.checked hoverEnabled: true Controls.ToolTip { text: i18nd("kcm_touchpad", "Software enabled middle-button will be added to bottom portion of your touchpad.") visible: parent.hovered delay: 1000 } } Controls.RadioButton { id: middleSoftwareEmulation text: i18nd("kcm_touchpad", "Press bottom left and bottom right corners simultaneously") visible: rightClickMethodAreas.checked hoverEnabled: true Controls.ToolTip { text: i18nd("kcm_touchpad", "Clicking left and right button simultaneously sends middle button click.") visible: parent.hovered delay: 1000 } onCheckedChanged: middleClickMethod.syncCurrent() } Controls.CheckBox { id: clickfingerMiddleInfoBox text: i18nd("kcm_touchpad", "Press anywhere with three fingers") checked: true enabled: false visible: rightClickMethodClickfinger.checked hoverEnabled: true Controls.ToolTip { text: i18nd("kcm_touchpad", "Press anywhere with three fingers.") visible: parent.hovered delay: 1000 } } } } // END Kirigami.FormLayout } // END Kirigami.ScrollablePage diff --git a/kcms/touchpad/src/kcm/libinput/touchpadconfiglibinput.cpp b/kcms/touchpad/src/kcm/libinput/touchpadconfiglibinput.cpp index a9703249a..0a0167868 100644 --- a/kcms/touchpad/src/kcm/libinput/touchpadconfiglibinput.cpp +++ b/kcms/touchpad/src/kcm/libinput/touchpadconfiglibinput.cpp @@ -1,221 +1,220 @@ /* * Copyright 2017 Roman Gilg * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "touchpadconfiglibinput.h" #include #include #include #include #include #include #include #include #include #include #include "../touchpadconfigcontainer.h" #include "touchpadbackend.h" #include "version.h" -TouchpadConfigLibinput::TouchpadConfigLibinput(TouchpadConfigContainer *parent, const QVariantList &args) - : TouchpadConfigPlugin(parent) +TouchpadConfigLibinput::TouchpadConfigLibinput(TouchpadConfigContainer *parent, TouchpadBackend* backend, const QVariantList &args) + : TouchpadConfigPlugin(parent, backend) { KAboutData* data = new KAboutData(QStringLiteral("kcm_touchpad"), i18n("Touchpad KCM"), TOUCHPAD_KCM_VERSION, i18n("System Settings module for managing your touchpad"), KAboutLicense::GPL_V2, i18n("Copyright © 2016 Roman Gilg"), QString()); data->addAuthor(i18n("Roman Gilg"), i18n("Developer"), QStringLiteral("subdiff@gmail.com")); m_parent->setAboutData(data); - m_backend = TouchpadBackend::implementation(); m_initError = !m_backend->errorString().isNull(); m_view = new QQuickWidget(this); m_errorMessage = new KMessageWidget(this); m_errorMessage->setCloseButtonVisible(false); m_errorMessage->setWordWrap(true); m_errorMessage->setVisible(false); QVBoxLayout *layout = new QVBoxLayout(parent); layout->addWidget(m_errorMessage); layout->addWidget(m_view); parent->setLayout(layout); m_view->setResizeMode(QQuickWidget::SizeRootObjectToView); m_view->setClearColor(Qt::transparent); m_view->setAttribute(Qt::WA_AlwaysStackOnTop); m_view->rootContext()->setContextProperty("backend", m_backend); m_view->rootContext()->setContextProperty("deviceModel", QVariant::fromValue(m_backend->getDevices().toList())); KDeclarative::KDeclarative kdeclarative; kdeclarative.setDeclarativeEngine(m_view->engine()); kdeclarative.setupBindings(); m_view->setSource(QUrl("qrc:/libinput/main.qml")); if (m_initError) { m_errorMessage->setMessageType(KMessageWidget::Error); m_errorMessage->setText(m_backend->errorString()); QMetaObject::invokeMethod(m_errorMessage, "animatedShow", Qt::QueuedConnection); } else { connect(m_backend, SIGNAL(touchpadAdded(bool)), this, SLOT(onTouchpadAdded(bool))); connect(m_backend, SIGNAL(touchpadRemoved(int)), this, SLOT(onTouchpadRemoved(int))); connect(m_view->rootObject(), SIGNAL(changeSignal()), this, SLOT(onChange())); } m_view->show(); } QSize TouchpadConfigLibinput::sizeHint() const { return QQmlProperty::read(m_view->rootObject(), "sizeHint").toSize(); } QSize TouchpadConfigLibinput::minimumSizeHint() const { return QQmlProperty::read(m_view->rootObject(), "minimumSizeHint").toSize(); } void TouchpadConfigLibinput::load() { // in case of critical init error in backend, don't try if (m_initError) { return; } if (!m_backend->getConfig()) { m_errorMessage->setMessageType(KMessageWidget::Error); m_errorMessage->setText(i18n("Error while loading values. See logs for more information. Please restart this configuration module.")); m_errorMessage->animatedShow(); } else { if (!m_backend->touchpadCount()) { m_errorMessage->setMessageType(KMessageWidget::Information); m_errorMessage->setText(i18n("No touchpad found. Connect touchpad now.")); m_errorMessage->animatedShow(); } } QMetaObject::invokeMethod(m_view->rootObject(), "syncValuesFromBackend"); } void TouchpadConfigLibinput::save() { if (!m_backend->applyConfig()) { m_errorMessage->setMessageType(KMessageWidget::Error); m_errorMessage->setText(i18n("Not able to save all changes. See logs for more information. Please restart this configuration module and try again.")); m_errorMessage->animatedShow(); } else { hideErrorMessage(); } // load newly written values load(); // in case of error, config still in changed state emit m_parent->changed(m_backend->isChangedConfig()); } void TouchpadConfigLibinput::defaults() { // in case of critical init error in backend, don't try if (m_initError) { return; } if (!m_backend->getDefaultConfig()) { m_errorMessage->setMessageType(KMessageWidget::Error); m_errorMessage->setText(i18n("Error while loading default values. Failed to set some options to their default values.")); m_errorMessage->animatedShow(); } QMetaObject::invokeMethod(m_view->rootObject(), "syncValuesFromBackend"); emit m_parent->changed(m_backend->isChangedConfig()); } void TouchpadConfigLibinput::onChange() { if (!m_backend->touchpadCount()) { return; } hideErrorMessage(); emit m_parent->changed(m_backend->isChangedConfig()); } void TouchpadConfigLibinput::onTouchpadAdded(bool success) { QQuickItem *rootObj = m_view->rootObject(); if (!success) { m_errorMessage->setMessageType(KMessageWidget::Error); m_errorMessage->setText(i18n("Error while adding newly connected device. Please reconnect it and restart this configuration module.")); } int activeIndex; if (m_backend->touchpadCount() == 1) { // if no touchpad was connected previously, show the new device and hide the no-device-message activeIndex = 0; hideErrorMessage(); } else { activeIndex = QQmlProperty::read(rootObj, "deviceIndex").toInt(); } m_view->rootContext()->setContextProperty("deviceModel", QVariant::fromValue(m_backend->getDevices())); QMetaObject::invokeMethod(rootObj, "resetModel", Q_ARG(QVariant, activeIndex)); QMetaObject::invokeMethod(rootObj, "syncValuesFromBackend"); } void TouchpadConfigLibinput::onTouchpadRemoved(int index) { QQuickItem *rootObj = m_view->rootObject(); int activeIndex = QQmlProperty::read(rootObj, "deviceIndex").toInt(); if (activeIndex == index) { m_errorMessage->setMessageType(KMessageWidget::Information); if (m_backend->touchpadCount()) { m_errorMessage->setText(i18n("Touchpad disconnected. Closed its setting dialog.")); } else { m_errorMessage->setText(i18n("Touchpad disconnected. No other touchpads found.")); } m_errorMessage->animatedShow(); activeIndex = 0; } else { if (index < activeIndex) { activeIndex--; } } m_view->rootContext()->setContextProperty("deviceModel", QVariant::fromValue(m_backend->getDevices())); QMetaObject::invokeMethod(m_view->rootObject(), "resetModel", Q_ARG(QVariant, activeIndex)); QMetaObject::invokeMethod(rootObj, "syncValuesFromBackend"); emit m_parent->changed(m_backend->isChangedConfig()); } void TouchpadConfigLibinput::hideErrorMessage() { if (m_errorMessage->isVisible()) { m_errorMessage->animatedHide(); } } diff --git a/kcms/touchpad/src/kcm/libinput/touchpadconfiglibinput.h b/kcms/touchpad/src/kcm/libinput/touchpadconfiglibinput.h index 298023aab..0af061fa1 100644 --- a/kcms/touchpad/src/kcm/libinput/touchpadconfiglibinput.h +++ b/kcms/touchpad/src/kcm/libinput/touchpadconfiglibinput.h @@ -1,61 +1,62 @@ /* * Copyright 2017 Roman Gilg * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef TOUCHPADCONFIGLIBINPUT_H #define TOUCHPADCONFIGLIBINPUT_H #include "../touchpadconfigplugin.h" class TouchpadBackend; class QHideEvent; class QQuickWidget; class KMessageWidget; class TouchpadConfigLibinput : public TouchpadConfigPlugin { Q_OBJECT public: explicit TouchpadConfigLibinput(TouchpadConfigContainer *parent, + TouchpadBackend *backend, const QVariantList &args = QVariantList()); virtual ~TouchpadConfigLibinput() {} void load() override; void save() override; void defaults() override; QSize sizeHint() const override; QSize minimumSizeHint() const override; void hideEvent(QHideEvent *) override {} private Q_SLOTS: void onChange(); void onTouchpadAdded(bool success); void onTouchpadRemoved(int index); private: void hideErrorMessage(); QQuickWidget *m_view; KMessageWidget *m_errorMessage; bool m_initError; }; #endif // TOUCHPADCONFIGLIBINPUT_H diff --git a/kcms/touchpad/src/kcm/touchpadconfigcontainer.cpp b/kcms/touchpad/src/kcm/touchpadconfigcontainer.cpp index 8dceca70b..85fd4d6c5 100644 --- a/kcms/touchpad/src/kcm/touchpadconfigcontainer.cpp +++ b/kcms/touchpad/src/kcm/touchpadconfigcontainer.cpp @@ -1,79 +1,86 @@ /* * Copyright 2017 Roman Gilg * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "touchpadconfigcontainer.h" #include "touchpadconfigplugin.h" #include "kcm/libinput/touchpadconfiglibinput.h" #include "kcm/xlib/touchpadconfigxlib.h" +#include "touchpadbackend.h" #include extern "C" { Q_DECL_EXPORT void kcminit_touchpad() { if (KWindowSystem::isPlatformX11()) { TouchpadConfigXlib::kcmInit(); } } } TouchpadConfigContainer::TouchpadConfigContainer(QWidget *parent, const QVariantList &args) : KCModule(parent, args) { + TouchpadBackend *backend = TouchpadBackend::implementation(); if (KWindowSystem::isPlatformX11()) { - m_plugin = new TouchpadConfigXlib(this); + if (backend->getMode() == TouchpadInputBackendMode::XLibinput) { + m_plugin = new TouchpadConfigLibinput(this, backend); + } + else if (backend->getMode() == TouchpadInputBackendMode::XSynaptics) { + m_plugin = new TouchpadConfigXlib(this, backend); + } } else if (KWindowSystem::isPlatformWayland()) { - m_plugin = new TouchpadConfigLibinput(this); + m_plugin = new TouchpadConfigLibinput(this, backend); } } QSize TouchpadConfigContainer::minimumSizeHint() const { return m_plugin->minimumSizeHint(); } QSize TouchpadConfigContainer::sizeHint() const { return m_plugin->sizeHint(); } void TouchpadConfigContainer::resizeEvent(QResizeEvent *event) { Q_EMIT changed(false); m_plugin->resize(this->size()); } void TouchpadConfigContainer::load() { m_plugin->load(); } void TouchpadConfigContainer::save() { m_plugin->save(); } void TouchpadConfigContainer::defaults() { m_plugin->defaults(); } void TouchpadConfigContainer::hideEvent(QHideEvent *e) { m_plugin->hideEvent(e); KCModule::hideEvent(e); } diff --git a/kcms/touchpad/src/kcm/touchpadconfigplugin.cpp b/kcms/touchpad/src/kcm/touchpadconfigplugin.cpp index 05dbd069a..874567eda 100644 --- a/kcms/touchpad/src/kcm/touchpadconfigplugin.cpp +++ b/kcms/touchpad/src/kcm/touchpadconfigplugin.cpp @@ -1,26 +1,27 @@ /* * Copyright 2017 Roman Gilg * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "touchpadconfigplugin.h" #include "touchpadconfigcontainer.h" -TouchpadConfigPlugin::TouchpadConfigPlugin(QWidget *parent) +TouchpadConfigPlugin::TouchpadConfigPlugin(QWidget *parent, TouchpadBackend *backend) : QWidget(parent), - m_parent(dynamic_cast(parent)) + m_parent(dynamic_cast(parent)), + m_backend(backend) { } diff --git a/kcms/touchpad/src/kcm/touchpadconfigplugin.h b/kcms/touchpad/src/kcm/touchpadconfigplugin.h index 9f3091475..5b1be62b3 100644 --- a/kcms/touchpad/src/kcm/touchpadconfigplugin.h +++ b/kcms/touchpad/src/kcm/touchpadconfigplugin.h @@ -1,46 +1,46 @@ /* * Copyright 2017 Roman Gilg * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef TOUCHPADCONFIGPLUGIN_H #define TOUCHPADCONFIGPLUGIN_H #include class TouchpadConfigContainer; class TouchpadBackend; class TouchpadConfigPlugin : public QWidget { Q_OBJECT public: - explicit TouchpadConfigPlugin(QWidget *parent); + TouchpadConfigPlugin(QWidget *parent, TouchpadBackend *backend); virtual ~TouchpadConfigPlugin() {} virtual void load() {} virtual void save() {} virtual void defaults() {} void hideEvent(QHideEvent *) override {} protected: TouchpadConfigContainer *m_parent; TouchpadBackend *m_backend; }; #endif // TOUCHPADCONFIGPLUGIN_H diff --git a/kcms/touchpad/src/kcm/xlib/touchpadconfigxlib.cpp b/kcms/touchpad/src/kcm/xlib/touchpadconfigxlib.cpp index 1ead5be8f..e36f4a382 100644 --- a/kcms/touchpad/src/kcm/xlib/touchpadconfigxlib.cpp +++ b/kcms/touchpad/src/kcm/xlib/touchpadconfigxlib.cpp @@ -1,396 +1,394 @@ /* * Copyright (C) 2013 Alexander Mezin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "touchpadconfigxlib.h" #include #include #include #include #include #include #include #include #include #include #include "../touchpadconfigcontainer.h" #include "customslider.h" #include "sliderpair.h" #include "touchpadbackend.h" #include "plugins.h" #include "testarea.h" #include "touchpadinterface.h" #include "customconfigdialogmanager.h" #include "kded/kdedactions.h" #include "version.h" void touchpadApplySavedConfig() { TouchpadBackend *backend = TouchpadBackend::implementation(); if (!backend) { return; } TouchpadParameters config; backend->applyConfig(config.values()); } void TouchpadConfigXlib::kcmInit() { TouchpadParameters::setSystemDefaults(); touchpadApplySavedConfig(); } static void copyHelpFromBuddy(QObject *root) { QLabel *asLabel = qobject_cast(root); if (asLabel && asLabel->buddy()) { if (asLabel->toolTip().isEmpty()) { asLabel->setToolTip(asLabel->buddy()->toolTip()); } if (asLabel->statusTip().isEmpty()) { asLabel->setStatusTip(asLabel->buddy()->statusTip()); } if (asLabel->whatsThis().isEmpty()) { asLabel->setWhatsThis(asLabel->buddy()->whatsThis()); } } Q_FOREACH(QObject *child, root->children()) { copyHelpFromBuddy(child); } } template QWidget *addTab(QTabWidget *tabs, T &form) { QScrollArea *container = new QScrollArea(tabs); container->setWidgetResizable(true); container->setFrameStyle(QFrame::NoFrame); container->setAlignment(Qt::AlignHCenter | Qt::AlignTop); QWidget *widget = new QWidget(container); form.setupUi(widget); copyHelpFromBuddy(widget); widget->setContentsMargins(20, 20, 20, 20); widget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); container->setWidget(widget); tabs->addTab(container, widget->windowTitle()); return widget; } -TouchpadConfigXlib::TouchpadConfigXlib(TouchpadConfigContainer *parent, const QVariantList &args) - : TouchpadConfigPlugin(parent), +TouchpadConfigXlib::TouchpadConfigXlib(TouchpadConfigContainer *parent, TouchpadBackend* backend, const QVariantList &args) + : TouchpadConfigPlugin(parent, backend), m_configOutOfSync(false) { KAboutData* data = new KAboutData(QStringLiteral("kcm_touchpad"), i18n("Touchpad KCM"), TOUCHPAD_KCM_VERSION, i18n("System Settings module, daemon and Plasma applet for managing your touchpad"), KAboutLicense::GPL_V2, i18n("Copyright © 2013 Alexander Mezin"), i18n("This program incorporates work covered by this copyright notice:\n" "Copyright © 2002-2005,2007 Peter Osterlund"), QStringLiteral("https://projects.kde.org/projects/playground/utils/kcm-touchpad/"), QString()); data->addAuthor(i18n("Alexander Mezin"), i18n("Developer"), QStringLiteral("mezin.alexander@gmail.com")); data->addCredit(i18n("Thomas Pfeiffer"), i18nc("Credits", "Usability, testing")); data->addCredit(i18n("Alex Fiestas"), i18nc("Credits", "Helped a bit")); data->addCredit(i18n("Peter Osterlund"), i18nc("Credits", "Developer of synclient")); data->addCredit(i18n("Vadim Zaytsev"), i18nc("Credits", "Testing")); data->addCredit(i18n("Violetta Raspryagayeva"), i18nc("Credits", "Testing")); m_parent->setAboutData(data); QGridLayout *layout = new QGridLayout(this); QVBoxLayout *messageLayout = new QVBoxLayout(); layout->addLayout(messageLayout, 0, 0, 1, 2); // Messages m_errorMessage = new KMessageWidget(this); m_errorMessage->setMessageType(KMessageWidget::Error); m_errorMessage->setVisible(false); messageLayout->addWidget(m_errorMessage); m_configOutOfSyncMessage = new KMessageWidget(this); m_configOutOfSyncMessage->setMessageType(KMessageWidget::Warning); m_configOutOfSyncMessage->setText( i18n("Active settings don't match saved settings.\n" "You currently see saved settings.")); m_configOutOfSyncMessage->setVisible(false); messageLayout->addWidget(m_configOutOfSyncMessage); m_loadActiveConfiguration = new QAction(m_configOutOfSyncMessage); m_loadActiveConfiguration->setText(i18n("Show active settings")); connect(m_loadActiveConfiguration, SIGNAL(triggered()), SLOT(loadActiveConfig())); m_configOutOfSyncMessage->addAction(m_loadActiveConfiguration); layout->setColumnStretch(0, 3); layout->setColumnStretch(1, 1); // Main UI m_tabs = new QTabWidget(this); layout->addWidget(m_tabs, 1, 0, 1, 1); addTab(m_tabs, m_tapping); addTab(m_tabs, m_scrolling); addTab(m_tabs, m_pointerMotion); addTab(m_tabs, m_sensitivity); static const CustomSlider::SqrtInterpolator interpolator; m_pointerMotion.kcfg_MinSpeed->setInterpolator(&interpolator); m_pointerMotion.kcfg_MaxSpeed->setInterpolator(&interpolator); m_pointerMotion.kcfg_AccelFactor->setInterpolator(&interpolator); new SliderPair(m_pointerMotion.kcfg_MinSpeed, m_pointerMotion.kcfg_MaxSpeed, this); new SliderPair(m_sensitivity.kcfg_FingerLow, m_sensitivity.kcfg_FingerHigh, this); new SliderPair(m_pointerMotion.kcfg_PressureMotionMinZ, m_pointerMotion.kcfg_PressureMotionMaxZ, this); - m_backend = TouchpadBackend::implementation(); - KConfigDialogManager::changedMap()->insert("CustomSlider", SIGNAL(valueChanged(double))); m_manager = new CustomConfigDialogManager(this, &m_config, m_backend->supportedParameters()); connect(m_manager, SIGNAL(widgetModified()), SLOT(checkChanges()), Qt::QueuedConnection); // KDED settings m_kdedTab = addTab(m_tabs, m_kded); m_daemonConfigManager = m_parent->addConfig(&m_daemonSettings, m_kdedTab); KMessageWidget *kdedMessage = new KMessageWidget(m_kdedTab); kdedMessage->setMessageType(KMessageWidget::Information); kdedMessage->setCloseButtonVisible(false); kdedMessage->setText( i18n("These settings won't take effect in the testing area")); qobject_cast(m_kdedTab->layout())-> insertWidget(0, kdedMessage); connect(m_kded.configureNotificationsButton, SIGNAL(clicked()), SLOT(showConfigureNotificationsDialog())); m_shortcutsDialog.reset(new KShortcutsDialog(KShortcutsEditor::GlobalAction, KShortcutsEditor::LetterShortcutsDisallowed)); m_shortcutsDialog->addCollection(new TouchpadGlobalActions(true, this), i18n("Enable/Disable Touchpad")); connect(m_kded.configureShortcutsButton, SIGNAL(clicked()), m_shortcutsDialog.data(), SLOT(show())); m_mouseCombo = new KComboBox(true, m_kded.kcfg_MouseBlacklist); m_kded.kcfg_MouseBlacklist->setCustomEditor(m_mouseCombo); connect(m_backend, SIGNAL(mousesChanged()), SLOT(updateMouseList())); m_backend->watchForEvents(false); updateMouseList(); m_daemon = new OrgKdeTouchpadInterface("org.kde.kded5", "/modules/touchpad", QDBusConnection::sessionBus(), this); m_kdedTab->setEnabled(false); QDBusPendingCallWatcher *watch; watch = new QDBusPendingCallWatcher(m_daemon->workingTouchpadFound(), this); connect(watch, SIGNAL(finished(QDBusPendingCallWatcher*)), SLOT(gotReplyFromDaemon(QDBusPendingCallWatcher*))); // Testing area m_testArea = new TestArea(this); layout->addWidget(m_testArea, 1, 1); connect(m_testArea, SIGNAL(enter()), SLOT(beginTesting())); connect(m_testArea, SIGNAL(leave()), SLOT(endTesting())); connect(m_tabs, SIGNAL(currentChanged(int)), SLOT(updateTestAreaEnabled())); updateTestAreaEnabled(); } void TouchpadConfigXlib::gotReplyFromDaemon(QDBusPendingCallWatcher *watch) { QDBusPendingReply reply = *watch; if (reply.isValid() && reply.value()) { m_kdedTab->setEnabled(true); } watch->deleteLater(); } void TouchpadConfigXlib::updateMouseList() { QStringList mouses( m_backend->listMouses(m_daemonSettings.mouseBlacklist())); for (int i = 0; i < m_mouseCombo->count(); ) { if (!mouses.contains(m_mouseCombo->itemText(i))) { m_mouseCombo->removeItem(i); } else { i++; } } Q_FOREACH (const QString &i, mouses) { if (!m_mouseCombo->contains(i)) { m_mouseCombo->addItem(i); } } } QVariantHash TouchpadConfigXlib::getActiveConfig() { if (m_prevConfig) { return *m_prevConfig; } QVariantHash activeConfig; if (!m_backend->getConfig(activeConfig)) { m_errorMessage->setText(m_backend->errorString()); QMetaObject::invokeMethod(m_errorMessage, "animatedShow", Qt::QueuedConnection); } return activeConfig; } void TouchpadConfigXlib::loadActiveConfig() { m_manager->setWidgetProperties(getActiveConfig()); m_configOutOfSync = false; m_configOutOfSyncMessage->animatedHide(); } void TouchpadConfigXlib::load() { m_manager->updateWidgets(); m_parent->kcmLoad(); m_configOutOfSync = !m_manager->compareWidgetProperties(getActiveConfig()); } void TouchpadConfigXlib::save() { m_manager->updateSettings(); m_configOutOfSync = false; m_configOutOfSyncMessage->animatedHide(); bool daemonSettingsChanged = m_daemonConfigManager->hasChanged(); m_parent->kcmSave(); if (m_backend->applyConfig(m_config.values())) { m_errorMessage->animatedHide(); } else { m_errorMessage->setText(m_backend->errorString()); m_errorMessage->animatedShow(); } if (daemonSettingsChanged) { m_daemon->reloadSettings(); updateMouseList(); } } void TouchpadConfigXlib::defaults() { m_manager->updateWidgetsDefault(); m_parent->kcmDefaults(); } void TouchpadConfigXlib::checkChanges() { if (!m_backend->touchpadCount()) { return; } m_parent->unmanagedWidgetChangeState(m_manager->hasChangedFuzzy() || m_configOutOfSync); if (m_configOutOfSync) { m_configOutOfSyncMessage->animatedShow(); } else { m_configOutOfSyncMessage->animatedHide(); } } void TouchpadConfigXlib::hideEvent(QHideEvent *e) { Q_UNUSED( e ); endTesting(); } TouchpadConfigXlib::~TouchpadConfigXlib() { endTesting(); } void TouchpadConfigXlib::onChanged() { if (m_testArea->underMouse()) { beginTesting(); } } void TouchpadConfigXlib::beginTesting() { if (!m_prevConfig) { m_prevConfig.reset(new QVariantHash()); m_backend->getConfig(*m_prevConfig.data()); } m_backend->applyConfig(m_manager->currentWidgetProperties()); } void TouchpadConfigXlib::endTesting() { if (!m_prevConfig) { return; } m_backend->applyConfig(*m_prevConfig.data()); m_prevConfig.reset(); } void TouchpadConfigXlib::updateTestAreaEnabled() { bool enable = true; for (QWidget *i = m_kdedTab; i; i = i->parentWidget()) { if (i == m_tabs->currentWidget()) { enable = false; break; } } m_testArea->setEnabled(enable); m_testArea->setMouseTracking(enable); if (!enable) { endTesting(); } } void TouchpadConfigXlib::showConfigureNotificationsDialog() { KNotifyConfigWidget *widget = KNotifyConfigWidget::configure(0, m_parent->componentData().componentName()); QDialog *dialog = qobject_cast(widget->topLevelWidget()); connect(dialog, SIGNAL(finished()), dialog, SLOT(deleteLater())); } diff --git a/kcms/touchpad/src/kcm/xlib/touchpadconfigxlib.h b/kcms/touchpad/src/kcm/xlib/touchpadconfigxlib.h index e7a8863b1..bae5bfaf3 100644 --- a/kcms/touchpad/src/kcm/xlib/touchpadconfigxlib.h +++ b/kcms/touchpad/src/kcm/xlib/touchpadconfigxlib.h @@ -1,103 +1,104 @@ /* * Copyright (C) 2013 Alexander Mezin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef TOUCHPADCONFIGXLIB_H #define TOUCHPADCONFIGXLIB_H #include "../touchpadconfigplugin.h" #include #include #include "touchpadparameters.h" #include "testarea.h" #include "kdedsettings.h" #include "ui_pointermotion.h" #include "ui_tap.h" #include "ui_scroll.h" #include "ui_sensitivity.h" #include "ui_kded.h" class TouchpadConfigContainer; class TouchpadBackend; class KMessageWidget; class OrgKdeTouchpadInterface; class CustomConfigDialogManager; class QAction; class KShortcutsDialog; class QTabWidget; class KComboBox; class QDBusPendingCallWatcher; class QHideEvent; class TouchpadConfigXlib : public TouchpadConfigPlugin { Q_OBJECT public: explicit TouchpadConfigXlib(TouchpadConfigContainer *parent, + TouchpadBackend* backend, const QVariantList &args = QVariantList()); ~TouchpadConfigXlib() override; static void kcmInit(); void load() override; void save() override; void defaults() override; void hideEvent(QHideEvent *) override; private Q_SLOTS: void beginTesting(); void endTesting(); void onChanged(); void checkChanges(); void loadActiveConfig(); void updateTestAreaEnabled(); void updateMouseList(); void showConfigureNotificationsDialog(); void gotReplyFromDaemon(QDBusPendingCallWatcher *); private: QVariantHash getActiveConfig(); TouchpadParameters m_config; QScopedPointer m_prevConfig; CustomConfigDialogManager *m_manager; TouchpadDisablerSettings m_daemonSettings; KConfigDialogManager *m_daemonConfigManager; KMessageWidget *m_errorMessage, *m_configOutOfSyncMessage; TestArea *m_testArea; OrgKdeTouchpadInterface *m_daemon; QAction *m_loadActiveConfiguration; bool m_configOutOfSync; QScopedPointer m_shortcutsDialog; QWidget *m_kdedTab; QTabWidget *m_tabs; KComboBox *m_mouseCombo; Ui::PointerMotionForm m_pointerMotion; Ui::TapForm m_tapping; Ui::ScrollForm m_scrolling; Ui::SensitivityForm m_sensitivity; Ui::KdedForm m_kded; }; #endif // TOUCHPADCONFIGXLIB_H diff --git a/kcms/touchpad/src/touchpadbackend.cpp b/kcms/touchpad/src/touchpadbackend.cpp index ed822a433..419241897 100644 --- a/kcms/touchpad/src/touchpadbackend.cpp +++ b/kcms/touchpad/src/touchpadbackend.cpp @@ -1,51 +1,56 @@ /* * Copyright 2017 Roman Gilg * Copyright 2013 Alexander Mezin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "touchpadbackend.h" #include "backends/x11/xlibbackend.h" #include "backends/kwin_wayland/kwinwaylandbackend.h" #include "logging.h" #include #include #include +void TouchpadBackend::setMode(TouchpadInputBackendMode mode) +{ + m_mode = mode; +} + TouchpadBackend *TouchpadBackend::implementation() { //There are multiple possible backends if (KWindowSystem::isPlatformX11()) { static QThreadStorage > backend; if (!backend.hasLocalData()) { qCDebug(KCM_TOUCHPAD) << "Using X11 backend"; backend.setLocalData(QSharedPointer(XlibBackend::initialize())); } return backend.localData().data(); } // TODO: test on kwin_wayland specifically? What about possibly other compositors under Wayland? else if (KWindowSystem::isPlatformWayland()) { qCDebug(KCM_TOUCHPAD) << "Using KWin+Wayland backend"; return (new KWinWaylandBackend()); } else { qCCritical(KCM_TOUCHPAD) << "Not able to select appropriate backend."; return nullptr; } } diff --git a/kcms/touchpad/src/touchpadbackend.h b/kcms/touchpad/src/touchpadbackend.h index d3f8232e9..339826ac0 100644 --- a/kcms/touchpad/src/touchpadbackend.h +++ b/kcms/touchpad/src/touchpadbackend.h @@ -1,76 +1,88 @@ /* * Copyright 2017 Roman Gilg * Copyright 2013 Alexander Mezin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef TOUCHPADBACKEND_H #define TOUCHPADBACKEND_H #include #include #include +enum class TouchpadInputBackendMode { + WaylandLibinput = 0, + XLibinput = 1, + XSynaptics = 2 +}; + class Q_DECL_EXPORT TouchpadBackend : public QObject { Q_OBJECT protected: - explicit TouchpadBackend(QObject *parent) : QObject(parent) {} + explicit TouchpadBackend(QObject *parent) : QObject(parent) {} + void setMode(TouchpadInputBackendMode mode); public: static TouchpadBackend *implementation(); + TouchpadInputBackendMode getMode() const {return m_mode;} + virtual bool applyConfig(const QVariantHash &) {return false;} virtual bool getConfig(QVariantHash &) {return false;} virtual bool applyConfig() {return false;} virtual bool getConfig() {return false;} virtual bool getDefaultConfig() {return false;} virtual bool isChangedConfig() const {return false;} virtual QStringList supportedParameters() const {return QStringList();} virtual QString errorString() const {return QString();} virtual QVector getDevices() const { return QVector(); } virtual int touchpadCount() const {return 0;} enum TouchpadOffState { TouchpadEnabled, TouchpadTapAndScrollDisabled, TouchpadFullyDisabled }; virtual void setTouchpadOff(TouchpadOffState) {} virtual TouchpadOffState getTouchpadOff() {return TouchpadFullyDisabled;} virtual bool isTouchpadAvailable() {return false;} virtual bool isTouchpadEnabled() {return false;} virtual void setTouchpadEnabled(bool) {} virtual void watchForEvents(bool keyboard) {} virtual QStringList listMouses(const QStringList &blacklist) {return QStringList();} +private: + TouchpadInputBackendMode m_mode; + Q_SIGNALS: void touchpadStateChanged(); void mousesChanged(); void touchpadReset(); void keyboardActivityStarted(); void keyboardActivityFinished(); void touchpadAdded(bool success); void touchpadRemoved(int index); }; #endif // TOUCHPADBACKEND_H