webdriver: Move NewWebView, FocusWebView, GetWindowSize, and SetWindowSize to servoshell (#37555)

Follow up to: https://github.com/servo/servo/pull/36714
Moving webdriver [context
commands](https://www.w3.org/TR/webdriver2/#contexts) to be handled in
embedder:

- [x] New Window command - `WebdriverCommandMsg::NewWebView`
- [x]  Switch To Window command - `WebdriverCommandMsg::FocusWebView`
- [x] Resizing commands

cc: @xiaochengh

---------

Signed-off-by: batu_hoang <longvatrong111@gmail.com>
This commit is contained in:
batu_hoang 2025-06-25 18:29:34 +08:00 committed by GitHub
parent 5ea003752a
commit d970584332
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 148 additions and 97 deletions

View file

@ -4542,41 +4542,11 @@ where
WebDriverCommandMsg::CloseWebView(..) => { WebDriverCommandMsg::CloseWebView(..) => {
unreachable!("This command should be send directly to the embedder."); unreachable!("This command should be send directly to the embedder.");
}, },
WebDriverCommandMsg::NewWebView( WebDriverCommandMsg::NewWebView(..) => {
originating_webview_id, unreachable!("This command should be send directly to the embedder.");
response_sender,
load_status_sender,
) => {
let (embedder_sender, receiver) = match ipc::channel() {
Ok(result) => result,
Err(error) => return warn!("Failed to create channel: {error:?}"),
};
self.embedder_proxy.send(EmbedderMsg::AllowOpeningWebView(
originating_webview_id,
embedder_sender,
));
let (new_webview_id, viewport_details) = match receiver.recv() {
Ok(Some((new_webview_id, viewport_details))) => {
(new_webview_id, viewport_details)
}, },
Ok(None) => return warn!("Embedder refused to allow opening webview"), WebDriverCommandMsg::FocusWebView(..) => {
Err(error) => return warn!("Failed to receive webview id: {error:?}"), unreachable!("This command should be send directly to the embedder.");
};
self.handle_new_top_level_browsing_context(
ServoUrl::parse_with_base(None, "about:blank").expect("Infallible parse"),
new_webview_id,
viewport_details,
Some(load_status_sender),
);
if let Err(error) = response_sender.send(new_webview_id) {
error!(
"WebDriverCommandMsg::NewWebView: IPC error when sending new_webview_id \
to webdriver server: {error}"
);
}
},
WebDriverCommandMsg::FocusWebView(webview_id) => {
self.handle_focus_web_view(webview_id);
}, },
WebDriverCommandMsg::IsWebViewOpen(..) => { WebDriverCommandMsg::IsWebViewOpen(..) => {
unreachable!("This command should be send directly to the embedder."); unreachable!("This command should be send directly to the embedder.");
@ -4585,7 +4555,10 @@ where
let is_open = self.browsing_contexts.contains_key(&browsing_context_id); let is_open = self.browsing_contexts.contains_key(&browsing_context_id);
let _ = response_sender.send(is_open); let _ = response_sender.send(is_open);
}, },
WebDriverCommandMsg::GetWindowSize(webview_id, response_sender) => { WebDriverCommandMsg::GetWindowSize(..) => {
unreachable!("This command should be send directly to the embedder.");
},
WebDriverCommandMsg::GetViewportSize(webview_id, response_sender) => {
let browsing_context_id = BrowsingContextId::from(webview_id); let browsing_context_id = BrowsingContextId::from(webview_id);
let size = self let size = self
.browsing_contexts .browsing_contexts
@ -4594,10 +4567,8 @@ where
.unwrap_or_default(); .unwrap_or_default();
let _ = response_sender.send(size); let _ = response_sender.send(size);
}, },
WebDriverCommandMsg::SetWindowSize(webview_id, size, response_sender) => { WebDriverCommandMsg::SetWindowSize(..) => {
self.webdriver.resize_channel = Some(response_sender); unreachable!("This command should be send directly to the embedder.");
self.embedder_proxy
.send(EmbedderMsg::ResizeTo(webview_id, size));
}, },
WebDriverCommandMsg::LoadUrl(webview_id, url, response_sender) => { WebDriverCommandMsg::LoadUrl(webview_id, url, response_sender) => {
let load_data = LoadData::new( let load_data = LoadData::new(
@ -4767,6 +4738,9 @@ where
response_sender, response_sender,
)); ));
}, },
_ => {
warn!("Unhandled WebDriver command: {:?}", msg);
},
} }
} }

