forked from
me.webbeef.org/browser.html
Rewild Your Web
1--- original
2+++ modified
3@@ -48,6 +48,11 @@
4 /// The [`Theme`] that this [`ConstellationWebView`] uses. This is communicated to all
5 /// `ScriptThread`s so that they know how to render the contents of a particular `WebView.
6 theme: Theme,
7+
8+ /// Whether this webview should never receive focus (hidefocus attribute on the iframe).
9+ /// When true, focus-related events are processed but focus is not transferred to
10+ /// elements in this webview's documents.
11+ pub hide_focus: bool,
12 }
13
14 impl ConstellationWebView {
15@@ -57,6 +62,22 @@
16 focused_browsing_context_id: BrowsingContextId,
17 user_content_manager_id: Option<UserContentManagerId>,
18 ) -> Self {
19+ Self::new_with_hide_focus(
20+ webview_id,
21+ active_top_level_pipeline_id,
22+ focused_browsing_context_id,
23+ user_content_manager_id,
24+ false,
25+ )
26+ }
27+
28+ pub(crate) fn new_with_hide_focus(
29+ webview_id: WebViewId,
30+ active_top_level_pipeline_id: PipelineId,
31+ focused_browsing_context_id: BrowsingContextId,
32+ user_content_manager_id: Option<UserContentManagerId>,
33+ hide_focus: bool,
34+ ) -> Self {
35 Self {
36 webview_id,
37 user_content_manager_id,
38@@ -66,6 +87,7 @@
39 last_mouse_move_point: Default::default(),
40 session_history: JointSessionHistory::new(),
41 theme: Theme::Light,
42+ hide_focus,
43 }
44 }
45
46@@ -85,12 +107,41 @@
47 event: &ConstellationInputEvent,
48 browsing_contexts: &FxHashMap<BrowsingContextId, BrowsingContext>,
49 ) -> Option<PipelineId> {
50+ // For pointer events with coordinates (mouse, touch, wheel), we always route to
51+ // the ROOT browsing context of this webview, not the focused one.
52+ // This is because:
53+ // 1. WebRender hit testing doesn't respect CSS z-index/stacking contexts
54+ // 2. When an embedded webview is focused, we still want pointer events to go through
55+ // the parent's DOM hit testing first to respect z-index of overlays
56+ // 3. The parent's DOM hit testing will forward events to embedded webviews if the
57+ // hit target is an embedded iframe element
58+ //
59+ // The root browsing context ID is the same as the webview ID (WebViewId wraps
60+ // TopLevelBrowsingContextId which wraps BrowsingContextId).
61+ let has_pointer_coordinates = matches!(
62+ event.event.event,
63+ InputEvent::MouseButton(_) |
64+ InputEvent::MouseMove(_) |
65+ InputEvent::Touch(_) |
66+ InputEvent::Wheel(_)
67+ );
68+
69+ if has_pointer_coordinates {
70+ // Route to the root/parent browsing context of this webview
71+ let root_browsing_context_id: BrowsingContextId = self.webview_id.into();
72+ return Some(
73+ browsing_contexts
74+ .get(&root_browsing_context_id)?
75+ .pipeline_id,
76+ );
77+ }
78+
79+ // For non-pointer events (keyboard, etc.), use hit test result if available
80 if let Some(hit_test_result) = &event.hit_test_result {
81 return Some(hit_test_result.pipeline_id);
82 }
83
84- // If there's no hit test, send the event to either the hovered or focused browsing context,
85- // depending on the event type.
86+ // Otherwise, send to either the hovered or focused browsing context
87 let browsing_context_id = if matches!(event.event.event, InputEvent::MouseLeftViewport(_)) {
88 self.hovered_browsing_context_id
89 .unwrap_or(self.focused_browsing_context_id)
90@@ -160,11 +211,9 @@
91
92 if let InputEvent::MouseMove(_) = &event.event.event {
93 update_hovered_browsing_context(Some(pipeline.browsing_context_id), true);
94- self.last_mouse_move_point = event
95- .hit_test_result
96- .as_ref()
97- .expect("MouseMove events should always have hit tests.")
98- .point_in_viewport;
99+ if let Some(ref hit_test_result) = event.hit_test_result {
100+ self.last_mouse_move_point = hit_test_result.point_in_viewport;
101+ }
102 }
103
104 let _ = pipeline