Commit ea496ec7 authored by Alex Cooper's avatar Alex Cooper Committed by Commit Bot

Ensure OpenVR controllers re-connect properly after suspend

If a user suspends an OpenVR immersive session whether by dropping to
a home environment (like the WMR home), or by pressing the "system"
button on the controller to show the OpenVR/Vive menu, and then
re-enters the session, the controllers would no longer be visualized.
This appears to be occuring because while the controller stayed
connected, the OpenVRRenderLoop was not able to query it's state, and
therefore stopped reporting input information on the controller.
When the controller re-connected, the RenderLoop would resume sending
data about the controller back up, but did not send a new description
because it thought it had been connected all along.

In XRSession, when a new XRInputSource was created, it defaulted to
being created as a "Gaze" source with no handedness. With no override
from the description, it stayed that way; clicks would work on the gaze
target, but no controllers/pointers would be rendered.

The fix here is to simply mark the controller as inactive if it does
not have state, thus ensuring that a new description is sent up when
the controller is again tracked/has state.

While updating this change, it was discovered that the tests report all
devices as connected, and so connecting/disconnecting a controller on
the test side would not prompt the device to be registered in product
code as newly connected (where it's device type is updated), so it
was always ignored if it was ever disconnected.  This change modifies
the WaitGetPoses method (where GetInputSources gets it's data), to
properly report the connected state of controllers.

Bug: 934355
Change-Id: Ia61c7568916cc9446366e085e74b55c413c5f6f2
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1648654Reviewed-by: default avatarBill Orr <billorr@chromium.org>
Commit-Queue: Alexander Cooper <alcooper@chromium.org>
Cr-Commit-Position: refs/heads/master@{#667209}
parent 75e06640
......@@ -58,6 +58,13 @@ device::mojom::XRHandedness ConvertToMojoHandedness(
} // namespace
void OpenVRRenderLoop::InputActiveState::MarkAsInactive() {
active = false;
primary_input_pressed = false;
device_class = vr::TrackedDeviceClass_Invalid;
controller_role = vr::TrackedControllerRole_Invalid;
}
OpenVRRenderLoop::OpenVRRenderLoop() : XRCompositorCommon() {}
OpenVRRenderLoop::~OpenVRRenderLoop() {
......@@ -233,12 +240,8 @@ std::vector<mojom::XRInputSourceStatePtr> OpenVRRenderLoop::GetInputState(
if (!pose.bDeviceIsConnected) {
// If this was an active controller on the last frame report it as
// disconnected.
if (input_active_state.active) {
input_active_state.active = false;
input_active_state.primary_input_pressed = false;
input_active_state.device_class = vr::TrackedDeviceClass_Invalid;
input_active_state.controller_role = vr::TrackedControllerRole_Invalid;
}
if (input_active_state.active)
input_active_state.MarkAsInactive();
continue;
}
......@@ -262,8 +265,10 @@ std::vector<mojom::XRInputSourceStatePtr> OpenVRRenderLoop::GetInputState(
vr::VRControllerState_t controller_state;
bool have_state = openvr_->GetSystem()->GetControllerState(
i, &controller_state, sizeof(vr::VRControllerState_t));
if (!have_state)
if (!have_state) {
input_active_state.MarkAsInactive();
continue;
}
bool pressed = controller_state.ulButtonPressed &
vr::ButtonMaskFromId(vr::k_EButton_SteamVR_Trigger);
......
......@@ -54,6 +54,8 @@ class OpenVRRenderLoop : public XRCompositorCommon {
bool primary_input_pressed;
vr::ETrackedDeviceClass device_class;
vr::ETrackedControllerRole controller_role;
void MarkAsInactive();
};
InputActiveState input_active_states_[vr::k_unMaxTrackedDeviceCount];
......
......@@ -570,10 +570,24 @@ EVRCompositorError TestVRCompositor::WaitGetPoses(TrackedDevicePose_t* poses1,
unsigned int count2) {
TrackedDevicePose_t pose = g_test_helper.GetPose(true /* presenting pose */);
for (unsigned int i = 0; i < count1; ++i) {
if (i != vr::k_unTrackedDeviceIndex_Hmd) {
VRControllerState_t controller_state;
pose.bDeviceIsConnected =
g_test_helper.GetControllerState(i, &controller_state);
} else {
pose.bDeviceIsConnected = true;
}
poses1[i] = pose;
}
for (unsigned int i = 0; i < count2; ++i) {
if (i != vr::k_unTrackedDeviceIndex_Hmd) {
VRControllerState_t controller_state;
pose.bDeviceIsConnected =
g_test_helper.GetControllerState(i, &controller_state);
} else {
pose.bDeviceIsConnected = true;
}
poses2[i] = pose;
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment