mirror of
https://github.com/servo/servo.git
synced 2025-08-05 13:40:08 +01:00
libservo: Create a WebViewBuilder
class to construct WebView
s (#36483)
This exposes a new method of creating `WebView`s using the Rust builder pattern. This will be more important as we add more kinds of configuration options for `WebView` such as size and HiDPI scaling. Testing: The API currently doesn't have tests, but functionality is ensured by the fact that servoshell is the test harness. Signed-off-by: Martin Robinson <mrobinson@igalia.com> Signed-off-by: Martin Robinson <mrobinson@igalia.com>
This commit is contained in:
parent
2454e00a68
commit
084fe007a1
5 changed files with 100 additions and 51 deletions
|
@ -7,7 +7,9 @@ use std::rc::Rc;
|
||||||
|
|
||||||
use compositing::windowing::{EmbedderMethods, WindowMethods};
|
use compositing::windowing::{EmbedderMethods, WindowMethods};
|
||||||
use euclid::{Point2D, Scale, Size2D};
|
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 servo_geometry::DeviceIndependentPixel;
|
||||||
use tracing::warn;
|
use tracing::warn;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
@ -53,8 +55,9 @@ impl ::servo::WebViewDelegate for AppState {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn request_open_auxiliary_webview(&self, parent_webview: WebView) -> Option<WebView> {
|
fn request_open_auxiliary_webview(&self, parent_webview: WebView) -> Option<WebView> {
|
||||||
let webview = self.servo.new_auxiliary_webview();
|
let webview = WebViewBuilder::new_auxiliary(&self.servo)
|
||||||
webview.set_delegate(parent_webview.delegate());
|
.delegate(parent_webview.delegate())
|
||||||
|
.build();
|
||||||
webview.focus();
|
webview.focus();
|
||||||
webview.raise_to_top(true);
|
webview.raise_to_top(true);
|
||||||
self.webviews.borrow_mut().push(webview.clone());
|
self.webviews.borrow_mut().push(webview.clone());
|
||||||
|
@ -115,8 +118,10 @@ impl ApplicationHandler<WakerEvent> for App {
|
||||||
let url = Url::parse("https://demo.servo.org/experiments/twgl-tunnel/")
|
let url = Url::parse("https://demo.servo.org/experiments/twgl-tunnel/")
|
||||||
.expect("Guaranteed by argument");
|
.expect("Guaranteed by argument");
|
||||||
|
|
||||||
let webview = app_state.servo.new_webview(url);
|
let webview = WebViewBuilder::new(&app_state.servo)
|
||||||
webview.set_delegate(app_state.clone());
|
.url(url)
|
||||||
|
.delegate(app_state.clone())
|
||||||
|
.build();
|
||||||
webview.focus();
|
webview.focus();
|
||||||
webview.raise_to_top(true);
|
webview.raise_to_top(true);
|
||||||
|
|
||||||
|
|
|
@ -119,7 +119,7 @@ pub use {bluetooth, bluetooth_traits};
|
||||||
use crate::proxies::ConstellationProxy;
|
use crate::proxies::ConstellationProxy;
|
||||||
use crate::responders::ServoErrorChannel;
|
use crate::responders::ServoErrorChannel;
|
||||||
pub use crate::servo_delegate::{ServoDelegate, ServoError};
|
pub use crate::servo_delegate::{ServoDelegate, ServoError};
|
||||||
pub use crate::webview::WebView;
|
pub use crate::webview::{WebView, WebViewBuilder};
|
||||||
pub use crate::webview_delegate::{
|
pub use crate::webview_delegate::{
|
||||||
AllowOrDenyRequest, AuthenticationRequest, FormControl, NavigationRequest, PermissionRequest,
|
AllowOrDenyRequest, AuthenticationRequest, FormControl, NavigationRequest, PermissionRequest,
|
||||||
SelectElement, WebResourceLoad, WebViewDelegate,
|
SelectElement, WebResourceLoad, WebViewDelegate,
|
||||||
|
@ -661,29 +661,6 @@ impl Servo {
|
||||||
self.compositor.borrow_mut().deinit();
|
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<WebView> {
|
fn get_webview_handle(&self, id: WebViewId) -> Option<WebView> {
|
||||||
self.webviews
|
self.webviews
|
||||||
.borrow()
|
.borrow()
|
||||||
|
|
|
@ -20,9 +20,9 @@ use url::Url;
|
||||||
use webrender_api::ScrollLocation;
|
use webrender_api::ScrollLocation;
|
||||||
use webrender_api::units::{DeviceIntPoint, DeviceRect};
|
use webrender_api::units::{DeviceIntPoint, DeviceRect};
|
||||||
|
|
||||||
use crate::ConstellationProxy;
|
|
||||||
use crate::clipboard_delegate::{ClipboardDelegate, DefaultClipboardDelegate};
|
use crate::clipboard_delegate::{ClipboardDelegate, DefaultClipboardDelegate};
|
||||||
use crate::webview_delegate::{DefaultWebViewDelegate, WebViewDelegate};
|
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,
|
/// 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
|
/// 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 {
|
impl WebView {
|
||||||
pub(crate) fn new(
|
pub(crate) fn new(builder: WebViewBuilder) -> Self {
|
||||||
constellation_proxy: &ConstellationProxy,
|
|
||||||
compositor: Rc<RefCell<IOCompositor>>,
|
|
||||||
) -> Self {
|
|
||||||
let id = WebViewId::new();
|
let id = WebViewId::new();
|
||||||
|
let servo = builder.servo;
|
||||||
|
|
||||||
let webview = Self(Rc::new(RefCell::new(WebViewInner {
|
let webview = Self(Rc::new(RefCell::new(WebViewInner {
|
||||||
id,
|
id,
|
||||||
constellation_proxy: constellation_proxy.clone(),
|
constellation_proxy: servo.constellation_proxy.clone(),
|
||||||
compositor: compositor.clone(),
|
compositor: servo.compositor.clone(),
|
||||||
delegate: Rc::new(DefaultWebViewDelegate),
|
delegate: builder.delegate,
|
||||||
clipboard_delegate: Rc::new(DefaultClipboardDelegate),
|
clipboard_delegate: Rc::new(DefaultClipboardDelegate),
|
||||||
rect: DeviceRect::zero(),
|
rect: DeviceRect::zero(),
|
||||||
load_status: LoadStatus::Complete,
|
load_status: LoadStatus::Complete,
|
||||||
|
@ -115,13 +114,35 @@ impl WebView {
|
||||||
cursor: Cursor::Pointer,
|
cursor: Cursor::Pointer,
|
||||||
})));
|
})));
|
||||||
|
|
||||||
compositor
|
builder
|
||||||
|
.servo
|
||||||
|
.compositor
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
.add_webview(Box::new(ServoRendererWebView {
|
.add_webview(Box::new(ServoRendererWebView {
|
||||||
weak_handle: webview.weak_handle(),
|
weak_handle: webview.weak_handle(),
|
||||||
id,
|
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
|
webview
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -508,3 +529,41 @@ impl RendererWebView for ServoRendererWebView {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct WebViewBuilder<'servo> {
|
||||||
|
servo: &'servo Servo,
|
||||||
|
delegate: Rc<dyn WebViewDelegate>,
|
||||||
|
auxiliary: bool,
|
||||||
|
url: Option<Url>,
|
||||||
|
}
|
||||||
|
|
||||||
|
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<dyn WebViewDelegate>) -> 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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -19,7 +19,7 @@ use servo::webrender_api::units::{DeviceIntPoint, DeviceIntRect, DeviceIntSize};
|
||||||
use servo::{
|
use servo::{
|
||||||
AllowOrDenyRequest, AuthenticationRequest, FilterPattern, FormControl, GamepadHapticEffectType,
|
AllowOrDenyRequest, AuthenticationRequest, FilterPattern, FormControl, GamepadHapticEffectType,
|
||||||
LoadStatus, PermissionRequest, Servo, ServoDelegate, ServoError, SimpleDialog, TouchEventType,
|
LoadStatus, PermissionRequest, Servo, ServoDelegate, ServoError, SimpleDialog, TouchEventType,
|
||||||
WebView, WebViewDelegate,
|
WebView, WebViewBuilder, WebViewDelegate,
|
||||||
};
|
};
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
|
@ -107,8 +107,10 @@ impl RunningAppState {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn new_toplevel_webview(self: &Rc<Self>, url: Url) {
|
pub(crate) fn new_toplevel_webview(self: &Rc<Self>, url: Url) {
|
||||||
let webview = self.servo().new_webview(url);
|
let webview = WebViewBuilder::new(self.servo())
|
||||||
webview.set_delegate(self.clone());
|
.url(url)
|
||||||
|
.delegate(self.clone())
|
||||||
|
.build();
|
||||||
|
|
||||||
webview.focus();
|
webview.focus();
|
||||||
webview.raise_to_top(true);
|
webview.raise_to_top(true);
|
||||||
|
@ -459,8 +461,9 @@ impl WebViewDelegate for RunningAppState {
|
||||||
&self,
|
&self,
|
||||||
parent_webview: servo::WebView,
|
parent_webview: servo::WebView,
|
||||||
) -> Option<servo::WebView> {
|
) -> Option<servo::WebView> {
|
||||||
let webview = self.servo.new_auxiliary_webview();
|
let webview = WebViewBuilder::new_auxiliary(&self.servo)
|
||||||
webview.set_delegate(parent_webview.delegate());
|
.delegate(parent_webview.delegate())
|
||||||
|
.build();
|
||||||
|
|
||||||
webview.focus();
|
webview.focus();
|
||||||
webview.raise_to_top(true);
|
webview.raise_to_top(true);
|
||||||
|
|
|
@ -21,8 +21,8 @@ use servo::{
|
||||||
InputMethodType, Key, KeyState, KeyboardEvent, LoadStatus, MediaSessionActionType,
|
InputMethodType, Key, KeyState, KeyboardEvent, LoadStatus, MediaSessionActionType,
|
||||||
MediaSessionEvent, MouseButton, MouseButtonAction, MouseButtonEvent, MouseMoveEvent,
|
MediaSessionEvent, MouseButton, MouseButtonAction, MouseButtonEvent, MouseMoveEvent,
|
||||||
NavigationRequest, PermissionRequest, RenderingContext, ScreenGeometry, Servo, ServoDelegate,
|
NavigationRequest, PermissionRequest, RenderingContext, ScreenGeometry, Servo, ServoDelegate,
|
||||||
ServoError, SimpleDialog, TouchEvent, TouchEventType, TouchId, WebView, WebViewDelegate,
|
ServoError, SimpleDialog, TouchEvent, TouchEventType, TouchId, WebView, WebViewBuilder,
|
||||||
WindowRenderingContext,
|
WebViewDelegate, WindowRenderingContext,
|
||||||
};
|
};
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
|
@ -211,10 +211,12 @@ impl WebViewDelegate for RunningAppState {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn request_open_auxiliary_webview(&self, _parent_webview: WebView) -> Option<WebView> {
|
fn request_open_auxiliary_webview(&self, parent_webview: WebView) -> Option<WebView> {
|
||||||
let new_webview = self.servo.new_auxiliary_webview();
|
let webview = WebViewBuilder::new_auxiliary(&self.servo)
|
||||||
self.add(new_webview.clone());
|
.delegate(parent_webview.delegate())
|
||||||
Some(new_webview)
|
.build();
|
||||||
|
self.add(webview.clone());
|
||||||
|
Some(webview)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn request_permission(&self, webview: WebView, request: PermissionRequest) {
|
fn request_permission(&self, webview: WebView, request: PermissionRequest) {
|
||||||
|
@ -309,8 +311,11 @@ impl RunningAppState {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn new_toplevel_webview(self: &Rc<Self>, url: Url) {
|
pub(crate) fn new_toplevel_webview(self: &Rc<Self>, url: Url) {
|
||||||
let webview = self.servo.new_webview(url);
|
let webview = WebViewBuilder::new(&self.servo)
|
||||||
webview.set_delegate(self.clone());
|
.url(url)
|
||||||
|
.delegate(self.clone())
|
||||||
|
.build();
|
||||||
|
|
||||||
webview.focus();
|
webview.focus();
|
||||||
self.add(webview.clone());
|
self.add(webview.clone());
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue