devela/sys/os/browser/web/
window.rs1#[allow(unused_imports, reason = "used by _js_method_str_alloc!")]
8#[cfg(feature = "alloc")]
9use devela::String;
10use devela::{_js_doc, Distance, Extent, Float, offset_of};
11#[allow(unused_imports, reason = "not(windows)")]
12use devela::{
13 _js_extern, _js_method_str_alloc, Js, JsTimeout, WebDocument, js_bool, js_int32, js_number,
14 js_uint32,
15};
16
17#[doc = crate::_tags!(ui web)]
18#[doc = crate::_doc_meta!{location("sys/os/browser/web")}]
20#[repr(C)]
24#[derive(Copy, Clone, Debug)]
25pub struct WebWindow;
26
27#[rustfmt::skip]
28#[cfg(not(feature = "safe_lang"))]
29#[cfg(all(feature = "unsafe_ffi", not(windows)))]
30#[cfg_attr(nightly_doc, doc(cfg(feature = "unsafe_ffi")))]
31#[cfg_attr(nightly_doc, doc(cfg(target_arch = "wasm32")))]
32impl WebWindow {
33 #[doc = _js_doc!("Window", "document")]
34 pub fn document(&self) -> WebDocument { WebDocument }
36
37 pub fn state() -> WebWindowState { WebWindowState::new() }
39
40 #[doc = _js_doc!("Window", "closed")]
41 pub fn is_closed() -> js_bool { window_is_closed() }
43
44 #[doc = _js_doc!("Window", "crossOriginIsolated")]
45 pub fn is_coi() -> js_bool { window_is_coi() }
47
48 #[doc = _js_doc!("Window", "isSecureContext")]
49 pub fn is_secure() -> js_bool { window_is_secure() }
53
54 #[doc = _js_doc!("Window", "locationbar")]
55 pub fn is_popup() -> js_bool { window_is_popup() }
57
58 _js_method_str_alloc! {
61 #[doc = _js_doc!("Window", "name")]
62 name, window_name
64 }
65
66 #[doc = _js_doc!("Window", "name")]
67 pub fn set_name(name: &str) { unsafe { window_set_name(name.as_ptr(), name.len() as u32); } }
69
70 #[doc = _js_doc!("Window", "setTimeout")]
73 pub fn set_timeout(callback: extern "C" fn(), delay_ms: js_uint32) -> JsTimeout {
75 JsTimeout { id: unsafe { window_set_timeout(callback as usize, delay_ms) } } }
76
77 #[doc = _js_doc!("Window", "setInterval")]
78 pub fn set_interval(callback: extern "C" fn(), interval_ms: js_uint32) -> JsTimeout {
80 JsTimeout { id: unsafe { window_set_interval(callback as usize, interval_ms) } } }
81
82 #[doc = _js_doc!("Window", "clearTimeout")]
83 #[doc = _js_doc!("Window", "clearInterval")]
84 pub fn clear_timeout(id: JsTimeout) { window_clear_timeout(id.id()); }
86
87 pub fn eval(js_code: &str) { unsafe { window_eval(js_code.as_ptr(), js_code.len()); } }
94
95 #[doc = _js_doc!("Window", "setTimeout")]
96 pub fn eval_timeout(js_code: &str, delay_ms: js_uint32) -> JsTimeout { JsTimeout {
98 id: unsafe { window_eval_timeout(js_code.as_ptr(), js_code.len(), delay_ms) } } }
99
100 #[doc = _js_doc!("Window", "setInterval")]
101 pub fn eval_interval(js_code: &str, interval_ms: js_uint32) -> JsTimeout { JsTimeout {
103 id: unsafe { window_eval_interval(js_code.as_ptr(), js_code.len(), interval_ms) } } }
104
105 #[doc = _js_doc!("Window", "requestAnimationFrame")]
109 pub fn request_animation_frame(callback: extern "C" fn()) -> js_uint32 {
111 unsafe { window_request_animation_frame(callback as usize) } }
112 pub fn cancel_animation_frame(id: js_uint32) { window_cancel_animation_frame(id); }
114}
115_js_extern! {
117 [module: "api_window"]
118 unsafe fn window_state(data: *mut u8);
119 safe fn window_is_closed() -> js_bool;
120 safe fn window_is_coi() -> js_bool;
121 safe fn window_is_secure() -> js_bool;
122 safe fn window_is_popup() -> js_bool;
123 unsafe fn window_name(buf_ptr: *mut u8, max_len: js_uint32) -> js_int32;
125 unsafe fn window_set_name(str_ptr: *const u8, str_len: js_uint32);
126 unsafe fn window_set_timeout(callback_ptr: usize, delay_ms: js_uint32) -> js_uint32;
128 unsafe fn window_set_interval(callback_ptr: usize, interval_ms: js_uint32) -> js_uint32;
129 safe fn window_clear_timeout(timeout_id: js_uint32);
130 unsafe fn window_eval(js_code_ptr: *const u8, js_code_len: usize);
132 unsafe fn window_eval_timeout(js_code_ptr: *const u8, js_code_len: usize, delay_ms: js_uint32)
133 -> js_uint32;
134 unsafe fn window_eval_interval(js_code_ptr: *const u8, js_code_len: usize,
135 interval_ms: js_uint32) -> js_uint32;
136 unsafe fn window_request_animation_frame(callback_ptr: usize) -> js_uint32;
138 safe fn window_cancel_animation_frame(requestId: js_uint32);
139}
140
141#[doc = crate::_tags!(ui web)]
142#[doc = crate::_doc_meta!{location("sys/os/browser/web")}]
144#[repr(C)]
150#[derive(Clone, Copy, Default, PartialEq)] pub struct WebWindowState {
152 #[doc = _js_doc!("Window", "innerWidth")]
154 #[doc = _js_doc!("Window", "innerHeight")]
155 pub inner_size: Extent<u32, 2>,
157
158 #[doc = _js_doc!("Window", "outerWidth")]
159 #[doc = _js_doc!("Window", "outerHeight")]
160 pub outer_size: Extent<u32, 2>,
162
163 #[doc = _js_doc!("Window", "screenLeft")]
165 #[doc = _js_doc!("Window", "screenTop")]
166 pub screen_offset: Distance<i32, 2>,
168
169 #[doc = _js_doc!("Screen", "width")]
170 #[doc = _js_doc!("Screen", "height")]
171 pub screen_size: Extent<u32, 2>,
173
174 #[doc = _js_doc!("Screen", "availWidth")]
175 #[doc = _js_doc!("Screen", "availHeight")]
176 pub screen_usable_size: Extent<u32, 2>,
178
179 #[doc = _js_doc!("Window", "devicePixelRatio")]
181 pub dpr: f32,
185
186 #[doc = _js_doc!("Screen", "colorDepth")]
187 pub bpp: u8,
189
190 _pad: [u8; 3],
194}
195impl WebWindowState {
196 const __ASSERT_FIELD_OFFSETS: () = const {
197 assert!(offset_of!(Self, inner_size) == 0);
198 assert!(offset_of!(Self, outer_size) == 8);
199 assert!(offset_of!(Self, screen_offset) == 16);
200 assert!(offset_of!(Self, screen_size) == 24);
201 assert!(offset_of!(Self, screen_usable_size) == 32);
202 assert!(offset_of!(Self, dpr) == 40);
203 assert!(offset_of!(Self, bpp) == 44);
204 };
205
206 #[cfg(not(feature = "safe_lang"))]
211 #[cfg(feature = "unsafe_ffi")]
212 #[cfg_attr(nightly_doc, doc(cfg(feature = "unsafe_ffi")))]
213 pub fn new() -> WebWindowState {
214 let mut state = WebWindowState::default();
215 unsafe {
216 window_state(&mut state as *mut WebWindowState as *mut u8);
217 }
218 state
219 }
220
221 #[cfg(not(feature = "safe_lang"))]
223 #[cfg(feature = "unsafe_ffi")]
224 #[cfg_attr(nightly_doc, doc(cfg(feature = "unsafe_ffi")))]
225 pub fn update(&mut self) {
226 unsafe { window_state(self as *mut Self as *mut u8) };
227 }
228
229 pub const fn is_valid(&self) -> bool {
239 let non_zero = self.inner_size.x() > 0
241 && self.inner_size.y() > 0
242 && self.outer_size.x() > 0
243 && self.outer_size.y() > 0;
244
245 let inner_le_outer = self.inner_size.dim[0] <= self.outer_size.dim[0]
247 && self.inner_size.dim[1] <= self.outer_size.dim[1];
248
249 let outer_le_screen = (self.outer_size.dim[0] <= self.screen_size.dim[0] + 10)
251 && (self.outer_size.dim[1] <= self.screen_size.dim[1] + 10);
252
253 let sane_dpr = self.dpr >= 0.2 && self.dpr <= 10.0;
255
256 let sane_bpp = self.bpp >= 8 && self.bpp <= 64;
258
259 non_zero && inner_le_outer && outer_le_screen && sane_dpr && sane_bpp }
268
269 pub const fn chrome_size(&self) -> Extent<u32, 2> {
275 Extent::new([
276 self.outer_size.x() - self.inner_size.x(),
277 self.outer_size.y() - self.inner_size.y(),
278 ])
279 }
280 pub const fn is_maximized(&self) -> bool {
284 self.outer_size.x() >= self.screen_usable_size.x()
285 && self.outer_size.y() >= self.screen_usable_size.y()
286 }
287 pub const fn is_portrait(&self) -> bool {
289 self.inner_size.y() > self.inner_size.x()
290 }
291
292 pub const fn physical_size(&self) -> Extent<u32, 2> {
298 Extent::new([
299 (self.inner_size.x() as f32 * self.dpr) as u32,
300 (self.inner_size.y() as f32 * self.dpr) as u32,
301 ])
302 }
303 pub const fn physical_size_rounded(&self) -> Extent<u32, 2> {
309 Extent::new([
310 Float(self.inner_size.x() as f32 * self.dpr).const_round().0 as u32,
311 Float(self.inner_size.y() as f32 * self.dpr).const_round().0 as u32,
312 ])
313 }
314
315 pub const fn screen_margins(&self) -> [i32; 4] {
319 [
320 self.screen_offset.dim[0],
321 self.screen_offset.dim[1],
322 (self.screen_size.x() as i32)
323 - (self.screen_offset.dim[0] + self.outer_size.x() as i32),
324 (self.screen_size.y() as i32)
325 - (self.screen_offset.dim[1] + self.outer_size.y() as i32),
326 ]
327 }
328}
329
330impl crate::Debug for WebWindowState {
331 fn fmt(&self, f: &mut crate::Formatter<'_>) -> crate::FmtResult<()> {
332 let mut state = f.debug_struct("WebWindowState");
333 state
335 .field("inner_size", &self.inner_size)
336 .field("outer_size", &self.outer_size)
337 .field("screen_offset", &self.screen_offset)
338 .field("screen_size", &self.screen_size)
339 .field("screen_usable_size", &self.screen_usable_size)
340 .field("dpr", &self.dpr)
341 .field("bpp", &self.bpp)
342 .field("chrome_size()", &self.chrome_size())
344 .field("is_maximized()", &self.is_maximized())
345 .field("is_portrait()", &self.is_portrait())
346 .field("is_valid()", &self.is_valid())
347 .field("physical_size()", &self.physical_size());
348 state.field("physical_size_rounded()", &self.physical_size_rounded());
349 state.field("screen_margins()", &self.screen_margins()).finish_non_exhaustive() }
351}