diff options
author | BogDan Vatra <bogdan@kdab.com> | 2015-10-26 12:38:33 +0200 |
---|---|---|
committer | Andy Nichols <andy.nichols@theqtcompany.com> | 2015-10-26 12:40:37 +0000 |
commit | c32e995bc79035e600893e91fdcec984f8293c75 (patch) | |
tree | 6de9a857b695fedfb3a52c5e4e34334759a09acc /src/plugins/gamepads/evdev/qevdevgamepadbackend.cpp | |
parent | 00871e531f7fb44feb3dac7abfe4eff0af5dfada (diff) |
Enable the usage of unknown gamepads.
Allowing the user to configure every button & axis of (s)his gamepad,
will enable the usage of any gamepad.
Currently only evdev backed has this feature.
Change-Id: I6e0692980e77b448d20d5ba818b787a7b89e7257
Reviewed-by: Andy Nichols <andy.nichols@theqtcompany.com>
Diffstat (limited to 'src/plugins/gamepads/evdev/qevdevgamepadbackend.cpp')
-rw-r--r-- | src/plugins/gamepads/evdev/qevdevgamepadbackend.cpp | 494 |
1 files changed, 296 insertions, 198 deletions
diff --git a/src/plugins/gamepads/evdev/qevdevgamepadbackend.cpp b/src/plugins/gamepads/evdev/qevdevgamepadbackend.cpp index 6319441..17bd74e 100644 --- a/src/plugins/gamepads/evdev/qevdevgamepadbackend.cpp +++ b/src/plugins/gamepads/evdev/qevdevgamepadbackend.cpp @@ -45,8 +45,59 @@ QT_BEGIN_NAMESPACE Q_LOGGING_CATEGORY(lcEGB, "qt.gamepad") +QEvdevGamepadDevice::EvdevAxisInfo::EvdevAxisInfo() + : QGamepadBackend::AxisInfo<int>(0, 1, QGamepadManager::AxisInvalid) +{ +} + +QEvdevGamepadDevice::EvdevAxisInfo::EvdevAxisInfo(int fd, quint16 abs, int min, int max, QGamepadManager::GamepadAxis gamepadAxis) + : QGamepadBackend::AxisInfo<int>(min, max, gamepadAxis) + , flat(0) + , gamepadMinButton(QGamepadManager::ButtonInvalid) + , gamepadMaxButton(QGamepadManager::ButtonInvalid) + , gamepadLastButton(QGamepadManager::ButtonInvalid) +{ + setAbsInfo(fd, abs); +} + +double QEvdevGamepadDevice::EvdevAxisInfo::normalized(int value) const +{ + double val = AxisInfo::normalized(value); + if (qAbs(val) <= flat) + val = 0; + return val; +} + +void QEvdevGamepadDevice::EvdevAxisInfo::setAbsInfo(int fd, int abs) +{ + input_absinfo absInfo; + memset(&absInfo, 0, sizeof(input_absinfo)); + if (ioctl(fd, EVIOCGABS(abs), &absInfo) >= 0) { + minValue = absInfo.minimum; + maxValue = absInfo.maximum; + if (maxValue - minValue) + flat = fabs(absInfo.flat / double(maxValue - minValue)); + } +} + +void QEvdevGamepadDevice::EvdevAxisInfo::restoreSavedData(int fd, int abs, const QVariantMap &value) +{ + gamepadAxis = QGamepadManager::GamepadAxis(value[QLatin1Literal("axis")].toInt()); + gamepadMinButton = QGamepadManager::GamepadButton(value[QLatin1Literal("minButton")].toInt()); + gamepadMaxButton = QGamepadManager::GamepadButton(value[QLatin1Literal("maxButton")].toInt()); + setAbsInfo(fd, abs); +} + +QVariantMap QEvdevGamepadDevice::EvdevAxisInfo::dataToSave() const +{ + QVariantMap data; + data[QLatin1Literal("axis")] = gamepadAxis; + data[QLatin1Literal("minButton")] = gamepadMinButton; + data[QLatin1Literal("maxButton")] = gamepadMaxButton; + return data; +} + QEvdevGamepadBackend::QEvdevGamepadBackend() - : m_nextIndex(0) { } @@ -83,17 +134,46 @@ QEvdevGamepadDevice *QEvdevGamepadBackend::newDevice(const QByteArray &device) return new QEvdevGamepadDevice(device, this); } -// To be called only when it is sure that there is a controller on-line. -int QEvdevGamepadBackend::idForDevice(const QByteArray &device) +QEvdevGamepadDevice *QEvdevGamepadBackend::device(int deviceId) { - int index; - if (m_devIndex.contains(device)) { - index = m_devIndex[device]; - } else { - index = m_nextIndex++; - m_devIndex[device] = index; - } - return index; + foreach (QEvdevGamepadDevice *device, m_devices) + if (device->deviceId() == deviceId) + return device; + return nullptr; +} + +void QEvdevGamepadBackend::resetConfiguration(int deviceId) +{ + if (QEvdevGamepadDevice *dev = device(deviceId)) + return dev->resetConfiguration(); +} + +bool QEvdevGamepadBackend::isConfigurationNeeded(int deviceId) +{ + if (QEvdevGamepadDevice *dev = device(deviceId)) + return dev->isConfigurationNeeded(); + return false; +} + +bool QEvdevGamepadBackend::configureButton(int deviceId, QGamepadManager::GamepadButton button) +{ + if (QEvdevGamepadDevice *dev = device(deviceId)) + return dev->configureButton(button); + return false; +} + +bool QEvdevGamepadBackend::configureAxis(int deviceId, QGamepadManager::GamepadAxis axis) +{ + if (QEvdevGamepadDevice *dev = device(deviceId)) + return dev->configureAxis(axis); + return false; +} + +bool QEvdevGamepadBackend::setCancelConfigureButton(int deviceId, QGamepadManager::GamepadButton button) +{ + if (QEvdevGamepadDevice *dev = device(deviceId)) + return dev->setCancelConfigureButton(button); + return false; } void QEvdevGamepadBackend::stop() @@ -128,11 +208,12 @@ void QEvdevGamepadBackend::handleRemovedDevice(const QString &device) QEvdevGamepadDevice::QEvdevGamepadDevice(const QByteArray &dev, QEvdevGamepadBackend *backend) : m_dev(dev), m_backend(backend), - m_index(-1), m_fd(-1), + m_productId(0), + m_needsConfigure(true), m_notifier(0), - m_prevYHatButton(QGamepadManager::ButtonInvalid), - m_prevXHatButton(QGamepadManager::ButtonInvalid) + m_configureButton(QGamepadManager::ButtonInvalid), + m_configureAxis(QGamepadManager::AxisInvalid) { openDevice(dev); } @@ -141,8 +222,75 @@ QEvdevGamepadDevice::~QEvdevGamepadDevice() { if (m_fd != -1) QT_CLOSE(m_fd); - if (m_index >= 0) - emit m_backend->gamepadRemoved(m_index); + if (m_fd >= 0) + emit m_backend->gamepadRemoved(m_fd); +} + +void QEvdevGamepadDevice::resetConfiguration() +{ + m_axisMap.insert(ABS_X, EvdevAxisInfo(m_fd, ABS_X, -32768, 32767, QGamepadManager::AxisLeftX)); + m_axisMap.insert(ABS_Y, EvdevAxisInfo(m_fd, ABS_Y, -32768, 32767, QGamepadManager::AxisLeftY)); + m_axisMap.insert(ABS_RX, EvdevAxisInfo(m_fd, ABS_RX, -32768, 32767, QGamepadManager::AxisRightX)); + m_axisMap.insert(ABS_RY, EvdevAxisInfo(m_fd, ABS_RY, -32768, 32767, QGamepadManager::AxisRightY)); + m_axisMap.insert(ABS_Z, EvdevAxisInfo(m_fd, ABS_Z, 0, 255)); + m_axisMap[ABS_Z].gamepadMinButton = QGamepadManager::ButtonL2; + m_axisMap[ABS_Z].gamepadMaxButton = QGamepadManager::ButtonL2; + + m_axisMap.insert(ABS_RZ, EvdevAxisInfo(m_fd, ABS_RZ, 0, 255)); + m_axisMap[ABS_RZ].gamepadMinButton = QGamepadManager::ButtonR2; + m_axisMap[ABS_RZ].gamepadMaxButton = QGamepadManager::ButtonR2; + + m_axisMap.insert(ABS_HAT0X, EvdevAxisInfo(m_fd, ABS_HAT0X, -1, 1)); + m_axisMap[ABS_HAT0X].gamepadMinButton = QGamepadManager::ButtonLeft; + m_axisMap[ABS_HAT0X].gamepadMaxButton = QGamepadManager::ButtonRight; + + m_axisMap.insert(ABS_HAT0Y, EvdevAxisInfo(m_fd, ABS_HAT0Y, -1, 1)); + m_axisMap[ABS_HAT0Y].gamepadMinButton = QGamepadManager::ButtonUp; + m_axisMap[ABS_HAT0Y].gamepadMaxButton = QGamepadManager::ButtonDown; + + m_buttonsMap[BTN_START] = QGamepadManager::ButtonStart; + m_buttonsMap[BTN_SELECT] = QGamepadManager::ButtonSelect; + m_buttonsMap[BTN_MODE] = QGamepadManager::ButtonGuide; + m_buttonsMap[BTN_X] = QGamepadManager::ButtonX; + m_buttonsMap[BTN_Y] = QGamepadManager::ButtonY; + m_buttonsMap[BTN_A] = QGamepadManager::ButtonA; + m_buttonsMap[BTN_B] = QGamepadManager::ButtonB; + m_buttonsMap[BTN_TL] = QGamepadManager::ButtonL1; + m_buttonsMap[BTN_TR] = QGamepadManager::ButtonR1; + m_buttonsMap[BTN_TL2] = QGamepadManager::ButtonL2; + m_buttonsMap[BTN_TR2] = QGamepadManager::ButtonR2; + m_buttonsMap[BTN_THUMB] = m_buttonsMap[BTN_THUMBL] = QGamepadManager::ButtonL3; + m_buttonsMap[BTN_THUMBR] = QGamepadManager::ButtonR3; + m_buttonsMap[BTN_TRIGGER_HAPPY1] = QGamepadManager::ButtonLeft; + m_buttonsMap[BTN_TRIGGER_HAPPY2] = QGamepadManager::ButtonRight; + m_buttonsMap[BTN_TRIGGER_HAPPY3] = QGamepadManager::ButtonUp; + m_buttonsMap[BTN_TRIGGER_HAPPY4] = QGamepadManager::ButtonDown; + + if (m_productId) + m_backend->saveSettings(m_productId, QVariant()); +} + +bool QEvdevGamepadDevice::isConfigurationNeeded() +{ + return m_needsConfigure; +} + +bool QEvdevGamepadDevice::configureButton(QGamepadManager::GamepadButton button) +{ + m_configureButton = button; + return true; +} + +bool QEvdevGamepadDevice::configureAxis(QGamepadManager::GamepadAxis axis) +{ + m_configureAxis = axis; + return true; +} + +bool QEvdevGamepadDevice::setCancelConfigureButton(QGamepadManager::GamepadButton button) +{ + m_configureCancelButton = button; + return true; } bool QEvdevGamepadDevice::openDevice(const QByteArray &dev) @@ -152,41 +300,41 @@ bool QEvdevGamepadDevice::openDevice(const QByteArray &dev) if (m_fd >= 0) { m_notifier = new QSocketNotifier(m_fd, QSocketNotifier::Read, this); connect(m_notifier, SIGNAL(activated(int)), this, SLOT(readData())); + emit m_backend->gamepadAdded(m_fd); qCDebug(lcEGB) << "Successfully opened" << dev; } else { qErrnoWarning(errno, "Gamepad: Cannot open input device %s", qPrintable(dev)); return false; } - // Defaults. To be replaced with queried values below. - m_axisInfo.insert(ABS_X, AxisInfo(-32768, 32767, 0)); - m_axisInfo.insert(ABS_Y, AxisInfo(-32768, 32767, 0)); - m_axisInfo.insert(ABS_RX, AxisInfo(-32768, 32767, 0)); - m_axisInfo.insert(ABS_RY, AxisInfo(-32768, 32767, 0)); - m_axisInfo.insert(ABS_Z, AxisInfo(0, 255, 0)); - m_axisInfo.insert(ABS_RZ, AxisInfo(0, 255, 0)); + input_id id; + if (ioctl(m_fd, EVIOCGID, &id) >= 0) + m_productId = id.product; + + if (m_productId) { + QVariant settings = m_backend->readSettings(m_productId); + if (!settings.isNull()) { + m_needsConfigure = false; + QVariantMap data = settings.toMap()[QLatin1Literal("axes")].toMap(); + for (QVariantMap::const_iterator it = data.begin(); it != data.end(); ++it) { + const int key = it.key().toInt(); + m_axisMap[key].restoreSavedData(m_fd, key, it.value().toMap()); + } - input_absinfo absInfo; - memset(&absInfo, 0, sizeof(input_absinfo)); - if (ioctl(m_fd, EVIOCGABS(ABS_X), &absInfo) >= 0) - m_axisInfo.insert(ABS_X, AxisInfo(absInfo.minimum, absInfo.maximum, absInfo.flat)); - if (ioctl(m_fd, EVIOCGABS(ABS_Y), &absInfo) >= 0) - m_axisInfo.insert(ABS_Y, AxisInfo(absInfo.minimum, absInfo.maximum, absInfo.flat)); - if (ioctl(m_fd, EVIOCGABS(ABS_RX), &absInfo) >= 0) - m_axisInfo.insert(ABS_RX, AxisInfo(absInfo.minimum, absInfo.maximum, absInfo.flat)); - if (ioctl(m_fd, EVIOCGABS(ABS_RY), &absInfo) >= 0) - m_axisInfo.insert(ABS_RY, AxisInfo(absInfo.minimum, absInfo.maximum, absInfo.flat)); - if (ioctl(m_fd, EVIOCGABS(ABS_Z), &absInfo) >= 0) - m_axisInfo.insert(ABS_Z, AxisInfo(absInfo.minimum, absInfo.maximum, absInfo.flat)); - if (ioctl(m_fd, EVIOCGABS(ABS_RZ), &absInfo) >= 0) - m_axisInfo.insert(ABS_RZ, AxisInfo(absInfo.minimum, absInfo.maximum, absInfo.flat)); - - qCDebug(lcEGB) << "Axis limits:" << m_axisInfo; + data = settings.toMap()[QLatin1Literal("buttons")].toMap(); + for (QVariantMap::const_iterator it = data.begin(); it != data.end(); ++it) + m_buttonsMap[it.key().toInt()] = QGamepadManager::GamepadButton(it.value().toInt()); + } + } + if (m_needsConfigure) + resetConfiguration(); + + qCDebug(lcEGB) << "Axis limits:" << m_axisMap; return true; } -QDebug operator<<(QDebug dbg, const QEvdevGamepadDevice::AxisInfo &axisInfo) +QDebug operator<<(QDebug dbg, const QEvdevGamepadDevice::EvdevAxisInfo &axisInfo) { dbg.nospace() << "AxisInfo(min=" << axisInfo.minValue << ", max=" << axisInfo.maxValue << ")"; return dbg.space(); @@ -229,185 +377,135 @@ err: } } -double QEvdevGamepadDevice::AxisInfo::normalized(int value) const +void QEvdevGamepadDevice::saveData() { - double ret = 0; - if (minValue >= 0) - ret = 2 * (value - double(maxValue - minValue) / 2) / double(maxValue - minValue); - else - ret = 2 * (value - minValue) / double(maxValue - minValue) - 1.0; - if (fabs(ret) <= fabs(flat)) - ret = 0; - return ret; + if (!m_productId) + return ; + + QVariantMap settings, data; + for (AxisMap::const_iterator it = m_axisMap.begin(); it != m_axisMap.end(); ++it) + data[QString::number(it.key())] = it.value().dataToSave(); + settings[QLatin1Literal("axes")] = data; + + data.clear(); + for (ButtonsMap::const_iterator it = m_buttonsMap.begin(); it != m_buttonsMap.end(); ++it) + data[QString::number(it.key())] = it.value(); + + settings[QLatin1Literal("buttons")] = data; + + m_backend->saveSettings(m_productId, settings); } void QEvdevGamepadDevice::processInputEvent(input_event *e) { - if (m_index < 0) { - m_index = m_backend->idForDevice(m_dev); - qCDebug(lcEGB) << "Adding gamepad" << m_dev << "with index" << m_index; - emit m_backend->gamepadAdded(m_index); - } - if (e->type == EV_KEY) { - const bool pressed = e->value; QGamepadManager::GamepadButton btn = QGamepadManager::ButtonInvalid; + ButtonsMap::const_iterator it = m_buttonsMap.find(e->code); + if (it != m_buttonsMap.end()) + btn = it.value(); - switch (e->code) { - case BTN_START: - btn = QGamepadManager::ButtonStart; - break; - case BTN_SELECT: - btn = QGamepadManager::ButtonSelect; - break; - case BTN_MODE: - btn = QGamepadManager::ButtonGuide; - break; - - case BTN_X: - btn = QGamepadManager::ButtonX; - break; - case BTN_Y: - btn = QGamepadManager::ButtonY; - break; - case BTN_A: - btn = QGamepadManager::ButtonA; - break; - case BTN_B: - btn = QGamepadManager::ButtonB; - break; - - case BTN_TL: - btn = QGamepadManager::ButtonL1; - break; - case BTN_TR: - btn = QGamepadManager::ButtonR1; - break; - - case BTN_TL2: - btn = QGamepadManager::ButtonL2; - break; - case BTN_TR2: - btn = QGamepadManager::ButtonR2; - break; - + const bool pressed = e->value; + if (m_configureCancelButton != QGamepadManager::ButtonInvalid && + m_configureCancelButton != m_configureButton && + !pressed && btn == m_configureCancelButton && + (m_configureButton != QGamepadManager::ButtonInvalid || + m_configureAxis != QGamepadManager::AxisInvalid)) { + m_configureButton = QGamepadManager::ButtonInvalid; + m_configureAxis = QGamepadManager::AxisInvalid; + emit m_backend->configurationCanceled(m_fd); + return; + } - case BTN_THUMB: // wireless - case BTN_THUMBL: // wired - btn = QGamepadManager::ButtonL3; - break; - case BTN_THUMBR: - btn = QGamepadManager::ButtonR3; - break; + if (!pressed && m_configureButton != QGamepadManager::ButtonInvalid) { + m_buttonsMap[e->code] = m_configureButton; + QGamepadManager::GamepadButton but = m_configureButton; + m_configureButton = QGamepadManager::ButtonInvalid; + saveData(); + emit m_backend->buttonConfigured(m_fd, but); + } - // Directional buttons for wireless - case BTN_TRIGGER_HAPPY1: - btn = QGamepadManager::ButtonLeft; - break; - case BTN_TRIGGER_HAPPY2: - btn = QGamepadManager::ButtonRight; - break; - case BTN_TRIGGER_HAPPY3: - btn = QGamepadManager::ButtonUp; - break; - case BTN_TRIGGER_HAPPY4: - btn = QGamepadManager::ButtonDown; - break; + it = m_buttonsMap.find(e->code); + if (it != m_buttonsMap.end()) + btn = it.value(); - default: - break; - } if (btn != QGamepadManager::ButtonInvalid) { if (pressed) - emit m_backend->gamepadButtonPressed(m_index, btn, 1.0); + emit m_backend->gamepadButtonPressed(m_fd, btn, 1.0); else - emit m_backend->gamepadButtonReleased(m_index, btn); + emit m_backend->gamepadButtonReleased(m_fd, btn); } } else if (e->type == EV_ABS) { - if (e->code == ABS_HAT0X || e->code == ABS_HAT0Y) { - //Special logic for digital direction buttons as it is treated as a hat axis - //with the wired controller. - double value = m_axisInfo.value(e->code).normalized(e->value); - QGamepadManager::GamepadButton btn = QGamepadManager::ButtonInvalid; - bool pressed = false; - if (e->code == ABS_HAT0X) { - if (value == 1.0) { - btn = QGamepadManager::ButtonRight; - m_prevXHatButton = btn; - pressed = true; - } else if (value == -1.0) { - btn = QGamepadManager::ButtonLeft; - m_prevXHatButton = btn; - pressed = true; - } else { - //Release - btn = m_prevXHatButton; - m_prevXHatButton = QGamepadManager::ButtonInvalid; - pressed = false; - } - } else { - if (value == 1.0) { - btn = QGamepadManager::ButtonDown; - m_prevYHatButton = btn; - pressed = true; - } else if (value == -1.0) { - btn = QGamepadManager::ButtonUp; - m_prevYHatButton = btn; - pressed = true; - } else { - //Release - btn = m_prevYHatButton; - m_prevYHatButton = QGamepadManager::ButtonInvalid; - pressed = false; - } - } - if (btn != QGamepadManager::ButtonInvalid) { - if (pressed) - emit m_backend->gamepadButtonPressed(m_index, btn, 1.0); - else - emit m_backend->gamepadButtonReleased(m_index, btn); + if (m_configureAxis != QGamepadManager::AxisInvalid) { + m_axisMap.insert(e->code, EvdevAxisInfo(m_fd, e->code, -32768, 32767, m_configureAxis)); + + QGamepadManager::GamepadAxis axis = m_configureAxis; + m_configureAxis = QGamepadManager::AxisInvalid; + + saveData(); + emit m_backend->axisConfigured(m_fd, axis); + } + + AxisMap::iterator it = m_axisMap.find(e->code); + if (m_configureButton != QGamepadManager::ButtonInvalid) { + EvdevAxisInfo axisInfo; + if (it != m_axisMap.end()) + axisInfo = it.value(); + else + axisInfo = EvdevAxisInfo(m_fd, e->code); + + axisInfo.gamepadAxis = QGamepadManager::AxisInvalid; + + bool save = false; + if (e->value == axisInfo.minValue) { + axisInfo.gamepadMinButton = m_configureButton; + if (axisInfo.gamepadMaxButton != QGamepadManager::ButtonInvalid) + axisInfo.gamepadMaxButton = m_configureButton; + save = true; + } else if (e->value == axisInfo.maxValue) { + axisInfo.gamepadMaxButton = m_configureButton; + if (axisInfo.gamepadMinButton != QGamepadManager::ButtonInvalid) + axisInfo.gamepadMinButton = m_configureButton; + save = true; } - } else { - QGamepadManager::GamepadAxis axis = QGamepadManager::AxisInvalid; - QGamepadManager::GamepadButton btn = QGamepadManager::ButtonInvalid; - - switch (e->code) { - case ABS_X: - axis = QGamepadManager::AxisLeftX; - break; - case ABS_Y: - axis = QGamepadManager::AxisLeftY; - break; - - case ABS_RX: - axis = QGamepadManager::AxisRightX; - break; - case ABS_RY: - axis = QGamepadManager::AxisRightY; - break; - - case ABS_Z: - btn = QGamepadManager::ButtonL2; - break; - case ABS_RZ: - btn = QGamepadManager::ButtonR2; - break; - - default: - break; + if (save) { + QGamepadManager::GamepadButton but = m_configureButton; + m_configureButton = QGamepadManager::ButtonInvalid; + saveData(); + emit m_backend->buttonConfigured(m_fd, but); } + } + + it = m_axisMap.find(e->code); + if (it == m_axisMap.end()) + return; + + EvdevAxisInfo &info = it.value(); - AxisInfo axisInfo = m_axisInfo.value(e->code); - const double value = axisInfo.normalized(e->value); + double val = info.normalized(e->value); - if (axis != QGamepadManager::AxisInvalid) { - emit m_backend->gamepadAxisMoved(m_index, axis, value); - } else if (btn != QGamepadManager::ButtonInvalid) { - if (!qFuzzyIsNull(value)) - emit m_backend->gamepadButtonPressed(m_index, btn, value); - else - emit m_backend->gamepadButtonReleased(m_index, btn); + if (info.gamepadAxis != QGamepadManager::AxisInvalid) + emit m_backend->gamepadAxisMoved(m_fd, info.gamepadAxis, val); + + if (info.gamepadMaxButton == info.gamepadMinButton && + info.gamepadMaxButton != QGamepadManager::ButtonInvalid) { + if (val) + emit m_backend->gamepadButtonPressed(m_fd, info.gamepadMaxButton, val); + else + emit m_backend->gamepadButtonReleased(m_fd, info.gamepadMaxButton); + } else { + if (info.gamepadMaxButton != QGamepadManager::ButtonInvalid + && val == 1.0) { + info.gamepadLastButton = info.gamepadMaxButton; + emit m_backend->gamepadButtonPressed(m_fd, info.gamepadMaxButton, val); + } else if (info.gamepadMinButton != QGamepadManager::ButtonInvalid + && val == -1.0) { + info.gamepadLastButton = info.gamepadMinButton; + emit m_backend->gamepadButtonPressed(m_fd, info.gamepadMinButton, val); + } else if (!val && info.gamepadLastButton != QGamepadManager::ButtonInvalid) { + QGamepadManager::GamepadButton but = info.gamepadLastButton; + info.gamepadLastButton = QGamepadManager::ButtonInvalid; + emit m_backend->gamepadButtonReleased(m_fd, but); } } } |