diff --git a/components/servo/examples/winit_minimal.rs b/components/servo/examples/winit_minimal.rs index 1f6dbbe5c12..9f4017b4c3b 100644 --- a/components/servo/examples/winit_minimal.rs +++ b/components/servo/examples/winit_minimal.rs @@ -7,7 +7,9 @@ use std::rc::Rc; use compositing::windowing::{EmbedderMethods, WindowMethods}; use euclid::{Point2D, Scale, Size2D}; -use servo::{RenderingContext, Servo, TouchEventType, WebView, WindowRenderingContext}; +use servo::{ + RenderingContext, Servo, TouchEventType, WebView, WebViewBuilder, WindowRenderingContext, +}; use servo_geometry::DeviceIndependentPixel; use tracing::warn; use url::Url; @@ -53,8 +55,9 @@ impl ::servo::WebViewDelegate for AppState { } fn request_open_auxiliary_webview(&self, parent_webview: WebView) -> Option { - let webview = self.servo.new_auxiliary_webview(); - webview.set_delegate(parent_webview.delegate()); + let webview = WebViewBuilder::new_auxiliary(&self.servo) + .delegate(parent_webview.delegate()) + .build(); webview.focus(); webview.raise_to_top(true); self.webviews.borrow_mut().push(webview.clone()); @@ -115,8 +118,10 @@ impl ApplicationHandler for App { let url = Url::parse("https://demo.servo.org/experiments/twgl-tunnel/") .expect("Guaranteed by argument"); - let webview = app_state.servo.new_webview(url); - webview.set_delegate(app_state.clone()); + let webview = WebViewBuilder::new(&app_state.servo) + .url(url) + .delegate(app_state.clone()) + .build(); webview.focus(); webview.raise_to_top(true); diff --git a/components/servo/lib.rs b/components/servo/lib.rs index eea6ea01392..1b13729e9c7 100644 --- a/components/servo/lib.rs +++ b/components/servo/lib.rs @@ -119,7 +119,7 @@ pub use {bluetooth, bluetooth_traits}; use crate::proxies::ConstellationProxy; use crate::responders::ServoErrorChannel; pub use crate::servo_delegate::{ServoDelegate, ServoError}; -pub use crate::webview::WebView; +pub use crate::webview::{WebView, WebViewBuilder}; pub use crate::webview_delegate::{ AllowOrDenyRequest, AuthenticationRequest, FormControl, NavigationRequest, PermissionRequest, SelectElement, WebResourceLoad, WebViewDelegate, @@ -661,29 +661,6 @@ impl Servo { self.compositor.borrow_mut().deinit(); } - pub fn new_webview(&self, url: url::Url) -> WebView { - let webview = WebView::new(&self.constellation_proxy, self.compositor.clone()); - self.webviews - .borrow_mut() - .insert(webview.id(), webview.weak_handle()); - let viewport_details = self.compositor.borrow().default_webview_viewport_details(); - self.constellation_proxy - .send(EmbedderToConstellationMessage::NewWebView( - url.into(), - webview.id(), - viewport_details, - )); - webview - } - - pub fn new_auxiliary_webview(&self) -> WebView { - let webview = WebView::new(&self.constellation_proxy, self.compositor.clone()); - self.webviews - .borrow_mut() - .insert(webview.id(), webview.weak_handle()); - webview - } - fn get_webview_handle(&self, id: WebViewId) -> Option { self.webviews .borrow() diff --git a/components/servo/webview.rs b/components/servo/webview.rs index 92564753168..5c687a47f8a 100644 --- a/components/servo/webview.rs +++ b/components/servo/webview.rs @@ -20,9 +20,9 @@ use url::Url; use webrender_api::ScrollLocation; use webrender_api::units::{DeviceIntPoint, DeviceRect}; -use crate::ConstellationProxy; use crate::clipboard_delegate::{ClipboardDelegate, DefaultClipboardDelegate}; use crate::webview_delegate::{DefaultWebViewDelegate, WebViewDelegate}; +use crate::{ConstellationProxy, Servo}; /// A handle to a Servo webview. If you clone this handle, it does not create a new webview, /// but instead creates a new handle to the webview. Once the last handle is dropped, Servo @@ -93,16 +93,15 @@ impl Drop for WebViewInner { } impl WebView { - pub(crate) fn new( - constellation_proxy: &ConstellationProxy, - compositor: Rc>, - ) -> Self { + pub(crate) fn new(builder: WebViewBuilder) -> Self { let id = WebViewId::new(); + let servo = builder.servo; + let webview = Self(Rc::new(RefCell::new(WebViewInner { id, - constellation_proxy: constellation_proxy.clone(), - compositor: compositor.clone(), - delegate: Rc::new(DefaultWebViewDelegate), + constellation_proxy: servo.constellation_proxy.clone(), + compositor: servo.compositor.clone(), + delegate: builder.delegate, clipboard_delegate: Rc::new(DefaultClipboardDelegate), rect: DeviceRect::zero(), load_status: LoadStatus::Complete, @@ -115,13 +114,35 @@ impl WebView { cursor: Cursor::Pointer, }))); - compositor + builder + .servo + .compositor .borrow_mut() .add_webview(Box::new(ServoRendererWebView { weak_handle: webview.weak_handle(), id, })); + servo + .webviews + .borrow_mut() + .insert(webview.id(), webview.weak_handle()); + + if !builder.auxiliary { + let url = builder.url.unwrap_or( + Url::parse("about:blank").expect("Should always be able to parse 'about:blank'."), + ); + + let viewport_details = servo.compositor.borrow().default_webview_viewport_details(); + servo + .constellation_proxy + .send(EmbedderToConstellationMessage::NewWebView( + url.into(), + webview.id(), + viewport_details, + )); + } + webview } @@ -508,3 +529,41 @@ impl RendererWebView for ServoRendererWebView { } } } + +pub struct WebViewBuilder<'servo> { + servo: &'servo Servo, + delegate: Rc, + auxiliary: bool, + url: Option, +} + +impl<'servo> WebViewBuilder<'servo> { + pub fn new(servo: &'servo Servo) -> Self { + Self { + servo, + auxiliary: false, + url: None, + delegate: Rc::new(DefaultWebViewDelegate), + } + } + + pub fn new_auxiliary(servo: &'servo Servo) -> Self { + let mut builder = Self::new(servo); + builder.auxiliary = true; + builder + } + + pub fn delegate(mut self, delegate: Rc) -> Self { + self.delegate = delegate; + self + } + + pub fn url(mut self, url: Url) -> Self { + self.url = Some(url); + self + } + + pub fn build(self) -> WebView { + WebView::new(self) + } +} diff --git a/ports/servoshell/desktop/app_state.rs b/ports/servoshell/desktop/app_state.rs index 3bb381bb1a0..d60371d7acb 100644 --- a/ports/servoshell/desktop/app_state.rs +++ b/ports/servoshell/desktop/app_state.rs @@ -19,7 +19,7 @@ use servo::webrender_api::units::{DeviceIntPoint, DeviceIntRect, DeviceIntSize}; use servo::{ AllowOrDenyRequest, AuthenticationRequest, FilterPattern, FormControl, GamepadHapticEffectType, LoadStatus, PermissionRequest, Servo, ServoDelegate, ServoError, SimpleDialog, TouchEventType, - WebView, WebViewDelegate, + WebView, WebViewBuilder, WebViewDelegate, }; use url::Url; @@ -107,8 +107,10 @@ impl RunningAppState { } pub(crate) fn new_toplevel_webview(self: &Rc, url: Url) { - let webview = self.servo().new_webview(url); - webview.set_delegate(self.clone()); + let webview = WebViewBuilder::new(self.servo()) + .url(url) + .delegate(self.clone()) + .build(); webview.focus(); webview.raise_to_top(true); @@ -459,8 +461,9 @@ impl WebViewDelegate for RunningAppState { &self, parent_webview: servo::WebView, ) -> Option { - let webview = self.servo.new_auxiliary_webview(); - webview.set_delegate(parent_webview.delegate()); + let webview = WebViewBuilder::new_auxiliary(&self.servo) + .delegate(parent_webview.delegate()) + .build(); webview.focus(); webview.raise_to_top(true); diff --git a/ports/servoshell/egl/app_state.rs b/ports/servoshell/egl/app_state.rs index 8bf343878fb..4bf7cd2b839 100644 --- a/ports/servoshell/egl/app_state.rs +++ b/ports/servoshell/egl/app_state.rs @@ -21,8 +21,8 @@ use servo::{ InputMethodType, Key, KeyState, KeyboardEvent, LoadStatus, MediaSessionActionType, MediaSessionEvent, MouseButton, MouseButtonAction, MouseButtonEvent, MouseMoveEvent, NavigationRequest, PermissionRequest, RenderingContext, ScreenGeometry, Servo, ServoDelegate, - ServoError, SimpleDialog, TouchEvent, TouchEventType, TouchId, WebView, WebViewDelegate, - WindowRenderingContext, + ServoError, SimpleDialog, TouchEvent, TouchEventType, TouchId, WebView, WebViewBuilder, + WebViewDelegate, WindowRenderingContext, }; use url::Url; @@ -211,10 +211,12 @@ impl WebViewDelegate for RunningAppState { } } - fn request_open_auxiliary_webview(&self, _parent_webview: WebView) -> Option { - let new_webview = self.servo.new_auxiliary_webview(); - self.add(new_webview.clone()); - Some(new_webview) + fn request_open_auxiliary_webview(&self, parent_webview: WebView) -> Option { + let webview = WebViewBuilder::new_auxiliary(&self.servo) + .delegate(parent_webview.delegate()) + .build(); + self.add(webview.clone()); + Some(webview) } fn request_permission(&self, webview: WebView, request: PermissionRequest) { @@ -309,8 +311,11 @@ impl RunningAppState { } pub(crate) fn new_toplevel_webview(self: &Rc, url: Url) { - let webview = self.servo.new_webview(url); - webview.set_delegate(self.clone()); + let webview = WebViewBuilder::new(&self.servo) + .url(url) + .delegate(self.clone()) + .build(); + webview.focus(); self.add(webview.clone()); }