Bug 120786

Summary: Mouseenter/-leave not triggered when element under cursor is moved/removed
Product: WebKit Reporter: karl.bohlmark
Component: UI EventsAssignee: Allan Sandfeld Jensen <allan.jensen>
Status: REOPENED ---    
Severity: Normal CC: allan.jensen, ap, buildbot, commit-queue, dtrebbien, esprehn+autocc, gbonanome, kangil.han, kling, koivisto, rniwa
Priority: P2    
Version: 528+ (Nightly build)   
Hardware: Unspecified   
OS: OS X 10.8   
See Also: https://bugs.webkit.org/show_bug.cgi?id=156971
Bug Depends on: 120862, 121174    
Bug Blocks:    
Attachments:
Description Flags
Reproduction
none
Patch
none
Patch
tonikitoo: review+, buildbot: commit-queue-
Archive of layout-test-results from webkit-ews-14 for mac-mountainlion-wk2 none

Description karl.bohlmark 2013-09-05 12:20:06 PDT
Steps to reproduce:
----------------

1) Open the attached example with web inspector open.
2) Click the red div.

Expected: When the red div is removed and the green div takes its place, a mouseenter event should be triggered causing 'enter green' to be output to the console.

Actual: No mouseenter event is triggered.

Build: WebKit r154944 was built on 01 September 2013
Comment 1 karl.bohlmark 2013-09-05 12:20:41 PDT
Created attachment 210644 [details]
Reproduction
Comment 2 Alexey Proskuryakov 2013-09-05 12:58:28 PDT
Still not sure why we added support for these events, but now we are stuck polishing their behavior...
Comment 3 Allan Sandfeld Jensen 2013-09-05 16:22:26 PDT
I am guessing you can create a similar bug with CSS hover effects not being updated.
Comment 4 Allan Sandfeld Jensen 2013-09-06 04:46:50 PDT
This is a similar problem to when we do scrolling, we need to send a fake mousemove to make sure hover effects are updated (mouseenter/-leave is handled by the same code as CSS hover). 

One solution could be to emit a fake mousemove event when an element that has Element::hovered() set is moved or removed.
Comment 5 Allan Sandfeld Jensen 2013-09-06 05:07:38 PDT
We actually have code to update the hover/active state after a hovered element is removed.

Looking closer at the test-case, there is no layered content here. It only tests that mouseleave is not emitted when an element is removed from the document.
Comment 6 Allan Sandfeld Jensen 2013-09-06 05:28:33 PDT
Created attachment 210721 [details]
Patch

A quick fix to get updateHoverActive to generate mouseenter/-leave events when hoverstate is updated internally. It might be cleaner to just issue fake mousemoves here, but that could have other web visible effects.
Comment 7 Darin Adler 2013-09-06 13:36:49 PDT
Comment on attachment 210721 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=210721&action=review

We should make a regression test. Can we do that?

I’m going to say r=me, but the lack of a test is a big problem, and there are some minor issues in the code, too.

> Source/WebCore/page/EventHandler.cpp:3210
> +            bool shiftKey;
> +            bool ctrlKey;
> +            bool altKey;
> +            bool metaKey;
> +            PlatformKeyboardEvent::getCurrentModifierState(shiftKey, ctrlKey, altKey, metaKey);
> +            PlatformMouseEvent fakeMouseMoveEvent(m_lastKnownMousePosition, m_lastKnownMouseGlobalPosition, NoButton, PlatformEvent::MouseMoved, 0, shiftKey, ctrlKey, altKey, metaKey, currentTime());

It doesn’t seem great to combine the latest modifier state with the “last known” mouse position.

And this code sequence reads awkwardly and poorly here. I would prefer that we factor this into a separate function, and I also suggest we record the modifier state when we record the mouse position instead of explicitly re-getting it now.
Comment 8 Allan Sandfeld Jensen 2013-09-09 02:31:57 PDT
(In reply to comment #7)
> (From update of attachment 210721 [details])
> View in context: https://bugs.webkit.org/attachment.cgi?id=210721&action=review
> 
> We should make a regression test. Can we do that?
> 
> I’m going to say r=me, but the lack of a test is a big problem, and there are some minor issues in the code, too.
> 
> > Source/WebCore/page/EventHandler.cpp:3210
> > +            bool shiftKey;
> > +            bool ctrlKey;
> > +            bool altKey;
> > +            bool metaKey;
> > +            PlatformKeyboardEvent::getCurrentModifierState(shiftKey, ctrlKey, altKey, metaKey);
> > +            PlatformMouseEvent fakeMouseMoveEvent(m_lastKnownMousePosition, m_lastKnownMouseGlobalPosition, NoButton, PlatformEvent::MouseMoved, 0, shiftKey, ctrlKey, altKey, metaKey, currentTime());
> 
> It doesn’t seem great to combine the latest modifier state with the “last known” mouse position.
> 
> And this code sequence reads awkwardly and poorly here. I would prefer that we factor this into a separate function, and I also suggest we record the modifier state when we record the mouse position instead of explicitly re-getting it now.


I noticed later that we issue a fake mousemove when the hovered element is removed due to CSS display being set to none. I will prefer in the next patch to remove the hovertimer, and use the same fake mousemove mechanism for this case as well. It means removing code instead of adding code :)
Comment 9 Allan Sandfeld Jensen 2013-09-09 03:42:21 PDT
Created attachment 211025 [details]
Patch
Comment 10 Build Bot 2013-09-09 07:25:46 PDT
Comment on attachment 211025 [details]
Patch

