From 839c44bc4efe9280077d03f27bc062249d43e751 Mon Sep 17 00:00:00 2001 From: webbeef Date: Fri, 25 Sep 2026 14:57:23 -0700 Subject: [PATCH] chore: update to Servo 2c70100ad4ef82e2c35908f0f22138358324cb43 Signed-off-by: webbeef --- crates/beaver_shell/src/webdriver.rs | 6 +- forkme.lock | 2 +- patches/Cargo.lock.patch | 10 +- .../constellation/constellation.rs.patch | 146 +++++++++++------- .../constellation_webview.rs.patch | 12 +- .../constellation/embedder.rs.patch | 8 +- .../components/constellation/tracing.rs.patch | 18 +-- .../layout/display_list/mod.rs.patch | 22 +-- patches/components/layout/dom.rs.patch | 2 +- patches/components/paint/painter.rs.patch | 2 +- .../components/script/dom/atproto.rs.patch | 2 +- .../script/dom/brightnessdevice.rs.patch | 2 +- .../script/dom/contentblocker.rs.patch | 6 +- patches/components/script/dom/dbus.rs.patch | 19 +-- .../script/dom/document/document.rs.patch | 56 +++---- .../document_embedder_controls.rs.patch | 35 ++--- .../document/document_event_handler.rs.patch | 112 ++++++++++---- .../script/dom/document/focus.rs.patch | 4 +- .../dom/document/spatial_navigation.rs.patch | 7 +- .../components/script/dom/embedder.rs.patch | 2 +- .../dom/globalscope/globalscope.rs.patch | 10 +- .../htmliframeelement.rs.patch | 8 +- .../form_controls/htmlinputelement.rs.patch | 8 +- .../htmltextareaelement.rs.patch | 2 +- .../dom/html/htmlwebviewelement.rs.patch | 7 +- .../script/dom/idledetector.rs.patch | 4 +- .../components/script/dom/keyboard.rs.patch | 2 +- .../script/dom/navigator/navigator.rs.patch | 4 +- .../components/script/dom/pairing.rs.patch | 26 ++-- patches/components/script/dom/power.rs.patch | 8 +- .../dom/serviceworker/notification.rs.patch | 6 +- .../script/dom/window/window.rs.patch | 30 ++-- .../script/dom/window/windowproxy.rs.patch | 12 +- .../dom/workers/workerglobalscope.rs.patch | 2 +- .../script/event_loop/script_thread.rs.patch | 42 ++--- patches/components/script/navigation.rs.patch | 4 +- .../codegen/Bindings.conf.patch | 14 +- .../script_bindings/interfaces.rs.patch | 2 +- patches/components/servo/servo.rs.patch | 28 +++- patches/components/servo/webview.rs.patch | 2 +- .../servo/webview_delegate.rs.patch | 17 +- .../from_script_message.rs.patch | 31 ++-- .../shared/constellation/lib.rs.patch | 6 +- .../shared/embedder/input_events.rs.patch | 8 +- patches/components/shared/script/lib.rs.patch | 12 +- 45 files changed, 436 insertions(+), 332 deletions(-) diff --git a/crates/beaver_shell/src/webdriver.rs b/crates/beaver_shell/src/webdriver.rs index 66ad857..4fc9f97 100644 --- a/crates/beaver_shell/src/webdriver.rs +++ b/crates/beaver_shell/src/webdriver.rs @@ -70,7 +70,7 @@ impl WebDriverState { app_state.request_exit(); }, - WebDriverCommandMsg::GetFocusedWebView(response) => { + WebDriverCommandMsg::GetWebViewSelectedForInteraction(response) => { let _ = response.send(app_state.focused_webview_id_for_webdriver()); }, @@ -132,8 +132,8 @@ impl WebDriverState { let _ = response.send(()); }, - WebDriverCommandMsg::FocusWebView(_id) => { - warn!("WebDriver FocusWebView not yet implemented in beaver"); + WebDriverCommandMsg::SelectWebViewForInteraction(_id) => { + warn!("WebDriver SelectWebViewForInteraction not yet implemented in beaver"); }, WebDriverCommandMsg::SetWindowRect(_id, _rect, response) => { diff --git a/forkme.lock b/forkme.lock index 0219094..0a5d731 100644 --- a/forkme.lock +++ b/forkme.lock @@ -1 +1 @@ -780d95fff867e99e4a618ccb3d5726a14cc69585 +2c70100ad4ef82e2c35908f0f22138358324cb43 diff --git a/patches/Cargo.lock.patch b/patches/Cargo.lock.patch index bf1fdf7..1e9c0ea 100644 --- a/patches/Cargo.lock.patch +++ b/patches/Cargo.lock.patch @@ -477,7 +477,7 @@ name = "quote" version = "1.0.47" source = "registry+https://github.com/rust-lang/crates.io-index" -@@ -7531,6 +7842,56 @@ +@@ -7530,6 +7841,56 @@ checksum = "19b30a45b0cd0bcca8037f3d0dc3421eaf95327a17cad11964fb8179b4fc4832" [[package]] @@ -534,7 +534,7 @@ name = "resvg" version = "0.48.1" source = "registry+https://github.com/rust-lang/crates.io-index" -@@ -7715,6 +8076,7 @@ +@@ -7714,6 +8075,7 @@ "aws-lc-rs", "log", "once_cell", @@ -542,7 +542,7 @@ "rustls-pki-types", "rustls-webpki", "subtle", -@@ -7739,6 +8101,7 @@ +@@ -7738,6 +8100,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2f4925028c7eb5d1fcdaf196971378ed9d2c1c4efc7dc5d011256f76c99c0a96" dependencies = [ @@ -570,7 +570,7 @@ version = "1.0.151" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -8391,6 +8766,7 @@ - "rand 0.10.2", + "rand 0.10.3", "rustc-hash 2.1.3", "serde", + "serde_json", @@ -596,7 +596,7 @@ "async-tungstenite", @@ -9097,6 +9476,7 @@ "quick_cache", - "rand 0.10.2", + "rand 0.10.3", "regex", + "reqwest", "resvg", diff --git a/patches/components/constellation/constellation.rs.patch b/patches/components/constellation/constellation.rs.patch index 692227a..c10dc7c 100644 --- a/patches/components/constellation/constellation.rs.patch +++ b/patches/components/constellation/constellation.rs.patch @@ -254,10 +254,10 @@ + .is_some_and(|webview| webview.hide_focus); + let new_pipeline_info = NewPipelineInfo { + webview_state, parent_info: parent_pipeline_id, - new_pipeline_id, -@@ -1051,6 +1161,13 @@ - embedder_theme: theme, +@@ -1050,6 +1160,13 @@ + user_content_manager_id, target_snapshot_params, frame_name: name, + // Only set is_embedded_webview=true if this browsing context IS the embedded webview itself, @@ -270,7 +270,7 @@ }; let pipeline = match Pipeline::spawn(new_pipeline_info, event_loop, self, webview_hidden) { Ok(pipeline) => pipeline, -@@ -1208,6 +1325,9 @@ +@@ -1207,6 +1324,9 @@ Embedder(EmbedderToConstellationMessage), #[cfg_attr(not(feature = "multiprocess"), expect(unused))] RemoveProcess(usize), @@ -280,7 +280,7 @@ } // Get one incoming request. // This is one of the few places where `Paint` is -@@ -1226,6 +1346,28 @@ +@@ -1225,6 +1345,28 @@ sel.recv(&self.background_hang_monitor_receiver); sel.recv(&self.embedder_to_constellation_receiver); @@ -309,7 +309,7 @@ #[cfg(feature = "multiprocess")] self.process_manager.register(&mut sel); -@@ -1253,9 +1395,30 @@ +@@ -1252,9 +1394,30 @@ oper.recv(&self.embedder_to_constellation_receiver) .expect("Unexpected embedder channel panic in constellation"), )), @@ -341,7 +341,7 @@ #[cfg(feature = "multiprocess")] let _ = oper.recv(self.process_manager.receiver_at(process_index)); Ok(Request::RemoveProcess(process_index)) -@@ -1279,6 +1442,37 @@ +@@ -1278,6 +1441,37 @@ Request::BackgroundHangMonitor(message) => { self.handle_request_from_background_hang_monitor(message); }, @@ -379,7 +379,7 @@ #[cfg(feature = "multiprocess")] Request::RemoveProcess(index) => self.process_manager.remove(index), #[cfg(not(feature = "multiprocess"))] -@@ -1286,6 +1480,32 @@ +@@ -1285,6 +1479,32 @@ } } @@ -412,7 +412,7 @@ #[servo_tracing::instrument(skip_all)] fn handle_request_for_pipeline_namespace(&mut self, request: PipelineNamespaceRequest) { let PipelineNamespaceRequest(sender) = request; -@@ -1370,6 +1590,15 @@ +@@ -1368,6 +1588,15 @@ EmbedderToConstellationMessage::ThemeChange(webview_id, theme) => { self.handle_theme_change(webview_id, theme); }, @@ -428,7 +428,7 @@ EmbedderToConstellationMessage::TickAnimation(webview_ids) => { self.handle_tick_animation(webview_ids) }, -@@ -1388,6 +1617,16 @@ +@@ -1386,6 +1615,16 @@ EmbedderToConstellationMessage::ForwardInputEvent(webview_id, event, hit_test) => { self.forward_input_event(webview_id, event, hit_test); }, @@ -445,7 +445,7 @@ EmbedderToConstellationMessage::RefreshCursor(pipeline_id) => { self.handle_refresh_cursor(pipeline_id) }, -@@ -1437,11 +1676,7 @@ +@@ -1435,11 +1674,7 @@ } }, EmbedderToConstellationMessage::PreferencesUpdated(updates) => { @@ -458,7 +458,7 @@ let _ = event_loop.send(ScriptThreadMessage::PreferencesUpdated( updates .iter() -@@ -1476,6 +1711,18 @@ +@@ -1474,6 +1709,18 @@ EmbedderToConstellationMessage::ClearSessionHistory(webview_id) => { self.handle_clear_session_history(webview_id); }, @@ -477,7 +477,7 @@ } } -@@ -1673,7 +1920,13 @@ +@@ -1671,7 +1918,13 @@ return warn!("Attempt to add channel name from an unexpected origin."); } self.broadcast_channels @@ -492,7 +492,7 @@ }, ScriptToConstellationMessage::RemoveBroadcastChannelNameInRouter( router_id, -@@ -1687,7 +1940,13 @@ +@@ -1685,7 +1938,13 @@ return warn!("Attempt to remove channel name from an unexpected origin."); } self.broadcast_channels @@ -507,7 +507,7 @@ }, ScriptToConstellationMessage::RemoveBroadcastChannelRouter(router_id, origin) => { if self -@@ -1699,6 +1958,12 @@ +@@ -1697,6 +1956,12 @@ self.broadcast_channels .remove_broadcast_channel_router(router_id); }, @@ -520,7 +520,7 @@ ScriptToConstellationMessage::ScheduleBroadcast(router_id, message) => { if self .check_origin_against_pipeline(&source_pipeline_id, &message.origin) -@@ -1708,8 +1973,15 @@ +@@ -1706,8 +1971,15 @@ "Attempt to schedule broadcast from an origin not matching the origin of the msg." ); } @@ -537,7 +537,7 @@ }, ScriptToConstellationMessage::PipelineExited => { self.handle_pipeline_exited(source_pipeline_id, PipelineExitSource::Constellation); -@@ -1729,6 +2001,12 @@ +@@ -1727,6 +1999,12 @@ ScriptToConstellationMessage::CreateAuxiliaryWebView(load_info) => { self.handle_script_new_auxiliary(load_info); }, @@ -550,7 +550,7 @@ ScriptToConstellationMessage::ChangeRunningAnimationsState(animation_state) => { self.handle_change_running_animations_state(source_pipeline_id, animation_state) }, -@@ -1800,7 +2078,7 @@ +@@ -1798,7 +2076,7 @@ ScriptToConstellationMessage::SetFinalUrl(final_url) => { // The script may have finished loading after we already started shutting down. if let Some(ref mut pipeline) = self.pipelines.get_mut(&source_pipeline_id) { @@ -559,7 +559,7 @@ } else { warn!("constellation got set final url message for dead pipeline"); } -@@ -1937,6 +2215,12 @@ +@@ -1935,6 +2213,12 @@ .entry(interest) .or_default() .insert(source_pipeline_id); @@ -572,7 +572,7 @@ }, ScriptToConstellationMessage::UnregisterInterest(interest) => { if let Some(set) = self.pipeline_interests.get_mut(&interest) { -@@ -1962,6 +2246,29 @@ +@@ -1960,6 +2244,29 @@ new_value, ); }, @@ -602,22 +602,21 @@ ScriptToConstellationMessage::MediaSessionEvent(pipeline_id, event) => { // Unlikely at this point, but we may receive events coming from // different media sessions, so we set the active media session based -@@ -1980,8 +2287,13 @@ +@@ -1978,7 +2285,12 @@ }; self.active_media_session = Some(pipeline_id); self.constellation_to_embedder_proxy.send( - ConstellationToEmbedderMsg::MediaSessionEvent(webview_id, event), + ConstellationToEmbedderMsg::MediaSessionEvent(webview_id, event.clone()), - ); ++ ); + // Also route to embedded webview parent iframe. + self.handle_embedded_webview_notification( + webview_id, + EmbeddedWebViewEventType::MediaSessionEvent(event), -+ ); + ); }, #[cfg(feature = "webgpu")] - ScriptToConstellationMessage::RequestAdapter(response_sender, options, ids) => self -@@ -2060,9 +2372,1101 @@ +@@ -2058,7 +2370,1107 @@ } }, }, @@ -720,7 +719,15 @@ + self.handle_media_session_action_msg(action); + }, + ScriptToConstellationMessage::EmbeddedWebViewFocus(embedded_webview_id) => { -+ self.handle_focus_web_view(embedded_webview_id); ++ self.handle_set_has_system_focus(embedded_webview_id, true); ++ // Keep the embedder informed: beaver_shell tracks the focused ++ // webview to route keyboard input (was WebViewFocused, removed ++ // upstream in the system-focus rework). ++ self.constellation_to_embedder_proxy ++ .send(ConstellationToEmbedderMsg::WebViewFocused( ++ embedded_webview_id, ++ true, ++ )); + }, + ScriptToConstellationMessage::EmbeddedWebViewUseSpatialNavigation( + embedded_webview_id, @@ -1388,9 +1395,9 @@ + let _ = callback.send(None); + } + }, - } - } - ++ } ++ } ++ + fn handle_pairing_event(&mut self, event: PairingEvent) { + if let PairingEvent::MessageReceived { ref from, ref data } = event { + debug!("P2P message received from {from}, {} bytes", data.len()); @@ -1683,7 +1690,7 @@ + // Handle peer disconnect: clean up remote channel state. + if let PairingEvent::PeerExpired { ref id } = event { + self.pairing.clear_remote_peer(id); -+ } + } + + // When a paired peer connects or reconnects, sync our open broadcast channels + // to it. @@ -1714,12 +1721,10 @@ + let _ = event_loop.send(ScriptThreadMessage::DispatchPairingEvent(event.clone())); + } + } -+ } -+ + } + /// Check the origin of a message against that of the pipeline it came from. - /// Note: this is still limited as a security check, - /// see -@@ -2379,6 +3783,55 @@ +@@ -2377,6 +3789,55 @@ TransferState::TransferInProgress(queue) => queue.push_back(task), TransferState::CompletionFailed(queue) => queue.push_back(task), TransferState::CompletionRequested(_, queue) => queue.push_back(task), @@ -1775,7 +1780,7 @@ } } -@@ -3235,6 +4688,101 @@ +@@ -3249,6 +4710,101 @@ self.notify_history_changed(webview_id); } @@ -1877,7 +1882,7 @@ fn forward_input_event( &mut self, webview_id: WebViewId, -@@ -3254,6 +4802,66 @@ +@@ -3268,6 +4824,66 @@ let pressed_mouse_buttons = self.pressed_mouse_buttons; let active_keyboard_modifiers = self.active_keyboard_modifiers; @@ -1944,7 +1949,7 @@ let event_id = event.id; let Some(webview) = self.webviews.get_mut(&webview_id) else { warn!("Got input event for unknown WebViewId: {webview_id:?}"); -@@ -3352,6 +4960,40 @@ +@@ -3366,6 +4982,40 @@ /// fn handle_close_top_level_browsing_context(&mut self, webview_id: WebViewId) { debug!("{webview_id}: Closing"); @@ -1985,7 +1990,7 @@ let browsing_context_id = BrowsingContextId::from(webview_id); // Step 5. Remove traversable from the user agent's top-level traversable set. let browsing_context = -@@ -3656,8 +5298,27 @@ +@@ -3670,8 +5320,27 @@ opener_webview_id, opener_pipeline_id, response_sender, @@ -2013,7 +2018,7 @@ let Some((webview_id_sender, webview_id_receiver)) = generic_channel::channel() else { warn!("Failed to create channel"); let _ = response_sender.send(None); -@@ -3756,6 +5417,407 @@ +@@ -3779,6 +5448,407 @@ .insert(new_webview_id); } @@ -2123,26 +2128,26 @@ + .cross_process_paint_api + .register_embedded_webview(new_webview_id); + -+ self.webviews.insert( ++ let mut new_webview = ConstellationWebView::new_with_hide_focus( + new_webview_id, -+ ConstellationWebView::new_with_hide_focus( -+ new_webview_id, -+ new_browsing_context_id, -+ user_content_manager_id, -+ hide_focus, -+ ), ++ new_browsing_context_id, ++ user_content_manager_id, ++ hide_focus, + ); ++ // Embedded webviews inherit their parent's theme. ++ new_webview.set_theme(theme); ++ let webview_state = new_webview.state(); ++ self.webviews.insert(new_webview_id, new_webview); + + let new_pipeline_info = NewPipelineInfo { ++ webview_state, + parent_info: Some(parent_pipeline_id), + new_pipeline_id, + browsing_context_id: new_browsing_context_id, -+ webview_id: new_webview_id, + opener: None, + load_data, + viewport_details, + user_content_manager_id, -+ embedder_theme: theme, + target_snapshot_params: TargetSnapshotParams::default(), + frame_name: Default::default(), + is_embedded_webview: true, @@ -2421,7 +2426,7 @@ #[servo_tracing::instrument(skip_all)] fn handle_refresh_cursor(&self, pipeline_id: PipelineId) { let Some(pipeline) = self.pipelines.get(&pipeline_id) else { -@@ -4714,7 +6776,7 @@ +@@ -4737,7 +6807,7 @@ }, }; @@ -2430,7 +2435,7 @@ match self.browsing_contexts.get_mut(&browsing_context_id) { Some(browsing_context) => { let old_pipeline_id = browsing_context.pipeline_id; -@@ -4723,6 +6785,7 @@ +@@ -4746,6 +6816,7 @@ old_pipeline_id, browsing_context.parent_pipeline_id, browsing_context.webview_id, @@ -2438,7 +2443,7 @@ ) }, None => { -@@ -4733,6 +6796,15 @@ +@@ -4756,6 +6827,15 @@ self.unload_document(old_pipeline_id); @@ -2454,7 +2459,34 @@ if let Some(new_pipeline) = self.pipelines.get_mut(&new_pipeline_id) { if let Some(ref chan) = self.devtools_sender { let state = NavigationState::Start(new_pipeline.url.clone()); -@@ -5291,7 +7363,7 @@ +@@ -4982,10 +7062,10 @@ + focused_child_browsing_context_id: Option, + sequence: FocusSequenceNumber, + ) { +- let browsing_context_id = match self.pipelines.get_mut(&pipeline_id) { ++ let (browsing_context_id, webview_id) = match self.pipelines.get_mut(&pipeline_id) { + Some(pipeline) => { + pipeline.focus_sequence = sequence; +- pipeline.browsing_context_id ++ (pipeline.browsing_context_id, pipeline.webview_id) + }, + None => return warn!("{}: Focus parent after closure", pipeline_id), + }; +@@ -5000,6 +7080,13 @@ + return; + } + ++ // Beaver: notify the embedder that this webview took focus through a ++ // content-initiated focus chain. beaver_shell tracks this to route ++ // keyboard input to the right webview. Upstream removed this ++ // notification when moving to embedder-driven system focus. ++ self.constellation_to_embedder_proxy ++ .send(ConstellationToEmbedderMsg::WebViewFocused(webview_id, true)); ++ + // If a container with a non-null nested browsing context is focused, + // the nested browsing context's active document becomes the focused + // area of the top-level browsing context instead. +@@ -5310,7 +7397,7 @@ } #[servo_tracing::instrument(skip_all)] @@ -2463,7 +2495,7 @@ // Send a flat projection of the history to embedder. // The final vector is a concatenation of the URLs of the past // entries, the current entry and the future entries. -@@ -5403,9 +7475,22 @@ +@@ -5422,9 +7509,22 @@ self.constellation_to_embedder_proxy .send(ConstellationToEmbedderMsg::HistoryChanged( webview_id, @@ -2487,7 +2519,7 @@ } #[servo_tracing::instrument(skip_all)] -@@ -5424,7 +7509,7 @@ +@@ -5443,7 +7543,7 @@ webview.focused_browsing_context_id = change.browsing_context_id; } @@ -2496,7 +2528,7 @@ match self.browsing_contexts.get_mut(&change.browsing_context_id) { Some(browsing_context) => { debug!("Adding pipeline to existing browsing context."); -@@ -5431,11 +7516,15 @@ +@@ -5450,11 +7550,15 @@ let old_pipeline_id = browsing_context.pipeline_id; browsing_context.pipelines.insert(change.new_pipeline_id); browsing_context.update_current_entry(change.new_pipeline_id); @@ -2514,7 +2546,7 @@ }, }; -@@ -5443,6 +7532,18 @@ +@@ -5462,6 +7566,18 @@ self.unload_document(old_pipeline_id); } diff --git a/patches/components/constellation/constellation_webview.rs.patch b/patches/components/constellation/constellation_webview.rs.patch index 97a014d..d486fb5 100644 --- a/patches/components/constellation/constellation_webview.rs.patch +++ b/patches/components/constellation/constellation_webview.rs.patch @@ -1,6 +1,6 @@ --- original +++ modified -@@ -95,6 +95,11 @@ +@@ -101,6 +101,11 @@ /// ready to take place, at which point the Constellation informs the renderer that it /// can start the process of taking the screenshot. screenshot_readiness_requests: Vec, @@ -12,7 +12,7 @@ } impl ConstellationWebView { -@@ -103,6 +108,20 @@ +@@ -109,6 +114,20 @@ focused_browsing_context_id: BrowsingContextId, user_content_manager_id: Option, ) -> Self { @@ -33,15 +33,15 @@ Self { webview_id, user_content_manager_id, -@@ -120,6 +139,7 @@ - hidden: false, +@@ -127,6 +146,7 @@ + has_system_focus: true, accessibility_active: false, screenshot_readiness_requests: Default::default(), + hide_focus, } } -@@ -150,12 +170,41 @@ +@@ -175,12 +195,41 @@ event: &ConstellationInputEvent, browsing_contexts: &FxHashMap, ) -> Option { @@ -85,7 +85,7 @@ let browsing_context_id = if matches!(event.event.event, InputEvent::MouseLeftViewport(_)) { self.hovered_browsing_context_id .unwrap_or(self.focused_browsing_context_id) -@@ -225,11 +274,9 @@ +@@ -250,11 +299,9 @@ if let InputEvent::MouseMove(_) = &event.event.event { update_hovered_browsing_context(Some(pipeline.browsing_context_id), true); diff --git a/patches/components/constellation/embedder.rs.patch b/patches/components/constellation/embedder.rs.patch index e66ba1a..0255aed 100644 --- a/patches/components/constellation/embedder.rs.patch +++ b/patches/components/constellation/embedder.rs.patch @@ -11,7 +11,7 @@ use servo_url::ServoUrl; /// Messages sent from the `Constellation` to the embedder. -@@ -45,4 +46,13 @@ +@@ -40,4 +41,19 @@ AllowNavigationRequest(WebViewId, PipelineId, ServoUrl), /// The history state has changed. HistoryChanged(WebViewId, Vec, usize), @@ -24,4 +24,10 @@ + ContentBlockerSetOriginEnabled(String, bool, GenericCallback>), + /// Content blocker: reset counts. + ContentBlockerResetCounts(String, GenericCallback>), ++ /// A `WebView` gained or lost focus through a script-initiated focus request ++ /// (an embedded webview's `forceFocus()`, or a content-initiated focus chain ++ /// reaching the top-level browsing context). Beaver addition: upstream ++ /// removed this when moving to embedder-driven system focus, but beaver_shell ++ /// needs it to track which webview receives keyboard input. ++ WebViewFocused(WebViewId, bool), } diff --git a/patches/components/constellation/tracing.rs.patch b/patches/components/constellation/tracing.rs.patch index 5be5020..708c92b 100644 --- a/patches/components/constellation/tracing.rs.patch +++ b/patches/components/constellation/tracing.rs.patch @@ -8,16 +8,16 @@ Self::TickAnimation(..) => target!("TickAnimation"), Self::WebDriverCommand(..) => target!("WebDriverCommand"), Self::Reload(..) => target!("Reload"), -@@ -64,6 +65,8 @@ - Self::FocusWebView(..) => target!("FocusWebView"), - Self::BlurWebView => target!("BlurWebView"), +@@ -63,6 +64,8 @@ + Self::CloseWebView(..) => target!("CloseWebView"), + Self::SetWebViewHasSystemFocus(..) => target!("SetWebViewHasSystemFocus"), Self::ForwardInputEvent(_webview_id, event, ..) => event.log_target(), + Self::NotifyUserIdleTime(..) => target!("NotifyUserIdleTime"), + Self::NotifyScreenLocked(..) => target!("NotifyScreenLocked"), Self::RefreshCursor(..) => target!("RefreshCursor"), Self::ExitFullScreen(_) => target!("ExitFullScreen"), Self::MediaSessionAction(_) => target!("MediaSessionAction"), -@@ -83,6 +86,7 @@ +@@ -82,6 +85,7 @@ Self::UpdatePinchZoomInfos(..) => target!("UpdatePinchZoomInfos"), Self::SetAccessibilityActive(..) => target!("SetAccessibilityActive"), Self::ClearSessionHistory(..) => target!("ClearHistory"), @@ -25,7 +25,7 @@ } } } -@@ -134,6 +138,10 @@ +@@ -133,6 +137,10 @@ Self::DisentanglePorts(..) => target!("DisentanglePorts"), Self::NewBroadcastChannelRouter(..) => target!("NewBroadcastChannelRouter"), Self::RemoveBroadcastChannelRouter(..) => target!("RemoveBroadcastChannelRouter"), @@ -36,7 +36,7 @@ Self::NewBroadcastChannelNameInRouter(..) => { target!("NewBroadcastChannelNameInRouter") }, -@@ -144,6 +152,7 @@ +@@ -143,6 +151,7 @@ Self::RegisterInterest(..) => target!("RegisterInterest"), Self::UnregisterInterest(..) => target!("UnregisterInterest"), Self::BroadcastStorageEvent(..) => target!("BroadcastStorageEvent"), @@ -44,7 +44,7 @@ Self::ChangeRunningAnimationsState(..) => target!("ChangeRunningAnimationsState"), Self::RegisterWorkerAnimationFrameProvider(..) => { target!("RegisterWorkerAnimationFrameProvider") -@@ -166,6 +175,8 @@ +@@ -165,6 +174,8 @@ Self::GetDocumentOriginDetails(..) => { target!("GetDocumentOriginDetails") }, @@ -53,7 +53,7 @@ Self::GetChildBrowsingContextId(..) => target!("GetChildBrowsingContextId"), Self::LoadComplete => target!("LoadComplete"), Self::LoadUrl(..) => target!("LoadUrl"), -@@ -180,6 +191,8 @@ +@@ -179,6 +190,8 @@ Self::ScriptLoadedURLInIFrame(..) => target!("ScriptLoadedURLInIFrame"), Self::ScriptNewIFrame(..) => target!("ScriptNewIFrame"), Self::CreateAuxiliaryWebView(..) => target!("ScriptNewAuxiliary"), @@ -62,7 +62,7 @@ Self::ActivateDocument => target!("ActivateDocument"), Self::SetFinalUrl(..) => target!("SetFinalUrl"), Self::LogEntry(..) => target!("LogEntry"), -@@ -203,6 +216,85 @@ +@@ -202,6 +215,85 @@ Self::TriggerGarbageCollection => target!("TriggerGarbageCollection"), Self::AcquireWakeLock(..) => target!("AcquireWakeLock"), Self::ReleaseWakeLock(..) => target!("ReleaseWakeLock"), diff --git a/patches/components/layout/display_list/mod.rs.patch b/patches/components/layout/display_list/mod.rs.patch index fc8e50a..9591629 100644 --- a/patches/components/layout/display_list/mod.rs.patch +++ b/patches/components/layout/display_list/mod.rs.patch @@ -21,10 +21,10 @@ }; use wr::units::LayoutVector2D; -@@ -134,6 +135,10 @@ - - /// The background color used for the shell. - shell_background_color: AbsoluteColor, +@@ -145,6 +146,10 @@ + /// Whether or not the `WebView` this display list is being rendered for has system focus + /// and is the focused frame in the frame tree. + frame_focused: bool, + + /// For embedded webviews with page zoom, this is the SpatialId of the zoom reference frame. + /// When present, this is used as the root spatial ID instead of root_reference_frame. @@ -32,7 +32,7 @@ } struct InspectorHighlight { -@@ -213,6 +218,34 @@ +@@ -225,6 +230,34 @@ .into_srgb_legacy() }; @@ -67,15 +67,15 @@ let _span = profile_traits::trace_span!("DisplayListBuilder::build").entered(); let mut builder = DisplayListBuilder { fragment_tree, -@@ -228,6 +261,7 @@ - reflow_statistics, +@@ -241,6 +274,7 @@ largest_contentful_paint_enabled: pref!(largest_contentful_paint_enabled), shell_background_color, + frame_focused, + zoom_reference_frame_spatial_id, }; // Clear any caret color from previous display list constructions. -@@ -244,10 +278,15 @@ +@@ -257,10 +291,15 @@ let pipeline_id = builder.paint_info.pipeline_id; let viewport_size = builder.paint_info.viewport_details.size; let viewport_rect = LayoutRect::from_size(viewport_size.cast_unit()); @@ -92,7 +92,7 @@ PrimitiveFlags::default(), (0, 0), /* tag */ ); -@@ -255,6 +294,11 @@ +@@ -268,6 +307,11 @@ PaintTraversal::traverse(&stacking_context_tree.root_stacking_context, &mut builder); builder.paint_dom_inspector_highlight(); @@ -104,7 +104,7 @@ webrender_display_list_builder.end().1 } -@@ -289,15 +333,40 @@ +@@ -302,15 +346,40 @@ } pub(crate) fn add_all_spatial_nodes(&mut self) { @@ -150,7 +150,7 @@ for node in scroll_tree.nodes.iter().skip(2) { let parent_scroll_node_id = node .parent -@@ -1630,6 +1699,34 @@ +@@ -1638,6 +1707,34 @@ .translate(self.containing_block_origin.to_vector()) .to_webrender(), ); diff --git a/patches/components/layout/dom.rs.patch b/patches/components/layout/dom.rs.patch index 090f379..dc8b6dd 100644 --- a/patches/components/layout/dom.rs.patch +++ b/patches/components/layout/dom.rs.patch @@ -1,6 +1,6 @@ --- original +++ modified -@@ -518,6 +518,7 @@ +@@ -538,6 +538,7 @@ (Some(pipeline_id), Some(browsing_context_id)) => Some(IFrameInfo { pipeline_id, browsing_context_id, diff --git a/patches/components/paint/painter.rs.patch b/patches/components/paint/painter.rs.patch index c902dfb..fedb126 100644 --- a/patches/components/paint/painter.rs.patch +++ b/patches/components/paint/painter.rs.patch @@ -439,7 +439,7 @@ } pub(crate) fn remove_webview(&mut self, webview_id: WebViewId) { -@@ -1452,7 +1749,6 @@ +@@ -1458,7 +1755,6 @@ result: InputEventResult, ) { let Some(webview_renderer) = self.webview_renderers.get_mut(&webview_id) else { diff --git a/patches/components/script/dom/atproto.rs.patch b/patches/components/script/dom/atproto.rs.patch index fec54d7..00f57ad 100644 --- a/patches/components/script/dom/atproto.rs.patch +++ b/patches/components/script/dom/atproto.rs.patch @@ -86,7 +86,7 @@ +impl AtProto { + fn request(&self, cx: &mut JSContext, request: AtProtoRequest) -> RootedPromise { + let global = &self.global(); -+ let promise = Promise::new_rooted(cx, global); ++ let promise = Promise::new(cx, global); + let task_manager = global.task_manager(); + let task_source = task_manager.dom_manipulation_task_source(); + let callback = callback_promise(&promise, self, task_source); diff --git a/patches/components/script/dom/brightnessdevice.rs.patch b/patches/components/script/dom/brightnessdevice.rs.patch index d9dbc96..fb09b4e 100644 --- a/patches/components/script/dom/brightnessdevice.rs.patch +++ b/patches/components/script/dom/brightnessdevice.rs.patch @@ -87,7 +87,7 @@ + /// TODO: replace by an "onchange" event. + fn Read(&self, cx: &mut JSContext) -> RootedPromise { + let global = &self.global(); -+ let promise = Promise::new_rooted(cx, global); ++ let promise = Promise::new(cx, global); + let task_manager = global.task_manager(); + let task_source = task_manager.dom_manipulation_task_source(); + let callback = callback_promise(&promise, self, task_source); diff --git a/patches/components/script/dom/contentblocker.rs.patch b/patches/components/script/dom/contentblocker.rs.patch index 9a7ce39..582283c 100644 --- a/patches/components/script/dom/contentblocker.rs.patch +++ b/patches/components/script/dom/contentblocker.rs.patch @@ -39,7 +39,7 @@ +impl ContentBlockerMethods for ContentBlocker { + fn GetOriginState(&self, cx: &mut JSContext, origin: USVString) -> RootedPromise { + let global = &self.global(); -+ let promise = Promise::new_rooted(cx, global); ++ let promise = Promise::new(cx, global); + let task_manager = global.task_manager(); + let task_source = task_manager.dom_manipulation_task_source(); + let callback = callback_promise(&promise, self, task_source); @@ -63,7 +63,7 @@ + enabled: bool, + ) -> RootedPromise { + let global = &self.global(); -+ let promise = Promise::new_rooted(cx, global); ++ let promise = Promise::new(cx, global); + let task_manager = global.task_manager(); + let task_source = task_manager.dom_manipulation_task_source(); + let callback = callback_promise(&promise, self, task_source); @@ -84,7 +84,7 @@ + + fn ResetCounts(&self, cx: &mut JSContext, origin: USVString) -> RootedPromise { + let global = &self.global(); -+ let promise = Promise::new_rooted(cx, global); ++ let promise = Promise::new(cx, global); + let task_manager = global.task_manager(); + let task_source = task_manager.dom_manipulation_task_source(); + let callback = callback_promise(&promise, self, task_source); diff --git a/patches/components/script/dom/dbus.rs.patch b/patches/components/script/dom/dbus.rs.patch index f1b1dc0..4fb88bb 100644 --- a/patches/components/script/dom/dbus.rs.patch +++ b/patches/components/script/dom/dbus.rs.patch @@ -1,6 +1,6 @@ --- original +++ modified -@@ -0,0 +1,290 @@ +@@ -0,0 +1,285 @@ +/* SPDX Id: AGPL-3.0-or-later */ + +use dom_struct::dom_struct; @@ -10,7 +10,6 @@ +use js::rust::HandleValue; +use script_bindings::error::Error; +use script_bindings::reflector::reflect_dom_object_with_cx; -+use script_bindings::trace::RootedTraceableBox; +use servo_constellation_traits::{DbusSignalEvent, DbusValue, ScriptToConstellationMessage}; + +use crate::dom::bindings::codegen::Bindings::CustomEventBinding::CustomEventMethods; @@ -71,13 +70,9 @@ +} + +impl DBusMethods for DBus { -+ fn Call( -+ &self, -+ cx: &mut JSContext, -+ options: RootedTraceableBox, -+ ) -> RootedPromise { ++ fn Call(&self, cx: &mut JSContext, options: &DBusCallOptions) -> RootedPromise { + let global = &self.global(); -+ let promise = Promise::new_rooted(cx, global); ++ let promise = Promise::new(cx, global); + let task_manager = global.task_manager(); + let task_source = task_manager.dom_manipulation_task_source(); + let callback = callback_promise(&promise, self, task_source); @@ -109,7 +104,7 @@ + + fn GetProperty(&self, cx: &mut JSContext, options: &DBusPropertyOptions) -> RootedPromise { + let global = &self.global(); -+ let promise = Promise::new_rooted(cx, global); ++ let promise = Promise::new(cx, global); + let task_manager = global.task_manager(); + let task_source = task_manager.dom_manipulation_task_source(); + let callback = callback_promise(&promise, self, task_source); @@ -138,7 +133,7 @@ + value: HandleValue, + ) -> RootedPromise { + let global = &self.global(); -+ let promise = Promise::new_rooted(cx, global); ++ let promise = Promise::new(cx, global); + let task_manager = global.task_manager(); + let task_source = task_manager.dom_manipulation_task_source(); + let callback = callback_promise(&promise, self, task_source); @@ -165,7 +160,7 @@ + + fn Subscribe(&self, cx: &mut JSContext, options: &DBusSignalOptions) -> RootedPromise { + let global = &self.global(); -+ let promise = Promise::new_rooted(cx, global); ++ let promise = Promise::new(cx, global); + let task_manager = global.task_manager(); + let task_source = task_manager.dom_manipulation_task_source(); + let callback = callback_promise(&promise, self, task_source); @@ -195,7 +190,7 @@ + + fn Unsubscribe(&self, cx: &mut JSContext, subscription_id: u32) -> RootedPromise { + let global = &self.global(); -+ let promise = Promise::new_rooted(cx, global); ++ let promise = Promise::new(cx, global); + let task_manager = global.task_manager(); + let task_source = task_manager.dom_manipulation_task_source(); + let callback = callback_promise(&promise, self, task_source); diff --git a/patches/components/script/dom/document/document.rs.patch b/patches/components/script/dom/document/document.rs.patch index dc427fc..772283a 100644 --- a/patches/components/script/dom/document/document.rs.patch +++ b/patches/components/script/dom/document/document.rs.patch @@ -24,7 +24,7 @@ }; use servo_media::{ClientContextId, ServoMedia}; use servo_url::{ImmutableOrigin, MutableOrigin, ServoUrl}; -@@ -103,6 +105,8 @@ +@@ -104,6 +106,8 @@ use crate::dom::bindings::codegen::Bindings::EventBinding::Event_Binding::EventMethods; use crate::dom::bindings::codegen::Bindings::HTMLElementBinding::HTMLElementMethods; use crate::dom::bindings::codegen::Bindings::HTMLIFrameElementBinding::HTMLIFrameElement_Binding::HTMLIFrameElementMethods; @@ -33,7 +33,7 @@ #[cfg(any(feature = "webxr", feature = "gamepad"))] use crate::dom::bindings::codegen::Bindings::NavigatorBinding::Navigator_Binding::NavigatorMethods; use crate::dom::bindings::codegen::Bindings::NodeBinding::NodeMethods; -@@ -182,6 +186,7 @@ +@@ -183,6 +187,7 @@ use crate::dom::html::htmlscriptelement::{HTMLScriptElement, ScriptResult}; use crate::dom::html::htmltitleelement::HTMLTitleElement; use crate::dom::htmldetailselement::DetailsNameGroups; @@ -41,7 +41,7 @@ use crate::dom::intersectionobserver::IntersectionObserver; use crate::dom::iterators::ShadowIncluding; use crate::dom::keyboardevent::KeyboardEvent; -@@ -211,7 +216,9 @@ +@@ -212,7 +217,9 @@ use crate::dom::touchevent::TouchEvent as DomTouchEvent; use crate::dom::touchlist::TouchList; use crate::dom::trustedtypes::trustedhtml::TrustedHTML; @@ -52,7 +52,7 @@ use crate::dom::uievent::UIEvent; use crate::dom::window::Window; use crate::dom::window::scrolling_box::{ScrollAxisState, ScrollingBox}; -@@ -231,6 +238,7 @@ +@@ -232,6 +239,7 @@ use crate::tasks::task::NonSendTaskBox; use crate::tasks::task_manager::TaskManager; use crate::tasks::task_source::TaskSourceName; @@ -60,7 +60,7 @@ use crate::xpath::parse_expression; #[derive(Clone, Copy, PartialEq)] -@@ -441,6 +449,8 @@ +@@ -446,6 +454,8 @@ applets: MutNullableDom, /// Information about the `` in this [`Document`]. iframes: RefCell, @@ -69,7 +69,7 @@ /// Shared locks used for style attributes, author-origin stylesheets, and user and /// user agent stylesheets in this document. Can be acquired once for accessing many /// objects. This is shared with the owning [`ScriptThread`]. -@@ -602,6 +612,14 @@ +@@ -607,6 +617,14 @@ /// - /// - resize_observers: DomRefCell>>, @@ -84,7 +84,7 @@ /// The set of all fonts loaded by this document. /// fonts: MutNullableDom, -@@ -685,6 +703,9 @@ +@@ -690,6 +708,9 @@ #[no_trace] favicon: RefCell>, @@ -94,7 +94,7 @@ /// All websockets created that are associated with this document. websockets: DOMTracker, -@@ -698,6 +719,18 @@ +@@ -703,6 +724,18 @@ /// Reflect the value of that preferences to prevent paying the cost of a RwLock access. layout_animations_test_enabled: bool, @@ -113,7 +113,7 @@ /// #[no_trace] state_override: DomRefCell>, -@@ -765,6 +798,11 @@ +@@ -774,6 +807,11 @@ /// #[ignore_malloc_size_of = "mozjs"] module_map: DomRefCell>, @@ -125,7 +125,7 @@ } impl Document { -@@ -998,6 +1036,68 @@ +@@ -1007,6 +1045,68 @@ self.dirty_root.take() } @@ -194,7 +194,7 @@ #[inline] pub(crate) fn loader(&self) -> Ref<'_, DocumentLoader> { self.loader.borrow() -@@ -1082,6 +1182,12 @@ +@@ -1091,6 +1191,12 @@ // Set the document's activity level, reflow if necessary, and suspend or resume timers. self.activity.set(activity); @@ -207,7 +207,7 @@ let media = ServoMedia::get(); let pipeline_id = self.window().pipeline_id(); let client_context_id = -@@ -1101,6 +1207,7 @@ +@@ -1110,6 +1216,7 @@ self.title_changed(); self.notify_embedder_favicon(); @@ -215,7 +215,7 @@ self.dirty_all_nodes(cx.no_gc()); self.window().resume(cx); media.resume(&client_context_id); -@@ -1517,6 +1624,9 @@ +@@ -1545,6 +1652,9 @@ webview_id, LoadStatus::Started, )); @@ -225,7 +225,7 @@ self.send_to_embedder(EmbedderMsg::Status(webview_id, None)); } -@@ -1548,6 +1658,10 @@ +@@ -1576,6 +1686,10 @@ // avoid code duplication. self.notify_embedder_of_load_completion(); @@ -236,7 +236,7 @@ // Step 3.2: If readinessValue is "complete", and document's load timing info's // DOM complete time is 0, then set document's load timing info's DOM complete // time to now. -@@ -1634,7 +1748,12 @@ +@@ -1662,7 +1776,12 @@ let window = self.window(); if window.is_top_level() { let title = self.title().map(String::from); @@ -250,7 +250,7 @@ } } -@@ -1643,6 +1762,17 @@ +@@ -1671,6 +1790,17 @@ window.send_to_embedder(msg); } @@ -268,7 +268,7 @@ pub(crate) fn dirty_all_nodes(&self, no_gc: &NoGC) { let root = match self.GetDocumentElement() { Some(root) => root, -@@ -3038,6 +3168,17 @@ +@@ -3071,6 +3201,17 @@ self.iframes.borrow_mut() } @@ -286,7 +286,7 @@ pub(crate) fn set_navigation_start(&self, navigation_start: CrossProcessInstant) { self.interactive_time .borrow_mut() -@@ -3355,6 +3496,60 @@ +@@ -3388,6 +3529,60 @@ .push(Dom::from_ref(resize_observer)); } @@ -347,7 +347,7 @@ /// /// pub(crate) fn gather_active_resize_observations_at_depth( -@@ -4041,6 +4236,7 @@ +@@ -4086,6 +4281,7 @@ anchors: Default::default(), applets: Default::default(), iframes: RefCell::new(IFrameCollection::new()), @@ -355,7 +355,7 @@ shared_style_locks, stylesheets: DomRefCell::new(DocumentStylesheetSet::new()), stylesheet_list: MutNullableDom::new(None), -@@ -4102,6 +4298,8 @@ +@@ -4147,6 +4343,8 @@ dirty_root: Default::default(), declarative_refresh: Default::default(), resize_observers: Default::default(), @@ -364,7 +364,7 @@ fonts: Default::default(), // TODO: This is intended to workaround the issue where `visibilityState` // is always hidden. This should really be hooked with system visibility -@@ -4128,10 +4326,12 @@ +@@ -4173,10 +4371,12 @@ active_sandboxing_flag_set: Cell::new(creation_sandboxing_flag_set), creation_sandboxing_flag_set: Cell::new(creation_sandboxing_flag_set), favicon: RefCell::new(None), @@ -377,7 +377,7 @@ state_override: Default::default(), value_override: Default::default(), default_single_line_container_name: Default::default(), -@@ -4153,6 +4353,7 @@ +@@ -4199,6 +4399,7 @@ window_detached: Default::default(), live_ranges: Default::default(), module_map: Default::default(), @@ -385,7 +385,7 @@ } } -@@ -4912,6 +5113,33 @@ +@@ -4958,6 +5159,33 @@ .mark_animating_nodes_as_dirty(no_gc, current_timeline_value); } @@ -419,7 +419,7 @@ pub(crate) fn current_animation_timeline_value(&self) -> f64 { self.timeline .upcast::() -@@ -4966,10 +5194,8 @@ +@@ -5012,10 +5240,8 @@ /// An implementation of . pub(crate) fn update_animations_and_send_events(&self, cx: &mut CurrentRealm) { @@ -432,7 +432,7 @@ // > 1. Update the current time of all timelines associated with doc passing now // > as the timestamp. -@@ -5212,6 +5438,36 @@ +@@ -5258,6 +5484,36 @@ pub(crate) fn notify_embedder_favicon(&self) { if let Some(ref image) = *self.favicon.borrow() { @@ -469,9 +469,9 @@ self.send_to_embedder(EmbedderMsg::NewFavicon(self.webview_id(), image.clone())); } } -@@ -5307,6 +5563,30 @@ - pub(crate) fn set_default_language(&self, new_language: Option) { - *self.default_language.borrow_mut() = new_language; +@@ -5371,6 +5627,30 @@ + self.CreateElement(cx, name.into(), element_options) + .expect("Must always be able to create element") } + + /// Whether spatial navigation is enabled for this document. diff --git a/patches/components/script/dom/document/document_embedder_controls.rs.patch b/patches/components/script/dom/document/document_embedder_controls.rs.patch index 491737e..d405064 100644 --- a/patches/components/script/dom/document/document_embedder_controls.rs.patch +++ b/patches/components/script/dom/document/document_embedder_controls.rs.patch @@ -4,13 +4,12 @@ use std::cell::Cell; use embedder_traits::{ -- ContextMenuAction, ContextMenuElementInformation, ContextMenuElementInformationFlags, -- ContextMenuItem, ContextMenuRequest, EditingActionEvent, EmbedderControlId, +- ClipboardAction, ContextMenuAction, ContextMenuElementInformation, ++ AllowOrDeny, ClipboardAction, ContextMenuAction, ContextMenuElementInformation, + ContextMenuElementInformationFlags, ContextMenuItem, ContextMenuRequest, EmbedderControlId, - EmbedderControlRequest, EmbedderControlResponse, EmbedderMsg, -+ AllowOrDeny, ContextMenuAction, ContextMenuElementInformation, -+ ContextMenuElementInformationFlags, ContextMenuItem, ContextMenuRequest, EditingActionEvent, -+ EmbedderControlId, EmbedderControlRequest, EmbedderControlResponse, EmbedderMsg, -+ PermissionFeature, PermissionPromptRequest, SimpleDialogRequest, ++ EmbedderControlRequest, EmbedderControlResponse, EmbedderMsg, PermissionFeature, ++ PermissionPromptRequest, SimpleDialogRequest, }; use euclid::{Point2D, Rect, Size2D}; use js::context::{JSContext, NoGC}; @@ -153,12 +152,10 @@ }, } } -@@ -190,12 +233,67 @@ +@@ -190,10 +233,65 @@ pipeline_id: self.window.pipeline_id(), index: index.0, }; -- self.window -- .send_to_embedder(EmbedderMsg::HideEmbedderControl(id)); + // If this is an embedded webview, route the hide request to the parent + // iframe element via the Constellation. Otherwise, send directly to the embedder. + if self.window.as_global_scope().is_embedded_webview() { @@ -179,10 +176,10 @@ + ); + } + } - false - }); - } - ++ false ++ }); ++ } ++ + /// Hide all visible embedder controls. This is called when the document becomes inactive + /// (e.g., when navigating to a new page) to ensure controls like the virtual keyboard + /// are hidden. @@ -206,8 +203,10 @@ + ), + ); + } else { -+ self.window -+ .send_to_embedder(EmbedderMsg::HideEmbedderControl(id)); + self.window + .send_to_embedder(EmbedderMsg::HideEmbedderControl(id)); +- false +- }); + } + } + // Also notify constellation to clear IME tracking if we had an Ime control @@ -218,11 +217,9 @@ + )); + } + self.visible_elements.borrow_mut().clear(); -+ } -+ + } + pub(crate) fn handle_embedder_control_response( - &self, - cx: &mut JSContext, @@ -241,6 +339,10 @@ ) => { context_menu_nodes.handle_context_menu_action(action, cx); diff --git a/patches/components/script/dom/document/document_event_handler.rs.patch b/patches/components/script/dom/document/document_event_handler.rs.patch index fb1c89b..d679162 100644 --- a/patches/components/script/dom/document/document_event_handler.rs.patch +++ b/patches/components/script/dom/document/document_event_handler.rs.patch @@ -1,6 +1,6 @@ --- original +++ modified -@@ -10,10 +10,11 @@ +@@ -9,10 +9,11 @@ use std::time::{Duration, Instant}; use embedder_traits::{ @@ -16,7 +16,7 @@ }; #[cfg(feature = "gamepad")] use embedder_traits::{ -@@ -39,21 +40,26 @@ +@@ -39,22 +40,27 @@ use script_bindings::root::{Dom, DomRoot, DomSlice}; use script_bindings::str::DOMString; use script_traits::{ConstellationInputEvent, MouseButtons}; @@ -39,13 +39,14 @@ use crate::dom::bindings::root::MutNullableDom; use crate::dom::bindings::trace::NoTrace; -use crate::dom::document::FireMouseEventType; + use crate::dom::document::editing::editing_action_from_keyboard_event; use crate::dom::document::focus::FocusableArea; use crate::dom::document::interactive_element_command::InteractiveElementCommand; +use crate::dom::document::{Document, FireMouseEventType}; use crate::dom::event::{EventBubbles, EventCancelable, EventComposed, EventFlags}; #[cfg(feature = "gamepad")] use crate::dom::gamepad::gamepad::{Gamepad, contains_user_gesture}; -@@ -66,12 +72,14 @@ +@@ -67,12 +73,14 @@ use crate::dom::node::{self, Node, NodeTraits}; use crate::dom::pointerevent::{PointerEvent, PointerId}; use crate::dom::types::{ @@ -62,7 +63,7 @@ use crate::realms::enter_auto_realm; /// A data structure used for tracking the current click count. This can be -@@ -136,6 +144,56 @@ +@@ -137,6 +145,56 @@ } } @@ -119,7 +120,7 @@ /// The [`DocumentEventHandler`] is a structure responsible for handling input events for /// the [`crate::Document`] and storing data related to event handling. It exists to /// decrease the size of the [`crate::Document`] structure. -@@ -207,6 +265,20 @@ +@@ -208,6 +266,20 @@ /// The current drag gesture, if one exists. Events that affect this drag /// gesture will be forwarded to it. drag_gesture: DomRefCell>, @@ -140,7 +141,7 @@ } impl DocumentEventHandler { -@@ -234,6 +306,9 @@ +@@ -235,6 +307,9 @@ pending_pointer_capture: Default::default(), pointer_capture_target: Default::default(), drag_gesture: Default::default(), @@ -150,7 +151,7 @@ } } -@@ -577,6 +652,220 @@ +@@ -589,6 +664,220 @@ } } @@ -371,7 +372,7 @@ /// fn handle_native_mouse_move_event( &self, -@@ -627,6 +916,57 @@ +@@ -639,6 +928,57 @@ return; } @@ -429,7 +430,7 @@ // Update the cursor when the mouse moves, if it has changed. self.set_cursor(Some(hit_test_result.cursor)); -@@ -919,6 +1259,12 @@ +@@ -931,6 +1271,12 @@ return; }; @@ -442,7 +443,7 @@ debug!( "{:?}: at {:?}", mouse_button_event.action, hit_test_result.point_in_frame -@@ -1076,7 +1422,12 @@ +@@ -1088,7 +1434,12 @@ // Step 9. If mbutton is the secondary mouse button, then // Maybe show context menu with native, target. if let MouseButton::Secondary = mouse_button_event.button { @@ -456,7 +457,7 @@ } }, // https://w3c.github.io/pointerevents/#dfn-handle-native-mouse-up -@@ -1229,13 +1580,38 @@ +@@ -1241,13 +1592,38 @@ } /// @@ -466,7 +467,7 @@ + /// page has claimed the gesture for itself. fn maybe_show_context_menu( &self, - cx: &mut js::context::JSContext, + cx: &mut JSContext, target: &EventTarget, hit_test_result: &HitTestResult, - input_event: &ConstellationInputEvent, @@ -497,7 +498,7 @@ // let menu_event = PointerEvent::new( cx, -@@ -1250,25 +1626,25 @@ +@@ -1262,25 +1638,25 @@ hit_test_result .point_relative_to_initial_containing_block .to_i32(), @@ -542,7 +543,7 @@ ); menu_event.upcast::().set_composed(true); -@@ -1282,6 +1658,93 @@ +@@ -1294,8 +1670,95 @@ .embedder_controls() .show_context_menu(cx.no_gc(), hit_test_result); }; @@ -572,8 +573,8 @@ + touch_id, + start_point: point, + }); -+ } -+ + } + + /// Cancel the long-press timer if one is active. + fn cancel_long_press_timer(&self) { + if let Some(state) = self.long_press_state.borrow_mut().take() { @@ -633,10 +634,12 @@ + if showed_menu { + self.context_menu_touch_id.set(Some(touch_id)); + } - } - ++ } ++ fn handle_touch_event( -@@ -1290,7 +1753,46 @@ + &self, + cx: &mut JSContext, +@@ -1302,7 +1765,46 @@ event: EmbedderTouchEvent, input_event: &ConstellationInputEvent, ) -> InputEventResult { @@ -683,7 +686,7 @@ // Ignore all incoming events without a hit test. let Some(hit_test_result) = self.window.hit_test_from_input_event(flags, input_event) else { -@@ -1298,6 +1800,19 @@ +@@ -1310,6 +1812,19 @@ return Default::default(); }; @@ -703,7 +706,7 @@ let TouchId(identifier) = event.touch_id; let Some(element) = hit_test_result -@@ -1469,6 +1984,10 @@ +@@ -1481,6 +1996,10 @@ .safe_borrow_mut(cx.no_gc()) .push(Dom::from_ref(&*pointer_touch)); self.set_active_element(cx.no_gc(), &element); @@ -714,7 +717,7 @@ (current_target, pointer_touch) }, _ => { -@@ -1503,15 +2022,47 @@ +@@ -1515,15 +2034,47 @@ ); let mut active_touch_points = self.active_touch_points.safe_borrow_mut(cx.no_gc()); @@ -763,7 +766,7 @@ }, TouchEventType::Down => unreachable!("Should have been handled above"), } -@@ -1559,6 +2110,12 @@ +@@ -1571,6 +2122,12 @@ ); let event = touch_event.upcast::(); event.fire(cx, &touch_dispatch_target); @@ -776,7 +779,7 @@ event.flags().into() } -@@ -1695,6 +2252,16 @@ +@@ -1706,6 +2263,16 @@ return Default::default(); }; @@ -793,30 +796,79 @@ let Some(el) = hit_test_result .node .inclusive_ancestors(ShadowIncluding::Yes) -@@ -2056,6 +2623,26 @@ - return; +@@ -2068,6 +2635,26 @@ + return input_event_result | InputEventResult::Consumed; } + // Spatial navigation: arrow keys move focus, Enter activates. + // This is checked before scroll handling so it takes priority when enabled. + let document = self.window.Document(); -+ match event.key() { ++ match event.key { + Key::Named( + NamedKey::ArrowUp | + NamedKey::ArrowDown | + NamedKey::ArrowLeft | + NamedKey::ArrowRight, + ) if super::spatial_navigation::handle_arrow_key(cx, &document, event) => { -+ return; ++ return input_event_result | InputEventResult::Consumed; + }, + Key::Named(NamedKey::Enter) + if super::spatial_navigation::handle_enter_key(cx, &document) => + { -+ return; ++ return input_event_result | InputEventResult::Consumed; + }, + _ => {}, + } + let mut is_space = false; - let scroll = match event.key() { + let scroll = match &event.key { Key::Named(NamedKey::ArrowDown) => KeyboardScroll::Down, +@@ -2105,11 +2692,19 @@ + return input_event_result; + } + +- self.do_keyboard_scroll(cx, scroll); +- input_event_result | InputEventResult::Consumed ++ // Beaver: only consider the event consumed when a scroll really happened ++ // (or was handed off to a parent viewport). Marking unconsumed scrolls as ++ // consumed makes beaver_shell's chrome-first keyboard forwarding drop the ++ // event instead of passing it on to a focused embedded webview. ++ if self.do_keyboard_scroll(cx, scroll) { ++ return input_event_result | InputEventResult::Consumed; ++ } ++ input_event_result + } + +- pub(crate) fn do_keyboard_scroll(&self, cx: &mut JSContext, scroll: KeyboardScroll) { ++ /// Attempt a keyboard scroll. Returns true when the scroll was performed or ++ /// forwarded up the frame chain, false when nothing could scroll. ++ pub(crate) fn do_keyboard_scroll(&self, cx: &mut JSContext, scroll: KeyboardScroll) -> bool { + let scroll_axis = match scroll { + KeyboardScroll::Left | KeyboardScroll::Right => ScrollingBoxAxis::X, + _ => ScrollingBoxAxis::Y, +@@ -2190,7 +2785,7 @@ + let iframe_window = iframe.owner_window(); + let mut realm = enter_auto_realm(cx, &*iframe_window); + let cx = &mut realm; +- iframe_window ++ return iframe_window + .Document() + .event_handler() + .do_keyboard_scroll(cx, scroll); +@@ -2201,12 +2796,14 @@ + document.window().send_to_constellation( + ScriptToConstellationMessage::ForwardKeyboardScroll(parent_pipeline, scroll), + ); +- }; +- return; ++ return true; ++ } ++ return false; + } + + let (current_scroll_offset, delta) = calculate_current_scroll_offset_and_delta(); + scrolling_box.scroll_to(cx, delta + current_scroll_offset, ScrollBehavior::Auto); ++ true + } + + /// Get or create a pointer ID for the given touch identifier. diff --git a/patches/components/script/dom/document/focus.rs.patch b/patches/components/script/dom/document/focus.rs.patch index b79a63a..ae5bae7 100644 --- a/patches/components/script/dom/document/focus.rs.patch +++ b/patches/components/script/dom/document/focus.rs.patch @@ -1,8 +1,8 @@ --- original +++ modified -@@ -317,6 +317,11 @@ - mut old_focus_chain: RootedGuard<'_, Vec>, +@@ -340,6 +340,11 @@ new_focus_target: &FocusableArea, + for_system_focus_change: bool, ) { + // Ignore focus changes for "hide focus" embedded webviews. + if self.window.as_global_scope().hide_focus() { diff --git a/patches/components/script/dom/document/spatial_navigation.rs.patch b/patches/components/script/dom/document/spatial_navigation.rs.patch index ca1c5ea..ccda4bc 100644 --- a/patches/components/script/dom/document/spatial_navigation.rs.patch +++ b/patches/components/script/dom/document/spatial_navigation.rs.patch @@ -1,6 +1,6 @@ --- original +++ modified -@@ -0,0 +1,329 @@ +@@ -0,0 +1,328 @@ +/* SPDX Id: AGPL-3.0-or-later */ + +//! Spatial navigation: navigate to the nearest focusable element using arrow keys. @@ -14,7 +14,7 @@ +use app_units::Au; +use euclid::Rect; +use html5ever::local_name; -+use keyboard_types::{Key, NamedKey}; ++use keyboard_types::{Key, KeyboardEvent, NamedKey}; +use script_bindings::codegen::GenericBindings::DocumentBinding::DocumentMethods; +use script_bindings::codegen::GenericBindings::ElementBinding::ScrollLogicalPosition; +use script_bindings::codegen::GenericBindings::HTMLElementBinding::HTMLElementMethods; @@ -25,7 +25,6 @@ + +use crate::dom::document::Document; +use crate::dom::element::element::Element; -+use crate::dom::event::keyboardevent::KeyboardEvent; +use crate::dom::html::htmlelement::HTMLElement; +use crate::dom::html::htmlmetaelement::HTMLMetaElement; +use crate::dom::iterators::ShadowIncluding; @@ -70,7 +69,7 @@ + return false; + } + -+ let Some(direction) = Direction::from_key(&event.key()) else { ++ let Some(direction) = Direction::from_key(&event.key) else { + return false; + }; + diff --git a/patches/components/script/dom/embedder.rs.patch b/patches/components/script/dom/embedder.rs.patch index e484799..15d3f25 100644 --- a/patches/components/script/dom/embedder.rs.patch +++ b/patches/components/script/dom/embedder.rs.patch @@ -543,7 +543,7 @@ + ))); + }; + -+ let promise = Promise::new_rooted(cx, &global); ++ let promise = Promise::new(cx, &global); + + let image_type = match &*options.type_.str() { + "image/jpeg" => ScreenshotImageType::Jpeg, diff --git a/patches/components/script/dom/globalscope/globalscope.rs.patch b/patches/components/script/dom/globalscope/globalscope.rs.patch index 146e1bb..40379b3 100644 --- a/patches/components/script/dom/globalscope/globalscope.rs.patch +++ b/patches/components/script/dom/globalscope/globalscope.rs.patch @@ -1,6 +1,6 @@ --- original +++ modified -@@ -352,6 +352,16 @@ +@@ -307,6 +307,16 @@ /// Is considered in a secure context inherited_secure_context: Option, @@ -17,7 +17,7 @@ /// Directory to store unminified scripts for this window if unminify-js /// opt is enabled. unminified_js_dir: Option, -@@ -773,6 +783,8 @@ +@@ -398,6 +408,8 @@ #[cfg(feature = "webgpu")] gpu_id_hub: Arc, inherited_secure_context: Option, unminify_js: bool, @@ -26,7 +26,7 @@ ) -> Self { let fetch_group = RefCell::new(FetchGroup::new(resource_threads.sender())); Self { -@@ -809,6 +821,8 @@ +@@ -434,6 +446,8 @@ console_group_stack: DomRefCell::new(Vec::new()), console_count_map: Default::default(), inherited_secure_context, @@ -35,7 +35,7 @@ unminified_js_dir: unminify_js.then(|| unminified_path("unminified-js")), byte_length_queuing_strategy_size_function: OnceCell::new(), count_queuing_strategy_size_function: OnceCell::new(), -@@ -1156,6 +1170,25 @@ +@@ -781,6 +795,25 @@ .send(ScriptToConstellationMessage::EntanglePorts(port1, port2)); } @@ -61,7 +61,7 @@ /// Handle the transfer of a port in the current task. pub(crate) fn mark_port_as_transferred(&self, port_id: &MessagePortId) -> MessagePortImpl { if let MessagePortState::Managed(_id, message_ports) = -@@ -3212,6 +3245,16 @@ +@@ -2839,6 +2872,16 @@ self.inherited_secure_context } diff --git a/patches/components/script/dom/html/embedded_content/htmliframeelement.rs.patch b/patches/components/script/dom/html/embedded_content/htmliframeelement.rs.patch index b5e02de..491a707 100644 --- a/patches/components/script/dom/html/embedded_content/htmliframeelement.rs.patch +++ b/patches/components/script/dom/html/embedded_content/htmliframeelement.rs.patch @@ -10,8 +10,8 @@ use crate::dom::bindings::codegen::Bindings::HTMLIFrameElementBinding::HTMLIFrameElementMethods; use crate::dom::bindings::codegen::Bindings::WindowBinding::Window_Binding::WindowMethods; -@@ -305,6 +305,8 @@ - embedder_theme: window.embedder_theme(), +@@ -303,6 +303,8 @@ + user_content_manager_id: None, target_snapshot_params, frame_name: self.frozen_name.borrow().clone(), + is_embedded_webview: false, @@ -19,7 +19,7 @@ }; self.pipeline_id.set(Some(new_pipeline_id)); -@@ -1142,7 +1144,16 @@ +@@ -1139,7 +1141,16 @@ // may be in a different script thread. Instead, we check to see if the parent // is in a document tree and has a browsing context, which is what causes // the child browsing context to be created. @@ -37,7 +37,7 @@ debug!("iframe src set while in browsing context."); self.process_the_iframe_attributes(ProcessingMode::NotFirstTime, cx); } -@@ -1235,7 +1246,7 @@ +@@ -1232,7 +1243,7 @@ } // The iframe HTML element removing steps, given removedNode, are to destroy a child diff --git a/patches/components/script/dom/html/form_controls/htmlinputelement.rs.patch b/patches/components/script/dom/html/form_controls/htmlinputelement.rs.patch index fd0d595..925ae31 100644 --- a/patches/components/script/dom/html/form_controls/htmlinputelement.rs.patch +++ b/patches/components/script/dom/html/form_controls/htmlinputelement.rs.patch @@ -10,8 +10,8 @@ +}; use encoding_rs::Encoding; use html5ever::{LocalName, Prefix, local_name}; - use js::context::JSContext; -@@ -1029,6 +1031,9 @@ + use js::context::{JSContext, NoGC}; +@@ -1005,6 +1007,9 @@ } else { // Non-text input type. Would this be even called? } @@ -21,7 +21,7 @@ } fn is_password_field(&self) -> bool { -@@ -1991,7 +1996,7 @@ +@@ -1985,7 +1990,7 @@ .hide_embedder_control(self.upcast()); } else if *event_type == *"focus" { let input_type = &*self.input_type(); @@ -30,7 +30,7 @@ return; }; -@@ -2005,6 +2010,21 @@ +@@ -1999,6 +2004,21 @@ let _ = selection.Collapse(cx, None, 0); } diff --git a/patches/components/script/dom/html/form_controls/htmltextareaelement.rs.patch b/patches/components/script/dom/html/form_controls/htmltextareaelement.rs.patch index 5bb95a0..d777ebc 100644 --- a/patches/components/script/dom/html/form_controls/htmltextareaelement.rs.patch +++ b/patches/components/script/dom/html/form_controls/htmltextareaelement.rs.patch @@ -1,6 +1,6 @@ --- original +++ modified -@@ -304,6 +304,9 @@ +@@ -303,6 +303,9 @@ } else { // If there isn’t a text run, layout is pending to create it anyway } diff --git a/patches/components/script/dom/html/htmlwebviewelement.rs.patch b/patches/components/script/dom/html/htmlwebviewelement.rs.patch index d30d6f1..0852863 100644 --- a/patches/components/script/dom/html/htmlwebviewelement.rs.patch +++ b/patches/components/script/dom/html/htmlwebviewelement.rs.patch @@ -1,6 +1,6 @@ --- original +++ modified -@@ -0,0 +1,1748 @@ +@@ -0,0 +1,1747 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ @@ -239,7 +239,7 @@ + generic_channel::channel().expect("Failed to create IPC channel for embedded webview"); + + let hide_focus = self.has_hide_focus(); -+ let theme = window.embedder_theme(); ++ let theme = window.webview_theme(); + let request = EmbeddedWebViewCreationRequest { + load_data, + parent_pipeline_id: pipeline_id, @@ -424,7 +424,6 @@ + load_data, + old_pipeline_id, + viewport_details, -+ embedder_theme: window.embedder_theme(), + }; + window + .as_global_scope() @@ -1150,7 +1149,7 @@ + }; + + let global = self.owner_global(); -+ let promise = Promise::new_rooted(cx, &global); ++ let promise = Promise::new(cx, &global); + + // Parse image type from options + let image_type = match &*options.type_.str() { diff --git a/patches/components/script/dom/idledetector.rs.patch b/patches/components/script/dom/idledetector.rs.patch index ecb4fc8..2439b39 100644 --- a/patches/components/script/dom/idledetector.rs.patch +++ b/patches/components/script/dom/idledetector.rs.patch @@ -235,7 +235,7 @@ + /// + fn RequestPermission(cx: &mut JSContext, window: &Window) -> RootedPromise { + let global = window.as_global_scope(); -+ let promise = Promise::new_rooted(cx, global); ++ let promise = Promise::new(cx, global); + + // Step 2. If the relevant global object does not have transient + // activation, reject with "NotAllowedError". @@ -256,7 +256,7 @@ + /// + fn Start(&self, cx: &mut JSContext, options: &IdleOptions) -> RootedPromise { + let global = self.global(); -+ let promise = Promise::new_rooted(cx, &global); ++ let promise = Promise::new(cx, &global); + + // Step 1-2. If the document is not fully active, reject with + // "InvalidStateError". Always a Window: `Exposed=Window`. diff --git a/patches/components/script/dom/keyboard.rs.patch b/patches/components/script/dom/keyboard.rs.patch index 9971431..2f206bb 100644 --- a/patches/components/script/dom/keyboard.rs.patch +++ b/patches/components/script/dom/keyboard.rs.patch @@ -216,7 +216,7 @@ + /// input, resolving `promise` when the focused pipeline's script replies. + fn request_surrounding_text(&self, cx: &mut JSContext, max_chars: u32) -> RootedPromise { + let global = self.global(); -+ let promise = Promise::new_rooted(cx, &global); ++ let promise = Promise::new(cx, &global); + let task_manager = global.task_manager(); + let task_source = task_manager.dom_manipulation_task_source(); + let callback = callback_promise(&promise, self, task_source); diff --git a/patches/components/script/dom/navigator/navigator.rs.patch b/patches/components/script/dom/navigator/navigator.rs.patch index 47831d6..75a0fdd 100644 --- a/patches/components/script/dom/navigator/navigator.rs.patch +++ b/patches/components/script/dom/navigator/navigator.rs.patch @@ -132,7 +132,7 @@ + target_url: USVString, + ) -> Fallible { + let global = self.global(); -+ let promise = Promise::new_rooted(cx, &global); ++ let promise = Promise::new(cx, &global); + + // Create a local port and a virtual remote port ID. + // The remote port is NOT tracked in this global — it only exists @@ -182,7 +182,7 @@ + ) -> Fallible { + let global = self.global(); + let mut realm = CurrentRealm::assert(cx); -+ let promise = Promise::new_in_realm_rooted(&mut realm); ++ let promise = Promise::new_in_realm(&mut realm); + let task_manager = global.task_manager(); + let task_source = task_manager.dom_manipulation_task_source(); + diff --git a/patches/components/script/dom/pairing.rs.patch b/patches/components/script/dom/pairing.rs.patch index 74f00b6..42d248f 100644 --- a/patches/components/script/dom/pairing.rs.patch +++ b/patches/components/script/dom/pairing.rs.patch @@ -87,7 +87,7 @@ +impl PairingMethods for Pairing { + fn Local(&self, cx: &mut JSContext) -> RootedPromise { + let global = &self.global(); -+ let promise = Promise::new_rooted(cx, global); ++ let promise = Promise::new(cx, global); + let task_manager = global.task_manager(); + let task_source = task_manager.dom_manipulation_task_source(); + let callback = callback_promise(&promise, self, task_source); @@ -104,7 +104,7 @@ + + fn GuestPin(&self, cx: &mut JSContext) -> RootedPromise { + let global = &self.global(); -+ let promise = Promise::new_rooted(cx, global); ++ let promise = Promise::new(cx, global); + let task_manager = global.task_manager(); + let task_source = task_manager.dom_manipulation_task_source(); + let callback = callback_promise(&promise, self, task_source); @@ -121,7 +121,7 @@ + + fn Peers(&self, cx: &mut JSContext) -> RootedPromise { + let global = &self.global(); -+ let promise = Promise::new_rooted(cx, global); ++ let promise = Promise::new(cx, global); + let task_manager = global.task_manager(); + let task_source = task_manager.dom_manipulation_task_source(); + let callback = callback_promise(&promise, self, task_source); @@ -138,7 +138,7 @@ + + fn RequestPairing(&self, cx: &mut JSContext, peer: &Peer) -> RootedPromise { + let global = &self.global(); -+ let promise = Promise::new_rooted(cx, global); ++ let promise = Promise::new(cx, global); + let task_manager = global.task_manager(); + let task_source = task_manager.dom_manipulation_task_source(); + let callback = callback_promise(&promise, self, task_source); @@ -158,7 +158,7 @@ + + fn AcceptPairing(&self, cx: &mut JSContext, peer: &Peer) -> RootedPromise { + let global = &self.global(); -+ let promise = Promise::new_rooted(cx, global); ++ let promise = Promise::new(cx, global); + let task_manager = global.task_manager(); + let task_source = task_manager.dom_manipulation_task_source(); + let callback = callback_promise(&promise, self, task_source); @@ -178,7 +178,7 @@ + + fn RejectPairing(&self, cx: &mut JSContext, peer: &Peer) -> RootedPromise { + let global = &self.global(); -+ let promise = Promise::new_rooted(cx, global); ++ let promise = Promise::new(cx, global); + let task_manager = global.task_manager(); + let task_source = task_manager.dom_manipulation_task_source(); + let callback = callback_promise(&promise, self, task_source); @@ -198,7 +198,7 @@ + + fn RemovePeer(&self, cx: &mut JSContext, peer: &Peer) -> RootedPromise { + let global = &self.global(); -+ let promise = Promise::new_rooted(cx, global); ++ let promise = Promise::new(cx, global); + let task_manager = global.task_manager(); + let task_source = task_manager.dom_manipulation_task_source(); + let callback = callback_promise(&promise, self, task_source); @@ -218,7 +218,7 @@ + + fn EnableGuestMode(&self, cx: &mut JSContext, duration_minutes: u32) -> RootedPromise { + let global = &self.global(); -+ let promise = Promise::new_rooted(cx, global); ++ let promise = Promise::new(cx, global); + let task_manager = global.task_manager(); + let task_source = task_manager.dom_manipulation_task_source(); + let callback = callback_promise(&promise, self, task_source); @@ -238,7 +238,7 @@ + + fn DisableGuestMode(&self, cx: &mut JSContext) -> RootedPromise { + let global = &self.global(); -+ let promise = Promise::new_rooted(cx, global); ++ let promise = Promise::new(cx, global); + let task_manager = global.task_manager(); + let task_source = task_manager.dom_manipulation_task_source(); + let callback = callback_promise(&promise, self, task_source); @@ -262,7 +262,7 @@ + pin: DOMString, + ) -> RootedPromise { + let global = &self.global(); -+ let promise = Promise::new_rooted(cx, global); ++ let promise = Promise::new(cx, global); + let task_manager = global.task_manager(); + let task_source = task_manager.dom_manipulation_task_source(); + let callback = callback_promise(&promise, self, task_source); @@ -283,7 +283,7 @@ + + fn SetName(&self, cx: &mut JSContext, name: DOMString) -> RootedPromise { + let global = &self.global(); -+ let promise = Promise::new_rooted(cx, global); ++ let promise = Promise::new(cx, global); + let task_manager = global.task_manager(); + let task_source = task_manager.dom_manipulation_task_source(); + let callback = callback_promise(&promise, self, task_source); @@ -303,7 +303,7 @@ + + fn Start(&self, cx: &mut JSContext) -> RootedPromise { + let global = &self.global(); -+ let promise = Promise::new_rooted(cx, global); ++ let promise = Promise::new(cx, global); + let task_manager = global.task_manager(); + let task_source = task_manager.dom_manipulation_task_source(); + let callback = callback_promise(&promise, self, task_source); @@ -320,7 +320,7 @@ + + fn Stop(&self, cx: &mut JSContext) -> RootedPromise { + let global = &self.global(); -+ let promise = Promise::new_rooted(cx, global); ++ let promise = Promise::new(cx, global); + let task_manager = global.task_manager(); + let task_source = task_manager.dom_manipulation_task_source(); + let callback = callback_promise(&promise, self, task_source); diff --git a/patches/components/script/dom/power.rs.patch b/patches/components/script/dom/power.rs.patch index b00b718..5335d87 100644 --- a/patches/components/script/dom/power.rs.patch +++ b/patches/components/script/dom/power.rs.patch @@ -48,7 +48,7 @@ +impl PowerMethods for Power { + fn Devices(&self, cx: &mut JSContext) -> RootedPromise { + let global = &self.global(); -+ let promise = Promise::new_rooted(cx, global); ++ let promise = Promise::new(cx, global); + let task_manager = global.task_manager(); + let task_source = task_manager.dom_manipulation_task_source(); + let callback = callback_promise(&promise, self, task_source); @@ -80,7 +80,7 @@ + /// Re-read the real state and refresh the cached value. + fn ReadScreenOn(&self, cx: &mut JSContext) -> RootedPromise { + let global = &self.global(); -+ let promise = Promise::new_rooted(cx, global); ++ let promise = Promise::new(cx, global); + let task_manager = global.task_manager(); + let task_source = task_manager.dom_manipulation_task_source(); + let callback = callback_promise(&promise, self, task_source); @@ -97,7 +97,7 @@ + + fn Shutdown(&self, cx: &mut JSContext) -> RootedPromise { + let global = &self.global(); -+ let promise = Promise::new_rooted(cx, global); ++ let promise = Promise::new(cx, global); + let task_manager = global.task_manager(); + let task_source = task_manager.dom_manipulation_task_source(); + let callback = callback_promise(&promise, self, task_source); @@ -114,7 +114,7 @@ + + fn Reboot(&self, cx: &mut JSContext, target: RebootTarget) -> RootedPromise { + let global = &self.global(); -+ let promise = Promise::new_rooted(cx, global); ++ let promise = Promise::new(cx, global); + let task_manager = global.task_manager(); + let task_source = task_manager.dom_manipulation_task_source(); + let callback = callback_promise(&promise, self, task_source); diff --git a/patches/components/script/dom/serviceworker/notification.rs.patch b/patches/components/script/dom/serviceworker/notification.rs.patch index 0db1b60..b306230 100644 --- a/patches/components/script/dom/serviceworker/notification.rs.patch +++ b/patches/components/script/dom/serviceworker/notification.rs.patch @@ -1,6 +1,6 @@ --- original +++ modified -@@ -27,6 +27,7 @@ +@@ -26,6 +26,7 @@ use rustc_hash::FxHashSet; use script_bindings::cell::DomRefCell; use script_bindings::reflector::reflect_dom_object_with_proto; @@ -8,7 +8,7 @@ use servo_url::{ImmutableOrigin, ServoUrl}; use uuid::Uuid; -@@ -269,11 +270,22 @@ +@@ -267,11 +268,22 @@ if !shown { // TODO: step 6.1: Append notification to the list of notifications. // step 6.2: Display notification on the device @@ -36,7 +36,7 @@ } // TODO: step 7: If shown is false or oldNotification is non-null, -@@ -889,6 +901,11 @@ +@@ -890,6 +902,11 @@ for (request, resource_type) in pending_requests { self.fetch_and_show_when_ready(request, resource_type); } diff --git a/patches/components/script/dom/window/window.rs.patch b/patches/components/script/dom/window/window.rs.patch index 4a82a95..85e9257 100644 --- a/patches/components/script/dom/window/window.rs.patch +++ b/patches/components/script/dom/window/window.rs.patch @@ -1,6 +1,6 @@ --- original +++ modified -@@ -28,6 +28,7 @@ +@@ -27,6 +27,7 @@ use embedder_traits::{ AlertResponse, ConfirmResponse, EmbedderMsg, PromptResponse, ScriptToEmbedderChan, SimpleDialogRequest, Theme, UntrustedNodeAddress, ViewportDetails, WebDriverLoadStatus, @@ -8,7 +8,7 @@ }; use euclid::{Point2D, Rect, Scale, Size2D, Vector2D}; use fonts::{ -@@ -38,10 +39,10 @@ +@@ -37,10 +38,10 @@ use js::conversions::ToJSValConvertible; use js::glue::DumpJSStack; use js::jsapi::{ @@ -22,7 +22,7 @@ use js::realm::{AutoRealm, CurrentRealm}; use js::rust::wrappers2::{JS_DefineProperty, JS_GC}; use js::rust::{ -@@ -54,6 +55,7 @@ +@@ -53,6 +54,7 @@ ReflowStatistics, RestyleReason, ScrollContainerQueryFlags, ScrollContainerResponse, TrustedNodeAddress, combine_id_with_fragment_type, }; @@ -58,7 +58,7 @@ use crate::runtime::job_queue::UserMicrotask; use crate::runtime::script_runtime::Runtime; use crate::tasks::task_manager::TaskManager; -@@ -1228,12 +1233,22 @@ +@@ -1226,12 +1231,22 @@ let (sender, receiver) = ProfiledGenericChannel::channel(self.global().time_profiler_chan().clone()).unwrap(); @@ -82,7 +82,7 @@ receiver.recv().unwrap_or_else(|_| { // If the receiver is closed, we assume the dialog was cancelled. debug!("Alert dialog was cancelled or failed to show."); -@@ -1267,13 +1282,22 @@ +@@ -1265,13 +1280,22 @@ // the user to respond with a positive or negative response. let (sender, receiver) = ProfiledGenericChannel::channel(self.global().time_profiler_chan().clone()).unwrap(); @@ -106,7 +106,7 @@ // Step 5: Let userPromptHandler be WebDriver BiDi user prompt opened with this, // "confirm", and message. // -@@ -1318,6 +1342,7 @@ +@@ -1316,6 +1340,7 @@ // defaulted to the value given by default. let (sender, receiver) = ProfiledGenericChannel::channel(self.global().time_profiler_chan().clone()).unwrap(); @@ -114,7 +114,7 @@ let dialog = SimpleDialogRequest::Prompt { id: self.Document().embedder_controls().next_control_id(), message: String::from(message), -@@ -1324,8 +1349,16 @@ +@@ -1322,8 +1347,16 @@ default: String::from(default), response_sender: sender, }; @@ -132,7 +132,7 @@ // Step 6: Let userPromptHandler be WebDriver BiDi user prompt opened with this, // "prompt", and message. // TODO: Add support for WebDriver BiDi. -@@ -1817,6 +1850,27 @@ +@@ -1813,6 +1846,27 @@ // https://html.spec.whatwg.org/multipage/#windoweventhandlers window_event_handlers!(); @@ -141,7 +141,7 @@ + + fn AcceptTask(&self, cx: &mut js::context::JSContext) -> Fallible { + let global = self.upcast::(); -+ let promise = Promise::new_rooted(cx, global); ++ let promise = Promise::new(cx, global); + let task_manager = global.task_manager(); + let task_source = task_manager.dom_manipulation_task_source(); + let callback = callback_promise(&promise, self, task_source); @@ -160,7 +160,7 @@ /// fn Screen(&self, cx: &mut JSContext) -> DomRoot { self.screen.or_init(|| Screen::new(cx, self)) -@@ -2724,6 +2778,10 @@ +@@ -2725,6 +2779,10 @@ accessibility_damage = Some(accessibility_data.drain_pending_accessibility_damage()); } @@ -171,7 +171,7 @@ // Send new document and relevant styles to layout. let reflow = ReflowRequest { document: document.upcast::().to_trusted_node_address(), -@@ -3250,10 +3308,33 @@ +@@ -3254,10 +3312,33 @@ flags: HitTestFlags, input_event: &ConstellationInputEvent, ) -> Option { @@ -209,7 +209,7 @@ } #[expect(unsafe_code)] -@@ -3274,8 +3355,42 @@ +@@ -3278,8 +3359,42 @@ let address = UntrustedNodeAddress(node.0 as *const c_void); unsafe { from_untrusted_node_address(address) } }; @@ -253,7 +253,7 @@ dom_position_for_selection: result .dom_position_for_selection .map(|(node, offset)| (from_opaque_node(node), offset)), -@@ -3673,17 +3788,19 @@ +@@ -3676,17 +3791,19 @@ } pub(crate) fn send_to_embedder(&self, msg: EmbedderMsg) { @@ -280,9 +280,9 @@ #[cfg(feature = "webxr")] @@ -3914,6 +4031,8 @@ + player_context: WindowGLContext, #[cfg(feature = "webgpu")] gpu_id_hub: Arc, inherited_secure_context: Option, - embedder_theme: Theme, + is_embedded_webview: bool, + hide_focus: bool, weak_script_thread: Weak, @@ -297,7 +297,7 @@ ), caches: Default::default(), ongoing_navigation: Default::default(), -@@ -4238,3 +4359,115 @@ +@@ -4237,3 +4358,115 @@ Window::origin(self) } } diff --git a/patches/components/script/dom/window/windowproxy.rs.patch b/patches/components/script/dom/window/windowproxy.rs.patch index 70273a2..2de6419 100644 --- a/patches/components/script/dom/window/windowproxy.rs.patch +++ b/patches/components/script/dom/window/windowproxy.rs.patch @@ -1,6 +1,6 @@ --- original +++ modified -@@ -327,6 +327,7 @@ +@@ -328,6 +328,7 @@ cx: &mut JSContext, name: DOMString, noopener: bool, @@ -8,7 +8,7 @@ ) -> Option> { let (response_sender, response_receiver) = generic_channel::channel().unwrap(); let window = self -@@ -379,6 +380,7 @@ +@@ -380,6 +381,7 @@ opener_webview_id: window.webview_id(), opener_pipeline_id: self.currently_active.get().unwrap(), response_sender, @@ -16,7 +16,7 @@ }; let constellation_msg = ScriptToConstellationMessage::CreateAuxiliaryWebView(load_info); window.send_to_constellation(constellation_msg); -@@ -402,6 +404,8 @@ +@@ -407,6 +409,8 @@ iframe_element_referrer_policy: ReferrerPolicy::EmptyString, }, frame_name: None, @@ -25,7 +25,7 @@ }; with_script_thread(|script_thread| { -@@ -568,14 +572,32 @@ +@@ -573,14 +577,32 @@ // (TODO) Step 11. Let referrerPolicy be the empty string. // (TODO) Step 12. If noreferrer is true, then set referrerPolicy to "no-referrer". @@ -62,7 +62,7 @@ // TODO Step 15.2, Set up browsing context features for targetNavigable's // active browsing context given tokenizedFeatures. let target_document = match chosen.document() { -@@ -658,6 +680,7 @@ +@@ -663,6 +685,7 @@ cx: &mut JSContext, name: DOMString, noopener: bool, @@ -70,7 +70,7 @@ ) -> (Option>, bool) { // Step 1. Let chosen be null. // Step 2. Let windowType be "existing or none". -@@ -727,7 +750,7 @@ +@@ -732,7 +755,7 @@ // TODO: Integrate `create_auxiliary_browsing_context` here and have it follow the spec. else { ( diff --git a/patches/components/script/dom/workers/workerglobalscope.rs.patch b/patches/components/script/dom/workers/workerglobalscope.rs.patch index 3ebb7b4..c39ed2e 100644 --- a/patches/components/script/dom/workers/workerglobalscope.rs.patch +++ b/patches/components/script/dom/workers/workerglobalscope.rs.patch @@ -1,6 +1,6 @@ --- original +++ modified -@@ -428,6 +428,8 @@ +@@ -429,6 +429,8 @@ gpu_id_hub, init.inherited_secure_context, init.unminify_js, diff --git a/patches/components/script/event_loop/script_thread.rs.patch b/patches/components/script/event_loop/script_thread.rs.patch index eff4ca0..77f8e5a 100644 --- a/patches/components/script/event_loop/script_thread.rs.patch +++ b/patches/components/script/event_loop/script_thread.rs.patch @@ -4,8 +4,8 @@ use embedder_traits::{ EmbedderControlId, EmbedderControlResponse, EmbedderMsg, FocusSequenceNumber, InputEventOutcome, JavaScriptEvaluationError, JavaScriptEvaluationId, MediaSessionActionType, -- Theme, ViewportDetails, WebDriverScriptCommand, -+ ServoErrorType, Theme, ViewportDetails, WebDriverScriptCommand, +- ViewportDetails, WebDriverScriptCommand, ++ ServoErrorType, ViewportDetails, WebDriverScriptCommand, }; use encoding_rs::Encoding; use fonts::{FontContext, SystemFontServiceProxy, WebFontLoadEvent}; @@ -61,7 +61,7 @@ use crate::dom::script_execution::{RethrowErrors, ScriptOptions}; use crate::dom::servoparser::{ParserContext, ServoParser}; use crate::dom::types::DebuggerGlobalScope; -@@ -1203,8 +1212,15 @@ +@@ -1234,8 +1243,15 @@ // Unspecified, but necessary: Any of the previous callbacks may have put the // document into a render-blocked state. If that's the case, then abort the // rendering process now. @@ -79,7 +79,7 @@ } // > 21. For each doc of docs, mark paint timing for doc. -@@ -1218,6 +1234,12 @@ +@@ -1249,6 +1265,12 @@ // TODO: Process top layer removals according to // https://drafts.csswg.org/css-position-4/#process-top-layer-removals. @@ -92,7 +92,7 @@ } let should_generate_frame = !painters_generating_frames.is_empty(); -@@ -1734,6 +1756,14 @@ +@@ -1765,6 +1787,14 @@ ScriptThreadMessage::GetDocumentOriginDetails(pipeline_id, result_sender) => { self.handle_get_origin_details(pipeline_id, result_sender); }, @@ -107,7 +107,7 @@ ScriptThreadMessage::GetTitle(pipeline_id) => self.handle_get_title_msg(pipeline_id), ScriptThreadMessage::SetDocumentActivity(pipeline_id, activity) => { self.handle_set_document_activity_msg(cx, pipeline_id, activity) -@@ -1886,12 +1916,47 @@ +@@ -1917,12 +1947,47 @@ self.handle_refresh_cursor(pipeline_id); }, ScriptThreadMessage::PreferencesUpdated(updates) => { @@ -159,7 +159,7 @@ ScriptThreadMessage::ForwardKeyboardScroll(pipeline_id, scroll) => { if let Some(document) = self.documents.borrow().find_document(pipeline_id) { document.event_handler().do_keyboard_scroll(cx, scroll); -@@ -1923,6 +1988,52 @@ +@@ -1954,6 +2019,52 @@ ScriptThreadMessage::TriggerGarbageCollection => unsafe { JS_GC(cx, GCReason::API); }, @@ -212,7 +212,7 @@ } } -@@ -2984,16 +3095,32 @@ +@@ -3061,16 +3172,32 @@ reason: UpdatePipelineIdReason, cx: &mut js::context::JSContext, ) { @@ -249,7 +249,7 @@ let Some(window) = self.documents.borrow().find_window(new_pipeline_id) else { return; -@@ -3007,11 +3134,12 @@ +@@ -3084,11 +3211,12 @@ browsing_context_id, webview_id, Some(parent_pipeline_id), @@ -263,7 +263,7 @@ ); } -@@ -3309,6 +3437,212 @@ +@@ -3389,6 +3517,212 @@ } } @@ -476,7 +476,7 @@ fn ask_constellation_for_top_level_info( &self, sender_webview_id: WebViewId, -@@ -3439,7 +3773,13 @@ +@@ -3520,7 +3854,13 @@ self.senders.pipeline_to_embedder_sender.clone(), self.senders.constellation_sender.clone(), incomplete.pipeline_id, @@ -491,16 +491,16 @@ incomplete.viewport_details, origin.clone(), creation_url, -@@ -3463,6 +3803,8 @@ +@@ -3543,6 +3883,8 @@ + #[cfg(feature = "webgpu")] self.gpu_id_hub.clone(), incomplete.load_data.inherited_secure_context, - incomplete.embedder_theme, + incomplete.is_embedded_webview, + incomplete.hide_focus, self.this.clone(), ) }, -@@ -3564,6 +3906,9 @@ +@@ -3644,6 +3986,9 @@ image_cache, ); @@ -510,7 +510,7 @@ // Step 8. Let loadTimingInfo be a new document load timing info with its // navigation start time set to navigationParams's response's timing // info's start time. -@@ -3580,9 +3925,6 @@ +@@ -3660,9 +4005,6 @@ .borrow_mut() .insert(incomplete.pipeline_id, &document); @@ -520,7 +520,7 @@ let iframe = incomplete.parent_info.and_then(|parent_id| { self.documents .borrow() -@@ -3617,6 +3959,7 @@ +@@ -3697,6 +4039,7 @@ parent_info, iframe, incomplete.opener, @@ -528,7 +528,7 @@ ); if let Some(name) = incomplete.frame_name { window_proxy.set_name(DOMString::from(name)); -@@ -3631,7 +3974,9 @@ +@@ -3711,7 +4054,9 @@ window.init_window_proxy(&window_proxy); if let Some(parent_pipeline) = parent_info { @@ -539,7 +539,7 @@ // For any similar-origin iframe, ensure that the contentWindow/contentDocument // APIs resolve to the new window/document as soon as parsing starts. self.handle_update_pipeline_id( -@@ -3826,11 +4171,11 @@ +@@ -3906,11 +4251,11 @@ target_snapshot_params: TargetSnapshotParams, cx: &mut js::context::JSContext, ) { @@ -554,7 +554,7 @@ iframe.navigate_or_reload_child_browsing_context( load_data, history_handling, -@@ -3838,7 +4183,17 @@ +@@ -3918,7 +4263,17 @@ target_snapshot_params, cx, ); @@ -572,7 +572,7 @@ } /// -@@ -4471,10 +4826,88 @@ +@@ -4551,10 +4906,88 @@ document.event_handler().handle_refresh_cursor(); } @@ -661,7 +661,7 @@ fn handle_request_screenshot_readiness( &self, webview_id: WebViewId, -@@ -4515,7 +4948,7 @@ +@@ -4595,7 +5028,7 @@ pinch_zoom_infos: PinchZoomInfos, ) { let Some(window) = self.documents.borrow().find_window(pipeline_id) else { diff --git a/patches/components/script/navigation.rs.patch b/patches/components/script/navigation.rs.patch index 19c0a7e..4acb9f2 100644 --- a/patches/components/script/navigation.rs.patch +++ b/patches/components/script/navigation.rs.patch @@ -1,6 +1,6 @@ --- original +++ modified -@@ -186,6 +186,10 @@ +@@ -184,6 +184,10 @@ pub(crate) target_snapshot_params: TargetSnapshotParams, /// Name of this iframe, if any pub(crate) frame_name: Option, @@ -12,7 +12,7 @@ impl InProgressLoad { @@ -210,6 +214,8 @@ - embedder_theme: new_pipeline_info.embedder_theme, + user_content_manager_id: new_pipeline_info.user_content_manager_id, target_snapshot_params: new_pipeline_info.target_snapshot_params, frame_name: new_pipeline_info.frame_name, + is_embedded_webview: new_pipeline_info.is_embedded_webview, diff --git a/patches/components/script_bindings/codegen/Bindings.conf.patch b/patches/components/script_bindings/codegen/Bindings.conf.patch index 2114947..9f7a91e 100644 --- a/patches/components/script_bindings/codegen/Bindings.conf.patch +++ b/patches/components/script_bindings/codegen/Bindings.conf.patch @@ -47,8 +47,8 @@ 'CookieStore': { 'cx': ['Set', 'Set_', 'Get', 'Get_', 'GetAll', 'GetAll_', 'Delete', 'Delete_'], }, -@@ -449,6 +482,11 @@ - 'cx': ['CheckValidity', 'GetValidity', 'GetLabels', 'ReportValidity', 'SetValidity', 'States'], +@@ -448,6 +481,11 @@ + 'no_gc': ['GetWillValidate'], }, +'Embedder': { @@ -59,7 +59,7 @@ 'Event': { 'cx': ['TimeStamp'], 'additionalTraits': ["crate::traits::DomEventTrait"], -@@ -831,6 +869,11 @@ +@@ -837,6 +875,11 @@ 'weakReferenceable': True, }, @@ -71,7 +71,7 @@ 'IDBCursor': { 'cx': ['Key', 'PrimaryKey'] }, -@@ -867,11 +910,19 @@ +@@ -873,11 +916,19 @@ 'cx': ['Abort', 'ObjectStore', 'ObjectStoreNames'], }, @@ -91,7 +91,7 @@ 'KeyframeEffect': { 'cx': ['GetKeyframes', 'SetKeyframes'] }, -@@ -947,7 +998,7 @@ +@@ -953,7 +1004,7 @@ }, 'Navigator': { @@ -100,7 +100,7 @@ 'Storage', 'Plugins', 'UserActivation', 'WakeLock', 'Xr', 'MediaDevices', 'MediaSession', 'Permissions', 'GetGamepads'], }, -@@ -1007,6 +1058,10 @@ +@@ -1004,6 +1055,10 @@ 'cx': ['RegisterPaint'], }, @@ -111,7 +111,7 @@ 'Performance': { 'cx': ['Mark', 'Measure'], }, -@@ -1436,6 +1491,7 @@ +@@ -1432,6 +1487,7 @@ 'additionalTraits': ['crate::interfaces::WindowHelpers', 'crate::interfaces::HasOrigin'], 'realm': ['CreateImageBitmap', 'CreateImageBitmap_', 'WebdriverCallback', 'GetOpener', 'Fetch'], 'cx': [ diff --git a/patches/components/script_bindings/interfaces.rs.patch b/patches/components/script_bindings/interfaces.rs.patch index 785307d..a6d4dbd 100644 --- a/patches/components/script_bindings/interfaces.rs.patch +++ b/patches/components/script_bindings/interfaces.rs.patch @@ -1,6 +1,6 @@ --- original +++ modified -@@ -152,3 +152,7 @@ +@@ -150,3 +150,7 @@ pub trait HasOrigin { fn origin(&self) -> MutableOrigin; } diff --git a/patches/components/servo/servo.rs.patch b/patches/components/servo/servo.rs.patch index f03f5ab..6a84b68 100644 --- a/patches/components/servo/servo.rs.patch +++ b/patches/components/servo/servo.rs.patch @@ -153,7 +153,19 @@ } } -@@ -888,6 +964,25 @@ +@@ -815,6 +891,11 @@ + webview.delegate().notify_closed(webview); + } + }, ++ ConstellationToEmbedderMsg::WebViewFocused(webview_id, focused) => { ++ if let Some(webview) = self.get_webview_handle(webview_id) { ++ webview.delegate().notify_focus_changed(webview, focused); ++ } ++ }, + ConstellationToEmbedderMsg::FinishJavaScriptEvaluation(evaluation_id, result) => { + self.javascript_evaluator + .borrow_mut() +@@ -871,6 +952,25 @@ .notify_media_session_event(webview, media_session_event); } }, @@ -179,7 +191,7 @@ } } } -@@ -1033,6 +1128,7 @@ +@@ -1016,6 +1116,7 @@ async_runtime, public_storage_threads.clone(), private_storage_threads.clone(), @@ -187,7 +199,7 @@ ); net::connector::prewarm_tls(); -@@ -1045,6 +1141,7 @@ +@@ -1028,6 +1129,7 @@ Servo(Rc::new(ServoInner { delegate: RefCell::new(Rc::new(DefaultServoDelegate)), paint, @@ -195,7 +207,7 @@ network_manager: Rc::new(RefCell::new(NetworkManager::new( public_resource_threads.clone(), private_resource_threads.clone(), -@@ -1079,6 +1176,10 @@ +@@ -1062,6 +1164,10 @@ *self.0.delegate.borrow_mut() = delegate; } @@ -206,7 +218,7 @@ /// **EXPERIMENTAL:** Intialize GL accelerated media playback. This currently only works on a limited number /// of platforms. This should be run *before* creating [`Servo`] and its first [`WebView`]. pub fn initialize_gl_accelerated_media(display: NativeDisplay, api: GlApi, context: GlContext) { -@@ -1119,6 +1220,22 @@ +@@ -1102,6 +1208,22 @@ .send(EmbedderToConstellationMessage::WebDriverCommand(command)); } @@ -229,7 +241,7 @@ pub fn set_preference(&self, name: &str, value: PrefValue) { let mut preferences = prefs::get().clone(); preferences.set_value(name, value); -@@ -1133,6 +1250,14 @@ +@@ -1116,6 +1238,14 @@ &self.0.site_data_manager } @@ -244,7 +256,7 @@ pub(crate) fn paint<'a>(&'a self) -> Ref<'a, Paint> { self.0.paint.borrow() } -@@ -1241,6 +1366,7 @@ +@@ -1224,6 +1354,7 @@ async_runtime: Box, public_storage_threads: StorageThreads, private_storage_threads: StorageThreads, @@ -252,7 +264,7 @@ ) { // Global configuration options, parsed from the command line. let opts = opts::get(); -@@ -1285,6 +1411,7 @@ +@@ -1268,6 +1399,7 @@ async_runtime, privileged_urls, wake_lock_provider: Box::new(DefaultWakeLockDelegate), diff --git a/patches/components/servo/webview.rs.patch b/patches/components/servo/webview.rs.patch index 376728c..310198b 100644 --- a/patches/components/servo/webview.rs.patch +++ b/patches/components/servo/webview.rs.patch @@ -27,7 +27,7 @@ } } -@@ -866,6 +879,11 @@ +@@ -855,6 +868,11 @@ EmbedderControlRequest::FilePicker { .. } => { unreachable!("This message should be routed through the FileManagerThread") }, diff --git a/patches/components/servo/webview_delegate.rs.patch b/patches/components/servo/webview_delegate.rs.patch index 119c73a..04d705d 100644 --- a/patches/components/servo/webview_delegate.rs.patch +++ b/patches/components/servo/webview_delegate.rs.patch @@ -9,7 +9,20 @@ use servo_constellation_traits::EmbedderToConstellationMessage; use tokio::sync::mpsc::UnboundedSender as TokioSender; use tokio::sync::oneshot::Sender; -@@ -1029,6 +1029,14 @@ +@@ -958,6 +958,12 @@ + /// occurs. + fn notify_closed(&self, _webview: WebView) {} + ++ /// The [`WebView`] gained or lost focus through a script-initiated focus ++ /// request (e.g. an embedded webview's `forceFocus()`). Beaver addition: ++ /// upstream removed this when moving to embedder-driven system focus, but ++ /// beaver_shell needs it to track which webview receives keyboard input. ++ fn notify_focus_changed(&self, _webview: WebView, _focused: bool) {} ++ + /// An input event passed to this [`WebView`] via [`WebView::notify_input_event`] has been handled + /// by Servo. This allows post-procesing of input events, such as chaining up unhandled events + /// to parent UI elements. +@@ -1026,6 +1032,14 @@ /// /// [`window.open`]: https://developer.mozilla.org/en-US/docs/Web/API/Window/open fn request_create_new(&self, _parent_webview: WebView, _request: CreateNewWebViewRequest) {} @@ -24,7 +37,7 @@ /// Content in a [`WebView`] is requesting permission to access a feature requiring /// permission from the user. The embedder should allow or deny the request, either by /// reading a cached value or querying the user for permission via the user interface. -@@ -1088,6 +1096,25 @@ +@@ -1085,6 +1099,25 @@ _tree_update: accesskit::TreeUpdate, ) { } diff --git a/patches/components/shared/constellation/from_script_message.rs.patch b/patches/components/shared/constellation/from_script_message.rs.patch index 312803e..30cb932 100644 --- a/patches/components/shared/constellation/from_script_message.rs.patch +++ b/patches/components/shared/constellation/from_script_message.rs.patch @@ -1,19 +1,18 @@ --- original +++ modified -@@ -10,9 +10,9 @@ +@@ -10,8 +10,9 @@ use devtools_traits::{DevtoolScriptControlMsg, ScriptToDevtoolsControlMsg, WorkerId}; use embedder_traits::user_contents::UserContentManagerId; use embedder_traits::{ - AnimationState, FocusSequenceNumber, JSValue, JavaScriptEvaluationError, -- JavaScriptEvaluationId, MediaSessionEvent, ScriptToEmbedderChan, Theme, ViewportDetails, -- WakeLockType, +- JavaScriptEvaluationId, MediaSessionEvent, ScriptToEmbedderChan, ViewportDetails, WakeLockType, + AnimationState, EmbedderControlId, EmbedderControlResponse, FocusSequenceNumber, + InputEventAndId, JSValue, JavaScriptEvaluationError, JavaScriptEvaluationId, MediaSessionEvent, + ScriptToEmbedderChan, SurroundingText, Theme, ViewportDetails, WakeLockType, }; use encoding_rs::Encoding; use euclid::default::Size2D as UntypedSize2D; -@@ -37,6 +37,7 @@ +@@ -36,6 +37,7 @@ use servo_canvas_traits::canvas::{CanvasId, CanvasMsg}; #[cfg(feature = "webgl")] use servo_canvas_traits::webgl::WebGLChan; @@ -21,7 +20,7 @@ use servo_url::{ImmutableOrigin, OriginSnapshot, ServoUrl}; use storage_traits::StorageThreads; use storage_traits::webstorage_thread::WebStorageType; -@@ -46,8 +47,8 @@ +@@ -45,8 +47,8 @@ use crate::structured_data::{BroadcastChannelMsg, StructuredSerializedData}; use crate::{ @@ -32,7 +31,7 @@ }; pub type ScriptToConstellationSender = -@@ -453,11 +454,14 @@ +@@ -452,11 +454,14 @@ pub opener_webview_id: WebViewId, /// The pipeline opener browsing context. pub opener_pipeline_id: PipelineId, @@ -49,7 +48,7 @@ #[derive(Debug, Deserialize, Serialize)] pub struct AuxiliaryWebViewCreationResponse { /// The new webview ID. -@@ -468,6 +472,38 @@ +@@ -467,6 +472,38 @@ pub user_content_manager_id: Option, } @@ -88,7 +87,7 @@ /// Specifies the information required to load an iframe. #[derive(Debug, Deserialize, Serialize)] pub struct IFrameLoadInfo { -@@ -609,8 +645,143 @@ +@@ -606,8 +643,143 @@ pub enum ConstellationInterest { /// Interest in `storage` events (fired when another same-origin pipeline modifies storage). StorageEvent, @@ -129,8 +128,8 @@ + SearchUrl(String, bool), + /// Run a read-only SQL query over the local store: (sql, text params). + QueryStore(String, Vec), -+} -+ + } + +/// Data returned by com.atproto.server.createSession xrpc calls. +#[derive(Clone, Debug, Deserialize, Serialize)] +#[serde(rename_all = "camelCase")] @@ -161,8 +160,8 @@ +pub struct AtProtoError { + pub error: AtProtoErrorKind, + pub message: String, - } - ++} ++ +/// Data returned by com.atproto.server.getSession xrpc calls. +#[derive(Clone, Debug, Deserialize, Serialize)] +#[serde(rename_all = "camelCase")] @@ -232,7 +231,7 @@ /// Messages from the script to the constellation. #[derive(Deserialize, IntoStaticStr, Serialize)] pub enum ScriptToConstellationMessage { -@@ -656,6 +827,10 @@ +@@ -653,6 +825,10 @@ NewBroadcastChannelNameInRouter(BroadcastChannelRouterId, String, ImmutableOrigin), /// A global stopped managing broadcast channels for a given channel-name. RemoveBroadcastChannelNameInRouter(BroadcastChannelRouterId, String, ImmutableOrigin), @@ -243,7 +242,7 @@ /// Broadcast a message to all same-origin broadcast channels, /// excluding the source of the broadcast. ScheduleBroadcast(BroadcastChannelRouterId, BroadcastChannelMsg), -@@ -674,6 +849,9 @@ +@@ -671,6 +847,9 @@ Option, Option, ), @@ -253,7 +252,7 @@ /// Indicates whether this pipeline is currently running animations. ChangeRunningAnimationsState(AnimationState), /// Register a dedicated worker that can receive animation frame ticks. -@@ -773,6 +951,10 @@ +@@ -770,6 +949,10 @@ ScriptNewIFrame(IFrameLoadInfoWithData), /// Script has opened a new auxiliary browsing context. CreateAuxiliaryWebView(AuxiliaryWebViewCreationRequest), @@ -264,7 +263,7 @@ /// Mark a new document as active ActivateDocument, /// Update the pipeline Url, which can change after redirections. -@@ -826,6 +1008,213 @@ +@@ -823,6 +1006,213 @@ /// aggregate lock count and notify the provider only when the count transitions from N to 0. /// ReleaseWakeLock(WakeLockType), diff --git a/patches/components/shared/constellation/lib.rs.patch b/patches/components/shared/constellation/lib.rs.patch index a052ac0..dea633c 100644 --- a/patches/components/shared/constellation/lib.rs.patch +++ b/patches/components/shared/constellation/lib.rs.patch @@ -311,8 +311,8 @@ /// Requests that the constellation instruct script/layout to try to layout again and tick /// animations. TickAnimation(Vec), -@@ -78,6 +346,12 @@ - BlurWebView, +@@ -77,6 +345,12 @@ + SetWebViewHasSystemFocus(WebViewId, bool), /// Forward an input event to an appropriate ScriptTask. ForwardInputEvent(WebViewId, InputEventAndId, Option), + /// Report how long the user has been idle system-wide, as the platform sees @@ -324,7 +324,7 @@ /// Request that the given pipeline refresh the cursor by doing a hit test at the most /// recently hovered cursor position and resetting the cursor. This happens after a /// display list update is rendered. -@@ -118,6 +392,9 @@ +@@ -117,6 +391,9 @@ /// Clears the session history for the `WebView` with the given `WebViewId`, leaving /// the `WebView` with only the current URL in its session history. ClearSessionHistory(WebViewId), diff --git a/patches/components/shared/embedder/input_events.rs.patch b/patches/components/shared/embedder/input_events.rs.patch index 72f1e47..564ea44 100644 --- a/patches/components/shared/embedder/input_events.rs.patch +++ b/patches/components/shared/embedder/input_events.rs.patch @@ -30,7 +30,7 @@ impl From for InputEventAndId { fn from(event: InputEvent) -> Self { Self { -@@ -101,6 +117,31 @@ +@@ -142,6 +158,31 @@ InputEvent::Wheel(event) => Some(event.point), } } @@ -62,7 +62,7 @@ } #[derive(Clone, Debug, Default, Deserialize, Serialize)] -@@ -149,6 +190,11 @@ +@@ -190,6 +231,11 @@ pub action: MouseButtonAction, pub button: MouseButton, pub point: WebViewPoint, @@ -74,7 +74,7 @@ } impl MouseButtonEvent { -@@ -157,8 +203,23 @@ +@@ -198,8 +244,23 @@ action, button, point, @@ -98,7 +98,7 @@ } /// The types of mouse buttons. -@@ -246,7 +307,7 @@ +@@ -287,7 +348,7 @@ } /// The type of input represented by a multi-touch event. diff --git a/patches/components/shared/script/lib.rs.patch b/patches/components/shared/script/lib.rs.patch index 56d7a29..f5201d8 100644 --- a/patches/components/shared/script/lib.rs.patch +++ b/patches/components/shared/script/lib.rs.patch @@ -1,6 +1,6 @@ --- original +++ modified -@@ -18,7 +18,8 @@ +@@ -19,7 +19,8 @@ use embedder_traits::{ EmbedderControlId, EmbedderControlResponse, FocusSequenceNumber, InputEventAndId, JavaScriptEvaluationId, MediaSessionActionType, MouseButton, PaintHitTestResult, @@ -10,7 +10,7 @@ }; use euclid::{Scale, Size2D}; use fonts_traits::{SystemFontServiceProxySender, WebFontLoadEvent}; -@@ -44,9 +45,9 @@ +@@ -45,9 +46,9 @@ use servo_canvas_traits::webgl::WebGLPipeline; use servo_config::prefs::PrefValue; use servo_constellation_traits::{ @@ -23,7 +23,7 @@ }; use servo_url::{ImmutableOrigin, OriginSnapshot, ServoUrl}; use storage_traits::StorageThreads; -@@ -85,6 +86,14 @@ +@@ -97,6 +98,14 @@ pub target_snapshot_params: TargetSnapshotParams, /// Name of this iframe, if any pub frame_name: Option, @@ -38,7 +38,7 @@ } /// When a pipeline is closed, should its browsing context be discarded too? -@@ -182,6 +191,14 @@ +@@ -194,6 +203,14 @@ PipelineId, GenericSender)>>, ), @@ -53,7 +53,7 @@ /// Notifies script thread of a change to one of its document's activity SetDocumentActivity(PipelineId, DocumentActivity), /// Set whether to use less resources by running timers at a heavily limited rate. -@@ -290,6 +307,15 @@ +@@ -302,6 +319,15 @@ SendImageKeysBatch(PipelineId, Vec), /// Preferences were updated in the parent process. PreferencesUpdated(Vec<(String, PrefValue)>), @@ -69,7 +69,7 @@ /// Notify the `ScriptThread` that the Servo renderer is no longer waiting on /// asynchronous image uploads for the given `Pipeline`. These are mainly used /// by canvas to perform uploads while the display list is being built. -@@ -324,6 +350,32 @@ +@@ -336,6 +362,32 @@ SetAccessibilityActive(PipelineId, bool, Epoch), /// Force a garbage collection in this script thread. TriggerGarbageCollection, -- 2.51.2