Commit b4581ba3 authored by Jacob DeWitt's avatar Jacob DeWitt Committed by Commit Bot

Send XRInputSource.profiles data to blink

This gets attached to the XRInputSourceDescription mojo struct
which is sent from XR device processes to blink.

For WMR controllers, use:
["windows-mixed-reality", "touchpad-thumbstick-controller"]

Populating this array for other platforms such as Oculus and OpenVR
will come in later CL(s).

Bug: 979250
Change-Id: I06c6666c4c085f6578630c25059d07faff158bbd
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1726903
Commit-Queue: Jacob DeWitt <jacde@chromium.org>
Reviewed-by: default avatarDaniel Cheng <dcheng@chromium.org>
Reviewed-by: default avatarAlexander Cooper <alcooper@chromium.org>
Cr-Commit-Position: refs/heads/master@{#683004}
parent b0d0f2f0
......@@ -95,6 +95,12 @@ struct XRInputSourceDescription {
// Transform from the grip matrix to the pointer's origin and orientation.
gfx.mojom.Transform? pointer_offset;
// List of 0 or more names describing both the preferred visual representation
// and behavior of the associated input source. Each name is lowercase with no
// spaces and has separate words concatenated with a "-". These names are
// sorted in descending order of specificity.
array<string> profiles;
};
struct XRInputSourceState {
......
......@@ -562,6 +562,11 @@ ParsedInputState MixedRealityInputHelper::ParseWindowsSourceState(
NOTREACHED();
}
if (is_controller) {
description->profiles.push_back("windows-mixed-reality");
description->profiles.push_back("touchpad-thumbstick-controller");
}
source_state->description = std::move(description);
input_state.source_state = std::move(source_state);
......
......@@ -83,6 +83,13 @@ XRInputSource* XRInputSource::CreateOrUpdateFrom(
updated_source->pointer_transform_matrix_ =
TryGetTransformationMatrix(desc->pointer_offset);
// Update the profiles list in-place.
// TODO(crbug.com/989244): Re-create the XRInputSource object if necessary.
updated_source->profiles_.clear();
for (const auto& name : desc->profiles) {
updated_source->profiles_.push_back(name);
}
}
updated_source->base_pose_matrix_ = TryGetTransformationMatrix(state->grip);
......
......@@ -554,6 +554,7 @@ class MockXRInputSource {
this.handedness_ = fakeInputSourceInit.handedness;
this.target_ray_mode_ = fakeInputSourceInit.targetRayMode;
this.setPointerOrigin(fakeInputSourceInit.pointerOrigin);
this.setProfiles(fakeInputSourceInit.profiles);
this.primary_input_pressed_ = false;
if (fakeInputSourceInit.selectionStarted != null) {
......@@ -593,7 +594,8 @@ class MockXRInputSource {
}
setProfiles(profiles) {
// Profiles are not yet implemented by chromium
this.desc_dirty_ = true;
this.profiles_ = profiles;
}
setGripOrigin(transform, emulatedPosition = false) {
......@@ -762,6 +764,8 @@ class MockXRInputSource {
input_desc.pointerOffset = this.pointer_offset_;
input_desc.profiles = this.profiles_;
input_state.description = input_desc;
this.desc_dirty_ = false;
......
<!DOCTYPE html>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/webxr_util.js"></script>
<script src="resources/webxr_test_constants.js"></script>
<canvas id="webgl-canvas"></canvas>
<script>
let testName = "WebXR InputSource's profiles list can be set";
let fakeDeviceInitParams = TRACKED_IMMERSIVE_DEVICE;
let testFunction = function(session, fakeDeviceController, t) {
let input_source = fakeDeviceController.simulateInputSourceConnection({
handedness: "right",
targetRayMode: "tracked-pointer",
pointerOrigin: VALID_POINTER_TRANSFORM,
profiles: ["most-specific-name", "less-specific-name"]
});
// Input events and state changes need one frame to propagate, which is why we
// are requesting an animation frame before checking the profiles list.
return new Promise((resolve) => {
session.requestAnimationFrame(() => {
let profiles = session.inputSources[0].profiles;
t.step(() => {
assert_equals(profiles.length, 2);
assert_equals(profiles[0], "most-specific-name");
assert_equals(profiles[1], "less-specific-name");
}, "Verify profiles list is set");
resolve();
});
});
};
xr_session_promise_test(
testName, testFunction, fakeDeviceInitParams, 'immersive-vr');
</script>
......@@ -48,7 +48,8 @@ let testFunction =
handedness: "right",
targetRayMode: "tracked-pointer",
pointerOrigin: POINTER_TRANSFORM_WITH_ROTATION,
gripOrigin: GRIP_TRANSFORM_WITH_ROTATION
gripOrigin: GRIP_TRANSFORM_WITH_ROTATION,
profiles: []
});
const RADIANS_90D = Math.PI / 2;
......
......@@ -60,7 +60,8 @@ function testFunction(session, fakeDeviceController, t) {
handedness: "right",
targetRayMode: "tracked-pointer",
pointerOrigin: LOCAL_POINTER_TRANSFORM,
gripOrigin: INITIAL_GRIP_TRANSFORM
gripOrigin: INITIAL_GRIP_TRANSFORM,
profiles: []
});
return new Promise((resolve, reject) => {
......
......@@ -202,11 +202,13 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
}
}
function ProcessGamepad(gamepad, hand) {
function ProcessInputSource(input_source) {
if (displayTables) {
tableManager.update(gamepad, hand);
tableManager.update(input_source);
}
let hand = input_source.handedness;
let gamepad = input_source.gamepad;
if (!(hand in boxTable)) {
const y_positions = {
"left" : 1,
......@@ -303,7 +305,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// Check for and respond to any gamepad state changes.
for (let source of session.inputSources) {
if (source.gamepad) {
ProcessGamepad(source.gamepad, source.handedness);
ProcessInputSource(source);
}
}
......
......@@ -129,19 +129,21 @@ class AxesTable extends GamepadTable {
}
class InfoTable extends GamepadTable {
constructor(gamepad, parent) {
constructor(gamepad, profiles, parent) {
super("Gamepad", 2, parent);
this.id = gamepad.id;
this.mapping = gamepad.mapping;
this.index = gamepad.index;
this.profiles_string = profiles.toString();
this.id_cell = this.AddRow(["id", gamepad.id])[1];
this.mapping_cell = this.AddRow(["mapping", gamepad.mapping])[1];
this.index_cell = this.AddRow(["index", gamepad.index])[1];
this.profiles_cell = this.AddRow(["profiles", this.profiles_string])[1];
}
update(gamepad) {
update(gamepad, profiles) {
if (this.id != gamepad.id) {
this.id_cell.innerHTML = gamepad.id;
this.id = gamepad.id;
......@@ -154,6 +156,11 @@ class InfoTable extends GamepadTable {
this.index_cell.innerHTML = gamepad.index;
this.index = gamepad.index;
}
let profiles_string = profiles.toString();
if (this.profiles_string != profiles_string) {
this.profiles_cell.innerHTML = profiles_string;
this.profiles_string = profiles_string;
}
}
}
......@@ -167,10 +174,13 @@ export class GamepadTableManager {
this.frame_number++;
}
update(gamepad, hand) {
update(input_source) {
// Construct the tables if necessary. Must check this every frame
// because otherwise, the table doesn't get created until the gamepad
// has an input change on a frame that's a multiple of 10.
let hand = input_source.handedness;
let gamepad = input_source.gamepad;
let profiles = input_source.profiles;
if (!(hand in this.tables)) {
let div = document.getElementById("gamepad-details");
let header = document.createElement("header");
......@@ -187,7 +197,7 @@ export class GamepadTableManager {
div.appendChild(header);
this.tables[hand] = {
info : new InfoTable(gamepad, details),
info : new InfoTable(gamepad, profiles, details),
axes : new AxesTable(gamepad.axes, details),
buttons : new ButtonTable(gamepad.buttons, details)
};
......@@ -195,7 +205,7 @@ export class GamepadTableManager {
// Only update the gamepad tables once every 10 frames for perf reasons.
if ((this.frame_number % 10) == 0) {
this.tables[hand].info.update(gamepad);
this.tables[hand].info.update(gamepad, profiles);
this.tables[hand].axes.update(gamepad.axes);
this.tables[hand].buttons.update(gamepad.buttons);
}
......
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