On Web, implement WindowEvent::Occluded (#2940)
This commit is contained in:
parent
bd890e69aa
commit
5e0e1e96bc
9 changed files with 165 additions and 9 deletions
|
|
@ -1,5 +1,6 @@
|
|||
use super::super::WindowId;
|
||||
use super::event_handle::EventListenerHandle;
|
||||
use super::intersection_handle::IntersectionObserverHandle;
|
||||
use super::media_query_handle::MediaQueryListHandle;
|
||||
use super::pointer::PointerHandler;
|
||||
use super::{event, ButtonsState, ResizeScaleHandle};
|
||||
|
|
@ -37,6 +38,7 @@ pub struct Canvas {
|
|||
on_dark_mode: Option<MediaQueryListHandle>,
|
||||
pointer_handler: PointerHandler,
|
||||
on_resize_scale: Option<ResizeScaleHandle>,
|
||||
on_intersect: Option<IntersectionObserverHandle>,
|
||||
}
|
||||
|
||||
pub struct Common {
|
||||
|
|
@ -105,6 +107,7 @@ impl Canvas {
|
|||
on_dark_mode: None,
|
||||
pointer_handler: PointerHandler::new(),
|
||||
on_resize_scale: None,
|
||||
on_intersect: None,
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -365,6 +368,13 @@ impl Canvas {
|
|||
));
|
||||
}
|
||||
|
||||
pub(crate) fn on_intersection<F>(&mut self, handler: F)
|
||||
where
|
||||
F: 'static + FnMut(bool),
|
||||
{
|
||||
self.on_intersect = Some(IntersectionObserverHandle::new(self.raw(), handler));
|
||||
}
|
||||
|
||||
pub fn request_fullscreen(&self) {
|
||||
self.common.request_fullscreen()
|
||||
}
|
||||
|
|
@ -421,6 +431,7 @@ impl Canvas {
|
|||
self.on_dark_mode = None;
|
||||
self.pointer_handler.remove_listeners();
|
||||
self.on_resize_scale = None;
|
||||
self.on_intersect = None;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
45
src/platform_impl/web/web_sys/intersection_handle.rs
Normal file
45
src/platform_impl/web/web_sys/intersection_handle.rs
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
use js_sys::Array;
|
||||
use wasm_bindgen::{prelude::Closure, JsCast};
|
||||
use web_sys::{Element, IntersectionObserver, IntersectionObserverEntry};
|
||||
|
||||
pub(super) struct IntersectionObserverHandle {
|
||||
observer: IntersectionObserver,
|
||||
_closure: Closure<dyn FnMut(Array)>,
|
||||
}
|
||||
|
||||
impl IntersectionObserverHandle {
|
||||
pub fn new<F>(element: &Element, mut callback: F) -> Self
|
||||
where
|
||||
F: 'static + FnMut(bool),
|
||||
{
|
||||
let mut skip = true;
|
||||
let closure = Closure::new(move |entries: Array| {
|
||||
let entry: IntersectionObserverEntry = entries.get(0).unchecked_into();
|
||||
|
||||
let is_intersecting = entry.is_intersecting();
|
||||
|
||||
// skip first intersection
|
||||
if skip && is_intersecting {
|
||||
skip = false;
|
||||
return;
|
||||
}
|
||||
|
||||
callback(is_intersecting);
|
||||
});
|
||||
let observer = IntersectionObserver::new(closure.as_ref().unchecked_ref())
|
||||
// we don't provide any `options`
|
||||
.expect("Invalid `options`");
|
||||
observer.observe(element);
|
||||
|
||||
Self {
|
||||
observer,
|
||||
_closure: closure,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for IntersectionObserverHandle {
|
||||
fn drop(&mut self) {
|
||||
self.observer.disconnect()
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
mod canvas;
|
||||
pub mod event;
|
||||
mod event_handle;
|
||||
mod intersection_handle;
|
||||
mod media_query_handle;
|
||||
mod pointer;
|
||||
mod resize_scaling;
|
||||
|
|
@ -16,7 +17,9 @@ use crate::dpi::LogicalSize;
|
|||
use crate::platform::web::WindowExtWebSys;
|
||||
use crate::window::Window;
|
||||
use wasm_bindgen::closure::Closure;
|
||||
use web_sys::{CssStyleDeclaration, Element, HtmlCanvasElement, PageTransitionEvent};
|
||||
use web_sys::{
|
||||
CssStyleDeclaration, Element, HtmlCanvasElement, PageTransitionEvent, VisibilityState,
|
||||
};
|
||||
|
||||
pub fn throw(msg: &str) {
|
||||
wasm_bindgen::throw_str(msg);
|
||||
|
|
@ -136,4 +139,25 @@ pub fn is_dark_mode(window: &web_sys::Window) -> Option<bool> {
|
|||
.map(|media| media.matches())
|
||||
}
|
||||
|
||||
pub fn is_visible(window: &web_sys::Window) -> bool {
|
||||
let document = window.document().expect("Failed to obtain document");
|
||||
document.visibility_state() == VisibilityState::Visible
|
||||
}
|
||||
|
||||
pub fn is_intersecting(window: &web_sys::Window, canvas: &HtmlCanvasElement) -> bool {
|
||||
let rect = canvas.get_bounding_client_rect();
|
||||
// This should never panic.
|
||||
let window_width = window.inner_width().unwrap().as_f64().unwrap() as i32;
|
||||
let window_height = window.inner_height().unwrap().as_f64().unwrap() as i32;
|
||||
let left = rect.left() as i32;
|
||||
let width = rect.width() as i32;
|
||||
let top = rect.top() as i32;
|
||||
let height = rect.height() as i32;
|
||||
|
||||
let horizontal = left <= window_width && left + width >= 0;
|
||||
let vertical = top <= window_height && top + height >= 0;
|
||||
|
||||
horizontal && vertical
|
||||
}
|
||||
|
||||
pub type RawCanvasType = HtmlCanvasElement;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue