mirror of
https://github.com/servo/servo.git
synced 2025-07-23 15:23:42 +01:00
script: Move Window-only gamepad functionality out of GlobalScope (#36805)
The only code that calls these methods is in the script thread, and the code is simpler when we can assume a Window global. Pulling this thread led to cleaning up a lot of constructors for Window-only WebXR code, too. Testing: Existing WPT coverage. --------- Signed-off-by: Josh Matthews <josh@joshmatthews.net>
This commit is contained in:
parent
80d3e138a8
commit
b8971e528f
13 changed files with 199 additions and 236 deletions
|
@ -13,7 +13,7 @@ use crate::dom::bindings::codegen::Bindings::GamepadBinding::{GamepadHand, Gamep
|
||||||
use crate::dom::bindings::codegen::Bindings::GamepadButtonListBinding::GamepadButtonListMethods;
|
use crate::dom::bindings::codegen::Bindings::GamepadButtonListBinding::GamepadButtonListMethods;
|
||||||
use crate::dom::bindings::inheritance::Castable;
|
use crate::dom::bindings::inheritance::Castable;
|
||||||
use crate::dom::bindings::num::Finite;
|
use crate::dom::bindings::num::Finite;
|
||||||
use crate::dom::bindings::reflector::{DomGlobal, Reflector, reflect_dom_object_with_proto};
|
use crate::dom::bindings::reflector::{DomGlobal, Reflector, reflect_dom_object};
|
||||||
use crate::dom::bindings::root::{Dom, DomRoot};
|
use crate::dom::bindings::root::{Dom, DomRoot};
|
||||||
use crate::dom::bindings::str::DOMString;
|
use crate::dom::bindings::str::DOMString;
|
||||||
use crate::dom::event::Event;
|
use crate::dom::event::Event;
|
||||||
|
@ -23,6 +23,7 @@ use crate::dom::gamepadevent::{GamepadEvent, GamepadEventType};
|
||||||
use crate::dom::gamepadhapticactuator::GamepadHapticActuator;
|
use crate::dom::gamepadhapticactuator::GamepadHapticActuator;
|
||||||
use crate::dom::gamepadpose::GamepadPose;
|
use crate::dom::gamepadpose::GamepadPose;
|
||||||
use crate::dom::globalscope::GlobalScope;
|
use crate::dom::globalscope::GlobalScope;
|
||||||
|
use crate::dom::window::Window;
|
||||||
use crate::script_runtime::{CanGc, JSContext};
|
use crate::script_runtime::{CanGc, JSContext};
|
||||||
|
|
||||||
// This value is for determining when to consider a gamepad as having a user gesture
|
// This value is for determining when to consider a gamepad as having a user gesture
|
||||||
|
@ -88,39 +89,14 @@ impl Gamepad {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::too_many_arguments)]
|
|
||||||
pub(crate) fn new(
|
|
||||||
global: &GlobalScope,
|
|
||||||
gamepad_id: u32,
|
|
||||||
id: String,
|
|
||||||
mapping_type: String,
|
|
||||||
axis_bounds: (f64, f64),
|
|
||||||
button_bounds: (f64, f64),
|
|
||||||
supported_haptic_effects: GamepadSupportedHapticEffects,
|
|
||||||
xr: bool,
|
|
||||||
can_gc: CanGc,
|
|
||||||
) -> DomRoot<Gamepad> {
|
|
||||||
Self::new_with_proto(
|
|
||||||
global,
|
|
||||||
gamepad_id,
|
|
||||||
id,
|
|
||||||
mapping_type,
|
|
||||||
axis_bounds,
|
|
||||||
button_bounds,
|
|
||||||
supported_haptic_effects,
|
|
||||||
xr,
|
|
||||||
can_gc,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// When we construct a new gamepad, we initialize the number of buttons and
|
/// When we construct a new gamepad, we initialize the number of buttons and
|
||||||
/// axes corresponding to the "standard" gamepad mapping.
|
/// axes corresponding to the "standard" gamepad mapping.
|
||||||
/// The spec says UAs *may* do this for fingerprint mitigation, and it also
|
/// The spec says UAs *may* do this for fingerprint mitigation, and it also
|
||||||
/// happens to simplify implementation
|
/// happens to simplify implementation
|
||||||
/// <https://www.w3.org/TR/gamepad/#fingerprinting-mitigation>
|
/// <https://www.w3.org/TR/gamepad/#fingerprinting-mitigation>
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
fn new_with_proto(
|
pub(crate) fn new(
|
||||||
global: &GlobalScope,
|
window: &Window,
|
||||||
gamepad_id: u32,
|
gamepad_id: u32,
|
||||||
id: String,
|
id: String,
|
||||||
mapping_type: String,
|
mapping_type: String,
|
||||||
|
@ -130,11 +106,11 @@ impl Gamepad {
|
||||||
xr: bool,
|
xr: bool,
|
||||||
can_gc: CanGc,
|
can_gc: CanGc,
|
||||||
) -> DomRoot<Gamepad> {
|
) -> DomRoot<Gamepad> {
|
||||||
let button_list = GamepadButtonList::init_buttons(global, can_gc);
|
let button_list = GamepadButtonList::init_buttons(window, can_gc);
|
||||||
let vibration_actuator =
|
let vibration_actuator =
|
||||||
GamepadHapticActuator::new(global, gamepad_id, supported_haptic_effects, can_gc);
|
GamepadHapticActuator::new(window, gamepad_id, supported_haptic_effects, can_gc);
|
||||||
let index = if xr { -1 } else { 0 };
|
let index = if xr { -1 } else { 0 };
|
||||||
let gamepad = reflect_dom_object_with_proto(
|
let gamepad = reflect_dom_object(
|
||||||
Box::new(Gamepad::new_inherited(
|
Box::new(Gamepad::new_inherited(
|
||||||
gamepad_id,
|
gamepad_id,
|
||||||
id,
|
id,
|
||||||
|
@ -149,8 +125,7 @@ impl Gamepad {
|
||||||
button_bounds,
|
button_bounds,
|
||||||
&vibration_actuator,
|
&vibration_actuator,
|
||||||
)),
|
)),
|
||||||
global,
|
window,
|
||||||
None,
|
|
||||||
can_gc,
|
can_gc,
|
||||||
);
|
);
|
||||||
gamepad.init_axes(can_gc);
|
gamepad.init_axes(can_gc);
|
||||||
|
|
|
@ -10,7 +10,7 @@ use crate::dom::bindings::codegen::Bindings::GamepadButtonBinding::GamepadButton
|
||||||
use crate::dom::bindings::num::Finite;
|
use crate::dom::bindings::num::Finite;
|
||||||
use crate::dom::bindings::reflector::{Reflector, reflect_dom_object};
|
use crate::dom::bindings::reflector::{Reflector, reflect_dom_object};
|
||||||
use crate::dom::bindings::root::DomRoot;
|
use crate::dom::bindings::root::DomRoot;
|
||||||
use crate::dom::globalscope::GlobalScope;
|
use crate::dom::window::Window;
|
||||||
use crate::script_runtime::CanGc;
|
use crate::script_runtime::CanGc;
|
||||||
|
|
||||||
#[dom_struct]
|
#[dom_struct]
|
||||||
|
@ -32,14 +32,14 @@ impl GamepadButton {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn new(
|
pub(crate) fn new(
|
||||||
global: &GlobalScope,
|
window: &Window,
|
||||||
pressed: bool,
|
pressed: bool,
|
||||||
touched: bool,
|
touched: bool,
|
||||||
can_gc: CanGc,
|
can_gc: CanGc,
|
||||||
) -> DomRoot<GamepadButton> {
|
) -> DomRoot<GamepadButton> {
|
||||||
reflect_dom_object(
|
reflect_dom_object(
|
||||||
Box::new(GamepadButton::new_inherited(pressed, touched)),
|
Box::new(GamepadButton::new_inherited(pressed, touched)),
|
||||||
global,
|
window,
|
||||||
can_gc,
|
can_gc,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@ use crate::dom::bindings::codegen::Bindings::GamepadButtonListBinding::GamepadBu
|
||||||
use crate::dom::bindings::reflector::{Reflector, reflect_dom_object};
|
use crate::dom::bindings::reflector::{Reflector, reflect_dom_object};
|
||||||
use crate::dom::bindings::root::{Dom, DomRoot, DomSlice};
|
use crate::dom::bindings::root::{Dom, DomRoot, DomSlice};
|
||||||
use crate::dom::gamepadbutton::GamepadButton;
|
use crate::dom::gamepadbutton::GamepadButton;
|
||||||
use crate::dom::globalscope::GlobalScope;
|
use crate::dom::window::Window;
|
||||||
use crate::script_runtime::CanGc;
|
use crate::script_runtime::CanGc;
|
||||||
|
|
||||||
// https://w3c.github.io/gamepad/#gamepadbutton-interface
|
// https://w3c.github.io/gamepad/#gamepadbutton-interface
|
||||||
|
@ -28,13 +28,13 @@ impl GamepadButtonList {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn new(
|
pub(crate) fn new(
|
||||||
global: &GlobalScope,
|
window: &Window,
|
||||||
list: &[&GamepadButton],
|
list: &[&GamepadButton],
|
||||||
can_gc: CanGc,
|
can_gc: CanGc,
|
||||||
) -> DomRoot<GamepadButtonList> {
|
) -> DomRoot<GamepadButtonList> {
|
||||||
reflect_dom_object(
|
reflect_dom_object(
|
||||||
Box::new(GamepadButtonList::new_inherited(list)),
|
Box::new(GamepadButtonList::new_inherited(list)),
|
||||||
global,
|
window,
|
||||||
can_gc,
|
can_gc,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -62,27 +62,27 @@ impl GamepadButtonListMethods<crate::DomTypeHolder> for GamepadButtonList {
|
||||||
impl GamepadButtonList {
|
impl GamepadButtonList {
|
||||||
/// Initialize the number of buttons in the "standard" gamepad mapping.
|
/// Initialize the number of buttons in the "standard" gamepad mapping.
|
||||||
/// <https://www.w3.org/TR/gamepad/#dfn-initializing-buttons>
|
/// <https://www.w3.org/TR/gamepad/#dfn-initializing-buttons>
|
||||||
pub(crate) fn init_buttons(global: &GlobalScope, can_gc: CanGc) -> DomRoot<GamepadButtonList> {
|
pub(crate) fn init_buttons(window: &Window, can_gc: CanGc) -> DomRoot<GamepadButtonList> {
|
||||||
let standard_buttons = &[
|
let standard_buttons = &[
|
||||||
GamepadButton::new(global, false, false, can_gc), // Bottom button in right cluster
|
GamepadButton::new(window, false, false, can_gc), // Bottom button in right cluster
|
||||||
GamepadButton::new(global, false, false, can_gc), // Right button in right cluster
|
GamepadButton::new(window, false, false, can_gc), // Right button in right cluster
|
||||||
GamepadButton::new(global, false, false, can_gc), // Left button in right cluster
|
GamepadButton::new(window, false, false, can_gc), // Left button in right cluster
|
||||||
GamepadButton::new(global, false, false, can_gc), // Top button in right cluster
|
GamepadButton::new(window, false, false, can_gc), // Top button in right cluster
|
||||||
GamepadButton::new(global, false, false, can_gc), // Top left front button
|
GamepadButton::new(window, false, false, can_gc), // Top left front button
|
||||||
GamepadButton::new(global, false, false, can_gc), // Top right front button
|
GamepadButton::new(window, false, false, can_gc), // Top right front button
|
||||||
GamepadButton::new(global, false, false, can_gc), // Bottom left front button
|
GamepadButton::new(window, false, false, can_gc), // Bottom left front button
|
||||||
GamepadButton::new(global, false, false, can_gc), // Bottom right front button
|
GamepadButton::new(window, false, false, can_gc), // Bottom right front button
|
||||||
GamepadButton::new(global, false, false, can_gc), // Left button in center cluster
|
GamepadButton::new(window, false, false, can_gc), // Left button in center cluster
|
||||||
GamepadButton::new(global, false, false, can_gc), // Right button in center cluster
|
GamepadButton::new(window, false, false, can_gc), // Right button in center cluster
|
||||||
GamepadButton::new(global, false, false, can_gc), // Left stick pressed button
|
GamepadButton::new(window, false, false, can_gc), // Left stick pressed button
|
||||||
GamepadButton::new(global, false, false, can_gc), // Right stick pressed button
|
GamepadButton::new(window, false, false, can_gc), // Right stick pressed button
|
||||||
GamepadButton::new(global, false, false, can_gc), // Top button in left cluster
|
GamepadButton::new(window, false, false, can_gc), // Top button in left cluster
|
||||||
GamepadButton::new(global, false, false, can_gc), // Bottom button in left cluster
|
GamepadButton::new(window, false, false, can_gc), // Bottom button in left cluster
|
||||||
GamepadButton::new(global, false, false, can_gc), // Left button in left cluster
|
GamepadButton::new(window, false, false, can_gc), // Left button in left cluster
|
||||||
GamepadButton::new(global, false, false, can_gc), // Right button in left cluster
|
GamepadButton::new(window, false, false, can_gc), // Right button in left cluster
|
||||||
GamepadButton::new(global, false, false, can_gc), // Center button in center cluster
|
GamepadButton::new(window, false, false, can_gc), // Center button in center cluster
|
||||||
];
|
];
|
||||||
rooted_vec!(let buttons <- standard_buttons.iter().map(DomRoot::as_traced));
|
rooted_vec!(let buttons <- standard_buttons.iter().map(DomRoot::as_traced));
|
||||||
Self::new(global, buttons.r(), can_gc)
|
Self::new(window, buttons.r(), can_gc)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,12 +18,12 @@ use crate::dom::bindings::codegen::Bindings::GamepadHapticActuatorBinding::{
|
||||||
use crate::dom::bindings::codegen::Bindings::WindowBinding::Window_Binding::WindowMethods;
|
use crate::dom::bindings::codegen::Bindings::WindowBinding::Window_Binding::WindowMethods;
|
||||||
use crate::dom::bindings::error::Error;
|
use crate::dom::bindings::error::Error;
|
||||||
use crate::dom::bindings::refcounted::{Trusted, TrustedPromise};
|
use crate::dom::bindings::refcounted::{Trusted, TrustedPromise};
|
||||||
use crate::dom::bindings::reflector::{DomGlobal, Reflector, reflect_dom_object_with_proto};
|
use crate::dom::bindings::reflector::{DomGlobal, Reflector, reflect_dom_object};
|
||||||
use crate::dom::bindings::root::DomRoot;
|
use crate::dom::bindings::root::DomRoot;
|
||||||
use crate::dom::bindings::str::DOMString;
|
use crate::dom::bindings::str::DOMString;
|
||||||
use crate::dom::bindings::utils::to_frozen_array;
|
use crate::dom::bindings::utils::to_frozen_array;
|
||||||
use crate::dom::globalscope::GlobalScope;
|
|
||||||
use crate::dom::promise::Promise;
|
use crate::dom::promise::Promise;
|
||||||
|
use crate::dom::window::Window;
|
||||||
use crate::realms::InRealm;
|
use crate::realms::InRealm;
|
||||||
use crate::script_runtime::{CanGc, JSContext};
|
use crate::script_runtime::{CanGc, JSContext};
|
||||||
use crate::task_source::SendableTaskSource;
|
use crate::task_source::SendableTaskSource;
|
||||||
|
@ -98,27 +98,17 @@ impl GamepadHapticActuator {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn new(
|
pub(crate) fn new(
|
||||||
global: &GlobalScope,
|
window: &Window,
|
||||||
gamepad_index: u32,
|
gamepad_index: u32,
|
||||||
supported_haptic_effects: GamepadSupportedHapticEffects,
|
supported_haptic_effects: GamepadSupportedHapticEffects,
|
||||||
can_gc: CanGc,
|
can_gc: CanGc,
|
||||||
) -> DomRoot<GamepadHapticActuator> {
|
) -> DomRoot<GamepadHapticActuator> {
|
||||||
Self::new_with_proto(global, gamepad_index, supported_haptic_effects, can_gc)
|
reflect_dom_object(
|
||||||
}
|
|
||||||
|
|
||||||
fn new_with_proto(
|
|
||||||
global: &GlobalScope,
|
|
||||||
gamepad_index: u32,
|
|
||||||
supported_haptic_effects: GamepadSupportedHapticEffects,
|
|
||||||
can_gc: CanGc,
|
|
||||||
) -> DomRoot<GamepadHapticActuator> {
|
|
||||||
reflect_dom_object_with_proto(
|
|
||||||
Box::new(GamepadHapticActuator::new_inherited(
|
Box::new(GamepadHapticActuator::new_inherited(
|
||||||
gamepad_index,
|
gamepad_index,
|
||||||
supported_haptic_effects,
|
supported_haptic_effects,
|
||||||
)),
|
)),
|
||||||
global,
|
window,
|
||||||
None,
|
|
||||||
can_gc,
|
can_gc,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,9 +27,7 @@ use content_security_policy::{
|
||||||
use crossbeam_channel::Sender;
|
use crossbeam_channel::Sender;
|
||||||
use devtools_traits::{PageError, ScriptToDevtoolsControlMsg};
|
use devtools_traits::{PageError, ScriptToDevtoolsControlMsg};
|
||||||
use dom_struct::dom_struct;
|
use dom_struct::dom_struct;
|
||||||
use embedder_traits::{
|
use embedder_traits::EmbedderMsg;
|
||||||
EmbedderMsg, GamepadEvent, GamepadSupportedHapticEffects, GamepadUpdateType,
|
|
||||||
};
|
|
||||||
use http::HeaderMap;
|
use http::HeaderMap;
|
||||||
use hyper_serde::Serde;
|
use hyper_serde::Serde;
|
||||||
use ipc_channel::ipc::{self, IpcSender};
|
use ipc_channel::ipc::{self, IpcSender};
|
||||||
|
@ -81,9 +79,7 @@ use crate::dom::bindings::codegen::Bindings::FunctionBinding::Function;
|
||||||
use crate::dom::bindings::codegen::Bindings::ImageBitmapBinding::{
|
use crate::dom::bindings::codegen::Bindings::ImageBitmapBinding::{
|
||||||
ImageBitmapOptions, ImageBitmapSource,
|
ImageBitmapOptions, ImageBitmapSource,
|
||||||
};
|
};
|
||||||
use crate::dom::bindings::codegen::Bindings::NavigatorBinding::NavigatorMethods;
|
|
||||||
use crate::dom::bindings::codegen::Bindings::NotificationBinding::NotificationPermissionCallback;
|
use crate::dom::bindings::codegen::Bindings::NotificationBinding::NotificationPermissionCallback;
|
||||||
use crate::dom::bindings::codegen::Bindings::PerformanceBinding::Performance_Binding::PerformanceMethods;
|
|
||||||
use crate::dom::bindings::codegen::Bindings::PermissionStatusBinding::{
|
use crate::dom::bindings::codegen::Bindings::PermissionStatusBinding::{
|
||||||
PermissionName, PermissionState,
|
PermissionName, PermissionState,
|
||||||
};
|
};
|
||||||
|
@ -113,8 +109,6 @@ use crate::dom::event::{Event, EventBubbles, EventCancelable, EventStatus};
|
||||||
use crate::dom::eventsource::EventSource;
|
use crate::dom::eventsource::EventSource;
|
||||||
use crate::dom::eventtarget::EventTarget;
|
use crate::dom::eventtarget::EventTarget;
|
||||||
use crate::dom::file::File;
|
use crate::dom::file::File;
|
||||||
use crate::dom::gamepad::{Gamepad, contains_user_gesture};
|
|
||||||
use crate::dom::gamepadevent::GamepadEventType;
|
|
||||||
use crate::dom::htmlscriptelement::{ScriptId, SourceCode};
|
use crate::dom::htmlscriptelement::{ScriptId, SourceCode};
|
||||||
use crate::dom::imagebitmap::ImageBitmap;
|
use crate::dom::imagebitmap::ImageBitmap;
|
||||||
use crate::dom::messageevent::MessageEvent;
|
use crate::dom::messageevent::MessageEvent;
|
||||||
|
@ -3287,134 +3281,6 @@ impl GlobalScope {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn handle_gamepad_event(&self, gamepad_event: GamepadEvent) {
|
|
||||||
match gamepad_event {
|
|
||||||
GamepadEvent::Connected(index, name, bounds, supported_haptic_effects) => {
|
|
||||||
self.handle_gamepad_connect(
|
|
||||||
index.0,
|
|
||||||
name,
|
|
||||||
bounds.axis_bounds,
|
|
||||||
bounds.button_bounds,
|
|
||||||
supported_haptic_effects,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
GamepadEvent::Disconnected(index) => {
|
|
||||||
self.handle_gamepad_disconnect(index.0);
|
|
||||||
},
|
|
||||||
GamepadEvent::Updated(index, update_type) => {
|
|
||||||
self.receive_new_gamepad_button_or_axis(index.0, update_type);
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <https://www.w3.org/TR/gamepad/#dfn-gamepadconnected>
|
|
||||||
fn handle_gamepad_connect(
|
|
||||||
&self,
|
|
||||||
// As the spec actually defines how to set the gamepad index, the GilRs index
|
|
||||||
// is currently unused, though in practice it will almost always be the same.
|
|
||||||
// More infra is currently needed to track gamepads across windows.
|
|
||||||
_index: usize,
|
|
||||||
name: String,
|
|
||||||
axis_bounds: (f64, f64),
|
|
||||||
button_bounds: (f64, f64),
|
|
||||||
supported_haptic_effects: GamepadSupportedHapticEffects,
|
|
||||||
) {
|
|
||||||
// TODO: 2. If document is not null and is not allowed to use the "gamepad" permission,
|
|
||||||
// then abort these steps.
|
|
||||||
let this = Trusted::new(self);
|
|
||||||
self.task_manager()
|
|
||||||
.gamepad_task_source()
|
|
||||||
.queue(task!(gamepad_connected: move || {
|
|
||||||
let global = this.root();
|
|
||||||
|
|
||||||
if let Some(window) = global.downcast::<Window>() {
|
|
||||||
let navigator = window.Navigator();
|
|
||||||
let selected_index = navigator.select_gamepad_index();
|
|
||||||
let gamepad = Gamepad::new(
|
|
||||||
&global,
|
|
||||||
selected_index,
|
|
||||||
name,
|
|
||||||
"standard".into(),
|
|
||||||
axis_bounds,
|
|
||||||
button_bounds,
|
|
||||||
supported_haptic_effects,
|
|
||||||
false,
|
|
||||||
CanGc::note(),
|
|
||||||
);
|
|
||||||
navigator.set_gamepad(selected_index as usize, &gamepad, CanGc::note());
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <https://www.w3.org/TR/gamepad/#dfn-gamepaddisconnected>
|
|
||||||
pub(crate) fn handle_gamepad_disconnect(&self, index: usize) {
|
|
||||||
let this = Trusted::new(self);
|
|
||||||
self.task_manager()
|
|
||||||
.gamepad_task_source()
|
|
||||||
.queue(task!(gamepad_disconnected: move || {
|
|
||||||
let global = this.root();
|
|
||||||
if let Some(window) = global.downcast::<Window>() {
|
|
||||||
let navigator = window.Navigator();
|
|
||||||
if let Some(gamepad) = navigator.get_gamepad(index) {
|
|
||||||
if window.Document().is_fully_active() {
|
|
||||||
gamepad.update_connected(false, gamepad.exposed(), CanGc::note());
|
|
||||||
navigator.remove_gamepad(index);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <https://www.w3.org/TR/gamepad/#receiving-inputs>
|
|
||||||
pub(crate) fn receive_new_gamepad_button_or_axis(
|
|
||||||
&self,
|
|
||||||
index: usize,
|
|
||||||
update_type: GamepadUpdateType,
|
|
||||||
) {
|
|
||||||
let this = Trusted::new(self);
|
|
||||||
|
|
||||||
// <https://w3c.github.io/gamepad/#dfn-update-gamepad-state>
|
|
||||||
self.task_manager().gamepad_task_source().queue(
|
|
||||||
task!(update_gamepad_state: move || {
|
|
||||||
let global = this.root();
|
|
||||||
if let Some(window) = global.downcast::<Window>() {
|
|
||||||
let navigator = window.Navigator();
|
|
||||||
if let Some(gamepad) = navigator.get_gamepad(index) {
|
|
||||||
let current_time = global.performance().Now();
|
|
||||||
gamepad.update_timestamp(*current_time);
|
|
||||||
match update_type {
|
|
||||||
GamepadUpdateType::Axis(index, value) => {
|
|
||||||
gamepad.map_and_normalize_axes(index, value);
|
|
||||||
},
|
|
||||||
GamepadUpdateType::Button(index, value) => {
|
|
||||||
gamepad.map_and_normalize_buttons(index, value);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
if !navigator.has_gamepad_gesture() && contains_user_gesture(update_type) {
|
|
||||||
navigator.set_has_gamepad_gesture(true);
|
|
||||||
navigator.GetGamepads()
|
|
||||||
.iter()
|
|
||||||
.filter_map(|g| g.as_ref())
|
|
||||||
.for_each(|gamepad| {
|
|
||||||
gamepad.set_exposed(true);
|
|
||||||
gamepad.update_timestamp(*current_time);
|
|
||||||
let new_gamepad = Trusted::new(&**gamepad);
|
|
||||||
if window.Document().is_fully_active() {
|
|
||||||
global.task_manager().gamepad_task_source().queue(
|
|
||||||
task!(update_gamepad_connect: move || {
|
|
||||||
let gamepad = new_gamepad.root();
|
|
||||||
gamepad.notify_event(GamepadEventType::Connected, CanGc::note());
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn current_group_label(&self) -> Option<DOMString> {
|
pub(crate) fn current_group_label(&self) -> Option<DOMString> {
|
||||||
self.console_group_stack
|
self.console_group_stack
|
||||||
.borrow()
|
.borrow()
|
||||||
|
|
|
@ -8,7 +8,7 @@ use webxr_api::HitTestId;
|
||||||
use crate::dom::bindings::codegen::Bindings::XRHitTestSourceBinding::XRHitTestSourceMethods;
|
use crate::dom::bindings::codegen::Bindings::XRHitTestSourceBinding::XRHitTestSourceMethods;
|
||||||
use crate::dom::bindings::reflector::{Reflector, reflect_dom_object};
|
use crate::dom::bindings::reflector::{Reflector, reflect_dom_object};
|
||||||
use crate::dom::bindings::root::{Dom, DomRoot};
|
use crate::dom::bindings::root::{Dom, DomRoot};
|
||||||
use crate::dom::globalscope::GlobalScope;
|
use crate::dom::window::Window;
|
||||||
use crate::dom::xrsession::XRSession;
|
use crate::dom::xrsession::XRSession;
|
||||||
use crate::script_runtime::CanGc;
|
use crate::script_runtime::CanGc;
|
||||||
|
|
||||||
|
@ -31,14 +31,14 @@ impl XRHitTestSource {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn new(
|
pub(crate) fn new(
|
||||||
global: &GlobalScope,
|
window: &Window,
|
||||||
id: HitTestId,
|
id: HitTestId,
|
||||||
session: &XRSession,
|
session: &XRSession,
|
||||||
can_gc: CanGc,
|
can_gc: CanGc,
|
||||||
) -> DomRoot<XRHitTestSource> {
|
) -> DomRoot<XRHitTestSource> {
|
||||||
reflect_dom_object(
|
reflect_dom_object(
|
||||||
Box::new(XRHitTestSource::new_inherited(id, session)),
|
Box::new(XRHitTestSource::new_inherited(id, session)),
|
||||||
global,
|
window,
|
||||||
can_gc,
|
can_gc,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@ use crate::dom::bindings::reflector::{DomGlobal, Reflector, reflect_dom_object};
|
||||||
use crate::dom::bindings::root::{Dom, DomRoot, MutNullableDom};
|
use crate::dom::bindings::root::{Dom, DomRoot, MutNullableDom};
|
||||||
use crate::dom::gamepad::Gamepad;
|
use crate::dom::gamepad::Gamepad;
|
||||||
use crate::dom::globalscope::GlobalScope;
|
use crate::dom::globalscope::GlobalScope;
|
||||||
|
use crate::dom::window::Window;
|
||||||
use crate::dom::xrhand::XRHand;
|
use crate::dom::xrhand::XRHand;
|
||||||
use crate::dom::xrsession::XRSession;
|
use crate::dom::xrsession::XRSession;
|
||||||
use crate::dom::xrspace::XRSpace;
|
use crate::dom::xrspace::XRSpace;
|
||||||
|
@ -40,14 +41,14 @@ pub(crate) struct XRInputSource {
|
||||||
|
|
||||||
impl XRInputSource {
|
impl XRInputSource {
|
||||||
pub(crate) fn new_inherited(
|
pub(crate) fn new_inherited(
|
||||||
global: &GlobalScope,
|
window: &Window,
|
||||||
session: &XRSession,
|
session: &XRSession,
|
||||||
info: InputSource,
|
info: InputSource,
|
||||||
can_gc: CanGc,
|
can_gc: CanGc,
|
||||||
) -> XRInputSource {
|
) -> XRInputSource {
|
||||||
// <https://www.w3.org/TR/webxr-gamepads-module-1/#gamepad-differences>
|
// <https://www.w3.org/TR/webxr-gamepads-module-1/#gamepad-differences>
|
||||||
let gamepad = Gamepad::new(
|
let gamepad = Gamepad::new(
|
||||||
global,
|
window,
|
||||||
0,
|
0,
|
||||||
"".into(),
|
"".into(),
|
||||||
"xr-standard".into(),
|
"xr-standard".into(),
|
||||||
|
@ -74,18 +75,18 @@ impl XRInputSource {
|
||||||
|
|
||||||
#[allow(unsafe_code)]
|
#[allow(unsafe_code)]
|
||||||
pub(crate) fn new(
|
pub(crate) fn new(
|
||||||
global: &GlobalScope,
|
window: &Window,
|
||||||
session: &XRSession,
|
session: &XRSession,
|
||||||
info: InputSource,
|
info: InputSource,
|
||||||
can_gc: CanGc,
|
can_gc: CanGc,
|
||||||
) -> DomRoot<XRInputSource> {
|
) -> DomRoot<XRInputSource> {
|
||||||
let source = reflect_dom_object(
|
let source = reflect_dom_object(
|
||||||
Box::new(XRInputSource::new_inherited(global, session, info, can_gc)),
|
Box::new(XRInputSource::new_inherited(window, session, info, can_gc)),
|
||||||
global,
|
window,
|
||||||
can_gc,
|
can_gc,
|
||||||
);
|
);
|
||||||
|
|
||||||
let _ac = enter_realm(global);
|
let _ac = enter_realm(window);
|
||||||
let cx = GlobalScope::get_cx();
|
let cx = GlobalScope::get_cx();
|
||||||
unsafe {
|
unsafe {
|
||||||
rooted!(in(*cx) let mut profiles = UndefinedValue());
|
rooted!(in(*cx) let mut profiles = UndefinedValue());
|
||||||
|
|
|
@ -11,7 +11,7 @@ use crate::dom::bindings::inheritance::Castable;
|
||||||
use crate::dom::bindings::reflector::{DomGlobal, Reflector, reflect_dom_object};
|
use crate::dom::bindings::reflector::{DomGlobal, Reflector, reflect_dom_object};
|
||||||
use crate::dom::bindings::root::{Dom, DomRoot};
|
use crate::dom::bindings::root::{Dom, DomRoot};
|
||||||
use crate::dom::event::Event;
|
use crate::dom::event::Event;
|
||||||
use crate::dom::globalscope::GlobalScope;
|
use crate::dom::window::Window;
|
||||||
use crate::dom::xrinputsource::XRInputSource;
|
use crate::dom::xrinputsource::XRInputSource;
|
||||||
use crate::dom::xrinputsourceschangeevent::XRInputSourcesChangeEvent;
|
use crate::dom::xrinputsourceschangeevent::XRInputSourcesChangeEvent;
|
||||||
use crate::dom::xrsession::XRSession;
|
use crate::dom::xrsession::XRSession;
|
||||||
|
@ -31,10 +31,10 @@ impl XRInputSourceArray {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn new(global: &GlobalScope, can_gc: CanGc) -> DomRoot<XRInputSourceArray> {
|
pub(crate) fn new(window: &Window, can_gc: CanGc) -> DomRoot<XRInputSourceArray> {
|
||||||
reflect_dom_object(
|
reflect_dom_object(
|
||||||
Box::new(XRInputSourceArray::new_inherited()),
|
Box::new(XRInputSourceArray::new_inherited()),
|
||||||
global,
|
window,
|
||||||
can_gc,
|
can_gc,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -60,7 +60,7 @@ impl XRInputSourceArray {
|
||||||
.any(|i| i.id() == info.id),
|
.any(|i| i.id() == info.id),
|
||||||
"Should never add a duplicate input id!"
|
"Should never add a duplicate input id!"
|
||||||
);
|
);
|
||||||
let input = XRInputSource::new(&global, session, info.clone(), can_gc);
|
let input = XRInputSource::new(window, session, info.clone(), can_gc);
|
||||||
self.input_sources.borrow_mut().push(Dom::from_ref(&input));
|
self.input_sources.borrow_mut().push(Dom::from_ref(&input));
|
||||||
added.push(input);
|
added.push(input);
|
||||||
}
|
}
|
||||||
|
@ -121,7 +121,7 @@ impl XRInputSourceArray {
|
||||||
&[]
|
&[]
|
||||||
};
|
};
|
||||||
self.input_sources.borrow_mut().retain(|i| i.id() != id);
|
self.input_sources.borrow_mut().retain(|i| i.id() != id);
|
||||||
let input = XRInputSource::new(&global, session, info, can_gc);
|
let input = XRInputSource::new(window, session, info, can_gc);
|
||||||
self.input_sources.borrow_mut().push(Dom::from_ref(&input));
|
self.input_sources.borrow_mut().push(Dom::from_ref(&input));
|
||||||
|
|
||||||
let added = [input];
|
let added = [input];
|
||||||
|
|
|
@ -14,7 +14,7 @@ use crate::dom::bindings::num::Finite;
|
||||||
use crate::dom::bindings::reflector::{DomGlobal, Reflector, reflect_dom_object};
|
use crate::dom::bindings::reflector::{DomGlobal, Reflector, reflect_dom_object};
|
||||||
use crate::dom::bindings::root::{Dom, DomRoot, MutNullableDom};
|
use crate::dom::bindings::root::{Dom, DomRoot, MutNullableDom};
|
||||||
use crate::dom::bindings::utils::to_frozen_array;
|
use crate::dom::bindings::utils::to_frozen_array;
|
||||||
use crate::dom::globalscope::GlobalScope;
|
use crate::dom::window::Window;
|
||||||
use crate::dom::xrlayer::XRLayer;
|
use crate::dom::xrlayer::XRLayer;
|
||||||
use crate::dom::xrwebgllayer::XRWebGLLayer;
|
use crate::dom::xrwebgllayer::XRWebGLLayer;
|
||||||
use crate::script_runtime::{CanGc, JSContext};
|
use crate::script_runtime::{CanGc, JSContext};
|
||||||
|
@ -49,7 +49,7 @@ impl XRRenderState {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn new(
|
pub(crate) fn new(
|
||||||
global: &GlobalScope,
|
window: &Window,
|
||||||
depth_near: f64,
|
depth_near: f64,
|
||||||
depth_far: f64,
|
depth_far: f64,
|
||||||
inline_vertical_fov: Option<f64>,
|
inline_vertical_fov: Option<f64>,
|
||||||
|
@ -65,14 +65,14 @@ impl XRRenderState {
|
||||||
layer,
|
layer,
|
||||||
layers,
|
layers,
|
||||||
)),
|
)),
|
||||||
global,
|
window,
|
||||||
can_gc,
|
can_gc,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn clone_object(&self) -> DomRoot<Self> {
|
pub(crate) fn clone_object(&self) -> DomRoot<Self> {
|
||||||
XRRenderState::new(
|
XRRenderState::new(
|
||||||
&self.global(),
|
self.global().as_window(),
|
||||||
self.depth_near.get(),
|
self.depth_near.get(),
|
||||||
self.depth_far.get(),
|
self.depth_far.get(),
|
||||||
self.inline_vertical_fov.get(),
|
self.inline_vertical_fov.get(),
|
||||||
|
|
|
@ -54,8 +54,8 @@ use crate::dom::bindings::root::{Dom, DomRoot, MutDom, MutNullableDom};
|
||||||
use crate::dom::bindings::utils::to_frozen_array;
|
use crate::dom::bindings::utils::to_frozen_array;
|
||||||
use crate::dom::event::Event;
|
use crate::dom::event::Event;
|
||||||
use crate::dom::eventtarget::EventTarget;
|
use crate::dom::eventtarget::EventTarget;
|
||||||
use crate::dom::globalscope::GlobalScope;
|
|
||||||
use crate::dom::promise::Promise;
|
use crate::dom::promise::Promise;
|
||||||
|
use crate::dom::window::Window;
|
||||||
use crate::dom::xrboundedreferencespace::XRBoundedReferenceSpace;
|
use crate::dom::xrboundedreferencespace::XRBoundedReferenceSpace;
|
||||||
use crate::dom::xrframe::XRFrame;
|
use crate::dom::xrframe::XRFrame;
|
||||||
use crate::dom::xrhittestsource::XRHitTestSource;
|
use crate::dom::xrhittestsource::XRHitTestSource;
|
||||||
|
@ -152,7 +152,7 @@ impl XRSession {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn new(
|
pub(crate) fn new(
|
||||||
global: &GlobalScope,
|
window: &Window,
|
||||||
session: Session,
|
session: Session,
|
||||||
mode: XRSessionMode,
|
mode: XRSessionMode,
|
||||||
frame_receiver: IpcReceiver<Frame>,
|
frame_receiver: IpcReceiver<Frame>,
|
||||||
|
@ -163,8 +163,8 @@ impl XRSession {
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
let render_state = XRRenderState::new(global, 0.1, 1000.0, ivfov, None, Vec::new(), can_gc);
|
let render_state = XRRenderState::new(window, 0.1, 1000.0, ivfov, None, Vec::new(), can_gc);
|
||||||
let input_sources = XRInputSourceArray::new(global, can_gc);
|
let input_sources = XRInputSourceArray::new(window, can_gc);
|
||||||
let ret = reflect_dom_object(
|
let ret = reflect_dom_object(
|
||||||
Box::new(XRSession::new_inherited(
|
Box::new(XRSession::new_inherited(
|
||||||
session,
|
session,
|
||||||
|
@ -172,7 +172,7 @@ impl XRSession {
|
||||||
&input_sources,
|
&input_sources,
|
||||||
mode,
|
mode,
|
||||||
)),
|
)),
|
||||||
global,
|
window,
|
||||||
can_gc,
|
can_gc,
|
||||||
);
|
);
|
||||||
ret.attach_event_handler();
|
ret.attach_event_handler();
|
||||||
|
@ -587,7 +587,7 @@ impl XRSession {
|
||||||
FrameUpdateEvent::HitTestSourceAdded(id) => {
|
FrameUpdateEvent::HitTestSourceAdded(id) => {
|
||||||
if let Some(promise) = self.pending_hit_test_promises.borrow_mut().remove(&id) {
|
if let Some(promise) = self.pending_hit_test_promises.borrow_mut().remove(&id) {
|
||||||
promise.resolve_native(
|
promise.resolve_native(
|
||||||
&XRHitTestSource::new(&self.global(), id, self, can_gc),
|
&XRHitTestSource::new(self.global().as_window(), id, self, can_gc),
|
||||||
can_gc,
|
can_gc,
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -297,7 +297,13 @@ impl XRSystem {
|
||||||
return;
|
return;
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
let session = XRSession::new(&self.global(), session, mode, frame_receiver, CanGc::note());
|
let session = XRSession::new(
|
||||||
|
self.global().as_window(),
|
||||||
|
session,
|
||||||
|
mode,
|
||||||
|
frame_receiver,
|
||||||
|
CanGc::note(),
|
||||||
|
);
|
||||||
if mode == XRSessionMode::Inline {
|
if mode == XRSessionMode::Inline {
|
||||||
self.active_inline_sessions
|
self.active_inline_sessions
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
|
|
|
@ -32,8 +32,9 @@ use devtools_traits::{ScriptToDevtoolsControlMsg, TimelineMarker, TimelineMarker
|
||||||
use dom_struct::dom_struct;
|
use dom_struct::dom_struct;
|
||||||
use embedder_traits::user_content_manager::{UserContentManager, UserScript};
|
use embedder_traits::user_content_manager::{UserContentManager, UserScript};
|
||||||
use embedder_traits::{
|
use embedder_traits::{
|
||||||
AlertResponse, ConfirmResponse, EmbedderMsg, PromptResponse, SimpleDialog, Theme,
|
AlertResponse, ConfirmResponse, EmbedderMsg, GamepadEvent, GamepadSupportedHapticEffects,
|
||||||
ViewportDetails, WebDriverJSError, WebDriverJSResult,
|
GamepadUpdateType, PromptResponse, SimpleDialog, Theme, ViewportDetails, WebDriverJSError,
|
||||||
|
WebDriverJSResult,
|
||||||
};
|
};
|
||||||
use euclid::default::{Point2D as UntypedPoint2D, Rect as UntypedRect};
|
use euclid::default::{Point2D as UntypedPoint2D, Rect as UntypedRect};
|
||||||
use euclid::{Point2D, Rect, Scale, Size2D, Vector2D};
|
use euclid::{Point2D, Rect, Scale, Size2D, Vector2D};
|
||||||
|
@ -61,6 +62,8 @@ use num_traits::ToPrimitive;
|
||||||
use profile_traits::ipc as ProfiledIpc;
|
use profile_traits::ipc as ProfiledIpc;
|
||||||
use profile_traits::mem::ProfilerChan as MemProfilerChan;
|
use profile_traits::mem::ProfilerChan as MemProfilerChan;
|
||||||
use profile_traits::time::ProfilerChan as TimeProfilerChan;
|
use profile_traits::time::ProfilerChan as TimeProfilerChan;
|
||||||
|
use script_bindings::codegen::GenericBindings::NavigatorBinding::NavigatorMethods;
|
||||||
|
use script_bindings::codegen::GenericBindings::PerformanceBinding::PerformanceMethods;
|
||||||
use script_bindings::interfaces::WindowHelpers;
|
use script_bindings::interfaces::WindowHelpers;
|
||||||
use script_layout_interface::{
|
use script_layout_interface::{
|
||||||
FragmentType, Layout, PendingImageState, QueryMsg, Reflow, ReflowGoal, ReflowRequest,
|
FragmentType, Layout, PendingImageState, QueryMsg, Reflow, ReflowGoal, ReflowRequest,
|
||||||
|
@ -125,6 +128,8 @@ use crate::dom::document::{AnimationFrameCallback, Document, ReflowTriggerCondit
|
||||||
use crate::dom::element::Element;
|
use crate::dom::element::Element;
|
||||||
use crate::dom::event::{Event, EventBubbles, EventCancelable, EventStatus};
|
use crate::dom::event::{Event, EventBubbles, EventCancelable, EventStatus};
|
||||||
use crate::dom::eventtarget::EventTarget;
|
use crate::dom::eventtarget::EventTarget;
|
||||||
|
use crate::dom::gamepad::{Gamepad, contains_user_gesture};
|
||||||
|
use crate::dom::gamepadevent::GamepadEventType;
|
||||||
use crate::dom::globalscope::GlobalScope;
|
use crate::dom::globalscope::GlobalScope;
|
||||||
use crate::dom::hashchangeevent::HashChangeEvent;
|
use crate::dom::hashchangeevent::HashChangeEvent;
|
||||||
use crate::dom::history::History;
|
use crate::dom::history::History;
|
||||||
|
@ -642,6 +647,126 @@ impl Window {
|
||||||
pub(crate) fn font_context(&self) -> &Arc<FontContext> {
|
pub(crate) fn font_context(&self) -> &Arc<FontContext> {
|
||||||
&self.font_context
|
&self.font_context
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn handle_gamepad_event(&self, gamepad_event: GamepadEvent) {
|
||||||
|
match gamepad_event {
|
||||||
|
GamepadEvent::Connected(index, name, bounds, supported_haptic_effects) => {
|
||||||
|
self.handle_gamepad_connect(
|
||||||
|
index.0,
|
||||||
|
name,
|
||||||
|
bounds.axis_bounds,
|
||||||
|
bounds.button_bounds,
|
||||||
|
supported_haptic_effects,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
GamepadEvent::Disconnected(index) => {
|
||||||
|
self.handle_gamepad_disconnect(index.0);
|
||||||
|
},
|
||||||
|
GamepadEvent::Updated(index, update_type) => {
|
||||||
|
self.receive_new_gamepad_button_or_axis(index.0, update_type);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <https://www.w3.org/TR/gamepad/#dfn-gamepadconnected>
|
||||||
|
fn handle_gamepad_connect(
|
||||||
|
&self,
|
||||||
|
// As the spec actually defines how to set the gamepad index, the GilRs index
|
||||||
|
// is currently unused, though in practice it will almost always be the same.
|
||||||
|
// More infra is currently needed to track gamepads across windows.
|
||||||
|
_index: usize,
|
||||||
|
name: String,
|
||||||
|
axis_bounds: (f64, f64),
|
||||||
|
button_bounds: (f64, f64),
|
||||||
|
supported_haptic_effects: GamepadSupportedHapticEffects,
|
||||||
|
) {
|
||||||
|
// TODO: 2. If document is not null and is not allowed to use the "gamepad" permission,
|
||||||
|
// then abort these steps.
|
||||||
|
let this = Trusted::new(self);
|
||||||
|
self.upcast::<GlobalScope>()
|
||||||
|
.task_manager()
|
||||||
|
.gamepad_task_source()
|
||||||
|
.queue(task!(gamepad_connected: move || {
|
||||||
|
let window = this.root();
|
||||||
|
|
||||||
|
let navigator = window.Navigator();
|
||||||
|
let selected_index = navigator.select_gamepad_index();
|
||||||
|
let gamepad = Gamepad::new(
|
||||||
|
&window,
|
||||||
|
selected_index,
|
||||||
|
name,
|
||||||
|
"standard".into(),
|
||||||
|
axis_bounds,
|
||||||
|
button_bounds,
|
||||||
|
supported_haptic_effects,
|
||||||
|
false,
|
||||||
|
CanGc::note(),
|
||||||
|
);
|
||||||
|
navigator.set_gamepad(selected_index as usize, &gamepad, CanGc::note());
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <https://www.w3.org/TR/gamepad/#dfn-gamepaddisconnected>
|
||||||
|
fn handle_gamepad_disconnect(&self, index: usize) {
|
||||||
|
let this = Trusted::new(self);
|
||||||
|
self.upcast::<GlobalScope>()
|
||||||
|
.task_manager()
|
||||||
|
.gamepad_task_source()
|
||||||
|
.queue(task!(gamepad_disconnected: move || {
|
||||||
|
let window = this.root();
|
||||||
|
let navigator = window.Navigator();
|
||||||
|
if let Some(gamepad) = navigator.get_gamepad(index) {
|
||||||
|
if window.Document().is_fully_active() {
|
||||||
|
gamepad.update_connected(false, gamepad.exposed(), CanGc::note());
|
||||||
|
navigator.remove_gamepad(index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <https://www.w3.org/TR/gamepad/#receiving-inputs>
|
||||||
|
fn receive_new_gamepad_button_or_axis(&self, index: usize, update_type: GamepadUpdateType) {
|
||||||
|
let this = Trusted::new(self);
|
||||||
|
|
||||||
|
// <https://w3c.github.io/gamepad/#dfn-update-gamepad-state>
|
||||||
|
self.upcast::<GlobalScope>().task_manager().gamepad_task_source().queue(
|
||||||
|
task!(update_gamepad_state: move || {
|
||||||
|
let window = this.root();
|
||||||
|
let navigator = window.Navigator();
|
||||||
|
if let Some(gamepad) = navigator.get_gamepad(index) {
|
||||||
|
let current_time = window.Performance().Now();
|
||||||
|
gamepad.update_timestamp(*current_time);
|
||||||
|
match update_type {
|
||||||
|
GamepadUpdateType::Axis(index, value) => {
|
||||||
|
gamepad.map_and_normalize_axes(index, value);
|
||||||
|
},
|
||||||
|
GamepadUpdateType::Button(index, value) => {
|
||||||
|
gamepad.map_and_normalize_buttons(index, value);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if !navigator.has_gamepad_gesture() && contains_user_gesture(update_type) {
|
||||||
|
navigator.set_has_gamepad_gesture(true);
|
||||||
|
navigator.GetGamepads()
|
||||||
|
.iter()
|
||||||
|
.filter_map(|g| g.as_ref())
|
||||||
|
.for_each(|gamepad| {
|
||||||
|
gamepad.set_exposed(true);
|
||||||
|
gamepad.update_timestamp(*current_time);
|
||||||
|
let new_gamepad = Trusted::new(&**gamepad);
|
||||||
|
if window.Document().is_fully_active() {
|
||||||
|
window.upcast::<GlobalScope>().task_manager().gamepad_task_source().queue(
|
||||||
|
task!(update_gamepad_connect: move || {
|
||||||
|
let gamepad = new_gamepad.root();
|
||||||
|
gamepad.notify_event(GamepadEventType::Connected, CanGc::note());
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/#atob
|
// https://html.spec.whatwg.org/multipage/#atob
|
||||||
|
|
|
@ -1126,7 +1126,7 @@ impl ScriptThread {
|
||||||
document.dispatch_ime_event(ime_event, can_gc);
|
document.dispatch_ime_event(ime_event, can_gc);
|
||||||
},
|
},
|
||||||
InputEvent::Gamepad(gamepad_event) => {
|
InputEvent::Gamepad(gamepad_event) => {
|
||||||
window.as_global_scope().handle_gamepad_event(gamepad_event);
|
window.handle_gamepad_event(gamepad_event);
|
||||||
},
|
},
|
||||||
InputEvent::EditingAction(editing_action_event) => {
|
InputEvent::EditingAction(editing_action_event) => {
|
||||||
document.handle_editing_action(editing_action_event, can_gc);
|
document.handle_editing_action(editing_action_event, can_gc);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue