Store inner_size

In Winit, the Resize event has multiple purposes (actual resize,
screen change, workspace change, …). So we might get a Resize
event even if the window size hasn't changed yet. For example,
on MacOS, when going fullscreen.

Servo assume a resize and request a sync paint, which will freeze the
app. See:

0fa3248723/components/compositing/compositor.rs (L1485)
This commit is contained in:
Paul Rouget 2018-02-23 06:53:31 +01:00
parent 8149767f73
commit 74249b6322

View file

@ -175,7 +175,8 @@ enum WindowKind {
/// The type of a window. /// The type of a window.
pub struct Window { pub struct Window {
kind: WindowKind, kind: WindowKind,
screen: Size2D<u32>, screen_size: Size2D<u32>,
inner_size: Cell<TypedSize2D<u32, DeviceIndependentPixel>>,
mouse_down_button: Cell<Option<glutin::MouseButton>>, mouse_down_button: Cell<Option<glutin::MouseButton>>,
mouse_down_point: Cell<Point2D<i32>>, mouse_down_point: Cell<Point2D<i32>>,
@ -230,14 +231,14 @@ impl Window {
// #9996. // #9996.
let visible = is_foreground && !opts::get().no_native_titlebar; let visible = is_foreground && !opts::get().no_native_titlebar;
let screen; let screen_size;
let inner_size;
let window_kind = if opts::get().headless { let window_kind = if opts::get().headless {
screen = Size2D::new(width, height); screen_size = Size2D::new(width, height);
inner_size = TypedSize2D::new(width, height);
WindowKind::Headless(HeadlessContext::new(width, height)) WindowKind::Headless(HeadlessContext::new(width, height))
} else { } else {
let events_loop = glutin::EventsLoop::new(); let events_loop = glutin::EventsLoop::new();
let (screen_width, screen_height) = events_loop.get_primary_monitor().get_dimensions();
screen = Size2D::new(screen_width, screen_height);
let mut window_builder = glutin::WindowBuilder::new() let mut window_builder = glutin::WindowBuilder::new()
.with_title("Servo".to_string()) .with_title("Servo".to_string())
.with_decorations(!opts::get().no_native_titlebar) .with_decorations(!opts::get().no_native_titlebar)
@ -263,6 +264,11 @@ impl Window {
glutin_window.context().make_current().expect("Couldn't make window current"); glutin_window.context().make_current().expect("Couldn't make window current");
} }
let (screen_width, screen_height) = events_loop.get_primary_monitor().get_dimensions();
screen_size = Size2D::new(screen_width, screen_height);
// TODO(ajeffrey): can this fail?
let (width, height) = glutin_window.get_inner_size().expect("Failed to get window inner size.");
inner_size = TypedSize2D::new(width, height);
glutin_window.show(); glutin_window.show();
@ -319,7 +325,8 @@ impl Window {
gl: gl.clone(), gl: gl.clone(),
animation_state: Cell::new(AnimationState::Idle), animation_state: Cell::new(AnimationState::Idle),
fullscreen: Cell::new(false), fullscreen: Cell::new(false),
screen, inner_size: Cell::new(inner_size),
screen_size,
}; };
window.present(); window.present();
@ -460,13 +467,21 @@ impl Window {
self.event_queue.borrow_mut().push(WindowEvent::Quit); self.event_queue.borrow_mut().push(WindowEvent::Quit);
} }
Event::WindowEvent { Event::WindowEvent {
event: glutin::WindowEvent::Resized(x, y), event: glutin::WindowEvent::Resized(width, height),
.. ..
} => { } => {
// width and height are DevicePixel.
// window.resize() takes DevicePixel.
if let WindowKind::Window(ref window, _) = self.kind { if let WindowKind::Window(ref window, _) = self.kind {
window.resize(x, y); window.resize(width, height);
}
// window.set_inner_size() takes DeviceIndependentPixel.
let new_size = TypedSize2D::new(width as f32, height as f32);
let new_size = (new_size / self.hidpi_factor()).cast().expect("Window size should fit in u32");
if self.inner_size.get() != new_size {
self.inner_size.set(new_size);
self.event_queue.borrow_mut().push(WindowEvent::Resize);
} }
self.event_queue.borrow_mut().push(WindowEvent::Resize);
} }
Event::Awakened => { Event::Awakened => {
self.event_queue.borrow_mut().push(WindowEvent::Idle); self.event_queue.borrow_mut().push(WindowEvent::Idle);
@ -844,17 +859,7 @@ impl WindowMethods for Window {
} }
fn framebuffer_size(&self) -> DeviceUintSize { fn framebuffer_size(&self) -> DeviceUintSize {
match self.kind { (self.inner_size.get().to_f32() * self.hidpi_factor()).to_usize().cast().expect("Window size should fit in u32")
WindowKind::Window(ref window, ..) => {
let scale_factor = window.hidpi_factor() as u32;
// TODO(ajeffrey): can this fail?
let (width, height) = window.get_inner_size().expect("Failed to get window inner size.");
DeviceUintSize::new(width, height) * scale_factor
}
WindowKind::Headless(ref context) => {
DeviceUintSize::new(context.width, context.height)
}
}
} }
fn window_rect(&self) -> DeviceUintRect { fn window_rect(&self) -> DeviceUintRect {
@ -864,16 +869,7 @@ impl WindowMethods for Window {
} }
fn size(&self) -> TypedSize2D<f32, DeviceIndependentPixel> { fn size(&self) -> TypedSize2D<f32, DeviceIndependentPixel> {
match self.kind { self.inner_size.get().to_f32()
WindowKind::Window(ref window, ..) => {
// TODO(ajeffrey): can this fail?
let (width, height) = window.get_inner_size().expect("Failed to get window inner size.");
TypedSize2D::new(width as f32, height as f32)
}
WindowKind::Headless(ref context) => {
TypedSize2D::new(context.width as f32, context.height as f32)
}
}
} }
fn client_window(&self, _: BrowserId) -> (Size2D<u32>, Point2D<i32>) { fn client_window(&self, _: BrowserId) -> (Size2D<u32>, Point2D<i32>) {
@ -896,7 +892,7 @@ impl WindowMethods for Window {
} }
fn screen_size(&self, _: BrowserId) -> Size2D<u32> { fn screen_size(&self, _: BrowserId) -> Size2D<u32> {
self.screen self.screen_size
} }
fn screen_avail_size(&self, browser_id: BrowserId) -> Size2D<u32> { fn screen_avail_size(&self, browser_id: BrowserId) -> Size2D<u32> {