mirror of
https://github.com/servo/servo
synced 2026-04-25 17:15:48 +02:00
feat: gamepad feature flag (#41451)
Put the Gamepad API and its supporting infrastructure behind a `gamepad` feature flag. This allows embedders to opt-out of gamepad support at compile time to save on binary size and reduce dependencies. Testing: 1. `./mach build -d` (Gamepad enabled by default) 2. `cargo build -p servoshell --no-default-features --features "libservo/clipboard,js_jit,max_log_level,webgpu"` (Gamepad Disabled) 3. `cargo build -p servoshell --features "gamepad,webxr,..."` (Gamepad & WebXR Enabled) Fixes: #40897 Signed-off-by: WaterWhisperer <waterwhisperer24@qq.com>
This commit is contained in:
@@ -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"]
|
||||
|
||||
@@ -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"),
|
||||
|
||||
@@ -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)'] }
|
||||
|
||||
@@ -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.
|
||||
|
||||
// <https://www.w3.org/TR/gamepad/#handling-visibility-change>
|
||||
#[cfg(feature = "gamepad")]
|
||||
if visibility_state == DocumentVisibilityState::Hidden {
|
||||
self.window
|
||||
.Navigator()
|
||||
|
||||
@@ -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 {
|
||||
}
|
||||
|
||||
/// <https://www.w3.org/TR/gamepad/#dfn-gamepadconnected>
|
||||
#[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 {
|
||||
}
|
||||
|
||||
/// <https://www.w3.org/TR/gamepad/#dfn-gamepaddisconnected>
|
||||
#[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 {
|
||||
}
|
||||
|
||||
/// <https://www.w3.org/TR/gamepad/#receiving-inputs>
|
||||
#[cfg(feature = "gamepad")]
|
||||
fn receive_new_gamepad_button_or_axis(&self, index: usize, update_type: GamepadUpdateType) {
|
||||
let trusted_window = Trusted::new(&*self.window);
|
||||
|
||||
|
||||
@@ -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);
|
||||
);
|
||||
);
|
||||
|
||||
@@ -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::*;
|
||||
|
||||
@@ -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<XRSystem>,
|
||||
mediadevices: MutNullableDom<MediaDevices>,
|
||||
/// <https://www.w3.org/TR/gamepad/#dfn-gamepads>
|
||||
#[cfg(feature = "gamepad")]
|
||||
gamepads: DomRefCell<Vec<MutNullableDom<Gamepad>>>,
|
||||
permissions: MutNullableDom<Permissions>,
|
||||
mediasession: MutNullableDom<MediaSession>,
|
||||
@@ -121,6 +124,7 @@ pub(crate) struct Navigator {
|
||||
#[cfg(feature = "webgpu")]
|
||||
gpu: MutNullableDom<GPU>,
|
||||
/// <https://www.w3.org/TR/gamepad/#dfn-hasgamepadgesture>
|
||||
#[cfg(feature = "gamepad")]
|
||||
has_gamepad_gesture: Cell<bool>,
|
||||
servo_internals: MutNullableDom<ServoInternals>,
|
||||
}
|
||||
@@ -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<DomRoot<Gamepad>> {
|
||||
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 {
|
||||
}
|
||||
|
||||
/// <https://www.w3.org/TR/gamepad/#dfn-selecting-an-unused-gamepad-index>
|
||||
#[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<crate::DomTypeHolder> for Navigator {
|
||||
}
|
||||
|
||||
/// <https://www.w3.org/TR/gamepad/#dom-navigator-getgamepads>
|
||||
#[cfg(feature = "gamepad")]
|
||||
fn GetGamepads(&self) -> Vec<Option<DomRoot<Gamepad>>> {
|
||||
let global = self.global();
|
||||
let window = global.as_window();
|
||||
|
||||
@@ -53,6 +53,7 @@ serde_json = { workspace = true }
|
||||
|
||||
[features]
|
||||
bluetooth = []
|
||||
gamepad = []
|
||||
testbinding = []
|
||||
tracing = ["dep:tracing"]
|
||||
webgpu = []
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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<Gamepad?> getGamepads();
|
||||
};
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#navigatorconcurrenthardware
|
||||
interface mixin NavigatorConcurrentHardware {
|
||||
readonly attribute unsigned long long hardwareConcurrency;
|
||||
|
||||
10
components/script_bindings/webidls/NavigatorGamepads.webidl
Normal file
10
components/script_bindings/webidls/NavigatorGamepads.webidl
Normal file
@@ -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<Gamepad?> getGamepads();
|
||||
};
|
||||
@@ -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"]
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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<bool>) {}
|
||||
|
||||
/// Triggered when this [`WebView`] will load a web (HTTP/HTTPS) resource. The load may be
|
||||
|
||||
@@ -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 }
|
||||
|
||||
@@ -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<WebViewPoint> {
|
||||
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 {
|
||||
|
||||
@@ -503,8 +503,10 @@ pub enum EmbedderMsg {
|
||||
/// Ask the user to allow a devtools client to connect.
|
||||
RequestDevtoolsConnection(GenericSender<AllowOrDeny>),
|
||||
/// Request to play a haptic effect on a connected gamepad.
|
||||
#[cfg(feature = "gamepad")]
|
||||
PlayGamepadHapticEffect(WebViewId, usize, GamepadHapticEffectType, IpcSender<bool>),
|
||||
/// Request to stop a haptic effect on a connected gamepad.
|
||||
#[cfg(feature = "gamepad")]
|
||||
StopGamepadHapticEffect(WebViewId, usize, IpcSender<bool>),
|
||||
/// 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)]
|
||||
/// <https://w3.org/TR/gamepad/#dom-gamepadhapticeffecttype-dual-rumble>
|
||||
pub struct DualRumbleEffectParams {
|
||||
@@ -644,6 +647,7 @@ pub struct DualRumbleEffectParams {
|
||||
pub weak_magnitude: f64,
|
||||
}
|
||||
|
||||
#[cfg(feature = "gamepad")]
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
/// <https://w3.org/TR/gamepad/#dom-gamepadhapticeffecttype>
|
||||
pub enum GamepadHapticEffectType {
|
||||
|
||||
@@ -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"]
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#[cfg(target_os = "android")]
|
||||
mod android;
|
||||
mod app;
|
||||
#[cfg(feature = "gamepad")]
|
||||
pub(crate) mod gamepad;
|
||||
mod host_trait;
|
||||
mod log;
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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<Option<GamepadSupport>>,
|
||||
|
||||
/// 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,
|
||||
|
||||
Reference in New Issue
Block a user