From a8c1790780de4ffb5800f8fea844f6ca2ecd3256 Mon Sep 17 00:00:00 2001 From: xxvvii Date: Wed, 22 Jan 2025 15:33:07 +0800 Subject: [PATCH 1/5] Add pointer events and focus handling for apps run in a Shadow DOM --- crates/eframe/Cargo.toml | 1 + crates/eframe/src/web/events.rs | 17 ++++++++++++----- crates/eframe/src/web/mod.rs | 20 ++++++++++++-------- crates/eframe/src/web/text_agent.rs | 15 +++++++++++++-- crates/eframe/src/web/web_runner.rs | 2 +- 5 files changed, 39 insertions(+), 16 deletions(-) diff --git a/crates/eframe/Cargo.toml b/crates/eframe/Cargo.toml index c07dc9d0d3a1..44d2caedf5fc 100644 --- a/crates/eframe/Cargo.toml +++ b/crates/eframe/Cargo.toml @@ -225,6 +225,7 @@ web-sys = { workspace = true, features = [ "ResizeObserverEntry", "ResizeObserverOptions", "ResizeObserverSize", + "ShadowRoot", "Storage", "Touch", "TouchEvent", diff --git a/crates/eframe/src/web/events.rs b/crates/eframe/src/web/events.rs index 414e5be23837..242bac30d435 100644 --- a/crates/eframe/src/web/events.rs +++ b/crates/eframe/src/web/events.rs @@ -4,7 +4,7 @@ use super::{ push_touches, text_from_keyboard_event, theme_from_dark_mode, translate_key, AppRunner, Closure, JsCast, JsValue, WebRunner, }; -use web_sys::EventTarget; +use web_sys::{Document, EventTarget, ShadowRoot}; // TODO(emilk): there are more calls to `prevent_default` and `stop_propagation` // than what is probably needed. @@ -510,10 +510,17 @@ fn install_pointerup(runner_ref: &WebRunner, target: &EventTarget) -> Result<(), /// Returns true if the cursor is above the canvas, or if we're dragging something. /// Pass in the position in browser viewport coordinates (usually event.clientX/Y). fn is_interested_in_pointer_event(runner: &AppRunner, pos: egui::Pos2) -> bool { - let document = web_sys::window().unwrap().document().unwrap(); - let is_hovering_canvas = document - .element_from_point(pos.x, pos.y) - .is_some_and(|element| element.eq(runner.canvas())); + let root_node = runner.canvas().get_root_node(); + + let element_at_point = if let Some(document) = root_node.dyn_ref::() { + document.element_from_point(pos.x, pos.y) + } else if let Some(shadow) = root_node.dyn_ref::() { + shadow.element_from_point(pos.x, pos.y) + } else { + None + }; + + let is_hovering_canvas = element_at_point.is_some_and(|element| element.eq(runner.canvas())); let is_pointer_down = runner .egui_ctx() .input(|i| i.pointer.any_down() || i.any_touches()); diff --git a/crates/eframe/src/web/mod.rs b/crates/eframe/src/web/mod.rs index 827feb9244fe..236bf96bbad0 100644 --- a/crates/eframe/src/web/mod.rs +++ b/crates/eframe/src/web/mod.rs @@ -41,7 +41,7 @@ pub(crate) type ActiveWebPainter = web_painter_wgpu::WebPainterWgpu; pub use backend::*; use wasm_bindgen::prelude::*; -use web_sys::MediaQueryList; +use web_sys::{Document, MediaQueryList, Node}; use input::{ button_from_mouse_event, modifiers_from_kb_event, modifiers_from_mouse_event, @@ -61,18 +61,22 @@ pub(crate) fn string_from_js_value(value: &JsValue) -> String { /// - ``/`` with an `href` attribute /// - ``/`