KControl: add touchpad configuration module

Supports the Libinput and Synaptics drivers, includes documentation and inpupt-touchpad icon.

Signed-off-by: Mavridis Philippe <mavridisf@gmail.com>
(cherry picked from commit 8bd4c502f6)
r14.1.x
Mavridis Philippe 6 months ago
parent 63178a8866
commit 2af9d1ed2c

@ -678,4 +678,13 @@ if( BUILD_KCONTROL OR BUILD_TDM )
endif( BUILD_KCONTROL OR BUILD_TDM )
# XInput (kcontrol/input/touchpad.cpp)
if( BUILD_KCONTROL )
pkg_search_module( XINPUT xi )
if( NOT XINPUT_FOUND )
tde_message_fatal( "XInput is required, but was not found on your system" )
endif( )
endif ( BUILD_KCONTROL )
check_include_files( "sys/time.h;sys/loadavg.h" HAVE_SYS_LOADAVG_H )

@ -0,0 +1 @@
tde_create_handbook( DESTINATION kcontrol/touchpad )

@ -0,0 +1,402 @@
<?xml version="1.0" ?>
<!DOCTYPE article PUBLIC "-//KDE//DTD DocBook XML V4.2-Based Variant V1.1//EN" "dtd/kdex.dtd" [
<!ENTITY % addindex "IGNORE">
<!ENTITY % English "INCLUDE" > <!-- change language only here -->
]>
<article lang="&language;">
<title>Touchpad</title>
<articleinfo>
<authorgroup>
<author>
<firstname>Philippe</firstname><surname>Mavridis</surname>
</author>
<author>&tde-authors;</author>
<!-- TRANS:ROLES_OF_TRANSLATORS -->
</authorgroup>
<copyright>
<year>2024</year>
<holder>Philippe Mavridis</holder>
</copyright>
<copyright>
<year>&tde-copyright-date;</year>
<holder>&tde-team;</holder>
</copyright>
<releaseinfo>&tde-release-version;</releaseinfo>
<date>Reviewed: &tde-release-date;</date>
<keywordset>
<keyword>TDE</keyword>
<keyword>KControl</keyword>
<keyword>System Settings</keyword>
<keyword>devices</keyword>
<keyword>input</keyword>
<keyword>touchpad</keyword>
<keyword>clickpad</keyword>
<keyword>tapping</keyword>
<keyword>tap-to-click</keyword>
</keywordset>
</articleinfo>
<abstract>
<para>This is the documentation for the &tde; &kcontrol; module which configures the touchpad, if one is detected.</para>
</abstract>
<sect1 id="touchpad">
<title>Touchpad</title>
<para>The module automatically detects the touchpad and provides options for configuring its behaviour. The provided options are grouped into five categories:</para>
<itemizedlist>
<listitem>
<para><link linkend="touchpad-behaviour">Behaviour</link></para>
</listitem>
<listitem>
<para><link linkend="touchpad-speed">Speed</link></para>
</listitem>
<listitem>
<para><link linkend="touchpad-tapping">Tapping</link></para>
</listitem>
<listitem>
<para><link linkend="touchpad-scroll-options">Scrolling options</link></para>
</listitem>
<listitem>
<para><link linkend="touchpad-scroll-methods">Scrolling method</link></para>
</listitem>
</itemizedlist>
<para>The available options depend on which driver is currently in use. This module supports the modern Libinput driver, as well as the older Synaptics driver. While the Synaptics driver is considered unmaintained, one may choose it over the newer Libinput driver if some feature they need is not supported by the Libinput driver and vice versa. For an overview of features supported by each driver see <link linkend="touchpad-drivers">Driver compatibility</link>.</para>
<sect2 id="touchpad-behaviour">
<title>Behaviour</title>
<variablelist>
<varlistentry>
<term><guilabel>Disable touchpad while typing</guilabel></term>
<listitem><para>
If this option is checked, the touchpad is disabled while you are typing, so as
to prevent accidental cursor movement and clicks. The touchpad is enabled again
after a short while.
</para></listitem>
</varlistentry>
<varlistentry>
<term><guilabel>Middle button emulation</guilabel></term>
<listitem><para>
If this option is enabled, a simultaneous left and right button click is automatically
transformed into a middle button click. Some devices provide middle mouse button
emulation but do not allow enabling/disabling that emulation.
</para></listitem>
</varlistentry>
</variablelist>
</sect2>
<sect2 id="touchpad-speed">
<title>Speed</title>
<variablelist>
<varlistentry>
<term><guilabel>Acceleration</guilabel></term>
<listitem><para>
With this option you can change the speed that the pointer moves on the screen.
</para></listitem>
</varlistentry>
<varlistentry>
<term><guilabel>Use adaptive profile</guilabel></term>
<listitem><para>
If this option is enabled, the adaptive acceleration profile is used, otherwise
the flat profile is used.
</para>
<para>
The <guilabel>adaptive</guilabel> profile is the default profile used by the Libinput driver. It takes the current speed of the device into account when deciding on acceleration.
</para><para>
The <guilabel>flat</guilabel> profile applies a constant factor to every pointer movement, regardless of the speed of motion, providing 1:1 movement between the
pointer and the device. Techincally, each delta (dx, dy) results in an accelerated
delta (dx * factor, dy * factor).
</para></listitem>
</varlistentry>
</variablelist>
</sect2>
<sect2 id="touchpad-tapping">
<title>Tapping</title>
<variablelist>
<varlistentry>
<term><guilabel>Tap-to-click</guilabel></term>
<listitem><para>
This option enables or disables the "tap-to-click" feature (also known as "tapping").
With this option enabled, a tap on the touchpad is interpreted as a click.
</para>
<para>Several other features are also related to tapping, including tap-and-drag and
multiple finger taps. These features can be configured via the rest of the options
of this section. This option must be enabled for the rest to work.
</para></listitem>
</varlistentry>
<varlistentry>
<term><guilabel>Tap-and-drag</guilabel></term>
<listitem><para>
This option enables or disables the "tap-and-drag" feature. Tap-and-drag is a short
tap which is immediately followed by a longer tap, with the finger being then held
down. This simulates a button press and moving the finger around can thus cause the
the object under the mouse pointer to be dragged around. When the finger is lifted,
the dragging is completed.
</para></listitem>
</varlistentry>
<varlistentry>
<term><guilabel>Tap-and-drag lock</guilabel></term>
<listitem><para>
This option modifies the behaviour of the tap-and-drag feature so that lifting
a finger while dragging will not immediately stop dragging. Therefore, if you place
the finger down on the touchpad again before a short while has passed, the dragging
will resume from the place it was left.
</para>
<para>
This option is disabled when the tap-and-drag feature is not enabled.
</para></listitem>
</varlistentry>
<varlistentry>
<term><guilabel>Two-finger tap</guilabel></term>
<listitem><para>
With this option you can choose whether the two-finger tap will invoke a middle click
or a right click action. The three-finger tap is automatically assigned the other
action.</para>
<para>
The default for this option is the right click. This means that a two-finger tap will
emulate a right button click, whereas a three-finger tap will emulate a middle button
click.
</para></listitem>
</varlistentry>
</variablelist>
</sect2>
<sect2 id="touchpad-scroll-options">
<title>Scrolling options</title>
<variablelist>
<varlistentry>
<term><guilabel>Vertical scrolling</guilabel></term>
<listitem><para>
This option enables/disables the vertical scrolling gesture on the touchpad.
</para>
<para>
The gesture used for scrolling depends on the selected scrolling method, see
<link linkend="touchpad-scroll-methods">Scrolling method</link>.
</para></listitem>
</varlistentry>
<varlistentry>
<term><guilabel>Horizontal scrolling</guilabel></term>
<listitem><para>
This option enables/disables the horizontal scrolling gesture on the touchpad.
</para>
<para>
The gesture used for scrolling depends on the selected scrolling method, see
<link linkend="touchpad-scroll-methods">Scrolling method</link>.
</para></listitem>
</varlistentry>
<varlistentry>
<term><guilabel>Reverse scroll direction</guilabel></term>
<listitem><para>
If this option is checked, the scrolling direction is reversed to resemble natural
movement of content. This feature is also known as Natural scrolling.
</para>
<para>
With the Synaptics driver you can configure this option for individual directions,
see the options <guilabel>Apply to horizontal scrolling</guilabel> and
<guilabel>Apply to vertical scrolling</guilabel> below.
</para></listitem>
</varlistentry>
<varlistentry>
<term><guilabel>Apply to horizontal scrolling</guilabel></term>
<listitem><para>
If this option is checked, the horizontal scrolling direction is reversed
(Synaptics driver only).
</para></listitem>
</varlistentry>
<varlistentry>
<term><guilabel>Apply to vertical scrolling</guilabel></term>
<listitem><para>
If this option is checked, the vertical scrolling direction is reversed
(Synaptics driver only).
</para></listitem>
</varlistentry>
</variablelist>
</sect2>
<sect2 id="touchpad-scroll-methods">
<title>Scrolling method</title>
<para>
This section allows you to pick your preferred scrolling method. This will determine
the gesture which you will use to trigger scrolling.
</para>
<para>
The two most common options are <guilabel>Two-finger</guilabel> and
<guilabel>Edge</guilabel> scrolling.</para>
<orderedlist>
<listitem><para>
<guilabel>Two-finger</guilabel> scrolling entails a movement with two fingers vertically or horizontally upon the surface of the touchpad.
</para></listitem>
<listitem><para>
<guilabel>Edge scrolling</guilabel> on the other hand tracks movements with one finger
long the right or bottom edge of the touchpad.
</para></listitem>
</orderedlist>
<para>
Additionally, the Libinput driver provides the <guilabel>Button</guilabel> scrolling
method. On-button scrolling converts the motion of a device into scroll events while a designated button is held down.
</para>
</sect2>
<sect2 id="touchpad-drivers">
<title>Driver compatibility</title>
<informaltable>
<tgroup cols="4">
<thead><row>
<entry>Group</entry>
<entry>Feature</entry>
<entry>LibInput driver</entry>
<entry>Synaptics driver</entry>
</row></thead>
<tbody>
<row>
<entry>GENERIC</entry>
<entry>Enable/disable touchpad</entry>
<entry>YES</entry>
<entry>YES</entry>
</row>
<row>
<entry>BEHAVIOUR</entry>
<entry>Disable touchpad while typing</entry>
<entry>YES</entry>
<entry>YES*</entry>
</row>
<row>
<entry>BEHAVIOUR</entry>
<entry>Middle button emulation</entry>
<entry>YES</entry>
<entry>YES**</entry>
</row>
<row>
<entry>SPEED</entry>
<entry>Acceleration</entry>
<entry>YES</entry>
<entry>NO</entry>
</row>
<row>
<entry>SPEED</entry>
<entry>Acceleration profile</entry>
<entry>YES</entry>
<entry>NO</entry>
</row>
<row>
<entry>TAPPING</entry>
<entry>Tap-to-click</entry>
<entry>YES</entry>
<entry>YES</entry>
</row>
<row>
<entry>TAPPING</entry>
<entry>Tap-and-drag</entry>
<entry>YES</entry>
<entry>YES</entry>
</row>
<row>
<entry>TAPPING</entry>
<entry>Tap-and-drag lock</entry>
<entry>YES</entry>
<entry>NO</entry>
</row>
<row>
<entry>TAPPING</entry>
<entry>Two-finger/three-finger tap swapping</entry>
<entry>YES</entry>
<entry>YES</entry>
</row>
<row>
<entry>SCROLLING OPTIONS</entry>
<entry>Enable/disable vertical scrolling</entry>
<entry>YES***</entry>
<entry>YES</entry>
</row>
<row>
<entry>SCROLLING OPTIONS</entry>
<entry>Enable/disable horizontal scrolling</entry>
<entry>YES</entry>
<entry>YES</entry>
</row>
<row>
<entry>SCROLLING OPTIONS</entry>
<entry>Enable/disable natural scrolling</entry>
<entry>YES</entry>
<entry>YES</entry>
</row>
<row>
<entry>SCROLLING OPTIONS</entry>
<entry>Enable/disable vertical natural scrolling</entry>
<entry>NO</entry>
<entry>YES</entry>
</row>
<row>
<entry>SCROLLING OPTIONS</entry>
<entry>Enable/disable horizontal natural scrolling</entry>
<entry>NO</entry>
<entry>YES</entry>
</row>
<row>
<entry>SCROLLING METHODS</entry>
<entry>Two-finger</entry>
<entry>YES</entry>
<entry>YES</entry>
</row>
<row>
<entry>SCROLLING METHODS</entry>
<entry>Edge</entry>
<entry>YES</entry>
<entry>YES</entry>
</row>
<row>
<entry>SCROLLING METHODS</entry>
<entry>Button</entry>
<entry>YES</entry>
<entry>NO</entry>
</row>
</tbody>
</tgroup>
</informaltable>
<para>* Synaptics supported using external <guilabel>syndaemon</guilabel> service, automatically started/stopped.</para>
<para>** Not configurable with the Synaptics driver.</para>
<para>*** Disabling vertical scrolling under the Libinput driver disables scrolling entirely.</para>
</sect2>
</sect1>
</article>

