webdriver: Focus WebView asynchronously (#39241)

#38160 added a webdriver-specific API to support waiting on focus
operations to complete. Later, #38243 added a unique id to track each
focus operation.

Back then we wait on focusing webview in webdriver hoping to improve
stability, but it does not matter as it turns out later. #39086 also
focuses browsing context asynchronously.

This PR would make webdriver's focusing-webview behaviour same as human
interaction.

Testing: 
[Before 1](https://github.com/yezhizhen/servo/actions/runs/17598288280),
[Before 2](https://github.com/yezhizhen/servo/actions/runs/17598289360),
[Before 3](https://github.com/yezhizhen/servo/actions/runs/17598290532)
[After 1](https://github.com/yezhizhen/servo/actions/runs/17598282988),
[After 2](https://github.com/yezhizhen/servo/actions/runs/17598280603),
[After 3](https://github.com/yezhizhen/servo/actions/runs/17589228530)

---------

Signed-off-by: Euclid Ye <yezhizhenjiakang@gmail.com>
This commit is contained in:
Euclid Ye 2025-09-10 15:36:53 +08:00 committed by GitHub
parent 433a6bf47b
commit 726b456120
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
12 changed files with 42 additions and 124 deletions

View file

@ -19,8 +19,8 @@ use base::Epoch;
use base::cross_process_instant::CrossProcessInstant;
use base::id::{MessagePortId, PipelineId, WebViewId};
use embedder_traits::{
CompositorHitTestResult, FocusId, InputEvent, JavaScriptEvaluationId, MediaSessionActionType,
Theme, TraversalId, ViewportDetails, WebDriverCommandMsg, WebDriverCommandResponse,
CompositorHitTestResult, InputEvent, JavaScriptEvaluationId, MediaSessionActionType, Theme,
TraversalId, ViewportDetails, WebDriverCommandMsg, WebDriverCommandResponse,
};
use fnv::FnvHashMap;
pub use from_script_message::*;
@ -76,7 +76,7 @@ pub enum EmbedderToConstellationMessage {
SendError(Option<WebViewId>, String),
/// Make a webview focused. [EmbedderMsg::WebViewFocused] will be sent with
/// the result of this operation.
FocusWebView(WebViewId, FocusId),
FocusWebView(WebViewId),
/// Make none of the webviews focused.
BlurWebView,
/// Forward an input event to an appropriate ScriptTask.

View file

@ -338,17 +338,6 @@ pub struct ScreenMetrics {
pub available_size: DeviceIndependentIntSize,
}
/// An opaque identifier for a single webview focus operation.
#[derive(Clone, Deserialize, Eq, Hash, PartialEq, Serialize)]
pub struct FocusId(String);
impl FocusId {
#[allow(clippy::new_without_default)]
pub fn new() -> Self {
Self(Uuid::new_v4().to_string())
}
}
/// An opaque identifier for a single history traversal operation.
#[derive(Clone, Deserialize, Eq, Hash, PartialEq, Serialize)]
pub struct TraversalId(String);
@ -445,10 +434,9 @@ pub enum EmbedderMsg {
),
/// A webview was destroyed.
WebViewClosed(WebViewId),
/// A webview potentially gained focus for keyboard events, as initiated
/// by the provided focus id. If the boolean value is false, the webiew
/// could not be focused.
WebViewFocused(WebViewId, FocusId, bool),
/// A webview potentially gained focus for keyboard events.
/// If the boolean value is false, the webiew could not be focused.
WebViewFocused(WebViewId, bool),
/// All webviews lost focus for keyboard events.
WebViewBlurred,
/// Wether or not to unload a document

View file

@ -22,7 +22,7 @@ use style_traits::CSSPixel;
use webdriver::error::ErrorStatus;
use webrender_api::units::DevicePixel;
use crate::{FocusId, JSValue, MouseButton, MouseButtonAction, TraversalId};
use crate::{JSValue, MouseButton, MouseButtonAction, TraversalId};
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
pub struct WebDriverMessageId(pub usize);
@ -155,8 +155,7 @@ pub enum WebDriverCommandMsg {
/// Close the webview associated with the provided id.
CloseWebView(WebViewId, IpcSender<()>),
/// Focus the webview associated with the provided id.
/// Sends back a bool indicating whether the focus was successfully set.
FocusWebView(WebViewId, IpcSender<bool>),
FocusWebView(WebViewId),
/// Get focused webview. For now, this is only used when start new session.
GetFocusedWebView(IpcSender<Option<WebViewId>>),
/// Get webviews state
@ -298,5 +297,4 @@ pub struct WebDriverSenders {
pub load_status_senders: HashMap<WebViewId, GenericSender<WebDriverLoadStatus>>,
pub script_evaluation_interrupt_sender: Option<IpcSender<WebDriverJSResult>>,
pub pending_traversals: HashMap<TraversalId, GenericSender<WebDriverLoadStatus>>,
pub pending_focus: HashMap<FocusId, IpcSender<bool>>,
}