diff --git a/components/constellation/Cargo.toml b/components/constellation/Cargo.toml index 5974dd08eea..3c92eea0d18 100644 --- a/components/constellation/Cargo.toml +++ b/components/constellation/Cargo.toml @@ -14,6 +14,7 @@ path = "lib.rs" [features] default = [] bluetooth = ["bluetooth_traits"] +gamepad = ["embedder_traits/gamepad"] tracing = ["dep:tracing", "canvas/tracing"] vello = ["canvas/vello"] vello_cpu = ["canvas/vello_cpu"] diff --git a/components/constellation/tracing.rs b/components/constellation/tracing.rs index ecf439fe25b..40b481f46b4 100644 --- a/components/constellation/tracing.rs +++ b/components/constellation/tracing.rs @@ -94,6 +94,7 @@ mod from_embedder { } match self.event { InputEvent::EditingAction(..) => target_variant!("EditingAction"), + #[cfg(feature = "gamepad")] InputEvent::Gamepad(..) => target_variant!("Gamepad"), InputEvent::Ime(..) => target_variant!("Ime"), InputEvent::Keyboard(..) => target_variant!("Keyboard"), diff --git a/components/script/Cargo.toml b/components/script/Cargo.toml index 77a459318d0..4d54c9f64d3 100644 --- a/components/script/Cargo.toml +++ b/components/script/Cargo.toml @@ -16,6 +16,7 @@ path = "lib.rs" bluetooth = ['bluetooth_traits', 'script_bindings/bluetooth'] crown = ['js/crown'] debugmozjs = ['js/debugmozjs'] +gamepad = ["script_bindings/gamepad", "embedder_traits/gamepad"] jitspew = ['js/jitspew'] js_backtrace = [] js_jit = ["js/jit"] @@ -25,7 +26,7 @@ testbinding = ["script_bindings/testbinding"] tracing = ["dep:tracing", "script_bindings/tracing"] webgl_backtrace = ["canvas_traits/webgl_backtrace"] webgpu = ["script_bindings/webgpu", "script_traits/webgpu"] -webxr = ["webxr-api", "script_bindings/webxr"] +webxr = ["gamepad", "webxr-api", "script_bindings/webxr"] [lints.rust] unexpected_cfgs = { level = "warn", check-cfg = ['cfg(crown)'] } diff --git a/components/script/dom/document.rs b/components/script/dom/document.rs index fbf8eba8b73..76c7729d164 100644 --- a/components/script/dom/document.rs +++ b/components/script/dom/document.rs @@ -83,6 +83,7 @@ use crate::dom::bindings::codegen::Bindings::ElementBinding::ScrollLogicalPositi use crate::dom::bindings::codegen::Bindings::EventBinding::Event_Binding::EventMethods; use crate::dom::bindings::codegen::Bindings::HTMLIFrameElementBinding::HTMLIFrameElement_Binding::HTMLIFrameElementMethods; use crate::dom::bindings::codegen::Bindings::HTMLOrSVGElementBinding::FocusOptions; +#[cfg(any(feature = "webxr", feature = "gamepad"))] use crate::dom::bindings::codegen::Bindings::NavigatorBinding::Navigator_Binding::NavigatorMethods; use crate::dom::bindings::codegen::Bindings::NodeBinding::NodeMethods; use crate::dom::bindings::codegen::Bindings::NodeFilterBinding::NodeFilter; @@ -4688,6 +4689,7 @@ impl Document { // state and document. Any other specs' visibility steps will go here. // + #[cfg(feature = "gamepad")] if visibility_state == DocumentVisibilityState::Hidden { self.window .Navigator() diff --git a/components/script/dom/document_event_handler.rs b/components/script/dom/document_event_handler.rs index a821b12670d..453c439bf81 100644 --- a/components/script/dom/document_event_handler.rs +++ b/components/script/dom/document_event_handler.rs @@ -11,12 +11,15 @@ use std::time::{Duration, Instant}; use constellation_traits::{KeyboardScroll, ScriptToConstellationMessage}; use embedder_traits::{ - Cursor, EditingActionEvent, EmbedderMsg, GamepadEvent as EmbedderGamepadEvent, - GamepadSupportedHapticEffects, GamepadUpdateType, ImeEvent, InputEvent, InputEventAndId, + Cursor, EditingActionEvent, EmbedderMsg, ImeEvent, InputEvent, InputEventAndId, InputEventResult, KeyboardEvent as EmbedderKeyboardEvent, MouseButton, MouseButtonAction, MouseButtonEvent, MouseLeftViewportEvent, ScrollEvent, TouchEvent as EmbedderTouchEvent, TouchEventType, TouchId, UntrustedNodeAddress, WheelEvent as EmbedderWheelEvent, }; +#[cfg(feature = "gamepad")] +use embedder_traits::{ + GamepadEvent as EmbedderGamepadEvent, GamepadSupportedHapticEffects, GamepadUpdateType, +}; use euclid::{Point2D, Vector2D}; use ipc_channel::ipc; use js::jsapi::JSAutoRealm; @@ -46,7 +49,9 @@ use crate::dom::bindings::root::MutNullableDom; use crate::dom::clipboardevent::ClipboardEventType; use crate::dom::document::{FireMouseEventType, FocusInitiator}; use crate::dom::event::{EventBubbles, EventCancelable, EventComposed, EventFlags}; +#[cfg(feature = "gamepad")] use crate::dom::gamepad::gamepad::{Gamepad, contains_user_gesture}; +#[cfg(feature = "gamepad")] use crate::dom::gamepad::gamepadevent::GamepadEventType; use crate::dom::inputevent::HitTestResult; use crate::dom::node::{self, Node, NodeTraits, ShadowIncluding}; @@ -195,6 +200,7 @@ impl DocumentEventHandler { self.handle_keyboard_event(keyboard_event, can_gc) }, InputEvent::Ime(ime_event) => self.handle_ime_event(ime_event, can_gc), + #[cfg(feature = "gamepad")] InputEvent::Gamepad(gamepad_event) => { self.handle_gamepad_event(gamepad_event); InputEventResult::default() @@ -1163,6 +1169,7 @@ impl DocumentEventHandler { dom_event.flags().into() } + #[cfg(feature = "gamepad")] fn handle_gamepad_event(&self, gamepad_event: EmbedderGamepadEvent) { match gamepad_event { EmbedderGamepadEvent::Connected(index, name, bounds, supported_haptic_effects) => { @@ -1184,6 +1191,7 @@ impl DocumentEventHandler { } /// + #[cfg(feature = "gamepad")] fn handle_gamepad_connect( &self, // As the spec actually defines how to set the gamepad index, the GilRs index @@ -1223,6 +1231,7 @@ impl DocumentEventHandler { } /// + #[cfg(feature = "gamepad")] fn handle_gamepad_disconnect(&self, index: usize) { let trusted_window = Trusted::new(&*self.window); self.window @@ -1242,6 +1251,7 @@ impl DocumentEventHandler { } /// + #[cfg(feature = "gamepad")] fn receive_new_gamepad_button_or_axis(&self, index: usize, update_type: GamepadUpdateType) { let trusted_window = Trusted::new(&*self.window); diff --git a/components/script/dom/macros.rs b/components/script/dom/macros.rs index b3a1069c399..69d414fed45 100644 --- a/components/script/dom/macros.rs +++ b/components/script/dom/macros.rs @@ -681,7 +681,9 @@ macro_rules! window_event_handlers( event_handler!(unhandledrejection, GetOnunhandledrejection, SetOnunhandledrejection); event_handler!(unload, GetOnunload, SetOnunload); + #[cfg(feature = "gamepad")] event_handler!(gamepadconnected, GetOngamepadconnected, SetOngamepadconnected); + #[cfg(feature = "gamepad")] event_handler!(gamepaddisconnected, GetOngamepaddisconnected, SetOngamepaddisconnected); ); (ForwardToWindow) => ( @@ -711,7 +713,9 @@ macro_rules! window_event_handlers( window_owned_event_handler!(unhandledrejection, GetOnunhandledrejection, SetOnunhandledrejection); window_owned_event_handler!(unload, GetOnunload, SetOnunload); + #[cfg(feature = "gamepad")] window_owned_event_handler!(gamepadconnected, GetOngamepadconnected, SetOngamepadconnected); + #[cfg(feature = "gamepad")] window_owned_event_handler!(gamepaddisconnected, GetOngamepaddisconnected, SetOngamepaddisconnected); ); ); diff --git a/components/script/dom/mod.rs b/components/script/dom/mod.rs index 759470d4995..3598abd9b7b 100644 --- a/components/script/dom/mod.rs +++ b/components/script/dom/mod.rs @@ -307,7 +307,9 @@ pub(crate) mod filereadersync; pub(crate) mod focusevent; pub(crate) mod formdata; pub(crate) mod formdataevent; +#[cfg(feature = "gamepad")] pub(crate) mod gamepad; +#[cfg(feature = "gamepad")] pub(crate) use self::gamepad::*; pub(crate) mod geolocation; pub(crate) use self::geolocation::*; diff --git a/components/script/dom/navigator.rs b/components/script/dom/navigator.rs index ba5bfa299d7..1c5f20b4e31 100644 --- a/components/script/dom/navigator.rs +++ b/components/script/dom/navigator.rs @@ -38,7 +38,9 @@ use crate::dom::bluetooth::Bluetooth; use crate::dom::clipboard::Clipboard; use crate::dom::credentialmanagement::credentialscontainer::CredentialsContainer; use crate::dom::csp::{GlobalCspReporting, Violation}; +#[cfg(feature = "gamepad")] use crate::dom::gamepad::Gamepad; +#[cfg(feature = "gamepad")] use crate::dom::gamepad::gamepadevent::GamepadEventType; use crate::dom::geolocation::Geolocation; use crate::dom::globalscope::GlobalScope; @@ -114,6 +116,7 @@ pub(crate) struct Navigator { xr: MutNullableDom, mediadevices: MutNullableDom, /// + #[cfg(feature = "gamepad")] gamepads: DomRefCell>>, permissions: MutNullableDom, mediasession: MutNullableDom, @@ -121,6 +124,7 @@ pub(crate) struct Navigator { #[cfg(feature = "webgpu")] gpu: MutNullableDom, /// + #[cfg(feature = "gamepad")] has_gamepad_gesture: Cell, servo_internals: MutNullableDom, } @@ -138,12 +142,14 @@ impl Navigator { #[cfg(feature = "webxr")] xr: Default::default(), mediadevices: Default::default(), + #[cfg(feature = "gamepad")] gamepads: Default::default(), permissions: Default::default(), mediasession: Default::default(), clipboard: Default::default(), #[cfg(feature = "webgpu")] gpu: Default::default(), + #[cfg(feature = "gamepad")] has_gamepad_gesture: Cell::new(false), servo_internals: Default::default(), } @@ -158,10 +164,12 @@ impl Navigator { self.xr.get() } + #[cfg(feature = "gamepad")] pub(crate) fn get_gamepad(&self, index: usize) -> Option> { self.gamepads.borrow().get(index).and_then(|g| g.get()) } + #[cfg(feature = "gamepad")] pub(crate) fn set_gamepad(&self, index: usize, gamepad: &Gamepad, can_gc: CanGc) { if let Some(gamepad_to_set) = self.gamepads.borrow().get(index) { gamepad_to_set.set(Some(gamepad)); @@ -174,6 +182,7 @@ impl Navigator { } } + #[cfg(feature = "gamepad")] pub(crate) fn remove_gamepad(&self, index: usize) { if let Some(gamepad_to_remove) = self.gamepads.borrow_mut().get(index) { gamepad_to_remove.set(None); @@ -182,6 +191,7 @@ impl Navigator { } /// + #[cfg(feature = "gamepad")] pub(crate) fn select_gamepad_index(&self) -> u32 { let mut gamepad_list = self.gamepads.borrow_mut(); if let Some(index) = gamepad_list.iter().position(|g| g.get().is_none()) { @@ -193,6 +203,7 @@ impl Navigator { } } + #[cfg(feature = "gamepad")] fn shrink_gamepads_list(&self) { let mut gamepad_list = self.gamepads.borrow_mut(); for i in (0..gamepad_list.len()).rev() { @@ -204,10 +215,12 @@ impl Navigator { } } + #[cfg(feature = "gamepad")] pub(crate) fn has_gamepad_gesture(&self) -> bool { self.has_gamepad_gesture.get() } + #[cfg(feature = "gamepad")] pub(crate) fn set_has_gamepad_gesture(&self, has_gamepad_gesture: bool) { self.has_gamepad_gesture.set(has_gamepad_gesture); } @@ -384,6 +397,7 @@ impl NavigatorMethods for Navigator { } /// + #[cfg(feature = "gamepad")] fn GetGamepads(&self) -> Vec>> { let global = self.global(); let window = global.as_window(); diff --git a/components/script_bindings/Cargo.toml b/components/script_bindings/Cargo.toml index c732a72f141..14d3413078b 100644 --- a/components/script_bindings/Cargo.toml +++ b/components/script_bindings/Cargo.toml @@ -53,6 +53,7 @@ serde_json = { workspace = true } [features] bluetooth = [] +gamepad = [] testbinding = [] tracing = ["dep:tracing"] webgpu = [] diff --git a/components/script_bindings/webidls/Gamepad.webidl b/components/script_bindings/webidls/Gamepad.webidl index bef601c5c7c..e040c0a2ab7 100644 --- a/components/script_bindings/webidls/Gamepad.webidl +++ b/components/script_bindings/webidls/Gamepad.webidl @@ -2,6 +2,8 @@ * 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/#gamepad-interface [Exposed=Window, Pref="dom_gamepad_enabled"] interface Gamepad { diff --git a/components/script_bindings/webidls/GamepadButton.webidl b/components/script_bindings/webidls/GamepadButton.webidl index d4aa41be8d9..bcc58aac46e 100644 --- a/components/script_bindings/webidls/GamepadButton.webidl +++ b/components/script_bindings/webidls/GamepadButton.webidl @@ -2,6 +2,8 @@ * 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/#gamepadbutton-interface [Exposed=Window, Pref="dom_gamepad_enabled"] interface GamepadButton { diff --git a/components/script_bindings/webidls/GamepadButtonList.webidl b/components/script_bindings/webidls/GamepadButtonList.webidl index 24a82a4b322..040a9acc133 100644 --- a/components/script_bindings/webidls/GamepadButtonList.webidl +++ b/components/script_bindings/webidls/GamepadButtonList.webidl @@ -2,6 +2,8 @@ * 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 { diff --git a/components/script_bindings/webidls/GamepadEvent.webidl b/components/script_bindings/webidls/GamepadEvent.webidl index 0dc82e4083b..67d9169ee49 100644 --- a/components/script_bindings/webidls/GamepadEvent.webidl +++ b/components/script_bindings/webidls/GamepadEvent.webidl @@ -2,6 +2,8 @@ * 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/#gamepadevent-interface [Exposed=Window, Pref="dom_gamepad_enabled"] interface GamepadEvent : Event { diff --git a/components/script_bindings/webidls/GamepadHapticActuator.webidl b/components/script_bindings/webidls/GamepadHapticActuator.webidl index db6f6eb5f8b..9009bb5a981 100644 --- a/components/script_bindings/webidls/GamepadHapticActuator.webidl +++ b/components/script_bindings/webidls/GamepadHapticActuator.webidl @@ -2,6 +2,8 @@ * 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/#gamepadhapticactuator-interface [Exposed=Window, Pref="dom_gamepad_enabled"] interface GamepadHapticActuator { diff --git a/components/script_bindings/webidls/GamepadPose.webidl b/components/script_bindings/webidls/GamepadPose.webidl index aeb5411b12b..dbcca4d7da6 100644 --- a/components/script_bindings/webidls/GamepadPose.webidl +++ b/components/script_bindings/webidls/GamepadPose.webidl @@ -2,6 +2,8 @@ * 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/extensions.html#gamepadpose-interface [Exposed=Window, Pref="dom_gamepad_enabled"] interface GamepadPose { diff --git a/components/script_bindings/webidls/Navigator.webidl b/components/script_bindings/webidls/Navigator.webidl index 69d7e66cbf4..588122d70f7 100644 --- a/components/script_bindings/webidls/Navigator.webidl +++ b/components/script_bindings/webidls/Navigator.webidl @@ -67,11 +67,6 @@ partial interface Navigator { [Pref="dom_permissions_enabled"] readonly attribute Permissions permissions; }; -// https://w3c.github.io/gamepad/#navigator-interface-extension -partial interface Navigator { - [Pref="dom_gamepad_enabled"] sequence getGamepads(); -}; - // https://html.spec.whatwg.org/multipage/#navigatorconcurrenthardware interface mixin NavigatorConcurrentHardware { readonly attribute unsigned long long hardwareConcurrency; diff --git a/components/script_bindings/webidls/NavigatorGamepads.webidl b/components/script_bindings/webidls/NavigatorGamepads.webidl new file mode 100644 index 00000000000..7a48aae33b8 --- /dev/null +++ b/components/script_bindings/webidls/NavigatorGamepads.webidl @@ -0,0 +1,10 @@ +/* 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/#navigator-interface-extension +partial interface Navigator { + [Pref="dom_gamepad_enabled"] sequence getGamepads(); +}; diff --git a/components/servo/Cargo.toml b/components/servo/Cargo.toml index 14512dd5e5c..b2a84cf3b97 100644 --- a/components/servo/Cargo.toml +++ b/components/servo/Cargo.toml @@ -29,6 +29,11 @@ clipboard = ["dep:arboard"] crown = ["script/crown"] debugmozjs = ["script/debugmozjs"] dynamic_freetype = ["webrender/dynamic_freetype"] +gamepad = [ + "script/gamepad", + "constellation/gamepad", + "embedder_traits/gamepad", +] jitspew = ["script/jitspew"] js_backtrace = ["script/js_backtrace"] js_jit = ["script/js_jit"] diff --git a/components/servo/servo.rs b/components/servo/servo.rs index 31b0b557852..25a88546725 100644 --- a/components/servo/servo.rs +++ b/components/servo/servo.rs @@ -537,6 +537,7 @@ impl ServoInner { self.servo_errors.sender(), )); }, + #[cfg(feature = "gamepad")] EmbedderMsg::PlayGamepadHapticEffect( webview_id, gamepad_index, @@ -552,6 +553,7 @@ impl ServoInner { ); } }, + #[cfg(feature = "gamepad")] EmbedderMsg::StopGamepadHapticEffect(webview_id, gamepad_index, ipc_sender) => { if let Some(webview) = self.get_webview_handle(webview_id) { webview.delegate().stop_gamepad_haptic_effect( diff --git a/components/servo/webview_delegate.rs b/components/servo/webview_delegate.rs index f98ef6611dc..b946b915441 100644 --- a/components/servo/webview_delegate.rs +++ b/components/servo/webview_delegate.rs @@ -9,14 +9,15 @@ use base::generic_channel::GenericSender; use base::id::{PipelineId, WebViewId}; use compositing_traits::rendering_context::RenderingContext; use constellation_traits::EmbedderToConstellationMessage; +#[cfg(feature = "gamepad")] +use embedder_traits::GamepadHapticEffectType; use embedder_traits::{ AlertResponse, AllowOrDeny, AuthenticationResponse, ConfirmResponse, ConsoleLogLevel, ContextMenuAction, ContextMenuElementInformation, ContextMenuItem, Cursor, EmbedderControlId, - EmbedderControlResponse, FilePickerRequest, FilterPattern, GamepadHapticEffectType, - InputEventId, InputEventResult, InputMethodType, LoadStatus, MediaSessionEvent, Notification, - PermissionFeature, PromptResponse, RgbColor, ScreenGeometry, SelectElementOptionOrOptgroup, - SimpleDialogRequest, TraversalId, ViewportDetails, WebResourceRequest, WebResourceResponse, - WebResourceResponseMsg, + EmbedderControlResponse, FilePickerRequest, FilterPattern, InputEventId, InputEventResult, + InputMethodType, LoadStatus, MediaSessionEvent, Notification, PermissionFeature, + PromptResponse, RgbColor, ScreenGeometry, SelectElementOptionOrOptgroup, SimpleDialogRequest, + TraversalId, ViewportDetails, WebResourceRequest, WebResourceResponse, WebResourceResponseMsg, }; use ipc_channel::ipc::IpcSender; use url::Url; @@ -941,6 +942,7 @@ pub trait WebViewDelegate { fn hide_embedder_control(&self, _webview: WebView, _control_id: EmbedderControlId) {} /// Request to play a haptic effect on a connected gamepad. + #[cfg(feature = "gamepad")] fn play_gamepad_haptic_effect( &self, _webview: WebView, @@ -950,6 +952,7 @@ pub trait WebViewDelegate { ) { } /// Request to stop a haptic effect on a connected gamepad. + #[cfg(feature = "gamepad")] fn stop_gamepad_haptic_effect(&self, _webview: WebView, _: usize, _: IpcSender) {} /// Triggered when this [`WebView`] will load a web (HTTP/HTTPS) resource. The load may be diff --git a/components/shared/embedder/Cargo.toml b/components/shared/embedder/Cargo.toml index 9f3a7c62893..8a559c24156 100644 --- a/components/shared/embedder/Cargo.toml +++ b/components/shared/embedder/Cargo.toml @@ -15,6 +15,7 @@ path = "lib.rs" # bakes default resources into the library. # This feature is mainly intended for testing purposes. baked-default-resources = [] +gamepad = [] [dependencies] base = { workspace = true } diff --git a/components/shared/embedder/input_events.rs b/components/shared/embedder/input_events.rs index f12a58599f4..64573a0b5c9 100644 --- a/components/shared/embedder/input_events.rs +++ b/components/shared/embedder/input_events.rs @@ -41,6 +41,7 @@ bitflags! { #[derive(Clone, Debug, Deserialize, Serialize)] pub enum InputEvent { EditingAction(EditingActionEvent), + #[cfg(feature = "gamepad")] Gamepad(GamepadEvent), Ime(ImeEvent), Keyboard(KeyboardEvent), @@ -79,6 +80,7 @@ impl InputEvent { pub fn point(&self) -> Option { match self { InputEvent::EditingAction(..) => None, + #[cfg(feature = "gamepad")] InputEvent::Gamepad(..) => None, InputEvent::Ime(..) => None, InputEvent::Keyboard(..) => None, @@ -319,12 +321,14 @@ pub enum ImeEvent { Dismissed, } +#[cfg(feature = "gamepad")] #[derive( Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, Ord, PartialEq, PartialOrd, Serialize, )] /// Index of gamepad in list of system's connected gamepads pub struct GamepadIndex(pub usize); +#[cfg(feature = "gamepad")] #[derive(Clone, Debug, Deserialize, Serialize)] /// The minimum and maximum values that can be reported for axis or button input from this gamepad pub struct GamepadInputBounds { @@ -334,6 +338,7 @@ pub struct GamepadInputBounds { pub button_bounds: (f64, f64), } +#[cfg(feature = "gamepad")] #[derive(Clone, Debug, Deserialize, Serialize)] /// The haptic effects supported by this gamepad pub struct GamepadSupportedHapticEffects { @@ -343,6 +348,7 @@ pub struct GamepadSupportedHapticEffects { pub supports_trigger_rumble: bool, } +#[cfg(feature = "gamepad")] #[derive(Clone, Debug, Deserialize, Serialize)] /// The type of Gamepad event pub enum GamepadEvent { @@ -362,6 +368,7 @@ pub enum GamepadEvent { Updated(GamepadIndex, GamepadUpdateType), } +#[cfg(feature = "gamepad")] #[derive(Clone, Debug, Deserialize, Serialize)] /// The type of Gamepad input being updated pub enum GamepadUpdateType { diff --git a/components/shared/embedder/lib.rs b/components/shared/embedder/lib.rs index d39aea034d9..54f67fb53ea 100644 --- a/components/shared/embedder/lib.rs +++ b/components/shared/embedder/lib.rs @@ -503,8 +503,10 @@ pub enum EmbedderMsg { /// Ask the user to allow a devtools client to connect. RequestDevtoolsConnection(GenericSender), /// Request to play a haptic effect on a connected gamepad. + #[cfg(feature = "gamepad")] PlayGamepadHapticEffect(WebViewId, usize, GamepadHapticEffectType, IpcSender), /// Request to stop a haptic effect on a connected gamepad. + #[cfg(feature = "gamepad")] StopGamepadHapticEffect(WebViewId, usize, IpcSender), /// Informs the embedder that the constellation has completed shutdown. /// Required because the constellation can have pending calls to make @@ -635,6 +637,7 @@ pub enum InputMethodType { Week, } +#[cfg(feature = "gamepad")] #[derive(Clone, Debug, Deserialize, Serialize)] /// pub struct DualRumbleEffectParams { @@ -644,6 +647,7 @@ pub struct DualRumbleEffectParams { pub weak_magnitude: f64, } +#[cfg(feature = "gamepad")] #[derive(Clone, Debug, Deserialize, Serialize)] /// pub enum GamepadHapticEffectType { diff --git a/ports/servoshell/Cargo.toml b/ports/servoshell/Cargo.toml index 1f858345fb4..9b146821a32 100644 --- a/ports/servoshell/Cargo.toml +++ b/ports/servoshell/Cargo.toml @@ -35,9 +35,10 @@ OriginalFilename = "servo.exe" ProductName = "Servo" [features] -default = ["libservo/clipboard", "js_jit", "max_log_level", "webgpu", "webxr"] +default = ["gamepad", "libservo/clipboard", "js_jit", "max_log_level", "webgpu", "webxr"] crown = ["libservo/crown"] debugmozjs = ["libservo/debugmozjs"] +gamepad = ["libservo/gamepad"] jitspew = ["libservo/jitspew"] js_backtrace = ["libservo/js_backtrace"] js_jit = ["libservo/js_jit"] diff --git a/ports/servoshell/desktop/mod.rs b/ports/servoshell/desktop/mod.rs index 1379f413b64..0400f5f57a5 100644 --- a/ports/servoshell/desktop/mod.rs +++ b/ports/servoshell/desktop/mod.rs @@ -9,6 +9,7 @@ pub(crate) mod app; pub(crate) mod cli; pub(crate) mod dialog; pub(crate) mod event_loop; +#[cfg(feature = "gamepad")] pub(crate) mod gamepad; pub mod geometry; mod gui; diff --git a/ports/servoshell/egl/mod.rs b/ports/servoshell/egl/mod.rs index d97b5032b4f..2d392036074 100644 --- a/ports/servoshell/egl/mod.rs +++ b/ports/servoshell/egl/mod.rs @@ -5,6 +5,7 @@ #[cfg(target_os = "android")] mod android; mod app; +#[cfg(feature = "gamepad")] pub(crate) mod gamepad; mod host_trait; mod log; diff --git a/ports/servoshell/lib.rs b/ports/servoshell/lib.rs index e0879cfeb69..b37a6a1da8b 100644 --- a/ports/servoshell/lib.rs +++ b/ports/servoshell/lib.rs @@ -25,9 +25,12 @@ mod running_app_state; mod webdriver; mod window; -#[cfg(not(any(target_os = "android", target_env = "ohos")))] +#[cfg(all( + feature = "gamepad", + not(any(target_os = "android", target_env = "ohos")) +))] pub(crate) use crate::desktop::gamepad::GamepadSupport; -#[cfg(any(target_os = "android", target_env = "ohos"))] +#[cfg(all(feature = "gamepad", any(target_os = "android", target_env = "ohos")))] pub(crate) use crate::egl::gamepad::GamepadSupport; pub mod platform { diff --git a/ports/servoshell/running_app_state.rs b/ports/servoshell/running_app_state.rs index 9be56204cfe..bb4d9ad7c46 100644 --- a/ports/servoshell/running_app_state.rs +++ b/ports/servoshell/running_app_state.rs @@ -13,17 +13,19 @@ use crossbeam_channel::{Receiver, Sender, unbounded}; use euclid::Rect; use image::{DynamicImage, ImageFormat, RgbaImage}; use log::{error, info, warn}; +#[cfg(feature = "gamepad")] +use servo::GamepadHapticEffectType; use servo::{ AllowOrDenyRequest, AuthenticationRequest, CSSPixel, ConsoleLogLevel, CreateNewWebViewRequest, DeviceIntPoint, DeviceIntSize, EmbedderControl, EmbedderControlId, EventLoopWaker, - GamepadHapticEffectType, GenericSender, InputEvent, InputEventId, InputEventResult, IpcSender, - JSValue, LoadStatus, MediaSessionEvent, PermissionRequest, PrefValue, ScreenshotCaptureError, - Servo, ServoDelegate, ServoError, TraversalId, WebDriverCommandMsg, WebDriverJSResult, - WebDriverLoadStatus, WebDriverScriptCommand, WebDriverSenders, WebView, WebViewDelegate, - WebViewId, pref, + GenericSender, InputEvent, InputEventId, InputEventResult, IpcSender, JSValue, LoadStatus, + MediaSessionEvent, PermissionRequest, PrefValue, ScreenshotCaptureError, Servo, ServoDelegate, + ServoError, TraversalId, WebDriverCommandMsg, WebDriverJSResult, WebDriverLoadStatus, + WebDriverScriptCommand, WebDriverSenders, WebView, WebViewDelegate, WebViewId, pref, }; use url::Url; +#[cfg(feature = "gamepad")] use crate::GamepadSupport; use crate::prefs::{EXPERIMENTAL_PREFS, ServoShellPreferences}; use crate::webdriver::WebDriverEmbedderControls; @@ -146,6 +148,7 @@ pub(crate) enum UserInterfaceCommand { pub(crate) struct RunningAppState { /// Gamepad support, which may be `None` if it failed to initialize. + #[cfg(feature = "gamepad")] gamepad_support: RefCell>, /// The [`WebDriverSenders`] used to reply to pending WebDriver requests. @@ -200,6 +203,7 @@ impl RunningAppState { ) -> Self { servo.set_delegate(Rc::new(ServoShellServoDelegate)); + #[cfg(feature = "gamepad")] let gamepad_support = if pref!(dom_gamepad_enabled) { GamepadSupport::maybe_new() } else { @@ -218,6 +222,7 @@ impl RunningAppState { Self { windows: Default::default(), focused_window: Default::default(), + #[cfg(feature = "gamepad")] gamepad_support: RefCell::new(gamepad_support), webdriver_senders: RefCell::default(), webdriver_embedder_controls: Default::default(), @@ -345,6 +350,7 @@ impl RunningAppState { self.handle_webdriver_messages(create_platform_window); + #[cfg(feature = "gamepad")] if pref!(dom_gamepad_enabled) { self.handle_gamepad_events(); } @@ -549,6 +555,7 @@ impl RunningAppState { webview.load(url); } + #[cfg(feature = "gamepad")] pub(crate) fn handle_gamepad_events(&self) { let Some(active_webview) = self .focused_window() @@ -721,6 +728,7 @@ impl WebViewDelegate for RunningAppState { self.window_for_webview_id(webview.id()).set_needs_repaint(); } + #[cfg(feature = "gamepad")] fn play_gamepad_haptic_effect( &self, _webview: WebView, @@ -738,6 +746,7 @@ impl WebViewDelegate for RunningAppState { } } + #[cfg(feature = "gamepad")] fn stop_gamepad_haptic_effect( &self, _webview: WebView,