View file

@ -20,7 +20,7 @@ use servo_url::ServoUrl;
use style_traits::CSSPixel; use style_traits::CSSPixel;
use webdriver::common::{WebElement, WebFrame, WebWindow}; use webdriver::common::{WebElement, WebFrame, WebWindow};
use webdriver::error::ErrorStatus; use webdriver::error::ErrorStatus;
use webrender_api::units::DeviceIntSize; use webrender_api::units::{DeviceIntSize, DevicePixel};
use crate::{MouseButton, MouseButtonAction}; use crate::{MouseButton, MouseButtonAction};
@ -31,7 +31,9 @@ pub struct WebDriverMessageId(pub usize);
#[derive(Debug, Deserialize, Serialize)] #[derive(Debug, Deserialize, Serialize)]
pub enum WebDriverCommandMsg { pub enum WebDriverCommandMsg {
/// Get the window size. /// Get the window size.
GetWindowSize(WebViewId, IpcSender<Size2D<f32, CSSPixel>>), GetWindowSize(WebViewId, IpcSender<Size2D<i32, DevicePixel>>),
/// Get the viewport size.
GetViewportSize(WebViewId, IpcSender<Size2D<f32, CSSPixel>>),
/// Load a URL in the top-level browsing context with the given ID. /// Load a URL in the top-level browsing context with the given ID.
LoadUrl(WebViewId, ServoUrl, IpcSender<WebDriverLoadStatus>), LoadUrl(WebViewId, ServoUrl, IpcSender<WebDriverLoadStatus>),
/// Refresh the top-level browsing context with the given ID. /// Refresh the top-level browsing context with the given ID.
@ -83,7 +85,11 @@ pub enum WebDriverCommandMsg {
IpcSender<WebDriverCommandResponse>, IpcSender<WebDriverCommandResponse>,
), ),
/// Set the window size. /// Set the window size.
SetWindowSize(WebViewId, DeviceIntSize, IpcSender<Size2D<f32, CSSPixel>>), SetWindowSize(
WebViewId,
DeviceIntSize,
IpcSender<Size2D<i32, DevicePixel>>,
),
/// Take a screenshot of the window. /// Take a screenshot of the window.
TakeScreenshot( TakeScreenshot(
WebViewId, WebViewId,
@ -94,15 +100,13 @@ pub enum WebDriverCommandMsg {
/// the provided channels to return the top level browsing context id /// the provided channels to return the top level browsing context id
/// associated with the new webview, and a notification when the initial /// associated with the new webview, and a notification when the initial
/// load is complete. /// load is complete.
NewWebView( NewWebView(IpcSender<WebViewId>, IpcSender<WebDriverLoadStatus>),
WebViewId,
IpcSender<WebViewId>,
IpcSender<WebDriverLoadStatus>,
),
/// Close the webview associated with the provided id. /// Close the webview associated with the provided id.
CloseWebView(WebViewId), CloseWebView(WebViewId),
/// Focus the webview associated with the provided id. /// Focus the webview associated with the provided id.
FocusWebView(WebViewId), FocusWebView(WebViewId),
/// Get focused webview.
GetFocusedWebView(IpcSender<Option<WebViewId>>),
/// Check whether top-level browsing context is open. /// Check whether top-level browsing context is open.
IsWebViewOpen(WebViewId, IpcSender<bool>), IsWebViewOpen(WebViewId, IpcSender<bool>),
/// Check whether browsing context is open. /// Check whether browsing context is open.

View file

@ -517,11 +517,8 @@ impl Handler {
} }
fn focus_webview_id(&self) -> WebDriverResult<WebViewId> { fn focus_webview_id(&self) -> WebDriverResult<WebViewId> {
debug!("Getting focused context.");
let (sender, receiver) = ipc::channel().unwrap(); let (sender, receiver) = ipc::channel().unwrap();
self.send_message_to_embedder(WebDriverCommandMsg::GetFocusedWebView(sender.clone()))?;
let msg = EmbedderToConstellationMessage::GetFocusTopLevelBrowsingContext(sender.clone());
self.constellation_chan.send(msg).unwrap();
// Wait until the document is ready before returning the top-level browsing context id. // Wait until the document is ready before returning the top-level browsing context id.
match wait_for_script_response(receiver)? { match wait_for_script_response(receiver)? {
Some(webview_id) => Ok(webview_id), Some(webview_id) => Ok(webview_id),
@ -807,18 +804,14 @@ impl Handler {
self.verify_top_level_browsing_context_is_open(webview_id)?; self.verify_top_level_browsing_context_is_open(webview_id)?;
let cmd_msg = WebDriverCommandMsg::GetWindowSize(webview_id, sender); self.send_message_to_embedder(WebDriverCommandMsg::GetWindowSize(webview_id, sender))?;
self.constellation_chan
.send(EmbedderToConstellationMessage::WebDriverCommand(cmd_msg))
.unwrap();
let window_size = wait_for_script_response(receiver)?; let window_size = wait_for_script_response(receiver)?;
let window_size_response = WindowRectResponse { let window_size_response = WindowRectResponse {
x: 0, x: 0,
y: 0, y: 0,
width: window_size.width as i32, width: window_size.width,
height: window_size.height as i32, height: window_size.height,
}; };
Ok(WebDriverResponse::WindowRect(window_size_response)) Ok(WebDriverResponse::WindowRect(window_size_response))
} }
@ -844,30 +837,30 @@ impl Handler {
// Step 12. If session's current top-level browsing context is no longer open, // Step 12. If session's current top-level browsing context is no longer open,
// return error with error code no such window. // return error with error code no such window.
self.verify_top_level_browsing_context_is_open(webview_id)?; self.verify_top_level_browsing_context_is_open(webview_id)?;
let cmd_msg = WebDriverCommandMsg::SetWindowSize(webview_id, size.to_i32(), sender.clone());
self.constellation_chan self.send_message_to_embedder(WebDriverCommandMsg::SetWindowSize(
.send(EmbedderToConstellationMessage::WebDriverCommand(cmd_msg)) webview_id,
.unwrap(); size.to_i32(),
sender.clone(),
))?;
let timeout = self.resize_timeout; let timeout = self.resize_timeout;
let constellation_chan = self.constellation_chan.clone(); let embedder_sender = self.embedder_sender.clone();
let waker = self.event_loop_waker.clone();
thread::spawn(move || { thread::spawn(move || {
// On timeout, we send a GetWindowSize message to the constellation, // On timeout, we send a GetWindowSize message to the constellation,
// which will give the current window size. // which will give the current window size.
thread::sleep(Duration::from_millis(timeout as u64)); thread::sleep(Duration::from_millis(timeout as u64));
let cmd_msg = WebDriverCommandMsg::GetWindowSize(webview_id, sender); let _ = embedder_sender.send(WebDriverCommandMsg::GetWindowSize(webview_id, sender));
constellation_chan waker.wake();
.send(EmbedderToConstellationMessage::WebDriverCommand(cmd_msg))
.unwrap();
}); });
let window_size = wait_for_script_response(receiver)?; let window_size = wait_for_script_response(receiver)?;
let window_size_response = WindowRectResponse { let window_size_response = WindowRectResponse {
x: 0, x: 0,
y: 0, y: 0,
width: window_size.width as i32, width: window_size.width,
height: window_size.height as i32, height: window_size.height,
}; };
Ok(WebDriverResponse::WindowRect(window_size_response)) Ok(WebDriverResponse::WindowRect(window_size_response))
} }
@ -1071,16 +1064,10 @@ impl Handler {
let session = self.session().unwrap(); let session = self.session().unwrap();
self.verify_top_level_browsing_context_is_open(session.webview_id)?; self.verify_top_level_browsing_context_is_open(session.webview_id)?;
let cmd_msg = WebDriverCommandMsg::NewWebView( let cmd_msg = WebDriverCommandMsg::NewWebView(sender, self.load_status_sender.clone());
session.webview_id,
sender,
self.load_status_sender.clone(),
);
// Step 5. Create a new top-level browsing context by running the window open steps. // Step 5. Create a new top-level browsing context by running the window open steps.
// This MUST be done without invoking the focusing steps. // This MUST be done without invoking the focusing steps.
self.constellation_chan self.send_message_to_embedder(cmd_msg)?;
.send(EmbedderToConstellationMessage::WebDriverCommand(cmd_msg))
.unwrap();
let mut handle = self.session.as_ref().unwrap().id.to_string(); let mut handle = self.session.as_ref().unwrap().id.to_string();
if let Ok(new_webview_id) = receiver.recv() { if let Ok(new_webview_id) = receiver.recv() {
@ -1145,8 +1132,8 @@ impl Handler {
session.webview_id = webview_id; session.webview_id = webview_id;
session.browsing_context_id = BrowsingContextId::from(webview_id); session.browsing_context_id = BrowsingContextId::from(webview_id);
let msg = EmbedderToConstellationMessage::FocusWebView(webview_id); let msg = WebDriverCommandMsg::FocusWebView(webview_id);
self.constellation_chan.send(msg).unwrap(); self.send_message_to_embedder(msg)?;
Ok(WebDriverResponse::Void) Ok(WebDriverResponse::Void)
} else { } else {
Err(WebDriverError::new( Err(WebDriverError::new(

View file

@ -182,7 +182,7 @@ impl App {
self.servoshell_preferences.clone(), self.servoshell_preferences.clone(),
webdriver_receiver, webdriver_receiver,
)); ));
running_state.new_toplevel_webview(self.initial_url.clone().into_url()); running_state.create_and_focus_toplevel_webview(self.initial_url.clone().into_url());
if let Some(ref mut minibrowser) = self.minibrowser { if let Some(ref mut minibrowser) = self.minibrowser {
minibrowser.update(window.winit_window().unwrap(), &running_state, "init"); minibrowser.update(window.winit_window().unwrap(), &running_state, "init");
@ -310,7 +310,7 @@ impl App {
}, },
MinibrowserEvent::NewWebView => { MinibrowserEvent::NewWebView => {
minibrowser.update_location_dirty(false); minibrowser.update_location_dirty(false);
state.new_toplevel_webview(Url::parse("servo:newtab").unwrap()); state.create_and_focus_toplevel_webview(Url::parse("servo:newtab").unwrap());
}, },
MinibrowserEvent::CloseWebView(id) => { MinibrowserEvent::CloseWebView(id) => {
minibrowser.update_location_dirty(false); minibrowser.update_location_dirty(false);
@ -333,16 +333,69 @@ impl App {
match msg { match msg {
WebDriverCommandMsg::IsWebViewOpen(webview_id, sender) => { WebDriverCommandMsg::IsWebViewOpen(webview_id, sender) => {
let context = running_state.webview_by_id(webview_id); let context = running_state.webview_by_id(webview_id);
sender.send(context.is_some()).unwrap();
if let Err(error) = sender.send(context.is_some()) {
warn!("Failed to send response of IsWebViewOpein: {error}");
}
}, },
webdriver_msg @ WebDriverCommandMsg::IsBrowsingContextOpen(..) => { webdriver_msg @ WebDriverCommandMsg::IsBrowsingContextOpen(..) => {
running_state.forward_webdriver_command(webdriver_msg); running_state.forward_webdriver_command(webdriver_msg);
}, },
WebDriverCommandMsg::NewWebView(response_sender, load_status_sender) => {
let new_webview =
running_state.create_toplevel_webview(Url::parse("auto:blank").unwrap());
if let Err(error) = response_sender.send(new_webview.id()) {
warn!("Failed to send response of NewWebview: {error}");
}
running_state.set_load_status_sender(new_webview.id(), load_status_sender);
},
WebDriverCommandMsg::CloseWebView(webview_id) => { WebDriverCommandMsg::CloseWebView(webview_id) => {
running_state.close_webview(webview_id); running_state.close_webview(webview_id);
}, },
WebDriverCommandMsg::GetWindowSize(..) | WebDriverCommandMsg::FocusWebView(webview_id) => {
WebDriverCommandMsg::FocusWebView(..) | if let Some(webview) = running_state.webview_by_id(webview_id) {
webview.focus();
}
// TODO: send a response to the WebDriver
// so it knows when the focus has finished.
},
WebDriverCommandMsg::GetWindowSize(_webview_id, response_sender) => {
let window = self
.windows
.values()
.next()
.expect("Should have at least one window in servoshell");
if let Err(error) = response_sender.send(window.screen_geometry().size) {
warn!("Failed to send response of GetWindowSize: {error}");
}
},
WebDriverCommandMsg::SetWindowSize(webview_id, size, size_sender) => {
let Some(webview) = running_state.webview_by_id(webview_id) else {
continue;
};
let window = self
.windows
.values()
.next()
.expect("Should have at least one window in servoshell");
let size = window.request_resize(&webview, size);
if let Err(error) = size_sender.send(size.unwrap_or_default()) {
warn!("Failed to send window size: {error}");
}
},
WebDriverCommandMsg::GetFocusedWebView(sender) => {
let focused_webview = running_state.focused_webview();
if let Err(error) = sender.send(focused_webview.map(|w| w.id())) {
warn!("Failed to send response of GetFocusedWebView: {error}");
};
},
WebDriverCommandMsg::GetViewportSize(..) |
WebDriverCommandMsg::LoadUrl(..) | WebDriverCommandMsg::LoadUrl(..) |
WebDriverCommandMsg::ScriptCommand(..) | WebDriverCommandMsg::ScriptCommand(..) |
WebDriverCommandMsg::SendKeys(..) | WebDriverCommandMsg::SendKeys(..) |
@ -350,9 +403,7 @@ impl App {
WebDriverCommandMsg::MouseButtonAction(..) | WebDriverCommandMsg::MouseButtonAction(..) |
WebDriverCommandMsg::MouseMoveAction(..) | WebDriverCommandMsg::MouseMoveAction(..) |
WebDriverCommandMsg::WheelScrollAction(..) | WebDriverCommandMsg::WheelScrollAction(..) |
WebDriverCommandMsg::SetWindowSize(..) |
WebDriverCommandMsg::TakeScreenshot(..) | WebDriverCommandMsg::TakeScreenshot(..) |
WebDriverCommandMsg::NewWebView(..) |
WebDriverCommandMsg::Refresh(..) => { WebDriverCommandMsg::Refresh(..) => {
warn!( warn!(
"WebDriverCommand {:?} is still not moved from constellation to embedder", "WebDriverCommand {:?} is still not moved from constellation to embedder",

View file

@ -19,7 +19,7 @@ use servo::webrender_api::units::{DeviceIntPoint, DeviceIntSize};
use servo::{ use servo::{
AllowOrDenyRequest, AuthenticationRequest, FilterPattern, FormControl, GamepadHapticEffectType, AllowOrDenyRequest, AuthenticationRequest, FilterPattern, FormControl, GamepadHapticEffectType,
KeyboardEvent, LoadStatus, PermissionRequest, Servo, ServoDelegate, ServoError, SimpleDialog, KeyboardEvent, LoadStatus, PermissionRequest, Servo, ServoDelegate, ServoError, SimpleDialog,
WebDriverCommandMsg, WebView, WebViewBuilder, WebViewDelegate, WebDriverCommandMsg, WebDriverLoadStatus, WebView, WebViewBuilder, WebViewDelegate,
}; };
use url::Url; use url::Url;
@ -37,6 +37,13 @@ pub(crate) enum AppState {
ShuttingDown, ShuttingDown,
} }
/// A collection of [`IpcSender`]s that are used to asynchronously communicate
/// to a WebDriver server with information about application state.
#[derive(Clone, Default)]
struct WebDriverSenders {
pub load_status_senders: HashMap<WebViewId, IpcSender<WebDriverLoadStatus>>,
}
pub(crate) struct RunningAppState { pub(crate) struct RunningAppState {
/// A handle to the Servo instance of the [`RunningAppState`]. This is not stored inside /// A handle to the Servo instance of the [`RunningAppState`]. This is not stored inside
/// `inner` so that we can keep a reference to Servo in order to spin the event loop, /// `inner` so that we can keep a reference to Servo in order to spin the event loop,
@ -48,6 +55,7 @@ pub(crate) struct RunningAppState {
/// A [`Receiver`] for receiving commands from a running WebDriver server, if WebDriver /// A [`Receiver`] for receiving commands from a running WebDriver server, if WebDriver
/// was enabled. /// was enabled.
webdriver_receiver: Option<Receiver<WebDriverCommandMsg>>, webdriver_receiver: Option<Receiver<WebDriverCommandMsg>>,
webdriver_senders: RefCell<WebDriverSenders>,
inner: RefCell<RunningAppStateInner>, inner: RefCell<RunningAppStateInner>,
} }
@ -99,6 +107,7 @@ impl RunningAppState {
servo, servo,
servoshell_preferences, servoshell_preferences,
webdriver_receiver, webdriver_receiver,
webdriver_senders: RefCell::default(),
inner: RefCell::new(RunningAppStateInner { inner: RefCell::new(RunningAppStateInner {
webviews: HashMap::default(), webviews: HashMap::default(),
creation_order: Default::default(), creation_order: Default::default(),
@ -112,7 +121,13 @@ impl RunningAppState {
} }
} }
pub(crate) fn new_toplevel_webview(self: &Rc<Self>, url: Url) { pub(crate) fn create_and_focus_toplevel_webview(self: &Rc<Self>, url: Url) {
let webview = self.create_toplevel_webview(url);
webview.focus();
webview.raise_to_top(true);
}
pub(crate) fn create_toplevel_webview(self: &Rc<Self>, url: Url) -> WebView {
let webview = WebViewBuilder::new(self.servo()) let webview = WebViewBuilder::new(self.servo())
.url(url) .url(url)
.hidpi_scale_factor(self.inner().window.hidpi_scale_factor()) .hidpi_scale_factor(self.inner().window.hidpi_scale_factor())
@ -120,10 +135,8 @@ impl RunningAppState {
.build(); .build();
webview.notify_theme_change(self.inner().window.theme()); webview.notify_theme_change(self.inner().window.theme());
webview.focus(); self.add(webview.clone());
webview.raise_to_top(true); webview
self.add(webview);
} }
pub(crate) fn inner(&self) -> Ref<RunningAppStateInner> { pub(crate) fn inner(&self) -> Ref<RunningAppStateInner> {
@ -382,6 +395,17 @@ impl RunningAppState {
webview.notify_scroll_event(location, origin); webview.notify_scroll_event(location, origin);
}); });
} }
pub(crate) fn set_load_status_sender(
&self,
webview_id: WebViewId,
sender: IpcSender<WebDriverLoadStatus>,
) {
self.webdriver_senders
.borrow_mut()
.load_status_senders
.insert(webview_id, sender);
}
} }
struct ServoShellServoDelegate; struct ServoShellServoDelegate;
@ -507,8 +531,19 @@ impl WebViewDelegate for RunningAppState {
self.inner().window.set_cursor(cursor); self.inner().window.set_cursor(cursor);
} }
fn notify_load_status_changed(&self, _webview: servo::WebView, _status: LoadStatus) { fn notify_load_status_changed(&self, webview: servo::WebView, status: LoadStatus) {
self.inner_mut().need_update = true; self.inner_mut().need_update = true;
if status == LoadStatus::Complete {
if let Some(sender) = self
.webdriver_senders
.borrow_mut()
.load_status_senders
.remove(&webview.id())
{
let _ = sender.send(WebDriverLoadStatus::Complete);
}
}
} }
fn notify_fullscreen_state_changed(&self, _webview: servo::WebView, fullscreen_state: bool) { fn notify_fullscreen_state_changed(&self, _webview: servo::WebView, fullscreen_state: bool) {

View file

@ -394,7 +394,7 @@ impl Window {
} }
}) })
.shortcut(CMD_OR_CONTROL, 'T', || { .shortcut(CMD_OR_CONTROL, 'T', || {
state.new_toplevel_webview(Url::parse("servo:newtab").unwrap()); state.create_and_focus_toplevel_webview(Url::parse("servo:newtab").unwrap());
}) })
.shortcut(CMD_OR_CONTROL, 'Q', || state.servo().start_shutting_down()) .shortcut(CMD_OR_CONTROL, 'Q', || state.servo().start_shutting_down())
.otherwise(|| handled = false); .otherwise(|| handled = false);

View file

@ -336,11 +336,11 @@ impl RunningAppState {
}), }),
}); });
app_state.new_toplevel_webview(initial_url); app_state.create_and_focus_toplevel_webview(initial_url);
app_state app_state
} }
pub(crate) fn new_toplevel_webview(self: &Rc<Self>, url: Url) { pub(crate) fn create_and_focus_toplevel_webview(self: &Rc<Self>, url: Url) {
let webview = WebViewBuilder::new(&self.servo) let webview = WebViewBuilder::new(&self.servo)
.url(url) .url(url)
.hidpi_scale_factor(self.inner().hidpi_scale_factor) .hidpi_scale_factor(self.inner().hidpi_scale_factor)

View file

@ -228,7 +228,7 @@ impl ServoAction {
}, },
NewWebview(xcomponent, window) => { NewWebview(xcomponent, window) => {
servo.pause_compositor(); servo.pause_compositor();
servo.new_toplevel_webview("about:blank".parse().unwrap()); servo.create_and_focus_toplevel_webview("about:blank".parse().unwrap());
let (window_handle, _, coordinates) = let (window_handle, _, coordinates) =
simpleservo::get_raw_window_handle(xcomponent.0, window.0); simpleservo::get_raw_window_handle(xcomponent.0, window.0);