Initial internal support for multiple webviews (#31417)

* Add multiple concurrent top-level browsing contexts

Co-authored-by: Delan Azabani <dazabani@igalia.com>

* Rename variables and comments

There are some variable and comments still use browser as names.
This commit renames them to webview.

* Update log message from web view to webview

* Revert offscreen_framebuffer_id rename

* Rename all web view to webview

* Cargo fmt

* Fix viewport/event/clear coordinates when multiview is disabled

* Only deprecate things when multiview is enabled

* Update WebViewManger with shown and invisible sets

Replace visible_webviews and native_window_is_visible with shown_webviews
and invisible_webviews. Add 4 more methods to set them accordingly. The
behavior of is_effectively_visible will return true if the wbview is in
shown_webviews set but not in invisible_webviews.

* Update variant behaviors

* Rename WebViewVisibilityChanged to MarkWebViewInvisible

* Fix unit test by marking id 3 visible again

* Update MarkWebViewInvisible and add UnmarkWebViewInvisible

* Update format and doc comments

* Clean up doc comments

* Address style and naming changes

* Rename UpdateWebView to UpdateFrameTreeForWebView

* constellation: send frame tree unconditionally over focus and feature

* Clarify shown and invisible sets in constellation WebViewManager

* Eliminate forward_to_constellation!()

* Actually remove the unused macro

* Don’t gate compositor changes on multiview feature flag

* Update todo in mouse event dispatch

* Pass all visible webview ids in a single ReadyToPresent message

* Fix compile and lint errors

* servoshell: fix gap between minibrowser toolbar and webview

* Fix failure in /_mozilla/mozilla/window_resizeTo.html

* Fix compile warnings

* Remove stray dbg!()

* Remove confusing “effectively visible” logic (see #31815, #31816)

* Allow embedder to show/hide/raise webviews without ipc

* Update root pipeline only when painting order actually changes

* Stop gating old focus and SetFrameTree behaviour behind Cargo feature

* Use webview_id and WebViewId in webview-related code

* Improve logging of webview-related embedder events

* Allow webview Show and Raise events to optionally hide all others

* Don’t do anything in response to WebViewPaintingOrder

* Remove WebViewPaintingOrder, since its payload is unreliable

* On MoveResizeWebView, only update root pipeline if rect changed

* Rename IOCompositor methods for clarity

* compositor: add event tracing; log webview ops even without ipc

* Add temporary debug logging

* Add more temporary debug logging

* Remove temporary logging in compositor

* Remove temporary debug logging

* Add temporary debug logging, but defer I/O until panic

* Capture a backtrace with each crash log entry

* Proper error handling without panicking in WebViewManager

* Clean up imports in constellation

---------

Co-authored-by: Delan Azabani <dazabani@igalia.com>
Co-authored-by: Martin Robinson <mrobinson@igalia.com>
This commit is contained in:
Ngo Iok Ui (Wu Yu Wei) 2024-04-03 20:06:28 +09:00 committed by GitHub
parent 18b37e676b
commit 66878fb834
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
21 changed files with 1142 additions and 434 deletions

View file

@ -19,7 +19,7 @@ use script_traits::{
use servo_geometry::DeviceIndependentPixel;
use servo_url::ServoUrl;
use style_traits::DevicePixel;
use webrender_api::units::{DeviceIntPoint, DeviceIntRect, DeviceIntSize, DevicePoint};
use webrender_api::units::{DeviceIntPoint, DeviceIntRect, DeviceIntSize, DevicePoint, DeviceRect};
use webrender_api::ScrollLocation;
#[derive(Clone)]
@ -51,7 +51,7 @@ pub enum EmbedderEvent {
/// message, the window must make the same GL context as in `PrepareRenderingEvent` current.
Refresh,
/// Sent when the window is resized.
Resize,
WindowResize,
/// Sent when a navigation request from script is allowed/refused.
AllowNavigationResponse(PipelineId, bool),
/// Sent when a new URL is to be loaded.
@ -83,15 +83,24 @@ pub enum EmbedderEvent {
Keyboard(KeyboardEvent),
/// Sent when Ctr+R/Apple+R is called to reload the current page.
Reload(TopLevelBrowsingContextId),
/// Create a new top level browsing context
/// Create a new top-level browsing context.
NewWebView(ServoUrl, TopLevelBrowsingContextId),
/// Close a top level browsing context
/// Close a top-level browsing context.
CloseWebView(TopLevelBrowsingContextId),
/// Panic a top level browsing context.
/// Panic a top-level browsing context.
SendError(Option<TopLevelBrowsingContextId>, String),
/// Make a top level browsing context visible, hiding the previous
/// visible one.
/// Move and/or resize a webview to the given rect.
MoveResizeWebView(TopLevelBrowsingContextId, DeviceRect),
/// Start painting a webview, and optionally stop painting all others.
ShowWebView(TopLevelBrowsingContextId, bool),
/// Stop painting a webview.
HideWebView(TopLevelBrowsingContextId),
/// Start painting a webview on top of all others, and optionally stop painting all others.
RaiseWebViewToTop(TopLevelBrowsingContextId, bool),
/// Make a webview focused.
FocusWebView(TopLevelBrowsingContextId),
/// Make none of the webviews focused.
BlurWebView,
/// Toggles a debug flag in WebRender
ToggleWebRenderDebug(WebRenderDebugOption),
/// Capture current WebRender
@ -124,7 +133,7 @@ impl Debug for EmbedderEvent {
match *self {
EmbedderEvent::Idle => write!(f, "Idle"),
EmbedderEvent::Refresh => write!(f, "Refresh"),
EmbedderEvent::Resize => write!(f, "Resize"),
EmbedderEvent::WindowResize => write!(f, "Resize"),
EmbedderEvent::Keyboard(..) => write!(f, "Keyboard"),
EmbedderEvent::AllowNavigationResponse(..) => write!(f, "AllowNavigationResponse"),
EmbedderEvent::LoadUrl(..) => write!(f, "LoadUrl"),
@ -139,10 +148,32 @@ impl Debug for EmbedderEvent {
EmbedderEvent::Navigation(..) => write!(f, "Navigation"),
EmbedderEvent::Quit => write!(f, "Quit"),
EmbedderEvent::Reload(..) => write!(f, "Reload"),
EmbedderEvent::NewWebView(..) => write!(f, "NewWebView"),
EmbedderEvent::NewWebView(_, TopLevelBrowsingContextId(webview_id)) => {
write!(f, "NewWebView({webview_id:?})")
},
EmbedderEvent::SendError(..) => write!(f, "SendError"),
EmbedderEvent::CloseWebView(..) => write!(f, "CloseWebView"),
EmbedderEvent::FocusWebView(..) => write!(f, "FocusWebView"),
EmbedderEvent::CloseWebView(TopLevelBrowsingContextId(webview_id)) => {
write!(f, "CloseWebView({webview_id:?})")
},
EmbedderEvent::MoveResizeWebView(webview_id, _) => {
write!(f, "MoveResizeWebView({webview_id:?})")
},
EmbedderEvent::ShowWebView(TopLevelBrowsingContextId(webview_id), hide_others) => {
write!(f, "ShowWebView({webview_id:?}, {hide_others})")
},
EmbedderEvent::HideWebView(TopLevelBrowsingContextId(webview_id)) => {
write!(f, "HideWebView({webview_id:?})")
},
EmbedderEvent::RaiseWebViewToTop(
TopLevelBrowsingContextId(webview_id),
hide_others,
) => {
write!(f, "RaiseWebViewToTop({webview_id:?}, {hide_others})")
},
EmbedderEvent::FocusWebView(TopLevelBrowsingContextId(webview_id)) => {
write!(f, "FocusWebView({webview_id:?})")
},
EmbedderEvent::BlurWebView => write!(f, "BlurWebView"),
EmbedderEvent::ToggleWebRenderDebug(..) => write!(f, "ToggleWebRenderDebug"),
EmbedderEvent::CaptureWebRender => write!(f, "CaptureWebRender"),
EmbedderEvent::ToggleSamplingProfiler(..) => write!(f, "ToggleSamplingProfiler"),
@ -211,15 +242,20 @@ pub struct EmbedderCoordinates {
impl EmbedderCoordinates {
/// Get the unflipped viewport rectangle for use with the WebRender API.
pub fn get_viewport(&self) -> DeviceIntRect {
DeviceIntRect::from_untyped(&self.viewport.to_untyped())
self.viewport.clone()
}
/// Get the flipped viewport rectangle. This should be used when drawing directly
/// to the framebuffer with OpenGL commands.
/// Flip the given rect.
/// This should be used when drawing directly to the framebuffer with OpenGL commands.
pub fn flip_rect(&self, rect: &DeviceIntRect) -> DeviceIntRect {
let mut result = rect.clone();
result.min.y = self.framebuffer.height - result.min.y - result.size().height;
result
}
/// Get the flipped viewport rectangle.
/// This should be used when drawing directly to the framebuffer with OpenGL commands.
pub fn get_flipped_viewport(&self) -> DeviceIntRect {
let fb_height = self.framebuffer.height;
let mut view = self.viewport;
view.min.y = fb_height - view.min.y - view.size().height;
DeviceIntRect::from_untyped(&view.to_untyped())
self.flip_rect(&self.get_viewport())
}
}