servoshell/desktop/
headless_window.rs1#![deny(clippy::panic)]
8#![deny(clippy::unwrap_used)]
9
10use std::cell::Cell;
11use std::rc::Rc;
12
13use euclid::{Point2D, Scale, Size2D};
14use servo::{
15 DeviceIndependentIntRect, DeviceIndependentPixel, DeviceIntPoint, DeviceIntRect, DeviceIntSize,
16 DevicePixel, RenderingContext, ScreenGeometry, SoftwareRenderingContext, WebView,
17 convert_rect_to_css_pixel,
18};
19use winit::dpi::PhysicalSize;
20
21use crate::prefs::ServoShellPreferences;
22use crate::window::{MIN_WINDOW_INNER_SIZE, PlatformWindow, ServoShellWindow, ServoShellWindowId};
23
24pub struct Window {
25 fullscreen: Cell<bool>,
26 device_pixel_ratio_override: Option<Scale<f32, DeviceIndependentPixel, DevicePixel>>,
27 inner_size: Cell<DeviceIntSize>,
28 screen_size: Size2D<i32, DevicePixel>,
29 window_position: Cell<Point2D<i32, DevicePixel>>,
31 rendering_context: Rc<SoftwareRenderingContext>,
32}
33
34impl Window {
35 pub fn new(servoshell_preferences: &ServoShellPreferences) -> Rc<Self> {
36 let size = servoshell_preferences.initial_window_size;
37
38 let device_pixel_ratio_override = servoshell_preferences.device_pixel_ratio_override;
39 let device_pixel_ratio_override: Option<Scale<f32, DeviceIndependentPixel, DevicePixel>> =
40 device_pixel_ratio_override.map(Scale::new);
41 let hidpi_factor = device_pixel_ratio_override.unwrap_or_else(Scale::identity);
42
43 let inner_size = (size.to_f32() * hidpi_factor).to_i32();
44 let physical_size = PhysicalSize::new(inner_size.width as u32, inner_size.height as u32);
45 let rendering_context =
46 SoftwareRenderingContext::new(physical_size).expect("Failed to create WR surfman");
47
48 let screen_size = servoshell_preferences
49 .screen_size_override
50 .map_or(inner_size * 2, |screen_size_override| {
51 (screen_size_override.to_f32() * hidpi_factor).to_i32()
52 });
53
54 let window = Window {
55 fullscreen: Cell::new(false),
56 device_pixel_ratio_override,
57 inner_size: Cell::new(inner_size),
58 screen_size,
59 window_position: Cell::new(Point2D::zero()),
60 rendering_context: Rc::new(rendering_context),
61 };
62
63 Rc::new(window)
64 }
65}
66
67impl PlatformWindow for Window {
68 fn id(&self) -> ServoShellWindowId {
69 0.into()
70 }
71
72 fn screen_geometry(&self) -> servo::ScreenGeometry {
73 ScreenGeometry {
74 size: self.screen_size,
75 available_size: self.screen_size,
76 window_rect: DeviceIntRect::from_origin_and_size(
77 self.window_position.get(),
78 self.inner_size.get(),
79 ),
80 }
81 }
82
83 fn set_position(&self, point: DeviceIntPoint) {
84 self.window_position.set(point);
85 }
86
87 fn request_repaint(&self, window: &ServoShellWindow) {
88 window.repaint_webviews();
89 }
90
91 fn request_resize(&self, webview: &WebView, new_size: DeviceIntSize) -> Option<DeviceIntSize> {
92 let new_size = new_size.clamp(MIN_WINDOW_INNER_SIZE, self.screen_size * 2);
95 if self.inner_size.get() == new_size {
96 return Some(new_size);
97 }
98
99 self.inner_size.set(new_size);
100
101 webview.resize(PhysicalSize::new(
105 new_size.width as u32,
106 new_size.height as u32,
107 ));
108
109 Some(new_size)
110 }
111
112 fn device_hidpi_scale_factor(&self) -> Scale<f32, DeviceIndependentPixel, DevicePixel> {
113 Scale::new(1.0)
114 }
115
116 fn hidpi_scale_factor(&self) -> Scale<f32, DeviceIndependentPixel, DevicePixel> {
117 self.device_pixel_ratio_override
118 .unwrap_or_else(|| self.device_hidpi_scale_factor())
119 }
120
121 fn set_fullscreen(&self, state: bool) {
122 self.fullscreen.set(state);
123 }
124
125 fn get_fullscreen(&self) -> bool {
126 self.fullscreen.get()
127 }
128
129 #[cfg(feature = "webxr")]
130 fn new_glwindow(
131 &self,
132 _event_loop: &winit::event_loop::ActiveEventLoop,
133 ) -> Rc<dyn servo::webxr::GlWindow> {
134 unimplemented!()
135 }
136
137 fn window_rect(&self) -> DeviceIndependentIntRect {
138 convert_rect_to_css_pixel(
139 DeviceIntRect::from_origin_and_size(self.window_position.get(), self.inner_size.get()),
140 self.hidpi_scale_factor(),
141 )
142 }
143
144 fn rendering_context(&self) -> Rc<dyn RenderingContext> {
145 self.rendering_context.clone()
146 }
147
148 fn maximize(&self, webview: &WebView) {
149 self.window_position.set(Point2D::zero());
150 self.inner_size.set(self.screen_size);
151 webview.resize(PhysicalSize::new(
155 self.screen_size.width as u32,
156 self.screen_size.height as u32,
157 ));
158 }
159
160 fn focused(&self) -> bool {
161 true
162 }
163}