libservo: Add WebView immediately to the Compositor (#35662)

When creating a `WebView`, let the Compositor know synchronously that
it exists. This allows the embedder to immediately call methods like
`WebView::focus()`. In addition remove messages associated with the
`WebViewDelegate::notify_ready_to_show()` method (and the method
itself), as now `WebView`s can be shown immediately.

Signed-off-by: Martin Robinson <mrobinson@igalia.com>
This commit is contained in:
Martin Robinson 2025-02-26 17:16:48 +01:00 committed by GitHub
parent de66f72197
commit 9d5171f3c5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
12 changed files with 46 additions and 89 deletions

View file

@ -29,7 +29,7 @@ use euclid::{Box2D, Point2D, Rect, Scale, Size2D, Transform3D, Vector2D};
use fnv::{FnvHashMap, FnvHashSet};
use ipc_channel::ipc::{self, IpcSharedMemory};
use libc::c_void;
use log::{debug, error, info, trace, warn};
use log::{debug, info, trace, warn};
use pixels::{CorsStatus, Image, PixelFormat};
use profile_traits::time::{self as profile_time, ProfilerCategory};
use profile_traits::time_profile;
@ -59,7 +59,7 @@ use webrender_traits::{
};
use crate::touch::{TouchHandler, TouchMoveAction, TouchMoveAllowed, TouchSequenceState};
use crate::webview::{UnknownWebView, WebView, WebViewAlreadyExists, WebViewManager};
use crate::webview::{UnknownWebView, WebView, WebViewManager};
use crate::windowing::{self, EmbedderCoordinates, WebRenderDebugOption, WindowMethods};
use crate::InitialCompositorState;
@ -1007,42 +1007,33 @@ impl IOCompositor {
}
}
pub fn add_webview(&mut self, webview_id: WebViewId) {
let size = self.rendering_context.size2d().to_f32();
self.global.webviews.entry(webview_id).or_insert(WebView {
pipeline_id: None,
rect: Box2D::from_origin_and_size(Point2D::origin(), size),
});
}
fn set_frame_tree_for_webview(&mut self, frame_tree: &SendableFrameTree) {
debug!("{}: Setting frame tree for webview", frame_tree.pipeline.id);
let top_level_browsing_context_id = frame_tree.pipeline.top_level_browsing_context_id;
if let Some(webview) = self.global.webviews.get_mut(top_level_browsing_context_id) {
let new_pipeline_id = Some(frame_tree.pipeline.id);
if new_pipeline_id != webview.pipeline_id {
debug!(
"{:?}: Updating webview from pipeline {:?} to {:?}",
top_level_browsing_context_id, webview.pipeline_id, new_pipeline_id
);
}
webview.pipeline_id = new_pipeline_id;
} else {
let top_level_browsing_context_id = frame_tree.pipeline.top_level_browsing_context_id;
let pipeline_id = Some(frame_tree.pipeline.id);
debug!(
"{:?}: Creating new webview with pipeline {:?}",
top_level_browsing_context_id, pipeline_id
let webview_id = frame_tree.pipeline.top_level_browsing_context_id;
let Some(webview) = self.global.webviews.get_mut(webview_id) else {
warn!(
"Attempted to set frame tree on unknown WebView (perhaps closed?): {webview_id:?}"
);
return;
};
let new_pipeline_id = Some(frame_tree.pipeline.id);
if new_pipeline_id != webview.pipeline_id {
debug!(
"{webview_id:?}: Updating webview from pipeline {:?} to {new_pipeline_id:?}",
webview.pipeline_id
);
let size = self.rendering_context.size2d().to_f32();
if let Err(WebViewAlreadyExists(webview_id)) = self.global.webviews.add(
top_level_browsing_context_id,
WebView {
pipeline_id,
rect: Box2D::from_origin_and_size(Point2D::origin(), size),
},
) {
error!("{webview_id}: Creating webview that already exists");
return;
}
let msg = ConstellationMsg::WebViewOpened(top_level_browsing_context_id);
if let Err(e) = self.global.constellation_sender.send(msg) {
warn!("Sending event to constellation failed ({:?}).", e);
}
}
webview.pipeline_id = new_pipeline_id;
self.send_root_pipeline_display_list();
self.create_or_update_pipeline_details_with_frame_tree(frame_tree, None);

View file

@ -2,6 +2,7 @@
* 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/. */
use std::collections::hash_map::Entry;
use std::collections::HashMap;
use base::id::{PipelineId, WebViewId};
@ -23,24 +24,10 @@ pub struct WebViewManager<WebView> {
pub(crate) painting_order: Vec<WebViewId>,
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct WebViewAlreadyExists(pub WebViewId);
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct UnknownWebView(pub WebViewId);
impl<WebView> WebViewManager<WebView> {
pub fn add(
&mut self,
webview_id: WebViewId,
webview: WebView,
) -> Result<&mut WebView, WebViewAlreadyExists> {
if self.webviews.contains_key(&webview_id) {
return Err(WebViewAlreadyExists(webview_id));
}
Ok(self.webviews.entry(webview_id).or_insert(webview))
}
pub fn remove(&mut self, webview_id: WebViewId) -> Result<WebView, UnknownWebView> {
self.painting_order.retain(|b| *b != webview_id);
self.webviews
@ -107,6 +94,10 @@ impl<WebView> WebViewManager<WebView> {
.iter()
.flat_map(move |webview_id| self.get(*webview_id).map(|b| (webview_id, b)))
}
pub fn entry(&mut self, webview_id: WebViewId) -> Entry<'_, WebViewId, WebView> {
self.webviews.entry(webview_id)
}
}
#[cfg(test)]