diff options
author | Andy Nichols <andy.nichols@theqtcompany.com> | 2016-03-17 15:45:44 +0100 |
---|---|---|
committer | Andy Nichols <andy.nichols@theqtcompany.com> | 2016-03-17 15:46:51 +0100 |
commit | 57b578485a192b55765461adbd6a47a81fdf6eb3 (patch) | |
tree | 58767a3038402938663a2e913902f05341bc3ed7 | |
parent | bb53183d4089a9f764b69dfbc47d8b91433af4f4 (diff) | |
parent | b3e8bd55289d54bd21b4f16c6b997d805bba816e (diff) |
Merge remote-tracking branch 'origin/5.7' into dev
Change-Id: I091e2a9c4f5c65affd4b5b32c1c3e38b7c9076d9
-rw-r--r-- | src/gamepad/doc/src/qtgamepad-overview.qdoc | 2 | ||||
-rw-r--r-- | src/gamepad/gamepad.pro | 3 | ||||
-rw-r--r-- | src/gamepad/qgamepad.h | 2 | ||||
-rw-r--r-- | src/gamepad/qgamepadbackend.cpp | 6 | ||||
-rw-r--r-- | src/gamepad/qgamepadbackendfactory.cpp | 4 | ||||
-rw-r--r-- | src/gamepad/qgamepadkeynavigation.h | 2 | ||||
-rw-r--r-- | src/imports/gamepad/qtgamepad.cpp | 2 | ||||
-rw-r--r-- | src/plugins/gamepads/android/src/qandroidgamepadbackend.cpp | 176 | ||||
-rw-r--r-- | src/plugins/gamepads/android/src/qandroidgamepadbackend_p.h | 7 |
9 files changed, 152 insertions, 52 deletions
diff --git a/src/gamepad/doc/src/qtgamepad-overview.qdoc b/src/gamepad/doc/src/qtgamepad-overview.qdoc index 594796a..08c7c85 100644 --- a/src/gamepad/doc/src/qtgamepad-overview.qdoc +++ b/src/gamepad/doc/src/qtgamepad-overview.qdoc @@ -35,7 +35,7 @@ ****************************************************************************/ /*! - \page index.html + \page qtgamepad-index.html \title Qt Gamepad \brief A cross-platform library to facilitate the use of gamepad hardware in Qt and Qt Quick applications diff --git a/src/gamepad/gamepad.pro b/src/gamepad/gamepad.pro index b97a01d..92d68cc 100644 --- a/src/gamepad/gamepad.pro +++ b/src/gamepad/gamepad.pro @@ -34,3 +34,6 @@ ANDROID_JAR_DEPENDENCIES = \ ANDROID_LIB_DEPENDENCIES = \ plugins/gamepads/libandroidgamepad.so + +ANDROID_FEATURES = \ + android.hardware.gamepad diff --git a/src/gamepad/qgamepad.h b/src/gamepad/qgamepad.h index 3ad3503..2c99e85 100644 --- a/src/gamepad/qgamepad.h +++ b/src/gamepad/qgamepad.h @@ -72,7 +72,7 @@ class Q_GAMEPAD_EXPORT QGamepad : public QObject Q_PROPERTY(bool buttonCenter READ buttonCenter NOTIFY buttonCenterChanged) Q_PROPERTY(bool buttonGuide READ buttonGuide NOTIFY buttonGuideChanged) public: - explicit QGamepad(int deviceId = 0, QObject *parent = 0); + explicit QGamepad(int deviceId = 0, QObject *parent = nullptr); ~QGamepad(); int deviceId() const; diff --git a/src/gamepad/qgamepadbackend.cpp b/src/gamepad/qgamepadbackend.cpp index 0f11800..2b74634 100644 --- a/src/gamepad/qgamepadbackend.cpp +++ b/src/gamepad/qgamepadbackend.cpp @@ -39,6 +39,8 @@ QT_BEGIN_NAMESPACE +static const QLatin1String GAMEPAD_GROUP("___gamepad_saved_states_v2"); + QGamepadBackend::QGamepadBackend(QObject *parent) : QObject(parent) { @@ -80,7 +82,7 @@ void QGamepadBackend::saveSettings(int productId, const QVariant &value) s.reset(new QSettings()); else s.reset(new QSettings(m_settingsFilePath)); - s->beginGroup(QString::fromLatin1("___gamepad_saved_states")); + s->beginGroup(GAMEPAD_GROUP); QString key = QString::fromLatin1("id_%1").arg(productId); if (value.isNull()) s->remove(key); @@ -95,7 +97,7 @@ QVariant QGamepadBackend::readSettings(int productId) s.reset(new QSettings()); else s.reset(new QSettings(m_settingsFilePath)); - s->beginGroup(QString::fromLatin1("___gamepad_saved_states")); + s->beginGroup(GAMEPAD_GROUP); return s->value(QString::fromLatin1("id_%1").arg(productId)); } diff --git a/src/gamepad/qgamepadbackendfactory.cpp b/src/gamepad/qgamepadbackendfactory.cpp index 0434e4b..25a1064 100644 --- a/src/gamepad/qgamepadbackendfactory.cpp +++ b/src/gamepad/qgamepadbackendfactory.cpp @@ -77,10 +77,10 @@ QGamepadBackend *QGamepadBackendFactory::create(const QString &name, const QStri #ifndef QT_NO_LIBRARY if (!pluginPath.isEmpty()) { QCoreApplication::addLibraryPath(pluginPath); - if (QGamepadBackend *ret = qLoadPlugin1<QGamepadBackend, QGamepadBackendPlugin>(directLoader(), name, args)) + if (QGamepadBackend *ret = qLoadPlugin<QGamepadBackend, QGamepadBackendPlugin>(directLoader(), name, args)) return ret; } - if (QGamepadBackend *ret = qLoadPlugin1<QGamepadBackend, QGamepadBackendPlugin>(loader(), name, args)) + if (QGamepadBackend *ret = qLoadPlugin<QGamepadBackend, QGamepadBackendPlugin>(loader(), name, args)) return ret; #endif return 0; diff --git a/src/gamepad/qgamepadkeynavigation.h b/src/gamepad/qgamepadkeynavigation.h index e9e7959..9bd599c 100644 --- a/src/gamepad/qgamepadkeynavigation.h +++ b/src/gamepad/qgamepadkeynavigation.h @@ -70,7 +70,7 @@ class Q_GAMEPAD_EXPORT QGamepadKeyNavigation : public QObject Q_PROPERTY(Qt::Key buttonL3Key READ buttonL3Key WRITE setButtonL3Key NOTIFY buttonL3KeyChanged) Q_PROPERTY(Qt::Key buttonR3Key READ buttonR3Key WRITE setButtonR3Key NOTIFY buttonR3KeyChanged) public: - explicit QGamepadKeyNavigation(QObject *parent = 0); + explicit QGamepadKeyNavigation(QObject *parent = nullptr); bool active() const; QGamepad *gamepad() const; diff --git a/src/imports/gamepad/qtgamepad.cpp b/src/imports/gamepad/qtgamepad.cpp index 1d550db..8196f47 100644 --- a/src/imports/gamepad/qtgamepad.cpp +++ b/src/imports/gamepad/qtgamepad.cpp @@ -45,7 +45,7 @@ QT_BEGIN_NAMESPACE -static QObject *gamepadmanager_singletontype_provider(QQmlEngine */*engine*/, QJSEngine */*scriptEngine*/) +static QObject *gamepadmanager_singletontype_provider(QQmlEngine * /* engine */, QJSEngine * /* scriptEngine */) { QGamepadManager *manager = QGamepadManager::instance(); QQmlEngine::setObjectOwnership(manager, QQmlEngine::CppOwnership); diff --git a/src/plugins/gamepads/android/src/qandroidgamepadbackend.cpp b/src/plugins/gamepads/android/src/qandroidgamepadbackend.cpp index 8ad5287..492e123 100644 --- a/src/plugins/gamepads/android/src/qandroidgamepadbackend.cpp +++ b/src/plugins/gamepads/android/src/qandroidgamepadbackend.cpp @@ -120,6 +120,18 @@ namespace { axisMap[motionField("AXIS_HAT_Y")].gamepadAxis = QGamepadManager::AxisLeftY; axisMap[motionField("AXIS_Z")].gamepadAxis = QGamepadManager::AxisRightX; axisMap[motionField("AXIS_RZ")].gamepadAxis = QGamepadManager::AxisRightY; + { + auto &axis = axisMap[motionField("AXIS_LTRIGGER")]; + axis.gamepadAxis = QGamepadManager::AxisInvalid; + axis.gamepadMinButton = QGamepadManager::ButtonL2; + axis.gamepadMaxButton = QGamepadManager::ButtonL2; + } + { + auto &axis = axisMap[motionField("AXIS_RTRIGGER")]; + axis.gamepadAxis = QGamepadManager::AxisInvalid; + axis.gamepadMinButton = QGamepadManager::ButtonR2; + axis.gamepadMaxButton = QGamepadManager::ButtonR2; + } allAndroidAxes.push_back(motionField("AXIS_X")); allAndroidAxes.push_back(motionField("AXIS_Y")); @@ -140,13 +152,14 @@ namespace { allAndroidAxes.push_back(motionField("AXIS_WHEEL")); } - acceptedSources.push_back(inputDeviceField("SOURCE_DPAD")); if (QtAndroidPrivate::androidSdkVersion() >= 12) { acceptedSources.push_back(inputDeviceField("SOURCE_GAMEPAD")); acceptedSources.push_back(inputDeviceField("SOURCE_CLASS_JOYSTICK")); if (QtAndroidPrivate::androidSdkVersion() >= 21) { acceptedSources.push_back(inputDeviceField("SOURCE_HDMI")); } + } else { + acceptedSources.push_back(inputDeviceField("SOURCE_DPAD")); } ACTION_DOWN = keyField("ACTION_DOWN"); @@ -186,22 +199,43 @@ namespace { const char qtGamePadClassName[] = "org/qtproject/qt5/android/gamepad/QtGamepad"; - inline void setAxisInfo(QJNIObjectPrivate &motionRange, QAndroidGamepadBackend::Mapping::AndroidAxisInfo &info) + inline void setAxisInfo(QJNIObjectPrivate &event, int axis, QAndroidGamepadBackend::Mapping::AndroidAxisInfo &info) { - if (motionRange.isValid()) { - info.flatArea = motionRange.callMethod<jfloat>("getFlat", "()F"); - info.minValue = motionRange.callMethod<jfloat>("getMin", "()F"); - info.maxValue = motionRange.callMethod<jfloat>("getMax", "()F"); - info.fuzz = motionRange.callMethod<jfloat>("getFuzz", "()F"); - } else { - info.flatArea = 0; + QJNIObjectPrivate device(event.callObjectMethod("getDevice", "()Landroid/view/InputDevice;")); + if (device.isValid()) { + const int source = event.callMethod<jint>("getSource", "()I"); + QJNIObjectPrivate motionRange = device.callObjectMethod("getMotionRange","(II)Landroid/view/InputDevice$MotionRange;", axis, source); + if (motionRange.isValid()) { + info.flatArea = motionRange.callMethod<jfloat>("getFlat", "()F"); + info.minValue = motionRange.callMethod<jfloat>("getMin", "()F"); + info.maxValue = motionRange.callMethod<jfloat>("getMax", "()F"); + info.fuzz = motionRange.callMethod<jfloat>("getFuzz", "()F"); + return; + } } + info.flatArea = 0; } } // namespace Q_GLOBAL_STATIC(DefaultMapping, g_defaultMapping) +void QAndroidGamepadBackend::Mapping::AndroidAxisInfo::restoreSavedData(const QVariantMap &value) +{ + gamepadAxis = QGamepadManager::GamepadAxis(value[QLatin1Literal("axis")].toInt()); + gamepadMinButton = QGamepadManager::GamepadButton(value[QLatin1Literal("minButton")].toInt()); + gamepadMaxButton = QGamepadManager::GamepadButton(value[QLatin1Literal("maxButton")].toInt()); +} + +QVariantMap QAndroidGamepadBackend::Mapping::AndroidAxisInfo::dataToSave() const +{ + QVariantMap data; + data[QLatin1Literal("axis")] = gamepadAxis; + data[QLatin1Literal("minButton")] = gamepadMinButton; + data[QLatin1Literal("maxButton")] = gamepadMaxButton; + return data; +} + QAndroidGamepadBackend::QAndroidGamepadBackend(QObject *parent) : QGamepadBackend(parent) { @@ -233,7 +267,7 @@ void QAndroidGamepadBackend::addDevice(int deviceId) if (acceptable) { m_devices.insert(deviceId, *g_defaultMapping()); - int productId = inputDevice.callMethod<jint>("getProductId", "()I"); + int productId = qHash(inputDevice.callObjectMethod("getDescriptor", "()Ljava/lang/String;").toString()); m_devices[deviceId].productId = productId; if (productId) { QVariant settings = readSettings(productId); @@ -243,7 +277,7 @@ void QAndroidGamepadBackend::addDevice(int deviceId) QVariantMap data = settings.toMap()[AXES_KEY].toMap(); for (QVariantMap::const_iterator it = data.begin(); it != data.end(); ++it) - deviceInfo.axisMap[it.key().toInt()].gamepadAxis = QGamepadManager::GamepadAxis(it.value().toInt()); + deviceInfo.axisMap[it.key().toInt()].restoreSavedData(it.value().toMap()); data = settings.toMap()[BUTTONS_KEY].toMap(); for (QVariantMap::const_iterator it = data.begin(); it != data.end(); ++it) @@ -330,9 +364,12 @@ void QAndroidGamepadBackend::resetConfiguration(int deviceId) if (it == m_devices.end()) return; - int productId = it.value().productId; - it.value() = *g_defaultMapping(); - it.value().productId = productId; + it.value().axisMap.clear(); + it.value().buttonsMap.clear(); + it.value().calibrateButton = QGamepadManager::ButtonInvalid; + it.value().calibrateAxis = QGamepadManager::AxisInvalid; + it.value().cancelConfigurationButton = QGamepadManager::ButtonInvalid; + it.value().needsConfigure = false; } bool QAndroidGamepadBackend::handleKeyEvent(jobject event) @@ -412,12 +449,13 @@ bool QAndroidGamepadBackend::handleGenericMotionEvent(jobject event) return false; auto &deviceMap = deviceIt.value(); - if (deviceMap.calibrateAxis != QGamepadManager::AxisInvalid) { + if (deviceMap.calibrateAxis != QGamepadManager::AxisInvalid || + deviceMap.calibrateButton != QGamepadManager::ButtonInvalid) { double lastValue = 0; int lastAxis = -1; for (int axis : g_defaultMapping()->allAndroidAxes) { - double value = fabs(ev.callMethod<jfloat>("getAxisValue", "(I)F", axis)); - if (value > lastValue) { + double value = ev.callMethod<jfloat>("getAxisValue", "(I)F", axis); + if (fabs(value) > fabs(lastValue)) { lastValue = value; lastAxis = axis; } @@ -426,46 +464,98 @@ bool QAndroidGamepadBackend::handleGenericMotionEvent(jobject event) if (!lastValue || lastAxis == -1) return false; - deviceMap.axisMap[lastAxis].gamepadAxis = deviceMap.calibrateAxis; - auto axis = deviceMap.calibrateAxis; - deviceMap.calibrateAxis = QGamepadManager::AxisInvalid; - saveData(deviceMap); - FunctionEvent::runOnQtThread(this, [this, deviceId, axis]{ - emit axisConfigured(deviceId, axis); - }); + if (deviceMap.calibrateAxis != QGamepadManager::AxisInvalid) { + deviceMap.axisMap[lastAxis].gamepadAxis = deviceMap.calibrateAxis; + auto axis = deviceMap.calibrateAxis; + deviceMap.calibrateAxis = QGamepadManager::AxisInvalid; + saveData(deviceMap); + FunctionEvent::runOnQtThread(this, [this, deviceId, axis]{ + emit axisConfigured(deviceId, axis); + }); + } else if (deviceMap.calibrateButton != QGamepadManager::ButtonInvalid && + deviceMap.calibrateButton != QGamepadManager::ButtonUp && + deviceMap.calibrateButton != QGamepadManager::ButtonDown && + deviceMap.calibrateButton != QGamepadManager::ButtonLeft && + deviceMap.calibrateButton != QGamepadManager::ButtonRight) { + auto &axis = deviceMap.axisMap[lastAxis]; + axis.gamepadAxis = QGamepadManager::AxisInvalid; + setAxisInfo(ev, lastAxis, axis); + bool save = false; + if (lastValue == axis.minValue) { + axis.gamepadMinButton = deviceMap.calibrateButton; + if (axis.gamepadMaxButton == QGamepadManager::ButtonInvalid) + axis.gamepadMaxButton = deviceMap.calibrateButton; + save = true; + } else if (lastValue == axis.maxValue) { + axis.gamepadMaxButton = deviceMap.calibrateButton; + if (axis.gamepadMinButton == QGamepadManager::ButtonInvalid) + axis.gamepadMinButton = deviceMap.calibrateButton; + save = true; + } + + if (save) { + auto but = deviceMap.calibrateButton; + deviceMap.calibrateButton = QGamepadManager::ButtonInvalid; + saveData(deviceMap); + FunctionEvent::runOnQtThread(this, [this, deviceId, but]{ + emit buttonConfigured(deviceId, but); + }); + } + } } typedef QPair<QGamepadManager::GamepadAxis, double> GamepadAxisValue; - QVector<GamepadAxisValue> values; - for (auto it = deviceMap.axisMap.begin(); it != deviceMap.axisMap.end(); ++it) { - auto &axisInfo = it.value(); - if (axisInfo.flatArea == -1) { - // compute the range & flat area - QJNIObjectPrivate device(ev.callObjectMethod("getDevice", "()Landroid/view/InputDevice;")); - if (device.isValid()) { - const int source = ev.callMethod<jint>("getSource", "()I"); - QJNIObjectPrivate motionRange = device.callObjectMethod("getMotionRange","(II)Landroid/view/InputDevice$MotionRange;", it.key(), source); - setAxisInfo(motionRange, axisInfo); + QVector<GamepadAxisValue> axisValues; + typedef QPair<QGamepadManager::GamepadButton, double> GamepadButtonValue; + QVector<GamepadButtonValue> buttonValues; + auto setValue = [&axisValues, &buttonValues](Mapping::AndroidAxisInfo &axisInfo, double value) { + if (axisInfo.setValue(value)) { + if (axisInfo.gamepadAxis != QGamepadManager::AxisInvalid) { + axisValues.push_back(GamepadAxisValue(axisInfo.gamepadAxis, axisInfo.lastValue)); + } else { + if (axisInfo.lastValue < 0) { + buttonValues.push_back(GamepadButtonValue(axisInfo.gamepadMinButton, axisInfo.lastValue)); + axisInfo.gamepadLastButton = axisInfo.gamepadMinButton; + } else if (axisInfo.lastValue > 0) { + buttonValues.push_back(GamepadButtonValue(axisInfo.gamepadMaxButton, axisInfo.lastValue)); + axisInfo.gamepadLastButton = axisInfo.gamepadMaxButton; + } else { + buttonValues.push_back(GamepadButtonValue(axisInfo.gamepadLastButton, 0.0)); + axisInfo.gamepadLastButton = QGamepadManager::ButtonInvalid; + } } } - + }; + for (auto it = deviceMap.axisMap.begin(); it != deviceMap.axisMap.end(); ++it) { + auto &axisInfo = it.value(); + if (axisInfo.flatArea == -1) + setAxisInfo(ev, it.key(), axisInfo); const int historicalValues = ev.callMethod<jint>("getHistorySize", "()I"); for (int i = 0; i < historicalValues; ++i) { double value = ev.callMethod<jfloat>("getHistoricalAxisValue", "(II)F", it.key(), i); - if (axisInfo.setValue(value)) - values.push_back(GamepadAxisValue(axisInfo.gamepadAxis, axisInfo.lastValue)); + setValue(axisInfo, value); } double value = ev.callMethod<jfloat>("getAxisValue", "(I)F", it.key()); - if (axisInfo.setValue(value)) - values.push_back(GamepadAxisValue(axisInfo.gamepadAxis, axisInfo.lastValue)); + setValue(axisInfo, value); } - if (!values.isEmpty()) { - FunctionEvent::runOnQtThread(this, [this, deviceId, values]{ - foreach (const auto &axisValue, values) + if (!axisValues.isEmpty()) { + FunctionEvent::runOnQtThread(this, [this, deviceId, axisValues]{ + foreach (const auto &axisValue, axisValues) emit gamepadAxisMoved(deviceId, axisValue.first, axisValue.second); }); } + + if (!buttonValues.isEmpty()) { + FunctionEvent::runOnQtThread(this, [this, deviceId, buttonValues]{ + foreach (const auto &buttonValue, buttonValues) + if (buttonValue.second) + emit gamepadButtonPressed(deviceId, buttonValue.first, fabs(buttonValue.second)); + else + emit gamepadButtonReleased(deviceId, buttonValue.first); + }); + } + return false; } @@ -505,7 +595,7 @@ void QAndroidGamepadBackend::saveData(const QAndroidGamepadBackend::Mapping &dev QVariantMap settings, data; for (auto it = deviceInfo.axisMap.begin(); it != deviceInfo.axisMap.end(); ++it) - data[QString::number(it.key())] = it.value().gamepadAxis; + data[QString::number(it.key())] = it.value().dataToSave(); settings[AXES_KEY] = data; data.clear(); diff --git a/src/plugins/gamepads/android/src/qandroidgamepadbackend_p.h b/src/plugins/gamepads/android/src/qandroidgamepadbackend_p.h index 764a530..4ef6552 100644 --- a/src/plugins/gamepads/android/src/qandroidgamepadbackend_p.h +++ b/src/plugins/gamepads/android/src/qandroidgamepadbackend_p.h @@ -101,10 +101,15 @@ public: lastValue = value; return true; } + void restoreSavedData(const QVariantMap &value); + QVariantMap dataToSave() const; double flatArea = -1; double fuzz = 0; double lastValue = 0; + QGamepadManager::GamepadButton gamepadMinButton = QGamepadManager::ButtonInvalid; + QGamepadManager::GamepadButton gamepadMaxButton = QGamepadManager::ButtonInvalid; + QGamepadManager::GamepadButton gamepadLastButton = QGamepadManager::ButtonInvalid; }; QHash<int, AndroidAxisInfo> axisMap; QHash<int, QGamepadManager::GamepadButton> buttonsMap; @@ -113,7 +118,7 @@ public: QGamepadManager::GamepadAxis calibrateAxis = QGamepadManager::AxisInvalid; QGamepadManager::GamepadButton cancelConfigurationButton = QGamepadManager::ButtonInvalid; int productId = 0; - bool needsConfigure = true; + bool needsConfigure = false; }; private: |