mirror of
https://github.com/servo/servo.git
synced 2025-08-05 21:50:18 +01:00
Auto merge of #28236 - pecastro:winit_0_24_surfman, r=jdm
Winit 0.24.0 and surfman <!-- Please describe your changes on the following line: --> I've updated Servo to Winit 0.24.0 based on the previous work in #26394. I've basically rebased master onto his jdm/winit branch which had the bulk of the work and I brute forced it till it built correcting things here and there as I could. The build reports a few warnings: ``` 00:04:59 Mar 03 10:20:06 warning: use of deprecated field `winit::event::KeyboardInput::modifiers`: Deprecated in favor of WindowEvent::ModifiersChanged 00:04:59 Mar 03 10:20:06 --> ports/winit/headed_window.rs:753:12 00:04:59 Mar 03 10:20:06 | 00:04:59 Mar 03 10:20:06 753 | if input.modifiers.shift() { 00:04:59 Mar 03 10:20:06 | ^^^^^^^^^^^^^^^ 00:04:59 Mar 03 10:20:06 | 00:04:59 Mar 03 10:20:06 = note: `#[warn(deprecated)]` on by default 00:04:59 Mar 03 10:20:06 00:04:59 Mar 03 10:20:06 warning: use of deprecated field `winit::event::KeyboardInput::modifiers`: Deprecated in favor of WindowEvent::ModifiersChanged 00:04:59 Mar 03 10:20:06 --> ports/winit/keyutils.rs:263:34 00:04:59 Mar 03 10:20:06 | 00:04:59 Mar 03 10:20:06 263 | modifiers: get_modifiers(input.modifiers), 00:04:59 Mar 03 10:20:06 | ^^^^^^^^^^^^^^^ 00:04:59 Mar 03 10:20:06 00:07:06 Mar 03 10:22:13 warning: 2 warnings emitted 00:07:06 Mar 03 10:22:13 00:07:06 Mar 03 10:22:13 Completed servo v0.0.1 bin "servo" in 132.7s 00:07:06 Mar 03 10:22:13 Finished dev [unoptimized + debuginfo] target(s) in 6m 59s 00:07:08 Mar 03 10:22:15 [Warning] Could not generate notification! 00:07:08 Mar 03 10:22:15 Build Completed in 0:07:01 ``` And there are a few commits namely b27e09e009 which I'm not entirely sure of. I've intentionally left the surfman patch in Cargo.toml so someone else can validate this branch. Unit tests and smoke test run successfully. Servo runs but I'm not familiar enough with it to validate how well it does. The window opens and content loads though. My Rust foo is not great and I could use some help fixing those warnings. Regards, PECastro --- <!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `___` with appropriate data: --> - [x ] `./mach build -d` does not report any errors A few warnings ... - [x ] `./mach test-tidy` does not report any errors A few duplicate version statements but no errors. - [x] These changes fix #26394 - [x] There are tests for these changes - [ ] These changes do not require tests because <!-- Also, please make sure that "Allow edits from maintainers" checkbox is checked, so that we can help you if you get stuck somewhere along the way.--> <!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. -->
This commit is contained in:
commit
68e200a581
21 changed files with 714 additions and 559 deletions
599
Cargo.lock
generated
599
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
|
@ -28,6 +28,8 @@ opt-level = 3
|
|||
|
||||
# This is here to dedupe winapi since mio 0.6 is still using winapi 0.2.
|
||||
mio = { git = "https://github.com/servo/mio.git", branch = "servo-mio-0.6.22" }
|
||||
# Work around bug in winit 0.24 crashing servo headless in macOS
|
||||
winit = { git = "https://github.com/rust-windowing/winit.git", rev = "4192d04a53202c199f94d1b7d883a34c9ad09272" }
|
||||
|
||||
[patch."https://github.com/jrmuizel/raqote"]
|
||||
raqote = { git = "https://github.com/jdm/raqote", branch = "fkup" }
|
||||
|
|
|
@ -40,8 +40,8 @@ sparkle = "0.1.25"
|
|||
style = { path = "../style" }
|
||||
style_traits = { path = "../style_traits" }
|
||||
# NOTE: the sm-angle feature only enables angle on windows, not other platforms!
|
||||
surfman = { version = "0.3", features = ["sm-angle","sm-angle-default"] }
|
||||
surfman-chains = "0.5"
|
||||
surfman = { version = "0.4", features = ["sm-angle","sm-angle-default"] }
|
||||
surfman-chains = "0.6"
|
||||
surfman-chains-api = "0.2"
|
||||
time = { version = "0.1.0", optional = true }
|
||||
webrender = { git = "https://github.com/servo/webrender" }
|
||||
|
|
|
@ -835,7 +835,7 @@ impl<Window: WindowMethods + ?Sized> IOCompositor<Window> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn on_resize_window_event(&mut self) {
|
||||
pub fn on_resize_window_event(&mut self) -> bool {
|
||||
debug!("compositor resize requested");
|
||||
|
||||
let old_coords = self.embedder_coordinates;
|
||||
|
@ -847,11 +847,12 @@ impl<Window: WindowMethods + ?Sized> IOCompositor<Window> {
|
|||
}
|
||||
|
||||
if self.embedder_coordinates.viewport == old_coords.viewport {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
self.send_window_size(WindowSizeType::Resize);
|
||||
self.composite_if_necessary(CompositingReason::Resize);
|
||||
return true;
|
||||
}
|
||||
|
||||
pub fn on_mouse_window_event_class(&mut self, mouse_window_event: MouseWindowEvent) {
|
||||
|
|
|
@ -78,7 +78,7 @@ servo_url = { path = "../url" }
|
|||
sparkle = "0.1"
|
||||
style = { path = "../style", features = ["servo"] }
|
||||
style_traits = { path = "../style_traits", features = ["servo"] }
|
||||
surfman = "0.3"
|
||||
surfman = "0.4"
|
||||
webdriver_server = { path = "../webdriver_server", optional = true }
|
||||
webgpu = { path = "../webgpu" }
|
||||
webrender = { git = "https://github.com/servo/webrender" }
|
||||
|
|
|
@ -549,7 +549,7 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
fn handle_window_event(&mut self, event: WindowEvent) {
|
||||
fn handle_window_event(&mut self, event: WindowEvent) -> bool {
|
||||
match event {
|
||||
WindowEvent::Idle => {},
|
||||
|
||||
|
@ -558,7 +558,7 @@ where
|
|||
},
|
||||
|
||||
WindowEvent::Resize => {
|
||||
self.compositor.on_resize_window_event();
|
||||
return self.compositor.on_resize_window_event();
|
||||
},
|
||||
|
||||
WindowEvent::AllowNavigationResponse(pipeline_id, allowed) => {
|
||||
|
@ -745,6 +745,7 @@ where
|
|||
}
|
||||
},
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
fn receive_messages(&mut self) {
|
||||
|
@ -776,18 +777,20 @@ where
|
|||
::std::mem::replace(&mut self.embedder_events, Vec::new())
|
||||
}
|
||||
|
||||
pub fn handle_events(&mut self, events: Vec<WindowEvent>) {
|
||||
pub fn handle_events(&mut self, events: Vec<WindowEvent>) -> bool {
|
||||
if self.compositor.receive_messages() {
|
||||
self.receive_messages();
|
||||
}
|
||||
let mut need_resize = false;
|
||||
for event in events {
|
||||
self.handle_window_event(event);
|
||||
need_resize |= self.handle_window_event(event);
|
||||
}
|
||||
if self.compositor.shutdown_state != ShutdownState::FinishedShuttingDown {
|
||||
self.compositor.perform_updates();
|
||||
} else {
|
||||
self.embedder_events.push((None, EmbedderMsg::Shutdown));
|
||||
}
|
||||
need_resize
|
||||
}
|
||||
|
||||
pub fn repaint_synchronously(&mut self) {
|
||||
|
|
|
@ -12,6 +12,6 @@ path = "lib.rs"
|
|||
|
||||
[dependencies]
|
||||
euclid = "0.20"
|
||||
surfman = "0.3"
|
||||
surfman-chains = "0.5"
|
||||
surfman = "0.4"
|
||||
surfman-chains = "0.6"
|
||||
|
||||
|
|
|
@ -29,8 +29,8 @@ libservo = { path = "../../components/servo" }
|
|||
log = "0.4"
|
||||
servo-media = { git = "https://github.com/servo/media" }
|
||||
sparkle = "0.1"
|
||||
surfman = "0.3"
|
||||
surfman-chains = "0.5"
|
||||
surfman = "0.4"
|
||||
surfman-chains = "0.6"
|
||||
surfman-chains-api = "0.2"
|
||||
webxr = { git = "https://github.com/servo/webxr", features = ["glwindow"] }
|
||||
|
||||
|
|
|
@ -249,7 +249,9 @@ impl ServoThread {
|
|||
ServoWebSrcMsg::GetSwapChain(sender) => self.send_swap_chain(sender),
|
||||
ServoWebSrcMsg::SetSwapChain(swap_chain) => self.swap_chain = Some(swap_chain.0),
|
||||
ServoWebSrcMsg::Resize(size) => self.resize(size),
|
||||
ServoWebSrcMsg::Heartbeat => self.servo.handle_events(vec![]),
|
||||
ServoWebSrcMsg::Heartbeat => {
|
||||
self.servo.handle_events(vec![]);
|
||||
},
|
||||
ServoWebSrcMsg::Stop => break,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ ipc-channel = "0.14"
|
|||
libservo = { path = "../../../components/servo" }
|
||||
log = "0.4"
|
||||
servo-media = { git = "https://github.com/servo/media" }
|
||||
surfman = { version = "0.3", features = ["sm-angle-default"] }
|
||||
surfman = { version = "0.4", features = ["sm-angle-default"] }
|
||||
webxr = { git = "https://github.com/servo/webxr"}
|
||||
webxr-api = { git = "https://github.com/servo/webxr", features = ["ipc"] }
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@ env_logger = "0.8"
|
|||
lazy_static = "1"
|
||||
log = "0.4"
|
||||
simpleservo = { path = "../api" }
|
||||
surfman = "0.3"
|
||||
surfman = "0.4"
|
||||
keyboard-types = "0.5"
|
||||
|
||||
[target.'cfg(target_os = "windows")'.dependencies]
|
||||
|
|
|
@ -57,10 +57,10 @@ libservo = { path = "../../components/servo" }
|
|||
log = "0.4"
|
||||
servo-media = { git = "https://github.com/servo/media" }
|
||||
shellwords = "1.0.0"
|
||||
surfman = { version = "0.3", features = ["sm-winit", "sm-x11"] }
|
||||
surfman = { version = "0.4", features = ["sm-winit", "sm-x11"] }
|
||||
tinyfiledialogs = "3.0"
|
||||
webxr = { git = "https://github.com/servo/webxr", features = ["ipc", "glwindow", "headless"] }
|
||||
winit = "0.19"
|
||||
winit = "0.24"
|
||||
|
||||
[target.'cfg(any(target_os = "linux", target_os = "windows"))'.dependencies]
|
||||
image = "0.23"
|
||||
|
|
|
@ -6,9 +6,11 @@
|
|||
|
||||
use crate::browser::Browser;
|
||||
use crate::embedder::EmbedderCallbacks;
|
||||
use crate::events_loop::EventsLoop;
|
||||
use crate::events_loop::{EventsLoop, ServoEvent};
|
||||
use crate::window_trait::WindowPortsMethods;
|
||||
use crate::{headed_window, headless_window};
|
||||
use winit::window::WindowId;
|
||||
use winit::event_loop::EventLoopWindowTarget;
|
||||
use servo::compositing::windowing::WindowEvent;
|
||||
use servo::config::opts::{self, parse_url_or_filename};
|
||||
use servo::servo_config::pref;
|
||||
|
@ -20,15 +22,13 @@ use std::env;
|
|||
use std::mem;
|
||||
use std::rc::Rc;
|
||||
use webxr::glwindow::GlWindowDiscovery;
|
||||
use winit::WindowId;
|
||||
|
||||
thread_local! {
|
||||
pub static WINDOWS: RefCell<HashMap<WindowId, Rc<dyn WindowPortsMethods>>> = RefCell::new(HashMap::new());
|
||||
}
|
||||
|
||||
pub struct App {
|
||||
events_loop: Rc<RefCell<EventsLoop>>,
|
||||
servo: RefCell<Servo<dyn WindowPortsMethods>>,
|
||||
servo: Option<Servo<dyn WindowPortsMethods>>,
|
||||
browser: RefCell<Browser<dyn WindowPortsMethods>>,
|
||||
event_queue: RefCell<Vec<WindowEvent>>,
|
||||
suspended: Cell<bool>,
|
||||
|
@ -48,49 +48,96 @@ impl App {
|
|||
} else {
|
||||
Rc::new(headed_window::Window::new(
|
||||
opts::get().initial_window_size,
|
||||
events_loop.clone(),
|
||||
&events_loop,
|
||||
no_native_titlebar,
|
||||
device_pixels_per_px,
|
||||
))
|
||||
};
|
||||
|
||||
let xr_discovery = if pref!(dom.webxr.glwindow.enabled) {
|
||||
let window = window.clone();
|
||||
let surfman = window.webrender_surfman();
|
||||
let events_loop = events_loop.clone();
|
||||
let factory = Box::new(move || Ok(window.new_glwindow(&*events_loop.borrow())));
|
||||
Some(GlWindowDiscovery::new(
|
||||
surfman.connection(),
|
||||
surfman.adapter(),
|
||||
surfman.context_attributes(),
|
||||
factory,
|
||||
))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
// Implements embedder methods, used by libservo and constellation.
|
||||
let embedder = Box::new(EmbedderCallbacks::new(events_loop.clone(), xr_discovery));
|
||||
|
||||
// Handle browser state.
|
||||
let browser = Browser::new(window.clone());
|
||||
|
||||
let mut servo = Servo::new(embedder, window.clone(), user_agent);
|
||||
let browser_id = BrowserId::new();
|
||||
servo.handle_events(vec![WindowEvent::NewBrowser(get_default_url(), browser_id)]);
|
||||
servo.setup_logging();
|
||||
|
||||
register_window(window);
|
||||
|
||||
let app = App {
|
||||
let mut app = App {
|
||||
event_queue: RefCell::new(vec![]),
|
||||
events_loop,
|
||||
browser: RefCell::new(browser),
|
||||
servo: RefCell::new(servo),
|
||||
servo: None,
|
||||
suspended: Cell::new(false),
|
||||
};
|
||||
|
||||
app.run_loop();
|
||||
let ev_waker = events_loop.create_event_loop_waker();
|
||||
events_loop.run_forever(move |e, w, control_flow| {
|
||||
if let winit::event::Event::NewEvents(winit::event::StartCause::Init) = e {
|
||||
let surfman = window.webrender_surfman();
|
||||
|
||||
let xr_discovery = if pref!(dom.webxr.glwindow.enabled) && ! opts::get().headless {
|
||||
let window = window.clone();
|
||||
// This should be safe because run_forever does, in fact,
|
||||
// run forever. The event loop window target doesn't get
|
||||
// moved, and does outlast this closure, and we won't
|
||||
// ever try to make use of it once shutdown begins and
|
||||
// it stops being valid.
|
||||
let w = unsafe {
|
||||
std::mem::transmute::<
|
||||
&EventLoopWindowTarget<ServoEvent>,
|
||||
&'static EventLoopWindowTarget<ServoEvent>
|
||||
>(w.unwrap())
|
||||
};
|
||||
let factory = Box::new(move || Ok(window.new_glwindow(w)));
|
||||
Some(GlWindowDiscovery::new(
|
||||
surfman.connection(),
|
||||
surfman.adapter(),
|
||||
surfman.context_attributes(),
|
||||
factory,
|
||||
))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let window = window.clone();
|
||||
// Implements embedder methods, used by libservo and constellation.
|
||||
let embedder = Box::new(EmbedderCallbacks::new(
|
||||
ev_waker.clone(),
|
||||
xr_discovery,
|
||||
));
|
||||
|
||||
let mut servo = Servo::new(embedder, window.clone(), user_agent.clone());
|
||||
let browser_id = BrowserId::new();
|
||||
servo.handle_events(vec![WindowEvent::NewBrowser(get_default_url(), browser_id)]);
|
||||
servo.setup_logging();
|
||||
|
||||
register_window(window.clone());
|
||||
app.servo = Some(servo);
|
||||
}
|
||||
|
||||
// If self.servo is None here, it means that we're in the process of shutting down,
|
||||
// let's ignore events.
|
||||
if app.servo.is_none() {
|
||||
return;
|
||||
}
|
||||
|
||||
// Handle the event
|
||||
app.winit_event_to_servo_event(e);
|
||||
|
||||
let animating = WINDOWS.with(|windows| {
|
||||
windows
|
||||
.borrow()
|
||||
.iter()
|
||||
.any(|(_, window)| window.is_animating())
|
||||
});
|
||||
|
||||
// Block until the window gets an event
|
||||
if !animating || app.suspended.get() {
|
||||
*control_flow = winit::event_loop::ControlFlow::Wait;
|
||||
} else {
|
||||
*control_flow = winit::event_loop::ControlFlow::Poll;
|
||||
}
|
||||
|
||||
let stop = app.handle_events();
|
||||
if stop {
|
||||
*control_flow = winit::event_loop::ControlFlow::Exit;
|
||||
app.servo.take().unwrap().deinit();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
fn get_events(&self) -> Vec<WindowEvent> {
|
||||
|
@ -98,87 +145,50 @@ impl App {
|
|||
}
|
||||
|
||||
// This function decides whether the event should be handled during `run_forever`.
|
||||
fn winit_event_to_servo_event(&self, event: winit::Event) -> winit::ControlFlow {
|
||||
fn winit_event_to_servo_event(&self, event: winit::event::Event<ServoEvent>) {
|
||||
match event {
|
||||
// App level events
|
||||
winit::Event::Suspended(suspended) => {
|
||||
self.suspended.set(suspended);
|
||||
if !suspended {
|
||||
self.event_queue.borrow_mut().push(WindowEvent::Idle);
|
||||
}
|
||||
winit::event::Event::Suspended => {
|
||||
self.suspended.set(true);
|
||||
},
|
||||
winit::Event::Awakened => {
|
||||
winit::event::Event::Resumed => {
|
||||
self.suspended.set(false);
|
||||
self.event_queue.borrow_mut().push(WindowEvent::Idle);
|
||||
},
|
||||
winit::event::Event::UserEvent(_) => {
|
||||
self.event_queue.borrow_mut().push(WindowEvent::Idle);
|
||||
},
|
||||
winit::event::Event::DeviceEvent { .. } => {},
|
||||
|
||||
winit::event::Event::RedrawRequested(_) => {
|
||||
self.event_queue.borrow_mut().push(WindowEvent::Idle);
|
||||
},
|
||||
winit::Event::DeviceEvent { .. } => {},
|
||||
|
||||
// Window level events
|
||||
winit::Event::WindowEvent {
|
||||
winit::event::Event::WindowEvent {
|
||||
window_id, event, ..
|
||||
} => {
|
||||
return WINDOWS.with(|windows| {
|
||||
match windows.borrow().get(&window_id) {
|
||||
None => {
|
||||
warn!("Got an event from unknown window");
|
||||
winit::ControlFlow::Break
|
||||
},
|
||||
Some(window) => {
|
||||
// Resize events need to be handled during run_forever
|
||||
let cont = if let winit::WindowEvent::Resized(_) = event {
|
||||
winit::ControlFlow::Continue
|
||||
} else {
|
||||
winit::ControlFlow::Break
|
||||
};
|
||||
window.winit_event_to_servo_event(event);
|
||||
return cont;
|
||||
},
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
winit::event::Event::LoopDestroyed |
|
||||
winit::event::Event::NewEvents(..) |
|
||||
winit::event::Event::MainEventsCleared |
|
||||
winit::event::Event::RedrawEventsCleared => {},
|
||||
}
|
||||
winit::ControlFlow::Break
|
||||
}
|
||||
|
||||
fn run_loop(self) {
|
||||
loop {
|
||||
let animating = WINDOWS.with(|windows| {
|
||||
windows
|
||||
.borrow()
|
||||
.iter()
|
||||
.any(|(_, window)| window.is_animating())
|
||||
});
|
||||
if !animating || self.suspended.get() {
|
||||
// If there's no animations running then we block on the window event loop.
|
||||
self.events_loop.borrow_mut().run_forever(|e| {
|
||||
let cont = self.winit_event_to_servo_event(e);
|
||||
if cont == winit::ControlFlow::Continue {
|
||||
// Note we need to be careful to make sure that any events
|
||||
// that are handled during run_forever aren't re-entrant,
|
||||
// since we are handling them while holding onto a mutable borrow
|
||||
// of the events loop
|
||||
self.handle_events();
|
||||
}
|
||||
cont
|
||||
});
|
||||
}
|
||||
// Grab any other events that may have happened
|
||||
self.events_loop.borrow_mut().poll_events(|e| {
|
||||
self.winit_event_to_servo_event(e);
|
||||
});
|
||||
// If animations are running, we block on compositing
|
||||
// (self.handle_events() ends up calling swap_buffers)
|
||||
let stop = self.handle_events();
|
||||
if stop {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
self.servo.into_inner().deinit()
|
||||
}
|
||||
|
||||
fn handle_events(&self) -> bool {
|
||||
fn handle_events(&mut self) -> bool {
|
||||
let mut browser = self.browser.borrow_mut();
|
||||
let mut servo = self.servo.borrow_mut();
|
||||
|
||||
// FIXME:
|
||||
// As of now, we support only one browser (self.browser)
|
||||
|
@ -194,30 +204,24 @@ impl App {
|
|||
}
|
||||
});
|
||||
|
||||
// FIXME: this could be handled by Servo. We don't need
|
||||
// a repaint_synchronously function exposed.
|
||||
let need_resize = app_events.iter().any(|e| match *e {
|
||||
WindowEvent::Resize => true,
|
||||
_ => false,
|
||||
});
|
||||
|
||||
browser.handle_window_events(app_events);
|
||||
|
||||
let mut servo_events = servo.get_events();
|
||||
let mut servo_events = self.servo.as_mut().unwrap().get_events();
|
||||
let mut need_resize = false;
|
||||
loop {
|
||||
browser.handle_servo_events(servo_events);
|
||||
servo.handle_events(browser.get_events());
|
||||
need_resize |= self.servo.as_mut().unwrap().handle_events(browser.get_events());
|
||||
if browser.shutdown_requested() {
|
||||
return true;
|
||||
}
|
||||
servo_events = servo.get_events();
|
||||
servo_events = self.servo.as_mut().unwrap().get_events();
|
||||
if servo_events.is_empty() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if need_resize {
|
||||
servo.repaint_synchronously();
|
||||
self.servo.as_mut().unwrap().repaint_synchronously();
|
||||
}
|
||||
false
|
||||
}
|
||||
|
|
|
@ -4,26 +4,23 @@
|
|||
|
||||
//! Implements the global methods required by Servo (not window/gl/compositor related).
|
||||
|
||||
use crate::events_loop::EventsLoop;
|
||||
use servo::compositing::windowing::EmbedderMethods;
|
||||
use servo::embedder_traits::{EmbedderProxy, EventLoopWaker};
|
||||
use servo::servo_config::pref;
|
||||
use std::cell::RefCell;
|
||||
use std::rc::Rc;
|
||||
use webxr::glwindow::GlWindowDiscovery;
|
||||
|
||||
pub struct EmbedderCallbacks {
|
||||
events_loop: Rc<RefCell<EventsLoop>>,
|
||||
event_loop_waker: Box<dyn EventLoopWaker>,
|
||||
xr_discovery: Option<GlWindowDiscovery>,
|
||||
}
|
||||
|
||||
impl EmbedderCallbacks {
|
||||
pub fn new(
|
||||
events_loop: Rc<RefCell<EventsLoop>>,
|
||||
event_loop_waker: Box<dyn EventLoopWaker>,
|
||||
xr_discovery: Option<GlWindowDiscovery>,
|
||||
) -> EmbedderCallbacks {
|
||||
EmbedderCallbacks {
|
||||
events_loop,
|
||||
event_loop_waker,
|
||||
xr_discovery,
|
||||
}
|
||||
}
|
||||
|
@ -31,7 +28,7 @@ impl EmbedderCallbacks {
|
|||
|
||||
impl EmbedderMethods for EmbedderCallbacks {
|
||||
fn create_event_loop_waker(&mut self) -> Box<dyn EventLoopWaker> {
|
||||
self.events_loop.borrow().create_event_loop_waker()
|
||||
self.event_loop_waker.clone()
|
||||
}
|
||||
|
||||
fn register_webxr(
|
||||
|
|
|
@ -5,16 +5,19 @@
|
|||
//! An event loop implementation that works in headless mode.
|
||||
|
||||
use servo::embedder_traits::EventLoopWaker;
|
||||
use std::cell::RefCell;
|
||||
use std::rc::Rc;
|
||||
use std::sync::{Arc, Condvar, Mutex};
|
||||
use std::time;
|
||||
use winit;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum ServoEvent {
|
||||
Awakened,
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
enum EventLoop {
|
||||
/// A real Winit windowing event loop.
|
||||
Winit(Option<winit::EventsLoop>),
|
||||
Winit(Option<winit::event_loop::EventLoop<ServoEvent>>),
|
||||
/// A fake event loop which contains a signalling flag used to ensure
|
||||
/// that pending events get processed in a timely fashion, and a condition
|
||||
/// variable to allow waiting on that flag changing state.
|
||||
|
@ -26,20 +29,17 @@ pub struct EventsLoop(EventLoop);
|
|||
impl EventsLoop {
|
||||
// Ideally, we could use the winit event loop in both modes,
|
||||
// but on Linux, the event loop requires a X11 server.
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
pub fn new(_headless: bool) -> Rc<RefCell<EventsLoop>> {
|
||||
Rc::new(RefCell::new(EventsLoop(EventLoop::Winit(Some(
|
||||
winit::EventsLoop::new(),
|
||||
)))))
|
||||
#[cfg(not(any(target_os = "linux", target_os = "macos")))]
|
||||
pub fn new(_headless: bool) -> EventsLoop {
|
||||
EventsLoop(EventLoop::Winit(Some(winit::event_loop::EventLoop::with_user_event())))
|
||||
}
|
||||
#[cfg(target_os = "linux")]
|
||||
pub fn new(headless: bool) -> Rc<RefCell<EventsLoop>> {
|
||||
let events_loop = if headless {
|
||||
#[cfg(any(target_os = "linux", target_os = "macos"))]
|
||||
pub fn new(headless: bool) -> EventsLoop {
|
||||
EventsLoop(if headless {
|
||||
EventLoop::Headless(Arc::new((Mutex::new(false), Condvar::new())))
|
||||
} else {
|
||||
EventLoop::Winit(Some(winit::EventsLoop::new()))
|
||||
};
|
||||
Rc::new(RefCell::new(EventsLoop(events_loop)))
|
||||
EventLoop::Winit(Some(winit::event_loop::EventLoop::with_user_event()))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -55,7 +55,7 @@ impl EventsLoop {
|
|||
EventLoop::Headless(ref data) => Box::new(HeadlessEventLoopWaker(data.clone())),
|
||||
}
|
||||
}
|
||||
pub fn as_winit(&self) -> &winit::EventsLoop {
|
||||
pub fn as_winit(&self) -> &winit::event_loop::EventLoop<ServoEvent> {
|
||||
match self.0 {
|
||||
EventLoop::Winit(Some(ref event_loop)) => event_loop,
|
||||
EventLoop::Winit(None) | EventLoop::Headless(..) => {
|
||||
|
@ -64,49 +64,45 @@ impl EventsLoop {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn poll_events<F>(&mut self, callback: F)
|
||||
where
|
||||
F: FnMut(winit::Event),
|
||||
{
|
||||
pub fn run_forever<F: 'static>(self, mut callback: F)
|
||||
where F: FnMut(
|
||||
winit::event::Event<ServoEvent>,
|
||||
Option<&winit::event_loop::EventLoopWindowTarget<ServoEvent>>,
|
||||
&mut winit::event_loop::ControlFlow
|
||||
) {
|
||||
match self.0 {
|
||||
EventLoop::Winit(Some(ref mut events_loop)) => events_loop.poll_events(callback),
|
||||
EventLoop::Winit(None) => (),
|
||||
EventLoop::Headless(ref data) => {
|
||||
// This is subtle - the use of the event loop in App::run_loop
|
||||
// optionally calls run_forever, then always calls poll_events.
|
||||
// If our signalling flag is true before we call run_forever,
|
||||
// we don't want to reset it before poll_events is called or
|
||||
// we'll end up sleeping even though there are events waiting
|
||||
// to be handled. We compromise by only resetting the flag here
|
||||
// in poll_events, so that both poll_events and run_forever can
|
||||
// check it first and avoid sleeping unnecessarily.
|
||||
self.sleep(&data.0, &data.1);
|
||||
*data.0.lock().unwrap() = false;
|
||||
},
|
||||
}
|
||||
}
|
||||
pub fn run_forever<F>(&mut self, mut callback: F)
|
||||
where
|
||||
F: FnMut(winit::Event) -> winit::ControlFlow,
|
||||
{
|
||||
match self.0 {
|
||||
EventLoop::Winit(ref mut events_loop) => {
|
||||
EventLoop::Winit(events_loop) => {
|
||||
let events_loop = events_loop
|
||||
.as_mut()
|
||||
.expect("Can't run an unavailable event loop.");
|
||||
events_loop.run_forever(callback);
|
||||
},
|
||||
events_loop.run(move |e, window_target, ref mut control_flow| {
|
||||
callback(e, Some(window_target), control_flow)
|
||||
});
|
||||
}
|
||||
EventLoop::Headless(ref data) => {
|
||||
let &(ref flag, ref condvar) = &**data;
|
||||
while !*flag.lock().unwrap() {
|
||||
let mut event = winit::event::Event::NewEvents(winit::event::StartCause::Init);
|
||||
loop {
|
||||
self.sleep(flag, condvar);
|
||||
if callback(winit::Event::Awakened) == winit::ControlFlow::Break {
|
||||
let mut control_flow = winit::event_loop::ControlFlow::Poll;
|
||||
callback(
|
||||
event,
|
||||
None,
|
||||
&mut control_flow
|
||||
);
|
||||
event = winit::event::Event::<ServoEvent>::UserEvent(ServoEvent::Awakened);
|
||||
|
||||
if control_flow != winit::event_loop::ControlFlow::Poll {
|
||||
*flag.lock().unwrap() = false;
|
||||
}
|
||||
|
||||
if control_flow == winit::event_loop::ControlFlow::Exit {
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn sleep(&self, lock: &Mutex<bool>, condvar: &Condvar) {
|
||||
// To avoid sleeping when we should be processing events, do two things:
|
||||
// * before sleeping, check whether our signalling flag has been set
|
||||
|
@ -123,18 +119,18 @@ impl EventsLoop {
|
|||
}
|
||||
|
||||
struct HeadedEventLoopWaker {
|
||||
proxy: Arc<winit::EventsLoopProxy>,
|
||||
proxy: Arc<Mutex<winit::event_loop::EventLoopProxy<ServoEvent>>>,
|
||||
}
|
||||
impl HeadedEventLoopWaker {
|
||||
fn new(events_loop: &winit::EventsLoop) -> HeadedEventLoopWaker {
|
||||
let proxy = Arc::new(events_loop.create_proxy());
|
||||
fn new(events_loop: &winit::event_loop::EventLoop<ServoEvent>) -> HeadedEventLoopWaker {
|
||||
let proxy = Arc::new(Mutex::new(events_loop.create_proxy()));
|
||||
HeadedEventLoopWaker { proxy }
|
||||
}
|
||||
}
|
||||
impl EventLoopWaker for HeadedEventLoopWaker {
|
||||
fn wake(&self) {
|
||||
// kick the OS event loop awake.
|
||||
if let Err(err) = self.proxy.wakeup() {
|
||||
// Kick the OS event loop awake.
|
||||
if let Err(err) = self.proxy.lock().unwrap().send_event(ServoEvent::Awakened) {
|
||||
warn!("Failed to wake up event loop ({}).", err);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,10 +4,18 @@
|
|||
|
||||
//! A winit window implementation.
|
||||
|
||||
use crate::events_loop::EventsLoop;
|
||||
use crate::events_loop::{EventsLoop, ServoEvent};
|
||||
use crate::keyutils::keyboard_event_from_winit;
|
||||
use crate::window_trait::{WindowPortsMethods, LINE_HEIGHT};
|
||||
use euclid::{Angle, Point2D, Rotation3D, Scale, Size2D, UnknownUnit, Vector2D, Vector3D};
|
||||
use euclid::{
|
||||
Angle, Point2D, Rotation3D, Scale, Size2D, UnknownUnit,
|
||||
Vector2D, Vector3D,
|
||||
};
|
||||
#[cfg(target_os = "macos")]
|
||||
use winit::platform::macos::{ActivationPolicy, WindowBuilderExtMacOS};
|
||||
#[cfg(any(target_os = "linux", target_os = "windows"))]
|
||||
use winit::window::Icon;
|
||||
use winit::event::{ElementState, KeyboardInput, MouseButton, MouseScrollDelta, TouchPhase, VirtualKeyCode};
|
||||
#[cfg(any(target_os = "linux", target_os = "windows"))]
|
||||
use image;
|
||||
use keyboard_types::{Key, KeyState, KeyboardEvent};
|
||||
|
@ -39,17 +47,11 @@ use surfman::GLVersion;
|
|||
use surfman::SurfaceType;
|
||||
#[cfg(target_os = "windows")]
|
||||
use winapi;
|
||||
use winit::dpi::{LogicalPosition, LogicalSize, PhysicalSize};
|
||||
#[cfg(target_os = "macos")]
|
||||
use winit::os::macos::{ActivationPolicy, WindowBuilderExt};
|
||||
#[cfg(any(target_os = "linux", target_os = "windows"))]
|
||||
use winit::Icon;
|
||||
use winit::{
|
||||
ElementState, KeyboardInput, MouseButton, MouseScrollDelta, TouchPhase, VirtualKeyCode,
|
||||
};
|
||||
use winit::dpi::{LogicalPosition, PhysicalPosition, PhysicalSize};
|
||||
use winit::event::ModifiersState;
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
fn builder_with_platform_options(mut builder: winit::WindowBuilder) -> winit::WindowBuilder {
|
||||
fn builder_with_platform_options(mut builder: winit::window::WindowBuilder) -> winit::window::WindowBuilder {
|
||||
if opts::get().output_file.is_some() {
|
||||
// Prevent the window from showing in Dock.app, stealing focus,
|
||||
// when generating an output file.
|
||||
|
@ -59,18 +61,18 @@ fn builder_with_platform_options(mut builder: winit::WindowBuilder) -> winit::Wi
|
|||
}
|
||||
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
fn builder_with_platform_options(builder: winit::WindowBuilder) -> winit::WindowBuilder {
|
||||
fn builder_with_platform_options(builder: winit::window::WindowBuilder) -> winit::window::WindowBuilder {
|
||||
builder
|
||||
}
|
||||
|
||||
pub struct Window {
|
||||
winit_window: winit::Window,
|
||||
winit_window: winit::window::Window,
|
||||
webrender_surfman: WebrenderSurfman,
|
||||
screen_size: Size2D<u32, DeviceIndependentPixel>,
|
||||
inner_size: Cell<Size2D<u32, DeviceIndependentPixel>>,
|
||||
mouse_down_button: Cell<Option<winit::MouseButton>>,
|
||||
mouse_down_button: Cell<Option<winit::event::MouseButton>>,
|
||||
mouse_down_point: Cell<Point2D<i32, DevicePixel>>,
|
||||
primary_monitor: winit::MonitorId,
|
||||
primary_monitor: winit::monitor::MonitorHandle,
|
||||
event_queue: RefCell<Vec<WindowEvent>>,
|
||||
mouse_pos: Cell<Point2D<i32, DevicePixel>>,
|
||||
last_pressed: Cell<Option<(KeyboardEvent, Option<VirtualKeyCode>)>>,
|
||||
|
@ -81,6 +83,7 @@ pub struct Window {
|
|||
fullscreen: Cell<bool>,
|
||||
device_pixels_per_px: Option<f32>,
|
||||
xr_window_poses: RefCell<Vec<Rc<XRWindowPose>>>,
|
||||
modifiers_state: Cell<ModifiersState>,
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
|
@ -98,7 +101,7 @@ fn window_creation_scale_factor() -> Scale<f32, DeviceIndependentPixel, DevicePi
|
|||
impl Window {
|
||||
pub fn new(
|
||||
win_size: Size2D<u32, DeviceIndependentPixel>,
|
||||
events_loop: Rc<RefCell<EventsLoop>>,
|
||||
events_loop: &EventsLoop,
|
||||
no_native_titlebar: bool,
|
||||
device_pixels_per_px: Option<f32>,
|
||||
) -> Window {
|
||||
|
@ -114,19 +117,16 @@ impl Window {
|
|||
let width = win_size.to_untyped().width;
|
||||
let height = win_size.to_untyped().height;
|
||||
|
||||
let mut window_builder = winit::WindowBuilder::new()
|
||||
let mut window_builder = winit::window::WindowBuilder::new()
|
||||
.with_title("Servo".to_string())
|
||||
.with_decorations(!no_native_titlebar)
|
||||
.with_transparency(no_native_titlebar)
|
||||
.with_dimensions(LogicalSize::new(width as f64, height as f64))
|
||||
.with_visibility(visible)
|
||||
.with_multitouch();
|
||||
.with_transparent(no_native_titlebar)
|
||||
.with_inner_size(PhysicalSize::new(width as f64, height as f64))
|
||||
.with_visible(visible);
|
||||
|
||||
window_builder = builder_with_platform_options(window_builder);
|
||||
|
||||
let winit_window = window_builder
|
||||
.build(events_loop.borrow().as_winit())
|
||||
.expect("Failed to create window.");
|
||||
let winit_window = window_builder.build(events_loop.as_winit()).expect("Failed to create window.");
|
||||
|
||||
#[cfg(any(target_os = "linux", target_os = "windows"))]
|
||||
{
|
||||
|
@ -134,21 +134,16 @@ impl Window {
|
|||
winit_window.set_window_icon(Some(load_icon(icon_bytes)));
|
||||
}
|
||||
|
||||
let primary_monitor = events_loop.borrow().as_winit().get_primary_monitor();
|
||||
let primary_monitor = events_loop.as_winit().available_monitors().nth(0).expect("No monitor detected");
|
||||
|
||||
let PhysicalSize {
|
||||
width: screen_width,
|
||||
height: screen_height,
|
||||
} = primary_monitor.get_dimensions();
|
||||
} = primary_monitor.clone().size();
|
||||
let screen_size = Size2D::new(screen_width as u32, screen_height as u32);
|
||||
// TODO(ajeffrey): can this fail?
|
||||
let LogicalSize { width, height } = winit_window
|
||||
.get_inner_size()
|
||||
.expect("Failed to get window inner size.");
|
||||
let PhysicalSize { width, height } = winit_window.inner_size();
|
||||
let inner_size = Size2D::new(width as u32, height as u32);
|
||||
|
||||
winit_window.show();
|
||||
|
||||
// Initialize surfman
|
||||
let connection =
|
||||
Connection::from_winit_window(&winit_window).expect("Failed to create connection");
|
||||
|
@ -179,6 +174,7 @@ impl Window {
|
|||
screen_size,
|
||||
device_pixels_per_px,
|
||||
xr_window_poses: RefCell::new(vec![]),
|
||||
modifiers_state: Cell::new(ModifiersState::empty()),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -227,7 +223,7 @@ impl Window {
|
|||
}
|
||||
|
||||
fn handle_keyboard_input(&self, input: KeyboardInput) {
|
||||
let mut event = keyboard_event_from_winit(input);
|
||||
let mut event = keyboard_event_from_winit(input, self.modifiers_state.get());
|
||||
trace!("handling {:?}", event);
|
||||
if event.state == KeyState::Down && event.key == Key::Unidentified {
|
||||
// If pressed and probably printable, we expect a ReceivedCharacter event.
|
||||
|
@ -247,7 +243,7 @@ impl Window {
|
|||
self.last_pressed.set(None);
|
||||
let xr_poses = self.xr_window_poses.borrow();
|
||||
for xr_window_pose in &*xr_poses {
|
||||
xr_window_pose.handle_xr_rotation(&input);
|
||||
xr_window_pose.handle_xr_rotation(&input, self.modifiers_state.get());
|
||||
}
|
||||
self.event_queue
|
||||
.borrow_mut()
|
||||
|
@ -258,17 +254,17 @@ impl Window {
|
|||
/// Helper function to handle a click
|
||||
fn handle_mouse(
|
||||
&self,
|
||||
button: winit::MouseButton,
|
||||
action: winit::ElementState,
|
||||
button: winit::event::MouseButton,
|
||||
action: winit::event::ElementState,
|
||||
coords: Point2D<i32, DevicePixel>,
|
||||
) {
|
||||
use servo::script_traits::MouseButton;
|
||||
|
||||
let max_pixel_dist = 10.0 * self.servo_hidpi_factor().get();
|
||||
let mouse_button = match &button {
|
||||
winit::MouseButton::Left => MouseButton::Left,
|
||||
winit::MouseButton::Right => MouseButton::Right,
|
||||
winit::MouseButton::Middle => MouseButton::Middle,
|
||||
winit::event::MouseButton::Left => MouseButton::Left,
|
||||
winit::event::MouseButton::Right => MouseButton::Right,
|
||||
winit::event::MouseButton::Middle => MouseButton::Middle,
|
||||
_ => MouseButton::Left,
|
||||
};
|
||||
let event = match action {
|
||||
|
@ -305,7 +301,7 @@ impl Window {
|
|||
}
|
||||
|
||||
fn device_hidpi_factor(&self) -> Scale<f32, DeviceIndependentPixel, DevicePixel> {
|
||||
Scale::new(self.winit_window.get_hidpi_factor() as f32)
|
||||
Scale::new(self.winit_window.scale_factor() as f32)
|
||||
}
|
||||
|
||||
fn servo_hidpi_factor(&self) -> Scale<f32, DeviceIndependentPixel, DevicePixel> {
|
||||
|
@ -332,8 +328,7 @@ impl WindowPortsMethods for Window {
|
|||
let dpr = self.servo_hidpi_factor();
|
||||
let size = self
|
||||
.winit_window
|
||||
.get_inner_size()
|
||||
.expect("Failed to get window inner size.");
|
||||
.inner_size();
|
||||
size.height as f32 * dpr.get()
|
||||
}
|
||||
|
||||
|
@ -342,24 +337,23 @@ impl WindowPortsMethods for Window {
|
|||
}
|
||||
|
||||
fn set_inner_size(&self, size: DeviceIntSize) {
|
||||
let size = size.to_f32() / self.device_hidpi_factor();
|
||||
self.winit_window
|
||||
.set_inner_size(LogicalSize::new(size.width.into(), size.height.into()))
|
||||
.set_inner_size::<PhysicalSize<i32>>(PhysicalSize::new(size.width.into(), size.height.into()))
|
||||
}
|
||||
|
||||
fn set_position(&self, point: DeviceIntPoint) {
|
||||
let point = point.to_f32() / self.device_hidpi_factor();
|
||||
self.winit_window
|
||||
.set_position(LogicalPosition::new(point.x.into(), point.y.into()))
|
||||
.set_outer_position::<PhysicalPosition<i32>>(PhysicalPosition::new(point.x.into(), point.y.into()))
|
||||
}
|
||||
|
||||
fn set_fullscreen(&self, state: bool) {
|
||||
if self.fullscreen.get() != state {
|
||||
self.winit_window.set_fullscreen(if state {
|
||||
Some(self.primary_monitor.clone())
|
||||
} else {
|
||||
None
|
||||
});
|
||||
self.winit_window
|
||||
.set_fullscreen(
|
||||
if state {
|
||||
Some(winit::window::Fullscreen::Borderless(Some(self.primary_monitor.clone())))
|
||||
} else { None }
|
||||
);
|
||||
}
|
||||
self.fullscreen.set(state);
|
||||
}
|
||||
|
@ -369,68 +363,68 @@ impl WindowPortsMethods for Window {
|
|||
}
|
||||
|
||||
fn set_cursor(&self, cursor: Cursor) {
|
||||
use winit::MouseCursor;
|
||||
use winit::window::CursorIcon;
|
||||
|
||||
let winit_cursor = match cursor {
|
||||
Cursor::Default => MouseCursor::Default,
|
||||
Cursor::Pointer => MouseCursor::Hand,
|
||||
Cursor::ContextMenu => MouseCursor::ContextMenu,
|
||||
Cursor::Help => MouseCursor::Help,
|
||||
Cursor::Progress => MouseCursor::Progress,
|
||||
Cursor::Wait => MouseCursor::Wait,
|
||||
Cursor::Cell => MouseCursor::Cell,
|
||||
Cursor::Crosshair => MouseCursor::Crosshair,
|
||||
Cursor::Text => MouseCursor::Text,
|
||||
Cursor::VerticalText => MouseCursor::VerticalText,
|
||||
Cursor::Alias => MouseCursor::Alias,
|
||||
Cursor::Copy => MouseCursor::Copy,
|
||||
Cursor::Move => MouseCursor::Move,
|
||||
Cursor::NoDrop => MouseCursor::NoDrop,
|
||||
Cursor::NotAllowed => MouseCursor::NotAllowed,
|
||||
Cursor::Grab => MouseCursor::Grab,
|
||||
Cursor::Grabbing => MouseCursor::Grabbing,
|
||||
Cursor::EResize => MouseCursor::EResize,
|
||||
Cursor::NResize => MouseCursor::NResize,
|
||||
Cursor::NeResize => MouseCursor::NeResize,
|
||||
Cursor::NwResize => MouseCursor::NwResize,
|
||||
Cursor::SResize => MouseCursor::SResize,
|
||||
Cursor::SeResize => MouseCursor::SeResize,
|
||||
Cursor::SwResize => MouseCursor::SwResize,
|
||||
Cursor::WResize => MouseCursor::WResize,
|
||||
Cursor::EwResize => MouseCursor::EwResize,
|
||||
Cursor::NsResize => MouseCursor::NsResize,
|
||||
Cursor::NeswResize => MouseCursor::NeswResize,
|
||||
Cursor::NwseResize => MouseCursor::NwseResize,
|
||||
Cursor::ColResize => MouseCursor::ColResize,
|
||||
Cursor::RowResize => MouseCursor::RowResize,
|
||||
Cursor::AllScroll => MouseCursor::AllScroll,
|
||||
Cursor::ZoomIn => MouseCursor::ZoomIn,
|
||||
Cursor::ZoomOut => MouseCursor::ZoomOut,
|
||||
_ => MouseCursor::Default,
|
||||
Cursor::Default => CursorIcon::Default,
|
||||
Cursor::Pointer => CursorIcon::Hand,
|
||||
Cursor::ContextMenu => CursorIcon::ContextMenu,
|
||||
Cursor::Help => CursorIcon::Help,
|
||||
Cursor::Progress => CursorIcon::Progress,
|
||||
Cursor::Wait => CursorIcon::Wait,
|
||||
Cursor::Cell => CursorIcon::Cell,
|
||||
Cursor::Crosshair => CursorIcon::Crosshair,
|
||||
Cursor::Text => CursorIcon::Text,
|
||||
Cursor::VerticalText => CursorIcon::VerticalText,
|
||||
Cursor::Alias => CursorIcon::Alias,
|
||||
Cursor::Copy => CursorIcon::Copy,
|
||||
Cursor::Move => CursorIcon::Move,
|
||||
Cursor::NoDrop => CursorIcon::NoDrop,
|
||||
Cursor::NotAllowed => CursorIcon::NotAllowed,
|
||||
Cursor::Grab => CursorIcon::Grab,
|
||||
Cursor::Grabbing => CursorIcon::Grabbing,
|
||||
Cursor::EResize => CursorIcon::EResize,
|
||||
Cursor::NResize => CursorIcon::NResize,
|
||||
Cursor::NeResize => CursorIcon::NeResize,
|
||||
Cursor::NwResize => CursorIcon::NwResize,
|
||||
Cursor::SResize => CursorIcon::SResize,
|
||||
Cursor::SeResize => CursorIcon::SeResize,
|
||||
Cursor::SwResize => CursorIcon::SwResize,
|
||||
Cursor::WResize => CursorIcon::WResize,
|
||||
Cursor::EwResize => CursorIcon::EwResize,
|
||||
Cursor::NsResize => CursorIcon::NsResize,
|
||||
Cursor::NeswResize => CursorIcon::NeswResize,
|
||||
Cursor::NwseResize => CursorIcon::NwseResize,
|
||||
Cursor::ColResize => CursorIcon::ColResize,
|
||||
Cursor::RowResize => CursorIcon::RowResize,
|
||||
Cursor::AllScroll => CursorIcon::AllScroll,
|
||||
Cursor::ZoomIn => CursorIcon::ZoomIn,
|
||||
Cursor::ZoomOut => CursorIcon::ZoomOut,
|
||||
_ => CursorIcon::Default,
|
||||
};
|
||||
self.winit_window.set_cursor(winit_cursor);
|
||||
self.winit_window.set_cursor_icon(winit_cursor);
|
||||
}
|
||||
|
||||
fn is_animating(&self) -> bool {
|
||||
self.animation_state.get() == AnimationState::Animating
|
||||
}
|
||||
|
||||
fn id(&self) -> winit::WindowId {
|
||||
fn id(&self) -> winit::window::WindowId {
|
||||
self.winit_window.id()
|
||||
}
|
||||
|
||||
fn winit_event_to_servo_event(&self, event: winit::WindowEvent) {
|
||||
fn winit_event_to_servo_event(&self, event: winit::event::WindowEvent) {
|
||||
match event {
|
||||
winit::WindowEvent::ReceivedCharacter(ch) => self.handle_received_character(ch),
|
||||
winit::WindowEvent::KeyboardInput { input, .. } => self.handle_keyboard_input(input),
|
||||
winit::WindowEvent::MouseInput { state, button, .. } => {
|
||||
winit::event::WindowEvent::ReceivedCharacter(ch) => self.handle_received_character(ch),
|
||||
winit::event::WindowEvent::KeyboardInput { input, .. } => self.handle_keyboard_input(input),
|
||||
winit::event::WindowEvent::ModifiersChanged(state) => self.modifiers_state.set(state),
|
||||
winit::event::WindowEvent::MouseInput { state, button, .. } => {
|
||||
if button == MouseButton::Left || button == MouseButton::Right {
|
||||
self.handle_mouse(button, state, self.mouse_pos.get());
|
||||
}
|
||||
},
|
||||
winit::WindowEvent::CursorMoved { position, .. } => {
|
||||
let pos = position.to_physical(self.device_hidpi_factor().get() as f64);
|
||||
let (x, y): (i32, i32) = pos.into();
|
||||
winit::event::WindowEvent::CursorMoved { position, .. } => {
|
||||
let (x, y): (i32, i32) = position.into();
|
||||
self.mouse_pos.set(Point2D::new(x, y));
|
||||
self.event_queue
|
||||
.borrow_mut()
|
||||
|
@ -438,15 +432,15 @@ impl WindowPortsMethods for Window {
|
|||
x as f32, y as f32,
|
||||
)));
|
||||
},
|
||||
winit::WindowEvent::MouseWheel { delta, phase, .. } => {
|
||||
winit::event::WindowEvent::MouseWheel { delta, phase, .. } => {
|
||||
let (mut dx, mut dy, mode) = match delta {
|
||||
MouseScrollDelta::LineDelta(dx, dy) => {
|
||||
(dx as f64, (dy * LINE_HEIGHT) as f64, WheelMode::DeltaLine)
|
||||
},
|
||||
MouseScrollDelta::PixelDelta(position) => {
|
||||
let position =
|
||||
position.to_physical(self.device_hidpi_factor().get() as f64);
|
||||
(position.x as f64, position.y as f64, WheelMode::DeltaPixel)
|
||||
let position: LogicalPosition<f64> =
|
||||
position.to_logical(self.device_hidpi_factor().get() as f64);
|
||||
(position.x, position.y, WheelMode::DeltaPixel)
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -478,30 +472,24 @@ impl WindowPortsMethods for Window {
|
|||
self.event_queue.borrow_mut().push(wheel_event);
|
||||
self.event_queue.borrow_mut().push(scroll_event);
|
||||
},
|
||||
winit::WindowEvent::Touch(touch) => {
|
||||
winit::event::WindowEvent::Touch(touch) => {
|
||||
use servo::script_traits::TouchId;
|
||||
|
||||
let phase = winit_phase_to_touch_event_type(touch.phase);
|
||||
let id = TouchId(touch.id as i32);
|
||||
let position = touch
|
||||
.location
|
||||
.to_physical(self.device_hidpi_factor().get() as f64);
|
||||
let position = touch.location;
|
||||
let point = Point2D::new(position.x as f32, position.y as f32);
|
||||
self.event_queue
|
||||
.borrow_mut()
|
||||
.push(WindowEvent::Touch(phase, id, point));
|
||||
},
|
||||
winit::WindowEvent::Refresh => {
|
||||
self.event_queue.borrow_mut().push(WindowEvent::Refresh);
|
||||
},
|
||||
winit::WindowEvent::CloseRequested => {
|
||||
winit::event::WindowEvent::CloseRequested => {
|
||||
self.event_queue.borrow_mut().push(WindowEvent::Quit);
|
||||
},
|
||||
winit::WindowEvent::Resized(size) => {
|
||||
let (width, height) = size.into();
|
||||
winit::event::WindowEvent::Resized(physical_size) => {
|
||||
let (width, height) = physical_size.into();
|
||||
let new_size = Size2D::new(width, height);
|
||||
if self.inner_size.get() != new_size {
|
||||
let physical_size = size.to_physical(self.device_hidpi_factor().get() as f64);
|
||||
let physical_size = Size2D::new(physical_size.width, physical_size.height);
|
||||
self.webrender_surfman
|
||||
.resize(physical_size.to_i32())
|
||||
|
@ -514,21 +502,20 @@ impl WindowPortsMethods for Window {
|
|||
}
|
||||
}
|
||||
|
||||
fn new_glwindow(&self, events_loop: &EventsLoop) -> Box<dyn webxr::glwindow::GlWindow> {
|
||||
let size = self
|
||||
.winit_window
|
||||
.get_outer_size()
|
||||
.expect("Failed to get window outer size");
|
||||
fn new_glwindow(
|
||||
&self,
|
||||
event_loop: &winit::event_loop::EventLoopWindowTarget<ServoEvent>
|
||||
) -> Box<dyn webxr::glwindow::GlWindow> {
|
||||
let size = self.winit_window.outer_size();
|
||||
|
||||
let mut window_builder = winit::WindowBuilder::new()
|
||||
let mut window_builder = winit::window::WindowBuilder::new()
|
||||
.with_title("Servo XR".to_string())
|
||||
.with_dimensions(size)
|
||||
.with_visibility(true);
|
||||
.with_inner_size(size)
|
||||
.with_visible(true);
|
||||
|
||||
window_builder = builder_with_platform_options(window_builder);
|
||||
|
||||
let winit_window = window_builder
|
||||
.build(events_loop.as_winit())
|
||||
let winit_window = window_builder.build(event_loop)
|
||||
.expect("Failed to create window.");
|
||||
|
||||
let pose = Rc::new(XRWindowPose {
|
||||
|
@ -542,24 +529,23 @@ impl WindowPortsMethods for Window {
|
|||
|
||||
impl WindowMethods for Window {
|
||||
fn get_coordinates(&self) -> EmbedderCoordinates {
|
||||
// TODO(ajeffrey): can this fail?
|
||||
let dpr = self.device_hidpi_factor();
|
||||
let LogicalSize { width, height } = self
|
||||
// Needed to convince the type system that winit's physical pixels
|
||||
// are actually device pixels.
|
||||
let dpr: Scale<f32, DeviceIndependentPixel, DevicePixel> = Scale::new(1.0);
|
||||
let PhysicalSize { width, height } = self
|
||||
.winit_window
|
||||
.get_outer_size()
|
||||
.expect("Failed to get window outer size.");
|
||||
let LogicalPosition { x, y } = self
|
||||
.outer_size();
|
||||
let PhysicalPosition { x, y } = self
|
||||
.winit_window
|
||||
.get_position()
|
||||
.unwrap_or(LogicalPosition::new(0., 0.));
|
||||
.outer_position()
|
||||
.unwrap_or(PhysicalPosition::new(0, 0));
|
||||
let win_size = (Size2D::new(width as f32, height as f32) * dpr).to_i32();
|
||||
let win_origin = (Point2D::new(x as f32, y as f32) * dpr).to_i32();
|
||||
let screen = (self.screen_size.to_f32() * dpr).to_i32();
|
||||
|
||||
let LogicalSize { width, height } = self
|
||||
let PhysicalSize { width, height } = self
|
||||
.winit_window
|
||||
.get_inner_size()
|
||||
.expect("Failed to get window inner size.");
|
||||
.inner_size();
|
||||
let inner_size = (Size2D::new(width as f32, height as f32) * dpr).to_i32();
|
||||
let viewport = DeviceIntRect::new(Point2D::zero(), inner_size);
|
||||
let framebuffer = DeviceIntSize::from_untyped(viewport.size.to_untyped());
|
||||
|
@ -684,7 +670,7 @@ fn load_icon(icon_bytes: &[u8]) -> Icon {
|
|||
}
|
||||
|
||||
struct XRWindow {
|
||||
winit_window: winit::Window,
|
||||
winit_window: winit::window::Window,
|
||||
pose: Rc<XRWindowPose>,
|
||||
}
|
||||
|
||||
|
@ -757,8 +743,8 @@ impl XRWindowPose {
|
|||
self.xr_translation.set(vec);
|
||||
}
|
||||
|
||||
fn handle_xr_rotation(&self, input: &KeyboardInput) {
|
||||
if input.state != winit::ElementState::Pressed {
|
||||
fn handle_xr_rotation(&self, input: &KeyboardInput, modifiers: ModifiersState) {
|
||||
if input.state != winit::event::ElementState::Pressed {
|
||||
return;
|
||||
}
|
||||
let mut x = 0.0;
|
||||
|
@ -770,7 +756,7 @@ impl XRWindowPose {
|
|||
Some(VirtualKeyCode::Right) => y = -1.0,
|
||||
_ => return,
|
||||
};
|
||||
if input.modifiers.shift {
|
||||
if modifiers.shift() {
|
||||
x = 10.0 * x;
|
||||
y = 10.0 * y;
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
//! A headless window implementation.
|
||||
|
||||
use crate::events_loop::EventsLoop;
|
||||
use crate::events_loop::ServoEvent;
|
||||
use crate::window_trait::WindowPortsMethods;
|
||||
use euclid::{Point2D, Rotation3D, Scale, Size2D, UnknownUnit, Vector3D};
|
||||
use servo::compositing::windowing::{AnimationState, WindowEvent};
|
||||
|
@ -71,8 +71,8 @@ impl WindowPortsMethods for Window {
|
|||
false
|
||||
}
|
||||
|
||||
fn id(&self) -> winit::WindowId {
|
||||
unsafe { winit::WindowId::dummy() }
|
||||
fn id(&self) -> winit::window::WindowId {
|
||||
unsafe { winit::window::WindowId::dummy() }
|
||||
}
|
||||
|
||||
fn page_height(&self) -> f32 {
|
||||
|
@ -98,11 +98,14 @@ impl WindowPortsMethods for Window {
|
|||
self.animation_state.get() == AnimationState::Animating
|
||||
}
|
||||
|
||||
fn winit_event_to_servo_event(&self, _event: winit::WindowEvent) {
|
||||
fn winit_event_to_servo_event(&self, _event: winit::event::WindowEvent) {
|
||||
// Not expecting any winit events.
|
||||
}
|
||||
|
||||
fn new_glwindow(&self, _events_loop: &EventsLoop) -> Box<dyn webxr::glwindow::GlWindow> {
|
||||
fn new_glwindow(
|
||||
&self,
|
||||
_events_loop: &winit::event_loop::EventLoopWindowTarget<ServoEvent>
|
||||
) -> Box<dyn webxr::glwindow::GlWindow> {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,8 +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/. */
|
||||
|
||||
use winit::event::{ElementState, KeyboardInput, ModifiersState, VirtualKeyCode};
|
||||
use keyboard_types::{Code, Key, KeyState, KeyboardEvent, Location, Modifiers};
|
||||
use winit::{ElementState, KeyboardInput, ModifiersState, VirtualKeyCode};
|
||||
|
||||
// Some shortcuts use Cmd on Mac and Control on other systems.
|
||||
#[cfg(target_os = "macos")]
|
||||
|
@ -18,7 +18,7 @@ pub const CMD_OR_ALT: Modifiers = Modifiers::META;
|
|||
pub const CMD_OR_ALT: Modifiers = Modifiers::ALT;
|
||||
|
||||
fn get_servo_key_from_winit_key(key: Option<VirtualKeyCode>) -> Key {
|
||||
use winit::VirtualKeyCode::*;
|
||||
use winit::event::VirtualKeyCode::*;
|
||||
// TODO: figure out how to map NavigateForward, NavigateBackward
|
||||
// TODO: map the remaining keys if possible
|
||||
let key = if let Some(key) = key {
|
||||
|
@ -127,7 +127,7 @@ fn get_servo_key_from_winit_key(key: Option<VirtualKeyCode>) -> Key {
|
|||
}
|
||||
|
||||
fn get_servo_location_from_winit_key(key: Option<VirtualKeyCode>) -> Location {
|
||||
use winit::VirtualKeyCode::*;
|
||||
use winit::event::VirtualKeyCode::*;
|
||||
// TODO: add more numpad keys
|
||||
let key = if let Some(key) = key {
|
||||
key
|
||||
|
@ -243,14 +243,14 @@ fn get_servo_code_from_scancode(_scancode: u32) -> Code {
|
|||
|
||||
fn get_modifiers(mods: ModifiersState) -> Modifiers {
|
||||
let mut modifiers = Modifiers::empty();
|
||||
modifiers.set(Modifiers::CONTROL, mods.ctrl);
|
||||
modifiers.set(Modifiers::SHIFT, mods.shift);
|
||||
modifiers.set(Modifiers::ALT, mods.alt);
|
||||
modifiers.set(Modifiers::META, mods.logo);
|
||||
modifiers.set(Modifiers::CONTROL, mods.ctrl());
|
||||
modifiers.set(Modifiers::SHIFT, mods.shift());
|
||||
modifiers.set(Modifiers::ALT, mods.alt());
|
||||
modifiers.set(Modifiers::META, mods.logo());
|
||||
modifiers
|
||||
}
|
||||
|
||||
pub fn keyboard_event_from_winit(input: KeyboardInput) -> KeyboardEvent {
|
||||
pub fn keyboard_event_from_winit(input: KeyboardInput, state: ModifiersState) -> KeyboardEvent {
|
||||
info!("winit keyboard input: {:?}", input);
|
||||
KeyboardEvent {
|
||||
state: match input.state {
|
||||
|
@ -260,7 +260,7 @@ pub fn keyboard_event_from_winit(input: KeyboardInput) -> KeyboardEvent {
|
|||
key: get_servo_key_from_winit_key(input.virtual_keycode),
|
||||
code: get_servo_code_from_scancode(input.scancode),
|
||||
location: get_servo_location_from_winit_key(input.virtual_keycode),
|
||||
modifiers: get_modifiers(input.modifiers),
|
||||
modifiers: get_modifiers(state),
|
||||
repeat: false,
|
||||
is_composing: false,
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
//! Definition of Window.
|
||||
//! Implemented by headless and headed windows.
|
||||
|
||||
use crate::events_loop::EventsLoop;
|
||||
use crate::events_loop::ServoEvent;
|
||||
use servo::compositing::windowing::{WindowEvent, WindowMethods};
|
||||
use servo::embedder_traits::Cursor;
|
||||
use servo::webrender_api::units::{DeviceIntPoint, DeviceIntSize};
|
||||
|
@ -16,16 +16,19 @@ pub const LINE_HEIGHT: f32 = 38.0;
|
|||
|
||||
pub trait WindowPortsMethods: WindowMethods {
|
||||
fn get_events(&self) -> Vec<WindowEvent>;
|
||||
fn id(&self) -> winit::WindowId;
|
||||
fn id(&self) -> winit::window::WindowId;
|
||||
fn has_events(&self) -> bool;
|
||||
fn page_height(&self) -> f32;
|
||||
fn get_fullscreen(&self) -> bool;
|
||||
fn winit_event_to_servo_event(&self, event: winit::WindowEvent);
|
||||
fn winit_event_to_servo_event(&self, event: winit::event::WindowEvent);
|
||||
fn is_animating(&self) -> bool;
|
||||
fn set_title(&self, _title: &str) {}
|
||||
fn set_inner_size(&self, _size: DeviceIntSize) {}
|
||||
fn set_position(&self, _point: DeviceIntPoint) {}
|
||||
fn set_fullscreen(&self, _state: bool) {}
|
||||
fn set_cursor(&self, _cursor: Cursor) {}
|
||||
fn new_glwindow(&self, events_loop: &EventsLoop) -> Box<dyn webxr::glwindow::GlWindow>;
|
||||
fn new_glwindow(
|
||||
&self,
|
||||
events_loop: &winit::event_loop::EventLoopWindowTarget<ServoEvent>
|
||||
) -> Box<dyn webxr::glwindow::GlWindow>;
|
||||
}
|
||||
|
|
|
@ -67,17 +67,18 @@ packages = [
|
|||
# Lots of crates to update.
|
||||
"smallvec",
|
||||
|
||||
# https://github.com/servo/servo/issues/24421
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-xid",
|
||||
|
||||
# https://github.com/servo/servo/pull/25518
|
||||
"core-foundation",
|
||||
"core-foundation-sys",
|
||||
"core-graphics",
|
||||
"lyon_geom",
|
||||
|
||||
# https://github.com/servo/servo/pull/28236
|
||||
"dlib",
|
||||
"nix",
|
||||
"nom",
|
||||
"strsim",
|
||||
|
||||
# Duplicated by webrender debugger via ws
|
||||
"digest",
|
||||
"generic-array",
|
||||
|
|
|
@ -1,2 +0,0 @@
|
|||
[flexible-order.html]
|
||||
expected: FAIL
|
Loading…
Add table
Add a link
Reference in a new issue