mirror of
https://github.com/overte-org/overte.git
synced 2025-08-08 14:37:46 +02:00
Update SteamVR keyboard behavior
This commit is contained in:
parent
eab611acc0
commit
c2aa9e7f61
4 changed files with 95 additions and 57 deletions
|
@ -751,30 +751,9 @@ void OffscreenQmlSurface::onFocusObjectChanged(QObject* object) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
QVariant result;
|
QInputMethodQueryEvent query(Qt::ImEnabled);
|
||||||
#if 1
|
qApp->sendEvent(object, &query);
|
||||||
auto invokeResult = QMetaObject::invokeMethod(object, "inputMethodQuery", Q_RETURN_ARG(QVariant, result),
|
setFocusText(query.value(Qt::ImEnabled).toBool());
|
||||||
Q_ARG(Qt::InputMethodQuery, Qt::ImEnabled),
|
|
||||||
Q_ARG(QVariant, QVariant()));
|
|
||||||
#else
|
|
||||||
|
|
||||||
//static const char* INPUT_METHOD_QUERY_METHOD_NAME = "inputMethodQuery(Qt::InputMethodQuery, QVariant)";
|
|
||||||
static const char* INPUT_METHOD_QUERY_METHOD_NAME = "inputMethodQuery";
|
|
||||||
auto meta = object->metaObject();
|
|
||||||
qDebug() << "new focus " << object;
|
|
||||||
auto index = meta->indexOfMethod(INPUT_METHOD_QUERY_METHOD_NAME);
|
|
||||||
if (index < 0 || index >= meta->methodCount()) {
|
|
||||||
setFocusText(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto method = meta->method(index);
|
|
||||||
auto invokeResult = method.invoke(object,
|
|
||||||
Q_RETURN_ARG(QVariant, result),
|
|
||||||
Q_ARG(Qt::InputMethodQuery, Qt::ImEnabled),
|
|
||||||
Q_ARG(QVariant, QVariant()));
|
|
||||||
#endif
|
|
||||||
setFocusText(invokeResult && result.toBool());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void OffscreenQmlSurface::setFocusText(bool newFocusText) {
|
void OffscreenQmlSurface::setFocusText(bool newFocusText) {
|
||||||
|
|
|
@ -14,9 +14,13 @@
|
||||||
#include <QtCore/QTimer>
|
#include <QtCore/QTimer>
|
||||||
#include <QtCore/QLoggingCategory>
|
#include <QtCore/QLoggingCategory>
|
||||||
#include <QtCore/QProcessEnvironment>
|
#include <QtCore/QProcessEnvironment>
|
||||||
|
#include <QtGui/QInputMethodEvent>
|
||||||
|
#include <QtQuick/QQuickWindow>
|
||||||
|
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
|
|
||||||
|
#include <OffscreenUi.h>
|
||||||
|
|
||||||
Q_DECLARE_LOGGING_CATEGORY(displayplugins)
|
Q_DECLARE_LOGGING_CATEGORY(displayplugins)
|
||||||
Q_LOGGING_CATEGORY(displayplugins, "hifi.plugins.display")
|
Q_LOGGING_CATEGORY(displayplugins, "hifi.plugins.display")
|
||||||
|
|
||||||
|
@ -90,6 +94,82 @@ void releaseOpenVrSystem() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static char textArray[8192];
|
||||||
|
|
||||||
|
static QMetaObject::Connection _focusConnection, _focusTextConnection;
|
||||||
|
extern bool _openVrDisplayActive;
|
||||||
|
static vr::IVROverlay* _overlay { nullptr };
|
||||||
|
static QObject* _focusObject { nullptr };
|
||||||
|
static QString _existingText;
|
||||||
|
static Qt::InputMethodHints _currentHints;
|
||||||
|
|
||||||
|
void showOpenVrKeyboard(bool show = true) {
|
||||||
|
if (_overlay) {
|
||||||
|
if (show) {
|
||||||
|
auto offscreenUi = DependencyManager::get<OffscreenUi>();
|
||||||
|
_focusObject = offscreenUi->getWindow()->focusObject();
|
||||||
|
|
||||||
|
QInputMethodQueryEvent query(Qt::ImQueryInput | Qt::ImHints);
|
||||||
|
qApp->sendEvent(_focusObject, &query);
|
||||||
|
_currentHints = Qt::InputMethodHints(query.value(Qt::ImHints).toUInt());
|
||||||
|
vr::EGamepadTextInputMode inputMode = vr::k_EGamepadTextInputModeNormal;
|
||||||
|
if (_currentHints & Qt::ImhHiddenText) {
|
||||||
|
inputMode = vr::k_EGamepadTextInputModePassword;
|
||||||
|
}
|
||||||
|
vr::EGamepadTextInputLineMode lineMode = vr::k_EGamepadTextInputLineModeSingleLine;
|
||||||
|
if (_currentHints & Qt::ImhMultiLine) {
|
||||||
|
lineMode = vr::k_EGamepadTextInputLineModeMultipleLines;
|
||||||
|
}
|
||||||
|
_existingText = query.value(Qt::ImSurroundingText).toString();
|
||||||
|
_overlay->ShowKeyboard(inputMode, lineMode, "Keyboard", 1024, _existingText.toLocal8Bit().toStdString().c_str(), false, (uint64_t)(void*)_focusObject);
|
||||||
|
} else {
|
||||||
|
_focusObject = nullptr;
|
||||||
|
_overlay->HideKeyboard();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void finishOpenVrKeyboardInput() {
|
||||||
|
auto offscreenUi = DependencyManager::get<OffscreenUi>();
|
||||||
|
auto chars = _overlay->GetKeyboardText(textArray, 8192);
|
||||||
|
auto newText = QString(QByteArray(textArray, chars));
|
||||||
|
// TODO modify the new text to match the possible input hints:
|
||||||
|
// ImhDigitsOnly ImhFormattedNumbersOnly ImhUppercaseOnly ImhLowercaseOnly
|
||||||
|
// ImhDialableCharactersOnly ImhEmailCharactersOnly ImhUrlCharactersOnly ImhLatinOnly
|
||||||
|
QInputMethodEvent event(_existingText, QList<QInputMethodEvent::Attribute>());
|
||||||
|
event.setCommitString(newText, 0, _existingText.size());
|
||||||
|
qApp->sendEvent(_focusObject, &event);
|
||||||
|
// Simulate an enter press on the top level window to trigger the action
|
||||||
|
if (0 == (_currentHints & Qt::ImhMultiLine)) {
|
||||||
|
qApp->sendEvent(offscreenUi->getWindow(), &QKeyEvent(QEvent::KeyPress, Qt::Key_Return, Qt::KeyboardModifiers(), QString("\n")));
|
||||||
|
qApp->sendEvent(offscreenUi->getWindow(), &QKeyEvent(QEvent::KeyRelease, Qt::Key_Return, Qt::KeyboardModifiers()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void enableOpenVrKeyboard() {
|
||||||
|
auto offscreenUi = DependencyManager::get<OffscreenUi>();
|
||||||
|
_overlay = vr::VROverlay();
|
||||||
|
|
||||||
|
_focusConnection = QObject::connect(offscreenUi->getWindow(), &QQuickWindow::focusObjectChanged, [](QObject* object) {
|
||||||
|
if (object != _focusObject && _overlay) {
|
||||||
|
showOpenVrKeyboard(false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
_focusTextConnection = QObject::connect(offscreenUi.data(), &OffscreenUi::focusTextChanged, [](bool focusText) {
|
||||||
|
if (_openVrDisplayActive) {
|
||||||
|
showOpenVrKeyboard(focusText);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void disableOpenVrKeyboard() {
|
||||||
|
QObject::disconnect(_focusTextConnection);
|
||||||
|
QObject::disconnect(_focusConnection);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void handleOpenVrEvents() {
|
void handleOpenVrEvents() {
|
||||||
if (!activeHmd) {
|
if (!activeHmd) {
|
||||||
return;
|
return;
|
||||||
|
@ -107,6 +187,10 @@ void handleOpenVrEvents() {
|
||||||
activeHmd->AcknowledgeQuit_Exiting();
|
activeHmd->AcknowledgeQuit_Exiting();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case vr::VREvent_KeyboardDone:
|
||||||
|
finishOpenVrKeyboardInput();
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -114,3 +198,4 @@ void handleOpenVrEvents() {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,9 @@ vr::IVRSystem* acquireOpenVrSystem();
|
||||||
void releaseOpenVrSystem();
|
void releaseOpenVrSystem();
|
||||||
void handleOpenVrEvents();
|
void handleOpenVrEvents();
|
||||||
bool openVrQuitRequested();
|
bool openVrQuitRequested();
|
||||||
|
void enableOpenVrKeyboard();
|
||||||
|
void disableOpenVrKeyboard();
|
||||||
|
|
||||||
|
|
||||||
template<typename F>
|
template<typename F>
|
||||||
void openvr_for_each_eye(F f) {
|
void openvr_for_each_eye(F f) {
|
||||||
|
|
|
@ -11,9 +11,6 @@
|
||||||
|
|
||||||
#include "ViveControllerManager.h"
|
#include "ViveControllerManager.h"
|
||||||
|
|
||||||
#include <QtCore/QProcessEnvironment>
|
|
||||||
#include <QtQuick/QQuickWindow>
|
|
||||||
|
|
||||||
#include <PerfStat.h>
|
#include <PerfStat.h>
|
||||||
#include <PathUtils.h>
|
#include <PathUtils.h>
|
||||||
#include <GeometryCache.h>
|
#include <GeometryCache.h>
|
||||||
|
@ -57,9 +54,6 @@ bool ViveControllerManager::isSupported() const {
|
||||||
return openVrSupported();
|
return openVrSupported();
|
||||||
}
|
}
|
||||||
|
|
||||||
QMetaObject::Connection _focusConnection;
|
|
||||||
extern bool _openVrDisplayActive;
|
|
||||||
|
|
||||||
bool ViveControllerManager::activate() {
|
bool ViveControllerManager::activate() {
|
||||||
InputPlugin::activate();
|
InputPlugin::activate();
|
||||||
|
|
||||||
|
@ -72,20 +66,9 @@ bool ViveControllerManager::activate() {
|
||||||
_system = acquireOpenVrSystem();
|
_system = acquireOpenVrSystem();
|
||||||
}
|
}
|
||||||
Q_ASSERT(_system);
|
Q_ASSERT(_system);
|
||||||
auto offscreenUi = DependencyManager::get<OffscreenUi>();
|
|
||||||
_focusConnection = connect(offscreenUi.data(), &OffscreenUi::focusTextChanged, [this](bool focusText) {
|
enableOpenVrKeyboard();
|
||||||
if (_openVrDisplayActive) {
|
|
||||||
auto overlay = vr::VROverlay();
|
|
||||||
if (overlay) {
|
|
||||||
if (focusText) {
|
|
||||||
//virtual EVROverlayError ShowKeyboard( eInputMode, EGamepadTextInputLineMode eLineInputMode, const char *pchDescription, uint32_t unCharMax, const char *pchExistingText, bool bUseMinimalMode, uint64_t uUserValue) = 0;
|
|
||||||
overlay->ShowKeyboard(vr::EGamepadTextInputMode::k_EGamepadTextInputModeNormal, vr::k_EGamepadTextInputLineModeSingleLine, "Test", 1024, "", false, 0);
|
|
||||||
} else {
|
|
||||||
overlay->HideKeyboard();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
// OpenVR provides 3d mesh representations of the controllers
|
// OpenVR provides 3d mesh representations of the controllers
|
||||||
// Disabled controller rendering code
|
// Disabled controller rendering code
|
||||||
/*
|
/*
|
||||||
|
@ -150,7 +133,7 @@ bool ViveControllerManager::activate() {
|
||||||
void ViveControllerManager::deactivate() {
|
void ViveControllerManager::deactivate() {
|
||||||
InputPlugin::deactivate();
|
InputPlugin::deactivate();
|
||||||
|
|
||||||
disconnect(_focusConnection);
|
disableOpenVrKeyboard();
|
||||||
|
|
||||||
_container->removeMenuItem(MENU_NAME, RENDER_CONTROLLERS);
|
_container->removeMenuItem(MENU_NAME, RENDER_CONTROLLERS);
|
||||||
_container->removeMenu(MENU_PATH);
|
_container->removeMenu(MENU_PATH);
|
||||||
|
@ -240,18 +223,6 @@ void ViveControllerManager::pluginUpdate(float deltaTime, const controller::Inpu
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
vr::VREvent_t vrEvent;
|
|
||||||
static char textArray[8192];
|
|
||||||
while (vr::VRSystem()->PollNextEvent(&vrEvent, sizeof(vrEvent))) {
|
|
||||||
if (vrEvent.eventType == vr::VREvent_KeyboardDone) {
|
|
||||||
auto chars = vr::VROverlay()->GetKeyboardText(textArray, 8192);
|
|
||||||
QInputMethodEvent* event = new QInputMethodEvent();
|
|
||||||
event->setCommitString(QString(QByteArray(textArray, chars)), 0, 0);
|
|
||||||
auto focusObject = DependencyManager::get<OffscreenUi>()->getWindow()->focusObject();
|
|
||||||
qApp->postEvent(focusObject, event);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// because update mutates the internal state we need to lock
|
// because update mutates the internal state we need to lock
|
||||||
userInputMapper->withLock([&, this]() {
|
userInputMapper->withLock([&, this]() {
|
||||||
_inputDevice->update(deltaTime, inputCalibrationData);
|
_inputDevice->update(deltaTime, inputCalibrationData);
|
||||||
|
|
Loading…
Reference in a new issue