Scare Crowe d2ebfd0519 QortalOS Titan 5.60.12
Screw the description like that inbred T3Q
2022-03-05 21:17:59 +05:00

258 lines
6.3 KiB
C++

#include <cmath>
#include "xlibtouchpad.h"
#include <X11/Xlib-xcb.h>
#include <X11/extensions/XInput.h>
#include <X11/extensions/XInput2.h>
#include <xserver-properties.h>
static QVariant negateVariant(const QVariant &value)
{
if (value.type() == QVariant::Double) {
return QVariant(-value.toDouble());
} else if (value.type() == QVariant::Int) {
return QVariant(-value.toInt());
}
return value;
}
XlibTouchpad::XlibTouchpad(Display *display, int deviceId)
: m_display(display)
, m_connection(XGetXCBConnection(display))
, m_deviceId(deviceId)
{
m_floatType.intern(m_connection, "FLOAT");
m_enabledAtom.intern(m_connection, XI_PROP_ENABLED);
}
bool XlibTouchpad::applyConfig(const QVariantHash &p)
{
m_props.clear();
bool error = false;
for (const QString &name : qAsConst(m_supported)) {
QVariantHash::ConstIterator i = p.find(name);
if (i == p.end()) {
continue;
}
const Parameter *par = findParameter(name);
if (par) {
QVariant value(i.value());
double k = getPropertyScale(name);
if (k != 1.0) {
bool ok = false;
value = QVariant(value.toDouble(&ok) * k);
if (!ok) {
error = true;
continue;
}
}
if (m_negate.contains(name)) {
QVariantHash::ConstIterator i = p.find(m_negate[name]);
if (i != p.end() && i.value().toBool()) {
value = negateVariant(value);
}
}
if (name == "CoastingSpeed") {
QVariantHash::ConstIterator coastingEnabled = p.find("Coasting");
if (coastingEnabled != p.end() && !coastingEnabled.value().toBool()) {
value = QVariant(0);
}
}
if (!setParameter(par, value)) {
error = true;
}
}
}
flush();
return !error;
}
bool XlibTouchpad::getConfig(QVariantHash &p)
{
if (m_supported.isEmpty()) {
return false;
}
m_props.clear();
bool error = false;
for (const QString &name : qAsConst(m_supported)) {
const Parameter *par = findParameter(name);
if (!par) {
continue;
}
QVariant value(getParameter(par));
if (!value.isValid()) {
error = true;
continue;
}
double k = getPropertyScale(name);
if (k != 1.0) {
bool ok = false;
value = QVariant(value.toDouble(&ok) / k);
if (!ok) {
error = true;
continue;
}
}
if (m_negate.contains(name)) {
bool negative = value.toDouble() < 0.0;
p[m_negate[name]] = QVariant(negative);
if (negative) {
value = negateVariant(value);
}
}
if (name == "CoastingSpeed") {
bool coasting = value.toDouble() != 0.0;
p["Coasting"] = QVariant(coasting);
if (!coasting) {
continue;
}
}
p[name] = value;
}
return !error;
}
void XlibTouchpad::loadSupportedProperties(const Parameter *props)
{
m_paramList = props;
for (const Parameter *param = props; param->name; param++) {
QLatin1String name(param->prop_name);
if (!m_atoms.contains(name)) {
m_atoms.insert(name, QSharedPointer<XcbAtom>(new XcbAtom(m_connection, param->prop_name)));
}
}
for (const Parameter *p = props; p->name; p++) {
if (getParameter(p).isValid()) {
m_supported.append(p->name);
}
}
}
QVariant XlibTouchpad::getParameter(const Parameter *par)
{
PropertyInfo *p = getDevProperty(QLatin1String(par->prop_name));
if (!p || par->prop_offset >= p->nitems) {
return QVariant();
}
return p->value(par->prop_offset);
}
void XlibTouchpad::flush()
{
for (const QLatin1String &name : qAsConst(m_changed)) {
m_props[name].set();
}
m_changed.clear();
XFlush(m_display);
}
double XlibTouchpad::getPropertyScale(const QString &name) const
{
Q_UNUSED(name);
return 1.0;
}
PropertyInfo *XlibTouchpad::getDevProperty(const QLatin1String &propName)
{
if (m_props.contains(propName)) {
return &m_props[propName];
}
if (!m_atoms.contains(propName) || !m_atoms[propName]) {
return nullptr;
}
xcb_atom_t prop = m_atoms[propName]->atom();
if (!prop) {
return nullptr;
}
PropertyInfo p(m_display, m_deviceId, prop, m_floatType.atom());
if (!p.b && !p.f && !p.i) {
return nullptr;
}
return &m_props.insert(propName, p).value();
}
bool XlibTouchpad::setParameter(const Parameter *par, const QVariant &value)
{
QLatin1String propName(par->prop_name);
PropertyInfo *p = getDevProperty(propName);
if (!p || par->prop_offset >= p->nitems) {
return false;
}
QVariant converted(value);
QVariant::Type convType = QVariant::Int;
if (p->f) {
convType = QVariant::Double;
} else if (value.type() == QVariant::Double) {
converted = QVariant(qRound(static_cast<qreal>(value.toDouble())));
}
if (!converted.convert(convType)) {
return false;
}
if (converted == p->value(par->prop_offset)) {
return true;
}
if (p->b) {
p->b[par->prop_offset] = static_cast<char>(converted.toInt());
} else if (p->i) {
p->i[par->prop_offset] = converted.toInt();
} else if (p->f) {
p->f[par->prop_offset] = converted.toDouble();
}
m_changed.insert(propName);
return true;
}
void XlibTouchpad::setEnabled(bool enable)
{
PropertyInfo enabled(m_display, m_deviceId, m_enabledAtom.atom(), 0);
if (enabled.b && *(enabled.b) != enable) {
*(enabled.b) = enable;
enabled.set();
}
flush();
}
bool XlibTouchpad::enabled()
{
PropertyInfo enabled(m_display, m_deviceId, m_enabledAtom.atom(), 0);
return enabled.value(0).toBool();
}
const Parameter *XlibTouchpad::findParameter(const QString &name)
{
for (const Parameter *par = m_paramList; par->name; par++) {
if (name == par->name) {
return par;
}
}
return nullptr;
}