[WebDriver] Add synchronization for key action (#37403)

Implement action synchronization for key event. Previously only done for
pointer https://github.com/servo/servo/pull/36932 and wheel
https://github.com/servo/servo/pull/37260.

---------

Signed-off-by: PotatoCP <kenzieradityatirtarahardja18@gmail.com>
This commit is contained in:
Kenzie Raditya Tirtarahardja 2025-06-18 15:26:44 +08:00 committed by GitHub
parent f97cdb4d12
commit cdc8b45965
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
16 changed files with 171 additions and 118 deletions

View file

@ -157,7 +157,7 @@ impl Handler {
// Step 1.4. Wait for
// The user agent event loop has spun enough times to process the DOM events
// generated by the last invocation of the dispatch tick actions steps.
self.wait_for_user_agent_handling_complete(tick_actions)?;
self.wait_for_user_agent_handling_complete()?;
// At least tick duration milliseconds have passed.
let elapsed = now.elapsed();
if elapsed.as_millis() < tick_duration as u128 {
@ -171,29 +171,13 @@ impl Handler {
Ok(())
}
fn wait_for_user_agent_handling_complete(
&self,
tick_actions: &TickActions,
) -> Result<(), ErrorStatus> {
// TODO: Add matches! for key actions
// after implmenting webdriver id for key events.
let count_non_null_actions_in_tick = tick_actions
.iter()
.filter(|(_, action)| {
matches!(
action,
ActionItem::Pointer(PointerActionItem::Pointer(_)) |
ActionItem::Wheel(WheelActionItem::Wheel(_))
)
})
.count();
fn wait_for_user_agent_handling_complete(&self) -> Result<(), ErrorStatus> {
// To ensure we wait for all events to be processed, only the last event
// in each tick action step holds the message id.
// Whenever a new event is generated, the message id is passed to it.
//
// Wait for count_non_null_actions_in_tick number of responses
for _ in 0..count_non_null_actions_in_tick {
// Wait for num_pending_actions number of responses
for _ in 0..self.num_pending_actions.get() {
match self.constellation_receiver.recv() {
Ok(response) => {
let current_waiting_id = self
@ -213,6 +197,8 @@ impl Handler {
};
}
self.num_pending_actions.set(0);
Ok(())
}
@ -320,9 +306,13 @@ impl Handler {
let keyboard_event = key_input_state.dispatch_keydown(raw_key);
// Step 12
self.increment_num_pending_actions();
let msg_id = self.current_action_id.get();
let cmd_msg = WebDriverCommandMsg::KeyboardAction(
self.session().unwrap().browsing_context_id,
keyboard_event,
msg_id,
self.constellation_sender.clone(),
);
self.constellation_chan
.send(EmbedderToConstellationMessage::WebDriverCommand(cmd_msg))
@ -342,9 +332,13 @@ impl Handler {
if let Some(keyboard_event) = key_input_state.dispatch_keyup(raw_key) {
// Step 12
self.increment_num_pending_actions();
let msg_id = self.current_action_id.get();
let cmd_msg = WebDriverCommandMsg::KeyboardAction(
self.session().unwrap().browsing_context_id,
keyboard_event,
msg_id,
self.constellation_sender.clone(),
);
self.constellation_chan
.send(EmbedderToConstellationMessage::WebDriverCommand(cmd_msg))
@ -367,6 +361,7 @@ impl Handler {
}
pointer_input_state.pressed.insert(action.button);
self.increment_num_pending_actions();
let msg_id = self.current_action_id.get();
let cmd_msg = WebDriverCommandMsg::MouseButtonAction(
session.webview_id,
@ -397,6 +392,7 @@ impl Handler {
}
pointer_input_state.pressed.remove(&action.button);
self.increment_num_pending_actions();
let msg_id = self.current_action_id.get();
let cmd_msg = WebDriverCommandMsg::MouseButtonAction(
session.webview_id,
@ -523,6 +519,7 @@ impl Handler {
if x != current_x || y != current_y || last {
// Step 7.2
let msg_id = if last {
self.increment_num_pending_actions();
self.current_action_id.get()
} else {
None
@ -660,6 +657,7 @@ impl Handler {
if delta_x != 0 || delta_y != 0 || last {
// Perform implementation-specific action dispatch steps
let msg_id = if last {
self.increment_num_pending_actions();
self.current_action_id.get()
} else {
None

View file

@ -227,6 +227,9 @@ struct Handler {
current_action_id: Cell<Option<WebDriverMessageId>>,
resize_timeout: u32,
/// Number of pending actions of which WebDriver is waiting for responses.
num_pending_actions: Cell<u32>,
}
#[derive(Clone, Copy, Debug, PartialEq)]
@ -459,9 +462,16 @@ impl Handler {
id_generator: WebDriverMessageIdGenerator::new(),
current_action_id: Cell::new(None),
resize_timeout: 500,
num_pending_actions: Cell::new(0),
}
}
fn increment_num_pending_actions(&self) {
// Increase the num_pending_actions by one every time we dispatch non null actions.
self.num_pending_actions
.set(self.num_pending_actions.get() + 1);
}
fn focus_webview_id(&self) -> WebDriverResult<WebViewId> {
debug!("Getting focused context.");
let (sender, receiver) = ipc::channel().unwrap();