File indexing completed on 2024-11-10 04:56:32
0001 /* 0002 KWin - the KDE window manager 0003 This file is part of the KDE project. 0004 0005 SPDX-FileCopyrightText: 2016 Martin Gräßlin <mgraesslin@kde.org> 0006 0007 SPDX-License-Identifier: GPL-2.0-or-later 0008 */ 0009 #include "device.h" 0010 0011 #include <config-kwin.h> 0012 0013 #include "core/output.h" 0014 #include "core/outputbackend.h" 0015 #include "libinput_logging.h" 0016 #include "main.h" 0017 #include "mousebuttons.h" 0018 #include "pointer_input.h" 0019 0020 #include <QDBusArgument> 0021 #include <QDBusConnection> 0022 #include <QDBusMetaType> 0023 0024 #include <linux/input.h> 0025 0026 QDBusArgument &operator<<(QDBusArgument &argument, const QMatrix4x4 &matrix) 0027 { 0028 argument.beginArray(qMetaTypeId<double>()); 0029 for (quint8 row = 0; row < 4; ++row) { 0030 for (quint8 col = 0; col < 4; ++col) { 0031 argument << matrix(row, col); 0032 } 0033 } 0034 argument.endArray(); 0035 return argument; 0036 } 0037 0038 const QDBusArgument &operator>>(const QDBusArgument &argument, QMatrix4x4 &matrix) 0039 { 0040 argument.beginArray(); 0041 for (quint8 row = 0; row < 4; ++row) { 0042 for (quint8 col = 0; col < 4; ++col) { 0043 double val; 0044 argument >> val; 0045 matrix(row, col) = val; 0046 } 0047 } 0048 argument.endArray(); 0049 return argument; 0050 } 0051 0052 namespace KWin 0053 { 0054 namespace LibInput 0055 { 0056 0057 static bool checkAlphaNumericKeyboard(libinput_device *device) 0058 { 0059 for (uint i = KEY_1; i <= KEY_0; i++) { 0060 if (libinput_device_keyboard_has_key(device, i) == 0) { 0061 return false; 0062 } 0063 } 0064 for (uint i = KEY_Q; i <= KEY_P; i++) { 0065 if (libinput_device_keyboard_has_key(device, i) == 0) { 0066 return false; 0067 } 0068 } 0069 for (uint i = KEY_A; i <= KEY_L; i++) { 0070 if (libinput_device_keyboard_has_key(device, i) == 0) { 0071 return false; 0072 } 0073 } 0074 for (uint i = KEY_Z; i <= KEY_M; i++) { 0075 if (libinput_device_keyboard_has_key(device, i) == 0) { 0076 return false; 0077 } 0078 } 0079 return true; 0080 } 0081 0082 enum class ConfigKey { 0083 Enabled, 0084 LeftHanded, 0085 DisableWhileTyping, 0086 PointerAcceleration, 0087 PointerAccelerationProfile, 0088 TapToClick, 0089 LmrTapButtonMap, 0090 TapAndDrag, 0091 TapDragLock, 0092 MiddleButtonEmulation, 0093 NaturalScroll, 0094 ScrollMethod, 0095 ScrollButton, 0096 ClickMethod, 0097 ScrollFactor, 0098 Orientation, 0099 Calibration, 0100 OutputName, 0101 OutputArea, 0102 MapToWorkspace 0103 }; 0104 0105 struct ConfigDataBase 0106 { 0107 ConfigDataBase(const QByteArray &_key) 0108 : key(_key) 0109 { 0110 } 0111 virtual ~ConfigDataBase() = default; 0112 0113 QByteArray key; 0114 virtual void read(Device * /*device*/, const KConfigGroup & /*values*/) const = 0; 0115 }; 0116 0117 template<typename T> 0118 struct ConfigData : public ConfigDataBase 0119 { 0120 using SetterFunction = std::function<void(Device *, const T &)>; 0121 using DefaultValueFunction = std::function<T(Device *)>; 0122 0123 explicit ConfigData(const QByteArray &_key, const SetterFunction &_setter, const DefaultValueFunction &_defaultValue) 0124 : ConfigDataBase(_key) 0125 , setterFunction(_setter) 0126 , defaultValueFunction(_defaultValue) 0127 { 0128 } 0129 0130 void read(Device *device, const KConfigGroup &values) const override 0131 { 0132 if (!setterFunction || !defaultValueFunction) { 0133 return; 0134 } 0135 0136 setterFunction(device, values.readEntry(key.constData(), defaultValueFunction(device))); 0137 } 0138 0139 SetterFunction setterFunction; 0140 DefaultValueFunction defaultValueFunction; 0141 }; 0142 0143 // Template specializations for some specific config types that can't be handled 0144 // through plain readEntry. 0145 // 0146 // This uses tagged types to avoid specialising the general type since we 0147 // directly call the getters/setters. 0148 0149 using DeviceOrientation = Qt::ScreenOrientation; 0150 0151 template<> 0152 struct ConfigData<DeviceOrientation> : public ConfigDataBase 0153 { 0154 explicit ConfigData() 0155 : ConfigDataBase(QByteArrayLiteral("Orientation")) 0156 { 0157 } 0158 0159 void read(Device *device, const KConfigGroup &values) const override 0160 { 0161 int defaultValue = device->defaultOrientation(); 0162 device->setOrientation(static_cast<Qt::ScreenOrientation>(values.readEntry(key.constData(), defaultValue))); 0163 } 0164 }; 0165 0166 using CalibrationMatrix = QMatrix4x4; 0167 0168 template<> 0169 struct ConfigData<CalibrationMatrix> : public ConfigDataBase 0170 { 0171 explicit ConfigData() 0172 : ConfigDataBase(QByteArrayLiteral("CalibrationMatrix")) 0173 { 0174 } 0175 0176 void read(Device *device, const KConfigGroup &values) const override 0177 { 0178 if (values.hasKey(key.constData())) { 0179 auto list = values.readEntry(key.constData(), QList<float>()); 0180 if (list.size() == 16) { 0181 device->setCalibrationMatrix(QMatrix4x4{list.constData()}); 0182 return; 0183 } 0184 } 0185 0186 device->setCalibrationMatrix(device->defaultCalibrationMatrix()); 0187 } 0188 }; 0189 0190 static const QMap<ConfigKey, std::shared_ptr<ConfigDataBase>> s_configData{ 0191 {ConfigKey::Enabled, std::make_shared<ConfigData<bool>>(QByteArrayLiteral("Enabled"), &Device::setEnabled, &Device::isEnabledByDefault)}, 0192 {ConfigKey::LeftHanded, std::make_shared<ConfigData<bool>>(QByteArrayLiteral("LeftHanded"), &Device::setLeftHanded, &Device::leftHandedEnabledByDefault)}, 0193 {ConfigKey::DisableWhileTyping, std::make_shared<ConfigData<bool>>(QByteArrayLiteral("DisableWhileTyping"), &Device::setDisableWhileTyping, &Device::disableWhileTypingEnabledByDefault)}, 0194 {ConfigKey::PointerAcceleration, std::make_shared<ConfigData<QString>>(QByteArrayLiteral("PointerAcceleration"), &Device::setPointerAccelerationFromString, &Device::defaultPointerAccelerationToString)}, 0195 {ConfigKey::PointerAccelerationProfile, std::make_shared<ConfigData<quint32>>(QByteArrayLiteral("PointerAccelerationProfile"), &Device::setPointerAccelerationProfileFromInt, &Device::defaultPointerAccelerationProfileToInt)}, 0196 {ConfigKey::TapToClick, std::make_shared<ConfigData<bool>>(QByteArrayLiteral("TapToClick"), &Device::setTapToClick, &Device::tapToClickEnabledByDefault)}, 0197 {ConfigKey::TapAndDrag, std::make_shared<ConfigData<bool>>(QByteArrayLiteral("TapAndDrag"), &Device::setTapAndDrag, &Device::tapAndDragEnabledByDefault)}, 0198 {ConfigKey::TapDragLock, std::make_shared<ConfigData<bool>>(QByteArrayLiteral("TapDragLock"), &Device::setTapDragLock, &Device::tapDragLockEnabledByDefault)}, 0199 {ConfigKey::MiddleButtonEmulation, std::make_shared<ConfigData<bool>>(QByteArrayLiteral("MiddleButtonEmulation"), &Device::setMiddleEmulation, &Device::middleEmulationEnabledByDefault)}, 0200 {ConfigKey::LmrTapButtonMap, std::make_shared<ConfigData<bool>>(QByteArrayLiteral("LmrTapButtonMap"), &Device::setLmrTapButtonMap, &Device::lmrTapButtonMapEnabledByDefault)}, 0201 {ConfigKey::NaturalScroll, std::make_shared<ConfigData<bool>>(QByteArrayLiteral("NaturalScroll"), &Device::setNaturalScroll, &Device::naturalScrollEnabledByDefault)}, 0202 {ConfigKey::ScrollMethod, std::make_shared<ConfigData<quint32>>(QByteArrayLiteral("ScrollMethod"), &Device::activateScrollMethodFromInt, &Device::defaultScrollMethodToInt)}, 0203 {ConfigKey::ScrollButton, std::make_shared<ConfigData<quint32>>(QByteArrayLiteral("ScrollButton"), &Device::setScrollButton, &Device::defaultScrollButton)}, 0204 {ConfigKey::ClickMethod, std::make_shared<ConfigData<quint32>>(QByteArrayLiteral("ClickMethod"), &Device::setClickMethodFromInt, &Device::defaultClickMethodToInt)}, 0205 {ConfigKey::ScrollFactor, std::make_shared<ConfigData<qreal>>(QByteArrayLiteral("ScrollFactor"), &Device::setScrollFactor, &Device::scrollFactorDefault)}, 0206 {ConfigKey::Orientation, std::make_shared<ConfigData<DeviceOrientation>>()}, 0207 {ConfigKey::Calibration, std::make_shared<ConfigData<CalibrationMatrix>>()}, 0208 {ConfigKey::OutputName, std::make_shared<ConfigData<QString>>(QByteArrayLiteral("OutputName"), &Device::setOutputName, &Device::defaultOutputName)}, 0209 {ConfigKey::OutputArea, std::make_shared<ConfigData<QRectF>>(QByteArrayLiteral("OutputArea"), &Device::setOutputArea, &Device::defaultOutputArea)}, 0210 {ConfigKey::MapToWorkspace, std::make_shared<ConfigData<bool>>(QByteArrayLiteral("MapToWorkspace"), &Device::setMapToWorkspace, &Device::defaultMapToWorkspace)}, 0211 }; 0212 0213 namespace 0214 { 0215 QMatrix4x4 getMatrix(libinput_device *device, std::function<int(libinput_device *, float[6])> getter) 0216 { 0217 float matrix[6]; 0218 if (!getter(device, matrix)) { 0219 return {}; 0220 } 0221 return QMatrix4x4{ 0222 matrix[0], matrix[1], matrix[2], 0.0f, 0223 matrix[3], matrix[4], matrix[5], 0.0f, 0224 0.0f, 0.0f, 1.0f, 0.0f, 0225 0.0f, 0.0f, 0.0f, 1.0f}; 0226 } 0227 0228 bool setOrientedCalibrationMatrix(libinput_device *device, QMatrix4x4 matrix, Qt::ScreenOrientation orientation) 0229 { 0230 // 90 deg cw 0231 static const QMatrix4x4 portraitMatrix{ 0232 0.0f, -1.0f, 1.0f, 0.0f, 0233 1.0f, 0.0f, 0.0f, 0.0f, 0234 0.0f, 0.0f, 1.0f, 0.0f, 0235 0.0f, 0.0f, 0.0f, 1.0f}; 0236 // 180 deg cw 0237 static const QMatrix4x4 invertedLandscapeMatrix{ 0238 -1.0f, 0.0f, 1.0f, 0.0f, 0239 0.0f, -1.0f, 1.0f, 0.0f, 0240 0.0f, 0.0f, 1.0f, 0.0f, 0241 0.0f, 0.0f, 0.0f, 1.0f}; 0242 // 270 deg cw 0243 static const QMatrix4x4 invertedPortraitMatrix{ 0244 0.0f, 1.0f, 0.0f, 0.0f, 0245 -1.0f, 0.0f, 1.0f, 0.0f, 0246 0.0f, 0.0f, 1.0f, 0.0f, 0247 0.0f, 0.0f, 0.0f, 1.0f}; 0248 0249 switch (orientation) { 0250 case Qt::PortraitOrientation: 0251 matrix *= portraitMatrix; 0252 break; 0253 case Qt::InvertedLandscapeOrientation: 0254 matrix *= invertedLandscapeMatrix; 0255 break; 0256 case Qt::InvertedPortraitOrientation: 0257 matrix *= invertedPortraitMatrix; 0258 break; 0259 case Qt::PrimaryOrientation: 0260 case Qt::LandscapeOrientation: 0261 default: 0262 break; 0263 } 0264 0265 float data[6]{matrix(0, 0), matrix(0, 1), matrix(0, 2), matrix(1, 0), matrix(1, 1), matrix(1, 2)}; 0266 return libinput_device_config_calibration_set_matrix(device, data) == LIBINPUT_CONFIG_STATUS_SUCCESS; 0267 } 0268 } 0269 0270 Device::Device(libinput_device *device, QObject *parent) 0271 : InputDevice(parent) 0272 , m_device(device) 0273 , m_keyboard(libinput_device_has_capability(m_device, LIBINPUT_DEVICE_CAP_KEYBOARD)) 0274 , m_pointer(libinput_device_has_capability(m_device, LIBINPUT_DEVICE_CAP_POINTER)) 0275 , m_touch(libinput_device_has_capability(m_device, LIBINPUT_DEVICE_CAP_TOUCH)) 0276 , m_tabletTool(libinput_device_has_capability(m_device, LIBINPUT_DEVICE_CAP_TABLET_TOOL)) 0277 , m_tabletPad(libinput_device_has_capability(m_device, LIBINPUT_DEVICE_CAP_TABLET_PAD)) 0278 , m_supportsGesture(libinput_device_has_capability(m_device, LIBINPUT_DEVICE_CAP_GESTURE)) 0279 , m_switch(libinput_device_has_capability(m_device, LIBINPUT_DEVICE_CAP_SWITCH)) 0280 , m_lidSwitch(m_switch ? libinput_device_switch_has_switch(m_device, LIBINPUT_SWITCH_LID) : false) 0281 , m_tabletSwitch(m_switch ? libinput_device_switch_has_switch(m_device, LIBINPUT_SWITCH_TABLET_MODE) : false) 0282 , m_name(QString::fromLocal8Bit(libinput_device_get_name(m_device))) 0283 , m_sysName(QString::fromLocal8Bit(libinput_device_get_sysname(m_device))) 0284 , m_outputName(QString::fromLocal8Bit(libinput_device_get_output_name(m_device))) 0285 , m_product(libinput_device_get_id_product(m_device)) 0286 , m_vendor(libinput_device_get_id_vendor(m_device)) 0287 , m_tapFingerCount(libinput_device_config_tap_get_finger_count(m_device)) 0288 , m_defaultTapButtonMap(libinput_device_config_tap_get_default_button_map(m_device)) 0289 , m_tapButtonMap(libinput_device_config_tap_get_button_map(m_device)) 0290 , m_tapToClickEnabledByDefault(true) 0291 , m_tapToClick(libinput_device_config_tap_get_enabled(m_device)) 0292 , m_tapAndDragEnabledByDefault(true) 0293 , m_tapAndDrag(libinput_device_config_tap_get_drag_enabled(m_device)) 0294 , m_tapDragLockEnabledByDefault(libinput_device_config_tap_get_default_drag_lock_enabled(m_device)) 0295 , m_tapDragLock(libinput_device_config_tap_get_drag_lock_enabled(m_device)) 0296 , m_supportsDisableWhileTyping(libinput_device_config_dwt_is_available(m_device)) 0297 , m_supportsPointerAcceleration(libinput_device_config_accel_is_available(m_device)) 0298 , m_supportsLeftHanded(libinput_device_config_left_handed_is_available(m_device)) 0299 , m_supportsCalibrationMatrix(libinput_device_config_calibration_has_matrix(m_device)) 0300 , m_supportsDisableEvents(libinput_device_config_send_events_get_modes(m_device) & LIBINPUT_CONFIG_SEND_EVENTS_DISABLED) 0301 , m_supportsDisableEventsOnExternalMouse(libinput_device_config_send_events_get_modes(m_device) & LIBINPUT_CONFIG_SEND_EVENTS_DISABLED_ON_EXTERNAL_MOUSE) 0302 , m_supportsMiddleEmulation(libinput_device_config_middle_emulation_is_available(m_device)) 0303 , m_supportsNaturalScroll(libinput_device_config_scroll_has_natural_scroll(m_device)) 0304 , m_supportedScrollMethods(libinput_device_config_scroll_get_methods(m_device)) 0305 , m_leftHandedEnabledByDefault(libinput_device_config_left_handed_get_default(m_device)) 0306 , m_middleEmulationEnabledByDefault(libinput_device_config_middle_emulation_get_default_enabled(m_device) == LIBINPUT_CONFIG_MIDDLE_EMULATION_ENABLED) 0307 , m_naturalScrollEnabledByDefault(libinput_device_config_scroll_get_default_natural_scroll_enabled(m_device)) 0308 , m_defaultScrollMethod(libinput_device_config_scroll_get_default_method(m_device)) 0309 , m_defaultScrollButton(libinput_device_config_scroll_get_default_button(m_device)) 0310 , m_disableWhileTypingEnabledByDefault(libinput_device_config_dwt_get_default_enabled(m_device)) 0311 , m_disableWhileTyping(m_supportsDisableWhileTyping ? libinput_device_config_dwt_get_enabled(m_device) == LIBINPUT_CONFIG_DWT_ENABLED : false) 0312 , m_middleEmulation(libinput_device_config_middle_emulation_get_enabled(m_device) == LIBINPUT_CONFIG_MIDDLE_EMULATION_ENABLED) 0313 , m_leftHanded(m_supportsLeftHanded ? libinput_device_config_left_handed_get(m_device) : false) 0314 , m_naturalScroll(m_supportsNaturalScroll ? libinput_device_config_scroll_get_natural_scroll_enabled(m_device) : false) 0315 , m_scrollMethod(libinput_device_config_scroll_get_method(m_device)) 0316 , m_scrollButton(libinput_device_config_scroll_get_button(m_device)) 0317 , m_defaultPointerAcceleration(libinput_device_config_accel_get_default_speed(m_device)) 0318 , m_pointerAcceleration(libinput_device_config_accel_get_speed(m_device)) 0319 , m_scrollFactor(1.0) 0320 , m_supportedPointerAccelerationProfiles(libinput_device_config_accel_get_profiles(m_device)) 0321 , m_defaultPointerAccelerationProfile(libinput_device_config_accel_get_default_profile(m_device)) 0322 , m_pointerAccelerationProfile(libinput_device_config_accel_get_profile(m_device)) 0323 , m_enabled(m_supportsDisableEvents ? libinput_device_config_send_events_get_mode(m_device) == LIBINPUT_CONFIG_SEND_EVENTS_ENABLED : true) 0324 , m_config() 0325 , m_defaultCalibrationMatrix(getMatrix(m_device, &libinput_device_config_calibration_get_default_matrix)) 0326 , m_calibrationMatrix(getMatrix(m_device, &libinput_device_config_calibration_get_matrix)) 0327 , m_supportedClickMethods(libinput_device_config_click_get_methods(m_device)) 0328 , m_defaultClickMethod(libinput_device_config_click_get_default_method(m_device)) 0329 , m_clickMethod(libinput_device_config_click_get_method(m_device)) 0330 { 0331 libinput_device_ref(m_device); 0332 libinput_device_set_user_data(m_device, this); 0333 0334 qreal width = 0; 0335 qreal height = 0; 0336 if (libinput_device_get_size(m_device, &width, &height) == 0) { 0337 m_size = QSizeF(width, height); 0338 } 0339 if (m_pointer) { 0340 // 0x120 is the first joystick Button 0341 for (int button = BTN_LEFT; button < 0x120; ++button) { 0342 if (libinput_device_pointer_has_button(m_device, button)) { 0343 m_supportedButtons |= buttonToQtMouseButton(button); 0344 } 0345 } 0346 } 0347 0348 if (m_keyboard) { 0349 m_alphaNumericKeyboard = checkAlphaNumericKeyboard(m_device); 0350 } 0351 0352 if (m_supportsCalibrationMatrix && m_calibrationMatrix != m_defaultCalibrationMatrix) { 0353 float matrix[]{m_defaultCalibrationMatrix(0, 0), 0354 m_defaultCalibrationMatrix(0, 1), 0355 m_defaultCalibrationMatrix(0, 2), 0356 m_defaultCalibrationMatrix(1, 0), 0357 m_defaultCalibrationMatrix(1, 1), 0358 m_defaultCalibrationMatrix(1, 2)}; 0359 libinput_device_config_calibration_set_matrix(m_device, matrix); 0360 m_calibrationMatrix = m_defaultCalibrationMatrix; 0361 } 0362 0363 qDBusRegisterMetaType<QMatrix4x4>(); 0364 0365 QDBusConnection::sessionBus().registerObject(QStringLiteral("/org/kde/KWin/InputDevice/") + m_sysName, 0366 QStringLiteral("org.kde.KWin.InputDevice"), 0367 this, 0368 QDBusConnection::ExportAllProperties); 0369 } 0370 0371 Device::~Device() 0372 { 0373 QDBusConnection::sessionBus().unregisterObject(QStringLiteral("/org/kde/KWin/InputDevice/") + m_sysName); 0374 libinput_device_set_user_data(m_device, nullptr); 0375 libinput_device_unref(m_device); 0376 } 0377 0378 Device *Device::get(libinput_device *native) 0379 { 0380 return static_cast<Device *>(libinput_device_get_user_data(native)); 0381 } 0382 0383 template<typename T> 0384 void Device::writeEntry(const ConfigKey &key, const T &value) 0385 { 0386 if (!m_config.isValid()) { 0387 return; 0388 } 0389 if (m_loading) { 0390 return; 0391 } 0392 auto it = s_configData.find(key); 0393 Q_ASSERT(it != s_configData.end()); 0394 m_config.writeEntry(it.value()->key.constData(), value); 0395 m_config.sync(); 0396 } 0397 0398 void Device::loadConfiguration() 0399 { 0400 if (!m_config.isValid() && !m_defaultConfig.isValid()) { 0401 return; 0402 } 0403 0404 m_loading = true; 0405 for (auto it = s_configData.begin(), end = s_configData.end(); it != end; ++it) { 0406 (*it)->read(this, m_config); 0407 }; 0408 0409 m_loading = false; 0410 } 0411 0412 void Device::setPointerAcceleration(qreal acceleration) 0413 { 0414 if (!m_supportsPointerAcceleration) { 0415 return; 0416 } 0417 acceleration = std::clamp(acceleration, -1.0, 1.0); 0418 if (libinput_device_config_accel_set_speed(m_device, acceleration) == LIBINPUT_CONFIG_STATUS_SUCCESS) { 0419 if (m_pointerAcceleration != acceleration) { 0420 m_pointerAcceleration = acceleration; 0421 Q_EMIT pointerAccelerationChanged(); 0422 writeEntry(ConfigKey::PointerAcceleration, QString::number(acceleration, 'f', 3)); 0423 } 0424 } 0425 } 0426 0427 void Device::setScrollButton(quint32 button) 0428 { 0429 if (!(m_supportedScrollMethods & LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN)) { 0430 return; 0431 } 0432 if (libinput_device_config_scroll_set_button(m_device, button) == LIBINPUT_CONFIG_STATUS_SUCCESS) { 0433 if (m_scrollButton != button) { 0434 m_scrollButton = button; 0435 writeEntry(ConfigKey::ScrollButton, m_scrollButton); 0436 Q_EMIT scrollButtonChanged(); 0437 } 0438 } 0439 } 0440 0441 void Device::setPointerAccelerationProfile(bool set, enum libinput_config_accel_profile profile) 0442 { 0443 if (!(m_supportedPointerAccelerationProfiles & profile)) { 0444 return; 0445 } 0446 if (!set) { 0447 profile = (profile == LIBINPUT_CONFIG_ACCEL_PROFILE_FLAT) ? LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE : LIBINPUT_CONFIG_ACCEL_PROFILE_FLAT; 0448 if (!(m_supportedPointerAccelerationProfiles & profile)) { 0449 return; 0450 } 0451 } 0452 0453 if (libinput_device_config_accel_set_profile(m_device, profile) == LIBINPUT_CONFIG_STATUS_SUCCESS) { 0454 if (m_pointerAccelerationProfile != profile) { 0455 m_pointerAccelerationProfile = profile; 0456 Q_EMIT pointerAccelerationProfileChanged(); 0457 writeEntry(ConfigKey::PointerAccelerationProfile, (quint32)profile); 0458 } 0459 } 0460 } 0461 0462 void Device::setClickMethod(bool set, enum libinput_config_click_method method) 0463 { 0464 if (!(m_supportedClickMethods & method)) { 0465 return; 0466 } 0467 if (!set) { 0468 method = (method == LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS) ? LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER : LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS; 0469 if (!(m_supportedClickMethods & method)) { 0470 return; 0471 } 0472 } 0473 0474 if (libinput_device_config_click_set_method(m_device, method) == LIBINPUT_CONFIG_STATUS_SUCCESS) { 0475 if (m_clickMethod != method) { 0476 m_clickMethod = method; 0477 Q_EMIT clickMethodChanged(); 0478 writeEntry(ConfigKey::ClickMethod, (quint32)method); 0479 } 0480 } 0481 } 0482 0483 void Device::setScrollMethod(bool set, enum libinput_config_scroll_method method) 0484 { 0485 if (!(m_supportedScrollMethods & method)) { 0486 return; 0487 } 0488 0489 bool isCurrent = m_scrollMethod == method; 0490 if (!set) { 0491 if (isCurrent) { 0492 method = LIBINPUT_CONFIG_SCROLL_NO_SCROLL; 0493 isCurrent = false; 0494 } else { 0495 return; 0496 } 0497 } 0498 0499 if (libinput_device_config_scroll_set_method(m_device, method) == LIBINPUT_CONFIG_STATUS_SUCCESS) { 0500 if (!isCurrent) { 0501 m_scrollMethod = method; 0502 Q_EMIT scrollMethodChanged(); 0503 writeEntry(ConfigKey::ScrollMethod, (quint32)method); 0504 } 0505 } 0506 } 0507 0508 void Device::setLmrTapButtonMap(bool set) 0509 { 0510 enum libinput_config_tap_button_map map = set ? LIBINPUT_CONFIG_TAP_MAP_LMR : LIBINPUT_CONFIG_TAP_MAP_LRM; 0511 0512 if (m_tapFingerCount < 2) { 0513 return; 0514 } 0515 if (!set) { 0516 map = LIBINPUT_CONFIG_TAP_MAP_LRM; 0517 } 0518 0519 if (libinput_device_config_tap_set_button_map(m_device, map) == LIBINPUT_CONFIG_STATUS_SUCCESS) { 0520 if (m_tapButtonMap != map) { 0521 m_tapButtonMap = map; 0522 writeEntry(ConfigKey::LmrTapButtonMap, set); 0523 Q_EMIT tapButtonMapChanged(); 0524 } 0525 } 0526 } 0527 0528 int Device::stripsCount() const 0529 { 0530 return libinput_device_tablet_pad_get_num_strips(m_device); 0531 } 0532 0533 int Device::ringsCount() const 0534 { 0535 return libinput_device_tablet_pad_get_num_rings(m_device); 0536 } 0537 0538 void *Device::groupUserData() const 0539 { 0540 auto deviceGroup = libinput_device_get_device_group(m_device); 0541 return libinput_device_group_get_user_data(deviceGroup); 0542 } 0543 0544 #define CONFIG(method, condition, function, variable, key) \ 0545 void Device::method(bool set) \ 0546 { \ 0547 if (condition) { \ 0548 return; \ 0549 } \ 0550 if (libinput_device_config_##function(m_device, set) == LIBINPUT_CONFIG_STATUS_SUCCESS) { \ 0551 if (m_##variable != set) { \ 0552 m_##variable = set; \ 0553 writeEntry(ConfigKey::key, m_##variable); \ 0554 Q_EMIT variable##Changed(); \ 0555 } \ 0556 } \ 0557 } 0558 0559 CONFIG(setLeftHanded, !m_supportsLeftHanded, left_handed_set, leftHanded, LeftHanded) 0560 CONFIG(setNaturalScroll, !m_supportsNaturalScroll, scroll_set_natural_scroll_enabled, naturalScroll, NaturalScroll) 0561 0562 #undef CONFIG 0563 0564 #define CONFIG(method, condition, function, enum, variable, key) \ 0565 void Device::method(bool set) \ 0566 { \ 0567 if (condition) { \ 0568 return; \ 0569 } \ 0570 if (libinput_device_config_##function(m_device, set ? LIBINPUT_CONFIG_##enum##_ENABLED : LIBINPUT_CONFIG_##enum##_DISABLED) == LIBINPUT_CONFIG_STATUS_SUCCESS) { \ 0571 if (m_##variable != set) { \ 0572 m_##variable = set; \ 0573 writeEntry(ConfigKey::key, m_##variable); \ 0574 Q_EMIT variable##Changed(); \ 0575 } \ 0576 } \ 0577 } 0578 0579 CONFIG(setEnabled, !m_supportsDisableEvents, send_events_set_mode, SEND_EVENTS, enabled, Enabled) 0580 CONFIG(setDisableWhileTyping, !m_supportsDisableWhileTyping, dwt_set_enabled, DWT, disableWhileTyping, DisableWhileTyping) 0581 CONFIG(setTapToClick, m_tapFingerCount == 0, tap_set_enabled, TAP, tapToClick, TapToClick) 0582 CONFIG(setTapAndDrag, false, tap_set_drag_enabled, DRAG, tapAndDrag, TapAndDrag) 0583 CONFIG(setTapDragLock, false, tap_set_drag_lock_enabled, DRAG_LOCK, tapDragLock, TapDragLock) 0584 CONFIG(setMiddleEmulation, m_supportsMiddleEmulation == false, middle_emulation_set_enabled, MIDDLE_EMULATION, middleEmulation, MiddleButtonEmulation) 0585 0586 #undef CONFIG 0587 0588 void Device::setScrollFactor(qreal factor) 0589 { 0590 if (m_scrollFactor != factor) { 0591 m_scrollFactor = factor; 0592 writeEntry(ConfigKey::ScrollFactor, m_scrollFactor); 0593 Q_EMIT scrollFactorChanged(); 0594 } 0595 } 0596 0597 void Device::setCalibrationMatrix(const QMatrix4x4 &matrix) 0598 { 0599 if (!m_supportsCalibrationMatrix || m_calibrationMatrix == matrix) { 0600 return; 0601 } 0602 0603 if (setOrientedCalibrationMatrix(m_device, matrix, m_orientation)) { 0604 QList<float> list; 0605 list.reserve(16); 0606 for (uchar row = 0; row < 4; ++row) { 0607 for (uchar col = 0; col < 4; ++col) { 0608 list << matrix(row, col); 0609 } 0610 } 0611 writeEntry(ConfigKey::Calibration, list); 0612 m_calibrationMatrix = matrix; 0613 Q_EMIT calibrationMatrixChanged(); 0614 } 0615 } 0616 0617 void Device::setOrientation(Qt::ScreenOrientation orientation) 0618 { 0619 if (!m_supportsCalibrationMatrix || m_orientation == orientation) { 0620 return; 0621 } 0622 0623 if (setOrientedCalibrationMatrix(m_device, m_calibrationMatrix, orientation)) { 0624 writeEntry(ConfigKey::Orientation, static_cast<int>(orientation)); 0625 m_orientation = orientation; 0626 Q_EMIT orientationChanged(); 0627 } 0628 } 0629 0630 void Device::setOutputName(const QString &name) 0631 { 0632 #ifndef KWIN_BUILD_TESTING 0633 if (name == m_outputName) { 0634 return; 0635 } 0636 0637 setOutput(nullptr); 0638 auto outputs = kwinApp()->outputBackend()->outputs(); 0639 for (int i = 0; i < outputs.count(); ++i) { 0640 if (!outputs[i]->isEnabled()) { 0641 continue; 0642 } 0643 if (outputs[i]->name() == name) { 0644 setOutput(outputs[i]); 0645 break; 0646 } 0647 } 0648 0649 m_outputName = name; 0650 writeEntry(ConfigKey::OutputName, name); 0651 Q_EMIT outputNameChanged(); 0652 #endif 0653 } 0654 0655 Output *Device::output() const 0656 { 0657 return m_output; 0658 } 0659 0660 void Device::setOutput(Output *output) 0661 { 0662 m_output = output; 0663 } 0664 0665 static libinput_led toLibinputLEDS(LEDs leds) 0666 { 0667 quint32 libinputLeds = 0; 0668 if (leds.testFlag(LED::NumLock)) { 0669 libinputLeds = libinputLeds | LIBINPUT_LED_NUM_LOCK; 0670 } 0671 if (leds.testFlag(LED::CapsLock)) { 0672 libinputLeds = libinputLeds | LIBINPUT_LED_CAPS_LOCK; 0673 } 0674 if (leds.testFlag(LED::ScrollLock)) { 0675 libinputLeds = libinputLeds | LIBINPUT_LED_SCROLL_LOCK; 0676 } 0677 return libinput_led(libinputLeds); 0678 } 0679 0680 LEDs Device::leds() const 0681 { 0682 return m_leds; 0683 } 0684 0685 void Device::setLeds(LEDs leds) 0686 { 0687 if (m_leds != leds) { 0688 m_leds = leds; 0689 libinput_device_led_update(m_device, toLibinputLEDS(m_leds)); 0690 } 0691 } 0692 0693 bool Device::supportsOutputArea() const 0694 { 0695 return m_tabletTool; 0696 } 0697 0698 QRectF Device::defaultOutputArea() const 0699 { 0700 return QRectF(0, 0, 1, 1); 0701 } 0702 0703 QRectF Device::outputArea() const 0704 { 0705 return m_outputArea; 0706 } 0707 0708 void Device::setOutputArea(const QRectF &outputArea) 0709 { 0710 if (m_outputArea != outputArea) { 0711 m_outputArea = outputArea; 0712 writeEntry(ConfigKey::OutputArea, m_outputArea); 0713 Q_EMIT outputAreaChanged(); 0714 } 0715 } 0716 0717 void Device::setMapToWorkspace(bool mapToWorkspace) 0718 { 0719 if (m_mapToWorkspace != mapToWorkspace) { 0720 m_mapToWorkspace = mapToWorkspace; 0721 writeEntry(ConfigKey::MapToWorkspace, m_mapToWorkspace); 0722 Q_EMIT mapToWorkspaceChanged(); 0723 } 0724 } 0725 } 0726 } 0727 0728 #include "moc_device.cpp"