From 40778d7f299777d5c395e0e742532f214ee5c799 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Wed, 8 Jun 2016 10:41:19 -0700 Subject: [PATCH] Allow env disabling of the keyboard. Show keyboard after short delay to avoid flickers --- plugins/openvr/src/OpenVrHelpers.cpp | 64 ++++++++++++++++++++-------- 1 file changed, 47 insertions(+), 17 deletions(-) diff --git a/plugins/openvr/src/OpenVrHelpers.cpp b/plugins/openvr/src/OpenVrHelpers.cpp index 6533371db8..1ff1c65ef8 100644 --- a/plugins/openvr/src/OpenVrHelpers.cpp +++ b/plugins/openvr/src/OpenVrHelpers.cpp @@ -99,19 +99,33 @@ static char textArray[8192]; static QMetaObject::Connection _focusConnection, _focusTextConnection; extern bool _openVrDisplayActive; static vr::IVROverlay* _overlay { nullptr }; -static QObject* _focusObject { nullptr }; +static QObject* _keyboardFocusObject { nullptr }; static QString _existingText; static Qt::InputMethodHints _currentHints; extern vr::TrackedDevicePose_t _trackedDevicePose[vr::k_unMaxTrackedDeviceCount]; +static bool _keyboardShown { false }; +static const uint32_t SHOW_KEYBOARD_DELAY_MS = 100; void showOpenVrKeyboard(bool show = true) { - if (_overlay) { - if (show) { - auto offscreenUi = DependencyManager::get(); - _focusObject = offscreenUi->getWindow()->focusObject(); + if (!_overlay) { + return; + } - QInputMethodQueryEvent query(Qt::ImQueryInput | Qt::ImHints); - qApp->sendEvent(_focusObject, &query); + if (show) { + // To avoid flickering the keyboard when a text element is only briefly selected, + // show the keyboard asynchrnously after a very short delay, but only after we check + // that the current focus object is still one that is text enabled + QTimer::singleShot(SHOW_KEYBOARD_DELAY_MS, [] { + auto offscreenUi = DependencyManager::get(); + auto currentFocus = offscreenUi->getWindow()->focusObject(); + QInputMethodQueryEvent query(Qt::ImEnabled | Qt::ImQueryInput | Qt::ImHints); + qApp->sendEvent(currentFocus, &query); + // Current focus isn't text enabled, bail early. + if (!query.value(Qt::ImEnabled).toBool()) { + return; + } + // We're going to show the keyboard now... + _keyboardFocusObject = currentFocus; _currentHints = Qt::InputMethodHints(query.value(Qt::ImHints).toUInt()); vr::EGamepadTextInputMode inputMode = vr::k_EGamepadTextInputModeNormal; if (_currentHints & Qt::ImhHiddenText) { @@ -123,17 +137,24 @@ void showOpenVrKeyboard(bool show = true) { } _existingText = query.value(Qt::ImSurroundingText).toString(); - auto showKeyboardResult = _overlay->ShowKeyboard(inputMode, lineMode, "Keyboard", 1024, + auto showKeyboardResult = _overlay->ShowKeyboard(inputMode, lineMode, "Keyboard", 1024, _existingText.toLocal8Bit().toStdString().c_str(), false, 0); - mat4 headPose = toGlm(_trackedDevicePose[0].mDeviceToAbsoluteTracking); - mat4 keyboardTransform = glm::translate(headPose, vec3(0, -0.5, -1)); - keyboardTransform = keyboardTransform * glm::rotate(mat4(), 3.14159f / 4.0f, vec3(-1, 0, 0)); - auto keyboardTransformVr = toOpenVr(keyboardTransform); - _overlay->SetKeyboardTransformAbsolute(vr::ETrackingUniverseOrigin::TrackingUniverseStanding, &keyboardTransformVr); - } else { - _focusObject = nullptr; + if (vr::VROverlayError_None == showKeyboardResult) { + _keyboardShown = true; + // Try to position the keyboard slightly below where the user is looking. + mat4 headPose = toGlm(_trackedDevicePose[0].mDeviceToAbsoluteTracking); + mat4 keyboardTransform = glm::translate(headPose, vec3(0, -0.5, -1)); + keyboardTransform = keyboardTransform * glm::rotate(mat4(), 3.14159f / 4.0f, vec3(-1, 0, 0)); + auto keyboardTransformVr = toOpenVr(keyboardTransform); + _overlay->SetKeyboardTransformAbsolute(vr::ETrackingUniverseOrigin::TrackingUniverseStanding, &keyboardTransformVr); + } + }); + } else { + _keyboardFocusObject = nullptr; + if (_keyboardShown) { _overlay->HideKeyboard(); + _keyboardShown = false; } } } @@ -147,7 +168,7 @@ void finishOpenVrKeyboardInput() { // ImhDialableCharactersOnly ImhEmailCharactersOnly ImhUrlCharactersOnly ImhLatinOnly QInputMethodEvent event(_existingText, QList()); event.setCommitString(newText, 0, _existingText.size()); - qApp->sendEvent(_focusObject, &event); + qApp->sendEvent(_keyboardFocusObject, &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"))); @@ -155,12 +176,18 @@ void finishOpenVrKeyboardInput() { } } +static const QString DEBUG_FLAG("HIFI_DISABLE_STEAM_VR_KEYBOARD"); +bool disableSteamVrKeyboard = QProcessEnvironment::systemEnvironment().contains(DEBUG_FLAG); + void enableOpenVrKeyboard() { + if (disableSteamVrKeyboard) { + return; + } auto offscreenUi = DependencyManager::get(); _overlay = vr::VROverlay(); _focusConnection = QObject::connect(offscreenUi->getWindow(), &QQuickWindow::focusObjectChanged, [](QObject* object) { - if (object != _focusObject && _overlay) { + if (object != _keyboardFocusObject) { showOpenVrKeyboard(false); } }); @@ -174,6 +201,9 @@ void enableOpenVrKeyboard() { void disableOpenVrKeyboard() { + if (disableSteamVrKeyboard) { + return; + } QObject::disconnect(_focusTextConnection); QObject::disconnect(_focusConnection); }