File indexing completed on 2024-05-12 17:07:21

0001 /*
0002     SPDX-FileCopyrightText: 2018 Roman Gilg <subdiff@gmail.com>
0003     SPDX-FileCopyrightText: 2021 Aleix Pol Gonzalez <aleixpol@kde.org>
0004 
0005     SPDX-License-Identifier: GPL-2.0-or-later
0006 */
0007 
0008 #pragma once
0009 
0010 #include "InputDevice_interface.h"
0011 
0012 #include <QObject>
0013 #include <QString>
0014 
0015 #include <optional>
0016 
0017 class InputDevice : public QObject
0018 {
0019     Q_OBJECT
0020 
0021     Q_PROPERTY(QString sysName READ sysName CONSTANT)
0022     Q_PROPERTY(QString name READ name CONSTANT)
0023     Q_PROPERTY(QSizeF size READ size CONSTANT)
0024     Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled NOTIFY enabledChanged)
0025     Q_PROPERTY(bool supportsLeftHanded READ supportsLeftHanded CONSTANT)
0026     Q_PROPERTY(bool leftHanded READ isLeftHanded WRITE setLeftHanded NOTIFY leftHandedChanged)
0027 
0028     Q_PROPERTY(bool supportsOrientation READ supportsOrientation CONSTANT)
0029     Q_PROPERTY(int orientation READ orientation WRITE setOrientation NOTIFY orientationChanged)
0030     Q_PROPERTY(QString outputName READ outputName WRITE setOutputName NOTIFY outputNameChanged)
0031     Q_PROPERTY(QRectF outputArea READ outputArea WRITE setOutputArea NOTIFY outputAreaChanged)
0032 
0033 public:
0034     InputDevice(const QString &dbusName, QObject *parent);
0035 
0036     void load();
0037     void save();
0038     void defaults();
0039     bool isSaveNeeded() const;
0040     bool isDefaults() const;
0041 
0042     QString name() const
0043     {
0044         return m_name.value();
0045     }
0046 
0047     QString sysName() const
0048     {
0049         return m_sysName.value();
0050     }
0051     bool isLeftHanded() const
0052     {
0053         return m_leftHanded.value();
0054     }
0055     bool supportsLeftHanded() const
0056     {
0057         return m_leftHanded.isSupported();
0058     }
0059     void setLeftHanded(bool set);
0060 
0061     bool supportsOrientation() const
0062     {
0063         return m_orientation.isSupported();
0064     }
0065     int orientation() const
0066     {
0067         return m_orientation.value();
0068     }
0069     void setOrientation(int ori);
0070 
0071     QString outputName() const
0072     {
0073         return m_outputName.value();
0074     }
0075     void setOutputName(const QString &outputName);
0076     QSizeF size() const
0077     {
0078         return m_size.value();
0079     }
0080 
0081     QRectF outputArea() const
0082     {
0083         return m_outputArea.value();
0084     }
0085     void setOutputArea(const QRectF &outputArea);
0086 
0087     bool isEnabled() const
0088     {
0089         return m_enabled.value();
0090     }
0091 
0092     void setEnabled(bool enabled);
0093 
0094 Q_SIGNALS:
0095     void needsSaveChanged();
0096 
0097     void leftHandedChanged();
0098     void orientationChanged();
0099     void outputNameChanged();
0100     void outputAreaChanged();
0101     void enabledChanged();
0102 
0103 private:
0104     template<typename T>
0105     struct Prop {
0106         typedef T (OrgKdeKWinInputDeviceInterface::*ValueFunction)() const;
0107         typedef bool (OrgKdeKWinInputDeviceInterface::*SupportedFunction)() const;
0108         typedef bool (OrgKdeKWinInputDeviceInterface::*SetterFunction)(const T &value);
0109         typedef void (InputDevice::*ChangedSignal)();
0110 
0111         explicit Prop(InputDevice *device, const char *propName, ValueFunction defaultValueFunction, SupportedFunction supported, ChangedSignal changedSignal)
0112             : m_defaultValueFunction(defaultValueFunction)
0113             , m_supportedFunction(supported)
0114             , m_changedSignalFunction(changedSignal)
0115             , m_device(device)
0116         {
0117             int idx = OrgKdeKWinInputDeviceInterface::staticMetaObject.indexOfProperty(propName);
0118             if (idx < 0) {
0119                 qDebug() << "there is no" << propName;
0120             }
0121             Q_ASSERT(idx >= 0);
0122             m_prop = OrgKdeKWinInputDeviceInterface::staticMetaObject.property(idx);
0123         }
0124 
0125         explicit Prop(InputDevice *device, const char *propName)
0126             : m_defaultValueFunction(nullptr)
0127             , m_supportedFunction(nullptr)
0128             , m_changedSignalFunction(nullptr)
0129             , m_device(device)
0130         {
0131             Q_ASSERT(m_device);
0132             int idx = OrgKdeKWinInputDeviceInterface::staticMetaObject.indexOfProperty(propName);
0133             Q_ASSERT(idx >= 0);
0134             m_prop = OrgKdeKWinInputDeviceInterface::staticMetaObject.property(idx);
0135         }
0136 
0137         T value() const
0138         {
0139             if (!m_value.has_value()) {
0140                 auto iface = m_device->m_iface.get();
0141                 if (isSupported()) {
0142                     m_value = m_prop.read(iface).value<T>();
0143                 }
0144             }
0145             return m_value ? m_value.value() : T();
0146         }
0147         void resetFromDefaults()
0148         {
0149             if (isSupported()) {
0150                 set(defaultValue());
0151             }
0152         }
0153         void resetFromSaved()
0154         {
0155             m_value = {};
0156             value();
0157             m_configValue = m_value;
0158             if (m_changedSignalFunction) {
0159                 (m_device->*m_changedSignalFunction)();
0160             }
0161         }
0162 
0163         void set(T newVal);
0164         T defaultValue() const
0165         {
0166             return m_defaultValueFunction ? (m_device->m_iface.get()->*m_defaultValueFunction)() : T();
0167         }
0168         bool changed() const;
0169         void set(const Prop<T> &p)
0170         {
0171             set(p.value);
0172         }
0173 
0174         bool isSupported() const
0175         {
0176             auto iface = m_device->m_iface.get();
0177             return !m_supportedFunction || (iface->*m_supportedFunction)();
0178         }
0179 
0180         bool save();
0181         bool isDefaults() const
0182         {
0183             return m_value == defaultValue();
0184         }
0185 
0186     private:
0187         QMetaProperty m_prop;
0188         const ValueFunction m_defaultValueFunction;
0189         const SupportedFunction m_supportedFunction;
0190         const ChangedSignal m_changedSignalFunction;
0191         InputDevice *const m_device;
0192         mutable std::optional<T> m_configValue;
0193         mutable std::optional<T> m_value;
0194     };
0195 
0196     //
0197     // general
0198     Prop<QString> m_name = Prop<QString>(this, "name");
0199     Prop<QSizeF> m_size = Prop<QSizeF>(this, "size");
0200     Prop<QString> m_sysName = Prop<QString>(this, "sysName");
0201 
0202     Prop<bool> m_leftHanded = Prop<bool>(this,
0203                                          "leftHanded",
0204                                          &OrgKdeKWinInputDeviceInterface::leftHandedEnabledByDefault,
0205                                          &OrgKdeKWinInputDeviceInterface::supportsLeftHanded,
0206                                          &InputDevice::leftHandedChanged);
0207     Prop<int> m_orientation =
0208         Prop<int>(this, "orientationDBus", nullptr, &OrgKdeKWinInputDeviceInterface::supportsCalibrationMatrix, &InputDevice::orientationChanged);
0209     Prop<bool> m_enabled = Prop<bool>(this, "enabled", &OrgKdeKWinInputDeviceInterface::enabledByDefault, nullptr, &InputDevice::enabledChanged);
0210 
0211     Prop<QString> m_outputName = Prop<QString>(this, "outputName", nullptr, nullptr, &InputDevice::outputNameChanged);
0212     Prop<QRectF> m_outputArea = Prop<QRectF>(this,
0213                                              "outputArea",
0214                                              &OrgKdeKWinInputDeviceInterface::defaultOutputArea,
0215                                              &OrgKdeKWinInputDeviceInterface::supportsOutputArea,
0216                                              &InputDevice::outputAreaChanged);
0217 
0218     std::unique_ptr<OrgKdeKWinInputDeviceInterface> m_iface;
0219 };