summaryrefslogtreecommitdiffstats
path: root/kcontrol
diff options
context:
space:
mode:
authorMavridis Philippe <[email protected]>2024-06-01 22:46:37 +0300
committerMavridis Philippe <[email protected]>2024-09-08 01:35:16 +0300
commit2af9d1ed2ccf0c303df4b6a845395ebd7b099c3b (patch)
treee745b4f24bf1a3a4b4ccd8244f82b6d60b744209 /kcontrol
parent63178a8866996791c95b349988a064c26a826025 (diff)
downloadtdebase-2af9d1ed2ccf0c303df4b6a845395ebd7b099c3b.tar.gz
tdebase-2af9d1ed2ccf0c303df4b6a845395ebd7b099c3b.zip
KControl: add touchpad configuration module
Supports the Libinput and Synaptics drivers, includes documentation and inpupt-touchpad icon. Signed-off-by: Mavridis Philippe <[email protected]> (cherry picked from commit 8bd4c502f65ad364261913150ce59a74c993ca1c)
Diffstat (limited to 'kcontrol')
-rw-r--r--kcontrol/input/CMakeLists.txt33
-rw-r--r--kcontrol/input/icons/CMakeLists.txt1
-rw-r--r--kcontrol/input/icons/cr128-device-input-touchpad.pngbin0 -> 8267 bytes
-rw-r--r--kcontrol/input/icons/cr16-device-input-touchpad.pngbin0 -> 719 bytes
-rw-r--r--kcontrol/input/icons/cr32-device-input-touchpad.pngbin0 -> 1696 bytes
-rw-r--r--kcontrol/input/icons/cr48-device-input-touchpad.pngbin0 -> 2824 bytes
-rw-r--r--kcontrol/input/icons/cr64-device-input-touchpad.pngbin0 -> 4044 bytes
-rw-r--r--kcontrol/input/icons/crsc-device-input-touchpad.svg485
-rw-r--r--kcontrol/input/main.cpp19
-rw-r--r--kcontrol/input/pics/CMakeLists.txt14
-rw-r--r--kcontrol/input/pics/mouse0.pngbin0 -> 1857 bytes
-rw-r--r--kcontrol/input/pics/mouse1.pngbin0 -> 1864 bytes
-rw-r--r--kcontrol/input/pics/mouse2.pngbin0 -> 1868 bytes
-rw-r--r--kcontrol/input/pics/mouse3.pngbin0 -> 1863 bytes
-rw-r--r--kcontrol/input/syndaemon.cpp201
-rw-r--r--kcontrol/input/syndaemon.h78
-rw-r--r--kcontrol/input/syndaemon_iface.h34
-rw-r--r--kcontrol/input/touchpad.cpp528
-rw-r--r--kcontrol/input/touchpad.desktop16
-rw-r--r--kcontrol/input/touchpad.h97
-rw-r--r--kcontrol/input/touchpad_settings.cpp409
-rw-r--r--kcontrol/input/touchpad_settings.h107
-rw-r--r--kcontrol/input/xiproperty.h123
23 files changed, 2125 insertions, 20 deletions
diff --git a/kcontrol/input/CMakeLists.txt b/kcontrol/input/CMakeLists.txt
index 2fc6f6ce8..81d4a2384 100644
--- a/kcontrol/input/CMakeLists.txt
+++ b/kcontrol/input/CMakeLists.txt
@@ -17,8 +17,6 @@ else( )
include_directories( core )
endif( )
-add_subdirectory( pics )
-
include_directories(
${CMAKE_CURRENT_BINARY_DIR}
${CMAKE_BINARY_DIR}
@@ -34,7 +32,7 @@ link_directories(
##### other data ################################
tde_create_translated_desktop(
- SOURCE mouse.desktop
+ SOURCE mouse.desktop touchpad.desktop
PO_DIR kcontrol-desktops
)
@@ -47,18 +45,41 @@ install( FILES
mouse_cursor_theme.upd
DESTINATION ${KCONF_UPDATE_INSTALL_DIR} )
+install(
+ DIRECTORY pics/
+ DESTINATION ${DATA_INSTALL_DIR}/kcminput/pics
+ FILES_MATCHING PATTERN *.png
+)
+
+add_subdirectory(icons)
+
##### kcm_input (module) ########################
tde_add_kpart( kcm_input AUTOMOC
SOURCES
- mouse.cpp kmousedlg.ui main.cpp logitechmouse.cpp
- logitechmouse_base.ui
- LINK themepage-static tdeio-shared ${XCURSOR_LIBRARIES} ${LIBUSB_LIBRARIES}
+ mouse.cpp kmousedlg.ui main.cpp
+ logitechmouse.cpp logitechmouse_base.ui
+ touchpad.cpp touchpad_settings.cpp
+ LINK
+ themepage-static tdeio-shared
+ ${XCURSOR_LIBRARIES} ${LIBUSB_LIBRARIES}
+ ${XINPUT_LIBRARIES}
DESTINATION ${PLUGIN_INSTALL_DIR}
)
+##### syndaemon (executable) ####################
+
+tde_add_executable( syndaemon AUTOMOC
+ SOURCES
+ syndaemon.cpp syndaemon_iface.skel
+ touchpad_settings.cpp
+ LINK tdecore-shared ${XINPUT_LIBRARIES}
+ DESTINATION ${BIN_INSTALL_DIR}
+)
+
+
##### kapplymousetheme (executable) #############
tde_add_executable( kapplymousetheme
diff --git a/kcontrol/input/icons/CMakeLists.txt b/kcontrol/input/icons/CMakeLists.txt
new file mode 100644
index 000000000..546096f2e
--- /dev/null
+++ b/kcontrol/input/icons/CMakeLists.txt
@@ -0,0 +1 @@
+tde_install_icons() \ No newline at end of file
diff --git a/kcontrol/input/icons/cr128-device-input-touchpad.png b/kcontrol/input/icons/cr128-device-input-touchpad.png
new file mode 100644
index 000000000..5b5b16553
--- /dev/null
+++ b/kcontrol/input/icons/cr128-device-input-touchpad.png
Binary files differ
diff --git a/kcontrol/input/icons/cr16-device-input-touchpad.png b/kcontrol/input/icons/cr16-device-input-touchpad.png
new file mode 100644
index 000000000..bde3c5e48
--- /dev/null
+++ b/kcontrol/input/icons/cr16-device-input-touchpad.png
Binary files differ
diff --git a/kcontrol/input/icons/cr32-device-input-touchpad.png b/kcontrol/input/icons/cr32-device-input-touchpad.png
new file mode 100644
index 000000000..6e00abaa4
--- /dev/null
+++ b/kcontrol/input/icons/cr32-device-input-touchpad.png
Binary files differ
diff --git a/kcontrol/input/icons/cr48-device-input-touchpad.png b/kcontrol/input/icons/cr48-device-input-touchpad.png
new file mode 100644
index 000000000..7c6a41c56
--- /dev/null
+++ b/kcontrol/input/icons/cr48-device-input-touchpad.png
Binary files differ
diff --git a/kcontrol/input/icons/cr64-device-input-touchpad.png b/kcontrol/input/icons/cr64-device-input-touchpad.png
new file mode 100644
index 000000000..b124147fa
--- /dev/null
+++ b/kcontrol/input/icons/cr64-device-input-touchpad.png
Binary files differ
diff --git a/kcontrol/input/icons/crsc-device-input-touchpad.svg b/kcontrol/input/icons/crsc-device-input-touchpad.svg
new file mode 100644
index 000000000..2802b4716
--- /dev/null
+++ b/kcontrol/input/icons/crsc-device-input-touchpad.svg
@@ -0,0 +1,485 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Generator: Adobe Illustrator 10.0.3, SVG Export Plug-In . SVG Version: 3.0.0 Build 77) -->
+<svg
+ xmlns:a="http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/"
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://web.resource.org/cc/"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://inkscape.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="128.338"
+ height="128"
+ viewBox="0 0 128.338 128"
+ overflow="visible"
+ enable-background="new 0 0 128.338 128"
+ xml:space="preserve"
+ id="svg1704"
+ sodipodi:version="0.32"
+ inkscape:version="0.42"
+ sodipodi:docname="touchpad.svg"
+ sodipodi:docbase="/home/kombrisn/Project/kdereview/ksynaptics"><metadata
+ id="metadata2067"><rdf:RDF><cc:Work
+ rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs
+ id="defs2065">
+
+
+
+
+ <linearGradient
+ id="XMLID_1_"
+ gradientUnits="userSpaceOnUse"
+ x1="6.1904001"
+ y1="15.246600"
+ x2="118.40850"
+ y2="84.415398"
+ gradientTransform="matrix(1.000000,0.000000,0.000000,1.043928,0.287175,3.271150)">
+ <stop
+ offset="0"
+ style="stop-color:#FFFFFF"
+ id="stop1712" />
+ <stop
+ offset="1"
+ style="stop-color:#DCDCE0"
+ id="stop1714" />
+
+
+
+ </linearGradient>
+
+ <linearGradient
+ id="XMLID_2_"
+ gradientUnits="userSpaceOnUse"
+ x1="116.84180"
+ y1="84.442398"
+ x2="16.851700"
+ y2="20.812099"
+ gradientTransform="matrix(1.000000,0.000000,0.000000,1.130136,0.287175,3.541282)">
+ <stop
+ offset="0"
+ style="stop-color:#FFFFFF"
+ id="stop1719" />
+ <stop
+ offset="1"
+ style="stop-color:#DCDCE0"
+ id="stop1721" />
+
+
+
+ </linearGradient>
+
+
+
+ <linearGradient
+ id="XMLID_3_"
+ gradientUnits="userSpaceOnUse"
+ x1="94.294899"
+ y1="35.819801"
+ x2="96.824898"
+ y2="32.868401"
+ gradientTransform="matrix(0.985500,-0.169900,0.169900,0.985500,0.979900,-9.081100)">
+ <stop
+ offset="0"
+ style="stop-color:#97FF86"
+ id="stop1728" />
+ <stop
+ offset="1"
+ style="stop-color:#94FF7F"
+ id="stop1730" />
+
+
+
+ </linearGradient>
+
+
+ <linearGradient
+ id="XMLID_4_"
+ gradientUnits="userSpaceOnUse"
+ x1="94.387703"
+ y1="35.655800"
+ x2="96.723297"
+ y2="32.931099"
+ gradientTransform="matrix(0.985500,-0.169900,0.169900,0.985500,0.979900,-9.081100)">
+ <stop
+ offset="0"
+ style="stop-color:#3DDF00"
+ id="stop1735" />
+ <stop
+ offset="1"
+ style="stop-color:#94FF7F"
+ id="stop1737" />
+
+
+
+ </linearGradient>
+
+
+
+
+ <linearGradient
+ id="XMLID_5_"
+ gradientUnits="userSpaceOnUse"
+ x1="64.881302"
+ y1="55.002399"
+ x2="64.881302"
+ y2="-3.4971001"
+ gradientTransform="matrix(1.000000,0.000000,0.000000,0.919938,0.000000,1.052981)">
+ <stop
+ offset="0"
+ style="stop-color:#9E9EAC"
+ id="stop1748" />
+ <stop
+ offset="1"
+ style="stop-color:#42425B"
+ id="stop1750" />
+
+
+
+ </linearGradient>
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <linearGradient
+ id="XMLID_18_"
+ gradientUnits="userSpaceOnUse"
+ x1="63.074699"
+ y1="54.390099"
+ x2="62.435501"
+ y2="69.409203"
+ gradientTransform="matrix(1.000000,0.000000,0.000000,1.043928,0.287175,3.271150)">
+ <stop
+ offset="0"
+ style="stop-color:#FFFFFF"
+ id="stop1887" />
+ <stop
+ offset="1"
+ style="stop-color:#FFFFFF;stop-opacity:0"
+ id="stop1889" />
+
+
+
+ </linearGradient>
+
+
+ <linearGradient
+ id="XMLID_20_"
+ gradientUnits="userSpaceOnUse"
+ x1="81.798798"
+ y1="104.17290"
+ x2="88.452904"
+ y2="114.22480">
+ <stop
+ offset="0"
+ style="stop-color:#FFFFFF"
+ id="stop1905" />
+ <stop
+ offset="1"
+ style="stop-color:#DCDCE0"
+ id="stop1907" />
+
+
+
+ </linearGradient>
+
+ <linearGradient
+ id="XMLID_21_"
+ gradientUnits="userSpaceOnUse"
+ x1="72.246101"
+ y1="100.22750"
+ x2="72.246101"
+ y2="83.708900">
+ <stop
+ offset="0"
+ style="stop-color:#9E9E9E"
+ id="stop1912" />
+ <stop
+ offset="1"
+ style="stop-color:#616161"
+ id="stop1914" />
+
+
+
+ </linearGradient>
+
+ <linearGradient
+ id="XMLID_22_"
+ gradientUnits="userSpaceOnUse"
+ x1="64.685097"
+ y1="-1.2637000"
+ x2="63.526699"
+ y2="114.37610"
+ gradientTransform="matrix(1.000000,0.000000,0.000000,1.130136,0.287175,3.541282)">
+ <stop
+ offset="0"
+ style="stop-color:#9E9EAC"
+ id="stop1919" />
+ <stop
+ offset="1"
+ style="stop-color:#42425B"
+ id="stop1921" />
+
+
+
+ </linearGradient>
+
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#XMLID_5_"
+ id="linearGradient3115"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.259073,0.000000,0.000000,0.145048,44.66793,81.50629)"
+ x1="64.881302"
+ y1="55.002399"
+ x2="64.881302"
+ y2="-3.4971001" /><linearGradient
+ inkscape:collect="always"
+ xlink:href="#XMLID_5_"
+ id="linearGradient3119"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.404572,0.000000,0.000000,0.210813,10.52265,95.00541)"
+ x1="64.881302"
+ y1="55.002399"
+ x2="64.881302"
+ y2="-3.4971001" /></defs><sodipodi:namedview
+ inkscape:window-height="725"
+ inkscape:window-width="1016"
+ inkscape:pageshadow="2"
+ inkscape:pageopacity="0.0"
+ borderopacity="1.0"
+ bordercolor="#666666"
+ pagecolor="#ffffff"
+ id="base"
+ inkscape:zoom="3.4822022"
+ inkscape:cx="72.564336"
+ inkscape:cy="56.149095"
+ inkscape:window-x="0"
+ inkscape:window-y="25"
+ inkscape:current-layer="Layer_1" />
+ <g
+ id="Layer_1">
+ <path
+ d="M 127.81817,87.825173 C 129.67917,103.42042 21.989175,123.45549 17.081175,104.65643 C 12.174175,85.855280 2.1931746,29.250351 1.0841746,23.409573 C -0.025825402,17.568794 111.16117,1.8931647 111.81917,6.5772713 C 112.47617,11.261378 125.95317,72.227839 127.81817,87.825173 z "
+ id="path1716"
+ style="fill:url(#XMLID_1_)" /><path
+ d="M 124.82002,86.233211 C 125.79544,93.680770 113.50726,100.54412 78.405838,105.83457 C 29.797840,113.16268 23.126889,113.85833 20.519977,104.00664 C 15.541863,85.199327 5.9298363,31.448190 4.7737780,25.598871 C 3.6187343,19.749533 108.25665,2.3575140 108.96323,7.0548317 C 109.66973,11.748770 122.77228,70.595456 124.82002,86.233211 z "
+ id="path1723"
+ style="fill:#d1d1d1;fill-opacity:1.0000000" /><path
+ id="path1741"
+ style="fill:#ffffff;stroke:#000000"
+ d="" /><path
+ d="M 114.73417,76.613763 C 115.45017,83.738518 30.508175,97.270824 28.334175,89.492570 C 24.565175,76.010462 15.476175,33.639362 15.033175,28.504056 C 14.823175,26.071543 100.47617,13.639662 101.93817,17.161979 C 103.71217,21.441081 113.46517,64.025506 114.73417,76.613763 z "
+ id="path1743"
+ style="fill:#d1d1d1;fill-opacity:1.0000000" /><path
+ d="M 112.96317,76.297478 C 113.74417,80.063057 31.345175,93.277308 30.371175,88.823042 C 29.397175,84.365887 17.551175,29.530614 17.551175,29.530614 L 100.67117,17.956091 C 100.67117,17.956091 112.18317,72.529006 112.96317,76.297478 z "
+ id="path1745"
+ style="fill:#f5f5f9" /><path
+ d="M 100.55617,17.107495 L 16.577175,28.749806 L 29.576175,88.599713 C 30.796175,94.163016 93.202175,82.438115 93.831175,82.314230 C 114.27417,78.285566 113.96517,76.797985 113.76017,75.814588 L 113.76017,75.812667 L 113.76017,75.814588 L 101.31617,17.000897 L 100.55617,17.107495 z M 100.02717,18.758335 C 100.32417,20.162365 112.00617,75.368026 112.11117,75.867407 C 109.52617,78.403689 71.541175,85.378704 46.885175,87.817029 C 33.642175,89.127906 31.482175,88.366349 31.138175,88.139706 C 30.836175,86.757764 20.006175,36.893566 18.523175,30.057801 C 20.184175,29.828278 98.550175,18.962890 100.02717,18.758335 z "
+ id="path1752"
+ style="fill:#000000;fill-opacity:1.0000000" /><path
+ a:adobe-blending-mode="screen"
+ d="M 105.98917,63.463016 C 105.98917,63.463016 92.840175,40.295114 63.690175,65.440217 C 43.907175,82.504270 28.755175,73.564067 27.010175,64.061187 C 23.959175,47.461682 22.534175,47.426188 21.429175,39.568540 L 100.28317,27.111343 L 105.98917,63.463016 z "
+ id="path1891"
+ style="fill:url(#XMLID_18_)" /><path
+ d="M 0.94217460,22.023236 C 0.26817460,22.617231 0.21417460,23.195568 0.28717460,23.575557 L 1.3971746,29.664791 C 4.3371746,45.885351 12.147175,88.974538 16.296175,104.87879 C 19.460175,116.99567 58.779175,113.52356 84.434175,108.23084 C 106.44117,103.69392 129.60417,95.921879 128.62517,87.721824 C 127.36017,77.145786 120.80717,45.925020 116.47017,25.266721 C 114.43717,15.589505 112.83217,7.9458614 112.62217,6.4551317 C 112.57417,6.1148110 112.36417,5.6502629 111.62217,5.3579630 C 102.72017,1.8461880 7.5561746,16.176193 0.94217460,22.023236 z M 14.952175,19.164960 C 45.879175,12.067291 107.28317,4.7493528 111.05917,6.9760519 C 111.37117,8.9083634 112.84817,15.952792 114.88117,25.630008 C 119.21117,46.260120 125.75517,77.434954 127.01017,87.929566 C 127.68117,93.555292 110.04317,101.21877 84.118175,106.56578 C 53.475175,112.88676 20.315175,113.81585 17.864175,104.43303 C 13.732175,88.593504 5.9331746,45.552337 2.9951746,29.349525 C 2.9951746,29.349525 1.9641746,23.699784 1.9101746,23.400177 C 2.1691746,23.060900 3.8551746,21.710057 14.952175,19.164960 z "
+ id="path1923"
+ style="fill:#000000;fill-opacity:1.0000000" /><g
+ id="g1925">
+ <linearGradient
+ y2="132.29289"
+ x2="35.785999"
+ y1="52.338402"
+ x1="36.586899"
+ gradientUnits="userSpaceOnUse"
+ id="XMLID_23_">
+ <stop
+ id="stop1928"
+ style="stop-color:#9E9EAC"
+ offset="0" />
+ <stop
+ id="stop1930"
+ style="stop-color:#42425B"
+ offset="1" />
+
+
+
+ </linearGradient>
+
+
+
+ <linearGradient
+ gradientTransform="matrix(0.962300,0.272200,-0.272200,0.962300,33.15460,32.60870)"
+ y2="51.923401"
+ x2="30.674400"
+ y1="38.364300"
+ x1="8.6763000"
+ gradientUnits="userSpaceOnUse"
+ id="XMLID_24_">
+ <stop
+ id="stop1937"
+ style="stop-color:#FFFFFF"
+ offset="0" />
+ <stop
+ id="stop1939"
+ style="stop-color:#DCDCE0"
+ offset="1" />
+
+
+
+ </linearGradient>
+
+
+ <linearGradient
+ gradientTransform="matrix(0.962300,0.272200,-0.272200,0.962300,33.15460,32.60870)"
+ y2="74.467400"
+ x2="18.130600"
+ y1="62.927700"
+ x1="14.248000"
+ gradientUnits="userSpaceOnUse"
+ id="XMLID_25_">
+ <stop
+ id="stop1944"
+ style="stop-color:#FFFFFF"
+ offset="0" />
+ <stop
+ id="stop1946"
+ style="stop-color:#DCDCE0"
+ offset="1" />
+
+
+
+ </linearGradient>
+
+
+
+ <linearGradient
+ gradientTransform="matrix(-0.279700,0.981500,-1.218600,-0.347400,50.63740,141.2638)"
+ y2="22.446800"
+ x2="-56.447201"
+ y1="21.737301"
+ x1="-68.426804"
+ gradientUnits="userSpaceOnUse"
+ id="XMLID_26_">
+ <stop
+ id="stop1953"
+ style="stop-color:#DCDCE0"
+ offset="0" />
+ <stop
+ id="stop1955"
+ style="stop-color:#BEBEC2"
+ offset="1" />
+
+
+
+ </linearGradient>
+
+
+ <linearGradient
+ gradientTransform="matrix(-0.274100,0.961700,-0.961700,-0.274100,24.23770,133.5791)"
+ y2="-1.5967000"
+ x2="-67.696297"
+ y1="3.6680000"
+ x1="-56.356400"
+ gradientUnits="userSpaceOnUse"
+ id="XMLID_27_">
+ <stop
+ id="stop1960"
+ style="stop-color:#0054BF"
+ offset="0" />
+ <stop
+ id="stop1962"
+ style="stop-color:#0047BF"
+ offset="1" />
+
+
+
+ </linearGradient>
+
+
+ <linearGradient
+ gradientTransform="matrix(-0.274100,0.961700,-0.816500,-0.232800,9.573000,128.7048)"
+ y2="-19.257999"
+ x2="-66.917702"
+ y1="-14.327600"
+ x1="-56.297901"
+ gradientUnits="userSpaceOnUse"
+ id="XMLID_28_">
+ <stop
+ id="stop1967"
+ style="stop-color:#0054BF"
+ offset="0" />
+ <stop
+ id="stop1969"
+ style="stop-color:#5FA0FF"
+ offset="1" />
+
+
+
+ </linearGradient>
+
+
+ <linearGradient
+ gradientTransform="matrix(-9.010000e-2,0.996000,-0.996000,-9.010000e-2,18.98860,131.3304)"
+ y2="-15.773900"
+ x2="-62.960201"
+ y1="-16.911600"
+ x1="-65.541496"
+ gradientUnits="userSpaceOnUse"
+ id="XMLID_29_">
+ <stop
+ id="stop1974"
+ style="stop-color:#BFE2FF"
+ offset="0" />
+ <stop
+ id="stop1976"
+ style="stop-color:#5FA0FF"
+ offset="1" />
+
+
+
+ </linearGradient>
+
+ </g>
+ <path
+ d="M 128.16900,118.23606 L 0.16900000,118.23606 L 0.16900000,-1.7097435e-14 L 128.16900,-1.7097435e-14 L 128.16900,118.23606 z "
+ id="path2062"
+ style="fill:none" />
+ <path
+ sodipodi:type="arc"
+ style="fill:#cccccc;fill-opacity:1.0000000"
+ id="path3123"
+ sodipodi:cx="79.111282"
+ sodipodi:cy="83.275467"
+ sodipodi:rx="34.713203"
+ sodipodi:ry="5.3321223"
+ d="M 113.82449 83.275467 A 34.713203 5.3321223 0 1 1 44.398079,83.275467 A 34.713203 5.3321223 0 1 1 113.82449 83.275467 z"
+ transform="matrix(1.267730,-0.246140,0.133394,1.354468,-35.04176,4.335442)" /><path
+ sodipodi:type="arc"
+ style="fill:#79799c;fill-opacity:1.0000000"
+ id="path3127"
+ sodipodi:cx="79.111282"
+ sodipodi:cy="83.275467"
+ sodipodi:rx="34.713203"
+ sodipodi:ry="5.3321223"
+ d="M 113.82449 83.275467 A 34.713203 5.3321223 0 1 1 44.398079,83.275467 A 34.713203 5.3321223 0 1 1 113.82449 83.275467 z"
+ transform="matrix(1.216726,-0.238824,0.191990,0.958919,-35.88576,36.67426)" /><rect
+ style="fill:#cccccc;fill-opacity:1.0000000"
+ id="rect3857"
+ width="3.3490131"
+ height="11.841051"
+ x="35.321518"
+ y="104.04992"
+ transform="matrix(0.991862,-0.127320,0.360903,0.932603,0.000000,0.000000)" /></g>
+</svg> \ No newline at end of file
diff --git a/kcontrol/input/main.cpp b/kcontrol/input/main.cpp
index d72dd0aa6..71d9ec66f 100644
--- a/kcontrol/input/main.cpp
+++ b/kcontrol/input/main.cpp
@@ -38,6 +38,8 @@
#endif
#include "mouse.h"
+#include "touchpad_settings.h"
+#include "touchpad.h"
extern "C"
{
@@ -91,6 +93,23 @@ extern "C"
delete config;
}
+
+ TDE_EXPORT TDECModule *create_touchpad(TQWidget *parent, const char *)
+ {
+ return new TouchpadConfig(parent, "kcminput");
+ }
+
+ TDE_EXPORT void init_touchpad()
+ {
+ TouchpadSettings settings;
+ settings.apply();
+ }
+
+ TDE_EXPORT bool test_touchpad()
+ {
+ TouchpadSettings settings;
+ return settings.foundTouchpad();
+ }
}
diff --git a/kcontrol/input/pics/CMakeLists.txt b/kcontrol/input/pics/CMakeLists.txt
deleted file mode 100644
index 0c9331efe..000000000
--- a/kcontrol/input/pics/CMakeLists.txt
+++ /dev/null
@@ -1,14 +0,0 @@
-#################################################
-#
-# (C) 2010-2011 Serghei Amelian
-# serghei (DOT) amelian (AT) gmail.com
-#
-# Improvements and feedback are welcome
-#
-# This file is released under GPL >= 2
-#
-#################################################
-
-install( FILES
- mouse_rh.png mouse_lh.png doubleclick_1.png doubleclick_2.png
- DESTINATION ${DATA_INSTALL_DIR}/kcminput/pics )
diff --git a/kcontrol/input/pics/mouse0.png b/kcontrol/input/pics/mouse0.png
new file mode 100644
index 000000000..02e708b04
--- /dev/null
+++ b/kcontrol/input/pics/mouse0.png
Binary files differ
diff --git a/kcontrol/input/pics/mouse1.png b/kcontrol/input/pics/mouse1.png
new file mode 100644
index 000000000..f3aeea106
--- /dev/null
+++ b/kcontrol/input/pics/mouse1.png
Binary files differ
diff --git a/kcontrol/input/pics/mouse2.png b/kcontrol/input/pics/mouse2.png
new file mode 100644
index 000000000..40c34fe59
--- /dev/null
+++ b/kcontrol/input/pics/mouse2.png
Binary files differ
diff --git a/kcontrol/input/pics/mouse3.png b/kcontrol/input/pics/mouse3.png
new file mode 100644
index 000000000..74e5c1423
--- /dev/null
+++ b/kcontrol/input/pics/mouse3.png
Binary files differ
diff --git a/kcontrol/input/syndaemon.cpp b/kcontrol/input/syndaemon.cpp
new file mode 100644
index 000000000..53d8346ca
--- /dev/null
+++ b/kcontrol/input/syndaemon.cpp
@@ -0,0 +1,201 @@
+/*******************************************************************************
+ syndaemon - daemon for the Synaptics touchpad driver which disables touchpad
+ on keyboard input
+
+ Copyright © 2004 Nadeem Hasan <[email protected]>
+ Stefan Kombrink <[email protected]>
+ 2024 Mavridis Philippe <[email protected]>
+
+ 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/>.
+
+*******************************************************************************/
+
+// TQt
+#include <tqdatetime.h>
+#include <tqtimer.h>
+
+// TDE
+#include <ksimpleconfig.h>
+#include <tdecmdlineargs.h>
+#include <kuniqueapplication.h>
+#include <tdeaboutdata.h>
+#include <tdelocale.h>
+#include <kdebug.h>
+
+// DCOP
+#include <dcopclient.h>
+
+// tdecm_touchpad
+#include "touchpad_settings.h"
+
+// SynDaemon
+#include "syndaemon.h"
+#include "syndaemon.moc"
+
+const unsigned int SynDaemon::TIME_OUT = 150;
+const unsigned int SynDaemon::POLL_INTERVAL = 100;
+const unsigned int SynDaemon::KEYMAP_SIZE = 32;
+
+unsigned char* SynDaemon::m_keyboard_mask;
+
+SynDaemon::SynDaemon() : DCOPObject("syndaemon"), TQObject()
+{
+ m_typing = false;
+ m_time = new TQTime();
+ d_settings = new TouchpadSettings;
+
+ m_keyboard_mask = new unsigned char[ KEYMAP_SIZE ];
+
+ // open a connection to the X server
+ m_display = XOpenDisplay(NULL);
+
+ if (!m_display) kdError() << "Can't open display!" << endl;
+
+ // setup keymap
+ XModifierKeymap *modifiers;
+
+ for (unsigned int i = 0; i < KEYMAP_SIZE; ++i)
+ m_keyboard_mask[i] = 0xFF;
+
+ modifiers = XGetModifierMapping(m_display);
+ for (int i = 0; i < 8 * modifiers->max_keypermod; ++i)
+ {
+ KeyCode kc = modifiers->modifiermap[i];
+ if (kc != 0) clearBit(m_keyboard_mask, kc);
+ }
+
+ XFreeModifiermap(modifiers);
+
+ m_poll = new TQTimer(this);
+ connect(m_poll, TQ_SIGNAL(timeout()), this, TQ_SLOT(poll()));
+ m_poll->start(POLL_INTERVAL);
+}
+
+SynDaemon::~SynDaemon()
+{
+ setTouchpadOn(true);
+ m_poll->stop();
+ delete m_keyboard_mask;
+}
+
+void SynDaemon::stop()
+{
+ kapp->quit();
+}
+
+void SynDaemon::poll()
+{
+ // do nothing if the user has explicitly disabled the touchpad in the settings
+ if (!touchpadEnabled()) return;
+
+ if (hasKeyboardActivity())
+ {
+ m_time->start();
+
+ if (!m_typing)
+ {
+ setTouchpadOn(false);
+ }
+ }
+
+ else
+ {
+ if (m_typing && (m_time->elapsed() > TIME_OUT))
+ {
+ setTouchpadOn(true);
+ }
+ }
+}
+
+bool SynDaemon::touchpadEnabled()
+{
+ // We can't read from our own TouchpadSettings
+ // as it contains the currently applied value
+ // so we revert to this
+ KSimpleConfig cfg("kcminputrc");
+ cfg.setGroup("Touchpad");
+ return cfg.readBoolEntry("Enabled", true);
+}
+
+void SynDaemon::setTouchpadOn(bool on)
+{
+ m_typing = !on;
+ if (!d_settings->setTouchpadEnabled(on))
+ {
+ kdWarning() << "unable to turn off touchpad!" << endl;
+ }
+}
+
+void SynDaemon::clearBit(unsigned char *ptr, int bit)
+{
+ int byteNum = bit / 8;
+ int bitNum = bit % 8;
+ ptr[byteNum] &= ~(1 << bitNum);
+}
+
+bool SynDaemon::hasKeyboardActivity()
+{
+ static unsigned char oldKeyState[KEYMAP_SIZE];
+ unsigned char keyState[KEYMAP_SIZE];
+
+ bool result = false;
+
+ XQueryKeymap(m_display, (char*)keyState);
+
+ // find pressed keys
+ for (unsigned int i = 0; i < KEYMAP_SIZE; ++i)
+ {
+ if ((keyState[i] & ~oldKeyState[i]) & m_keyboard_mask[i])
+ {
+ result = true;
+ break;
+ }
+ }
+
+ // ignore any modifiers
+ for (unsigned int i = 0; i < KEYMAP_SIZE; ++i)
+ {
+ if (keyState[i] & ~m_keyboard_mask[i])
+ {
+ result = false;
+ break;
+ }
+ }
+
+ // back up key states...
+ for (unsigned int i = 0; i < KEYMAP_SIZE; ++i)
+ {
+ oldKeyState[i] = keyState[i];
+ }
+
+ return result;
+}
+
+extern "C" TDE_EXPORT int main(int argc, char *argv[])
+{
+ TDEAboutData aboutData( "syndaemon", I18N_NOOP("Synaptics helper daemon"),
+ "0.1", I18N_NOOP("Synaptics helper daemon"), TDEAboutData::License_GPL_V2,
+ "© 2024 Mavridis Philippe" );
+
+ aboutData.addAuthor("Nadeem Hasan", I18N_NOOP("Author"), "[email protected]");
+ aboutData.addAuthor("Mavridis Philippe", I18N_NOOP("Author"), "[email protected]");
+
+ TDECmdLineArgs::init(argc, argv, &aboutData);
+
+ TDEApplication app;
+ app.disableSessionManagement();
+ app.dcopClient()->registerAs("syndaemon", false);
+
+ SynDaemon syndaemon;
+ return app.exec();
+} \ No newline at end of file
diff --git a/kcontrol/input/syndaemon.h b/kcontrol/input/syndaemon.h
new file mode 100644
index 000000000..0556345eb
--- /dev/null
+++ b/kcontrol/input/syndaemon.h
@@ -0,0 +1,78 @@
+/*******************************************************************************
+ syndaemon - daemon for the Synaptics touchpad driver which disables touchpad
+ on keyboard input
+
+ Copyright © 2004 Nadeem Hasan <[email protected]>
+ Stefan Kombrink <[email protected]>
+ 2024 Mavridis Philippe <[email protected]>
+
+ 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/>.
+
+*******************************************************************************/
+
+#ifndef __SYNDAEMON_H__
+#define __SYNDAEMON_H__
+
+// TQt
+#include <tqobject.h>
+#include <tqthread.h>
+
+// DCOP
+#include <dcopobject.h>
+
+// X11
+#include <X11/Xlib.h>
+#undef Bool /* fix problems in --enable-final mode */
+#undef None /* fix problems in --enable-final mode */
+
+// Syndaemon
+#include "syndaemon_iface.h"
+
+
+class TQTimer;
+
+class SynDaemon : public TQObject, public virtual SynDaemonIface
+{
+ TQ_OBJECT
+
+ public:
+ SynDaemon();
+ ~SynDaemon();
+
+ bool touchpadEnabled();
+
+ public slots:
+ void poll();
+ void setTouchpadOn(bool on);
+ virtual void stop();
+
+ protected:
+ void clearBit(unsigned char* ptr, int bit);
+ bool hasKeyboardActivity();
+
+ private:
+ TouchpadSettings *d_settings;
+
+ TQTimer *m_poll;
+ TQTime *m_time;
+ Display *m_display;
+ bool m_typing;
+
+ static const unsigned int POLL_INTERVAL;
+ static const unsigned int TIME_OUT;
+ static const unsigned int KEYMAP_SIZE;
+ static unsigned char *m_keyboard_mask;
+};
+
+#endif
+
diff --git a/kcontrol/input/syndaemon_iface.h b/kcontrol/input/syndaemon_iface.h
new file mode 100644
index 000000000..0f3d33929
--- /dev/null
+++ b/kcontrol/input/syndaemon_iface.h
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ syndaemon - daemon for the Synaptics touchpad driver which disables touchpad
+ on keyboard input
+
+ Copyright © 2024 Mavridis Philippe <[email protected]>
+
+ 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/>.
+
+*******************************************************************************/
+
+#ifndef __SYNDAEMON_IFACE_H__
+#define __SYNDAEMON_IFACE_H__
+
+// DCOP
+#include <dcopobject.h>
+
+class SynDaemonIface : virtual public DCOPObject
+{
+ K_DCOP
+ k_dcop:
+ virtual void stop() = 0;
+};
+
+#endif \ No newline at end of file
diff --git a/kcontrol/input/touchpad.cpp b/kcontrol/input/touchpad.cpp
new file mode 100644
index 000000000..d18e3b698
--- /dev/null
+++ b/kcontrol/input/touchpad.cpp
@@ -0,0 +1,528 @@
+/*******************************************************************************
+ tdecm_touchpad
+ A touchpad module for the TDE Control Centre
+
+ Copyright © 2024 Mavridis Philippe <[email protected]>
+
+ 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/>.
+
+*******************************************************************************/
+
+// TQt
+#include <tqwhatsthis.h>
+#include <tqtooltip.h>
+#include <tqtabwidget.h>
+#include <tqradiobutton.h>
+#include <tqbuttongroup.h>
+#include <tqcombobox.h>
+#include <tqcheckbox.h>
+#include <tqslider.h>
+#include <tqlayout.h>
+#include <tqlabel.h>
+
+// TDE
+#include <tdeglobal.h>
+#include <kiconloader.h>
+#include <tdeaboutdata.h>
+#include <kdialog.h>
+#include <kdebug.h>
+
+// TouchpadConfig
+#include "touchpad_settings.h"
+#include "touchpad.h"
+#include "touchpad.moc"
+
+
+/******************************* TouchpadConfig *******************************/
+TouchpadConfig::TouchpadConfig(TQWidget *parent, const char *name)
+: TDECModule(parent, name),
+ m_error(nullptr)
+{
+ TDEGlobal::iconLoader()->addAppDir("kcminput");
+
+ d_settings = new TouchpadSettings;
+ d_settings->apply();
+
+ if (!d_settings->supportedTouchpad())
+ {
+ TQString error_str;
+
+ if (!d_settings->foundTouchpad())
+ {
+ error_str = i18n(
+ "<qt><h1>Touchpad not found</h1>"
+ "Please check your system installation.</qt>"
+ );
+ }
+
+ else IF_DRIVER(None)
+ {
+ error_str = i18n(
+ "<qt><h1>Unsupported driver</h1>"
+ "<p>This module only supports the following drivers:"
+ "<p>Libinput, Synaptics</qt>"
+ );
+ }
+
+ else error_str = i18n("<qt><h1>Unknown error</h1></qt>");
+
+ m_error = new TQLabel(error_str, this);
+ m_error->setAlignment(TQt::AlignCenter);
+ new TQVBoxLayout(this);
+ layout()->add(m_error);
+ return;
+ }
+
+ initWidgets();
+ load();
+
+ kdDebug() << "managed touchpad: " << d_settings->touchpad().name
+ << " (xid = " << d_settings->touchpad().id << ")" << endl;
+
+ TDEAboutData* about = new TDEAboutData(
+ "tdecm_touchpad",
+ I18N_NOOP("Touchpad"),
+ 0, 0,
+ TDEAboutData::License_GPL,
+ I18N_NOOP("(c) 2024 Mavridis Philippe")
+ );
+ about->addAuthor("Mavridis Philippe", 0, 0);
+ setAboutData(about);
+}
+
+TouchpadConfig::~TouchpadConfig()
+{
+ DEL(m_error)
+ DEL(d_settings);
+}
+
+void TouchpadConfig::initWidgets()
+{
+ // Create containers
+ m_container = new TQTabWidget(this);
+
+ TQFrame *touchpadWidget = new TQFrame(this);
+ touchpadWidget->setMargin(0);
+ new TQVBoxLayout(touchpadWidget);
+
+ // Enable option
+ TQFrame *enableCheckBox = new TQFrame(touchpadWidget);
+ enableCheckBox->setSizePolicy(TQSizePolicy::Maximum, TQSizePolicy::Fixed);
+
+ m_enabled = new TQCheckBox(i18n("Enable touchpad"), enableCheckBox);
+ TQWhatsThis::add(m_enabled, i18n(
+ "This option determines whether the touchpad is enabled or disabled"
+ ));
+
+ // Compute margin for idented checkboxes based on checkbox height
+ int lmargin = m_enabled->height() / 2;
+
+ // Align the Enable checkbox with the other options below
+ new TQHBoxLayout(enableCheckBox);
+ enableCheckBox->layout()->addItem(new TQSpacerItem(lmargin, lmargin, TQSizePolicy::Fixed));
+ enableCheckBox->layout()->add(m_enabled);
+
+ // Settings frame
+ TQFrame *settingsFrame = new TQFrame(touchpadWidget);
+ TQGridLayout *grid = new TQGridLayout(settingsFrame, 3, 2, KDialog::spacingHint());
+
+ connect(m_enabled, TQ_SIGNAL(toggled(bool)), this, TQ_SLOT(changed()));
+ connect(m_enabled, TQ_SIGNAL(toggled(bool)), settingsFrame, TQ_SLOT(setEnabled(bool)));
+
+ // Behaviour
+ m_behaviour = new TQGroupBox(2, TQt::Vertical, i18n("Behaviour"), settingsFrame);
+
+ m_offWhileTyping = new TQCheckBox(i18n("Disable touchpad while typing"), m_behaviour);
+ TQWhatsThis::add(m_offWhileTyping, i18n(
+ "If this option is checked, the touchpad is disabled while you are typing, so as "
+ "to prevent accidental cursor movement and clicks."
+ ));
+ connect(m_offWhileTyping, TQ_SIGNAL(toggled(bool)), this, TQ_SLOT(changed()));
+
+ m_mbEmulation = new TQCheckBox(i18n("Middle button emulation"), m_behaviour);
+ TQWhatsThis::add(m_mbEmulation, i18n(
+ "If this option is enabled, a simultaneous left and right button click is "
+ "automatically transformed into a middle button click."
+ ));
+ IF_DRIVER(LibInput)
+ {
+ connect(m_mbEmulation, TQ_SIGNAL(toggled(bool)), this, TQ_SLOT(changed()));
+ }
+ else
+ {
+ DISABLE_UNSUPPORTED_OPTION(m_mbEmulation);
+ }
+
+ // Speed
+ m_speed = new TQGroupBox(4, TQt::Vertical, i18n("Speed"), settingsFrame);
+
+ TQLabel *accelLabel = new TQLabel(i18n("Acceleration:"), m_speed);
+
+ m_accel = new TQSlider(-100, 100, 5, 0, TQt::Horizontal, m_speed);
+
+ TQWidget *accelSliderMarkBox = new TQWidget(m_speed);
+ new TQHBoxLayout(accelSliderMarkBox);
+ accelSliderMarkBox->layout()->setAutoAdd(true);
+
+ TQLabel *l;
+ l = new TQLabel(i18n("Slower"), accelSliderMarkBox);
+ l->setAlignment(TQt::AlignLeft);
+ l = new TQLabel(i18n("Normal"), accelSliderMarkBox);
+ l->setAlignment(TQt::AlignHCenter);
+ l = new TQLabel(i18n("Faster"), accelSliderMarkBox);
+ l->setAlignment(TQt::AlignRight);
+ l = nullptr;
+
+ m_accelAdaptive = new TQCheckBox(i18n("Use adaptive profile"), m_speed);
+
+ IF_DRIVER(LibInput)
+ {
+ connect(m_accel, TQ_SIGNAL(valueChanged(int)), this, TQ_SLOT(changed()));
+ connect(m_accelAdaptive, TQ_SIGNAL(toggled(bool)), this, TQ_SLOT(changed()));
+
+ // check available profiles
+ TQValueList<bool> accelProfilesAvail = d_settings->getAccelProfilesAvailability();
+ if (!accelProfilesAvail.count() || accelProfilesAvail[0] == 0 || accelProfilesAvail[1] == 0)
+ {
+ m_accelAdaptive->setEnabled(false);
+ }
+ }
+ else
+ {
+ DISABLE_UNSUPPORTED_OPTION(m_speed)
+ }
+
+ // Tapping
+ m_tapping = new TQGroupBox(5, TQt::Vertical, i18n("Tapping"), settingsFrame);
+
+ m_tapClick = new TQCheckBox(i18n("Tap to click"), m_tapping);
+ TQWhatsThis::add(m_tapClick, i18n(
+ "If this option is checked, a tap on the touchpad is interpreted as a button click."
+ ));
+ connect(m_tapClick, TQ_SIGNAL(toggled(bool)), this, TQ_SLOT(changed()));
+ connect(m_tapClick, TQ_SIGNAL(toggled(bool)), this, TQ_SLOT(updateWidgetStates()));
+
+ m_tapDrag = new TQCheckBox(i18n("Tap-and-drag"), m_tapping);
+ TQWhatsThis::add(m_tapDrag, i18n(
+ "Tap-and-drag is a tap which is immediately followed by a finger down and that finger "
+ "being held down emulates a button press. Moving the finger around can thus drag the "
+ "selected item on the screen."
+ ));
+ connect(m_tapDrag, TQ_SIGNAL(toggled(bool)), this, TQ_SLOT(changed()));
+ connect(m_tapDrag, TQ_SIGNAL(toggled(bool)), this, TQ_SLOT(updateWidgetStates()));
+
+ m_tapDragLock = new TQCheckBox(i18n("Tap-and-drag lock"), m_tapping);
+ TQWhatsThis::add(m_tapDragLock, i18n(
+ "When enabled, lifting a finger while dragging will not immediately stop dragging."
+ ));
+
+ IF_DRIVER(LibInput)
+ {
+ connect(m_tapDragLock, TQ_SIGNAL(toggled(bool)), this, TQ_SLOT(changed()));
+ }
+ else
+ {
+ DISABLE_UNSUPPORTED_OPTION(m_tapDragLock);
+ }
+
+ TQLabel *tapMappingLabel = new TQLabel(i18n("Two-finger tap:"), m_tapping);
+ m_tapMapping = new TQComboBox(m_tapping); // "lrm" and "lmr"
+ m_tapMapping->setSizePolicy(TQSizePolicy::Maximum, TQSizePolicy::Fixed);
+ m_tapMapping->insertItem(
+ TDEGlobal::iconLoader()->loadIcon("mouse3", TDEIcon::Small),
+ i18n("Right click (three-finger tap for middle click)"),
+ 0);
+ m_tapMapping->insertItem(
+ TDEGlobal::iconLoader()->loadIcon("mouse2", TDEIcon::Small),
+ i18n("Middle click (three-finger tap for right click)"),
+ 1);
+ connect(m_tapMapping, TQ_SIGNAL(activated(const TQString&)), this, TQ_SLOT(changed()));
+
+ // Scrolling options
+ m_scrolling = new TQGroupBox(4, TQt::Vertical, i18n("Scrolling options"), settingsFrame);
+
+ m_verScroll = new TQCheckBox(i18n("Vertical scrolling"), m_scrolling);
+ TQWhatsThis::add(m_verScroll, i18n(
+ "This option enables/disables the vertical scrolling gesture on the touchpad. "
+ "(The actual gesture depends on the selected scroll method.) "
+ "Unless the used driver is Synaptics, disabling vertical scrolling also disables "
+ "horizontal scrolling."
+ ));
+ connect(m_verScroll, TQ_SIGNAL(toggled(bool)), this, TQ_SLOT(changed()));
+ connect(m_verScroll, TQ_SIGNAL(toggled(bool)), this, TQ_SLOT(updateWidgetStates()));
+
+ m_horScroll = new TQCheckBox(i18n("Horizontal scrolling"), m_scrolling);
+ TQWhatsThis::add(m_horScroll, i18n(
+ "This option enables/disables the horizontal scrolling gesture on the touchpad. "
+ "(The actual gesture depends on the selected scroll method.)"
+ ));
+ connect(m_horScroll, TQ_SIGNAL(toggled(bool)), this, TQ_SLOT(changed()));
+ connect(m_horScroll, TQ_SIGNAL(toggled(bool)), this, TQ_SLOT(updateWidgetStates()));
+
+ m_naturalScroll = new TQCheckBox(i18n("Reverse scroll direction"), m_scrolling);
+ TQWhatsThis::add(m_naturalScroll, i18n(
+ "If this option is checked, the scrolling direction is reversed to resemble natural "
+ "movement of content. This feature is also called natural scrolling."
+ ));
+ connect(m_naturalScroll, TQ_SIGNAL(toggled(bool)), this, TQ_SLOT(changed()));
+
+ m_naturalScrollDirections = new TQFrame(m_scrolling);
+ TQWhatsThis::add(m_naturalScrollDirections, i18n(
+ "This option allows you to select the scrolling directions to which reversed scrolling will be applied. "
+ "It is only available if the Synaptics driver is used."
+ ));
+ TQGridLayout *nsdl = new TQGridLayout(m_naturalScrollDirections, 2, 2, KDialog::spacingHint());
+ m_horNaturalScroll = new TQCheckBox(i18n("Apply to horizontal scrolling"), m_naturalScrollDirections);
+ m_verNaturalScroll = new TQCheckBox(i18n("Apply to vertical scrolling"), m_naturalScrollDirections);
+ nsdl->addItem(new TQSpacerItem(lmargin, lmargin, TQSizePolicy::Fixed), 0, 0);
+ nsdl->addItem(new TQSpacerItem(lmargin, lmargin, TQSizePolicy::Fixed), 1, 0);
+ nsdl->addWidget(m_horNaturalScroll, 0, 1);
+ nsdl->addWidget(m_verNaturalScroll, 1, 1);
+
+ IF_DRIVER(Synaptics)
+ {
+ connect(m_horNaturalScroll, TQ_SIGNAL(toggled(bool)), TQ_SLOT(changed()));
+ connect(m_verNaturalScroll, TQ_SIGNAL(toggled(bool)), TQ_SLOT(changed()));
+ connect(m_naturalScroll, TQ_SIGNAL(toggled(bool)), TQ_SLOT(updateWidgetStates()));
+ }
+ else
+ {
+ // Not only disable, but also force checkboxes to be checked on
+ // so that the user knows that the natural scrolling option applies
+ // always to both directions
+ DISABLE_UNSUPPORTED_OPTION(m_naturalScrollDirections);
+ m_horNaturalScroll->setChecked(true);
+ m_verNaturalScroll->setChecked(true);
+ }
+
+ // Scrolling methods
+ m_scrollMethods = new TQButtonGroup(3, TQt::Vertical, i18n("Scrolling method"), settingsFrame);
+ TQWhatsThis::add(m_scrollMethods, i18n(
+ "Here you can select your preferred scrolling method. The two most common options are "
+ "two-finger scrolling and edge scrolling. Two-finger scrolling entails a movement with "
+ "two fingers vertically or horizontally upon the surface of the touchpad. Edge scrolling "
+ "on the other hand tracks movements with one finger along the right or bottom edge of "
+ "the touchpad."
+ ));
+ connect(m_scrollMethods, TQ_SIGNAL(clicked(int)), this, TQ_SLOT(changed()));
+
+ TQStringList scrollMethodLabels;
+ scrollMethodLabels << i18n("Two-finger")
+ << i18n("Edge");
+
+ IF_DRIVER(LibInput)
+ {
+ scrollMethodLabels << i18n("Button");
+ }
+
+ TQValueList<bool> scrollMethodAvail = d_settings->getScrollMethodsAvailability();
+ Q_ASSERT(scrollMethodLabels.count() == scrollMethodAvail.count());
+
+ for (int i = 0; i < scrollMethodLabels.count(); ++i)
+ {
+ TQRadioButton *rad = new TQRadioButton(scrollMethodLabels[i], m_scrollMethods);
+ rad->setEnabled(scrollMethodAvail[i]);
+ }
+
+ // Finalize layout
+ grid->addWidget(m_behaviour, 0, 0);
+ grid->addWidget(m_speed, 1, 0);
+ grid->addMultiCellWidget(m_scrolling, 0, 1, 1, 1);
+ grid->addWidget(m_scrollMethods, 2, 1);
+ grid->addWidget(m_tapping, 2, 0);
+ grid->addItem(new TQSpacerItem(10, 10));
+
+ // Synaptics deprecation warning
+ IF_DRIVER(Synaptics)
+ {
+ TQLabel *l = new TQLabel(i18n(
+ "<qt><b>Warning:</b> The Synaptics driver has been deprecated.</qt>"
+ ), settingsFrame);
+ TQWhatsThis::add(l, i18n(
+ "<qt><p><b>The Synaptics driver is no longer in active development.</b>"
+ "<p>While Libinput is the preferred choice for handling input devices, "
+ "you might still have valid reasons to use the older Synaptics driver "
+ "in its place. Please bear in mind that you will probably not receive "
+ "updates and bug fixes from its upstream.</qt>"
+ ));
+ grid->addMultiCellWidget(l, 3, 3, 0, 1);
+ }
+
+ touchpadWidget->layout()->add(enableCheckBox);
+ touchpadWidget->layout()->add(settingsFrame);
+ m_container->addTab(touchpadWidget, SmallIconSet("input-touchpad"), d_settings->touchpad().name);
+
+ new TQVBoxLayout(this, KDialog::marginHint());
+ layout()->add(m_container);
+}
+
+// We handle more complex UI cases here
+void TouchpadConfig::updateWidgetStates()
+{
+ if (!d_settings->foundTouchpad()) return;
+
+ // Scrolling related options
+ bool on;
+
+ IF_DRIVER(LibInput)
+ {
+ // To disable vertical scrolling under LibInput one has to disable scrolling entirely
+ // so we mirror this in the UI
+ on = m_verScroll->isChecked();
+ m_horScroll->setEnabled(on);
+ }
+
+ else
+ {
+ // In case we can control both horizontal and vertical scrolling separately, any UI
+ // changes should be triggered when both are disabled
+ on = m_verScroll->isChecked() || m_horScroll->isChecked();
+
+ // Only enable natural scroll directions options when not under LibInput
+ m_naturalScrollDirections->setEnabled(on && m_naturalScroll->isChecked());
+ }
+
+ m_naturalScroll->setEnabled(on);
+ m_scrollMethods->setEnabled(on);
+
+ // Tapping related options
+ m_tapDrag->setEnabled(m_tapClick->isChecked());
+
+ IF_DRIVER(LibInput)
+ {
+ m_tapDragLock->setEnabled(m_tapClick->isChecked() && m_tapDrag->isChecked());
+ }
+}
+
+void TouchpadConfig::defaults()
+{
+ load(true);
+}
+
+void TouchpadConfig::load()
+{
+ load(false);
+}
+
+void TouchpadConfig::load(bool useDefaults)
+{
+ if (!d_settings->foundTouchpad()) return;
+
+ d_settings->load();
+
+ m_enabled->setChecked(d_settings->enabled);
+
+ // Behaviour
+ m_offWhileTyping->setChecked(d_settings->offWhileTyping);
+
+ IF_DRIVER(LibInput)
+ {
+ m_mbEmulation->setChecked(d_settings->midButtonEmulation);
+ }
+
+ // Speed
+ IF_DRIVER(LibInput)
+ {
+ m_accel->setValue(d_settings->accelSpeed);
+ m_accelAdaptive->setChecked(d_settings->accelProfile == 0);
+ }
+
+ // Tapping
+ m_tapClick->setChecked(d_settings->tapClick);
+ m_tapDrag->setChecked(d_settings->tapDrag);
+
+ IF_DRIVER(LibInput)
+ {
+ m_tapDragLock->setChecked(d_settings->tapDragLock);
+ }
+
+ m_tapMapping->setCurrentItem(d_settings->tapMapping);
+
+ // Scrolling options
+ m_horScroll->setChecked(d_settings->scrollDirections & TQt::Horizontal);
+ m_verScroll->setChecked(d_settings->scrollDirections & TQt::Vertical);
+ m_naturalScroll->setChecked(d_settings->naturalScroll);
+ IF_DRIVER(Synaptics)
+ {
+ m_naturalScrollDirections->setEnabled(d_settings->naturalScroll);
+ m_horNaturalScroll->setChecked(d_settings->naturalScrollDirections & TQt::Horizontal);
+ m_verNaturalScroll->setChecked(d_settings->naturalScrollDirections & TQt::Vertical);
+ }
+
+ IF_DRIVER(LibInput)
+ {
+ m_horScroll->setEnabled(m_verScroll->isOn());
+ m_naturalScroll->setEnabled(m_verScroll->isOn());
+ m_scrollMethods->setEnabled(m_verScroll->isOn());
+ }
+
+ // Scrolling method
+ m_scrollMethods->setButton(d_settings->scrollMethod);
+}
+
+void TouchpadConfig::save()
+{
+ if (!d_settings->foundTouchpad()) return;
+
+ d_settings->enabled = m_enabled->isChecked();
+
+ // Behaviour
+ d_settings->offWhileTyping = m_offWhileTyping->isChecked();
+
+ IF_DRIVER(LibInput)
+ {
+ d_settings->midButtonEmulation = m_mbEmulation->isChecked();
+ }
+
+ // Speed
+ IF_DRIVER(LibInput)
+ {
+ d_settings->accelSpeed = m_accel->value();
+ d_settings->accelProfile = (m_accelAdaptive->isChecked() ? 0 : 1);
+ }
+
+ // Tapping
+ d_settings->tapClick = m_tapClick->isChecked();
+ d_settings->tapDrag = m_tapDrag->isChecked();
+
+ IF_DRIVER(LibInput)
+ {
+ d_settings->tapDragLock = m_tapDragLock->isChecked();
+ }
+
+ d_settings->tapMapping = m_tapMapping->currentItem();
+
+ // Scrolling options
+ int scrollDirections = 0;
+ if (m_horScroll->isChecked()) scrollDirections |= TQt::Horizontal;
+ if (m_verScroll->isChecked()) scrollDirections |= TQt::Vertical;
+ d_settings->scrollDirections = scrollDirections;
+
+ d_settings->naturalScroll = m_naturalScroll->isChecked();
+
+ int naturalScrollDirections = 0;
+ if (m_horNaturalScroll->isChecked()) naturalScrollDirections |= TQt::Horizontal;
+ if (m_verNaturalScroll->isChecked()) naturalScrollDirections |= TQt::Vertical;
+ d_settings->naturalScrollDirections = naturalScrollDirections;
+
+ // Scrolling method
+ d_settings->scrollMethod = m_scrollMethods->selectedId();
+
+ d_settings->save();
+ d_settings->apply();
+}
+
+Touchpad TouchpadConfig::touchpad()
+{
+ return d_settings->touchpad();
+}
diff --git a/kcontrol/input/touchpad.desktop b/kcontrol/input/touchpad.desktop
new file mode 100644
index 000000000..d943749c1
--- /dev/null
+++ b/kcontrol/input/touchpad.desktop
@@ -0,0 +1,16 @@
+[Desktop Entry]
+Exec=tdecmshell touchpad
+Icon=input-touchpad
+Type=Application
+X-DocPath=kcontrol/touchpad/index.html
+
+X-TDE-Library=input
+X-TDE-FactoryName=touchpad
+X-TDE-Init=touchpad
+X-TDE-ParentApp=kcontrol
+X-TDE-Test-Module=true
+
+Name=Touchpad
+Comment=Touchpad settings
+Keywords=Touchpad;Tap to click;Mouse;Mouse buttons;Input Devices;Button Mapping;Tap;Click;mapping;right handed;left handed;
+Categories=Qt;TDE;X-TDE-settings-hardware; \ No newline at end of file
diff --git a/kcontrol/input/touchpad.h b/kcontrol/input/touchpad.h
new file mode 100644
index 000000000..088f7164a
--- /dev/null
+++ b/kcontrol/input/touchpad.h
@@ -0,0 +1,97 @@
+/*******************************************************************************
+ tdecm_touchpad
+ A touchpad module for the TDE Control Centre
+
+ Copyright © 2024 Mavridis Philippe <[email protected]>
+
+ 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/>.
+
+*******************************************************************************/
+
+#ifndef __TOUCHPAD_H__
+#define __TOUCHPAD_H__
+
+// TDE
+#include <tdecmodule.h>
+#include <tdelocale.h>
+
+// Macros
+#define OPTION_NOT_SUPPORTED I18N_NOOP("This option is not compatible with the currently used driver")
+#define DISABLE_UNSUPPORTED_OPTION(optionWidget) \
+ optionWidget->setEnabled(false); \
+ TQToolTip::add(optionWidget, i18n(OPTION_NOT_SUPPORTED));
+
+// Forward definitions
+class TQTabWidget;
+class TQButtonGroup;
+class TQGroupBox;
+class TQCheckBox;
+class TQComboBox;
+class TQSlider;
+class TQLabel;
+class TQFrame;
+class TDEConfig;
+class TouchpadSettings;
+struct Touchpad;
+
+
+/******************************* TouchpadConfig *******************************/
+class TouchpadConfig : public TDECModule
+{
+ TQ_OBJECT
+
+ public:
+ TouchpadConfig(TQWidget *parent, const char *name);
+ ~TouchpadConfig();
+
+ void load();
+ void load(bool useDefaults);
+ void save();
+ void defaults();
+
+ Touchpad touchpad();
+
+ protected:
+ void initWidgets();
+
+ protected slots:
+ void updateWidgetStates();
+
+ private:
+ TouchpadSettings *d_settings;
+
+ TQTabWidget *m_container;
+ TQLabel *m_error;
+ TQCheckBox *m_enabled;
+
+ TQGroupBox *m_behaviour;
+ TQCheckBox *m_offWhileTyping, *m_leftHanded, *m_mbEmulation;
+
+ TQGroupBox *m_speed;
+ TQSlider *m_accel;
+ TQCheckBox *m_accelAdaptive;
+
+ TQGroupBox *m_tapping;
+ TQCheckBox *m_tapClick, *m_tapDrag, *m_tapDragLock;
+ TQComboBox *m_tapMapping;
+
+ TQGroupBox *m_scrolling;
+ TQCheckBox *m_horScroll, *m_verScroll, *m_naturalScroll,
+ *m_horNaturalScroll, *m_verNaturalScroll;
+
+ TQFrame *m_naturalScrollDirections;
+
+ TQButtonGroup *m_scrollMethods;
+};
+
+#endif // __TOUCHPAD_H__
diff --git a/kcontrol/input/touchpad_settings.cpp b/kcontrol/input/touchpad_settings.cpp
new file mode 100644
index 000000000..1230efcee
--- /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 <[email protected]>
+
+ 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 syndaemon
+ DCOPRef syndaemon("syndaemon", "syndaemon");
+ syndaemon.call("stop()");
+
+ if (offWhileTyping)
+ {
+ kapp->tdeinitExec("syndaemon");
+ }
+ }
+
+ 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;
+} \ No newline at end of file
diff --git a/kcontrol/input/touchpad_settings.h b/kcontrol/input/touchpad_settings.h
new file mode 100644
index 000000000..8cdfea951
--- /dev/null
+++ b/kcontrol/input/touchpad_settings.h
@@ -0,0 +1,107 @@
+/*******************************************************************************
+ tdecm_touchpad
+ A touchpad module for the TDE Control Centre
+
+ Copyright © 2024 Mavridis Philippe <[email protected]>
+
+ 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/>.
+
+*******************************************************************************/
+
+#ifndef __TOUCHPAD_SETTINGS_H__
+#define __TOUCHPAD_SETTINGS_H__
+
+// TQt
+#include <tqvaluelist.h>
+
+// Macros
+#define DEL(var) \
+ if (var) { delete var; var = nullptr; }
+
+#define ATOM(var, atom) \
+ Atom var = XInternAtom(display, atom, true);
+
+#define PROP(var, property) \
+ XIProperty var = XIProperty(m_touchpad.id, property);
+
+#define SET_PROP(property, type) \
+ DEL(prop) \
+ prop = new XIProperty(m_touchpad.id, property); \
+ if (prop->type == nullptr) \
+ { \
+ kdWarning() << "Failed to set property " << property << endl; \
+ ++fail; \
+ } \
+ else
+
+#define IF_DRIVER(drv) \
+ if (touchpad().driver == Touchpad::Driver::drv)
+
+
+/****************************** struct Touchpad *******************************/
+#undef None
+
+struct Touchpad
+{
+ enum Driver { None, LibInput, Synaptics };
+
+ bool valid = false;
+ unsigned int id;
+ TQCString name;
+ Driver driver = Touchpad::Driver::None;
+
+ void init(unsigned int _id, TQCString _name)
+ {
+ valid = true;
+ id = _id;
+ name = _name;
+ }
+};
+
+
+/***************************** TouchpadSettings *******************************/
+class TouchpadSettings
+{
+ public:
+ TouchpadSettings();
+
+ void load(bool defaults = false);
+ void save();
+ void apply(bool force = false);
+
+ TQValueList<bool> getScrollMethodsAvailability();
+ TQValueList<bool> getAccelProfilesAvailability();
+
+ bool enabled, tapClick, tapDrag, tapDragLock, tapMapping, offWhileTyping,
+ leftHandedMode, midButtonEmulation, naturalScroll, scrollMethod;
+ int scrollDirections, naturalScrollDirections;
+
+ int accelSpeed, accelProfile;
+
+ bool foundTouchpad();
+ Touchpad touchpad();
+
+ // Enable/disable touchpad without applying all settings
+ bool setTouchpadEnabled(bool on);
+
+ bool supportedTouchpad();
+
+ protected:
+ bool findTouchpad();
+
+ private:
+ Touchpad m_touchpad;
+ bool m_foundTouchpad;
+};
+
+#endif // __TOUCHPAD_SETTINGS_H__ \ No newline at end of file
diff --git a/kcontrol/input/xiproperty.h b/kcontrol/input/xiproperty.h
new file mode 100644
index 000000000..ddbdf4b16
--- /dev/null
+++ b/kcontrol/input/xiproperty.h
@@ -0,0 +1,123 @@
+/*******************************************************************************
+ XIGetProperty/XIChangeProperty wrapper
+
+ Copyright © 2013 Alexandr Mezin <[email protected]>
+ Copyright © 2024 Mavridis Philippe <[email protected]>
+
+ 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, see <https://www.gnu.org/licenses/>.
+
+*******************************************************************************/
+
+#ifndef __XI_PROPERTY_H__
+#define __XI_PROPERTY_H__
+
+// TQt
+#include <tqobject.h> // tqt_xdisplay()
+#include <tqvariant.h>
+
+// X11
+#include <X11/Xatom.h>
+
+
+class XIProperty
+{
+ public:
+ XIProperty()
+ : device(-1),
+ type(0),
+ format(0),
+ num_items(0),
+ data(0),
+ b(nullptr),
+ i(nullptr),
+ f(nullptr)
+ {}
+
+ XIProperty(int device, TQCString propertyName)
+ : device(device),
+ type(0),
+ format(0),
+ num_items(0),
+ data(0),
+ b(nullptr),
+ i(nullptr),
+ f(nullptr)
+ {
+ Display *disp = tqt_xdisplay();
+
+ property = XInternAtom(disp, propertyName, true);
+
+ unsigned char *ptr = nullptr;
+ unsigned long bytes_after;
+
+ XIGetProperty(disp, device, property, 0, 1000, False, AnyPropertyType,
+ &type, &format, &num_items, &bytes_after, &ptr);
+
+ data = ptr;
+
+ if (format == CHAR_BIT && type == XA_INTEGER)
+ {
+ b = reinterpret_cast<char *>(data);
+ }
+
+ if (format == sizeof(int) * CHAR_BIT
+ && (type == XA_INTEGER || type == XA_CARDINAL))
+ {
+ i = reinterpret_cast<int *>(data);
+ }
+
+ Atom floatType = XInternAtom(disp, "FLOAT", true);
+
+ if (format == sizeof(float) * CHAR_BIT && floatType && type == floatType)
+ {
+ f = reinterpret_cast<float *>(data);
+ }
+ }
+
+ ~XIProperty()
+ {
+ XFree(data);
+ }
+
+ TQVariant operator[](int offset)
+ {
+ if (offset >= num_items) return TQVariant();
+
+ if (b) return TQVariant(static_cast<int>(b[offset]));
+ if (i) return TQVariant(i[offset]);
+ if (f) return TQVariant(f[offset]);
+
+ return TQVariant();
+ }
+
+ void set()
+ {
+ XIChangeProperty(tqt_xdisplay(), device, property, type, format, XIPropModeReplace,
+ data, num_items);
+ }
+
+ int count() { return num_items; }
+
+ public:
+ char *b;
+ int *i;
+ float *f;
+
+ private:
+ Atom property, type;
+ int device, format;
+ unsigned long num_items;
+ unsigned char *data;
+};
+
+#endif // __XI_PROPERTY_H__ \ No newline at end of file