mirror of
https://github.com/servo/servo.git
synced 2025-08-06 06:00:15 +01:00
Fix WebDriverSession::input_cancel_list
related logic (#37010)
- Remove incorrect addition to `input_cancel_list` in `dispatch_keyup_action` - For `KeyDown` and `PointerDown`, delay the addition to `input_cancel_list` until "Dispatching action algorithm" is done to match the spec. Previously the addition is done before notifying constellation. Moreover, this makes sure that `pointerUp` is appended even if `dispatch_pointerdown_action` returns early, so that [Release Actions](https://w3c.github.io/webdriver/#release-actions) always have the correct order. - Remove incorrect addition to `input_cancel_list` in `dispatch_pointerup_action`. This wrongly added "pointerdown" in [Release Actions](https://w3c.github.io/webdriver/#release-actions) - Reduce code duplication - Add TODO for PointerInputState::subtype and pointerID Testing: `./mach test-wpt -r --log-raw "D:\servo test log\perform-actions.txt" tests\wpt\tests\webdriver\tests\classic\perform_actions --product servodriver` has no new failures so no regression. There are a lot more passing tests, but I think mostly are because there is no CI for webdriver. cc @xiaochengh @jdm @PotatoCP @longvatrong111 --------- Signed-off-by: Euclid Ye <yezhizhenjiakang@gmail.com>
This commit is contained in:
parent
e2424fcec7
commit
7ac302f255
1 changed files with 87 additions and 98 deletions
|
@ -33,6 +33,9 @@ pub(crate) enum InputSourceState {
|
|||
}
|
||||
|
||||
// https://w3c.github.io/webdriver/#dfn-pointer-input-source
|
||||
// TODO: subtype is used for https://w3c.github.io/webdriver/#dfn-get-a-pointer-id
|
||||
// Need to add pointer-id to the following struct
|
||||
#[allow(dead_code)]
|
||||
pub(crate) struct PointerInputState {
|
||||
subtype: PointerType,
|
||||
pressed: HashSet<u64>,
|
||||
|
@ -142,7 +145,22 @@ impl Handler {
|
|||
.or_insert(InputSourceState::Key(KeyInputState::new()));
|
||||
match action {
|
||||
KeyAction::Down(action) => {
|
||||
self.dispatch_keydown_action(source_id, action)
|
||||
self.dispatch_keydown_action(source_id, action);
|
||||
// Step 9. If subtype is "keyDown", append a copy of action
|
||||
// object with the subtype property changed to "keyUp" to
|
||||
// input state's input cancel list.
|
||||
self.session_mut().unwrap().input_cancel_list.push(
|
||||
ActionSequence {
|
||||
id: source_id.into(),
|
||||
actions: ActionsType::Key {
|
||||
actions: vec![KeyActionItem::Key(KeyAction::Up(
|
||||
KeyUpAction {
|
||||
value: action.value.clone(),
|
||||
},
|
||||
))],
|
||||
},
|
||||
},
|
||||
);
|
||||
},
|
||||
KeyAction::Up(action) => {
|
||||
self.dispatch_keyup_action(source_id, action)
|
||||
|
@ -172,7 +190,27 @@ impl Handler {
|
|||
match action {
|
||||
PointerAction::Cancel => (),
|
||||
PointerAction::Down(action) => {
|
||||
self.dispatch_pointerdown_action(source_id, action)
|
||||
self.dispatch_pointerdown_action(source_id, action);
|
||||
|
||||
// Step 10. If subtype is "pointerDown", append a copy of action
|
||||
// object with the subtype property changed to "pointerUp" to
|
||||
// input state's input cancel list.
|
||||
self.session_mut().unwrap().input_cancel_list.push(
|
||||
ActionSequence {
|
||||
id: source_id.into(),
|
||||
actions: ActionsType::Pointer {
|
||||
parameters: PointerActionParameters {
|
||||
pointer_type: parameters.pointer_type,
|
||||
},
|
||||
actions: vec![PointerActionItem::Pointer(
|
||||
PointerAction::Up(PointerUpAction {
|
||||
button: action.button,
|
||||
..Default::default()
|
||||
}),
|
||||
)],
|
||||
},
|
||||
},
|
||||
);
|
||||
},
|
||||
PointerAction::Move(action) => self.dispatch_pointermove_action(
|
||||
source_id,
|
||||
|
@ -215,26 +253,18 @@ impl Handler {
|
|||
|
||||
// https://w3c.github.io/webdriver/#dfn-dispatch-a-keydown-action
|
||||
fn dispatch_keydown_action(&mut self, source_id: &str, action: &KeyDownAction) {
|
||||
let session = self.session.as_mut().unwrap();
|
||||
|
||||
// Step 1
|
||||
let raw_key = action.value.chars().next().unwrap();
|
||||
let key_input_state = match session.input_state_table.get_mut(source_id).unwrap() {
|
||||
InputSourceState::Key(key_input_state) => key_input_state,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
session.input_cancel_list.push(ActionSequence {
|
||||
id: source_id.into(),
|
||||
actions: ActionsType::Key {
|
||||
actions: vec![KeyActionItem::Key(KeyAction::Up(KeyUpAction {
|
||||
value: action.value.clone(),
|
||||
}))],
|
||||
},
|
||||
});
|
||||
let key_input_state = self.get_key_input_state_mut(source_id);
|
||||
|
||||
// Step 2 - 11. Done by `keyboard-types` crate.
|
||||
let keyboard_event = key_input_state.dispatch_keydown(raw_key);
|
||||
let cmd_msg =
|
||||
WebDriverCommandMsg::KeyboardAction(session.browsing_context_id, keyboard_event);
|
||||
|
||||
// Step 12
|
||||
let cmd_msg = WebDriverCommandMsg::KeyboardAction(
|
||||
self.session().unwrap().browsing_context_id,
|
||||
keyboard_event,
|
||||
);
|
||||
self.constellation_chan
|
||||
.send(EmbedderToConstellationMessage::WebDriverCommand(cmd_msg))
|
||||
.unwrap();
|
||||
|
@ -242,71 +272,57 @@ impl Handler {
|
|||
|
||||
// https://w3c.github.io/webdriver/#dfn-dispatch-a-keyup-action
|
||||
fn dispatch_keyup_action(&mut self, source_id: &str, action: &KeyUpAction) {
|
||||
let session = self.session.as_mut().unwrap();
|
||||
|
||||
// Step 1
|
||||
let raw_key = action.value.chars().next().unwrap();
|
||||
let key_input_state = match session.input_state_table.get_mut(source_id).unwrap() {
|
||||
InputSourceState::Key(key_input_state) => key_input_state,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
session.input_cancel_list.push(ActionSequence {
|
||||
id: source_id.into(),
|
||||
actions: ActionsType::Key {
|
||||
actions: vec![KeyActionItem::Key(KeyAction::Up(KeyUpAction {
|
||||
value: action.value.clone(),
|
||||
}))],
|
||||
},
|
||||
});
|
||||
let key_input_state = self.get_key_input_state_mut(source_id);
|
||||
|
||||
// Step 2 - 11. Done by `keyboard-types` crate.
|
||||
if let Some(keyboard_event) = key_input_state.dispatch_keyup(raw_key) {
|
||||
let cmd_msg =
|
||||
WebDriverCommandMsg::KeyboardAction(session.browsing_context_id, keyboard_event);
|
||||
// Step 12
|
||||
let cmd_msg = WebDriverCommandMsg::KeyboardAction(
|
||||
self.session().unwrap().browsing_context_id,
|
||||
keyboard_event,
|
||||
);
|
||||
self.constellation_chan
|
||||
.send(EmbedderToConstellationMessage::WebDriverCommand(cmd_msg))
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
fn get_pointer_input_state_mut(&mut self, source_id: &str) -> &mut PointerInputState {
|
||||
let session = self.session_mut().unwrap();
|
||||
let pointer_input_state = match session.input_state_table.get_mut(source_id).unwrap() {
|
||||
InputSourceState::Pointer(pointer_input_state) => pointer_input_state,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
pointer_input_state
|
||||
}
|
||||
|
||||
fn get_key_input_state_mut(&mut self, source_id: &str) -> &mut KeyInputState {
|
||||
let session = self.session_mut().unwrap();
|
||||
let key_input_state = match session.input_state_table.get_mut(source_id).unwrap() {
|
||||
InputSourceState::Key(key_input_state) => key_input_state,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
key_input_state
|
||||
}
|
||||
|
||||
// https://w3c.github.io/webdriver/#dfn-dispatch-a-pointerdown-action
|
||||
pub(crate) fn dispatch_pointerdown_action(
|
||||
&mut self,
|
||||
source_id: &str,
|
||||
action: &PointerDownAction,
|
||||
) {
|
||||
let session = self.session.as_mut().unwrap();
|
||||
|
||||
let pointer_input_state = match session.input_state_table.get_mut(source_id).unwrap() {
|
||||
InputSourceState::Pointer(pointer_input_state) => pointer_input_state,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
let webview_id = self.session().unwrap().webview_id;
|
||||
let pointer_input_state = self.get_pointer_input_state_mut(source_id);
|
||||
|
||||
if pointer_input_state.pressed.contains(&action.button) {
|
||||
return;
|
||||
}
|
||||
pointer_input_state.pressed.insert(action.button);
|
||||
|
||||
session.input_cancel_list.push(ActionSequence {
|
||||
id: source_id.into(),
|
||||
actions: ActionsType::Pointer {
|
||||
parameters: PointerActionParameters {
|
||||
pointer_type: match pointer_input_state.subtype {
|
||||
PointerType::Mouse => PointerType::Mouse,
|
||||
PointerType::Pen => PointerType::Pen,
|
||||
PointerType::Touch => PointerType::Touch,
|
||||
},
|
||||
},
|
||||
actions: vec![PointerActionItem::Pointer(PointerAction::Up(
|
||||
PointerUpAction {
|
||||
button: action.button,
|
||||
..Default::default()
|
||||
},
|
||||
))],
|
||||
},
|
||||
});
|
||||
|
||||
let cmd_msg = WebDriverCommandMsg::MouseButtonAction(
|
||||
session.webview_id,
|
||||
webview_id,
|
||||
MouseButtonAction::Down,
|
||||
action.button.into(),
|
||||
pointer_input_state.x as f32,
|
||||
|
@ -319,39 +335,16 @@ impl Handler {
|
|||
|
||||
// https://w3c.github.io/webdriver/#dfn-dispatch-a-pointerup-action
|
||||
pub(crate) fn dispatch_pointerup_action(&mut self, source_id: &str, action: &PointerUpAction) {
|
||||
let session = self.session.as_mut().unwrap();
|
||||
|
||||
let pointer_input_state = match session.input_state_table.get_mut(source_id).unwrap() {
|
||||
InputSourceState::Pointer(pointer_input_state) => pointer_input_state,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
let webview_id = self.session().unwrap().webview_id;
|
||||
let pointer_input_state = self.get_pointer_input_state_mut(source_id);
|
||||
|
||||
if !pointer_input_state.pressed.contains(&action.button) {
|
||||
return;
|
||||
}
|
||||
pointer_input_state.pressed.remove(&action.button);
|
||||
|
||||
session.input_cancel_list.push(ActionSequence {
|
||||
id: source_id.into(),
|
||||
actions: ActionsType::Pointer {
|
||||
parameters: PointerActionParameters {
|
||||
pointer_type: match pointer_input_state.subtype {
|
||||
PointerType::Mouse => PointerType::Mouse,
|
||||
PointerType::Pen => PointerType::Pen,
|
||||
PointerType::Touch => PointerType::Touch,
|
||||
},
|
||||
},
|
||||
actions: vec![PointerActionItem::Pointer(PointerAction::Down(
|
||||
PointerDownAction {
|
||||
button: action.button,
|
||||
..Default::default()
|
||||
},
|
||||
))],
|
||||
},
|
||||
});
|
||||
|
||||
let cmd_msg = WebDriverCommandMsg::MouseButtonAction(
|
||||
session.webview_id,
|
||||
webview_id,
|
||||
MouseButtonAction::Up,
|
||||
action.button.into(),
|
||||
pointer_input_state.x as f32,
|
||||
|
@ -432,12 +425,9 @@ impl Handler {
|
|||
target_y: f64,
|
||||
tick_start: Instant,
|
||||
) {
|
||||
let session = self.session.as_mut().unwrap();
|
||||
let pointer_input_state = match session.input_state_table.get_mut(source_id).unwrap() {
|
||||
InputSourceState::Pointer(pointer_input_state) => pointer_input_state,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
let webview_id = self.session().unwrap().webview_id;
|
||||
let constellation_chan = self.constellation_chan.clone();
|
||||
let pointer_input_state = self.get_pointer_input_state_mut(source_id);
|
||||
loop {
|
||||
// Step 1
|
||||
let time_delta = tick_start.elapsed().as_millis();
|
||||
|
@ -469,10 +459,9 @@ impl Handler {
|
|||
// Step 7
|
||||
if x != current_x || y != current_y {
|
||||
// Step 7.2
|
||||
let cmd_msg =
|
||||
WebDriverCommandMsg::MouseMoveAction(session.webview_id, x as f32, y as f32);
|
||||
let cmd_msg = WebDriverCommandMsg::MouseMoveAction(webview_id, x as f32, y as f32);
|
||||
//TODO: Need Synchronization here before updating `pointer_input_state`
|
||||
self.constellation_chan
|
||||
constellation_chan
|
||||
.send(EmbedderToConstellationMessage::WebDriverCommand(cmd_msg))
|
||||
.unwrap();
|
||||
// Step 7.3
|
||||
|
@ -567,7 +556,7 @@ impl Handler {
|
|||
mut curr_delta_y: i64,
|
||||
tick_start: Instant,
|
||||
) {
|
||||
let session = self.session.as_mut().unwrap();
|
||||
let session = self.session_mut().unwrap();
|
||||
|
||||
// Step 1
|
||||
let time_delta = tick_start.elapsed().as_millis();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue