Warning, file /plasma/wacomtablet/src/kded/xinputadaptor.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 /* 0002 * This file is part of the KDE wacomtablet project. For copyright 0003 * information and license terms see the AUTHORS and COPYING files 0004 * in the top-level directory of this distribution. 0005 * 0006 * This program is free software; you can redistribute it and/or 0007 * modify it under the terms of the GNU General Public License as 0008 * published by the Free Software Foundation; either version 2 of 0009 * the License, or (at your option) any later version. 0010 * 0011 * This program is distributed in the hope that it will be useful, 0012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0014 * GNU General Public License for more details. 0015 * 0016 * You should have received a copy of the GNU General Public License 0017 * along with this program. If not, see <http://www.gnu.org/licenses/>. 0018 */ 0019 0020 #include "xinputadaptor.h" 0021 0022 #include "logging.h" 0023 #include "screensinfo.h" 0024 #include "screenspace.h" 0025 #include "stringutils.h" 0026 #include "x11input.h" 0027 #include "x11inputdevice.h" 0028 #include "x11wacom.h" 0029 #include "xinputproperty.h" 0030 0031 #include <QApplication> 0032 0033 using namespace Wacom; 0034 0035 namespace Wacom 0036 { 0037 class XinputAdaptorPrivate 0038 { 0039 public: 0040 QString deviceName; 0041 X11InputDevice device; 0042 }; // CLASS 0043 } // NAMESPACE 0044 0045 XinputAdaptor::XinputAdaptor(const QString &deviceName) 0046 : PropertyAdaptor(nullptr) 0047 , d_ptr(new XinputAdaptorPrivate) 0048 { 0049 Q_D(XinputAdaptor); 0050 d->deviceName = deviceName; 0051 X11Input::findDevice(deviceName, d->device); 0052 } 0053 0054 XinputAdaptor::~XinputAdaptor() 0055 { 0056 delete this->d_ptr; 0057 } 0058 0059 const QList<Property> XinputAdaptor::getProperties() const 0060 { 0061 return XinputProperty::ids(); 0062 } 0063 0064 const QString XinputAdaptor::getProperty(const Property &property) const 0065 { 0066 Q_D(const XinputAdaptor); 0067 0068 const XinputProperty *xinputproperty = XinputProperty::map(property); 0069 0070 if (!xinputproperty) { 0071 qCWarning(KDED) << QString::fromLatin1("Can not get unsupported property '%1' from device '%2' using xinput!").arg(property.key()).arg(d->deviceName); 0072 return QString(); 0073 } 0074 0075 if (!d->device.isOpen()) { 0076 qCWarning(KDED) 0077 << QString::fromLatin1("Can not get property '%1' from device '%2' because the device is not available!").arg(property.key()).arg(d->deviceName); 0078 return QString(); 0079 } 0080 0081 return getProperty(*xinputproperty); 0082 } 0083 0084 bool XinputAdaptor::setProperty(const Property &property, const QString &value) 0085 { 0086 Q_D(const XinputAdaptor); 0087 0088 qCDebug(KDED) << QString::fromLatin1("Setting property '%1' to '%2'.").arg(property.key()).arg(value); 0089 0090 const XinputProperty *xinputproperty = XinputProperty::map(property); 0091 0092 if (!xinputproperty) { 0093 qCWarning(KDED) << QString::fromLatin1("Can not set unsupported property '%1' to '%2' on device '%3' using xinput!") 0094 .arg(property.key()) 0095 .arg(value) 0096 .arg(d->deviceName); 0097 return false; 0098 } 0099 0100 if (!d->device.isOpen()) { 0101 qCWarning(KDED) << QString::fromLatin1("Can not set property '%1' to '%2' on device '%3' because the device is not available!") 0102 .arg(property.key()) 0103 .arg(value) 0104 .arg(d->deviceName); 0105 return false; 0106 } 0107 0108 return setProperty(*xinputproperty, value); 0109 } 0110 0111 bool XinputAdaptor::supportsProperty(const Property &property) const 0112 { 0113 return (XinputProperty::map(property) != nullptr); 0114 } 0115 0116 const QString XinputAdaptor::getProperty(const XinputProperty &property) const 0117 { 0118 Q_D(const XinputAdaptor); 0119 0120 if (property == XinputProperty::CursorAccelProfile) { 0121 return getLongProperty(property); 0122 0123 } else if (property == XinputProperty::CursorAccelAdaptiveDeceleration) { 0124 return getFloatProperty(property); 0125 0126 } else if (property == XinputProperty::CursorAccelConstantDeceleration) { 0127 return getFloatProperty(property); 0128 0129 } else if (property == XinputProperty::CursorAccelVelocityScaling) { 0130 return getFloatProperty(property); 0131 0132 } else if (property == XinputProperty::InvertScroll) { 0133 return (X11Wacom::isScrollDirectionInverted(d->deviceName) ? QLatin1String("on") : QLatin1String("off")); 0134 0135 } else { 0136 qCWarning(KDED) << QString::fromLatin1("Getting Xinput property '%1' is not yet implemented!").arg(property.key()); 0137 } 0138 0139 return QString(); 0140 } 0141 0142 const QString XinputAdaptor::getFloatProperty(const XinputProperty &property, long nelements) const 0143 { 0144 Q_D(const XinputAdaptor); 0145 0146 QList<float> values; 0147 0148 if (!d->device.getFloatProperty(property.key(), values, nelements)) { 0149 qCWarning(KDED) << QString::fromLatin1("Failed to get Xinput property '%1' from device '%2'!").arg(property.key()).arg(d->deviceName); 0150 return QString(); 0151 } 0152 0153 return numbersToString<float>(values); 0154 } 0155 0156 const QString XinputAdaptor::getLongProperty(const XinputProperty &property, long nelements) const 0157 { 0158 Q_D(const XinputAdaptor); 0159 0160 QList<long> values; 0161 0162 if (!d->device.getLongProperty(property.key(), values, nelements)) { 0163 qCWarning(KDED) << QString::fromLatin1("Failed to get Xinput property '%1' from device '%2'!").arg(property.key()).arg(d->deviceName); 0164 return QString(); 0165 } 0166 0167 return numbersToString<long>(values); 0168 } 0169 0170 bool XinputAdaptor::mapTabletToScreen(const QString &screenArea) const 0171 { 0172 Q_D(const XinputAdaptor); 0173 0174 // what we need is the Coordinate Transformation Matrix 0175 // in the normal case where the whole screen is used we end up with a 3x3 identity matrix 0176 // in our case we want to change that 0177 // | w 0 offsetX | 0178 // | 0 h offsetY | 0179 // | 0 0 1 | 0180 0181 qCDebug(KDED) << "Mapping to area: " << screenArea; 0182 0183 if (screenArea.isEmpty()) { 0184 return false; // nothing to do 0185 } 0186 0187 // get the space the user wants to use to map the tablet 0188 QRect screenAreaGeometry; 0189 QRect fullScreenGeometry = ScreensInfo::getUnifiedDisplayGeometry(); 0190 ScreenSpace screenSpace(screenArea); 0191 0192 switch (screenSpace.getType()) { 0193 case Wacom::ScreenSpace::ScreenSpaceType::Desktop: { 0194 qCDebug(KDED) << "Full screen area selected: " << fullScreenGeometry; 0195 screenAreaGeometry = fullScreenGeometry; 0196 0197 break; 0198 } 0199 case Wacom::ScreenSpace::ScreenSpaceType::Output: { 0200 auto output = screenSpace.toString(); 0201 QMap<QString, QRect> screenList = ScreensInfo::getScreenGeometries(); 0202 0203 if (!screenList.contains(output)) { 0204 qCDebug(KDED) << "Selected monitor no longer connected - using full screen: " << fullScreenGeometry; 0205 screenAreaGeometry = fullScreenGeometry; 0206 } else { 0207 qCDebug(KDED) << "Use monitor geometry for screen " << output << ": " << screenList.value(output); 0208 screenAreaGeometry = screenList.value(output); 0209 } 0210 0211 break; 0212 } 0213 case Wacom::ScreenSpace::ScreenSpaceType::Area: { 0214 screenAreaGeometry = screenSpace.getArea(); 0215 qCDebug(KDED) << "Geometry selected: " << screenAreaGeometry; 0216 break; 0217 } 0218 case Wacom::ScreenSpace::ScreenSpaceType::ArbitraryTranslationMatrix: { 0219 qCDebug(KDED) << "Arbitrary transformation matrix is selected" << screenSpace.getSpeed(); 0220 0221 return X11Wacom::setCoordinateTransformationMatrix(d->deviceName, 0, 0, screenSpace.getSpeed().x(), screenSpace.getSpeed().y()); 0222 } 0223 } 0224 0225 // calculate the new transformation matrix 0226 int screenX = screenAreaGeometry.x(); 0227 int screenY = screenAreaGeometry.y(); 0228 int screenW = screenAreaGeometry.width(); 0229 int screenH = screenAreaGeometry.height(); 0230 0231 qreal w = static_cast<qreal>(screenW) / fullScreenGeometry.width(); 0232 qreal h = static_cast<qreal>(screenH) / fullScreenGeometry.height(); 0233 0234 qreal offsetX = static_cast<qreal>(screenX) / fullScreenGeometry.width(); 0235 qreal offsetY = static_cast<qreal>(screenY) / fullScreenGeometry.height(); 0236 0237 qCDebug(KDED) << "Apply Coordinate Transformation Matrix"; 0238 qCDebug(KDED) << w << "0" << offsetX; 0239 qCDebug(KDED) << "0" << h << offsetY; 0240 qCDebug(KDED) << "0" 0241 << "0" 0242 << "1"; 0243 0244 return X11Wacom::setCoordinateTransformationMatrix(d->deviceName, offsetX, offsetY, w, h); 0245 } 0246 0247 template<typename T> 0248 const QString XinputAdaptor::numbersToString(const QList<T> &values) const 0249 { 0250 QString result; 0251 0252 for (int i = 0; i < values.size(); ++i) { 0253 if (i > 0) { 0254 result += QLatin1String(" "); 0255 } 0256 0257 result += QString::number(values.at(i)); 0258 } 0259 0260 return result; 0261 } 0262 0263 bool XinputAdaptor::setProperty(const XinputProperty &property, const QString &value) const 0264 { 0265 Q_D(const XinputAdaptor); 0266 0267 if (property == XinputProperty::CursorAccelProfile) { 0268 return d->device.setLongProperty(property.key(), value); 0269 0270 } else if (property == XinputProperty::CursorAccelAdaptiveDeceleration) { 0271 return d->device.setFloatProperty(property.key(), value); 0272 0273 } else if (property == XinputProperty::CursorAccelConstantDeceleration) { 0274 return d->device.setFloatProperty(property.key(), value); 0275 0276 } else if (property == XinputProperty::CursorAccelVelocityScaling) { 0277 return d->device.setFloatProperty(property.key(), value); 0278 0279 } else if (property == XinputProperty::InvertScroll) { 0280 return X11Wacom::setScrollDirection(d->deviceName, StringUtils::asBool(value)); 0281 0282 } else if (property == XinputProperty::ScreenSpace) { 0283 return mapTabletToScreen(value); 0284 0285 } else { 0286 qCWarning(KDED) << QString::fromLatin1("Setting Xinput property '%1' is not yet implemented!").arg(property.key()); 0287 } 0288 0289 return false; 0290 }