diff options
author | Emilio Cobos Álvarez <ecoal95@gmail.com> | 2016-02-20 21:18:46 +0100 |
---|---|---|
committer | Emilio Cobos Álvarez <ecoal95@gmail.com> | 2016-03-02 20:01:41 +0100 |
commit | c3786437a39faf2c52b66f7dcc3b8a9430a62dbc (patch) | |
tree | 7919f0827604ddb568f228828d7b5581383ddc4d /components/script/dom | |
parent | b1f05816373f5e68ce242e0b1a45a50851f868bb (diff) | |
download | servo-c3786437a39faf2c52b66f7dcc3b8a9430a62dbc.tar.gz servo-c3786437a39faf2c52b66f7dcc3b8a9430a62dbc.zip |
script: Fix `mouseover`/`mouseout` dispatching.
Diffstat (limited to 'components/script/dom')
-rw-r--r-- | components/script/dom/document.rs | 51 |
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()); } |