2024-07-23 16:47:35 +02:00
|
|
|
use std::cell::Ref;
|
2020-09-21 06:42:07 +08:00
|
|
|
use std::rc::Rc;
|
2023-12-26 01:22:10 +01:00
|
|
|
use std::sync::Arc;
|
2024-07-07 18:38:50 +02:00
|
|
|
|
2023-12-16 22:02:17 +02:00
|
|
|
use web_sys::HtmlCanvasElement;
|
2024-07-07 18:38:50 +02:00
|
|
|
|
2023-12-26 01:22:10 +01:00
|
|
|
use super::main_thread::{MainThreadMarker, MainThreadSafe};
|
2024-08-23 23:40:27 +03:00
|
|
|
use super::monitor::MonitorHandler;
|
2023-06-05 02:44:54 +02:00
|
|
|
use super::r#async::Dispatcher;
|
2024-08-23 23:40:27 +03:00
|
|
|
use super::{backend, lock, ActiveEventLoop};
|
2023-06-04 14:29:59 +02:00
|
|
|
use crate::dpi::{PhysicalPosition, PhysicalSize, Position, Size};
|
2024-09-06 17:20:11 +03:00
|
|
|
use crate::error::{NotSupportedError, RequestError};
|
2019-06-25 03:15:34 +02:00
|
|
|
use crate::icon::Icon;
|
2024-08-23 23:40:27 +03:00
|
|
|
use crate::monitor::MonitorHandle as RootMonitorHandle;
|
2020-11-27 03:03:08 +01:00
|
|
|
use crate::window::{
|
2024-08-23 23:40:27 +03:00
|
|
|
Cursor, CursorGrabMode, Fullscreen as RootFullscreen, ImePurpose, ResizeDirection, Theme,
|
|
|
|
|
UserAttentionType, Window as RootWindow, WindowAttributes, WindowButtons, WindowId as RootWI,
|
|
|
|
|
WindowLevel,
|
2020-11-27 03:03:08 +01:00
|
|
|
};
|
2019-09-24 19:39:13 -04:00
|
|
|
|
2019-06-25 03:15:34 +02:00
|
|
|
pub struct Window {
|
2023-08-14 21:19:57 +02:00
|
|
|
inner: Dispatcher<Inner>,
|
2023-06-05 02:44:54 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub struct Inner {
|
2023-08-14 21:19:57 +02:00
|
|
|
id: WindowId,
|
2023-06-05 02:44:54 +02:00
|
|
|
pub window: web_sys::Window,
|
2024-07-23 20:33:10 +02:00
|
|
|
monitor: Rc<MonitorHandler>,
|
2024-07-23 16:47:35 +02:00
|
|
|
canvas: Rc<backend::Canvas>,
|
2020-09-21 06:42:07 +08:00
|
|
|
destroy_fn: Option<Box<dyn FnOnce()>>,
|
2019-06-25 03:15:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Window {
|
2024-09-06 17:20:11 +03:00
|
|
|
pub(crate) fn new(
|
|
|
|
|
target: &ActiveEventLoop,
|
|
|
|
|
attr: WindowAttributes,
|
|
|
|
|
) -> Result<Self, RequestError> {
|
2019-09-19 18:40:18 -04:00
|
|
|
let id = target.generate_id();
|
|
|
|
|
|
2023-06-05 02:44:54 +02:00
|
|
|
let window = target.runner.window();
|
2024-07-23 20:33:10 +02:00
|
|
|
let navigator = target.runner.navigator();
|
2023-07-11 00:11:06 +02:00
|
|
|
let document = target.runner.document();
|
2023-12-26 01:22:10 +01:00
|
|
|
let canvas = backend::Canvas::create(
|
|
|
|
|
target.runner.main_thread(),
|
|
|
|
|
id,
|
|
|
|
|
window.clone(),
|
2024-07-23 20:33:10 +02:00
|
|
|
navigator.clone(),
|
2023-12-26 01:22:10 +01:00
|
|
|
document.clone(),
|
2024-07-23 16:47:35 +02:00
|
|
|
attr,
|
2023-12-26 01:22:10 +01:00
|
|
|
)?;
|
2024-07-23 16:47:35 +02:00
|
|
|
let canvas = Rc::new(canvas);
|
2019-09-23 09:14:26 -04:00
|
|
|
|
2023-12-25 09:37:35 +01:00
|
|
|
target.register(&canvas, id);
|
2019-06-25 03:15:34 +02:00
|
|
|
|
2020-09-21 06:42:07 +08:00
|
|
|
let runner = target.runner.clone();
|
|
|
|
|
let destroy_fn = Box::new(move || runner.notify_destroy_window(RootWI(id)));
|
|
|
|
|
|
2024-07-23 20:33:10 +02:00
|
|
|
let inner = Inner {
|
|
|
|
|
id,
|
|
|
|
|
window: window.clone(),
|
|
|
|
|
monitor: Rc::clone(target.runner.monitor()),
|
|
|
|
|
canvas,
|
|
|
|
|
destroy_fn: Some(destroy_fn),
|
|
|
|
|
};
|
2023-06-05 02:44:54 +02:00
|
|
|
|
2023-10-16 15:50:22 +02:00
|
|
|
let canvas = Rc::downgrade(&inner.canvas);
|
2024-07-23 16:47:35 +02:00
|
|
|
let (dispatcher, runner) = Dispatcher::new(target.runner.main_thread(), inner);
|
2023-10-16 15:50:22 +02:00
|
|
|
target.runner.add_canvas(RootWI(id), canvas, runner);
|
|
|
|
|
|
|
|
|
|
Ok(Window { inner: dispatcher })
|
2023-08-14 21:19:57 +02:00
|
|
|
}
|
2019-06-25 03:15:34 +02:00
|
|
|
|
2024-07-23 16:47:35 +02:00
|
|
|
pub fn canvas(&self) -> Option<Ref<'_, HtmlCanvasElement>> {
|
|
|
|
|
MainThreadMarker::new()
|
|
|
|
|
.map(|main_thread| Ref::map(self.inner.value(main_thread), |inner| inner.canvas.raw()))
|
2019-06-25 18:07:47 +02:00
|
|
|
}
|
2023-12-22 22:33:50 +01:00
|
|
|
|
2023-12-25 09:37:35 +01:00
|
|
|
pub(crate) fn prevent_default(&self) -> bool {
|
2024-07-23 16:47:35 +02:00
|
|
|
self.inner.queue(|inner| inner.canvas.prevent_default.get())
|
2023-12-25 09:37:35 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub(crate) fn set_prevent_default(&self, prevent_default: bool) {
|
2024-07-23 16:47:35 +02:00
|
|
|
self.inner.dispatch(move |inner| inner.canvas.prevent_default.set(prevent_default))
|
2023-12-25 09:37:35 +01:00
|
|
|
}
|
|
|
|
|
|
2024-07-23 17:05:55 +02:00
|
|
|
pub(crate) fn is_cursor_lock_raw(&self) -> bool {
|
|
|
|
|
self.inner.queue(move |inner| {
|
2024-07-23 20:33:10 +02:00
|
|
|
lock::is_cursor_lock_raw(inner.canvas.navigator(), inner.canvas.document())
|
2024-07-23 17:05:55 +02:00
|
|
|
})
|
|
|
|
|
}
|
2023-08-14 21:19:57 +02:00
|
|
|
}
|
2019-06-25 18:07:47 +02:00
|
|
|
|
2024-08-23 23:40:27 +03:00
|
|
|
impl RootWindow for Window {
|
|
|
|
|
fn id(&self) -> RootWI {
|
|
|
|
|
RootWI(self.inner.queue(|inner| inner.id))
|
2019-06-25 03:15:34 +02:00
|
|
|
}
|
|
|
|
|
|
2024-08-23 23:40:27 +03:00
|
|
|
fn scale_factor(&self) -> f64 {
|
|
|
|
|
self.inner.queue(Inner::scale_factor)
|
2019-06-25 03:15:34 +02:00
|
|
|
}
|
|
|
|
|
|
2024-08-23 23:40:27 +03:00
|
|
|
fn request_redraw(&self) {
|
|
|
|
|
self.inner.dispatch(|inner| inner.canvas.request_animation_frame())
|
2022-02-17 20:44:14 +02:00
|
|
|
}
|
|
|
|
|
|
2024-08-23 23:40:27 +03:00
|
|
|
fn pre_present_notify(&self) {}
|
2019-06-25 03:15:34 +02:00
|
|
|
|
2024-08-23 23:40:27 +03:00
|
|
|
fn reset_dead_keys(&self) {
|
|
|
|
|
// Not supported
|
2019-06-25 03:15:34 +02:00
|
|
|
}
|
|
|
|
|
|
2024-09-06 17:20:11 +03:00
|
|
|
fn inner_position(&self) -> Result<PhysicalPosition<i32>, RequestError> {
|
2019-12-31 14:39:33 -08:00
|
|
|
// Note: the canvas element has no window decorations, so this is equal to `outer_position`.
|
|
|
|
|
self.outer_position()
|
2019-06-25 03:15:34 +02:00
|
|
|
}
|
|
|
|
|
|
2024-09-06 17:20:11 +03:00
|
|
|
fn outer_position(&self) -> Result<PhysicalPosition<i32>, RequestError> {
|
|
|
|
|
Ok(self.inner.queue(|inner| inner.canvas.position().to_physical(inner.scale_factor())))
|
2019-06-25 03:15:34 +02:00
|
|
|
}
|
|
|
|
|
|
2024-08-23 23:40:27 +03:00
|
|
|
fn set_outer_position(&self, position: Position) {
|
|
|
|
|
self.inner.dispatch(move |inner| {
|
|
|
|
|
let position = position.to_logical::<f64>(inner.scale_factor());
|
|
|
|
|
backend::set_canvas_position(
|
|
|
|
|
inner.canvas.document(),
|
|
|
|
|
inner.canvas.raw(),
|
|
|
|
|
inner.canvas.style(),
|
|
|
|
|
position,
|
|
|
|
|
)
|
|
|
|
|
})
|
2019-06-25 03:15:34 +02:00
|
|
|
}
|
|
|
|
|
|
2024-09-04 15:04:48 +02:00
|
|
|
fn surface_size(&self) -> PhysicalSize<u32> {
|
|
|
|
|
self.inner.queue(|inner| inner.canvas.surface_size())
|
2019-06-25 03:15:34 +02:00
|
|
|
}
|
|
|
|
|
|
2024-09-04 15:04:48 +02:00
|
|
|
fn request_surface_size(&self, size: Size) -> Option<PhysicalSize<u32>> {
|
2024-08-23 23:40:27 +03:00
|
|
|
self.inner.queue(|inner| {
|
|
|
|
|
let size = size.to_logical(self.scale_factor());
|
|
|
|
|
backend::set_canvas_size(
|
|
|
|
|
inner.canvas.document(),
|
|
|
|
|
inner.canvas.raw(),
|
|
|
|
|
inner.canvas.style(),
|
|
|
|
|
size,
|
|
|
|
|
);
|
|
|
|
|
None
|
|
|
|
|
})
|
2019-06-25 03:15:34 +02:00
|
|
|
}
|
|
|
|
|
|
2024-08-23 23:40:27 +03:00
|
|
|
fn outer_size(&self) -> PhysicalSize<u32> {
|
2024-09-04 15:04:48 +02:00
|
|
|
// Note: the canvas element has no window decorations, so this is equal to `surface_size`.
|
|
|
|
|
self.surface_size()
|
2019-06-25 03:15:34 +02:00
|
|
|
}
|
|
|
|
|
|
2024-09-04 15:04:48 +02:00
|
|
|
fn set_min_surface_size(&self, min_size: Option<Size>) {
|
2024-08-23 23:40:27 +03:00
|
|
|
self.inner.dispatch(move |inner| {
|
|
|
|
|
let dimensions = min_size.map(|min_size| min_size.to_logical(inner.scale_factor()));
|
|
|
|
|
backend::set_canvas_min_size(
|
|
|
|
|
inner.canvas.document(),
|
|
|
|
|
inner.canvas.raw(),
|
|
|
|
|
inner.canvas.style(),
|
|
|
|
|
dimensions,
|
|
|
|
|
)
|
|
|
|
|
})
|
2019-06-25 03:15:34 +02:00
|
|
|
}
|
|
|
|
|
|
2024-09-04 15:04:48 +02:00
|
|
|
fn set_max_surface_size(&self, max_size: Option<Size>) {
|
2024-08-23 23:40:27 +03:00
|
|
|
self.inner.dispatch(move |inner| {
|
|
|
|
|
let dimensions = max_size.map(|dimensions| dimensions.to_logical(inner.scale_factor()));
|
|
|
|
|
backend::set_canvas_max_size(
|
|
|
|
|
inner.canvas.document(),
|
|
|
|
|
inner.canvas.raw(),
|
|
|
|
|
inner.canvas.style(),
|
|
|
|
|
dimensions,
|
|
|
|
|
)
|
|
|
|
|
})
|
2022-09-03 21:50:22 +03:00
|
|
|
}
|
|
|
|
|
|
2024-09-04 15:04:48 +02:00
|
|
|
fn surface_resize_increments(&self) -> Option<PhysicalSize<u32>> {
|
2024-08-23 23:40:27 +03:00
|
|
|
None
|
2022-09-03 21:50:22 +03:00
|
|
|
}
|
|
|
|
|
|
2024-09-04 15:04:48 +02:00
|
|
|
fn set_surface_resize_increments(&self, _: Option<Size>) {
|
2019-06-25 03:15:34 +02:00
|
|
|
// Intentionally a no-op: users can't resize canvas elements
|
|
|
|
|
}
|
|
|
|
|
|
2024-08-23 23:40:27 +03:00
|
|
|
fn set_title(&self, title: &str) {
|
|
|
|
|
self.inner.queue(|inner| inner.canvas.set_attribute("alt", title))
|
2022-02-17 17:03:17 +02:00
|
|
|
}
|
|
|
|
|
|
2024-08-23 23:40:27 +03:00
|
|
|
fn set_transparent(&self, _: bool) {}
|
2022-11-29 12:03:51 +02:00
|
|
|
|
2024-08-23 23:40:27 +03:00
|
|
|
fn set_blur(&self, _: bool) {}
|
2019-06-25 03:15:34 +02:00
|
|
|
|
2024-08-23 23:40:27 +03:00
|
|
|
fn set_visible(&self, _: bool) {
|
|
|
|
|
// Intentionally a no-op
|
2019-06-25 03:15:34 +02:00
|
|
|
}
|
|
|
|
|
|
2024-08-23 23:40:27 +03:00
|
|
|
fn is_visible(&self) -> Option<bool> {
|
|
|
|
|
None
|
2019-06-25 03:15:34 +02:00
|
|
|
}
|
|
|
|
|
|
2024-08-23 23:40:27 +03:00
|
|
|
fn set_resizable(&self, _: bool) {
|
|
|
|
|
// Intentionally a no-op: users can't resize canvas elements
|
2021-03-07 10:43:23 +01:00
|
|
|
}
|
|
|
|
|
|
2024-08-23 23:40:27 +03:00
|
|
|
fn is_resizable(&self) -> bool {
|
|
|
|
|
true
|
2023-01-11 18:07:09 +01:00
|
|
|
}
|
|
|
|
|
|
2024-08-23 23:40:27 +03:00
|
|
|
fn set_enabled_buttons(&self, _: WindowButtons) {}
|
2023-10-11 01:16:16 +03:30
|
|
|
|
2024-08-23 23:40:27 +03:00
|
|
|
fn enabled_buttons(&self) -> WindowButtons {
|
|
|
|
|
WindowButtons::all()
|
2022-04-12 19:10:46 +02:00
|
|
|
}
|
|
|
|
|
|
2024-08-23 23:40:27 +03:00
|
|
|
fn set_minimized(&self, _: bool) {
|
2019-12-22 01:04:11 -05:00
|
|
|
// Intentionally a no-op, as canvases cannot be 'minimized'
|
|
|
|
|
}
|
|
|
|
|
|
2024-08-23 23:40:27 +03:00
|
|
|
fn is_minimized(&self) -> Option<bool> {
|
2023-01-19 23:39:04 +02:00
|
|
|
// Canvas cannot be 'minimized'
|
|
|
|
|
Some(false)
|
|
|
|
|
}
|
|
|
|
|
|
2024-08-23 23:40:27 +03:00
|
|
|
fn set_maximized(&self, _: bool) {
|
2019-09-24 19:33:32 -04:00
|
|
|
// Intentionally a no-op, as canvases cannot be 'maximized'
|
2019-06-25 03:15:34 +02:00
|
|
|
}
|
|
|
|
|
|
2024-08-23 23:40:27 +03:00
|
|
|
fn is_maximized(&self) -> bool {
|
2021-01-27 20:01:17 +02:00
|
|
|
// Canvas cannot be 'maximized'
|
|
|
|
|
false
|
|
|
|
|
}
|
|
|
|
|
|
2024-08-23 23:40:27 +03:00
|
|
|
fn set_fullscreen(&self, fullscreen: Option<RootFullscreen>) {
|
|
|
|
|
self.inner.dispatch(move |inner| {
|
|
|
|
|
if let Some(fullscreen) = fullscreen {
|
|
|
|
|
inner.canvas.request_fullscreen(fullscreen.into());
|
|
|
|
|
} else {
|
|
|
|
|
inner.canvas.exit_fullscreen()
|
|
|
|
|
}
|
|
|
|
|
})
|
2019-06-25 03:15:34 +02:00
|
|
|
}
|
|
|
|
|
|
2024-08-23 23:40:27 +03:00
|
|
|
fn fullscreen(&self) -> Option<RootFullscreen> {
|
|
|
|
|
self.inner.queue(|inner| {
|
|
|
|
|
if inner.canvas.is_fullscreen() {
|
|
|
|
|
Some(RootFullscreen::Borderless(None))
|
|
|
|
|
} else {
|
|
|
|
|
None
|
|
|
|
|
}
|
|
|
|
|
})
|
2019-06-25 03:15:34 +02:00
|
|
|
}
|
|
|
|
|
|
2024-08-23 23:40:27 +03:00
|
|
|
fn set_decorations(&self, _: bool) {
|
2019-06-25 03:15:34 +02:00
|
|
|
// Intentionally a no-op, no canvas decorations
|
|
|
|
|
}
|
2022-02-17 15:31:13 +02:00
|
|
|
|
2024-08-23 23:40:27 +03:00
|
|
|
fn is_decorated(&self) -> bool {
|
2022-02-17 15:31:13 +02:00
|
|
|
true
|
|
|
|
|
}
|
2019-06-25 03:15:34 +02:00
|
|
|
|
2024-08-23 23:40:27 +03:00
|
|
|
fn set_window_level(&self, _: WindowLevel) {
|
2019-06-25 03:15:34 +02:00
|
|
|
// Intentionally a no-op, no window ordering
|
|
|
|
|
}
|
|
|
|
|
|
2024-08-23 23:40:27 +03:00
|
|
|
fn set_window_icon(&self, _: Option<Icon>) {
|
2019-06-25 03:15:34 +02:00
|
|
|
// Currently an intentional no-op
|
|
|
|
|
}
|
|
|
|
|
|
2024-08-23 23:40:27 +03:00
|
|
|
fn set_ime_cursor_area(&self, _: Position, _: Size) {
|
2024-07-10 16:17:39 +02:00
|
|
|
// Currently not implemented
|
2019-06-25 03:15:34 +02:00
|
|
|
}
|
|
|
|
|
|
2024-08-23 23:40:27 +03:00
|
|
|
fn set_ime_allowed(&self, _: bool) {
|
2022-05-07 05:29:25 +03:00
|
|
|
// Currently not implemented
|
|
|
|
|
}
|
|
|
|
|
|
2024-08-23 23:40:27 +03:00
|
|
|
fn set_ime_purpose(&self, _: ImePurpose) {
|
2023-01-29 16:46:46 +01:00
|
|
|
// Currently not implemented
|
|
|
|
|
}
|
|
|
|
|
|
2024-08-23 23:40:27 +03:00
|
|
|
fn focus_window(&self) {
|
|
|
|
|
self.inner.dispatch(|inner| {
|
|
|
|
|
let _ = inner.canvas.raw().focus();
|
|
|
|
|
})
|
2021-05-19 18:39:53 +02:00
|
|
|
}
|
|
|
|
|
|
2024-08-23 23:40:27 +03:00
|
|
|
fn has_focus(&self) -> bool {
|
|
|
|
|
self.inner.queue(|inner| inner.canvas.has_focus.get())
|
2020-11-27 03:03:08 +01:00
|
|
|
}
|
|
|
|
|
|
2024-08-23 23:40:27 +03:00
|
|
|
fn request_user_attention(&self, _: Option<UserAttentionType>) {
|
|
|
|
|
// Currently an intentional no-op
|
2020-09-07 20:09:24 +03:00
|
|
|
}
|
|
|
|
|
|
2024-08-23 23:40:27 +03:00
|
|
|
fn set_theme(&self, _: Option<Theme>) {}
|
|
|
|
|
|
|
|
|
|
fn theme(&self) -> Option<Theme> {
|
|
|
|
|
self.inner.queue(|inner| {
|
|
|
|
|
backend::is_dark_mode(&inner.window).map(|is_dark_mode| {
|
|
|
|
|
if is_dark_mode {
|
|
|
|
|
Theme::Dark
|
|
|
|
|
} else {
|
|
|
|
|
Theme::Light
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
})
|
2019-06-25 03:15:34 +02:00
|
|
|
}
|
|
|
|
|
|
2024-08-23 23:40:27 +03:00
|
|
|
fn set_content_protected(&self, _: bool) {}
|
|
|
|
|
|
|
|
|
|
fn title(&self) -> String {
|
|
|
|
|
String::new()
|
2019-06-25 03:15:34 +02:00
|
|
|
}
|
|
|
|
|
|
2024-08-23 23:40:27 +03:00
|
|
|
fn set_cursor(&self, cursor: Cursor) {
|
|
|
|
|
self.inner.dispatch(move |inner| inner.canvas.cursor.set_cursor(cursor))
|
2019-06-25 03:15:34 +02:00
|
|
|
}
|
2019-09-24 19:39:13 -04:00
|
|
|
|
2024-09-06 17:20:11 +03:00
|
|
|
fn set_cursor_position(&self, _: Position) -> Result<(), RequestError> {
|
|
|
|
|
Err(NotSupportedError::new("set_cursor_position is not supported").into())
|
2024-08-23 23:40:27 +03:00
|
|
|
}
|
2022-11-29 11:05:51 +02:00
|
|
|
|
2024-09-06 17:20:11 +03:00
|
|
|
fn set_cursor_grab(&self, mode: CursorGrabMode) -> Result<(), RequestError> {
|
|
|
|
|
Ok(self.inner.queue(|inner| {
|
2024-08-23 23:40:27 +03:00
|
|
|
match mode {
|
|
|
|
|
CursorGrabMode::None => inner.canvas.document().exit_pointer_lock(),
|
|
|
|
|
CursorGrabMode::Locked => lock::request_pointer_lock(
|
|
|
|
|
inner.canvas.navigator(),
|
|
|
|
|
inner.canvas.document(),
|
|
|
|
|
inner.canvas.raw(),
|
|
|
|
|
),
|
|
|
|
|
CursorGrabMode::Confined => {
|
2024-09-06 17:20:11 +03:00
|
|
|
return Err(NotSupportedError::new("confined cursor mode is not supported"))
|
2024-08-23 23:40:27 +03:00
|
|
|
},
|
2023-08-14 21:19:57 +02:00
|
|
|
}
|
2024-08-23 23:40:27 +03:00
|
|
|
|
|
|
|
|
Ok(())
|
2024-09-06 17:20:11 +03:00
|
|
|
})?)
|
2022-10-19 03:34:36 +09:00
|
|
|
}
|
2022-11-03 10:11:37 -07:00
|
|
|
|
2024-08-23 23:40:27 +03:00
|
|
|
fn set_cursor_visible(&self, visible: bool) {
|
|
|
|
|
self.inner.dispatch(move |inner| inner.canvas.cursor.set_cursor_visible(visible))
|
|
|
|
|
}
|
2023-09-01 23:14:16 +02:00
|
|
|
|
2024-09-06 17:20:11 +03:00
|
|
|
fn drag_window(&self) -> Result<(), RequestError> {
|
|
|
|
|
Err(NotSupportedError::new("drag_window is not supported").into())
|
2023-01-17 03:30:14 +02:00
|
|
|
}
|
|
|
|
|
|
2024-09-06 17:20:11 +03:00
|
|
|
fn drag_resize_window(&self, _: ResizeDirection) -> Result<(), RequestError> {
|
|
|
|
|
Err(NotSupportedError::new("drag_resize_window is not supported").into())
|
2022-11-03 10:11:37 -07:00
|
|
|
}
|
2023-05-28 20:02:59 +02:00
|
|
|
|
2024-08-23 23:40:27 +03:00
|
|
|
fn show_window_menu(&self, _: Position) {}
|
|
|
|
|
|
2024-09-06 17:20:11 +03:00
|
|
|
fn set_cursor_hittest(&self, _: bool) -> Result<(), RequestError> {
|
|
|
|
|
Err(NotSupportedError::new("set_cursor_hittest is not supported").into())
|
2024-08-23 23:40:27 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn current_monitor(&self) -> Option<RootMonitorHandle> {
|
|
|
|
|
Some(self.inner.queue(|inner| inner.monitor.current_monitor()).into())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn available_monitors(&self) -> Box<dyn Iterator<Item = RootMonitorHandle>> {
|
|
|
|
|
Box::new(
|
|
|
|
|
self.inner
|
|
|
|
|
.queue(|inner| inner.monitor.available_monitors())
|
|
|
|
|
.into_iter()
|
|
|
|
|
.map(RootMonitorHandle::from),
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn primary_monitor(&self) -> Option<RootMonitorHandle> {
|
|
|
|
|
self.inner.queue(|inner| inner.monitor.primary_monitor()).map(RootMonitorHandle::from)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[cfg(feature = "rwh_06")]
|
|
|
|
|
fn rwh_06_display_handle(&self) -> &dyn rwh_06::HasDisplayHandle {
|
|
|
|
|
self
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[cfg(feature = "rwh_06")]
|
|
|
|
|
fn rwh_06_window_handle(&self) -> &dyn rwh_06::HasWindowHandle {
|
|
|
|
|
self
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[cfg(feature = "rwh_06")]
|
|
|
|
|
impl rwh_06::HasWindowHandle for Window {
|
|
|
|
|
fn window_handle(&self) -> Result<rwh_06::WindowHandle<'_>, rwh_06::HandleError> {
|
|
|
|
|
MainThreadMarker::new()
|
|
|
|
|
.map(|main_thread| {
|
|
|
|
|
let inner = self.inner.value(main_thread);
|
|
|
|
|
// SAFETY: This will only work if the reference to `HtmlCanvasElement` stays valid.
|
|
|
|
|
let canvas: &wasm_bindgen::JsValue = inner.canvas.raw();
|
|
|
|
|
let window_handle =
|
|
|
|
|
rwh_06::WebCanvasWindowHandle::new(std::ptr::NonNull::from(canvas).cast());
|
|
|
|
|
// SAFETY: The pointer won't be invalidated as long as `Window` lives, which the
|
|
|
|
|
// lifetime is bound to.
|
|
|
|
|
unsafe {
|
|
|
|
|
rwh_06::WindowHandle::borrow_raw(rwh_06::RawWindowHandle::WebCanvas(
|
|
|
|
|
window_handle,
|
|
|
|
|
))
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
.ok_or(rwh_06::HandleError::Unavailable)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[cfg(feature = "rwh_06")]
|
|
|
|
|
impl rwh_06::HasDisplayHandle for Window {
|
|
|
|
|
fn display_handle(&self) -> Result<rwh_06::DisplayHandle<'_>, rwh_06::HandleError> {
|
|
|
|
|
Ok(rwh_06::DisplayHandle::web())
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Inner {
|
|
|
|
|
#[inline]
|
|
|
|
|
pub fn scale_factor(&self) -> f64 {
|
|
|
|
|
super::backend::scale_factor(&self.window)
|
2023-05-28 20:02:59 +02:00
|
|
|
}
|
2019-06-25 03:15:34 +02:00
|
|
|
}
|
|
|
|
|
|
2023-08-14 21:19:57 +02:00
|
|
|
impl Drop for Inner {
|
2020-09-21 06:42:07 +08:00
|
|
|
fn drop(&mut self) {
|
2023-08-14 21:19:57 +02:00
|
|
|
if let Some(destroy_fn) = self.destroy_fn.take() {
|
|
|
|
|
destroy_fn();
|
|
|
|
|
}
|
2023-06-05 02:44:54 +02:00
|
|
|
}
|
2020-09-21 06:42:07 +08:00
|
|
|
}
|
2019-06-25 03:15:34 +02:00
|
|
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
2024-09-27 22:12:50 +02:00
|
|
|
pub struct WindowId(pub(crate) u64);
|
2019-06-25 03:15:34 +02:00
|
|
|
|
2022-03-18 14:09:39 +01:00
|
|
|
impl WindowId {
|
2024-09-27 22:12:50 +02:00
|
|
|
pub const fn into_raw(self) -> u64 {
|
|
|
|
|
self.0
|
2022-07-02 14:27:19 +03:00
|
|
|
}
|
|
|
|
|
|
2024-09-27 22:12:50 +02:00
|
|
|
pub const fn from_raw(id: u64) -> Self {
|
|
|
|
|
Self(id)
|
2022-07-02 14:27:19 +03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-01-17 23:37:28 +01:00
|
|
|
#[derive(Clone, Debug)]
|
2024-01-31 17:29:59 +04:00
|
|
|
pub struct PlatformSpecificWindowAttributes {
|
2023-12-26 01:22:10 +01:00
|
|
|
pub(crate) canvas: Option<Arc<MainThreadSafe<backend::RawCanvasType>>>,
|
2022-07-14 13:22:31 -02:30
|
|
|
pub(crate) prevent_default: bool,
|
|
|
|
|
pub(crate) focusable: bool,
|
2023-07-12 17:11:52 +02:00
|
|
|
pub(crate) append: bool,
|
2022-07-14 13:22:31 -02:30
|
|
|
}
|
|
|
|
|
|
2024-08-08 00:46:28 +02:00
|
|
|
impl PartialEq for PlatformSpecificWindowAttributes {
|
|
|
|
|
fn eq(&self, other: &Self) -> bool {
|
|
|
|
|
(match (&self.canvas, &other.canvas) {
|
|
|
|
|
(Some(this), Some(other)) => Arc::ptr_eq(this, other),
|
|
|
|
|
(None, None) => true,
|
|
|
|
|
_ => false,
|
|
|
|
|
}) && self.prevent_default.eq(&other.prevent_default)
|
|
|
|
|
&& self.focusable.eq(&other.focusable)
|
|
|
|
|
&& self.append.eq(&other.append)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-01-31 17:29:59 +04:00
|
|
|
impl PlatformSpecificWindowAttributes {
|
2023-12-26 01:22:10 +01:00
|
|
|
pub(crate) fn set_canvas(&mut self, canvas: Option<backend::RawCanvasType>) {
|
|
|
|
|
let Some(canvas) = canvas else {
|
|
|
|
|
self.canvas = None;
|
|
|
|
|
return;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let main_thread = MainThreadMarker::new()
|
|
|
|
|
.expect("received a `HtmlCanvasElement` outside the window context");
|
|
|
|
|
|
|
|
|
|
self.canvas = Some(Arc::new(MainThreadSafe::new(main_thread, canvas)));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-01-31 17:29:59 +04:00
|
|
|
impl Default for PlatformSpecificWindowAttributes {
|
2022-07-14 13:22:31 -02:30
|
|
|
fn default() -> Self {
|
|
|
|
|
Self { canvas: None, prevent_default: true, focusable: true, append: false }
|
|
|
|
|
}
|
2020-01-15 21:20:14 -05:00
|
|
|
}
|