Rewild Your Web
at main 104 lines 4.3 kB view raw
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