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
@ -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>
|
@ -0,0 +1 @@
|
||||
tde_install_icons()
|
After Width: | Height: | Size: 8.1 KiB |
After Width: | Height: | Size: 719 B |
After Width: | Height: | Size: 1.7 KiB |
After Width: | Height: | Size: 2.8 KiB |
After Width: | Height: | Size: 3.9 KiB |
After Width: | Height: | Size: 14 KiB |
@ -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 )
|
After Width: | Height: | Size: 1.8 KiB |
After Width: | Height: | Size: 1.8 KiB |
After Width: | Height: | Size: 1.8 KiB |
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__
|