mirror of
https://github.com/italicsjenga/winit-sonoma-fix.git
synced 2024-12-23 22:01:31 +11:00
On Web, implement and fix missing methods on Window(Builder)
(#2949)
This commit is contained in:
parent
50b17a3907
commit
3b2d1a7643
|
@ -15,6 +15,10 @@ And please only add new entries to the top of this list, right below the `# Unre
|
|||
- On Web, fix touch location to be as accurate as mouse position.
|
||||
- On Web, account for CSS `padding`, `border`, and `margin` when getting or setting the canvas position.
|
||||
- On Web, add Fullscreen API compatibility for Safari.
|
||||
- On Web, implement `Window::set_(min|max)_inner_size()`.
|
||||
- On Web, fix some `Window` methods using incorrect HTML attributes instead of CSS properties.
|
||||
- On Web, fix some `WindowBuilder` methods doing nothing.
|
||||
- On Web, implement `Window::focus_window()`.
|
||||
|
||||
# 0.29.0-beta.0
|
||||
|
||||
|
|
|
@ -88,21 +88,46 @@ impl Canvas {
|
|||
// this can't fail: we aren't using a pseudo-element
|
||||
.expect("Invalid pseudo-element");
|
||||
|
||||
let common = Common {
|
||||
window,
|
||||
document,
|
||||
raw: canvas,
|
||||
style,
|
||||
old_size: Rc::default(),
|
||||
current_size: Rc::default(),
|
||||
wants_fullscreen: Rc::new(RefCell::new(false)),
|
||||
};
|
||||
|
||||
if let Some(size) = attr.inner_size {
|
||||
let size = size.to_logical(super::scale_factor(&window));
|
||||
super::set_canvas_size(&document, &canvas, &style, size);
|
||||
let size = size.to_logical(super::scale_factor(&common.window));
|
||||
super::set_canvas_size(&common.document, &common.raw, &common.style, size);
|
||||
}
|
||||
|
||||
if let Some(size) = attr.min_inner_size {
|
||||
let size = size.to_logical(super::scale_factor(&common.window));
|
||||
super::set_canvas_min_size(&common.document, &common.raw, &common.style, Some(size));
|
||||
}
|
||||
|
||||
if let Some(size) = attr.max_inner_size {
|
||||
let size = size.to_logical(super::scale_factor(&common.window));
|
||||
super::set_canvas_max_size(&common.document, &common.raw, &common.style, Some(size));
|
||||
}
|
||||
|
||||
if let Some(position) = attr.position {
|
||||
let position = position.to_logical(super::scale_factor(&common.window));
|
||||
super::set_canvas_position(&common.document, &common.raw, &common.style, position);
|
||||
}
|
||||
|
||||
if attr.fullscreen.is_some() {
|
||||
common.request_fullscreen();
|
||||
}
|
||||
|
||||
if attr.active {
|
||||
let _ = common.raw.focus();
|
||||
}
|
||||
|
||||
Ok(Canvas {
|
||||
common: Common {
|
||||
window,
|
||||
document,
|
||||
raw: canvas,
|
||||
style,
|
||||
old_size: Rc::default(),
|
||||
current_size: Rc::default(),
|
||||
wants_fullscreen: Rc::new(RefCell::new(false)),
|
||||
},
|
||||
common,
|
||||
id,
|
||||
has_focus: Arc::new(AtomicBool::new(false)),
|
||||
is_intersecting: None,
|
||||
|
|
|
@ -14,7 +14,7 @@ pub use self::event_handle::EventListenerHandle;
|
|||
pub use self::resize_scaling::ResizeScaleHandle;
|
||||
pub use self::timeout::{IdleCallback, Timeout};
|
||||
|
||||
use crate::dpi::LogicalSize;
|
||||
use crate::dpi::{LogicalPosition, LogicalSize};
|
||||
use crate::platform::web::WindowExtWebSys;
|
||||
use crate::window::Window;
|
||||
use wasm_bindgen::closure::Closure;
|
||||
|
@ -67,35 +67,107 @@ pub fn scale_factor(window: &web_sys::Window) -> f64 {
|
|||
window.device_pixel_ratio()
|
||||
}
|
||||
|
||||
pub fn set_canvas_size(
|
||||
document: &Document,
|
||||
raw: &HtmlCanvasElement,
|
||||
style: &CssStyleDeclaration,
|
||||
mut new_size: LogicalSize<f64>,
|
||||
) {
|
||||
if !document.contains(Some(raw)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if style.get_property_value("display").unwrap() == "none" {
|
||||
return;
|
||||
}
|
||||
|
||||
fn fix_canvas_size(style: &CssStyleDeclaration, mut size: LogicalSize<f64>) -> LogicalSize<f64> {
|
||||
if style.get_property_value("box-sizing").unwrap() == "border-box" {
|
||||
new_size.width += style_size_property(style, "border-left-width")
|
||||
size.width += style_size_property(style, "border-left-width")
|
||||
+ style_size_property(style, "border-right-width")
|
||||
+ style_size_property(style, "padding-left")
|
||||
+ style_size_property(style, "padding-right");
|
||||
new_size.height += style_size_property(style, "border-top-width")
|
||||
size.height += style_size_property(style, "border-top-width")
|
||||
+ style_size_property(style, "border-bottom-width")
|
||||
+ style_size_property(style, "padding-top")
|
||||
+ style_size_property(style, "padding-bottom");
|
||||
}
|
||||
|
||||
size
|
||||
}
|
||||
|
||||
pub fn set_canvas_size(
|
||||
document: &Document,
|
||||
raw: &HtmlCanvasElement,
|
||||
style: &CssStyleDeclaration,
|
||||
new_size: LogicalSize<f64>,
|
||||
) {
|
||||
if !document.contains(Some(raw)) || style.get_property_value("display").unwrap() == "none" {
|
||||
return;
|
||||
}
|
||||
|
||||
let new_size = fix_canvas_size(style, new_size);
|
||||
|
||||
set_canvas_style_property(raw, "width", &format!("{}px", new_size.width));
|
||||
set_canvas_style_property(raw, "height", &format!("{}px", new_size.height));
|
||||
}
|
||||
|
||||
pub fn set_canvas_min_size(
|
||||
document: &Document,
|
||||
raw: &HtmlCanvasElement,
|
||||
style: &CssStyleDeclaration,
|
||||
dimensions: Option<LogicalSize<f64>>,
|
||||
) {
|
||||
if let Some(dimensions) = dimensions {
|
||||
if !document.contains(Some(raw)) || style.get_property_value("display").unwrap() == "none" {
|
||||
return;
|
||||
}
|
||||
|
||||
let new_size = fix_canvas_size(style, dimensions);
|
||||
|
||||
set_canvas_style_property(raw, "min-width", &format!("{}px", new_size.width));
|
||||
set_canvas_style_property(raw, "min-height", &format!("{}px", new_size.height));
|
||||
} else {
|
||||
style
|
||||
.remove_property("min-width")
|
||||
.expect("Property is read only");
|
||||
style
|
||||
.remove_property("min-height")
|
||||
.expect("Property is read only");
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_canvas_max_size(
|
||||
document: &Document,
|
||||
raw: &HtmlCanvasElement,
|
||||
style: &CssStyleDeclaration,
|
||||
dimensions: Option<LogicalSize<f64>>,
|
||||
) {
|
||||
if let Some(dimensions) = dimensions {
|
||||
if !document.contains(Some(raw)) || style.get_property_value("display").unwrap() == "none" {
|
||||
return;
|
||||
}
|
||||
|
||||
let new_size = fix_canvas_size(style, dimensions);
|
||||
|
||||
set_canvas_style_property(raw, "max-width", &format!("{}px", new_size.width));
|
||||
set_canvas_style_property(raw, "max-height", &format!("{}px", new_size.height));
|
||||
} else {
|
||||
style
|
||||
.remove_property("max-width")
|
||||
.expect("Property is read only");
|
||||
style
|
||||
.remove_property("max-height")
|
||||
.expect("Property is read only");
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_canvas_position(
|
||||
document: &Document,
|
||||
raw: &HtmlCanvasElement,
|
||||
style: &CssStyleDeclaration,
|
||||
mut position: LogicalPosition<f64>,
|
||||
) {
|
||||
if document.contains(Some(raw)) && style.get_property_value("display").unwrap() != "none" {
|
||||
position.x -= style_size_property(style, "margin-left")
|
||||
+ style_size_property(style, "border-left-width")
|
||||
+ style_size_property(style, "padding-left");
|
||||
position.y -= style_size_property(style, "margin-top")
|
||||
+ style_size_property(style, "border-top-width")
|
||||
+ style_size_property(style, "padding-top");
|
||||
}
|
||||
|
||||
set_canvas_style_property(raw, "position", "fixed");
|
||||
set_canvas_style_property(raw, "left", &format!("{}px", position.x));
|
||||
set_canvas_style_property(raw, "top", &format!("{}px", position.y));
|
||||
}
|
||||
|
||||
/// This function will panic if the element is not inserted in the DOM
|
||||
/// or is not a CSS property that represents a size in pixel.
|
||||
pub fn style_size_property(style: &CssStyleDeclaration, property: &str) -> f64 {
|
||||
|
|
|
@ -7,7 +7,7 @@ use crate::window::{
|
|||
};
|
||||
|
||||
use raw_window_handle::{RawDisplayHandle, RawWindowHandle, WebDisplayHandle, WebWindowHandle};
|
||||
use web_sys::{CssStyleDeclaration, Document, HtmlCanvasElement};
|
||||
use web_sys::{Document, HtmlCanvasElement};
|
||||
|
||||
use super::r#async::Dispatcher;
|
||||
use super::{backend, monitor::MonitorHandle, EventLoopWindowTarget, Fullscreen};
|
||||
|
@ -28,7 +28,6 @@ pub struct Window {
|
|||
pub struct Inner {
|
||||
pub window: web_sys::Window,
|
||||
document: Document,
|
||||
style: CssStyleDeclaration,
|
||||
canvas: Rc<RefCell<backend::Canvas>>,
|
||||
previous_pointer: RefCell<&'static str>,
|
||||
register_redraw_request: Box<dyn Fn()>,
|
||||
|
@ -51,7 +50,6 @@ impl Window {
|
|||
let document = target.runner.document();
|
||||
let canvas =
|
||||
backend::Canvas::create(id, window.clone(), document.clone(), &attr, platform_attr)?;
|
||||
let style = canvas.style().clone();
|
||||
let canvas = Rc::new(RefCell::new(canvas));
|
||||
|
||||
let register_redraw_request = Box::new(move || runner.request_redraw(RootWI(id)));
|
||||
|
@ -68,7 +66,6 @@ impl Window {
|
|||
inner: Dispatcher::new(Inner {
|
||||
window: window.clone(),
|
||||
document: document.clone(),
|
||||
style,
|
||||
canvas,
|
||||
previous_pointer: RefCell::new("auto"),
|
||||
register_redraw_request,
|
||||
|
@ -134,24 +131,10 @@ impl Window {
|
|||
|
||||
pub fn set_outer_position(&self, position: Position) {
|
||||
self.inner.dispatch(move |inner| {
|
||||
let mut position = position.to_logical::<f64>(inner.scale_factor());
|
||||
|
||||
let canvas = inner.canvas.borrow();
|
||||
let position = position.to_logical::<f64>(inner.scale_factor());
|
||||
|
||||
if inner.document.contains(Some(canvas.raw()))
|
||||
&& inner.style.get_property_value("display").unwrap() != "none"
|
||||
{
|
||||
position.x -= backend::style_size_property(&inner.style, "margin-left")
|
||||
+ backend::style_size_property(&inner.style, "border-left-width")
|
||||
+ backend::style_size_property(&inner.style, "padding-left");
|
||||
position.y -= backend::style_size_property(&inner.style, "margin-top")
|
||||
+ backend::style_size_property(&inner.style, "border-top-width")
|
||||
+ backend::style_size_property(&inner.style, "padding-top");
|
||||
}
|
||||
|
||||
canvas.set_attribute("position", "fixed");
|
||||
canvas.set_attribute("left", &position.x.to_string());
|
||||
canvas.set_attribute("top", &position.y.to_string());
|
||||
backend::set_canvas_position(canvas.document(), canvas.raw(), canvas.style(), position)
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -178,13 +161,33 @@ impl Window {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
pub fn set_min_inner_size(&self, _dimensions: Option<Size>) {
|
||||
// Intentionally a no-op: users can't resize canvas elements
|
||||
pub fn set_min_inner_size(&self, dimensions: Option<Size>) {
|
||||
self.inner.dispatch(move |inner| {
|
||||
let dimensions =
|
||||
dimensions.map(|dimensions| dimensions.to_logical(inner.scale_factor()));
|
||||
let canvas = inner.canvas.borrow();
|
||||
backend::set_canvas_min_size(
|
||||
canvas.document(),
|
||||
canvas.raw(),
|
||||
canvas.style(),
|
||||
dimensions,
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn set_max_inner_size(&self, _dimensions: Option<Size>) {
|
||||
// Intentionally a no-op: users can't resize canvas elements
|
||||
pub fn set_max_inner_size(&self, dimensions: Option<Size>) {
|
||||
self.inner.dispatch(move |inner| {
|
||||
let dimensions =
|
||||
dimensions.map(|dimensions| dimensions.to_logical(inner.scale_factor()));
|
||||
let canvas = inner.canvas.borrow();
|
||||
backend::set_canvas_max_size(
|
||||
canvas.document(),
|
||||
canvas.raw(),
|
||||
canvas.style(),
|
||||
dimensions,
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -259,12 +262,13 @@ impl Window {
|
|||
pub fn set_cursor_visible(&self, visible: bool) {
|
||||
self.inner.dispatch(move |inner| {
|
||||
if !visible {
|
||||
inner.canvas.borrow().set_attribute("cursor", "none");
|
||||
backend::set_canvas_style_property(inner.canvas.borrow().raw(), "cursor", "none");
|
||||
} else {
|
||||
inner
|
||||
.canvas
|
||||
.borrow()
|
||||
.set_attribute("cursor", &inner.previous_pointer.borrow());
|
||||
backend::set_canvas_style_property(
|
||||
inner.canvas.borrow().raw(),
|
||||
"cursor",
|
||||
&inner.previous_pointer.borrow(),
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -364,7 +368,9 @@ impl Window {
|
|||
|
||||
#[inline]
|
||||
pub fn focus_window(&self) {
|
||||
// Currently a no-op as it does not seem there is good support for this on web
|
||||
self.inner.dispatch(|inner| {
|
||||
let _ = inner.canvas.borrow().raw().focus();
|
||||
})
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
|
|
@ -730,7 +730,7 @@ impl Window {
|
|||
///
|
||||
/// ## Platform-specific
|
||||
///
|
||||
/// - **iOS / Android / Web / Orbital:** Unsupported.
|
||||
/// - **iOS / Android / Orbital:** Unsupported.
|
||||
#[inline]
|
||||
pub fn set_min_inner_size<S: Into<Size>>(&self, min_size: Option<S>) {
|
||||
self.window.set_min_inner_size(min_size.map(|s| s.into()))
|
||||
|
@ -753,7 +753,7 @@ impl Window {
|
|||
///
|
||||
/// ## Platform-specific
|
||||
///
|
||||
/// - **iOS / Android / Web / Orbital:** Unsupported.
|
||||
/// - **iOS / Android / Orbital:** Unsupported.
|
||||
#[inline]
|
||||
pub fn set_max_inner_size<S: Into<Size>>(&self, max_size: Option<S>) {
|
||||
self.window.set_max_inner_size(max_size.map(|s| s.into()))
|
||||
|
@ -1120,7 +1120,7 @@ impl Window {
|
|||
///
|
||||
/// ## Platform-specific
|
||||
///
|
||||
/// - **iOS / Android / Web / Wayland / Orbital:** Unsupported.
|
||||
/// - **iOS / Android / Wayland / Orbital:** Unsupported.
|
||||
#[inline]
|
||||
pub fn focus_window(&self) {
|
||||
self.window.focus_window()
|
||||
|
|
Loading…
Reference in a new issue