diff --git a/kcms/touchpad/src/CMakeLists.txt b/kcms/touchpad/src/CMakeLists.txt index 4489443cd..5ad107213 100644 --- a/kcms/touchpad/src/CMakeLists.txt +++ b/kcms/touchpad/src/CMakeLists.txt @@ -1,97 +1,110 @@ +# KI18N Translation Domain for this library +add_definitions(-DTRANSLATION_DOMAIN=\"kcmtouchpad\") + configure_file("${CMAKE_CURRENT_SOURCE_DIR}/version.h.cmake" "${CMAKE_CURRENT_BINARY_DIR}/version.h" ) SET(SRCS plugins.cpp touchpadbackend.cpp + logging.cpp ) include(backends/x11.cmake) +include(backends/kwin_wayland.cmake) set(SRCS ${SRCS} - kcm/customslider.cpp - kcm/sliderpair.cpp - kcm/testarea.cpp - kcm/testbutton.cpp - kcm/touchpadconfig.cpp - kcm/touchpadparametersbase.cpp - kcm/customconfigdialogmanager.cpp + kcm/touchpadconfigcontainer.cpp + kcm/touchpadconfigplugin.cpp + kcm/libinput/touchpadconfiglibinput.cpp + kcm/xlib/customslider.cpp + kcm/xlib/sliderpair.cpp + kcm/xlib/testarea.cpp + kcm/xlib/testbutton.cpp + kcm/xlib/touchpadconfigxlib.cpp + kcm/xlib/touchpadparametersbase.cpp + kcm/xlib/customconfigdialogmanager.cpp ) qt5_add_dbus_interfaces(SRCS ${CMAKE_CURRENT_BINARY_DIR}/org.kde.touchpad.xml ) -kconfig_add_kcfg_files(SRCS kcm/touchpadparameters.kcfgc) +qt5_add_resources( SRCS kcm/resources.qrc ) + +kconfig_add_kcfg_files(SRCS kcm/xlib/touchpadparameters.kcfgc) ki18n_wrap_ui(SRCS - kcm/ui/pointermotion.ui - kcm/ui/tap.ui - kcm/ui/scroll.ui - kcm/ui/sensitivity.ui - kcm/ui/kded.ui - kcm/ui/testarea.ui + kcm/xlib/ui/pointermotion.ui + kcm/xlib/ui/tap.ui + kcm/xlib/ui/scroll.ui + kcm/xlib/ui/sensitivity.ui + kcm/xlib/ui/kded.ui + kcm/xlib/ui/testarea.ui ) qt5_generate_dbus_interface(kded/kded.h org.kde.touchpad.xml) SET(SRCS ${SRCS} kded/kded.cpp kded/kdedactions.cpp ) kconfig_add_kcfg_files(SRCS kded/kdedsettings.kcfgc) add_library(kded_touchpad MODULE ${SRCS} ${backend_SRCS} ) target_link_libraries(kded_touchpad ${backend_LIBS} KF5::KCMUtils KF5::Notifications KF5::CoreAddons + KF5::WindowSystem KF5::ConfigWidgets KF5::DBusAddons KF5::Completion KF5::WidgetsAddons KF5::I18n KF5::Service KF5::NotifyConfig KF5::XmlGui KF5::GlobalAccel KF5::Plasma + KF5::Declarative Qt5::X11Extras + Qt5::QuickWidgets ) add_subdirectory(applet) install(FILES kcm/kcm_touchpad.desktop DESTINATION ${SERVICES_INSTALL_DIR} ) install(FILES kded/touchpaddaemon.kcfg DESTINATION ${KCFG_INSTALL_DIR} ) install(FILES kded/kded_touchpad.desktop DESTINATION ${SERVICES_INSTALL_DIR}/kded RENAME touchpad.desktop ) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/org.kde.touchpad.xml DESTINATION ${DBUS_INTERFACES_INSTALL_DIR} ) install(FILES kded/kcm_touchpad.notifyrc DESTINATION ${KNOTIFYRC_INSTALL_DIR} ) install(TARGETS kded_touchpad DESTINATION ${PLUGIN_INSTALL_DIR} ) -install(FILES kcm/touchpad.kcfg +install(FILES kcm/xlib/touchpad.kcfg DESTINATION ${KCFG_INSTALL_DIR} ) diff --git a/kcms/touchpad/src/backends/kwin_wayland.cmake b/kcms/touchpad/src/backends/kwin_wayland.cmake new file mode 100644 index 000000000..4f8ec0365 --- /dev/null +++ b/kcms/touchpad/src/backends/kwin_wayland.cmake @@ -0,0 +1,5 @@ +SET(backend_SRCS + ${backend_SRCS} + 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 new file mode 100644 index 000000000..621064d29 --- /dev/null +++ b/kcms/touchpad/src/backends/kwin_wayland/kwinwaylandbackend.cpp @@ -0,0 +1,164 @@ +/* + * 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); + + 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/kwinwaylandbackend.h b/kcms/touchpad/src/backends/kwin_wayland/kwinwaylandbackend.h new file mode 100644 index 000000000..db19d4d07 --- /dev/null +++ b/kcms/touchpad/src/backends/kwin_wayland/kwinwaylandbackend.h @@ -0,0 +1,61 @@ +/* + * 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 KWINWAYLANDBACKEND_H +#define KWINWAYLANDBACKEND_H + +#include "touchpadbackend.h" + +#include + +class KWinWaylandTouchpad; +class QDBusInterface; + +class KWinWaylandBackend : public TouchpadBackend +{ + Q_OBJECT + + Q_PROPERTY(int touchpadCount READ touchpadCount CONSTANT) + +public: + explicit KWinWaylandBackend(QObject *parent = 0); + ~KWinWaylandBackend(); + + bool applyConfig() Q_DECL_OVERRIDE; + bool getConfig() Q_DECL_OVERRIDE; + bool getDefaultConfig() Q_DECL_OVERRIDE; + bool isChangedConfig() const Q_DECL_OVERRIDE; + const QString &errorString() const Q_DECL_OVERRIDE { return m_errorString; } + + virtual int touchpadCount() const Q_DECL_OVERRIDE { return m_devices.count(); } + virtual QVector getDevices() const Q_DECL_OVERRIDE { return m_devices; } + +private Q_SLOTS: + void onDeviceAdded(QString); + void onDeviceRemoved(QString); + +private: + void findTouchpads(); + + QDBusInterface* m_deviceManager; + QVector m_devices; + + QString m_errorString = QString(); +}; + +#endif // KWINWAYLANDBACKEND_H diff --git a/kcms/touchpad/src/backends/kwin_wayland/kwinwaylandtouchpad.cpp b/kcms/touchpad/src/backends/kwin_wayland/kwinwaylandtouchpad.cpp new file mode 100644 index 000000000..5bac8ad30 --- /dev/null +++ b/kcms/touchpad/src/backends/kwin_wayland/kwinwaylandtouchpad.cpp @@ -0,0 +1,249 @@ +/* + * 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 "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) +{ + 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); + + 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); + + 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); + + 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(); +} + +template +QString KWinWaylandTouchpad::valueWriter(const Prop &prop) +{ + if (!prop.changed()) { + return QString(); + } + m_iface->setProperty(prop.dbus, 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); + if (!reply.isValid()) { + qCCritical(KCM_TOUCHPAD) << "Error on d-bus read of" << prop.dbus; + 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 new file mode 100644 index 000000000..74c760c85 --- /dev/null +++ b/kcms/touchpad/src/backends/kwin_wayland/kwinwaylandtouchpad.h @@ -0,0 +1,458 @@ +/* + * 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 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 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) + +public: + KWinWaylandTouchpad(QString dbusName); + virtual ~KWinWaylandTouchpad(); + + bool init(); + + bool getConfig(); + bool getDefaultConfig(); + bool applyConfig(); + bool isChangedConfig() const; + + // + // 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; + } + Qt::MouseButtons supportedButtons() const { + return m_supportedButtons.val; + } + + // + // advanced + bool supportsLeftHanded() const { + 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 { + return m_supportsDisableEventsOnExternalMouse.val; + } + + bool supportsDisableWhileTyping() const { + 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 { + 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); + } + + // + // acceleration speed and profile + bool supportsPointerAcceleration() const { + return m_supportsPointerAcceleration.val; + } + qreal pointerAcceleration() const { + return m_pointerAcceleration.val; + } + void setPointerAcceleration(qreal acceleration) { + m_pointerAcceleration.set(acceleration); + } + + bool supportsPointerAccelerationProfileFlat() const { + 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 { + 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 { + return m_supportsNaturalScroll.val; + } + 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; + } + 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; + } + 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; + } + 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); + } + +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(); + +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"); + + + QDBusInterface *m_iface; +}; + +#endif diff --git a/kcms/touchpad/src/backends/x11/xlibbackend.h b/kcms/touchpad/src/backends/x11/xlibbackend.h index 60ba17920..59c12c866 100644 --- a/kcms/touchpad/src/backends/x11/xlibbackend.h +++ b/kcms/touchpad/src/backends/x11/xlibbackend.h @@ -1,96 +1,96 @@ /* * 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 #include "xcbatom.h" #include "propertyinfo.h" class XlibTouchpad; class XlibNotifications; class XRecordKeyboardMonitor; class XlibBackend : public TouchpadBackend { Q_OBJECT public: static XlibBackend* initialize(QObject *parent = 0); ~XlibBackend(); bool applyConfig(const QVariantHash &) Q_DECL_OVERRIDE; bool getConfig(QVariantHash &) Q_DECL_OVERRIDE; QStringList supportedParameters() const Q_DECL_OVERRIDE { return m_device ? m_device->supportedParameters() : QStringList(); } const QString &errorString() const { return m_errorString; } - bool hasTouchpad() const { return m_device; } + int touchpadCount() const { return m_device ? 1 : 0; } void setTouchpadOff(TouchpadOffState) Q_DECL_OVERRIDE; TouchpadOffState getTouchpadOff() Q_DECL_OVERRIDE; bool isTouchpadAvailable() Q_DECL_OVERRIDE; bool isTouchpadEnabled() Q_DECL_OVERRIDE; void setTouchpadEnabled(bool) Q_DECL_OVERRIDE; void watchForEvents(bool keyboard) Q_DECL_OVERRIDE; QStringList listMouses(const QStringList &blacklist) Q_DECL_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/kcm/libinput/components/ExclGroupBox.qml b/kcms/touchpad/src/kcm/libinput/components/ExclGroupBox.qml new file mode 100644 index 000000000..639b0d142 --- /dev/null +++ b/kcms/touchpad/src/kcm/libinput/components/ExclGroupBox.qml @@ -0,0 +1,57 @@ +/* + * 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. + */ + +import QtQuick 2.7 +import QtQuick.Controls 1.4 as Controls + +import org.kde.plasma.core 2.0 as PlasmaCore + +Column { + spacing: units.smallSpacing / 2 + property alias label: textlabel.text + property alias model: repeater.model + property alias current: exlGroupbox.current + + function itemAt(index) { + return repeater.itemAt(index) + } + + Controls.Label { + id: textlabel + } + + Controls.ExclusiveGroup { id: exlGroupbox } + Column { + leftPadding: units.smallSpacing + spacing: units.smallSpacing / 2 + + Repeater { + id: repeater + Controls.RadioButton { + text: modelData + exclusiveGroup: exlGroupbox + + property alias tooltiptext: tooltip.text + + ToolTip { + id: tooltip + } + } + } + } +} diff --git a/kcms/touchpad/src/touchpadbackend.cpp b/kcms/touchpad/src/kcm/libinput/components/ToolTip.qml similarity index 52% copy from kcms/touchpad/src/touchpadbackend.cpp copy to kcms/touchpad/src/kcm/libinput/components/ToolTip.qml index 755275c38..fd1037ad2 100644 --- a/kcms/touchpad/src/touchpadbackend.cpp +++ b/kcms/touchpad/src/kcm/libinput/components/ToolTip.qml @@ -1,41 +1,52 @@ /* - * Copyright (C) 2013 Alexander Mezin + * 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 "touchpadbackend.h" +import QtQuick 2.7 -#include -#include -#include +import QtQuick.Controls.Private 1.0 -#include "backends/x11/xlibbackend.h" +MouseArea { + anchors.fill: parent -TouchpadBackend::TouchpadBackend(QObject *parent) : QObject(parent) -{ -} + property string text: "" + + hoverEnabled: true + acceptedButtons: Qt.NoButton + + onEntered: timer.start() + onExited: timer.killTooltip() + onPositionChanged: timer.resetTooltip() + + Timer { + id: timer + interval: 1000 + onTriggered: { + Tooltip.showText(parent, Qt.point(mouseX, mouseY), text) + } + + function killTooltip() { + stop() + Tooltip.hideText() + } -TouchpadBackend *TouchpadBackend::implementation() -{ - //There will be multiple backends later - static QThreadStorage > backend; - if (!backend.hasLocalData()) { - if (QX11Info::isPlatformX11()) { - backend.setLocalData(QSharedPointer(XlibBackend::initialize())); + function resetTooltip() { + restart() + Tooltip.hideText() } } - return backend.localData().data(); } diff --git a/kcms/touchpad/src/kcm/libinput/main.qml b/kcms/touchpad/src/kcm/libinput/main.qml new file mode 100644 index 000000000..62c69210b --- /dev/null +++ b/kcms/touchpad/src/kcm/libinput/main.qml @@ -0,0 +1,543 @@ +/* + * 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. + */ + +import QtQuick 2.7 +import QtQuick.Controls 1.4 as Controls +import QtQuick.Layouts 1.3 as Layouts +import QtQuick.Controls.Styles 1.4 as Styles + +import org.kde.plasma.core 2.0 as PlasmaCore + +import "components" + +Item { + id: root + + property size sizeHint: Qt.size(maincol.width, maincol.height) + property size minimumSizeHint: Qt.size(maincol.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 + maincol.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() +// TODO: +// scrollbutton.load() + + loading = false + } + + Controls.ScrollView { + anchors.fill: parent + + Layouts.ColumnLayout { + id: maincol + enabled: touchpadCount + spacing: units.largeSpacing + + Layouts.RowLayout { + spacing: units.largeSpacing + Layouts.Layout.leftMargin: 0.1 * parent.width + Layouts.Layout.rightMargin: 0.1 * parent.width + + Controls.Label { + text: i18n("Device:") + } + + Controls.ComboBox { + 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() + } + } + } + + Row { + spacing: units.largeSpacing * 2 + + Column { + spacing: units.smallSpacing * 2 + + Column { + leftPadding: units.smallSpacing + Column { + spacing: units.smallSpacing + Controls.Label { + text: "General settings:" + } + + Column { + leftPadding: units.smallSpacing + Column { + spacing: units.smallSpacing + Controls.CheckBox { + id: deviceEnabled + text: i18n("Device enabled") + + function load() { + if (!maincol.enabled) { + checked = false + return + } + enabled = touchpad.supportsDisableEvents + checked = enabled && touchpad.enabled + } + + onCheckedChanged: { + if (enabled && !root.loading) { + touchpad.enabled = checked + root.changeSignal() + } + } + + ToolTip { + text: i18n("Accept input through this device.") + } + } + + Controls.CheckBox { + id: dwt + text: i18n("Disable while typing") + + function load() { + if (!maincol.enabled) { + checked = false + return + } + enabled = touchpad.supportsDisableWhileTyping + checked = enabled && touchpad.disableWhileTyping + } + + onCheckedChanged: { + if (enabled && !root.loading) { + touchpad.disableWhileTyping = checked + root.changeSignal() + } + } + + ToolTip { + text: i18n("Disable touchpad while typing to prevent accidental inputs.") + } + } + + Controls.CheckBox { + id: leftHanded + text: i18n("Left handed mode") + + function load() { + if (!maincol.enabled) { + checked = false + return + } + enabled = touchpad.supportsLeftHanded + checked = enabled && touchpad.leftHanded + } + + onCheckedChanged: { + if (enabled && !root.loading) { + touchpad.leftHanded = checked + root.changeSignal() + } + } + + ToolTip { + text: i18n("Swap left and right buttons.") + } + } + + Controls.CheckBox { + id: middleEmulation + text: i18n("Emulate middle button") + + function load() { + if (!maincol.enabled) { + checked = false + return + } + enabled = touchpad.supportsMiddleEmulation + checked = enabled && touchpad.middleEmulation + } + + onCheckedChanged: { + if (enabled && !root.loading) { + touchpad.middleEmulation = checked + root.changeSignal() + } + } + + ToolTip { + text: i18n("Clicking left and right button simultaneously sends middle button click.") + } + } + } + } + } + } + + Column { + leftPadding: units.smallSpacing + Column { + spacing: units.smallSpacing + Controls.Label { + text: "Acceleration:" + } + + Column { + leftPadding: units.smallSpacing + Column { + spacing: units.smallSpacing * 2 + + Row { + Controls.Slider { + id: accelSpeed + anchors.verticalCenter: parent.verticalCenter + + tickmarksEnabled: true + + minimumValue: 1 + maximumValue: 10 + stepSize: 1 + + implicitWidth: units.gridUnit * 9 + + function load() { + enabled = touchpad.supportsPointerAcceleration + if (!enabled) { + value = 0.1 + return + } + // transform libinput's pointer acceleration range [-1, 1] to slider range [1, 10] + value = 4.5 * touchpad.pointerAcceleration + 5.5 + } + + onValueChanged: { + if (touchpad != undefined && enabled && !root.loading) { + // transform slider range [1, 10] to libinput's pointer acceleration range [-1, 1] + touchpad.pointerAcceleration = Math.round( (value - 5.5) / 4.5 * 100 ) / 100 + root.changeSignal() + } + } + } + } + + ExclGroupBox { + id: accelProfile + label: i18n("Acceleration Profile:") + model: [i18n("Flat"), i18n("Adaptive")] + + function load() { + enabled = touchpad.supportsPointerAccelerationProfileAdaptive + + if (!enabled) { + itemAt(0).checked = false + itemAt(1).checked = false + return + } + + itemAt(0).tooltiptext = i18n("Cursor moves the same distance as finger.") + itemAt(1).tooltiptext = i18n("Cursor travel distance depends on movement speed of finger.") + + var toCheck = touchpad.pointerAccelerationProfileAdaptive ? 1 : 0 + itemAt(toCheck).checked = true + } + + onCurrentChanged: { + if (enabled && !root.loading) { + touchpad.pointerAccelerationProfileFlat = itemAt(0).checked + touchpad.pointerAccelerationProfileAdaptive = itemAt(1).checked + root.changeSignal() + } + } + } + } + } + } + } + + Column { + leftPadding: units.smallSpacing + Column { + spacing: units.smallSpacing + Controls.Label { + text: "Tapping:" + } + + Column { + leftPadding: units.smallSpacing + Column { + spacing: units.smallSpacing + Controls.CheckBox { + id: tapToClick + text: i18n("Tap-to-click") + + 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() + } + } + + ToolTip { + text: i18n("Single tap is left button click.") + } + } + + Controls.CheckBox { + id: tapAndDrag + text: i18n("Tap-and-drag") + + 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() + } + } + + ToolTip { + text: i18n("Sliding over touchpad directly after tap drags.") + } + } + + Controls.CheckBox { + id: tapAndDragLock + text: i18n("Tap-and-drag lock") + + function load() { + enabled = touchpad.tapFingerCount > 0 && tapAndDrag.checked + checked = enabled && touchpad.tapDragLock + } + + onCheckedChanged: { + if (enabled && !root.loading) { + touchpad.tapDragLock = checked + root.changeSignal() + } + } + + ToolTip { + text: i18n("Dragging continues after a short finger lift.") + } + } + } + } + } + } + } + + Column { + spacing: units.smallSpacing * 2 + + Column { + leftPadding: units.smallSpacing + Column { + leftPadding: units.smallSpacing + ExclGroupBox { + id: multiTap + label: i18n("Multi tapping:") + + function load() { + enabled = touchpad.supportsLmrTapButtonMap && tapToClick.checked + if (touchpad.tapFingerCount > 2) { + model = [i18n("Two-tap right, three middle"), i18n("Two-tap middle, three right")] + itemAt(0).tooltiptext = i18n("Tap with two fingers triggers a right click, tap with three fingers a middle click.") + itemAt(1).tooltiptext = i18n("Tap with two fingers triggers a middle click, tap with three fingers a right click.") + } else { + model = [i18n("Two-tap right click"), i18n("Two-tap middle click")] + itemAt(0).tooltiptext = i18n("Tap with two fingers triggers a right click.") + itemAt(1).tooltiptext = i18n("Tap with two fingers triggers a middle click.") + } + + if (!enabled) { + itemAt(0).checked = false + itemAt(1).checked = false + return + } + var toCheck = touchpad.lmrTapButtonMap ? 1 : 0 + itemAt(toCheck).checked = true + } + + onCurrentChanged: { + if (enabled && !root.loading) { + touchpad.lmrTapButtonMap = itemAt(1).checked + root.changeSignal() + } + } + } + } + } + + Column { + leftPadding: units.smallSpacing + Column { + spacing: units.smallSpacing + Controls.Label { + text: "Scrolling:" + } + + Column { + leftPadding: units.smallSpacing + Column { + spacing: units.smallSpacing + ExclGroupBox { + id: scrollmethod + label: i18n("Scroll method:") + model: [i18n("Two fingers"), i18n("Touchpad edges"), /*i18n("On Button down"),*/ i18n("No scroll")] + + property bool isNoScroll: true + + function load() { + itemAt(0).enabled = touchpad.supportsScrollTwoFinger + itemAt(1).enabled = touchpad.supportsScrollEdge + // TODO: + // itemAt(2).enabled = touchpad.supportsScrollOnButtonDown + + var toCheck = 2 + if (itemAt(0).enabled && touchpad.scrollTwoFinger) { + toCheck = 0 + } else if (itemAt(1).enabled && touchpad.scrollEdge) { + toCheck = 1 + // } else if (itemAt(2).enabled && touchpad.scrollOnButtonDown) { + // toCheck = 2 + } + itemAt(0).tooltiptext = i18n("Slide with two fingers scrolls.") + itemAt(1).tooltiptext = i18n("Slide on the touchpad edges scrolls.") + itemAt(2).tooltiptext = i18n("All forms of touchpad scrolling are deactivated.") + + isNoScroll = (toCheck == 2) + itemAt(toCheck).checked = maincol.enabled + } + + onCurrentChanged: { + if (enabled && !root.loading) { + touchpad.scrollTwoFinger = itemAt(0).checked + touchpad.scrollEdge = itemAt(1).checked + // touchpad.scrollOnButtonDown = itemAt(2).checked + root.changeSignal() + } + isNoScroll = itemAt(2).checked + loading = true + naturalScroll.load() + loading = false + } + } + + Controls.CheckBox { + id: naturalScroll + text: i18n("Invert scroll direction") + + function load() { + enabled = touchpad.supportsNaturalScroll && !scrollmethod.isNoScroll + checked = enabled && touchpad.naturalScroll + } + + onCheckedChanged: { + if (enabled && !root.loading) { + touchpad.tapDragLock = checked + root.changeSignal() + } + } + + ToolTip { + text: i18n("Touchscreen like scrolling.") + } + } + } + } + } + } + } + } + } + } +} diff --git a/kcms/touchpad/src/kcm/libinput/touchpadconfiglibinput.cpp b/kcms/touchpad/src/kcm/libinput/touchpadconfiglibinput.cpp new file mode 100644 index 000000000..f95b56408 --- /dev/null +++ b/kcms/touchpad/src/kcm/libinput/touchpadconfiglibinput.cpp @@ -0,0 +1,219 @@ +/* + * 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) +{ + 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 informations. Please restart Touchpad KCM.")); + 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 informations. Please restart Touchpad KCM 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. Not all or none options could be set to their default values.")); + m_errorMessage->animatedShow(); + } +} + +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 Touchpad KCM.")); + } + + 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 new file mode 100644 index 000000000..fde2b920f --- /dev/null +++ b/kcms/touchpad/src/kcm/libinput/touchpadconfiglibinput.h @@ -0,0 +1,61 @@ +/* + * 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, + const QVariantList &args = QVariantList()); + virtual ~TouchpadConfigLibinput() {} + + virtual void load(); + virtual void save(); + virtual void defaults(); + + QSize sizeHint() const; + QSize minimumSizeHint() const; + + virtual void hideEvent(QHideEvent *) {} + +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/resources.qrc b/kcms/touchpad/src/kcm/resources.qrc new file mode 100644 index 000000000..8f032c7ef --- /dev/null +++ b/kcms/touchpad/src/kcm/resources.qrc @@ -0,0 +1,7 @@ + + + libinput/main.qml + libinput/components/ExclGroupBox.qml + libinput/components/ToolTip.qml + + diff --git a/kcms/touchpad/src/kcm/touchpadconfigcontainer.cpp b/kcms/touchpad/src/kcm/touchpadconfigcontainer.cpp new file mode 100644 index 000000000..8dceca70b --- /dev/null +++ b/kcms/touchpad/src/kcm/touchpadconfigcontainer.cpp @@ -0,0 +1,79 @@ +/* + * 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 + +extern "C" +{ + Q_DECL_EXPORT void kcminit_touchpad() + { + if (KWindowSystem::isPlatformX11()) { + TouchpadConfigXlib::kcmInit(); + } + } +} + +TouchpadConfigContainer::TouchpadConfigContainer(QWidget *parent, const QVariantList &args) + : KCModule(parent, args) +{ + if (KWindowSystem::isPlatformX11()) { + m_plugin = new TouchpadConfigXlib(this); + } else if (KWindowSystem::isPlatformWayland()) { + m_plugin = new TouchpadConfigLibinput(this); + } +} + +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/touchpadconfigcontainer.h b/kcms/touchpad/src/kcm/touchpadconfigcontainer.h new file mode 100644 index 000000000..a09681adc --- /dev/null +++ b/kcms/touchpad/src/kcm/touchpadconfigcontainer.h @@ -0,0 +1,58 @@ +/* + * 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 TOUCHPADCONFIGCONTAINER_H +#define TOUCHPADCONFIGCONTAINER_H + +#include + +class TouchpadConfigPlugin; +class TouchpadConfigLibinput; +class TouchpadConfigXlib; + +class TouchpadConfigContainer : public KCModule +{ + Q_OBJECT + + friend TouchpadConfigXlib; + friend TouchpadConfigLibinput; + +public: + explicit TouchpadConfigContainer(QWidget *parent, + const QVariantList &args = QVariantList()); + + QSize minimumSizeHint() const; + QSize sizeHint() const; + void resizeEvent(QResizeEvent *event); + + virtual void load(); + virtual void save(); + virtual void defaults(); + + void kcmLoad() {KCModule::load();}; + void kcmSave() {KCModule::save();}; + void kcmDefaults() {KCModule::defaults();}; + +protected: + virtual void hideEvent(QHideEvent *); + +private: + TouchpadConfigPlugin* m_plugin; +}; + +#endif // TOUCHPADCONFIGCONTAINER_H diff --git a/kcms/touchpad/src/kcm/testarea.h b/kcms/touchpad/src/kcm/touchpadconfigplugin.cpp similarity index 64% copy from kcms/touchpad/src/kcm/testarea.h copy to kcms/touchpad/src/kcm/touchpadconfigplugin.cpp index 7c91c4772..05dbd069a 100644 --- a/kcms/touchpad/src/kcm/testarea.h +++ b/kcms/touchpad/src/kcm/touchpadconfigplugin.cpp @@ -1,42 +1,26 @@ /* - * Copyright (C) 2013 Alexander Mezin + * 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 TESTAREA_H -#define TESTAREA_H +#include "touchpadconfigplugin.h" +#include "touchpadconfigcontainer.h" -#include "ui_testarea.h" - -class TestArea : public QWidget +TouchpadConfigPlugin::TouchpadConfigPlugin(QWidget *parent) + : QWidget(parent), + m_parent(dynamic_cast(parent)) { - Q_OBJECT -public: - explicit TestArea(QWidget *); - -Q_SIGNALS: - void enter(); - void leave(); - -protected: - void enterEvent(QEvent *); - void leaveEvent(QEvent *); - -private: - Ui::TestArea m_ui; -}; - -#endif // TESTAREA_H +} diff --git a/kcms/touchpad/src/kcm/testbutton.h b/kcms/touchpad/src/kcm/touchpadconfigplugin.h similarity index 58% copy from kcms/touchpad/src/kcm/testbutton.h copy to kcms/touchpad/src/kcm/touchpadconfigplugin.h index bef5af161..37a5fdfbb 100644 --- a/kcms/touchpad/src/kcm/testbutton.h +++ b/kcms/touchpad/src/kcm/touchpadconfigplugin.h @@ -1,42 +1,46 @@ /* - * Copyright (C) 2013 Alexander Mezin + * 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 TESTBUTTON_H -#define TESTBUTTON_H +#ifndef TOUCHPADCONFIGPLUGIN_H +#define TOUCHPADCONFIGPLUGIN_H -#include +#include -class TestButton : public QPushButton +class TouchpadConfigContainer; +class TouchpadBackend; + +class TouchpadConfigPlugin : public QWidget { Q_OBJECT public: - explicit TestButton(QWidget *); + explicit TouchpadConfigPlugin(QWidget *parent); + virtual ~TouchpadConfigPlugin() {} -protected: - void mousePressEvent(QMouseEvent *); + virtual void load() {} + virtual void save() {} + virtual void defaults() {} -private Q_SLOTS: - void resetText(); + virtual void hideEvent(QHideEvent *) {} -private: - QString m_originalText; - bool m_firstClick; +protected: + TouchpadConfigContainer *m_parent; + TouchpadBackend *m_backend; }; -#endif // TESTBUTTON_H +#endif // TOUCHPADCONFIGPLUGIN_H diff --git a/kcms/touchpad/src/kcm/customconfigdialogmanager.cpp b/kcms/touchpad/src/kcm/xlib/customconfigdialogmanager.cpp similarity index 100% rename from kcms/touchpad/src/kcm/customconfigdialogmanager.cpp rename to kcms/touchpad/src/kcm/xlib/customconfigdialogmanager.cpp diff --git a/kcms/touchpad/src/kcm/customconfigdialogmanager.h b/kcms/touchpad/src/kcm/xlib/customconfigdialogmanager.h similarity index 100% rename from kcms/touchpad/src/kcm/customconfigdialogmanager.h rename to kcms/touchpad/src/kcm/xlib/customconfigdialogmanager.h diff --git a/kcms/touchpad/src/kcm/customslider.cpp b/kcms/touchpad/src/kcm/xlib/customslider.cpp similarity index 100% rename from kcms/touchpad/src/kcm/customslider.cpp rename to kcms/touchpad/src/kcm/xlib/customslider.cpp diff --git a/kcms/touchpad/src/kcm/customslider.h b/kcms/touchpad/src/kcm/xlib/customslider.h similarity index 100% rename from kcms/touchpad/src/kcm/customslider.h rename to kcms/touchpad/src/kcm/xlib/customslider.h diff --git a/kcms/touchpad/src/kcm/sliderpair.cpp b/kcms/touchpad/src/kcm/xlib/sliderpair.cpp similarity index 100% rename from kcms/touchpad/src/kcm/sliderpair.cpp rename to kcms/touchpad/src/kcm/xlib/sliderpair.cpp diff --git a/kcms/touchpad/src/kcm/sliderpair.h b/kcms/touchpad/src/kcm/xlib/sliderpair.h similarity index 100% rename from kcms/touchpad/src/kcm/sliderpair.h rename to kcms/touchpad/src/kcm/xlib/sliderpair.h diff --git a/kcms/touchpad/src/kcm/testarea.cpp b/kcms/touchpad/src/kcm/xlib/testarea.cpp similarity index 100% rename from kcms/touchpad/src/kcm/testarea.cpp rename to kcms/touchpad/src/kcm/xlib/testarea.cpp diff --git a/kcms/touchpad/src/kcm/testarea.h b/kcms/touchpad/src/kcm/xlib/testarea.h similarity index 100% copy from kcms/touchpad/src/kcm/testarea.h copy to kcms/touchpad/src/kcm/xlib/testarea.h diff --git a/kcms/touchpad/src/kcm/testbutton.cpp b/kcms/touchpad/src/kcm/xlib/testbutton.cpp similarity index 100% rename from kcms/touchpad/src/kcm/testbutton.cpp rename to kcms/touchpad/src/kcm/xlib/testbutton.cpp diff --git a/kcms/touchpad/src/kcm/testbutton.h b/kcms/touchpad/src/kcm/xlib/testbutton.h similarity index 100% rename from kcms/touchpad/src/kcm/testbutton.h rename to kcms/touchpad/src/kcm/xlib/testbutton.h diff --git a/kcms/touchpad/src/kcm/touchpad.kcfg b/kcms/touchpad/src/kcm/xlib/touchpad.kcfg similarity index 100% rename from kcms/touchpad/src/kcm/touchpad.kcfg rename to kcms/touchpad/src/kcm/xlib/touchpad.kcfg diff --git a/kcms/touchpad/src/kcm/touchpadconfig.cpp b/kcms/touchpad/src/kcm/xlib/touchpadconfigxlib.cpp similarity index 88% rename from kcms/touchpad/src/kcm/touchpadconfig.cpp rename to kcms/touchpad/src/kcm/xlib/touchpadconfigxlib.cpp index e487877ea..1ead5be8f 100644 --- a/kcms/touchpad/src/kcm/touchpadconfig.cpp +++ b/kcms/touchpad/src/kcm/xlib/touchpadconfigxlib.cpp @@ -1,400 +1,396 @@ /* * 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 "touchpadconfig.h" +#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()); } -extern "C" +void TouchpadConfigXlib::kcmInit() { - Q_DECL_EXPORT void kcminit_touchpad() - { - TouchpadParameters::setSystemDefaults(); - touchpadApplySavedConfig(); - } + 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; } -TouchpadConfig::TouchpadConfig(QWidget *parent, const QVariantList &args) - : KCModule(parent, args), +TouchpadConfigXlib::TouchpadConfigXlib(TouchpadConfigContainer *parent, const QVariantList &args) + : TouchpadConfigPlugin(parent), 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()); + 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")); - - setAboutData(data); + 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 = addConfig(&m_daemonSettings, m_kdedTab); + 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(this, SIGNAL(changed(bool)), SLOT(onChanged())); connect(m_tabs, SIGNAL(currentChanged(int)), SLOT(updateTestAreaEnabled())); updateTestAreaEnabled(); } -void TouchpadConfig::gotReplyFromDaemon(QDBusPendingCallWatcher *watch) +void TouchpadConfigXlib::gotReplyFromDaemon(QDBusPendingCallWatcher *watch) { QDBusPendingReply reply = *watch; if (reply.isValid() && reply.value()) { m_kdedTab->setEnabled(true); } watch->deleteLater(); } -void TouchpadConfig::updateMouseList() +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 TouchpadConfig::getActiveConfig() +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 TouchpadConfig::loadActiveConfig() +void TouchpadConfigXlib::loadActiveConfig() { m_manager->setWidgetProperties(getActiveConfig()); m_configOutOfSync = false; m_configOutOfSyncMessage->animatedHide(); } -void TouchpadConfig::load() +void TouchpadConfigXlib::load() { m_manager->updateWidgets(); - KCModule::load(); + m_parent->kcmLoad(); m_configOutOfSync = !m_manager->compareWidgetProperties(getActiveConfig()); } -void TouchpadConfig::save() +void TouchpadConfigXlib::save() { m_manager->updateSettings(); m_configOutOfSync = false; m_configOutOfSyncMessage->animatedHide(); bool daemonSettingsChanged = m_daemonConfigManager->hasChanged(); - KCModule::save(); + 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 TouchpadConfig::defaults() +void TouchpadConfigXlib::defaults() { m_manager->updateWidgetsDefault(); - KCModule::defaults(); + m_parent->kcmDefaults(); } -void TouchpadConfig::checkChanges() +void TouchpadConfigXlib::checkChanges() { - if (!m_backend->hasTouchpad()) { + if (!m_backend->touchpadCount()) { return; } - unmanagedWidgetChangeState(m_manager->hasChangedFuzzy() + m_parent->unmanagedWidgetChangeState(m_manager->hasChangedFuzzy() || m_configOutOfSync); if (m_configOutOfSync) { m_configOutOfSyncMessage->animatedShow(); } else { m_configOutOfSyncMessage->animatedHide(); } } -void TouchpadConfig::hideEvent(QHideEvent *e) +void TouchpadConfigXlib::hideEvent(QHideEvent *e) { + Q_UNUSED( e ); endTesting(); - KCModule::hideEvent(e); } -TouchpadConfig::~TouchpadConfig() +TouchpadConfigXlib::~TouchpadConfigXlib() { endTesting(); } -void TouchpadConfig::onChanged() +void TouchpadConfigXlib::onChanged() { if (m_testArea->underMouse()) { beginTesting(); } } -void TouchpadConfig::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 TouchpadConfig::endTesting() +void TouchpadConfigXlib::endTesting() { if (!m_prevConfig) { return; } m_backend->applyConfig(*m_prevConfig.data()); m_prevConfig.reset(); } -void TouchpadConfig::updateTestAreaEnabled() +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 TouchpadConfig::showConfigureNotificationsDialog() +void TouchpadConfigXlib::showConfigureNotificationsDialog() { KNotifyConfigWidget *widget = - KNotifyConfigWidget::configure(0, componentData().componentName()); + 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/touchpadconfig.h b/kcms/touchpad/src/kcm/xlib/touchpadconfigxlib.h similarity index 87% rename from kcms/touchpad/src/kcm/touchpadconfig.h rename to kcms/touchpad/src/kcm/xlib/touchpadconfigxlib.h index 32c6ea8f4..2e506d13c 100644 --- a/kcms/touchpad/src/kcm/touchpadconfig.h +++ b/kcms/touchpad/src/kcm/xlib/touchpadconfigxlib.h @@ -1,100 +1,103 @@ /* * 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 TOUCHPADCONFIG_H -#define TOUCHPADCONFIG_H +#ifndef TOUCHPADCONFIGXLIB_H +#define TOUCHPADCONFIGXLIB_H + +#include "../touchpadconfigplugin.h" -#include #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 TouchpadConfig : public KCModule +class TouchpadConfigXlib : public TouchpadConfigPlugin { Q_OBJECT public: - explicit TouchpadConfig(QWidget *parent, + explicit TouchpadConfigXlib(TouchpadConfigContainer *parent, const QVariantList &args = QVariantList()); - virtual ~TouchpadConfig(); + virtual ~TouchpadConfigXlib(); + + static void kcmInit(); virtual void load(); virtual void save(); virtual void defaults(); -protected: virtual void hideEvent(QHideEvent *); 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(); - TouchpadBackend *m_backend; 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 // TOUCHPADCONFIG_H +#endif // TOUCHPADCONFIGXLIB_H diff --git a/kcms/touchpad/src/kcm/touchpadparameters.kcfgc b/kcms/touchpad/src/kcm/xlib/touchpadparameters.kcfgc similarity index 79% rename from kcms/touchpad/src/kcm/touchpadparameters.kcfgc rename to kcms/touchpad/src/kcm/xlib/touchpadparameters.kcfgc index 52ff74c30..ab5fb5646 100644 --- a/kcms/touchpad/src/kcm/touchpadparameters.kcfgc +++ b/kcms/touchpad/src/kcm/xlib/touchpadparameters.kcfgc @@ -1,10 +1,10 @@ File=touchpad.kcfg ClassName=TouchpadParameters Mutators=true MemberVariables=private GlobalEnums=true UseEnumTypes=true Inherits=TouchpadParametersBase -IncludeFiles=\"kcm/touchpadparametersbase.h\" +IncludeFiles=\"kcm/xlib/touchpadparametersbase.h\" SetUserTexts=true TranslationSystem=kde diff --git a/kcms/touchpad/src/kcm/touchpadparametersbase.cpp b/kcms/touchpad/src/kcm/xlib/touchpadparametersbase.cpp similarity index 100% rename from kcms/touchpad/src/kcm/touchpadparametersbase.cpp rename to kcms/touchpad/src/kcm/xlib/touchpadparametersbase.cpp diff --git a/kcms/touchpad/src/kcm/touchpadparametersbase.h b/kcms/touchpad/src/kcm/xlib/touchpadparametersbase.h similarity index 100% rename from kcms/touchpad/src/kcm/touchpadparametersbase.h rename to kcms/touchpad/src/kcm/xlib/touchpadparametersbase.h diff --git a/kcms/touchpad/src/kcm/ui/kded.ui b/kcms/touchpad/src/kcm/xlib/ui/kded.ui similarity index 100% rename from kcms/touchpad/src/kcm/ui/kded.ui rename to kcms/touchpad/src/kcm/xlib/ui/kded.ui diff --git a/kcms/touchpad/src/kcm/ui/pointermotion.ui b/kcms/touchpad/src/kcm/xlib/ui/pointermotion.ui similarity index 99% rename from kcms/touchpad/src/kcm/ui/pointermotion.ui rename to kcms/touchpad/src/kcm/xlib/ui/pointermotion.ui index 79fbd37a9..33de3f353 100644 --- a/kcms/touchpad/src/kcm/ui/pointermotion.ui +++ b/kcms/touchpad/src/kcm/xlib/ui/pointermotion.ui @@ -1,288 +1,288 @@ PointerMotionForm 0 0 400 407 Pointer Motion Speed true Minimum: kcfg_MinSpeed Minimum pointer speed Qt::Horizontal QSlider::TicksBelow Maximum: kcfg_MaxSpeed Maximum pointer speed Qt::Horizontal QSlider::TicksBelow Acceleration: kcfg_AccelFactor Acceleration factor for normal pointer movements Qt::Horizontal QSlider::TicksBelow Pressure-Dependent Motion true QFormLayout::AllNonFixedFieldsGrow Minimum pressure: kcfg_PressureMotionMinZ Minimum factor: kcfg_PressureMotionMinFactor Maximum pressure: kcfg_PressureMotionMaxZ Maximum factor: kcfg_PressureMotionMaxFactor Finger pressure at which minimum pressure motion factor is applied Qt::Horizontal QSlider::TicksBelow Finger pressure at which maximum pressure motion factor is applied Qt::Horizontal QSlider::TicksBelow Lowest setting for pressure motion factor x Greatest setting for pressure motion factor x Noise Cancellation true QFormLayout::AllNonFixedFieldsGrow Vertical: kcfg_VertHysteresis Horizontal: kcfg_HorizHysteresis The minimum vertical hardware distance required to generate motion events 0 10 units The minimum horizontal hardware distance required to generate motion events 0 10 units CustomSlider QSlider -
kcm/customslider.h
+
kcm/xlib/customslider.h
kcfg_MinSpeed kcfg_MaxSpeed kcfg_AccelFactor kcfg_PressureMotionMinZ kcfg_PressureMotionMinFactor kcfg_PressureMotionMaxZ kcfg_PressureMotionMaxFactor kcfg_VertHysteresis kcfg_HorizHysteresis
diff --git a/kcms/touchpad/src/kcm/ui/scroll.ui b/kcms/touchpad/src/kcm/xlib/ui/scroll.ui similarity index 100% rename from kcms/touchpad/src/kcm/ui/scroll.ui rename to kcms/touchpad/src/kcm/xlib/ui/scroll.ui diff --git a/kcms/touchpad/src/kcm/ui/sensitivity.ui b/kcms/touchpad/src/kcm/xlib/ui/sensitivity.ui similarity index 100% rename from kcms/touchpad/src/kcm/ui/sensitivity.ui rename to kcms/touchpad/src/kcm/xlib/ui/sensitivity.ui diff --git a/kcms/touchpad/src/kcm/ui/tap.ui b/kcms/touchpad/src/kcm/xlib/ui/tap.ui similarity index 100% rename from kcms/touchpad/src/kcm/ui/tap.ui rename to kcms/touchpad/src/kcm/xlib/ui/tap.ui diff --git a/kcms/touchpad/src/kcm/ui/testarea.ui b/kcms/touchpad/src/kcm/xlib/ui/testarea.ui similarity index 97% rename from kcms/touchpad/src/kcm/ui/testarea.ui rename to kcms/touchpad/src/kcm/xlib/ui/testarea.ui index 05b7cba6f..2db0d0b4b 100644 --- a/kcms/touchpad/src/kcm/ui/testarea.ui +++ b/kcms/touchpad/src/kcm/xlib/ui/testarea.ui @@ -1,72 +1,72 @@ TestArea 0 0 200 629 true Testing area Qt::NoFocus Click me Qt::NoFocus 2000 2000 Qt::NoFocus QListView::IconMode TestButton QPushButton -
kcm/testbutton.h
+
kcm/xlib/testbutton.h
diff --git a/kcms/touchpad/src/kcm/testarea.h b/kcms/touchpad/src/logging.cpp similarity index 64% copy from kcms/touchpad/src/kcm/testarea.h copy to kcms/touchpad/src/logging.cpp index 7c91c4772..cc56603fc 100644 --- a/kcms/touchpad/src/kcm/testarea.h +++ b/kcms/touchpad/src/logging.cpp @@ -1,42 +1,20 @@ /* - * Copyright (C) 2013 Alexander Mezin + * 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 TESTAREA_H -#define TESTAREA_H - -#include "ui_testarea.h" - -class TestArea : public QWidget -{ - Q_OBJECT -public: - explicit TestArea(QWidget *); - -Q_SIGNALS: - void enter(); - void leave(); - -protected: - void enterEvent(QEvent *); - void leaveEvent(QEvent *); - -private: - Ui::TestArea m_ui; -}; - -#endif // TESTAREA_H +#include "logging.h" +Q_LOGGING_CATEGORY(KCM_TOUCHPAD, "kcm_touchpad") diff --git a/kcms/touchpad/src/kcm/testarea.h b/kcms/touchpad/src/logging.h similarity index 64% rename from kcms/touchpad/src/kcm/testarea.h rename to kcms/touchpad/src/logging.h index 7c91c4772..1ff578ba6 100644 --- a/kcms/touchpad/src/kcm/testarea.h +++ b/kcms/touchpad/src/logging.h @@ -1,42 +1,25 @@ /* - * Copyright (C) 2013 Alexander Mezin + * 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 TESTAREA_H -#define TESTAREA_H +#ifndef KCM_TOUCHPAD_LOGGING_H +#define KCM_TOUCHPAD_LOGGING_H -#include "ui_testarea.h" +#include -class TestArea : public QWidget -{ - Q_OBJECT -public: - explicit TestArea(QWidget *); - -Q_SIGNALS: - void enter(); - void leave(); - -protected: - void enterEvent(QEvent *); - void leaveEvent(QEvent *); - -private: - Ui::TestArea m_ui; -}; - -#endif // TESTAREA_H +Q_DECLARE_LOGGING_CATEGORY(KCM_TOUCHPAD) +#endif diff --git a/kcms/touchpad/src/plugins.cpp b/kcms/touchpad/src/plugins.cpp index d9004f793..5abf35735 100644 --- a/kcms/touchpad/src/plugins.cpp +++ b/kcms/touchpad/src/plugins.cpp @@ -1,32 +1,32 @@ /* * 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 "plugins.h" #include #include -#include "kcm/touchpadconfig.h" +#include "kcm/touchpadconfigcontainer.h" #include "kded/kded.h" K_PLUGIN_FACTORY(TouchpadPluginFactory, registerPlugin(); - registerPlugin("kcm");) + registerPlugin("kcm");) #include //K_EXPORT_PLUGIN(TouchpadPluginFactory(buildAboutData())) diff --git a/kcms/touchpad/src/touchpadbackend.cpp b/kcms/touchpad/src/touchpadbackend.cpp index 755275c38..ed822a433 100644 --- a/kcms/touchpad/src/touchpadbackend.cpp +++ b/kcms/touchpad/src/touchpadbackend.cpp @@ -1,41 +1,51 @@ /* - * Copyright (C) 2013 Alexander Mezin + * 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 - -#include "backends/x11/xlibbackend.h" -TouchpadBackend::TouchpadBackend(QObject *parent) : QObject(parent) -{ -} +#include TouchpadBackend *TouchpadBackend::implementation() { - //There will be multiple backends later - static QThreadStorage > backend; - if (!backend.hasLocalData()) { - if (QX11Info::isPlatformX11()) { - backend.setLocalData(QSharedPointer(XlibBackend::initialize())); - } + //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; } - return backend.localData().data(); } diff --git a/kcms/touchpad/src/touchpadbackend.h b/kcms/touchpad/src/touchpadbackend.h index 469f8eca2..28a278982 100644 --- a/kcms/touchpad/src/touchpadbackend.h +++ b/kcms/touchpad/src/touchpadbackend.h @@ -1,66 +1,76 @@ /* - * Copyright (C) 2013 Alexander Mezin + * 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 -//#include - class Q_DECL_EXPORT TouchpadBackend : public QObject { Q_OBJECT protected: - explicit TouchpadBackend(QObject *parent); + explicit TouchpadBackend(QObject *parent) : QObject(parent) {} public: - static TouchpadBackend *implementation(); - virtual bool applyConfig(const QVariantHash &) = 0; - virtual bool getConfig(QVariantHash &) = 0; - virtual QStringList supportedParameters() const = 0; - virtual const QString &errorString() const = 0; - virtual bool hasTouchpad() const = 0; + 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 const 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) = 0; - virtual TouchpadOffState getTouchpadOff() = 0; + virtual void setTouchpadOff(TouchpadOffState) {} + virtual TouchpadOffState getTouchpadOff() {return TouchpadFullyDisabled;} - virtual bool isTouchpadAvailable() = 0; - virtual bool isTouchpadEnabled() = 0; - virtual void setTouchpadEnabled(bool) = 0; + virtual bool isTouchpadAvailable() {return false;} + virtual bool isTouchpadEnabled() {return false;} + virtual void setTouchpadEnabled(bool) {} - virtual QStringList listMouses(const QStringList &blacklist) = 0; + virtual void watchForEvents(bool keyboard) {} - virtual void watchForEvents(bool keyboard) = 0; + virtual QStringList listMouses(const QStringList &blacklist) {return QStringList();} Q_SIGNALS: void touchpadStateChanged(); void mousesChanged(); void touchpadReset(); void keyboardActivityStarted(); void keyboardActivityFinished(); + + void touchpadAdded(bool success); + void touchpadRemoved(int index); }; #endif // TOUCHPADBACKEND_H