summaryrefslogtreecommitdiffstats
path: root/kcontrol/input/touchpad_settings.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'kcontrol/input/touchpad_settings.cpp')
-rw-r--r--kcontrol/input/touchpad_settings.cpp409
1 files changed, 409 insertions, 0 deletions
diff --git a/kcontrol/input/touchpad_settings.cpp b/kcontrol/input/touchpad_settings.cpp
new file mode 100644
index 000000000..ff15e4c21
--- /dev/null
+++ b/kcontrol/input/touchpad_settings.cpp
@@ -0,0 +1,409 @@
+/*******************************************************************************
+ tdecm_touchpad
+ A touchpad module for the TDE Control Centre
+
+ Copyright © 2024 Mavridis Philippe <mavridisf@gmail.com>
+
+ 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 3 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, see <https://www.gnu.org/licenses/>.
+
+*******************************************************************************/
+
+// TDE
+#include <tdeapplication.h>
+#include <tdeconfig.h>
+#include <kdebug.h>
+
+// DCOP
+#include <dcopref.h>
+
+// X11
+#include <X11/extensions/XInput.h>
+#include <X11/extensions/XInput2.h>
+
+// tdecm_touchpad
+#include "xiproperty.h"
+#include "touchpad_settings.h"
+
+
+/****************************** TouchpadSettings ******************************/
+TouchpadSettings::TouchpadSettings()
+: m_foundTouchpad(false)
+{
+ findTouchpad();
+}
+
+bool TouchpadSettings::findTouchpad()
+{
+ Display *display = tqt_xdisplay();
+ ATOM(isTouchpad, XI_TOUCHPAD)
+ ATOM(isLibinput, "libinput Send Events Mode Enabled")
+ ATOM(isSynaptics, "Synaptics Off")
+
+ int devicesCount;
+ XDeviceInfo *deviceList = XListInputDevices(display, &devicesCount);
+
+ for (int d = 0; d < devicesCount; ++d)
+ {
+ if (deviceList[d].type != isTouchpad) continue;
+
+ m_foundTouchpad = true;
+ m_touchpad.init(deviceList[d].id, deviceList[d].name);
+
+ int propertiesCount;
+ Atom *propertiesList = XIListProperties(display, deviceList[d].id,
+ &propertiesCount);
+ for (int p = 0; p < propertiesCount; ++p)
+ {
+ if (propertiesList[p] == isLibinput)
+ {
+ m_touchpad.driver = Touchpad::Driver::LibInput;
+ break;
+ }
+
+ else if (propertiesList[p] == isSynaptics)
+ {
+ m_touchpad.driver = Touchpad::Driver::Synaptics;
+ }
+ }
+
+ XFree(propertiesList);
+
+ if (m_foundTouchpad) break;
+ }
+
+ XFreeDeviceList(deviceList);
+
+ return m_foundTouchpad;
+}
+
+void TouchpadSettings::load(bool defaults)
+{
+ TDEConfig cfg("kcminputrc");
+ cfg.setGroup("Touchpad");
+ cfg.setReadDefaults(defaults);
+
+ enabled = cfg.readBoolEntry("Enabled", true);
+
+ // Behaviour
+ offWhileTyping = cfg.readBoolEntry("OffWhileTyping", false);
+
+ IF_DRIVER(LibInput)
+ {
+ midButtonEmulation = cfg.readBoolEntry("MidButtonEmulation", false);
+ }
+
+ // Speed
+ IF_DRIVER(LibInput)
+ {
+ accelSpeed = cfg.readNumEntry("AccelSpeed", 0);
+ accelProfile = cfg.readNumEntry("AccelProfile", 0);
+ }
+
+ // Tapping
+ tapClick = cfg.readBoolEntry("TapToClick", true);
+ tapDrag = cfg.readBoolEntry("TapAndDrag", true);
+
+ IF_DRIVER(LibInput)
+ {
+ tapDragLock = cfg.readBoolEntry("TapAndDragLock", false);
+ }
+
+ tapMapping = cfg.readNumEntry("TapMapping", 0);
+
+ // Scrolling options
+ int both = TQt::Horizontal | TQt::Vertical;
+ scrollDirections = cfg.readNumEntry("ScrollDirections", both);
+ naturalScroll = cfg.readBoolEntry("NaturalScroll", false);
+ naturalScrollDirections = cfg.readNumEntry("NaturalScrollDirections", both);
+
+ // Scrolling method
+ scrollMethod = cfg.readNumEntry("ScrollMethod", 0);
+}
+
+void TouchpadSettings::save()
+{
+ TDEConfig cfg("kcminputrc");
+ cfg.setGroup("Touchpad");
+
+ cfg.writeEntry("Enabled", enabled);
+
+ // Behaviour
+ cfg.writeEntry("OffWhileTyping", offWhileTyping);
+
+ IF_DRIVER(LibInput)
+ {
+ cfg.writeEntry("MidButtonEmulation", midButtonEmulation);
+ }
+
+ // Speed
+ cfg.writeEntry("AccelSpeed", accelSpeed);
+ cfg.writeEntry("AccelProfile", accelProfile);
+
+ // Tapping
+ cfg.writeEntry("TapToClick", tapClick);
+ cfg.writeEntry("TapAndDrag", tapDrag);
+
+ IF_DRIVER(LibInput)
+ {
+ cfg.writeEntry("TapAndDragLock", tapDragLock);
+ }
+
+ cfg.writeEntry("TapMapping", tapMapping);
+
+ // Scrolling options
+ cfg.writeEntry("ScrollDirections", scrollDirections);
+ cfg.writeEntry("NaturalScroll", naturalScroll);
+ cfg.writeEntry("NaturalScrollDirections", naturalScrollDirections);
+
+ // Scrolling method
+ cfg.writeEntry("ScrollMethod", scrollMethod);
+
+ cfg.sync();
+}
+
+bool TouchpadSettings::setTouchpadEnabled(bool on)
+{
+ enabled = on;
+
+ XIProperty *prop = nullptr;
+ int fail = 0;
+
+ IF_DRIVER(LibInput)
+ {
+ SET_PROP("Device Enabled", b)
+ {
+ prop->b[0] = enabled;
+ prop->set();
+ }
+ }
+
+ else
+ IF_DRIVER(Synaptics)
+ {
+ SET_PROP("Synaptics Off", b)
+ {
+ prop->b[0] = !enabled;
+ prop->set();
+ }
+ }
+
+ return !fail;
+}
+
+void TouchpadSettings::apply(bool force)
+{
+ kdDebug() << "applying touchpad settings" << endl;
+ if (!foundTouchpad())
+ {
+ kdWarning() << "no supported touchpads! settings not applied" << endl;
+ return;
+ }
+
+ load();
+
+ Display *display = tqt_xdisplay();
+ XIProperty *prop = nullptr;
+ int fail = 0;
+
+ if (!setTouchpadEnabled(enabled))
+ ++fail;
+
+ IF_DRIVER(LibInput)
+ {
+ kdDebug() << "driver: libinput" << endl;
+
+ SET_PROP("libinput Disable While Typing Enabled", b)
+ {
+ prop->b[0] = offWhileTyping;
+ prop->set();
+ }
+
+ SET_PROP("libinput Middle Emulation Enabled", b)
+ {
+ prop->b[0] = midButtonEmulation;
+ prop->set();
+ }
+
+ SET_PROP("libinput Accel Speed", f)
+ {
+ float val = accelSpeed;
+ val /= 100;
+ prop->f[0] = val;
+ prop->set();
+ }
+
+ SET_PROP("libinput Accel Profile Enabled", b)
+ {
+ prop->b[0] = (accelProfile == 0);
+ prop->b[1] = (accelProfile == 1);
+ prop->set();
+ }
+
+ SET_PROP("libinput Tapping Enabled", b)
+ {
+ prop->b[0] = tapClick;
+ prop->set();
+ }
+
+ SET_PROP("libinput Tapping Drag Enabled", b)
+ {
+ prop->b[0] = tapClick && tapDrag;
+ prop->set();
+ }
+
+ SET_PROP("libinput Tapping Drag Lock Enabled", b)
+ {
+ prop->b[0] = tapClick && tapDrag && tapDragLock;
+ prop->set();
+ }
+
+ SET_PROP("libinput Tapping Button Mapping Enabled", b)
+ {
+ prop->b[0] = (tapMapping == 0);
+ prop->b[1] = (tapMapping == 1);
+ prop->set();
+ }
+
+ SET_PROP("libinput Horizontal Scroll Enabled", b)
+ {
+ prop->b[0] = scrollDirections & TQt::Horizontal;
+ prop->set();
+ }
+
+ SET_PROP("libinput Natural Scrolling Enabled", b)
+ {
+ prop->b[0] = naturalScroll;
+ prop->set();
+ }
+
+ SET_PROP("libinput Scroll Method Enabled", b)
+ {
+ prop->b[0] = scrollDirections ? (scrollMethod == 0) : 0; // two-finger
+ prop->b[1] = scrollDirections ? (scrollMethod == 1) : 0; // edge
+ prop->b[2] = scrollDirections ? (scrollMethod == 2) : 0; // button
+ prop->set();
+ }
+ }
+
+ else IF_DRIVER(Synaptics)
+ {
+ kdDebug() << "driver: synaptics" << endl;
+
+ SET_PROP("Synaptics Tap Action", b)
+ {
+ prop->b[0] = 0;
+ prop->b[1] = 0;
+ prop->b[2] = 0;
+ prop->b[3] = 0;
+ prop->b[4] = tapClick ? 1 : 0; // 1 finger
+ prop->b[5] = tapClick ? (tapMapping == 0 ? 3 : 2) : 0; // 2 fingers
+ prop->b[6] = tapClick ? (tapMapping == 0 ? 2 : 3) : 0; // 3 fingers
+ prop->set();
+ }
+
+ SET_PROP("Synaptics Gestures", b)
+ {
+ prop->b[0] = tapDrag;
+ prop->set();
+ }
+
+ SET_PROP("Synaptics Edge Scrolling", b)
+ {
+ prop->b[0] = scrollMethod == 1 ? (scrollDirections & TQt::Vertical ? 1 : 0) : 0;
+ prop->b[1] = scrollMethod == 1 ? (scrollDirections & TQt::Horizontal ? 1 : 0) : 0;
+ prop->b[2] = 0; // corner
+ prop->set();
+ }
+
+ SET_PROP("Synaptics Two-Finger Scrolling", b)
+ {
+ prop->b[0] = scrollMethod == 0 ? (scrollDirections & TQt::Vertical ? 1 : 0) : 0;
+ prop->b[1] = scrollMethod == 0 ? (scrollDirections & TQt::Horizontal ? 1 : 0) : 0;
+ prop->set();
+ }
+
+ SET_PROP("Synaptics Scrolling Distance", i)
+ {
+ prop->i[0] = naturalScroll && naturalScrollDirections & TQt::Vertical ? -80 : 80;
+ prop->i[1] = naturalScroll && naturalScrollDirections & TQt::Horizontal ? -80 : 80;
+ prop->set();
+ }
+
+ // start/stop tdesyndaemon
+ DCOPRef tdesyndaemon("tdesyndaemon", "tdesyndaemon");
+ tdesyndaemon.call("stop()");
+
+ if (offWhileTyping)
+ {
+ kapp->tdeinitExec("tdesyndaemon");
+ }
+ }
+
+ if (fail > 0)
+ kdWarning() << "some options could not be applied!" << endl;
+}
+
+TQValueList<bool> TouchpadSettings::getScrollMethodsAvailability()
+{
+ TQValueList<bool> avail;
+
+ IF_DRIVER(LibInput)
+ {
+ PROP(propScrollMethodsAvail, "libinput Scroll Methods Available")
+ for (int i = 0; i < propScrollMethodsAvail.count(); ++i)
+ {
+ avail.append(propScrollMethodsAvail[i].toBool());
+ }
+ }
+
+ IF_DRIVER(Synaptics)
+ {
+ avail.append(1); // two-finger
+ avail.append(1); // edge
+ }
+
+ return avail;
+}
+
+TQValueList<bool> TouchpadSettings::getAccelProfilesAvailability()
+{
+ TQValueList<bool> avail;
+
+ IF_DRIVER(LibInput)
+ {
+ PROP(propAccelProfilesAvail, "libinput Accel Profiles Available")
+ for (int i = 0; i < propAccelProfilesAvail.count(); ++i)
+ {
+ avail.append(propAccelProfilesAvail[i].toBool());
+ }
+ }
+
+ IF_DRIVER(Synaptics) { /* TODO no support yet */ }
+
+ return avail;
+}
+
+Touchpad TouchpadSettings::touchpad()
+{
+ return m_touchpad;
+}
+
+bool TouchpadSettings::foundTouchpad()
+{
+ return m_foundTouchpad;
+}
+
+bool TouchpadSettings::supportedTouchpad()
+{
+ return m_foundTouchpad && m_touchpad.driver != Touchpad::Driver::None;
+}