Skip to content

Commit

Permalink
Add GilRs as gamepad backend in servoshell
Browse files Browse the repository at this point in the history
  • Loading branch information
msub2 committed Feb 8, 2024
1 parent fb5a056 commit caad7ee
Show file tree
Hide file tree
Showing 4 changed files with 178 additions and 1 deletion.
95 changes: 95 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions ports/servoshell/Cargo.toml
Expand Up @@ -52,6 +52,7 @@ egui_glow = { version = "0.22.0", features = ["winit"] }
egui-winit = { version = "0.22.0", default-features = false, features = ["clipboard", "wayland"] }
euclid = { workspace = true }
getopts = { workspace = true }
gilrs = "0.10.4"
gleam = { workspace = true }
glow = "0.12.2"
keyboard-types = { workspace = true }
Expand Down
1 change: 1 addition & 0 deletions ports/servoshell/app.rs
Expand Up @@ -437,6 +437,7 @@ impl App {
}

// Catch some keyboard events, and push the rest onto the WebViewManager event queue.
webviews.handle_gamepad_events();
webviews.handle_window_events(embedder_events);

// Take any new embedder messages from Servo itself.
Expand Down
82 changes: 81 additions & 1 deletion ports/servoshell/webview.rs
Expand Up @@ -12,6 +12,7 @@ use std::{env, thread};

use arboard::Clipboard;
use euclid::{Point2D, Vector2D};
use gilrs::{EventType, Gilrs};
use keyboard_types::{Key, KeyboardEvent, Modifiers, ShortcutMatcher};
use log::{debug, error, info, trace, warn};
use servo::compositing::windowing::{EmbedderEvent, WebRenderDebugOption};
Expand All @@ -20,7 +21,7 @@ use servo::embedder_traits::{
PermissionRequest, PromptDefinition, PromptOrigin, PromptResult,
};
use servo::msg::constellation_msg::{TopLevelBrowsingContextId as WebViewId, TraversalDirection};
use servo::script_traits::TouchEventType;
use servo::script_traits::{GamepadEvent, GamepadIndex, GamepadUpdateType, TouchEventType};
use servo::servo_config::opts;
use servo::servo_url::ServoUrl;
use servo::webrender_api::ScrollLocation;
Expand Down Expand Up @@ -51,6 +52,7 @@ pub struct WebViewManager<Window: WindowPortsMethods + ?Sized> {
window: Rc<Window>,
event_queue: Vec<EmbedderEvent>,
clipboard: Option<Clipboard>,
gamepad: Option<Gilrs>,
shutdown_requested: bool,
}

Expand Down Expand Up @@ -82,6 +84,13 @@ where
None
},
},
gamepad: match Gilrs::new() {
Ok(g) => Some(g),
Err(e) => {
warn!("Error creating gamepad input connection ({})", e);
None
},
},
event_queue: Vec::new(),
shutdown_requested: false,
}
Expand Down Expand Up @@ -113,6 +122,77 @@ where
}
}

pub fn handle_gamepad_events(&mut self) {
if let Some(ref mut gilrs) = self.gamepad {
while let Some(event) = gilrs.next_event() {
let gamepad = gilrs.gamepad(event.id);
let name = gamepad.name();
let index = GamepadIndex(event.id.into());
match event.event {
EventType::ButtonChanged(button, value, _) => {
let mapped_index: usize = match button {
gilrs::Button::South => 0,
gilrs::Button::East => 1,
gilrs::Button::West => 2,
gilrs::Button::North => 3,
gilrs::Button::LeftTrigger => 4,
gilrs::Button::RightTrigger => 5,
gilrs::Button::LeftTrigger2 => 6,
gilrs::Button::RightTrigger2 => 7,
gilrs::Button::Select => 8,
gilrs::Button::Start => 9,
gilrs::Button::LeftThumb => 10,
gilrs::Button::RightThumb => 11,
gilrs::Button::DPadUp => 12,
gilrs::Button::DPadDown => 13,
gilrs::Button::DPadLeft => 14,
gilrs::Button::DPadRight => 15,
gilrs::Button::Mode => 16,
_ => 17 // Other buttons do not map to "standard" gamepad mapping and are ignored
};
if mapped_index < 17 {
let update_type = GamepadUpdateType::Button(mapped_index, value);
let event = GamepadEvent::Updated(index, update_type);
self.event_queue.push(EmbedderEvent::Gamepad(event));
}
},
EventType::AxisChanged(axis, value, _) => {
let mapped_axis: usize = match axis {
gilrs::Axis::LeftStickX => 0,
gilrs::Axis::LeftStickY => 1,
gilrs::Axis::RightStickX => 2,
gilrs::Axis::RightStickY => 3,
_ => 4, // Other axes do not map to "standard" gamepad mapping and are ignored
};
if mapped_axis < 4 {
// The Gamepad spec designates down as positive and up as negative.
// GilRs does the inverse of this, so correct for it here.
let axis_value = match mapped_axis {
0 | 2 => value,
1 | 3 => -value,
_ => 0. // Should not reach here
};
let update_type = GamepadUpdateType::Axis(mapped_axis, axis_value);
let event = GamepadEvent::Updated(index, update_type);
self.event_queue.push(EmbedderEvent::Gamepad(event));
}
},
EventType::Connected => {
println!("Gamepad was connected, firing GamepadEvent::Connected");
let name = String::from(name);
let event = GamepadEvent::Connected(index, name);
self.event_queue.push(EmbedderEvent::Gamepad(event));
},
EventType::Disconnected => {
let event = GamepadEvent::Disconnected(index);
self.event_queue.push(EmbedderEvent::Gamepad(event));
},
_ => {},
}
}
}
}

pub fn shutdown_requested(&self) -> bool {
self.shutdown_requested
}
Expand Down

0 comments on commit caad7ee

Please sign in to comment.