diff --git a/kcms/touchpad/src/backends/kwin_wayland/kwinwaylandtouchpad.h b/kcms/touchpad/src/backends/kwin_wayland/kwinwaylandtouchpad.h index ff3eb591e..5beaae91e 100644 --- a/kcms/touchpad/src/backends/kwin_wayland/kwinwaylandtouchpad.h +++ b/kcms/touchpad/src/backends/kwin_wayland/kwinwaylandtouchpad.h @@ -1,162 +1,165 @@ /* * 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 class QDBusInterface; class KWinWaylandTouchpad : public LibinputCommon { Q_OBJECT Q_PROPERTY(qreal scrollFactor READ scrollFactor WRITE setScrollFactor NOTIFY scrollFactorChanged) public: KWinWaylandTouchpad(QString dbusName); ~KWinWaylandTouchpad() override; bool init(); bool getConfig(); bool getDefaultConfig(); bool applyConfig(); bool isChangedConfig() const; // // general QString name() const override { return m_name.val; } QString sysName() const { return m_sysName.val; } bool supportsDisableEvents() const override { return m_supportsDisableEvents.val; } void setEnabled(bool enabled) override { m_enabled.set(enabled); } bool isEnabled() const override { return m_enabled.val; } // // advanced bool supportsLeftHanded() const override { return m_supportsLeftHanded.val; } bool supportsDisableEventsOnExternalMouse() const override { return m_supportsDisableEventsOnExternalMouse.val; } bool supportsDisableWhileTyping() const override { return m_supportsDisableWhileTyping.val; } bool supportsMiddleEmulation() const override { return m_supportsMiddleEmulation.val; } // // tapping void setLmrTapButtonMap(bool set) override { m_lmrTapButtonMap.set(set); } // // acceleration speed and profile bool supportsPointerAcceleration() const override { return m_supportsPointerAcceleration.val; } bool supportsPointerAccelerationProfileFlat() const override { return m_supportsPointerAccelerationProfileFlat.val; } bool supportsPointerAccelerationProfileAdaptive() const override { return m_supportsPointerAccelerationProfileAdaptive.val; } // // scrolling bool supportsNaturalScroll() const override { return m_supportsNaturalScroll.val; } bool supportsHorizontalScrolling() const override { return false; } bool supportsScrollTwoFinger() const override { return m_supportsScrollTwoFinger.val; } bool supportsScrollEdge() const override { return m_supportsScrollEdge.val; } bool supportsScrollOnButtonDown() const override { return m_supportsScrollOnButtonDown.val; } // // Scroll Factor + bool supportsScrollFactor() const override { + return true; + } qreal scrollFactor() const { return m_scrollFactor.val; } void setScrollFactor(qreal factor) { return m_scrollFactor.set(factor); } // // Click method bool supportsClickMethodAreas() const override { return m_supportsClickMethodAreas.val; } bool supportsClickMethodClickfinger() const override { return m_supportsClickMethodClickfinger.val; } Q_SIGNALS: void scrollFactorChanged(); private: template bool valueLoader(Prop &prop); template QString valueWriter(const Prop &prop); // // general Prop m_name = Prop("name"); Prop m_sysName = Prop("sysName"); // // advanced Prop m_supportsLeftHanded = Prop("supportsLeftHanded"); Prop m_supportsDisableWhileTyping = Prop("supportsDisableWhileTyping"); Prop m_supportsMiddleEmulation = Prop("supportsMiddleEmulation"); // // acceleration speed and profile Prop m_supportsPointerAcceleration = Prop("supportsPointerAcceleration"); // // scrolling Prop m_supportsNaturalScroll = Prop("supportsNaturalScroll"); Prop m_scrollFactor = Prop("scrollFactor"); QDBusInterface *m_iface; }; #endif diff --git a/kcms/touchpad/src/backends/libinputcommon.h b/kcms/touchpad/src/backends/libinputcommon.h index c8fa48ecf..ccc772f6b 100644 --- a/kcms/touchpad/src/backends/libinputcommon.h +++ b/kcms/touchpad/src/backends/libinputcommon.h @@ -1,490 +1,493 @@ /* * 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 LIBINPUTCOMMON_H #define LIBINPUTCOMMON_H #include #include namespace { template inline T valueLoaderPart(QVariant const &reply) { Q_UNUSED(reply); return T(); } template<> inline bool valueLoaderPart(QVariant const &reply) { return reply.toBool(); } template<> inline int valueLoaderPart(QVariant const &reply) { return reply.toInt(); } template<> inline quint32 valueLoaderPart(QVariant const &reply) { return reply.toInt(); } template<> inline qreal valueLoaderPart(QVariant const &reply) { return reply.toReal(); } template<> inline QString valueLoaderPart(QVariant const &reply) { return reply.toString(); } template<> inline 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 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) + Q_PROPERTY(bool supportsScrollFactor READ supportsScrollFactor CONSTANT) public: LibinputCommon() {} virtual ~LibinputCommon() {} virtual QString name() const = 0; virtual bool supportsDisableEvents() const = 0; virtual bool isEnabled() const = 0; virtual void setEnabled(bool set) = 0; // // advanced Qt::MouseButtons supportedButtons() const { return m_supportedButtons.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); } virtual bool supportsDisableEventsOnExternalMouse() const = 0; 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); } 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); } virtual bool supportsPointerAcceleration() const = 0; qreal pointerAcceleration() const { return m_pointerAcceleration.val; } void setPointerAcceleration(qreal acceleration) { m_pointerAcceleration.set(acceleration); } 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); } 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); } // // scrolling 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); } 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); } 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); } 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); } // // 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); } 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); } + virtual bool supportsScrollFactor() const = 0; + Q_SIGNALS: void enabledChanged(); // Tapping void tapToClickChanged(); void lmrTapButtonMapChanged(); void tapAndDragChanged(); void tapDragLockChanged(); // 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(); protected: template struct Prop { 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); } // In wayland, name will be dbus name QByteArray name; bool avail; T old; T val; }; // // general Prop m_supportsDisableEvents = Prop("supportsDisableEvents"); Prop m_enabledDefault = Prop("enabledDefault"); Prop m_enabled = Prop("enabled"); // // advanced Prop m_supportedButtons = Prop("supportedButtons"); Prop m_leftHandedEnabledByDefault = Prop("leftHandedEnabledByDefault"); Prop m_leftHanded = Prop("leftHanded"); Prop m_supportsDisableEventsOnExternalMouse = Prop("supportsDisableEventsOnExternalMouse"); Prop m_disableWhileTypingEnabledByDefault = Prop("disableWhileTypingEnabledByDefault"); Prop m_disableWhileTyping = Prop("disableWhileTyping"); Prop m_middleEmulationEnabledByDefault = Prop("middleEmulationEnabledByDefault"); Prop m_middleEmulation = Prop("middleEmulation"); // // acceleration speed and profile 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_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"); }; #endif // LIBINPUTCOMMON_H diff --git a/kcms/touchpad/src/backends/x11/libinputtouchpad.h b/kcms/touchpad/src/backends/x11/libinputtouchpad.h index 39353265f..c57193acd 100644 --- a/kcms/touchpad/src/backends/x11/libinputtouchpad.h +++ b/kcms/touchpad/src/backends/x11/libinputtouchpad.h @@ -1,136 +1,140 @@ /* * 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 "xlibtouchpad.h" #include "backends/libinputcommon.h" #include #include 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; int touchpadOff() override; XcbAtom &touchpadOffAtom() override; private: template bool valueLoader(Prop &prop); template QString valueWriter(const Prop &prop); KSharedConfigPtr m_config; // // 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; } + bool supportsScrollFactor() const override { + return false; + } + // 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/kcm/libinput/touchpad.qml b/kcms/touchpad/src/kcm/libinput/touchpad.qml index ef82d0190..0b017aa44 100644 --- a/kcms/touchpad/src/kcm/libinput/touchpad.qml +++ b/kcms/touchpad/src/kcm/libinput/touchpad.qml @@ -1,807 +1,808 @@ /* * 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 enabled: touchpadCount > 0 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() middleEmulation.load() accelSpeed.load() accelProfile.load() tapToClick.load() tapAndDrag.load() tapAndDragLock.load() multiTap.load() scrollMethod.load() naturalScroll.load() scrollFactor.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 } } // Scroll Speed aka scroll Factor Layouts.GridLayout { Kirigami.FormData.label: i18nd("kcm_touchpad", "Scrolling speed:") Kirigami.FormData.buddyFor: scrollFactor + visible: touchpad.supportsScrollFactor columns: 3 Controls.Slider { id: scrollFactor from: 0 to: 14 stepSize: 1 property variant values : [ 0.1, 0.3, 0.5, 0.75, 1, // default 1.5, 2, 3, 4, 5, 7, 9, 12, 15, 20 ] Layouts.Layout.columnSpan: 3 function load() { let index = values.indexOf(touchpad.scrollFactor) if (index === -1) { index = values.indexOf(1); } value = index } onMoved: { touchpad.scrollFactor = values[value] root.changeSignal() } } //row 2 Controls.Label { text: i18nc("Slower Scroll", "Slower") } Item { Layouts.Layout.fillWidth: true } Controls.Label { text: i18nc("Faster Scroll Speed", "Faster") } } Item { Kirigami.FormData.isSection: false } Layouts.ColumnLayout { Kirigami.FormData.label: i18nd("kcm_touchpad", "Right-click:") Kirigami.FormData.buddyFor: rightClickMethodAreas id: rightClickMethod enabled: touchpad.supportsClickMethodAreas && touchpad.supportsClickMethodClickfinger 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