/* 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 crate::dom::bindings::codegen::Bindings::GamepadBinding::GamepadHand; use crate::dom::bindings::codegen::Bindings::GamepadBinding::GamepadMethods; use crate::dom::bindings::inheritance::Castable; use crate::dom::bindings::num::Finite; use crate::dom::bindings::reflector::{DomObject, Reflector}; use crate::dom::bindings::root::{Dom, DomRoot}; use crate::dom::bindings::str::DOMString; use crate::dom::event::Event; use crate::dom::eventtarget::EventTarget; use crate::dom::gamepadbuttonlist::GamepadButtonList; use crate::dom::gamepadevent::{GamepadEvent, GamepadEventType}; use crate::dom::gamepadpose::GamepadPose; use crate::script_runtime::JSContext; use dom_struct::dom_struct; use js::jsapi::{Heap, JSObject}; use std::cell::Cell; use std::ptr::NonNull; #[dom_struct] pub struct Gamepad { reflector_: Reflector, gamepad_id: u32, id: String, index: Cell, connected: Cell, timestamp: Cell, mapping_type: String, #[ignore_malloc_size_of = "mozjs"] axes: Heap<*mut JSObject>, buttons: Dom, pose: Option>, #[ignore_malloc_size_of = "Defined in rust-webvr"] hand: GamepadHand, } // TODO: support gamepad discovery #[allow(dead_code)] impl Gamepad { fn new_inherited( gamepad_id: u32, id: String, index: i32, connected: bool, timestamp: f64, mapping_type: String, buttons: &GamepadButtonList, pose: Option<&GamepadPose>, hand: GamepadHand, ) -> Gamepad { Self { reflector_: Reflector::new(), gamepad_id: gamepad_id, id: id, index: Cell::new(index), connected: Cell::new(connected), timestamp: Cell::new(timestamp), mapping_type: mapping_type, axes: Heap::default(), buttons: Dom::from_ref(buttons), pose: pose.map(Dom::from_ref), hand: hand, } } } impl GamepadMethods for Gamepad { // https://w3c.github.io/gamepad/#dom-gamepad-id fn Id(&self) -> DOMString { DOMString::from(self.id.clone()) } // https://w3c.github.io/gamepad/#dom-gamepad-index fn Index(&self) -> i32 { self.index.get() } // https://w3c.github.io/gamepad/#dom-gamepad-connected fn Connected(&self) -> bool { self.connected.get() } // https://w3c.github.io/gamepad/#dom-gamepad-timestamp fn Timestamp(&self) -> Finite { Finite::wrap(self.timestamp.get()) } // https://w3c.github.io/gamepad/#dom-gamepad-mapping fn Mapping(&self) -> DOMString { DOMString::from(self.mapping_type.clone()) } #[allow(unsafe_code)] // https://w3c.github.io/gamepad/#dom-gamepad-axes fn Axes(&self, _cx: JSContext) -> NonNull { unsafe { NonNull::new_unchecked(self.axes.get()) } } // https://w3c.github.io/gamepad/#dom-gamepad-buttons fn Buttons(&self) -> DomRoot { DomRoot::from_ref(&*self.buttons) } // https://w3c.github.io/gamepad/extensions.html#gamepadhand-enum fn Hand(&self) -> GamepadHand { self.hand } // https://w3c.github.io/gamepad/extensions.html#dom-gamepad-pose fn GetPose(&self) -> Option> { self.pose.as_ref().map(|p| DomRoot::from_ref(&**p)) } } // TODO: support gamepad discovery #[allow(dead_code)] impl Gamepad { pub fn gamepad_id(&self) -> u32 { self.gamepad_id } pub fn update_connected(&self, connected: bool) { if self.connected.get() == connected { return; } self.connected.set(connected); let event_type = if connected { GamepadEventType::Connected } else { GamepadEventType::Disconnected }; self.notify_event(event_type); } pub fn update_index(&self, index: i32) { self.index.set(index); } pub fn notify_event(&self, event_type: GamepadEventType) { let event = GamepadEvent::new_with_type(&self.global(), event_type, &self); event .upcast::() .fire(self.global().as_window().upcast::()); } }