aboutsummaryrefslogtreecommitdiffstats
path: root/components/script/dom
diff options
context:
space:
mode:
authorEmilio Cobos Álvarez <ecoal95@gmail.com>2016-02-20 21:18:46 +0100
committerEmilio Cobos Álvarez <ecoal95@gmail.com>2016-03-02 20:01:41 +0100
commitc3786437a39faf2c52b66f7dcc3b8a9430a62dbc (patch)
tree7919f0827604ddb568f228828d7b5581383ddc4d /components/script/dom
parentb1f05816373f5e68ce242e0b1a45a50851f868bb (diff)
downloadservo-c3786437a39faf2c52b66f7dcc3b8a9430a62dbc.tar.gz
servo-c3786437a39faf2c52b66f7dcc3b8a9430a62dbc.zip
script: Fix `mouseover`/`mouseout` dispatching.
Diffstat (limited to 'components/script/dom')
-rw-r--r--components/script/dom/document.rs51
1 files changed, 33 insertions, 18 deletions
diff --git a/components/script/dom/document.rs b/components/script/dom/document.rs
index 4062fb7415f..966d245628b 100644
--- a/components/script/dom/document.rs
+++ b/components/script/dom/document.rs
@@ -824,21 +824,28 @@ impl Document {
}
}
+ // Werther the topmost element we are hovering now is diffrent than the previous
+ let is_different_topmost_target = mouse_over_targets.is_empty() ||
+ prev_mouse_over_targets.is_empty() ||
+ prev_mouse_over_targets[0].upcast::<Node>().to_trusted_node_address() !=
+ mouse_over_targets[0].upcast::<Node>().to_trusted_node_address();
+
// Remove hover from any elements in the previous list that are no longer
// under the mouse.
- for target in prev_mouse_over_targets.iter() {
- if !mouse_over_targets.contains(target) {
- let target_ref = &**target;
- if target_ref.get_hover_state() {
- target_ref.set_hover_state(false);
-
- let target = target_ref.upcast();
-
- // FIXME: we should be dispatching this event but we lack an actual
- // point to pass to it.
- if let Some(client_point) = client_point {
- self.fire_mouse_event(client_point, &target, "mouseout".to_owned());
- }
+ for (index, target) in prev_mouse_over_targets.iter().enumerate() {
+ // Hover state is reset as appropiate later
+ target.set_hover_state(false);
+
+ // https://www.w3.org/TR/uievents/#event-type-mouseout
+ //
+ // mouseout must be dispatched when the mouse moves off an element or when pointer
+ // mouse moves from an element onto the boundaries of one of its descendent elements.
+ let has_to_dispatch_mouse_out = index == 0 && is_different_topmost_target;
+
+ if has_to_dispatch_mouse_out {
+ let target = target.upcast();
+ if let Some(client_point) = client_point {
+ self.fire_mouse_event(client_point, &target, "mouseout".to_owned());
}
}
}
@@ -846,12 +853,20 @@ impl Document {
// Set hover state for any elements in the current mouse over list.
// Check if any of them changed state to determine whether to
// force a reflow below.
- for target in mouse_over_targets.r() {
- if !target.get_hover_state() {
- target.set_hover_state(true);
-
+ for (index, target) in mouse_over_targets.r().iter().enumerate() {
+ target.set_hover_state(true);
+
+ // https://www.w3.org/TR/uievents/#event-type-mouseover
+ //
+ // Mouseover must be fired when a pointing device is moved onto the boundaries of an
+ // element (we only fire it in the first because it bubbles), or when the pointer has
+ // moved from our children to ours.
+ //
+ // The below condition adresses both situations.
+ let has_to_dispatch_mouse_over = index == 0 && is_different_topmost_target;
+
+ if has_to_dispatch_mouse_over {
let target = target.upcast();
-
if let Some(client_point) = client_point {
self.fire_mouse_event(client_point, target, "mouseover".to_owned());
}