Update to winit 0.24.

Co-authored-by: Josh Matthews <josh@joshmatthews.net>
Co-authored-by: Paulo E. Castro <pecastro@wormholenet.com>
This commit is contained in:
Josh Matthews 2020-11-20 10:30:02 -05:00
parent 970ab0348f
commit 10231573be
18 changed files with 695 additions and 543 deletions

598
Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -40,8 +40,8 @@ sparkle = "0.1.25"
style = { path = "../style" } style = { path = "../style" }
style_traits = { path = "../style_traits" } style_traits = { path = "../style_traits" }
# NOTE: the sm-angle feature only enables angle on windows, not other platforms! # NOTE: the sm-angle feature only enables angle on windows, not other platforms!
surfman = { version = "0.3", features = ["sm-angle","sm-angle-default"] } surfman = { version = "0.4", features = ["sm-angle","sm-angle-default"] }
surfman-chains = "0.5" surfman-chains = "0.6"
surfman-chains-api = "0.2" surfman-chains-api = "0.2"
time = { version = "0.1.0", optional = true } time = { version = "0.1.0", optional = true }
webrender = { git = "https://github.com/servo/webrender" } webrender = { git = "https://github.com/servo/webrender" }

View file

@ -78,7 +78,7 @@ servo_url = { path = "../url" }
sparkle = "0.1" sparkle = "0.1"
style = { path = "../style", features = ["servo"] } style = { path = "../style", features = ["servo"] }
style_traits = { path = "../style_traits", features = ["servo"] } style_traits = { path = "../style_traits", features = ["servo"] }
surfman = "0.3" surfman = "0.4"
webdriver_server = { path = "../webdriver_server", optional = true } webdriver_server = { path = "../webdriver_server", optional = true }
webgpu = { path = "../webgpu" } webgpu = { path = "../webgpu" }
webrender = { git = "https://github.com/servo/webrender" } webrender = { git = "https://github.com/servo/webrender" }

View file

@ -12,6 +12,6 @@ path = "lib.rs"
[dependencies] [dependencies]
euclid = "0.20" euclid = "0.20"
surfman = "0.3" surfman = "0.4"
surfman-chains = "0.5" surfman-chains = "0.6"

View file

@ -29,8 +29,8 @@ libservo = { path = "../../components/servo" }
log = "0.4" log = "0.4"
servo-media = { git = "https://github.com/servo/media" } servo-media = { git = "https://github.com/servo/media" }
sparkle = "0.1" sparkle = "0.1"
surfman = "0.3" surfman = "0.4"
surfman-chains = "0.5" surfman-chains = "0.6"
surfman-chains-api = "0.2" surfman-chains-api = "0.2"
webxr = { git = "https://github.com/servo/webxr", features = ["glwindow"] } webxr = { git = "https://github.com/servo/webxr", features = ["glwindow"] }

View file

@ -249,7 +249,9 @@ impl ServoThread {
ServoWebSrcMsg::GetSwapChain(sender) => self.send_swap_chain(sender), ServoWebSrcMsg::GetSwapChain(sender) => self.send_swap_chain(sender),
ServoWebSrcMsg::SetSwapChain(swap_chain) => self.swap_chain = Some(swap_chain.0), ServoWebSrcMsg::SetSwapChain(swap_chain) => self.swap_chain = Some(swap_chain.0),
ServoWebSrcMsg::Resize(size) => self.resize(size), ServoWebSrcMsg::Resize(size) => self.resize(size),
ServoWebSrcMsg::Heartbeat => self.servo.handle_events(vec![]), ServoWebSrcMsg::Heartbeat => {
self.servo.handle_events(vec![]);
}
ServoWebSrcMsg::Stop => break, ServoWebSrcMsg::Stop => break,
} }
} }

View file

@ -12,7 +12,7 @@ ipc-channel = "0.14"
libservo = { path = "../../../components/servo" } libservo = { path = "../../../components/servo" }
log = "0.4" log = "0.4"
servo-media = { git = "https://github.com/servo/media" } 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 = { git = "https://github.com/servo/webxr"}
webxr-api = { git = "https://github.com/servo/webxr", features = ["ipc"] } webxr-api = { git = "https://github.com/servo/webxr", features = ["ipc"] }

View file

@ -18,7 +18,7 @@ env_logger = "0.8"
lazy_static = "1" lazy_static = "1"
log = "0.4" log = "0.4"
simpleservo = { path = "../api" } simpleservo = { path = "../api" }
surfman = "0.3" surfman = "0.4"
keyboard-types = "0.5" keyboard-types = "0.5"
[target.'cfg(target_os = "windows")'.dependencies] [target.'cfg(target_os = "windows")'.dependencies]

View file

@ -57,10 +57,10 @@ libservo = { path = "../../components/servo" }
log = "0.4" log = "0.4"
servo-media = { git = "https://github.com/servo/media" } servo-media = { git = "https://github.com/servo/media" }
shellwords = "1.0.0" 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" tinyfiledialogs = "3.0"
webxr = { git = "https://github.com/servo/webxr", features = ["ipc", "glwindow", "headless"] } 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] [target.'cfg(any(target_os = "linux", target_os = "windows"))'.dependencies]
image = "0.23" image = "0.23"

View file

