mirror of
https://github.com/servo/servo
synced 2026-04-25 17:15:48 +02:00
Gamepad: Implement gamepad buttons to be array, removing GamepadList (#44357)
Replaced `GamepadButtonList` interface with a frozen array of gamepad buttons to match the gamepad webidl specification. Testing: No idlharness tests possible since the values can't be accessed without a real gamepad. Fixes: #44333 --------- Signed-off-by: Rover track <rishan.pgowda@gmail.com>
This commit is contained in:
@@ -6,19 +6,20 @@ use std::cell::Cell;
|
||||
|
||||
use dom_struct::dom_struct;
|
||||
use embedder_traits::{GamepadSupportedHapticEffects, GamepadUpdateType};
|
||||
use js::rust::MutableHandleValue;
|
||||
use js::typedarray::{Float64, HeapFloat64Array};
|
||||
use script_bindings::trace::RootedTraceableBox;
|
||||
|
||||
use super::gamepadbuttonlist::GamepadButtonList;
|
||||
use super::gamepadbutton::GamepadButton;
|
||||
use super::gamepadhapticactuator::GamepadHapticActuator;
|
||||
use super::gamepadpose::GamepadPose;
|
||||
use crate::dom::bindings::buffer_source::HeapBufferSource;
|
||||
use crate::dom::bindings::codegen::Bindings::GamepadBinding::{GamepadHand, GamepadMethods};
|
||||
use crate::dom::bindings::codegen::Bindings::GamepadButtonListBinding::GamepadButtonListMethods;
|
||||
use crate::dom::bindings::frozenarray::CachedFrozenArray;
|
||||
use crate::dom::bindings::inheritance::Castable;
|
||||
use crate::dom::bindings::num::Finite;
|
||||
use crate::dom::bindings::reflector::{DomGlobal, Reflector, reflect_dom_object};
|
||||
use crate::dom::bindings::root::{Dom, DomRoot};
|
||||
use crate::dom::bindings::root::{Dom, DomRoot, DomSlice};
|
||||
use crate::dom::bindings::str::DOMString;
|
||||
use crate::dom::event::Event;
|
||||
use crate::dom::eventtarget::EventTarget;
|
||||
@@ -45,7 +46,9 @@ pub(crate) struct Gamepad {
|
||||
mapping_type: String,
|
||||
#[ignore_malloc_size_of = "mozjs"]
|
||||
axes: HeapBufferSource<Float64>,
|
||||
buttons: Dom<GamepadButtonList>,
|
||||
#[ignore_malloc_size_of = "mozjs"]
|
||||
frozen_buttons: CachedFrozenArray,
|
||||
buttons: Vec<Dom<GamepadButton>>,
|
||||
pose: Option<Dom<GamepadPose>>,
|
||||
#[ignore_malloc_size_of = "Defined in rust-webvr"]
|
||||
hand: GamepadHand,
|
||||
@@ -64,7 +67,7 @@ impl Gamepad {
|
||||
connected: bool,
|
||||
timestamp: f64,
|
||||
mapping_type: String,
|
||||
buttons: &GamepadButtonList,
|
||||
buttons: &[&GamepadButton],
|
||||
pose: Option<&GamepadPose>,
|
||||
hand: GamepadHand,
|
||||
axis_bounds: (f64, f64),
|
||||
@@ -80,7 +83,11 @@ impl Gamepad {
|
||||
timestamp: Cell::new(timestamp),
|
||||
mapping_type,
|
||||
axes: HeapBufferSource::default(),
|
||||
buttons: Dom::from_ref(buttons),
|
||||
frozen_buttons: CachedFrozenArray::new(),
|
||||
buttons: buttons
|
||||
.iter()
|
||||
.map(|button| Dom::from_ref(*button))
|
||||
.collect(),
|
||||
pose: pose.map(Dom::from_ref),
|
||||
hand,
|
||||
axis_bounds,
|
||||
@@ -107,7 +114,8 @@ impl Gamepad {
|
||||
xr: bool,
|
||||
can_gc: CanGc,
|
||||
) -> DomRoot<Gamepad> {
|
||||
let button_list = GamepadButtonList::init_buttons(window, can_gc);
|
||||
let buttons = Gamepad::init_buttons(window, can_gc);
|
||||
rooted_vec!(let buttons <- buttons.iter().map(DomRoot::as_traced));
|
||||
let vibration_actuator =
|
||||
GamepadHapticActuator::new(window, gamepad_id, supported_haptic_effects, can_gc);
|
||||
let index = if xr { -1 } else { 0 };
|
||||
@@ -119,7 +127,7 @@ impl Gamepad {
|
||||
true,
|
||||
0.,
|
||||
mapping_type,
|
||||
&button_list,
|
||||
buttons.r(),
|
||||
None,
|
||||
GamepadHand::_empty,
|
||||
axis_bounds,
|
||||
@@ -168,8 +176,18 @@ impl GamepadMethods<crate::DomTypeHolder> for Gamepad {
|
||||
}
|
||||
|
||||
/// <https://w3c.github.io/gamepad/#dom-gamepad-buttons>
|
||||
fn Buttons(&self) -> DomRoot<GamepadButtonList> {
|
||||
DomRoot::from_ref(&*self.buttons)
|
||||
fn Buttons(&self, cx: JSContext, retval: MutableHandleValue) {
|
||||
self.frozen_buttons.get_or_init(
|
||||
|| {
|
||||
self.buttons
|
||||
.iter()
|
||||
.map(|b| DomRoot::from_ref(&**b))
|
||||
.collect()
|
||||
},
|
||||
cx,
|
||||
retval,
|
||||
CanGc::deprecated_note(),
|
||||
);
|
||||
}
|
||||
|
||||
/// <https://w3c.github.io/gamepad/#dom-gamepad-vibrationactuator>
|
||||
@@ -194,6 +212,30 @@ impl Gamepad {
|
||||
self.gamepad_id
|
||||
}
|
||||
|
||||
/// Initialize the standard buttons for a gamepad.
|
||||
/// <https://www.w3.org/TR/gamepad/#dfn-initializing-buttons>
|
||||
fn init_buttons(window: &Window, can_gc: CanGc) -> Vec<DomRoot<GamepadButton>> {
|
||||
vec![
|
||||
GamepadButton::new(window, false, false, can_gc), // Bottom button in right cluster
|
||||
GamepadButton::new(window, false, false, can_gc), // Right button in right cluster
|
||||
GamepadButton::new(window, false, false, can_gc), // Left button in right cluster
|
||||
GamepadButton::new(window, false, false, can_gc), // Top button in right cluster
|
||||
GamepadButton::new(window, false, false, can_gc), // Top left front button
|
||||
GamepadButton::new(window, false, false, can_gc), // Top right front button
|
||||
GamepadButton::new(window, false, false, can_gc), // Bottom left front button
|
||||
GamepadButton::new(window, false, false, can_gc), // Bottom right front button
|
||||
GamepadButton::new(window, false, false, can_gc), // Left button in center cluster
|
||||
GamepadButton::new(window, false, false, can_gc), // Right button in center cluster
|
||||
GamepadButton::new(window, false, false, can_gc), // Left stick pressed button
|
||||
GamepadButton::new(window, false, false, can_gc), // Right stick pressed button
|
||||
GamepadButton::new(window, false, false, can_gc), // Top button in left cluster
|
||||
GamepadButton::new(window, false, false, can_gc), // Bottom button in left cluster
|
||||
GamepadButton::new(window, false, false, can_gc), // Left button in left cluster
|
||||
GamepadButton::new(window, false, false, can_gc), // Right button in left cluster
|
||||
GamepadButton::new(window, false, false, can_gc), // Center button in center cluster
|
||||
]
|
||||
}
|
||||
|
||||
pub(crate) fn update_connected(&self, connected: bool, has_gesture: bool, can_gc: CanGc) {
|
||||
if self.connected.get() == connected {
|
||||
return;
|
||||
@@ -279,8 +321,9 @@ impl Gamepad {
|
||||
if normalized_value.is_finite() {
|
||||
let pressed = normalized_value >= BUTTON_PRESS_THRESHOLD;
|
||||
// TODO: Determine a way of getting touch capability for button
|
||||
if let Some(button) = self.buttons.IndexedGetter(button_index as u32) {
|
||||
if let Some(button) = self.buttons.get(button_index) {
|
||||
button.update(pressed, /*touched*/ pressed, normalized_value);
|
||||
self.frozen_buttons.clear();
|
||||
}
|
||||
} else {
|
||||
warn!("Button value is not finite!");
|
||||
|
||||
@@ -1,87 +0,0 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use dom_struct::dom_struct;
|
||||
|
||||
use crate::dom::bindings::codegen::Bindings::GamepadButtonListBinding::GamepadButtonListMethods;
|
||||
use crate::dom::bindings::reflector::{Reflector, reflect_dom_object};
|
||||
use crate::dom::bindings::root::{Dom, DomRoot, DomSlice};
|
||||
use crate::dom::gamepad::gamepadbutton::GamepadButton;
|
||||
use crate::dom::window::Window;
|
||||
use crate::script_runtime::CanGc;
|
||||
|
||||
// https://w3c.github.io/gamepad/#gamepadbutton-interface
|
||||
#[dom_struct]
|
||||
pub(crate) struct GamepadButtonList {
|
||||
reflector_: Reflector,
|
||||
list: Vec<Dom<GamepadButton>>,
|
||||
}
|
||||
|
||||
impl GamepadButtonList {
|
||||
fn new_inherited(list: &[&GamepadButton]) -> GamepadButtonList {
|
||||
GamepadButtonList {
|
||||
reflector_: Reflector::new(),
|
||||
list: list.iter().map(|button| Dom::from_ref(*button)).collect(),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn new(
|
||||
window: &Window,
|
||||
list: &[&GamepadButton],
|
||||
can_gc: CanGc,
|
||||
) -> DomRoot<GamepadButtonList> {
|
||||
reflect_dom_object(
|
||||
Box::new(GamepadButtonList::new_inherited(list)),
|
||||
window,
|
||||
can_gc,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl GamepadButtonListMethods<crate::DomTypeHolder> for GamepadButtonList {
|
||||
/// <https://w3c.github.io/gamepad/#dom-gamepad-buttons>
|
||||
fn Length(&self) -> u32 {
|
||||
self.list.len() as u32
|
||||
}
|
||||
|
||||
/// <https://w3c.github.io/gamepad/#dom-gamepad-buttons>
|
||||
fn Item(&self, index: u32) -> Option<DomRoot<GamepadButton>> {
|
||||
self.list
|
||||
.get(index as usize)
|
||||
.map(|button| DomRoot::from_ref(&**button))
|
||||
}
|
||||
|
||||
/// <https://w3c.github.io/gamepad/#dom-gamepad-buttons>
|
||||
fn IndexedGetter(&self, index: u32) -> Option<DomRoot<GamepadButton>> {
|
||||
self.Item(index)
|
||||
}
|
||||
}
|
||||
|
||||
impl GamepadButtonList {
|
||||
/// Initialize the number of buttons in the "standard" gamepad mapping.
|
||||
/// <https://www.w3.org/TR/gamepad/#dfn-initializing-buttons>
|
||||
pub(crate) fn init_buttons(window: &Window, can_gc: CanGc) -> DomRoot<GamepadButtonList> {
|
||||
let standard_buttons = &[
|
||||
GamepadButton::new(window, false, false, can_gc), // Bottom button in right cluster
|
||||
GamepadButton::new(window, false, false, can_gc), // Right button in right cluster
|
||||
GamepadButton::new(window, false, false, can_gc), // Left button in right cluster
|
||||
GamepadButton::new(window, false, false, can_gc), // Top button in right cluster
|
||||
GamepadButton::new(window, false, false, can_gc), // Top left front button
|
||||
GamepadButton::new(window, false, false, can_gc), // Top right front button
|
||||
GamepadButton::new(window, false, false, can_gc), // Bottom left front button
|
||||
GamepadButton::new(window, false, false, can_gc), // Bottom right front button
|
||||
GamepadButton::new(window, false, false, can_gc), // Left button in center cluster
|
||||
GamepadButton::new(window, false, false, can_gc), // Right button in center cluster
|
||||
GamepadButton::new(window, false, false, can_gc), // Left stick pressed button
|
||||
GamepadButton::new(window, false, false, can_gc), // Right stick pressed button
|
||||
GamepadButton::new(window, false, false, can_gc), // Top button in left cluster
|
||||
GamepadButton::new(window, false, false, can_gc), // Bottom button in left cluster
|
||||
GamepadButton::new(window, false, false, can_gc), // Left button in left cluster
|
||||
GamepadButton::new(window, false, false, can_gc), // Right button in left cluster
|
||||
GamepadButton::new(window, false, false, can_gc), // Center button in center cluster
|
||||
];
|
||||
rooted_vec!(let buttons <- standard_buttons.iter().map(DomRoot::as_traced));
|
||||
Self::new(window, buttons.r(), can_gc)
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,6 @@
|
||||
pub(crate) mod gamepad;
|
||||
pub(crate) use gamepad::Gamepad;
|
||||
pub(crate) mod gamepadbutton;
|
||||
pub(crate) mod gamepadbuttonlist;
|
||||
pub(crate) mod gamepadevent;
|
||||
pub(crate) mod gamepadhapticactuator;
|
||||
pub(crate) mod gamepadpose;
|
||||
|
||||
@@ -13,7 +13,7 @@ interface Gamepad {
|
||||
readonly attribute DOMHighResTimeStamp timestamp;
|
||||
readonly attribute DOMString mapping;
|
||||
readonly attribute Float64Array axes;
|
||||
[SameObject] readonly attribute GamepadButtonList buttons;
|
||||
readonly attribute any buttons;
|
||||
[SameObject] readonly attribute GamepadHapticActuator vibrationActuator;
|
||||
};
|
||||
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
// skip-unless CARGO_FEATURE_GAMEPAD
|
||||
|
||||
// https://w3c.github.io/gamepad/#dom-gamepad-buttons
|
||||
[Exposed=Window, Pref="dom_gamepad_enabled"]
|
||||
interface GamepadButtonList {
|
||||
getter GamepadButton? item(unsigned long index);
|
||||
readonly attribute unsigned long length;
|
||||
};
|
||||
2
tests/wpt/mozilla/meta/MANIFEST.json
vendored
2
tests/wpt/mozilla/meta/MANIFEST.json
vendored
@@ -14340,7 +14340,7 @@
|
||||
]
|
||||
],
|
||||
"interfaces.https.html": [
|
||||
"566deaac42e0f430fadcbd28bf4dba751c7ba39a",
|
||||
"decaa2df2047787dbfc4b83d09ce49b117a7a53c",
|
||||
[
|
||||
null,
|
||||
{}
|
||||
|
||||
@@ -112,7 +112,6 @@ test_interfaces([
|
||||
"GainNode",
|
||||
"Gamepad",
|
||||
"GamepadButton",
|
||||
"GamepadButtonList",
|
||||
"GamepadEvent",
|
||||
"GamepadHapticActuator",
|
||||
"GamepadPose",
|
||||
|
||||
Reference in New Issue
Block a user