Brooklyn/plasma/kcms/touchpad/backends/x11/libinputtouchpad.cpp
Scare Crowe d2ebfd0519 QortalOS Titan 5.60.12
Screw the description like that inbred T3Q
2022-03-05 21:17:59 +05:00

396 lines
16 KiB
C++

/*
SPDX-FileCopyrightText: 2019 Atul Bisht <atulbisht26@gmail.com>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "libinputtouchpad.h"
#include "logging.h"
#include <QSet>
#include <limits.h>
#include <stddef.h>
#include <libinput-properties.h>
#include <xserver-properties.h>
#include <X11/extensions/XInput2.h>
const Parameter libinputProperties[] = {
/* libinput disable supports property */
{"supportsDisableEvents", PT_INT, 0, 1, LIBINPUT_PROP_SENDEVENTS_AVAILABLE, 8, 0},
{"enabled", PT_INT, 0, 1, LIBINPUT_PROP_SENDEVENTS_ENABLED, 8, 0},
{"enabledDefault", PT_INT, 0, 1, LIBINPUT_PROP_SENDEVENTS_ENABLED_DEFAULT, 8, 0},
/* LeftHandSupport */
{"leftHandedEnabledByDefault", PT_INT, 0, 1, LIBINPUT_PROP_LEFT_HANDED_DEFAULT, 8, 0},
{"leftHanded", PT_INT, 0, 1, LIBINPUT_PROP_LEFT_HANDED, 8, 0},
/* Disable on external mouse */
{"supportsDisableEventsOnExternalMouse", PT_INT, 0, 1, LIBINPUT_PROP_SENDEVENTS_AVAILABLE, 8, 1},
{"disableEventsOnExternalMouse", PT_INT, 0, 1, LIBINPUT_PROP_SENDEVENTS_ENABLED, 8, 1},
{"disableEventsOnExternalMouseDefault", PT_INT, 0, 1, LIBINPUT_PROP_SENDEVENTS_ENABLED_DEFAULT, 8, 1},
/* Disable while typing */
{"disableWhileTypingEnabledByDefault", PT_INT, 0, 1, LIBINPUT_PROP_DISABLE_WHILE_TYPING_DEFAULT, 8, 0},
{"disableWhileTyping", PT_INT, 0, 1, LIBINPUT_PROP_DISABLE_WHILE_TYPING, 8, 0},
/* Middle Emulation */
{"middleEmulationEnabledByDefault", PT_INT, 0, 1, LIBINPUT_PROP_MIDDLE_EMULATION_ENABLED_DEFAULT, 8, 0},
{"middleEmulation", PT_INT, 0, 1, LIBINPUT_PROP_MIDDLE_EMULATION_ENABLED, 8, 0},
/* This is a boolean for all three fingers, no per-finger config */
{"tapToClick", PT_INT, 0, 1, LIBINPUT_PROP_TAP, 8, 0},
{"tapToClickEnabledByDefault", PT_INT, 0, 1, LIBINPUT_PROP_TAP_DEFAULT, 8, 0},
/* LMR */
{"lrmTapButtonMapEnabledByDefault", PT_INT, 0, 1, LIBINPUT_PROP_TAP_BUTTONMAP_DEFAULT, 8, 0},
{"lrmTapButtonMap", PT_INT, 0, 1, LIBINPUT_PROP_TAP_BUTTONMAP, 8, 0},
{"lmrTapButtonMapEnabledByDefault", PT_INT, 0, 1, LIBINPUT_PROP_TAP_BUTTONMAP_DEFAULT, 8, 1},
{"lmrTapButtonMap", PT_INT, 0, 1, LIBINPUT_PROP_TAP_BUTTONMAP, 8, 1},
/* Tap and Drag Enabled */
{"tapAndDragEnabledByDefault", PT_INT, 0, 1, LIBINPUT_PROP_TAP_DRAG_DEFAULT, 8, 0},
{"tapAndDrag", PT_INT, 0, 1, LIBINPUT_PROP_TAP_DRAG, 8, 0},
/* Tap and Drag Lock Enabled */
{"tapDragLockEnabledByDefault", PT_INT, 0, 1, LIBINPUT_PROP_TAP_DRAG_LOCK_DEFAULT, 8, 0},
{"tapDragLock", PT_INT, 0, 1, LIBINPUT_PROP_TAP_DRAG_LOCK, 8, 0},
/* libinput normalizes the accel to -1/1 */
{"defaultPointerAcceleration", PT_DOUBLE, -1.0, 1.0, LIBINPUT_PROP_ACCEL_DEFAULT, 0 /*float */, 0},
{"pointerAcceleration", PT_DOUBLE, -1.0, 1.0, LIBINPUT_PROP_ACCEL, 0 /*float */, 0},
/* Libinput Accel Profile */
{"supportsPointerAccelerationProfileAdaptive", PT_BOOL, 0, 1, LIBINPUT_PROP_ACCEL_PROFILES_AVAILABLE, 8, 0},
{"defaultPointerAccelerationProfileAdaptive", PT_BOOL, 0, 1, LIBINPUT_PROP_ACCEL_PROFILE_ENABLED_DEFAULT, 8, 0},
{"pointerAccelerationProfileAdaptive", PT_BOOL, 0, 1, LIBINPUT_PROP_ACCEL_PROFILE_ENABLED, 8, 0},
{"supportsPointerAccelerationProfileFlat", PT_BOOL, 0, 1, LIBINPUT_PROP_ACCEL_PROFILES_AVAILABLE, 8, 1},
{"defaultPointerAccelerationProfileFlat", PT_BOOL, 0, 1, LIBINPUT_PROP_ACCEL_PROFILE_ENABLED_DEFAULT, 8, 1},
{"pointerAccelerationProfileFlat", PT_BOOL, 0, 1, LIBINPUT_PROP_ACCEL_PROFILE_ENABLED, 8, 1},
/* Natural Scrolling */
{"naturalScrollEnabledByDefault", PT_INT, 0, 1, LIBINPUT_PROP_NATURAL_SCROLL_DEFAULT, 8, 0},
{"naturalScroll", PT_INT, 0, 1, LIBINPUT_PROP_NATURAL_SCROLL, 8, 0},
/* Horizontal scrolling */
{"horizontalScrolling", PT_INT, 0, 1, LIBINPUT_PROP_HORIZ_SCROLL_ENABLED, 8, 0},
/* Two-Finger Scrolling */
{"supportsScrollTwoFinger", PT_INT, 0, 1, LIBINPUT_PROP_SCROLL_METHODS_AVAILABLE, 8, 0},
{"scrollTwoFingerEnabledByDefault", PT_INT, 0, 1, LIBINPUT_PROP_SCROLL_METHOD_ENABLED_DEFAULT, 8, 0},
{"scrollTwoFinger", PT_INT, 0, 1, LIBINPUT_PROP_SCROLL_METHOD_ENABLED, 8, 0},
/* Edge Scrolling */
{"supportsScrollEdge", PT_INT, 0, 1, LIBINPUT_PROP_SCROLL_METHODS_AVAILABLE, 8, 1},
{"scrollEdgeEnabledByDefault", PT_INT, 0, 1, LIBINPUT_PROP_SCROLL_METHOD_ENABLED_DEFAULT, 8, 1},
{"scrollEdge", PT_INT, 0, 1, LIBINPUT_PROP_SCROLL_METHOD_ENABLED, 8, 1},
/* scroll on button */
{"supportsScrollOnButtonDown", PT_INT, 0, 1, LIBINPUT_PROP_SCROLL_METHODS_AVAILABLE, 8, 2},
{"scrollOnButtonDownEnabledByDefault", PT_INT, 0, 1, LIBINPUT_PROP_SCROLL_METHOD_ENABLED_DEFAULT, 8, 2},
{"scrollOnButtonDown", PT_INT, 0, 1, LIBINPUT_PROP_SCROLL_METHOD_ENABLED, 8, 2},
/* Scroll Button for scroll on button Down */
{"defaultScrollButton", PT_INT, 0, INT_MAX, LIBINPUT_PROP_SCROLL_BUTTON_DEFAULT, 32, 0},
{"scrollButton", PT_INT, 0, INT_MAX, LIBINPUT_PROP_SCROLL_BUTTON, 32, 0},
/* Click Methods */
{"supportsClickMethodAreas", PT_INT, 0, 1, LIBINPUT_PROP_CLICK_METHODS_AVAILABLE, 8, 0},
{"defaultClickMethodAreas", PT_INT, 0, 1, LIBINPUT_PROP_CLICK_METHOD_ENABLED_DEFAULT, 8, 0},
{"clickMethodAreas", PT_INT, 0, 1, LIBINPUT_PROP_CLICK_METHOD_ENABLED, 8, 0},
{"supportsClickMethodClickfinger", PT_INT, 0, 1, LIBINPUT_PROP_CLICK_METHODS_AVAILABLE, 8, 1},
{"defaultClickMethodClickfinger", PT_INT, 0, 1, LIBINPUT_PROP_CLICK_METHOD_ENABLED_DEFAULT, 8, 1},
{"clickMethodClickfinger", PT_INT, 0, 1, LIBINPUT_PROP_CLICK_METHOD_ENABLED, 8, 1},
/* libinput doesn't have a separate toggle for horiz scrolling */
{nullptr, PT_INT, 0, 0, nullptr, 0, 0}};
Qt::MouseButtons maskBtns(Display *display, XIButtonClassInfo *buttonInfo)
{
Qt::MouseButtons buttons = Qt::NoButton;
for (int i = 0; i < buttonInfo->num_buttons; ++i) {
QByteArray reply = XGetAtomName(display, buttonInfo->labels[i]);
if (reply == BTN_LABEL_PROP_BTN_LEFT) {
buttons |= Qt::LeftButton;
}
if (reply == BTN_LABEL_PROP_BTN_RIGHT) {
buttons |= Qt::RightButton;
}
if (reply == BTN_LABEL_PROP_BTN_MIDDLE) {
buttons |= Qt::MiddleButton;
}
if (reply == BTN_LABEL_PROP_BTN_SIDE) {
buttons |= Qt::ExtraButton1;
}
if (reply == BTN_LABEL_PROP_BTN_EXTRA) {
buttons |= Qt::ExtraButton2;
}
if (reply == BTN_LABEL_PROP_BTN_FORWARD) {
buttons |= Qt::ForwardButton;
}
if (reply == BTN_LABEL_PROP_BTN_BACK) {
buttons |= Qt::BackButton;
}
if (reply == BTN_LABEL_PROP_BTN_TASK) {
buttons |= Qt::TaskButton;
}
}
return buttons;
}
LibinputTouchpad::LibinputTouchpad(Display *display, int deviceId)
: LibinputCommon()
, XlibTouchpad(display, deviceId)
{
loadSupportedProperties(libinputProperties);
int nDevices = 0;
XIDeviceInfo *deviceInfo = XIQueryDevice(m_display, m_deviceId, &nDevices);
m_name = deviceInfo->name;
for (int i = 0; i < deviceInfo->num_classes; ++i) {
XIAnyClassInfo *classInfo = deviceInfo->classes[i];
if (classInfo->type == XIButtonClass) {
XIButtonClassInfo *btnInfo = (XIButtonClassInfo *)classInfo;
m_supportedButtons.avail = true;
m_supportedButtons.set(maskBtns(m_display, btnInfo));
}
if (classInfo->type == XITouchClass) {
XITouchClassInfo *touchInfo = (XITouchClassInfo *)classInfo;
m_tapFingerCount.avail = true;
m_tapFingerCount.set(touchInfo->num_touches);
}
}
XIFreeDeviceInfo(deviceInfo);
/* FingerCount cannot be zero */
if (!m_tapFingerCount.val) {
m_tapFingerCount.avail = true;
m_tapFingerCount.set(1);
}
m_config = KSharedConfig::openConfig(QStringLiteral("touchpadxlibinputrc"));
}
bool LibinputTouchpad::getConfig()
{
bool success = true;
success &= valueLoader(m_supportsDisableEvents);
success &= valueLoader(m_enabled);
success &= valueLoader(m_enabledDefault);
success &= valueLoader(m_tapToClickEnabledByDefault);
success &= valueLoader(m_tapToClick);
success &= valueLoader(m_lrmTapButtonMapEnabledByDefault);
success &= valueLoader(m_lrmTapButtonMap);
success &= valueLoader(m_lmrTapButtonMapEnabledByDefault);
success &= valueLoader(m_lmrTapButtonMap);
success &= valueLoader(m_tapAndDragEnabledByDefault);
success &= valueLoader(m_tapAndDrag);
success &= valueLoader(m_tapDragLockEnabledByDefault);
success &= valueLoader(m_tapDragLock);
success &= valueLoader(m_leftHandedEnabledByDefault);
success &= valueLoader(m_leftHanded);
success &= valueLoader(m_supportsDisableEventsOnExternalMouse);
success &= valueLoader(m_disableEventsOnExternalMouse);
success &= valueLoader(m_disableEventsOnExternalMouseDefault);
success &= valueLoader(m_disableWhileTypingEnabledByDefault);
success &= valueLoader(m_disableWhileTyping);
success &= valueLoader(m_middleEmulationEnabledByDefault);
success &= valueLoader(m_middleEmulation);
success &= valueLoader(m_defaultPointerAcceleration);
success &= valueLoader(m_pointerAcceleration);
success &= valueLoader(m_supportsPointerAccelerationProfileFlat);
success &= valueLoader(m_defaultPointerAccelerationProfileFlat);
success &= valueLoader(m_pointerAccelerationProfileFlat);
success &= valueLoader(m_supportsPointerAccelerationProfileAdaptive);
success &= valueLoader(m_defaultPointerAccelerationProfileAdaptive);
success &= valueLoader(m_pointerAccelerationProfileAdaptive);
success &= valueLoader(m_naturalScrollEnabledByDefault);
success &= valueLoader(m_naturalScroll);
success &= valueLoader(m_horizontalScrolling);
success &= valueLoader(m_supportsScrollTwoFinger);
success &= valueLoader(m_scrollTwoFingerEnabledByDefault);
success &= valueLoader(m_isScrollTwoFinger);
success &= valueLoader(m_supportsScrollEdge);
success &= valueLoader(m_scrollEdgeEnabledByDefault);
success &= valueLoader(m_isScrollEdge);
success &= valueLoader(m_supportsScrollOnButtonDown);
success &= valueLoader(m_scrollOnButtonDownEnabledByDefault);
success &= valueLoader(m_isScrollOnButtonDown);
success &= valueLoader(m_defaultScrollButton);
success &= valueLoader(m_scrollButton);
// click methods
success &= valueLoader(m_supportsClickMethodAreas);
success &= valueLoader(m_supportsClickMethodClickfinger);
success &= valueLoader(m_defaultClickMethodAreas);
success &= valueLoader(m_defaultClickMethodClickfinger);
success &= valueLoader(m_clickMethodAreas);
success &= valueLoader(m_clickMethodClickfinger);
return success;
}
bool LibinputTouchpad::applyConfig()
{
QVector<QString> msgs;
msgs << valueWriter(m_enabled) << valueWriter(m_tapToClick) << valueWriter(m_lrmTapButtonMap) << valueWriter(m_lmrTapButtonMap) << valueWriter(m_tapAndDrag)
<< valueWriter(m_tapDragLock) << valueWriter(m_leftHanded) << valueWriter(m_disableWhileTyping) << valueWriter(m_middleEmulation)
<< valueWriter(m_pointerAcceleration) << valueWriter(m_pointerAccelerationProfileFlat) << valueWriter(m_pointerAccelerationProfileAdaptive)
<< valueWriter(m_naturalScroll) << valueWriter(m_horizontalScrolling) << valueWriter(m_isScrollTwoFinger) << valueWriter(m_isScrollEdge)
<< valueWriter(m_isScrollOnButtonDown) << valueWriter(m_scrollButton) << valueWriter(m_clickMethodAreas) << valueWriter(m_clickMethodClickfinger);
bool success = true;
QString error_msg;
for (QString m : msgs) {
if (!m.isNull()) {
qCCritical(KCM_TOUCHPAD) << "in error:" << m;
if (!success) {
error_msg.append("\n");
}
error_msg.append(m);
success = false;
}
}
if (!success) {
qCCritical(KCM_TOUCHPAD) << error_msg;
}
flush();
return success;
}
bool LibinputTouchpad::getDefaultConfig()
{
m_enabled.set(m_enabledDefault);
m_tapToClick.set(m_tapToClickEnabledByDefault);
m_lrmTapButtonMap.set(m_lrmTapButtonMap);
m_lmrTapButtonMap.set(m_lmrTapButtonMapEnabledByDefault);
m_tapAndDrag.set(m_tapAndDragEnabledByDefault);
m_tapDragLock.set(m_tapDragLockEnabledByDefault);
m_leftHanded.set(m_leftHandedEnabledByDefault);
m_disableEventsOnExternalMouse.set(m_disableEventsOnExternalMouseDefault);
m_disableWhileTyping.set(m_disableWhileTypingEnabledByDefault);
m_middleEmulation.set(m_middleEmulationEnabledByDefault);
m_pointerAcceleration.set(m_defaultPointerAcceleration);
m_pointerAccelerationProfileFlat.set(m_defaultPointerAccelerationProfileFlat);
m_pointerAccelerationProfileAdaptive.set(m_defaultPointerAccelerationProfileAdaptive);
m_naturalScroll.set(m_naturalScrollEnabledByDefault);
m_horizontalScrolling.set(true);
m_isScrollTwoFinger.set(m_scrollTwoFingerEnabledByDefault);
m_isScrollEdge.set(m_scrollEdgeEnabledByDefault);
m_isScrollOnButtonDown.set(m_scrollOnButtonDownEnabledByDefault);
m_scrollButton.set(m_defaultScrollButton);
m_clickMethodAreas.set(m_defaultClickMethodAreas);
m_clickMethodClickfinger.set(m_defaultClickMethodClickfinger);
return true;
}
bool LibinputTouchpad::isChangedConfig()
{
// clang-format off
bool changed = m_enabled.changed() ||
m_tapToClick.changed() ||
m_lrmTapButtonMap.changed() ||
m_lmrTapButtonMap.changed() ||
m_tapAndDrag.changed() ||
m_tapDragLock.changed() ||
m_leftHanded.changed() ||
m_disableEventsOnExternalMouse.changed() ||
m_disableWhileTyping.changed() ||
m_middleEmulation.changed() ||
m_pointerAcceleration.changed() ||
m_pointerAccelerationProfileFlat.changed() ||
m_pointerAccelerationProfileAdaptive.changed() ||
m_naturalScroll.changed() ||
m_horizontalScrolling.changed() ||
m_isScrollTwoFinger.changed() ||
m_isScrollEdge.changed() ||
m_isScrollOnButtonDown.changed() ||
m_scrollButton.changed() ||
m_clickMethodAreas.changed() ||
m_clickMethodClickfinger.changed();
// clang-format on
return changed;
}
int LibinputTouchpad::touchpadOff()
{
return m_enabled.val;
}
XcbAtom &LibinputTouchpad::touchpadOffAtom()
{
return *m_atoms[QLatin1String(LIBINPUT_PROP_SENDEVENTS_ENABLED)].data();
}
template<typename T>
bool LibinputTouchpad::valueLoader(Prop<T> &prop)
{
const Parameter *p = findParameter(QString::fromLatin1(prop.name));
if (!p) {
qCCritical(KCM_TOUCHPAD) << "Error on read of " << QString::fromLatin1(prop.name);
}
QVariant reply = getParameter(p);
if (!reply.isValid()) {
prop.avail = false;
return true;
}
prop.avail = true;
auto touchpadConfig = m_config->group(m_name);
const T replyValue = valueLoaderPart<T>(reply);
const T loadedValue = touchpadConfig.readEntry(QString(prop.name), replyValue);
prop.old = replyValue;
prop.val = loadedValue;
return true;
}
template<typename T>
QString LibinputTouchpad::valueWriter(const Prop<T> &prop)
{
const Parameter *p = findParameter(QString::fromLatin1(prop.name));
if (!p || !prop.changed()) {
return QString();
}
bool error = !setParameter(p, prop.val);
if (error) {
qCCritical(KCM_TOUCHPAD) << "Cannot set property " + QString::fromLatin1(prop.name);
return QStringLiteral("Cannot set property ") + QString::fromLatin1(prop.name);
}
auto touchpadConfig = m_config->group(m_name);
touchpadConfig.writeEntry(QString(prop.name), prop.val);
touchpadConfig.config()->sync();
return QString();
}