Attachment 211025 [details] did not pass mac-wk2-ews (mac-wk2):
Output: http://webkit-queues.appspot.com/results/1718996

New failing tests:
fast/events/mouseenterleave-detached-element.html
Comment 11 Build Bot 2013-09-09 07:25:48 PDT
Created attachment 211041 [details]
Archive of layout-test-results from webkit-ews-14 for mac-mountainlion-wk2

The attached test failures were seen while running run-webkit-tests on the mac-wk2-ews.
Bot: webkit-ews-14  Port: mac-mountainlion-wk2  Platform: Mac OS X 10.8.4
Comment 12 Allan Sandfeld Jensen 2013-09-10 02:05:19 PDT
(In reply to comment #11)
> Created an attachment (id=211041) [details]
> Archive of layout-test-results from webkit-ews-14 for mac-mountainlion-wk2
> 
> The attached test failures were seen while running run-webkit-tests on the mac-wk2-ews.
> Bot: webkit-ews-14  Port: mac-mountainlion-wk2  Platform: Mac OS X 10.8.4

 mouseenter on DIV#mydiv1
 mouseenter on BODY
 mouseenter on HTML
+mouseenter on #document
 removing DIV#mydiv1
 mouseenter on DIV#mydiv2
 
It is only failing because it was tested before the patch for bug 120862 was applied.
Comment 13 Antonio Gomes 2013-09-10 03:18:07 PDT
Comment on attachment 211025 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=211025&action=review

Change itself looks good. I am keeping cq- as test might get improved a bit.

> LayoutTests/fast/events/mouseenterleave-detached-element.html:20
> +    document.addEventListener('mouseleave', logMouseEvent, true);

is there any "mouselevave" event expected to be thrown?

> LayoutTests/fast/events/mouseenterleave-detached-element.html:26
> +        window.setTimeout(endTest, 200);

200 is quite a lot :(

If we know exactly how many events are being thrown, can we use a count instead, and call endTest when the count reaches the expected amount?
Comment 14 Allan Sandfeld Jensen 2013-09-10 04:31:44 PDT
(In reply to comment #13)
> (From update of attachment 211025 [details])
> View in context: https://bugs.webkit.org/attachment.cgi?id=211025&action=review
> 
> Change itself looks good. I am keeping cq- as test might get improved a bit.
> 
> > LayoutTests/fast/events/mouseenterleave-detached-element.html:20
> > +    document.addEventListener('mouseleave', logMouseEvent, true);
> 
> is there any "mouselevave" event expected to be thrown?
> 
> > LayoutTests/fast/events/mouseenterleave-detached-element.html:26
> > +        window.setTimeout(endTest, 200);
> 
> 200 is quite a lot :(
> 
The fake mousemove event has a minimum delay of 100ms.

> If we know exactly how many events are being thrown, can we use a count instead, and call endTest when the count reaches the expected amount?

Currently we only get one mouseenter to the new element. Some might argue we should also get a mouseleave on the removed element, but that is currently a lot harder because it would require emitting an immediately event during handling of the remove. I would also argue that you can not expect mouse events on detached elements or elements being detached.
Comment 15 Allan Sandfeld Jensen 2013-09-11 04:44:05 PDT
Committed r155519: <http://trac.webkit.org/changeset/155519>
Comment 16 WebKit Commit Bot 2013-09-11 11:47:20 PDT
Re-opened since this is blocked by bug 121174
Comment 17 Alexey Proskuryakov 2013-09-11 11:50:14 PDT
This change caused test failures, and Allan is away, so rolling out.

http://build.webkit.org/results/Apple%20MountainLion%20Release%20WK1%20(Tests)/r155540%20(12792)/results.html

The included test case fails, and editing/pasteboard/copy-standalone-image-crash.html started to crash.
Comment 18 Giulio Bonanome 2014-01-02 11:51:54 PST
Hi. This issue could be linked to this one: https://bugs.webkit.org/show_bug.cgi?id=4117 ? 
CSS :hover is not triggered untile mouse is moved.
Comment 19 Daniel Trebbien 2015-02-06 12:20:19 PST
See also: http://crbug.com/276329

I am not able to reproduce the issue in Safari 8.0.3 on Mac OS 10.10.2.
Comment 20 Lucas Forschler 2019-02-06 09:19:00 PST
Mass move bugs into the DOM component.
Comment 21 Ryosuke Niwa 2019-02-06 22:03:04 PST
These are UI events.