mirror of
https://github.com/servo/servo.git
synced 2025-06-06 16:45:39 +00:00
servoshell: Allow overriding screen resolution with a command-line argument (#34038)
There is a command-line argument to override the default window size, but not one for overriding the default screen resolution. This is important for testing pages that use screen size to have different behavior. In addition to adding the new option this change: - Renames the `--resolution` command-line argument to `--window-size` to remove ambiguity with the `--screen-size` argument. - Passes the screen size as device independent (device pixels scaled by HiDPI factor) to Servo internals. Not only it make it simpler to pass the `--window-size` override, it makes more sense. Different screens can have different HiDPI factors and these can be different from the scale of the window. This makes the screen HiDPI factor totally independent of the one that Servo uses for the window. Signed-off-by: Martin Robinson <mrobinson@igalia.com>
This commit is contained in:
parent
d877962ee8
commit
850e59f98e
14 changed files with 181 additions and 115 deletions
|
@ -38,12 +38,12 @@ use super::window_trait::{WindowPortsMethods, LINE_HEIGHT};
|
|||
pub struct Window {
|
||||
winit_window: winit::window::Window,
|
||||
rendering_context: RenderingContext,
|
||||
screen_size: Size2D<u32, DevicePixel>,
|
||||
inner_size: Cell<Size2D<u32, DevicePixel>>,
|
||||
screen_size: Size2D<u32, DeviceIndependentPixel>,
|
||||
inner_size: Cell<PhysicalSize<u32>>,
|
||||
toolbar_height: Cell<Length<f32, DeviceIndependentPixel>>,
|
||||
mouse_down_button: Cell<Option<winit::event::MouseButton>>,
|
||||
mouse_down_point: Cell<Point2D<i32, DevicePixel>>,
|
||||
primary_monitor: winit::monitor::MonitorHandle,
|
||||
monitor: winit::monitor::MonitorHandle,
|
||||
event_queue: RefCell<Vec<EmbedderEvent>>,
|
||||
mouse_pos: Cell<Point2D<i32, DevicePixel>>,
|
||||
last_pressed: Cell<Option<(KeyboardEvent, Option<LogicalKey>)>>,
|
||||
|
@ -59,7 +59,7 @@ pub struct Window {
|
|||
|
||||
impl Window {
|
||||
pub fn new(
|
||||
win_size: Size2D<u32, DeviceIndependentPixel>,
|
||||
window_size: Size2D<u32, DeviceIndependentPixel>,
|
||||
event_loop: &winit::event_loop::EventLoop<WakerEvent>,
|
||||
no_native_titlebar: bool,
|
||||
device_pixel_ratio_override: Option<f32>,
|
||||
|
@ -76,7 +76,7 @@ impl Window {
|
|||
.with_title("Servo".to_string())
|
||||
.with_decorations(!no_native_titlebar)
|
||||
.with_transparent(no_native_titlebar)
|
||||
.with_inner_size(LogicalSize::new(win_size.width, win_size.height))
|
||||
.with_inner_size(LogicalSize::new(window_size.width, window_size.height))
|
||||
.with_visible(visible);
|
||||
|
||||
#[allow(deprecated)]
|
||||
|
@ -90,13 +90,18 @@ impl Window {
|
|||
winit_window.set_window_icon(Some(load_icon(icon_bytes)));
|
||||
}
|
||||
|
||||
let primary_monitor = winit_window
|
||||
.available_monitors()
|
||||
.nth(0)
|
||||
let monitor = winit_window
|
||||
.current_monitor()
|
||||
.or_else(|| winit_window.available_monitors().nth(0))
|
||||
.expect("No monitor detected");
|
||||
|
||||
let screen_size = winit_size_to_euclid_size(primary_monitor.size());
|
||||
let inner_size = winit_size_to_euclid_size(winit_window.inner_size());
|
||||
let (screen_size, screen_scale) = opts.screen_size_override.map_or_else(
|
||||
|| (monitor.size(), monitor.scale_factor()),
|
||||
|size| (PhysicalSize::new(size.width, size.height), 1.0),
|
||||
);
|
||||
let screen_scale: Scale<f64, DevicePixel, DeviceIndependentPixel> =
|
||||
Scale::new(screen_scale);
|
||||
let screen_size = (winit_size_to_euclid_size(screen_size).to_f64() * screen_scale).to_u32();
|
||||
|
||||
// Initialize surfman
|
||||
let display_handle = winit_window
|
||||
|
@ -110,12 +115,15 @@ impl Window {
|
|||
let window_handle = winit_window
|
||||
.window_handle()
|
||||
.expect("could not get window handle from window");
|
||||
|
||||
let inner_size = winit_window.inner_size();
|
||||
let native_widget = connection
|
||||
.create_native_widget_from_window_handle(
|
||||
window_handle,
|
||||
inner_size.to_i32().to_untyped(),
|
||||
winit_size_to_euclid_size(inner_size).to_i32().to_untyped(),
|
||||
)
|
||||
.expect("Failed to create native widget");
|
||||
|
||||
let surface_type = SurfaceType::Widget { native_widget };
|
||||
let rendering_context = RenderingContext::create(&connection, &adapter, surface_type)
|
||||
.expect("Failed to create WR surfman");
|
||||
|
@ -133,7 +141,7 @@ impl Window {
|
|||
animation_state: Cell::new(AnimationState::Idle),
|
||||
fullscreen: Cell::new(false),
|
||||
inner_size: Cell::new(inner_size),
|
||||
primary_monitor,
|
||||
monitor,
|
||||
screen_size,
|
||||
device_pixel_ratio_override,
|
||||
xr_window_poses: RefCell::new(vec![]),
|
||||
|
@ -321,7 +329,7 @@ impl WindowPortsMethods for Window {
|
|||
if self.fullscreen.get() != state {
|
||||
self.winit_window.set_fullscreen(if state {
|
||||
Some(winit::window::Fullscreen::Borderless(Some(
|
||||
self.primary_monitor.clone(),
|
||||
self.monitor.clone(),
|
||||
)))
|
||||
} else {
|
||||
None
|
||||
|
@ -469,13 +477,10 @@ impl WindowPortsMethods for Window {
|
|||
winit::event::WindowEvent::CloseRequested => {
|
||||
self.event_queue.borrow_mut().push(EmbedderEvent::Quit);
|
||||
},
|
||||
winit::event::WindowEvent::Resized(physical_size) => {
|
||||
let (width, height) = physical_size.into();
|
||||
let new_size = Size2D::new(width, height);
|
||||
winit::event::WindowEvent::Resized(new_size) => {
|
||||
if self.inner_size.get() != new_size {
|
||||
let physical_size = Size2D::new(physical_size.width, physical_size.height);
|
||||
self.rendering_context
|
||||
.resize(physical_size.to_i32())
|
||||
.resize(Size2D::new(new_size.width, new_size.height).to_i32())
|
||||
.expect("Failed to resize");
|
||||
self.inner_size.set(new_size);
|
||||
self.event_queue
|
||||
|
@ -528,6 +533,11 @@ impl WindowMethods for Window {
|
|||
let window_size = winit_size_to_euclid_size(self.winit_window.outer_size()).to_i32();
|
||||
let window_origin = self.winit_window.outer_position().unwrap_or_default();
|
||||
let window_origin = winit_position_to_euclid_point(window_origin).to_i32();
|
||||
let window_rect = DeviceIntRect::from_origin_and_size(window_origin, window_size);
|
||||
let window_scale: Scale<f64, DevicePixel, DeviceIndependentPixel> =
|
||||
Scale::new(self.winit_window.scale_factor());
|
||||
let window_rect = (window_rect.to_f64() * window_scale).to_i32();
|
||||
|
||||
let viewport_origin = DeviceIntPoint::zero(); // bottom left
|
||||
let viewport_size = winit_size_to_euclid_size(self.winit_window.inner_size()).to_f32();
|
||||
let viewport = DeviceIntRect::from_origin_and_size(viewport_origin, viewport_size.to_i32());
|
||||
|
@ -536,7 +546,7 @@ impl WindowMethods for Window {
|
|||
EmbedderCoordinates {
|
||||
viewport,
|
||||
framebuffer: viewport.size(),
|
||||
window_rect: DeviceIntRect::from_origin_and_size(window_origin, window_size),
|
||||
window_rect,
|
||||
screen_size,
|
||||
// FIXME: Winit doesn't have API for available size. Fallback to screen size
|
||||
available_screen_size: screen_size,
|
||||
|
|
|
@ -9,14 +9,15 @@ use std::rc::Rc;
|
|||
use std::sync::RwLock;
|
||||
|
||||
use euclid::num::Zero;
|
||||
use euclid::{Length, Point2D, Rotation3D, Scale, Size2D, UnknownUnit, Vector3D};
|
||||
use euclid::{Box2D, Length, Point2D, Rotation3D, Scale, Size2D, UnknownUnit, Vector3D};
|
||||
use log::warn;
|
||||
use servo::compositing::windowing::{
|
||||
AnimationState, EmbedderCoordinates, EmbedderEvent, WindowMethods,
|
||||
};
|
||||
use servo::config::opts;
|
||||
use servo::servo_geometry::DeviceIndependentPixel;
|
||||
use servo::style_traits::DevicePixel;
|
||||
use servo::webrender_api::units::{DeviceIntRect, DeviceIntSize};
|
||||
use servo::webrender_api::units::DeviceIntSize;
|
||||
use servo::webrender_traits::RenderingContext;
|
||||
use surfman::{Connection, Context, Device, SurfaceType};
|
||||
|
||||
|
@ -26,8 +27,10 @@ pub struct Window {
|
|||
rendering_context: RenderingContext,
|
||||
animation_state: Cell<AnimationState>,
|
||||
fullscreen: Cell<bool>,
|
||||
device_pixel_ratio_override: Option<f32>,
|
||||
inner_size: Cell<Size2D<i32, UnknownUnit>>,
|
||||
device_pixel_ratio_override: Option<Scale<f32, DeviceIndependentPixel, DevicePixel>>,
|
||||
inner_size: Cell<DeviceIntSize>,
|
||||
screen_size: Size2D<i32, DeviceIndependentPixel>,
|
||||
window_rect: Box2D<i32, DeviceIndependentPixel>,
|
||||
event_queue: RwLock<Vec<EmbedderEvent>>,
|
||||
}
|
||||
|
||||
|
@ -42,17 +45,33 @@ impl Window {
|
|||
let adapter = connection
|
||||
.create_software_adapter()
|
||||
.expect("Failed to create adapter");
|
||||
let size = size.to_untyped().to_i32();
|
||||
let surface_type = SurfaceType::Generic { size };
|
||||
let surface_type = SurfaceType::Generic {
|
||||
size: size.to_untyped().to_i32(),
|
||||
};
|
||||
let rendering_context = RenderingContext::create(&connection, &adapter, surface_type)
|
||||
.expect("Failed to create WR surfman");
|
||||
|
||||
let device_pixel_ratio_override: Option<Scale<f32, DeviceIndependentPixel, DevicePixel>> =
|
||||
device_pixel_ratio_override.map(Scale::new);
|
||||
let hidpi_factor = device_pixel_ratio_override.unwrap_or_else(Scale::identity);
|
||||
|
||||
let size = size.to_i32();
|
||||
let inner_size = Cell::new((size.to_f32() * hidpi_factor).to_i32());
|
||||
let window_rect = Box2D::from_origin_and_size(Point2D::zero(), size);
|
||||
|
||||
let screen_size = opts::get().screen_size_override.map_or_else(
|
||||
|| window_rect.size(),
|
||||
|screen_size_override| screen_size_override.to_i32(),
|
||||
);
|
||||
|
||||
let window = Window {
|
||||
rendering_context,
|
||||
animation_state: Cell::new(AnimationState::Idle),
|
||||
fullscreen: Cell::new(false),
|
||||
device_pixel_ratio_override,
|
||||
inner_size: Cell::new(size.to_i32()),
|
||||
inner_size,
|
||||
screen_size,
|
||||
window_rect,
|
||||
event_queue: RwLock::new(Vec::new()),
|
||||
};
|
||||
|
||||
|
@ -73,17 +92,15 @@ impl WindowPortsMethods for Window {
|
|||
}
|
||||
|
||||
fn request_inner_size(&self, size: DeviceIntSize) -> Option<DeviceIntSize> {
|
||||
let (width, height) = size.into();
|
||||
|
||||
// Surfman doesn't support zero-sized surfaces.
|
||||
let new_size = DeviceIntSize::new(width.max(1), height.max(1));
|
||||
if self.inner_size.get() == new_size.to_untyped() {
|
||||
let new_size = DeviceIntSize::new(size.width.max(1), size.height.max(1));
|
||||
if self.inner_size.get() == new_size {
|
||||
return Some(new_size);
|
||||
}
|
||||
|
||||
match self.rendering_context.resize(new_size.to_untyped()) {
|
||||
Ok(()) => {
|
||||
self.inner_size.set(new_size.to_untyped());
|
||||
self.inner_size.set(new_size);
|
||||
if let Ok(ref mut queue) = self.event_queue.write() {
|
||||
queue.push(EmbedderEvent::WindowResize);
|
||||
}
|
||||
|
@ -103,7 +120,7 @@ impl WindowPortsMethods for Window {
|
|||
fn device_pixel_ratio_override(
|
||||
&self,
|
||||
) -> Option<Scale<f32, DeviceIndependentPixel, DevicePixel>> {
|
||||
self.device_pixel_ratio_override.map(Scale::new)
|
||||
self.device_pixel_ratio_override
|
||||
}
|
||||
|
||||
fn page_height(&self) -> f32 {
|
||||
|
@ -155,21 +172,14 @@ impl WindowPortsMethods for Window {
|
|||
|
||||
impl WindowMethods for Window {
|
||||
fn get_coordinates(&self) -> EmbedderCoordinates {
|
||||
let dpr = self.hidpi_factor();
|
||||
let size = self
|
||||
.rendering_context
|
||||
.context_surface_info()
|
||||
.unwrap_or(None)
|
||||
.map(|info| Size2D::from_untyped(info.size))
|
||||
.unwrap_or(Size2D::new(0, 0));
|
||||
let viewport = DeviceIntRect::from_origin_and_size(Point2D::zero(), size);
|
||||
let inner_size = self.inner_size.get();
|
||||
EmbedderCoordinates {
|
||||
viewport,
|
||||
framebuffer: size,
|
||||
window_rect: DeviceIntRect::from_origin_and_size(Point2D::zero(), size),
|
||||
screen_size: size,
|
||||
available_screen_size: size,
|
||||
hidpi_factor: dpr,
|
||||
viewport: Box2D::from_origin_and_size(Point2D::zero(), inner_size),
|
||||
framebuffer: inner_size,
|
||||
window_rect: self.window_rect,
|
||||
screen_size: self.screen_size,
|
||||
available_screen_size: self.screen_size,
|
||||
hidpi_factor: self.hidpi_factor(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@ use servo::embedder_traits::{
|
|||
ContextMenuResult, EmbedderMsg, EmbedderProxy, EventLoopWaker, MediaSessionEvent,
|
||||
PermissionPrompt, PermissionRequest, PromptDefinition, PromptOrigin, PromptResult,
|
||||
};
|
||||
use servo::euclid::{Point2D, Rect, Scale, Size2D, Vector2D};
|
||||
use servo::euclid::{Box2D, Point2D, Rect, Scale, Size2D, Vector2D};
|
||||
use servo::keyboard_types::{Key, KeyState, KeyboardEvent};
|
||||
use servo::script_traits::{
|
||||
MediaSessionActionType, MouseButton, TouchEventType, TouchId, TraversalDirection,
|
||||
|
@ -691,12 +691,13 @@ impl EmbedderMethods for ServoEmbedderCallbacks {
|
|||
impl WindowMethods for ServoWindowCallbacks {
|
||||
fn get_coordinates(&self) -> EmbedderCoordinates {
|
||||
let coords = self.coordinates.borrow();
|
||||
let screen_size = (coords.viewport.size.to_f32() * Scale::new(self.density)).to_i32();
|
||||
EmbedderCoordinates {
|
||||
viewport: coords.viewport.to_box2d(),
|
||||
framebuffer: coords.framebuffer,
|
||||
window_rect: DeviceIntRect::from_origin_and_size(Point2D::zero(), coords.viewport.size),
|
||||
screen_size: coords.viewport.size,
|
||||
available_screen_size: coords.viewport.size,
|
||||
window_rect: Box2D::from_origin_and_size(Point2D::zero(), screen_size),
|
||||
screen_size,
|
||||
available_screen_size: screen_size,
|
||||
hidpi_factor: Scale::new(self.density),
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue