Rewild Your Web
web browser dweb
at main 102 lines 4.2 kB view raw
1--- original 2+++ modified 3@@ -45,6 +45,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@@ -53,6 +58,20 @@ 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+ focused_browsing_context_id, 22+ user_content_manager_id, 23+ false, 24+ ) 25+ } 26+ 27+ pub(crate) fn new_with_hide_focus( 28+ webview_id: WebViewId, 29+ focused_browsing_context_id: BrowsingContextId, 30+ user_content_manager_id: Option<UserContentManagerId>, 31+ hide_focus: bool, 32+ ) -> Self { 33 Self { 34 webview_id, 35 user_content_manager_id, 36@@ -61,6 +80,7 @@ 37 last_mouse_move_point: Default::default(), 38 session_history: JointSessionHistory::new(), 39 theme: Theme::Light, 40+ hide_focus, 41 } 42 } 43 44@@ -80,12 +100,41 @@ 45 event: &ConstellationInputEvent, 46 browsing_contexts: &FxHashMap<BrowsingContextId, BrowsingContext>, 47 ) -> Option<PipelineId> { 48+ // For pointer events with coordinates (mouse, touch, wheel), we always route to 49+ // the ROOT browsing context of this webview, not the focused one. 50+ // This is because: 51+ // 1. WebRender hit testing doesn't respect CSS z-index/stacking contexts 52+ // 2. When an embedded webview is focused, we still want pointer events to go through 53+ // the parent's DOM hit testing first to respect z-index of overlays 54+ // 3. The parent's DOM hit testing will forward events to embedded webviews if the 55+ // hit target is an embedded iframe element 56+ // 57+ // The root browsing context ID is the same as the webview ID (WebViewId wraps 58+ // TopLevelBrowsingContextId which wraps BrowsingContextId). 59+ let has_pointer_coordinates = matches!( 60+ event.event.event, 61+ InputEvent::MouseButton(_) | 62+ InputEvent::MouseMove(_) | 63+ InputEvent::Touch(_) | 64+ InputEvent::Wheel(_) 65+ ); 66+ 67+ if has_pointer_coordinates { 68+ // Route to the root/parent browsing context of this webview 69+ let root_browsing_context_id: BrowsingContextId = self.webview_id.into(); 70+ return Some( 71+ browsing_contexts 72+ .get(&root_browsing_context_id)? 73+ .pipeline_id, 74+ ); 75+ } 76+ 77+ // For non-pointer events (keyboard, etc.), use hit test result if available 78 if let Some(hit_test_result) = &event.hit_test_result { 79 return Some(hit_test_result.pipeline_id); 80 } 81 82- // If there's no hit test, send the event to either the hovered or focused browsing context, 83- // depending on the event type. 84+ // Otherwise, send to either the hovered or focused browsing context 85 let browsing_context_id = if matches!(event.event.event, InputEvent::MouseLeftViewport(_)) { 86 self.hovered_browsing_context_id 87 .unwrap_or(self.focused_browsing_context_id) 88@@ -155,11 +204,9 @@ 89 90 if let InputEvent::MouseMove(_) = &event.event.event { 91 update_hovered_browsing_context(Some(pipeline.browsing_context_id), true); 92- self.last_mouse_move_point = event 93- .hit_test_result 94- .as_ref() 95- .expect("MouseMove events should always have hit tests.") 96- .point_in_viewport; 97+ if let Some(ref hit_test_result) = event.hit_test_result { 98+ self.last_mouse_move_point = hit_test_result.point_in_viewport; 99+ } 100 } 101 102 let _ = pipeline