1#[cfg(feature = "alloc")]
8use devela::String;
9use devela::{_js_doc, Distance, Extent, Float, offset_of};
10#[allow(unused_imports, reason = "not(windows)")]
11use devela::{
12 _js_extern, _js_method_str_alloc, Js, JsTimeout, WebDocument, js_bool, js_int32, js_number,
13 js_uint32,
14};
15
16#[repr(C)]
21#[derive(Copy, Clone, Debug)]
22pub struct WebWindow;
23
24#[rustfmt::skip]
25#[cfg(not(feature = "safe_lang"))]
26#[cfg(all(feature = "unsafe_ffi", not(windows)))]
27#[cfg_attr(nightly_doc, doc(cfg(feature = "unsafe_ffi")))]
28#[cfg_attr(nightly_doc, doc(cfg(target_arch = "wasm32")))]
29impl WebWindow {
30 #[doc = _js_doc!("Window", "document")]
31 pub fn document(&self) -> WebDocument { WebDocument }
33
34 pub fn state() -> WebWindowState { WebWindowState::new() }
36
37 #[doc = _js_doc!("Window", "closed")]
38 pub fn is_closed() -> js_bool { window_is_closed() }
40
41 #[doc = _js_doc!("Window", "crossOriginIsolated")]
42 pub fn is_coi() -> js_bool { window_is_coi() }
44
45 #[doc = _js_doc!("Window", "isSecureContext")]
46 pub fn is_secure() -> js_bool { window_is_secure() }
50
51 #[doc = _js_doc!("Window", "locationbar")]
52 pub fn is_popup() -> js_bool { window_is_popup() }
54
55 _js_method_str_alloc! {
58 #[doc = _js_doc!("Window", "name")]
59 name, window_name
61 }
62
63 #[doc = _js_doc!("Window", "name")]
64 pub fn set_name(name: &str) { unsafe { window_set_name(name.as_ptr(), name.len() as u32); } }
66
67 #[doc = _js_doc!("Window", "setTimeout")]
70 pub fn set_timeout(callback: extern "C" fn(), delay_ms: js_uint32) -> JsTimeout {
72 JsTimeout { id: unsafe { window_set_timeout(callback as usize, delay_ms) } } }
73
74 #[doc = _js_doc!("Window", "setInterval")]
75 pub fn set_interval(callback: extern "C" fn(), interval_ms: js_uint32) -> JsTimeout {
77 JsTimeout { id: unsafe { window_set_interval(callback as usize, interval_ms) } } }
78
79 #[doc = _js_doc!("Window", "clearTimeout")]
80 #[doc = _js_doc!("Window", "clearInterval")]
81 pub fn clear_timeout(id: JsTimeout) { window_clear_timeout(id.id); }
83
84 pub fn eval(js_code: &str) { unsafe { window_eval(js_code.as_ptr(), js_code.len()); } }
91
92 #[doc = _js_doc!("Window", "setTimeout")]
93 pub fn eval_timeout(js_code: &str, delay_ms: js_uint32) -> JsTimeout { JsTimeout {
95 id: unsafe { window_eval_timeout(js_code.as_ptr(), js_code.len(), delay_ms) } } }
96
97 #[doc = _js_doc!("Window", "setInterval")]
98 pub fn eval_interval(js_code: &str, interval_ms: js_uint32) -> JsTimeout { JsTimeout {
100 id: unsafe { window_eval_interval(js_code.as_ptr(), js_code.len(), interval_ms) } } }
101
102 #[doc = _js_doc!("Window", "requestAnimationFrame")]
105 pub fn request_animation_frame(callback: extern "C" fn()) -> js_uint32 {
107 unsafe { window_request_animation_frame(callback as usize) } }
108 pub fn cancel_animation_frame(id: js_uint32) { window_cancel_animation_frame(id); }
110}
111_js_extern! {
112 [module: "api_window"]
113 unsafe fn window_state(data: *mut u8);
114 safe fn window_is_closed() -> js_bool;
115 safe fn window_is_coi() -> js_bool;
116 safe fn window_is_secure() -> js_bool;
117 safe fn window_is_popup() -> js_bool;
118 unsafe fn window_name(buf_ptr: *mut u8, max_len: js_uint32) -> js_int32;
120 unsafe fn window_set_name(str_ptr: *const u8, str_len: js_uint32);
121 unsafe fn window_set_timeout(callback_ptr: usize, delay_ms: js_uint32) -> js_uint32;
123 unsafe fn window_set_interval(callback_ptr: usize, interval_ms: js_uint32) -> js_uint32;
124 safe fn window_clear_timeout(timeout_id: js_uint32);
125 unsafe fn window_eval(js_code_ptr: *const u8, js_code_len: usize);
127 unsafe fn window_eval_timeout(js_code_ptr: *const u8, js_code_len: usize, delay_ms: js_uint32)
128 -> js_uint32;
129 unsafe fn window_eval_interval(js_code_ptr: *const u8, js_code_len: usize,
130 interval_ms: js_uint32) -> js_uint32;
131 unsafe fn window_request_animation_frame(callback_ptr: usize) -> js_uint32;
133 safe fn window_cancel_animation_frame(requestId: js_uint32);
134}
135
136#[repr(C)]
143#[derive(Clone, Copy, Default, PartialEq)] pub struct WebWindowState {
145 #[doc = _js_doc!("Window", "innerWidth")]
147 #[doc = _js_doc!("Window", "innerHeight")]
148 pub inner_size: Extent<u32, 2>,
150
151 #[doc = _js_doc!("Window", "outerWidth")]
152 #[doc = _js_doc!("Window", "outerHeight")]
153 pub outer_size: Extent<u32, 2>,
155
156 #[doc = _js_doc!("Window", "screenLeft")]
158 #[doc = _js_doc!("Window", "screenTop")]
159 pub screen_offset: Distance<i32, 2>,
161
162 #[doc = _js_doc!("Screen", "width")]
163 #[doc = _js_doc!("Screen", "height")]
164 pub screen_size: Extent<u32, 2>,
166
167 #[doc = _js_doc!("Screen", "availWidth")]
168 #[doc = _js_doc!("Screen", "availHeight")]
169 pub screen_usable_size: Extent<u32, 2>,
171
172 #[doc = _js_doc!("Window", "devicePixelRatio")]
174 pub dpr: f32,
178
179 #[doc = _js_doc!("Screen", "colorDepth")]
180 pub bpp: u8,
182
183 _pad: [u8; 3],
187}
188impl WebWindowState {
189 const __ASSERT_FIELD_OFFSETS: () = const {
190 assert!(offset_of!(Self, inner_size) == 0);
191 assert!(offset_of!(Self, outer_size) == 8);
192 assert!(offset_of!(Self, screen_offset) == 16);
193 assert!(offset_of!(Self, screen_size) == 24);
194 assert!(offset_of!(Self, screen_usable_size) == 32);
195 assert!(offset_of!(Self, dpr) == 40);
196 assert!(offset_of!(Self, bpp) == 44);
197 };
198
199 #[cfg(not(feature = "safe_lang"))]
204 #[cfg(feature = "unsafe_ffi")]
205 #[cfg_attr(nightly_doc, doc(cfg(feature = "unsafe_ffi")))]
206 pub fn new() -> WebWindowState {
207 let mut state = WebWindowState::default();
208 unsafe {
209 window_state(&mut state as *mut WebWindowState as *mut u8);
210 }
211 state
212 }
213
214 #[cfg(not(feature = "safe_lang"))]
216 #[cfg(feature = "unsafe_ffi")]
217 #[cfg_attr(nightly_doc, doc(cfg(feature = "unsafe_ffi")))]
218 pub fn update(&mut self) {
219 unsafe { window_state(self as *mut Self as *mut u8) };
220 }
221
222 pub const fn is_valid(&self) -> bool {
232 let non_zero = self.inner_size.x() > 0
234 && self.inner_size.y() > 0
235 && self.outer_size.x() > 0
236 && self.outer_size.y() > 0;
237
238 let inner_le_outer = self.inner_size.dim[0] <= self.outer_size.dim[0]
240 && self.inner_size.dim[1] <= self.outer_size.dim[1];
241
242 let outer_le_screen = (self.outer_size.dim[0] <= self.screen_size.dim[0] + 10)
244 && (self.outer_size.dim[1] <= self.screen_size.dim[1] + 10);
245
246 let sane_dpr = self.dpr >= 0.2 && self.dpr <= 10.0;
248
249 let sane_bpp = self.bpp >= 8 && self.bpp <= 64;
251
252 non_zero && inner_le_outer && outer_le_screen && sane_dpr && sane_bpp }
261
262 pub const fn chrome_size(&self) -> Extent<u32, 2> {
268 Extent::new([
269 self.outer_size.x() - self.inner_size.x(),
270 self.outer_size.y() - self.inner_size.y(),
271 ])
272 }
273 pub const fn is_maximized(&self) -> bool {
277 self.outer_size.x() >= self.screen_usable_size.x()
278 && self.outer_size.y() >= self.screen_usable_size.y()
279 }
280 pub const fn is_portrait(&self) -> bool {
282 self.inner_size.y() > self.inner_size.x()
283 }
284
285 pub const fn physical_size(&self) -> Extent<u32, 2> {
291 Extent::new([
292 (self.inner_size.x() as f32 * self.dpr) as u32,
293 (self.inner_size.y() as f32 * self.dpr) as u32,
294 ])
295 }
296 pub const fn physical_size_rounded(&self) -> Extent<u32, 2> {
302 Extent::new([
303 Float(self.inner_size.x() as f32 * self.dpr).const_round().0 as u32,
304 Float(self.inner_size.y() as f32 * self.dpr).const_round().0 as u32,
305 ])
306 }
307
308 pub const fn screen_margins(&self) -> [i32; 4] {
312 [
313 self.screen_offset.dim[0],
314 self.screen_offset.dim[1],
315 (self.screen_size.x() as i32)
316 - (self.screen_offset.dim[0] + self.outer_size.x() as i32),
317 (self.screen_size.y() as i32)
318 - (self.screen_offset.dim[1] + self.outer_size.y() as i32),
319 ]
320 }
321}
322
323impl crate::Debug for WebWindowState {
324 fn fmt(&self, f: &mut crate::Formatter<'_>) -> crate::FmtResult<()> {
325 let mut state = f.debug_struct("WebWindowState");
326 state
328 .field("inner_size", &self.inner_size)
329 .field("outer_size", &self.outer_size)
330 .field("screen_offset", &self.screen_offset)
331 .field("screen_size", &self.screen_size)
332 .field("screen_usable_size", &self.screen_usable_size)
333 .field("dpr", &self.dpr)
334 .field("bpp", &self.bpp)
335 .field("chrome_size()", &self.chrome_size())
337 .field("is_maximized()", &self.is_maximized())
338 .field("is_portrait()", &self.is_portrait())
339 .field("is_valid()", &self.is_valid())
340 .field("physical_size()", &self.physical_size());
341 state.field("physical_size_rounded()", &self.physical_size_rounded());
342 state.field("screen_margins()", &self.screen_margins()).finish_non_exhaustive() }
344}