@ -6,9 +6,11 @@
use crate::browser::Browser; use crate::browser::Browser;
use crate::embedder::EmbedderCallbacks; use crate::embedder::EmbedderCallbacks;
use crate::events_loop::EventsLoop; use crate::events_loop::{EventsLoop, ServoEvent};
use crate::window_trait::WindowPortsMethods; use crate::window_trait::WindowPortsMethods;
use crate::{headed_window, headless_window}; use crate::{headed_window, headless_window};
use winit::window::WindowId;
use winit::event_loop::EventLoopWindowTarget;
use servo::compositing::windowing::WindowEvent; use servo::compositing::windowing::WindowEvent;
use servo::config::opts::{self, parse_url_or_filename}; use servo::config::opts::{self, parse_url_or_filename};
use servo::servo_config::pref; use servo::servo_config::pref;
@ -20,15 +22,13 @@ use std::env;
use std::mem; use std::mem;
use std::rc::Rc; use std::rc::Rc;
use webxr::glwindow::GlWindowDiscovery; use webxr::glwindow::GlWindowDiscovery;
use winit::WindowId;
thread_local! { thread_local! {
pub static WINDOWS: RefCell<HashMap<WindowId, Rc<dyn WindowPortsMethods>>> = RefCell::new(HashMap::new()); pub static WINDOWS: RefCell<HashMap<WindowId, Rc<dyn WindowPortsMethods>>> = RefCell::new(HashMap::new());
} }
pub struct App { pub struct App {
events_loop: Rc<RefCell<EventsLoop>>, servo: Option<Servo<dyn WindowPortsMethods>>,
servo: RefCell<Servo<dyn WindowPortsMethods>>,
browser: RefCell<Browser<dyn WindowPortsMethods>>, browser: RefCell<Browser<dyn WindowPortsMethods>>,
event_queue: RefCell<Vec<WindowEvent>>, event_queue: RefCell<Vec<WindowEvent>>,
suspended: Cell<bool>, suspended: Cell<bool>,
@ -48,17 +48,41 @@ impl App {
} else { } else {
Rc::new(headed_window::Window::new( Rc::new(headed_window::Window::new(
opts::get().initial_window_size, opts::get().initial_window_size,
events_loop.clone(), &events_loop,
no_native_titlebar, no_native_titlebar,
device_pixels_per_px, device_pixels_per_px,
)) ))
}; };
// Handle browser state.
let browser = Browser::new(window.clone());
let mut app = App {
event_queue: RefCell::new(vec![]),
browser: RefCell::new(browser),
servo: None,
suspended: Cell::new(false),
};
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) { let xr_discovery = if pref!(dom.webxr.glwindow.enabled) {
let window = window.clone(); let window = window.clone();
let surfman = window.webrender_surfman(); // This should be safe because run_forever does, in fact,
let events_loop = events_loop.clone(); // run forever. The event loop window target doesn't get
let factory = Box::new(move || Ok(window.new_glwindow(&*events_loop.borrow()))); // 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( Some(GlWindowDiscovery::new(
surfman.connection(), surfman.connection(),
surfman.adapter(), surfman.adapter(),
@ -69,28 +93,51 @@ impl App {
None None
}; };
let window = window.clone();
// Implements embedder methods, used by libservo and constellation. // Implements embedder methods, used by libservo and constellation.
let embedder = Box::new(EmbedderCallbacks::new(events_loop.clone(), xr_discovery)); let embedder = Box::new(EmbedderCallbacks::new(
ev_waker.clone(),
xr_discovery,
));
// Handle browser state. let mut servo = Servo::new(embedder, window.clone(), user_agent.clone());
let browser = Browser::new(window.clone());
let mut servo = Servo::new(embedder, window.clone(), user_agent);
let browser_id = BrowserId::new(); let browser_id = BrowserId::new();
servo.handle_events(vec![WindowEvent::NewBrowser(get_default_url(), browser_id)]); servo.handle_events(vec![WindowEvent::NewBrowser(get_default_url(), browser_id)]);
servo.setup_logging(); servo.setup_logging();
register_window(window); register_window(window.clone());
app.servo = Some(servo);
}
let app = App { // If self.servo is None here, it means that we're in the process of shutting down,
event_queue: RefCell::new(vec![]), // let's ignore events.
events_loop, if app.servo.is_none() {
browser: RefCell::new(browser), return;
servo: RefCell::new(servo), }
suspended: Cell::new(false),
};
app.run_loop(); // 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> { fn get_events(&self) -> Vec<WindowEvent> {
@ -98,87 +145,50 @@ impl App {
} }
// This function decides whether the event should be handled during `run_forever`. // 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 { match event {
// App level events // App level events
winit::Event::Suspended(suspended) => { winit::event::Event::Suspended => {
self.suspended.set(suspended); self.suspended.set(true);
if !suspended {
self.event_queue.borrow_mut().push(WindowEvent::Idle);
}
}, },
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); self.event_queue.borrow_mut().push(WindowEvent::Idle);
}, },
winit::Event::DeviceEvent { .. } => {},
// Window level events // Window level events
winit::Event::WindowEvent { winit::event::Event::WindowEvent {
window_id, event, .. window_id, event, ..
} => { } => {
return WINDOWS.with(|windows| { return WINDOWS.with(|windows| {
match windows.borrow().get(&window_id) { match windows.borrow().get(&window_id) {
None => { None => {
warn!("Got an event from unknown window"); warn!("Got an event from unknown window");
winit::ControlFlow::Break
}, },
Some(window) => { 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); window.winit_event_to_servo_event(event);
return cont;
}, },
} }
}); });
}, },
}
winit::ControlFlow::Break
}
fn run_loop(self) { winit::event::Event::LoopDestroyed |
loop { winit::event::Event::NewEvents(..) |
let animating = WINDOWS.with(|windows| { winit::event::Event::MainEventsCleared |
windows winit::event::Event::RedrawEventsCleared => {},
.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(&mut self) -> bool {
}
fn handle_events(&self) -> bool {
let mut browser = self.browser.borrow_mut(); let mut browser = self.browser.borrow_mut();
let mut servo = self.servo.borrow_mut();
// FIXME: // FIXME:
// As of now, we support only one browser (self.browser) // As of now, we support only one browser (self.browser)
@ -203,21 +213,21 @@ impl App {
browser.handle_window_events(app_events); browser.handle_window_events(app_events);
let mut servo_events = servo.get_events(); let mut servo_events = self.servo.as_mut().unwrap().get_events();
loop { loop {
browser.handle_servo_events(servo_events); browser.handle_servo_events(servo_events);
servo.handle_events(browser.get_events()); self.servo.as_mut().unwrap().handle_events(browser.get_events());
if browser.shutdown_requested() { if browser.shutdown_requested() {
return true; return true;
} }
servo_events = servo.get_events(); servo_events = self.servo.as_mut().unwrap().get_events();
if servo_events.is_empty() { if servo_events.is_empty() {
break; break;
} }
} }
if need_resize { if need_resize {
servo.repaint_synchronously(); self.servo.as_mut().unwrap().repaint_synchronously();
} }
false false
} }

View file

@ -4,26 +4,23 @@
//! Implements the global methods required by Servo (not window/gl/compositor related). //! Implements the global methods required by Servo (not window/gl/compositor related).
use crate::events_loop::EventsLoop;
use servo::compositing::windowing::EmbedderMethods; use servo::compositing::windowing::EmbedderMethods;
use servo::embedder_traits::{EmbedderProxy, EventLoopWaker}; use servo::embedder_traits::{EmbedderProxy, EventLoopWaker};
use servo::servo_config::pref; use servo::servo_config::pref;
use std::cell::RefCell;
use std::rc::Rc;
use webxr::glwindow::GlWindowDiscovery; use webxr::glwindow::GlWindowDiscovery;
pub struct EmbedderCallbacks { pub struct EmbedderCallbacks {
events_loop: Rc<RefCell<EventsLoop>>, event_loop_waker: Box<dyn EventLoopWaker>,
xr_discovery: Option<GlWindowDiscovery>, xr_discovery: Option<GlWindowDiscovery>,
} }
impl EmbedderCallbacks { impl EmbedderCallbacks {
pub fn new( pub fn new(
events_loop: Rc<RefCell<EventsLoop>>, event_loop_waker: Box<dyn EventLoopWaker>,
xr_discovery: Option<GlWindowDiscovery>, xr_discovery: Option<GlWindowDiscovery>,
) -> EmbedderCallbacks { ) -> EmbedderCallbacks {
EmbedderCallbacks { EmbedderCallbacks {
events_loop, event_loop_waker,
xr_discovery, xr_discovery,
} }
} }
@ -31,7 +28,7 @@ impl EmbedderCallbacks {
impl EmbedderMethods for EmbedderCallbacks { impl EmbedderMethods for EmbedderCallbacks {
fn create_event_loop_waker(&mut self) -> Box<dyn EventLoopWaker> { 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( fn register_webxr(

View file

@ -5,16 +5,19 @@
//! An event loop implementation that works in headless mode. //! An event loop implementation that works in headless mode.
use servo::embedder_traits::EventLoopWaker; use servo::embedder_traits::EventLoopWaker;
use std::cell::RefCell;
use std::rc::Rc;
use std::sync::{Arc, Condvar, Mutex}; use std::sync::{Arc, Condvar, Mutex};
use std::time; use std::time;
use winit; use winit;
#[derive(Debug)]
pub enum ServoEvent {
Awakened,
}
#[allow(dead_code)] #[allow(dead_code)]
enum EventLoop { enum EventLoop {
/// A real Winit windowing event loop. /// 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 /// A fake event loop which contains a signalling flag used to ensure
/// that pending events get processed in a timely fashion, and a condition /// that pending events get processed in a timely fashion, and a condition
/// variable to allow waiting on that flag changing state. /// variable to allow waiting on that flag changing state.
@ -27,19 +30,16 @@ impl EventsLoop {
// Ideally, we could use the winit event loop in both modes, // Ideally, we could use the winit event loop in both modes,
// but on Linux, the event loop requires a X11 server. // but on Linux, the event loop requires a X11 server.
#[cfg(not(target_os = "linux"))] #[cfg(not(target_os = "linux"))]
pub fn new(_headless: bool) -> Rc<RefCell<EventsLoop>> { pub fn new(_headless: bool) -> EventsLoop {
Rc::new(RefCell::new(EventsLoop(EventLoop::Winit(Some( EventsLoop(EventLoop::Winit(Some(winit::event_loop::EventLoop::with_user_event())))
winit::EventsLoop::new(),
)))))
} }
#[cfg(target_os = "linux")] #[cfg(target_os = "linux")]
pub fn new(headless: bool) -> Rc<RefCell<EventsLoop>> { pub fn new(headless: bool) -> EventsLoop {
let events_loop = if headless { EventsLoop(if headless {
EventLoop::Headless(Arc::new((Mutex::new(false), Condvar::new()))) EventLoop::Headless(Arc::new((Mutex::new(false), Condvar::new())))
} else { } else {
EventLoop::Winit(Some(winit::EventsLoop::new())) EventLoop::Winit(Some(winit::event_loop::EventLoop::with_user_event()))
}; })
Rc::new(RefCell::new(EventsLoop(events_loop)))
} }
} }
@ -55,7 +55,7 @@ impl EventsLoop {
EventLoop::Headless(ref data) => Box::new(HeadlessEventLoopWaker(data.clone())), 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 { match self.0 {
EventLoop::Winit(Some(ref event_loop)) => event_loop, EventLoop::Winit(Some(ref event_loop)) => event_loop,
EventLoop::Winit(None) | EventLoop::Headless(..) => { EventLoop::Winit(None) | EventLoop::Headless(..) => {
@ -64,49 +64,41 @@ impl EventsLoop {
} }
} }
pub fn poll_events<F>(&mut self, callback: F) pub fn run_forever<F: 'static>(self, mut callback: F)
where where F: FnMut(
F: FnMut(winit::Event), winit::event::Event<ServoEvent>,
{ Option<&winit::event_loop::EventLoopWindowTarget<ServoEvent>>,
&mut winit::event_loop::ControlFlow
) {
match self.0 { match self.0 {
EventLoop::Winit(Some(ref mut events_loop)) => events_loop.poll_events(callback), EventLoop::Winit(events_loop) => {
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) => {
let events_loop = events_loop let events_loop = events_loop
.as_mut()
.expect("Can't run an unavailable event loop."); .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) => { EventLoop::Headless(ref data) => {
let &(ref flag, ref condvar) = &**data; let &(ref flag, ref condvar) = &**data;
while !*flag.lock().unwrap() { loop {
self.sleep(flag, condvar); self.sleep(flag, condvar);
if callback(winit::Event::Awakened) == winit::ControlFlow::Break { let mut control_flow = winit::event_loop::ControlFlow::Poll;
callback(
winit::event::Event::<ServoEvent>::UserEvent(ServoEvent::Awakened),
None,
&mut control_flow
);
if control_flow != winit::event_loop::ControlFlow::Poll {
*flag.lock().unwrap() = false;
} else if control_flow == winit::event_loop::ControlFlow::Exit {
break; break;
} }
} }
}, },
} }
} }
fn sleep(&self, lock: &Mutex<bool>, condvar: &Condvar) { fn sleep(&self, lock: &Mutex<bool>, condvar: &Condvar) {
// To avoid sleeping when we should be processing events, do two things: // To avoid sleeping when we should be processing events, do two things:
// * before sleeping, check whether our signalling flag has been set // * before sleeping, check whether our signalling flag has been set
@ -123,18 +115,18 @@ impl EventsLoop {
} }
struct HeadedEventLoopWaker { struct HeadedEventLoopWaker {
proxy: Arc<winit::EventsLoopProxy>, proxy: Arc<Mutex<winit::event_loop::EventLoopProxy<ServoEvent>>>,
} }
impl HeadedEventLoopWaker { impl HeadedEventLoopWaker {
fn new(events_loop: &winit::EventsLoop) -> HeadedEventLoopWaker { fn new(events_loop: &winit::event_loop::EventLoop<ServoEvent>) -> HeadedEventLoopWaker {
let proxy = Arc::new(events_loop.create_proxy()); let proxy = Arc::new(Mutex::new(events_loop.create_proxy()));
HeadedEventLoopWaker { proxy } HeadedEventLoopWaker { proxy }
} }
} }
impl EventLoopWaker for HeadedEventLoopWaker { impl EventLoopWaker for HeadedEventLoopWaker {
fn wake(&self) { fn wake(&self) {
// kick the OS event loop awake. // Kick the OS event loop awake.
if let Err(err) = self.proxy.wakeup() { if let Err(err) = self.proxy.lock().unwrap().send_event(ServoEvent::Awakened) {
warn!("Failed to wake up event loop ({}).", err); warn!("Failed to wake up event loop ({}).", err);
} }
} }

View file

@ -4,10 +4,18 @@
//! A winit window implementation. //! A winit window implementation.
use crate::events_loop::EventsLoop; use crate::events_loop::{EventsLoop, ServoEvent};
use crate::keyutils::keyboard_event_from_winit; use crate::keyutils::keyboard_event_from_winit;
use crate::window_trait::{WindowPortsMethods, LINE_HEIGHT}; 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"))] #[cfg(any(target_os = "linux", target_os = "windows"))]
use image; use image;
use keyboard_types::{Key, KeyState, KeyboardEvent}; use keyboard_types::{Key, KeyState, KeyboardEvent};
@ -39,17 +47,11 @@ use surfman::GLVersion;
use surfman::SurfaceType; use surfman::SurfaceType;
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
use winapi; use winapi;
use winit::dpi::{LogicalPosition, LogicalSize, PhysicalSize}; use winit::dpi::{LogicalPosition, PhysicalPosition, PhysicalSize};
#[cfg(target_os = "macos")] use winit::event::ModifiersState;
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,
};
#[cfg(target_os = "macos")] #[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() { if opts::get().output_file.is_some() {
// Prevent the window from showing in Dock.app, stealing focus, // Prevent the window from showing in Dock.app, stealing focus,
// when generating an output file. // 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"))] #[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 builder
} }
pub struct Window { pub struct Window {
winit_window: winit::Window, winit_window: winit::window::Window,
webrender_surfman: WebrenderSurfman, webrender_surfman: WebrenderSurfman,
screen_size: Size2D<u32, DeviceIndependentPixel>, screen_size: Size2D<u32, DeviceIndependentPixel>,
inner_size: Cell<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>>, mouse_down_point: Cell<Point2D<i32, DevicePixel>>,
primary_monitor: winit::MonitorId, primary_monitor: winit::monitor::MonitorHandle,
event_queue: RefCell<Vec<WindowEvent>>, event_queue: RefCell<Vec<WindowEvent>>,
mouse_pos: Cell<Point2D<i32, DevicePixel>>, mouse_pos: Cell<Point2D<i32, DevicePixel>>,
last_pressed: Cell<Option<(KeyboardEvent, Option<VirtualKeyCode>)>>, last_pressed: Cell<Option<(KeyboardEvent, Option<VirtualKeyCode>)>>,
@ -81,6 +83,7 @@ pub struct Window {
fullscreen: Cell<bool>, fullscreen: Cell<bool>,
device_pixels_per_px: Option<f32>, device_pixels_per_px: Option<f32>,
xr_window_poses: RefCell<Vec<Rc<XRWindowPose>>>, xr_window_poses: RefCell<Vec<Rc<XRWindowPose>>>,
modifiers_state: Cell<ModifiersState>,
} }
#[cfg(not(target_os = "windows"))] #[cfg(not(target_os = "windows"))]
@ -98,7 +101,7 @@ fn window_creation_scale_factor() -> Scale<f32, DeviceIndependentPixel, DevicePi
impl Window { impl Window {
pub fn new( pub fn new(
win_size: Size2D<u32, DeviceIndependentPixel>, win_size: Size2D<u32, DeviceIndependentPixel>,
events_loop: Rc<RefCell<EventsLoop>>, events_loop: &EventsLoop,
no_native_titlebar: bool, no_native_titlebar: bool,
device_pixels_per_px: Option<f32>, device_pixels_per_px: Option<f32>,
) -> Window { ) -> Window {
@ -114,19 +117,16 @@ impl Window {
let width = win_size.to_untyped().width; let width = win_size.to_untyped().width;
let height = win_size.to_untyped().height; 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_title("Servo".to_string())
.with_decorations(!no_native_titlebar) .with_decorations(!no_native_titlebar)
.with_transparency(no_native_titlebar) .with_transparent(no_native_titlebar)
.with_dimensions(LogicalSize::new(width as f64, height as f64)) .with_inner_size(PhysicalSize::new(width as f64, height as f64))
.with_visibility(visible) .with_visible(visible);
.with_multitouch();
window_builder = builder_with_platform_options(window_builder); window_builder = builder_with_platform_options(window_builder);
let winit_window = window_builder let winit_window = window_builder.build(events_loop.as_winit()).expect("Failed to create window.");
.build(events_loop.borrow().as_winit())
.expect("Failed to create window.");
#[cfg(any(target_os = "linux", target_os = "windows"))] #[cfg(any(target_os = "linux", target_os = "windows"))]
{ {
@ -134,21 +134,16 @@ impl Window {
winit_window.set_window_icon(Some(load_icon(icon_bytes))); 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 { let PhysicalSize {
width: screen_width, width: screen_width,
height: screen_height, height: screen_height,
} = primary_monitor.get_dimensions(); } = primary_monitor.clone().size();
let screen_size = Size2D::new(screen_width as u32, screen_height as u32); let screen_size = Size2D::new(screen_width as u32, screen_height as u32);
// TODO(ajeffrey): can this fail? let PhysicalSize { width, height } = winit_window.inner_size();
let LogicalSize { width, height } = winit_window
.get_inner_size()
.expect("Failed to get window inner size.");
let inner_size = Size2D::new(width as u32, height as u32); let inner_size = Size2D::new(width as u32, height as u32);
winit_window.show();
// Initialize surfman // Initialize surfman
let connection = let connection =
Connection::from_winit_window(&winit_window).expect("Failed to create connection"); Connection::from_winit_window(&winit_window).expect("Failed to create connection");
@ -179,6 +174,7 @@ impl Window {
screen_size, screen_size,
device_pixels_per_px, device_pixels_per_px,
xr_window_poses: RefCell::new(vec![]), 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) { 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); trace!("handling {:?}", event);
if event.state == KeyState::Down && event.key == Key::Unidentified { if event.state == KeyState::Down && event.key == Key::Unidentified {
// If pressed and probably printable, we expect a ReceivedCharacter event. // If pressed and probably printable, we expect a ReceivedCharacter event.
@ -247,7 +243,7 @@ impl Window {
self.last_pressed.set(None); self.last_pressed.set(None);
let xr_poses = self.xr_window_poses.borrow(); let xr_poses = self.xr_window_poses.borrow();
for xr_window_pose in &*xr_poses { 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 self.event_queue
.borrow_mut() .borrow_mut()
@ -258,17 +254,17 @@ impl Window {
/// Helper function to handle a click /// Helper function to handle a click
fn handle_mouse( fn handle_mouse(
&self, &self,
button: winit::MouseButton, button: winit::event::MouseButton,
action: winit::ElementState, action: winit::event::ElementState,
coords: Point2D<i32, DevicePixel>, coords: Point2D<i32, DevicePixel>,
) { ) {
use servo::script_traits::MouseButton; use servo::script_traits::MouseButton;
let max_pixel_dist = 10.0 * self.servo_hidpi_factor().get(); let max_pixel_dist = 10.0 * self.servo_hidpi_factor().get();
let mouse_button = match &button { let mouse_button = match &button {
winit::MouseButton::Left => MouseButton::Left, winit::event::MouseButton::Left => MouseButton::Left,
winit::MouseButton::Right => MouseButton::Right, winit::event::MouseButton::Right => MouseButton::Right,
winit::MouseButton::Middle => MouseButton::Middle, winit::event::MouseButton::Middle => MouseButton::Middle,
_ => MouseButton::Left, _ => MouseButton::Left,
}; };
let event = match action { let event = match action {
@ -305,7 +301,7 @@ impl Window {
} }
fn device_hidpi_factor(&self) -> Scale<f32, DeviceIndependentPixel, DevicePixel> { 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> { fn servo_hidpi_factor(&self) -> Scale<f32, DeviceIndependentPixel, DevicePixel> {
@ -332,8 +328,7 @@ impl WindowPortsMethods for Window {
let dpr = self.servo_hidpi_factor(); let dpr = self.servo_hidpi_factor();
let size = self let size = self
.winit_window .winit_window
.get_inner_size() .inner_size();
.expect("Failed to get window inner size.");
size.height as f32 * dpr.get() size.height as f32 * dpr.get()
} }
@ -342,24 +337,23 @@ impl WindowPortsMethods for Window {
} }
fn set_inner_size(&self, size: DeviceIntSize) { fn set_inner_size(&self, size: DeviceIntSize) {
let size = size.to_f32() / self.device_hidpi_factor();
self.winit_window 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) { fn set_position(&self, point: DeviceIntPoint) {
let point = point.to_f32() / self.device_hidpi_factor();
self.winit_window 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) { fn set_fullscreen(&self, state: bool) {
if self.fullscreen.get() != state { if self.fullscreen.get() != state {
self.winit_window.set_fullscreen(if state { self.winit_window
Some(self.primary_monitor.clone()) .set_fullscreen(
} else { if state {
None Some(winit::window::Fullscreen::Borderless(Some(self.primary_monitor.clone())))
}); } else { None }
);
} }
self.fullscreen.set(state); self.fullscreen.set(state);
} }
@ -369,68 +363,68 @@ impl WindowPortsMethods for Window {
} }
fn set_cursor(&self, cursor: Cursor) { fn set_cursor(&self, cursor: Cursor) {
use winit::MouseCursor; use winit::window::CursorIcon;
let winit_cursor = match cursor { let winit_cursor = match cursor {
Cursor::Default => MouseCursor::Default, Cursor::Default => CursorIcon::Default,
Cursor::Pointer => MouseCursor::Hand, Cursor::Pointer => CursorIcon::Hand,
Cursor::ContextMenu => MouseCursor::ContextMenu, Cursor::ContextMenu => CursorIcon::ContextMenu,
Cursor::Help => MouseCursor::Help, Cursor::Help => CursorIcon::Help,
Cursor::Progress => MouseCursor::Progress, Cursor::Progress => CursorIcon::Progress,
Cursor::Wait => MouseCursor::Wait, Cursor::Wait => CursorIcon::Wait,
Cursor::Cell => MouseCursor::Cell, Cursor::Cell => CursorIcon::Cell,
Cursor::Crosshair => MouseCursor::Crosshair, Cursor::Crosshair => CursorIcon::Crosshair,
Cursor::Text => MouseCursor::Text, Cursor::Text => CursorIcon::Text,
Cursor::VerticalText => MouseCursor::VerticalText, Cursor::VerticalText => CursorIcon::VerticalText,
Cursor::Alias => MouseCursor::Alias, Cursor::Alias => CursorIcon::Alias,
Cursor::Copy => MouseCursor::Copy, Cursor::Copy => CursorIcon::Copy,
Cursor::Move => MouseCursor::Move, Cursor::Move => CursorIcon::Move,
Cursor::NoDrop => MouseCursor::NoDrop, Cursor::NoDrop => CursorIcon::NoDrop,
Cursor::NotAllowed => MouseCursor::NotAllowed, Cursor::NotAllowed => CursorIcon::NotAllowed,
Cursor::Grab => MouseCursor::Grab, Cursor::Grab => CursorIcon::Grab,
Cursor::Grabbing => MouseCursor::Grabbing, Cursor::Grabbing => CursorIcon::Grabbing,
Cursor::EResize => MouseCursor::EResize, Cursor::EResize => CursorIcon::EResize,
Cursor::NResize => MouseCursor::NResize, Cursor::NResize => CursorIcon::NResize,
Cursor::NeResize => MouseCursor::NeResize, Cursor::NeResize => CursorIcon::NeResize,
Cursor::NwResize => MouseCursor::NwResize, Cursor::NwResize => CursorIcon::NwResize,
Cursor::SResize => MouseCursor::SResize, Cursor::SResize => CursorIcon::SResize,
Cursor::SeResize => MouseCursor::SeResize, Cursor::SeResize => CursorIcon::SeResize,
Cursor::SwResize => MouseCursor::SwResize, Cursor::SwResize => CursorIcon::SwResize,
Cursor::WResize => MouseCursor::WResize, Cursor::WResize => CursorIcon::WResize,
Cursor::EwResize => MouseCursor::EwResize, Cursor::EwResize => CursorIcon::EwResize,
Cursor::NsResize => MouseCursor::NsResize, Cursor::NsResize => CursorIcon::NsResize,
Cursor::NeswResize => MouseCursor::NeswResize, Cursor::NeswResize => CursorIcon::NeswResize,
Cursor::NwseResize => MouseCursor::NwseResize, Cursor::NwseResize => CursorIcon::NwseResize,
Cursor::ColResize => MouseCursor::ColResize, Cursor::ColResize => CursorIcon::ColResize,
Cursor::RowResize => MouseCursor::RowResize, Cursor::RowResize => CursorIcon::RowResize,
Cursor::AllScroll => MouseCursor::AllScroll, Cursor::AllScroll => CursorIcon::AllScroll,
Cursor::ZoomIn => MouseCursor::ZoomIn, Cursor::ZoomIn => CursorIcon::ZoomIn,
Cursor::ZoomOut => MouseCursor::ZoomOut, Cursor::ZoomOut => CursorIcon::ZoomOut,
_ => MouseCursor::Default, _ => CursorIcon::Default,
}; };
self.winit_window.set_cursor(winit_cursor); self.winit_window.set_cursor_icon(winit_cursor);
} }
fn is_animating(&self) -> bool { fn is_animating(&self) -> bool {
self.animation_state.get() == AnimationState::Animating self.animation_state.get() == AnimationState::Animating
} }
fn id(&self) -> winit::WindowId { fn id(&self) -> winit::window::WindowId {
self.winit_window.id() 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 { match event {
winit::WindowEvent::ReceivedCharacter(ch) => self.handle_received_character(ch), winit::event::WindowEvent::ReceivedCharacter(ch) => self.handle_received_character(ch),
winit::WindowEvent::KeyboardInput { input, .. } => self.handle_keyboard_input(input), winit::event::WindowEvent::KeyboardInput { input, .. } => self.handle_keyboard_input(input),
winit::WindowEvent::MouseInput { state, button, .. } => { winit::event::WindowEvent::ModifiersChanged(state) => self.modifiers_state.set(state),
winit::event::WindowEvent::MouseInput { state, button, .. } => {
if button == MouseButton::Left || button == MouseButton::Right { if button == MouseButton::Left || button == MouseButton::Right {
self.handle_mouse(button, state, self.mouse_pos.get()); self.handle_mouse(button, state, self.mouse_pos.get());
} }
}, },
winit::WindowEvent::CursorMoved { position, .. } => { winit::event::WindowEvent::CursorMoved { position, .. } => {
let pos = position.to_physical(self.device_hidpi_factor().get() as f64); let (x, y): (i32, i32) = position.into();
let (x, y): (i32, i32) = pos.into();
self.mouse_pos.set(Point2D::new(x, y)); self.mouse_pos.set(Point2D::new(x, y));
self.event_queue self.event_queue
.borrow_mut() .borrow_mut()
@ -438,15 +432,15 @@ impl WindowPortsMethods for Window {
x as f32, y as f32, 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 { let (mut dx, mut dy, mode) = match delta {
MouseScrollDelta::LineDelta(dx, dy) => { MouseScrollDelta::LineDelta(dx, dy) => {
(dx as f64, (dy * LINE_HEIGHT) as f64, WheelMode::DeltaLine) (dx as f64, (dy * LINE_HEIGHT) as f64, WheelMode::DeltaLine)
}, },
MouseScrollDelta::PixelDelta(position) => { MouseScrollDelta::PixelDelta(position) => {
let position = let position: LogicalPosition<f64> =
position.to_physical(self.device_hidpi_factor().get() as f64); position.to_logical(self.device_hidpi_factor().get() as f64);
(position.x as f64, position.y as f64, WheelMode::DeltaPixel) (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(wheel_event);
self.event_queue.borrow_mut().push(scroll_event); self.event_queue.borrow_mut().push(scroll_event);
}, },
winit::WindowEvent::Touch(touch) => { winit::event::WindowEvent::Touch(touch) => {
use servo::script_traits::TouchId; use servo::script_traits::TouchId;
let phase = winit_phase_to_touch_event_type(touch.phase); let phase = winit_phase_to_touch_event_type(touch.phase);
let id = TouchId(touch.id as i32); let id = TouchId(touch.id as i32);
let position = touch let position = touch.location;
.location
.to_physical(self.device_hidpi_factor().get() as f64);
let point = Point2D::new(position.x as f32, position.y as f32); let point = Point2D::new(position.x as f32, position.y as f32);
self.event_queue self.event_queue
.borrow_mut() .borrow_mut()
.push(WindowEvent::Touch(phase, id, point)); .push(WindowEvent::Touch(phase, id, point));
}, },
winit::WindowEvent::Refresh => { winit::event::WindowEvent::CloseRequested => {
self.event_queue.borrow_mut().push(WindowEvent::Refresh);
},
winit::WindowEvent::CloseRequested => {
self.event_queue.borrow_mut().push(WindowEvent::Quit); self.event_queue.borrow_mut().push(WindowEvent::Quit);
}, },
winit::WindowEvent::Resized(size) => { winit::event::WindowEvent::Resized(physical_size) => {
let (width, height) = size.into(); let (width, height) = physical_size.into();
let new_size = Size2D::new(width, height); let new_size = Size2D::new(width, height);
if self.inner_size.get() != new_size { 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); let physical_size = Size2D::new(physical_size.width, physical_size.height);
self.webrender_surfman self.webrender_surfman
.resize(physical_size.to_i32()) .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> { fn new_glwindow(
let size = self &self,
.winit_window event_loop: &winit::event_loop::EventLoopWindowTarget<ServoEvent>
.get_outer_size() ) -> Box<dyn webxr::glwindow::GlWindow> {
.expect("Failed to get window outer size"); 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_title("Servo XR".to_string())
.with_dimensions(size) .with_inner_size(size)
.with_visibility(true); .with_visible(true);
window_builder = builder_with_platform_options(window_builder); window_builder = builder_with_platform_options(window_builder);
let winit_window = window_builder let winit_window = window_builder.build(event_loop)
.build(events_loop.as_winit())
.expect("Failed to create window."); .expect("Failed to create window.");
let pose = Rc::new(XRWindowPose { let pose = Rc::new(XRWindowPose {
@ -542,24 +529,23 @@ impl WindowPortsMethods for Window {
impl WindowMethods for Window { impl WindowMethods for Window {
fn get_coordinates(&self) -> EmbedderCoordinates { fn get_coordinates(&self) -> EmbedderCoordinates {
// TODO(ajeffrey): can this fail? // Needed to convince the type system that winit's physical pixels
let dpr = self.device_hidpi_factor(); // are actually device pixels.
let LogicalSize { width, height } = self let dpr: Scale<f32, DeviceIndependentPixel, DevicePixel> = Scale::new(1.0);
let PhysicalSize { width, height } = self
.winit_window .winit_window
.get_outer_size() .outer_size();
.expect("Failed to get window outer size."); let PhysicalPosition { x, y } = self
let LogicalPosition { x, y } = self
.winit_window .winit_window
.get_position() .outer_position()
.unwrap_or(LogicalPosition::new(0., 0.)); .unwrap_or(PhysicalPosition::new(0, 0));
let win_size = (Size2D::new(width as f32, height as f32) * dpr).to_i32(); 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 win_origin = (Point2D::new(x as f32, y as f32) * dpr).to_i32();
let screen = (self.screen_size.to_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 .winit_window
.get_inner_size() .inner_size();
.expect("Failed to get window inner size.");
let inner_size = (Size2D::new(width as f32, height as f32) * dpr).to_i32(); let inner_size = (Size2D::new(width as f32, height as f32) * dpr).to_i32();
let viewport = DeviceIntRect::new(Point2D::zero(), inner_size); let viewport = DeviceIntRect::new(Point2D::zero(), inner_size);
let framebuffer = DeviceIntSize::from_untyped(viewport.size.to_untyped()); let framebuffer = DeviceIntSize::from_untyped(viewport.size.to_untyped());
@ -684,7 +670,7 @@ fn load_icon(icon_bytes: &[u8]) -> Icon {
} }
struct XRWindow { struct XRWindow {
winit_window: winit::Window, winit_window: winit::window::Window,
pose: Rc<XRWindowPose>, pose: Rc<XRWindowPose>,
} }
@ -757,8 +743,8 @@ impl XRWindowPose {
self.xr_translation.set(vec); self.xr_translation.set(vec);
} }
fn handle_xr_rotation(&self, input: &KeyboardInput) { fn handle_xr_rotation(&self, input: &KeyboardInput, modifiers: ModifiersState) {
if input.state != winit::ElementState::Pressed { if input.state != winit::event::ElementState::Pressed {
return; return;
} }
let mut x = 0.0; let mut x = 0.0;
@ -770,7 +756,7 @@ impl XRWindowPose {
Some(VirtualKeyCode::Right) => y = -1.0, Some(VirtualKeyCode::Right) => y = -1.0,
_ => return, _ => return,
}; };
if input.modifiers.shift { if modifiers.shift() {
x = 10.0 * x; x = 10.0 * x;
y = 10.0 * y; y = 10.0 * y;
} }

View file

@ -4,7 +4,7 @@
//! A headless window implementation. //! A headless window implementation.
use crate::events_loop::EventsLoop; use crate::events_loop::ServoEvent;
use crate::window_trait::WindowPortsMethods; use crate::window_trait::WindowPortsMethods;
use euclid::{Point2D, Rotation3D, Scale, Size2D, UnknownUnit, Vector3D}; use euclid::{Point2D, Rotation3D, Scale, Size2D, UnknownUnit, Vector3D};
use servo::compositing::windowing::{AnimationState, WindowEvent}; use servo::compositing::windowing::{AnimationState, WindowEvent};
@ -71,8 +71,8 @@ impl WindowPortsMethods for Window {
false false
} }
fn id(&self) -> winit::WindowId { fn id(&self) -> winit::window::WindowId {
unsafe { winit::WindowId::dummy() } unsafe { winit::window::WindowId::dummy() }
} }
fn page_height(&self) -> f32 { fn page_height(&self) -> f32 {
@ -98,11 +98,14 @@ impl WindowPortsMethods for Window {
self.animation_state.get() == AnimationState::Animating 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. // 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!() unimplemented!()
} }
} }

View file

@ -2,8 +2,8 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * 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/. */ * 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 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. // Some shortcuts use Cmd on Mac and Control on other systems.
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
@ -18,7 +18,7 @@ pub const CMD_OR_ALT: Modifiers = Modifiers::META;
pub const CMD_OR_ALT: Modifiers = Modifiers::ALT; pub const CMD_OR_ALT: Modifiers = Modifiers::ALT;
fn get_servo_key_from_winit_key(key: Option<VirtualKeyCode>) -> Key { 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: figure out how to map NavigateForward, NavigateBackward
// TODO: map the remaining keys if possible // TODO: map the remaining keys if possible
let key = if let Some(key) = key { 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 { fn get_servo_location_from_winit_key(key: Option<VirtualKeyCode>) -> Location {
use winit::VirtualKeyCode::*; use winit::event::VirtualKeyCode::*;
// TODO: add more numpad keys // TODO: add more numpad keys
let key = if let Some(key) = key { let key = if let Some(key) = key {
key key
@ -243,14 +243,14 @@ fn get_servo_code_from_scancode(_scancode: u32) -> Code {
fn get_modifiers(mods: ModifiersState) -> Modifiers { fn get_modifiers(mods: ModifiersState) -> Modifiers {
let mut modifiers = Modifiers::empty(); let mut modifiers = Modifiers::empty();
modifiers.set(Modifiers::CONTROL, mods.ctrl); modifiers.set(Modifiers::CONTROL, mods.ctrl());
modifiers.set(Modifiers::SHIFT, mods.shift); modifiers.set(Modifiers::SHIFT, mods.shift());
modifiers.set(Modifiers::ALT, mods.alt); modifiers.set(Modifiers::ALT, mods.alt());
modifiers.set(Modifiers::META, mods.logo); modifiers.set(Modifiers::META, mods.logo());
modifiers 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); info!("winit keyboard input: {:?}", input);
KeyboardEvent { KeyboardEvent {
state: match input.state { 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), key: get_servo_key_from_winit_key(input.virtual_keycode),
code: get_servo_code_from_scancode(input.scancode), code: get_servo_code_from_scancode(input.scancode),
location: get_servo_location_from_winit_key(input.virtual_keycode), location: get_servo_location_from_winit_key(input.virtual_keycode),
modifiers: get_modifiers(input.modifiers), modifiers: get_modifiers(state),
repeat: false, repeat: false,
is_composing: false, is_composing: false,
} }

View file

@ -5,7 +5,7 @@
//! Definition of Window. //! Definition of Window.
//! Implemented by headless and headed windows. //! Implemented by headless and headed windows.
use crate::events_loop::EventsLoop; use crate::events_loop::ServoEvent;
use servo::compositing::windowing::{WindowEvent, WindowMethods}; use servo::compositing::windowing::{WindowEvent, WindowMethods};
use servo::embedder_traits::Cursor; use servo::embedder_traits::Cursor;
use servo::webrender_api::units::{DeviceIntPoint, DeviceIntSize}; use servo::webrender_api::units::{DeviceIntPoint, DeviceIntSize};
@ -16,16 +16,19 @@ pub const LINE_HEIGHT: f32 = 38.0;
pub trait WindowPortsMethods: WindowMethods { pub trait WindowPortsMethods: WindowMethods {
fn get_events(&self) -> Vec<WindowEvent>; fn get_events(&self) -> Vec<WindowEvent>;
fn id(&self) -> winit::WindowId; fn id(&self) -> winit::window::WindowId;
fn has_events(&self) -> bool; fn has_events(&self) -> bool;
fn page_height(&self) -> f32; fn page_height(&self) -> f32;
fn get_fullscreen(&self) -> bool; 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 is_animating(&self) -> bool;
fn set_title(&self, _title: &str) {} fn set_title(&self, _title: &str) {}
fn set_inner_size(&self, _size: DeviceIntSize) {} fn set_inner_size(&self, _size: DeviceIntSize) {}
fn set_position(&self, _point: DeviceIntPoint) {} fn set_position(&self, _point: DeviceIntPoint) {}
fn set_fullscreen(&self, _state: bool) {} fn set_fullscreen(&self, _state: bool) {}
fn set_cursor(&self, _cursor: Cursor) {} 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>;
} }

View file

@ -67,17 +67,18 @@ packages = [
# Lots of crates to update. # Lots of crates to update.
"smallvec", "smallvec",
# https://github.com/servo/servo/issues/24421
"proc-macro2",
"quote",
"unicode-xid",
# https://github.com/servo/servo/pull/25518 # https://github.com/servo/servo/pull/25518
"core-foundation", "core-foundation",
"core-foundation-sys", "core-foundation-sys",
"core-graphics", "core-graphics",
"lyon_geom", "lyon_geom",
# https://github.com/servo/servo/pull/28236
"dlib",
"nix",
"nom",
"strsim",
# Duplicated by webrender debugger via ws # Duplicated by webrender debugger via ws
"digest", "digest",
"generic-array", "generic-array",

View file

@ -1,2 +0,0 @@
[flexible-order.html]
expected: FAIL