@ -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

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 719 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

@ -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>

After

Width:  |  Height:  |  Size: 14 KiB

@ -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();
}
}

@ -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 )

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

@ -0,0 +1,201 @@
/*******************************************************************************
syndaemon - daemon for the Synaptics touchpad driver which disables touchpad
on keyboard input
Copyright © 2004 Nadeem Hasan <nhasan@kde.org>
Stefan Kombrink <katakombi@web.de>
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/>.
*******************************************************************************/
// 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"), "nhasan@kde.org");
aboutData.addAuthor("Mavridis Philippe", I18N_NOOP("Author"), "mavridisf@gmail.com");
TDECmdLineArgs::init(argc, argv, &aboutData);
TDEApplication app;
app.disableSessionManagement();
app.dcopClient()->registerAs("syndaemon", false);
SynDaemon syndaemon;
return app.exec();
}

@ -0,0 +1,78 @@
/*******************************************************************************
syndaemon - daemon for the Synaptics touchpad driver which disables touchpad
on keyboard input
Copyright © 2004 Nadeem Hasan <nhasan@kde.org>
Stefan Kombrink <katakombi@web.de>
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/>.
*******************************************************************************/
#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

@ -0,0 +1,34 @@
/*******************************************************************************
syndaemon - daemon for the Synaptics touchpad driver which disables touchpad
on keyboard input
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/>.
*******************************************************************************/
#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

@ -0,0 +1,528 @@
/*******************************************************************************
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/>.
*******************************************************************************/
// 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();
}

@ -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;

@ -0,0 +1,97 @@
/*******************************************************************************
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/>.
*******************************************************************************/
#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__

@ -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 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;
}

@ -0,0 +1,107 @@
/*******************************************************************************
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/>.
*******************************************************************************/
#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__

@ -0,0 +1,123 @@
/*******************************************************************************
XIGetProperty/XIChangeProperty wrapper
Copyright © 2013 Alexandr Mezin <mezin.alexander@gmail.com>
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 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__
Loading…
Cancel
Save