mirror of
https://github.com/servo/servo.git
synced 2025-08-14 09:55:35 +01:00
script: Focus on mousedown instead of mouse click according to spec (#38589)
- Focus on mousedown instead of mouse click according to [spec](https://w3c.github.io/uievents/#handle-native-mouse-down) - Refactor to follow spec closer and make things more clear. - Add some spec link. - Remove some dead spec link. Still some preparation before implementing #38435. Testing: No regression in WebDriver & WPT. But update some outdated test. Fixes: #38588 --------- Signed-off-by: Euclid Ye <euclid.ye@huawei.com>
This commit is contained in:
parent
d2122c8bd8
commit
5d21234872
8 changed files with 69 additions and 31 deletions
|
@ -1546,6 +1546,7 @@ impl Document {
|
|||
}
|
||||
}
|
||||
|
||||
/// <https://w3c.github.io/uievents/#mouseevent-algorithms>
|
||||
pub(crate) fn handle_mouse_button_event(
|
||||
&self,
|
||||
event: MouseButtonEvent,
|
||||
|
@ -1579,15 +1580,6 @@ impl Document {
|
|||
if el.is_actually_disabled() {
|
||||
return;
|
||||
}
|
||||
|
||||
// For a node within a text input UA shadow DOM, delegate the focus target into its shadow host.
|
||||
// TODO: This focus delegation should be done with shadow DOM delegateFocus attribute.
|
||||
let target_el = el.find_focusable_shadow_host_if_necessary();
|
||||
|
||||
self.begin_focus_transaction();
|
||||
// Try to focus `el`. If it's not focusable, focus the document instead.
|
||||
self.request_focus(None, FocusInitiator::Local, can_gc);
|
||||
self.request_focus(target_el.as_deref(), FocusInitiator::Local, can_gc);
|
||||
}
|
||||
|
||||
let dom_event = DomRoot::upcast::<Event>(MouseEvent::for_platform_mouse_event(
|
||||
|
@ -1599,44 +1591,65 @@ impl Document {
|
|||
can_gc,
|
||||
));
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#run-authentic-click-activation-steps
|
||||
let activatable = el.as_maybe_activatable();
|
||||
match event.action {
|
||||
// https://w3c.github.io/uievents/#handle-native-mouse-click
|
||||
MouseButtonAction::Click => {
|
||||
el.set_click_in_progress(true);
|
||||
dom_event.fire(node.upcast(), can_gc);
|
||||
dom_event.dispatch(node.upcast(), false, can_gc);
|
||||
el.set_click_in_progress(false);
|
||||
|
||||
self.maybe_fire_dblclick(node, &hit_test_result, input_event, can_gc);
|
||||
},
|
||||
// https://w3c.github.io/uievents/#handle-native-mouse-down
|
||||
MouseButtonAction::Down => {
|
||||
// (TODO) Step 6. Maybe send pointerdown event with `dom_event`.
|
||||
if let Some(a) = activatable {
|
||||
a.enter_formal_activation_state();
|
||||
}
|
||||
|
||||
let target = node.upcast();
|
||||
dom_event.fire(target, can_gc);
|
||||
// For a node within a text input UA shadow DOM,
|
||||
// delegate the focus target into its shadow host.
|
||||
// TODO: This focus delegation should be done
|
||||
// with shadow DOM delegateFocus attribute.
|
||||
let target_el = el.find_focusable_shadow_host_if_necessary();
|
||||
self.begin_focus_transaction();
|
||||
// Try to focus `el`. If it's not focusable, focus the document instead.
|
||||
self.request_focus(None, FocusInitiator::Local, can_gc);
|
||||
self.request_focus(target_el.as_deref(), FocusInitiator::Local, can_gc);
|
||||
|
||||
// Step 7. Let result = dispatch event at target
|
||||
let result = dom_event.dispatch(node.upcast(), false, can_gc);
|
||||
|
||||
// Step 8. If result is true and target is a focusable area
|
||||
// that is click focusable, then Run the focusing steps at target.
|
||||
if result && self.focus_transaction.borrow().is_some() {
|
||||
self.commit_focus_transaction(FocusInitiator::Local, can_gc);
|
||||
}
|
||||
|
||||
// Step 9. If mbutton is the secondary mouse button, then
|
||||
// Maybe show context menu with native, target.
|
||||
if let (MouseButtonAction::Down, MouseButton::Right) = (event.action, event.button)
|
||||
{
|
||||
self.maybe_show_context_menu(
|
||||
node.upcast(),
|
||||
&hit_test_result,
|
||||
input_event,
|
||||
can_gc,
|
||||
);
|
||||
}
|
||||
},
|
||||
// https://w3c.github.io/uievents/#handle-native-mouse-up
|
||||
MouseButtonAction::Up => {
|
||||
if let Some(a) = activatable {
|
||||
a.exit_formal_activation_state();
|
||||
}
|
||||
// (TODO) Step 6. Maybe send pointerup event with `dom_event``.
|
||||
|
||||
let target = node.upcast();
|
||||
dom_event.fire(target, can_gc);
|
||||
// Step 7. dispatch event at target.
|
||||
dom_event.dispatch(node.upcast(), false, can_gc);
|
||||
},
|
||||
}
|
||||
|
||||
if let MouseButtonAction::Click = event.action {
|
||||
if self.focus_transaction.borrow().is_some() {
|
||||
self.commit_focus_transaction(FocusInitiator::Local, can_gc);
|
||||
}
|
||||
self.maybe_fire_dblclick(node, &hit_test_result, input_event, can_gc);
|
||||
}
|
||||
|
||||
// When the contextmenu event is triggered by right mouse button
|
||||
// the contextmenu event MUST be dispatched after the mousedown event.
|
||||
if let (MouseButtonAction::Down, MouseButton::Right) = (event.action, event.button) {
|
||||
self.maybe_show_context_menu(node.upcast(), &hit_test_result, input_event, can_gc);
|
||||
}
|
||||
}
|
||||
|
||||
/// <https://www.w3.org/TR/uievents/#maybe-show-context-menu>
|
||||
|
|
|
@ -222,6 +222,7 @@ impl MouseEvent {
|
|||
}
|
||||
|
||||
/// Create a [MouseEvent] triggered by the embedder
|
||||
/// <https://w3c.github.io/uievents/#create-a-cancelable-mouseevent-id>
|
||||
pub(crate) fn for_platform_mouse_event(
|
||||
event: embedder_traits::MouseButtonEvent,
|
||||
pressed_mouse_buttons: u16,
|
||||
|
|
|
@ -1,9 +1,17 @@
|
|||
[navigate.py]
|
||||
expected: TIMEOUT
|
||||
[test_link_hash]
|
||||
[test_link_from_toplevel_context_with_target[_blank\]]
|
||||
expected: FAIL
|
||||
|
||||
[test_link_from_toplevel_context_with_target[_blank\]]
|
||||
[test_link_from_nested_context_with_target[]]
|
||||
expected: FAIL
|
||||
|
||||
[test_link_from_nested_context_with_target[_parent]]
|
||||
expected: FAIL
|
||||
|
||||
[test_link_from_nested_context_with_target[_self]]
|
||||
expected: FAIL
|
||||
|
||||
[test_link_from_nested_context_with_target[_top]]
|
||||
expected: FAIL
|
||||
|
||||
[test_link_from_toplevel_context_with_target[_parent\]]
|
||||
|
|
|
@ -7,3 +7,9 @@
|
|||
|
||||
[test_dismiss[prompt-None\]]
|
||||
expected: FAIL
|
||||
|
||||
[test_accept[alert-None\]]
|
||||
expected: FAIL
|
||||
|
||||
[test_dismiss[confirm-False\]]
|
||||
expected: FAIL
|
||||
|
|
|
@ -10,3 +10,6 @@
|
|||
|
||||
[test_seen_nodes[https coop\]]
|
||||
expected: FAIL
|
||||
|
||||
[test_removed_iframe]
|
||||
expected: FAIL
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
[navigation.py]
|
||||
expected: TIMEOUT
|
||||
[test_pointer]
|
||||
expected: FAIL
|
||||
|
|
3
tests/wpt/meta/webdriver/tests/classic/perform_actions/pointer_modifier_click.py.ini
vendored
Normal file
3
tests/wpt/meta/webdriver/tests/classic/perform_actions/pointer_modifier_click.py.ini
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
[pointer_modifier_click.py]
|
||||
[test_many_modifiers_click]
|
||||
expected: FAIL
|
|
@ -4,3 +4,6 @@
|
|||
|
||||
[test_set_to_available_size]
|
||||
expected: FAIL
|
||||
|
||||
[test_negative_x_y]
|
||||
expected: FAIL
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue