New issue
Advanced search Search tips
Note: Color blocks (like or ) mean that a user may not be available. Tooltip shows the reason.

Issue 798535 link

Starred by 27 users

MouseLeave Event is sometimes fired when repeatedly clicking

Reported by aris.hus...@jda.com, Jan 2 2018

Issue description

UserAgent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.108 Safari/537.36

Steps to reproduce the problem:
1. Create 2 nested DIVs
2. Listen for mouseleave on the outside one
3. REPEATEDLY click the inner div. Sometimes it is needed to move the mouse within the inner div, but not leave.

What is the expected behavior?
mouseLeave is not fired

What went wrong?
mouseleave was fired when the mouse stayed in the div

Did this work before? N/A 

Does this work in other browsers? Yes

Chrome version: 63.0.3239.108  Channel: stable
OS Version: 10.0
Flash Version: 

this bug, by nature, is hard to reproduce. At least 4 other issues have been logged about this bug, but are listed as WontFix because they could not be reproduced. (768166, 755817, 747273, 489234) these issues have test case, videos, and more info.
 
test.html
1.5 KB View Download
When this happens the relatedTarget and toElement of the event object are null.
As in the other issues we've requested an input trace. Can you please provide that?
trace_mouseLeaveInputTrace.json.gz
191 KB Download
Cc: vamshi.k...@techmahindra.com
Labels: Needs-Triage-M63 Triaged-ET Needs-Feedback
Unable to reproduce the issue on reported chrome version 63.0.3239.108 and on the latest canary 65.0.3309.0 using windows 10 with the below mentioned steps.
1. Launched chrome
2. Downloaded and opened the "test.html" file provided in comment#0
3. Clicked on inner div and noticed the MouseLeave events for 5-6 times

We observed the MouseLeave events registered correctly with out any issues. Attaching the screen cast of the same.

@Reporter: Could you please have a look at the screen cast and let us know if we have missed any steps while reproducing the issue. Any further inputs from your end helps us to triage the issue in abetter way.

Thanks!   
798535.mp4
1.2 MB View Download
I cant seem to pinpoint that exact time it will happen, but it generally takes several more clicks, since Ive used that test files the worst case has been ~160 clicks, but most times more than 10. This recording is actually the easiest time Ive had reproducing it. 

Now the weird part, I know this doesnt make any sense, but after testing this a lot, the issues seems to be easier to reproduce with the track-pad mouse buttons on my laptop vs the usb mouse. As far as I can tell, that should not matter at all, and it is not a requirement to reproduce.
731369ad-41a2-49dd-y835-d693a8fd907f.webm
1.9 MB View Download
Project Member

Comment 6 by sheriffbot@chromium.org, Jan 3 2018

Labels: -Needs-Feedback
Thank you for providing more feedback. Adding requester "vamshi.kommuri@techmahindra.com" to the cc list and removing "Needs-Feedback" label.

For more details visit https://www.chromium.org/issue-tracking/autotriage - Your friendly Sheriffbot
Cc: dtapu...@chromium.org
Unable to reproduce the issue even after trying with USB Mouse and Laptop's touch pad as said in your comment#5, though you mentioned it may not make a great difference in reproducing. CC'ing  dtapuska@chromium.org from https://bugs.chromium.org/p/chromium/issues/detail?id=747273 for further investigation.

Thanks!
Labels: Needs-Feedback
aris@ I don't seem to be able to reproduce it either. However, can you log a few other events in your environment. I'd like to know whether you get any of those events before you see the mouseleave. So can you log these as well and check when you see the mouseleave do you happen to get any of these events too.

pointerleave
select
dragstart


I have attached the updated file I used for this video, I was not able to get the pointer leave or select events to fire independently, I believe that this is because the element was a div, not a text box and I am not using a touch device (correct me if I'm wrong). If there is any other information needed please let me know.
7a7cea33-53d9-489c-y3e1-b2fb115c6238.webm
638 KB View Download
test.html
2.0 KB View Download
Project Member

Comment 10 by sheriffbot@chromium.org, Jan 4 2018

Cc: nzolghadr@chromium.org
Labels: -Needs-Feedback
Thank you for providing more feedback. Adding requester "nzolghadr@chromium.org" to the cc list and removing "Needs-Feedback" label.

For more details visit https://www.chromium.org/issue-tracking/autotriage - Your friendly Sheriffbot
We have tried with another updateed test file attached in comment#9 by reporter on chrome version 63.0.3239.108 using Windows 10 with the steps mentioned below. 
1. Launched chrome
2. Downloaded and opened the "test.html" file provided in comment#9
3. Clicked on inner div and noticed the MouseLeave events for 3 times around 20+ clicks for each event.

Still we are unable to reproduce the issue from our end. Attaching the screen cast for reference.

@ nzolghadr: Requesting you to look into this issue.

Thanks!
798535 updated.mp4
4.8 MB View Download
Cc: mustaq@chromium.org
I ran out of ideas. mustaq@ do you have any hint how we can make progress here? The fact that they don't get the pointerleave and only get the mouseleave does narrow down the scope. But looking at the code nothing pops up to my eyes.
No clue!

The repro video in #c10 doesn't apply as the mouse leaves the div there.
Can't repro on Surface.

aris.husanu@jda.com: Your trace in #c3 above seems to have too many mouse leaves, so no way to isolate the bad ones.

Could you please send us another trace where would be no valid mouse leave?  Start recording a trace, switch to your repro.  Right after you get the first bad mouseleave, don't move the mouse until you switch to tracing tab using use keyboard shortcut (alt-tab, ctrl-pageup etc).
I have attached the new trace, a quick test showed that the mouseleave event fired when I alt-tab ed as well, so this trace should have two mouseleave events. I also only selected input when tracing, I hope that is correct, and if not I'll add another trace.
trace_onlyBadMouseleave.json.gz
104 KB Download
In the last trace, WebViewImpl::HandleInputEvent received 3 mouseleave events, so I suspect this might be related to a crack in drag-and-drop.

aris.husanu: Do you recall ever having a bad mouseleave /before/ a dragstart?

No I don't remember that happening, and that's weird, for that trace I used the same test.html and it only showed the 2 mouseleave events in the textarea. I don't know if necessary, but I attached another trace replicating the same steps to see if it happened again.
trace_onlyBadMouseleave2.json.gz
124 KB Download
Owner: mustaq@chromium.org
Status: Assigned (was: Unconfirmed)
Thanks, your last trace looks better for debugging.  Here is the sequence of event-types seen by WebViewImpl::handleInputEvent with relative order in two renderers (not all of these event reach JS, btw):

Renderer1: L M+ (D U)+ L D U K K(5) L
Renderer2:                    K

(L=mouseleave, M=mousemove, D=mousedown, U=mouseup, K=RawKeyDown)

The first & last mouseleaves are not important to us, the middle one is the bad one.

In #c16 I suspected some crack in drag state but this trace proves me wrong: there is no mousemove in-between the button clicks.

I really suspect a spurious mouseleave event from OS/driver.

Yeah, the bad MouseLeave is forwarded to renderer from the browser side, see the RenderWidgetHostImpl::ForwardMouseEvent at 12753.814ms.

I will merge other related issues into this bug.  All of those issues are on Windows NT 10.0 (except for  Issue 768166  #c21).
Cc: bokan@chromium.org sc00335...@techmahindra.com kebalaji@chromium.org divya.pa...@techmahindra.com pnangunoori@chromium.org hdodda@chromium.org
 Issue 768166  has been merged into this issue.
 Issue 755817  has been merged into this issue.
 Issue 747273  has been merged into this issue.
Cc: krajshree@chromium.org ajha@chromium.org pbomm...@chromium.org
 Issue 794485  has been merged into this issue.
For whatever reason, it is easier to reproduce the bug though the link in  Issue 794485  (http://www.glavur.com).
Cc: tdres...@chromium.org
 Issue 489234  has been merged into this issue.
Labels: -Pri-2 Pri-3
Dropping the priority, it's a real bug but too hard to repro.

Comment 27 by bokan@chromium.org, Apr 13 2018

Cc: vamshi.kommuri@chromium.org
 Issue 829370  has been merged into this issue.

Comment 28 by bokan@chromium.org, Apr 13 2018

We seem to be getting quite a few reports here. Mustaq, could we add some TRACE events inside the mouse handling code that might help us diagnose the cause? Someone who can repro could probably capture a trace while this is happening.
 Issue 836151  has been merged into this issue.
I'm working on an Angular 5 application which uses ngx-popper for dialogs, and I see this issue very frequently. Around 20% of the clicks I do inside a popup register a spurious mouseleave event (causing the popup to close).

Comment 32 by skeet...@gmail.com, Jun 25 2018

I saw several remarks that say this is "difficult to reproduce".

I can reproduce it on every single element that has a "mouseleave" listener.

Simple example that can reproduce it everytime:

http://jsfiddle.net/vhf2te7d/3/
Comment 32 says it can be reproduced "everytime". His example is very similar to everyone else's, so his configuration or hardware setup may be more useful than some of our other reports which are more sporadic.
Yes, any info about the setup would be useful.

skeets23@: please let us know...
- What is your chrome://version?
- Windows version, device type (desktop/tablet...), if has touchscreen.
- Does it repro easily even after chrome://flags "reset all to default"?
- Etc.

Comment 35 by skeet...@gmail.com, Jun 26 2018

Sorry for the duplicate example, I just wanted to strip it down to very little code to narrow down the issue.

Here's my setup: 
Chrome version 67.0.3396.99
Windows 10 version 1803
TOSHIBA Satellite S55t-A
Intel i7-4700MQ

I reset my flags to default, I can still reproduce the issue consistantly. Rapid clicking causes the "mouseleave" event to fire once every 1-3 seconds.

I'm not sure if it matters, but I've got Chrome and Windows set to display in Japanese.

I've included a GIF that demonstrates I can reproduce the issue.

Curiously, in my project at work, the "mouseleave" event is getting fired very often, up to 1 time per 3 clicks.

The work around I'm using for now (that I found on stack overflow) is this:

$("div").mouseleave(function(event) {
  var e = event.originalEvent;
  if (!e.relatedTarget || !e.toElement) {
    // BUG in Chrome
    return;
  }
  <DO STUFF FOR MOUSELEAVE EVENT HERE>

});

With this work around in place, it works correctly 100% of time.
2018-06-26_14-50-30[1].gif
14.2 KB View Download

Comment 36 by skeet...@gmail.com, Jun 26 2018

Sorry for the duplicate comment (there's no way to edit comments here?)

I forgot to mention:

It's a laptop.
touchscreen: yes. Although I use 2 external montiors as well, that are not touchscreen

Comment 37 by skeet...@gmail.com, Jun 26 2018

Disabling all my extensions doesn't fix it either.

Comment 38 by skeet...@gmail.com, Jun 26 2018

Can also be reproduced consistantly on my older device:

Acer Apire 552
Chrome 67.0.3396.99
windows 7
AMD processor
no touchscreen, no external monitors
no chrome flags turned on

This device was factory reset recently, and the only thing I've installed is Chrome.
 Issue 860316  has been merged into this issue.
We are working on an application using the content API and have been hitting this very frequently when we have our own RAW Input Capture active to handle global hotkeys. 
Without this we can reproduce this but it's less reliable.
But with our RAW Input Capture active we have usually reproduce this with just one click.

I did some debugging, because we would rather not have to work around this bug in some complicated way.
Setting a breakpoint on ui::EventTypeFromMSG with a condition on WM_MOUSELEAVE did get triggered, so it seems like a bad WM_MOUSELEAVE from the OS.
But I will be doing some more debugging to maybe determine why we get this WM_MOUSELEAVE.

Also I was able to reproduce this issue on all chrome versions since 57.
Quick bisect:
You are probably looking for a change made after 442068 (known good), but no later than 442076 (first known bad).
CHANGELOG URL:
  https://chromium.googlesource.com/chromium/src/+log/0f17a6c232f6e4df227e3e149c6b097957151276..3963e231e4c43187a05f3c6420f5df997d734ea0

The only thing that happened in that time was https://codereview.chromium.org/2618063002, so I think this has always been an issue but is only noticeable after that change?!

Let me know if I can do anything else to help with this.
devenv_67f66720-48a7-40bc-a3f6-814c6b651743.png
20.5 KB View Download
I took a look at the code, and there is actually code in place to prevent this from happening, but the implementation was done using the wrong assumptions (at least it seems to me that way)

https://chromium.googlesource.com/chromium/src.git/+/master/content/browser/renderer_host/legacy_render_widget_host_win.cc#345

Here we can see that we are only supposed to send the MouseLeave if the leave event actually left the bounds of the Window.
This code here uses WindowFromPoint and assumes that it returns the parent, but that's not how WindowFromPoint works, rather then returning the shallowest result, it returns the deepest.

So the fix that I am currently testing locally, and which appears to be working without any side effects is instead of checking for != GetParent() to check for != hwnd() because WindowFromPoint returns the LegacyRenderWidgetHostHWND Window instead of the parent.

Why we even get a WM_MOUSELEAVE event from Windows is still beyond me, it seems wrong to me...but what do I know?!

Would be nice to get some feedback on this from someone who is more familiar with the code.
 Issue 861825  has been merged into this issue.
Cc: sky@chromium.org
Thanks alexander.guettler@ for debugging.  Adding sky@ who is familiar with the Windows class you mentioned.

sky@: does #c41 look reasonable to you?

In Chrome code we have very few HWNDs, so WindowFromPoint shouldn't really matter. Are you creating more child HWNDs?
No we are not creating more child HWNDs.
Correct me If I am wrong here, but the LegacyRenderWidgetHostHWND is a child of the Chrome_Widget_Win, which is a visible window.
So GetParent() in LegacyRenderWidgetHostHWND returns the Chrome_Widget_Win, but as WindowFromPoint returns the deepest window in the child tree of the window being hit it can't possibly return the Chrome_Widget_Win which is being checked in LegacyRenderWidgetHostHWND::OnMouseLeave()
That means that the check there can't ever work the way it's intended to work judging by the comment.

I still believe that changing it to check for hwnd() instead of GetParent(), fixes the issue without side effects. 
I had some other devs here test it too and they also report the bug as being fixed with that change.

I agree, this is all a bit tricky.
So what would be the next steps going forward. We continue to be happy with the solution I proposed earlier, and haven't found any issues after that change.
And I also confirmed this bug to be fixed after my change in a local regular chromium build.

I have some time to invest in this, as we would be very happy to have this fixed upstream for all the people using chrome that are experiencing this. And considering that there is now more use outside of chrome (cef, electron and some custom solutions). I can see this breaking some applications UX (as it did for us).

Not only does this bug cause a mouseleave on the web, but it also resets hover state of elements.


And to be clear, the reason I posted that link is that LegacyRenderWidgetHostHWND  as the WS_EX_TRANSPARENT extended style, so I wouldn't expect LegacyRenderWidgetHostHWND to be returned, but I could certainly be wrong.
Ah I see,

WS_EX_TRANSPARENT only matters for the ChildWindowFromPoint functions.
WindowFromPoint considers transparent only for a HTTRANSPARENT response for WM_NCHITTEST.

As per the link you posted:
¹There is a lot hiding behind the word Transparent because there are multiple ways a window can be determined transparent. The ...ChildWindowFromPoint... functions define transparent as has the WS_EX_TRANSPARENT extended window style.

²On the other hand, WindowFromPoint defines transparent as returns HTTRANSPARENT in response to WM_NCHITTEST. Actually, that's still not true. If the window belongs to a process thread different from the one calling WindowFromPoint, then WindowFromPoint will not send the message and will simply treat the window as opaque (i.e., not transparent).

³The RealChildWindowFromPoint includes transparent windows in the search, but has a special case for group boxes: The RealChildWindowFromPoint function skips over group boxes, unless the return value would have been the parent window, in which case it returns the group box after all.

So to me this is all behaving as expected, if we leave out that fact that we even get a WM_MOUSELEAVE, which I was not yet able to determine why.
Labels: -Pri-3 Pri-2
Given that we have 10 separate bugs merged into this one, with 4 of them reported since the last quarter, I am bumping up the priority.

 Issue 868774  has been merged into this issue.
Owner: lanwei@chromium.org
lanwei@ has agreed to look into this, thanks.
Cc: viswa.karala@chromium.org
 Issue 902629  has been merged into this issue.
Can actively pay attention to this issue?
Cc: -tdres...@chromium.org
Can anyone fix this? It has been one year now.
Sorry, this problem is really hard to reproduce, but we will look at this issue soon this month.
If you need help with debugging this I would be happy to as I can easily reproduce. In addition to the things I mentioned in comment #40 onwards.

We would really like this fixed in upstream instead of us having to patch it downstream
alexander...@ when you say downstream do you mean your own fork of chromium?

If you happen to have a fix feel free to send it for the upstream for review and we are happy to review it and merge it then. If the process seems hard you can also share the git patch with us and we will take care of that too.
Yes.

In fact we do have a small one line change that fixes this issue, I will see how the process works to submit a patch tomorrow.
Cc: phanindra.mandapaka@chromium.org susan.boorgula@chromium.org
 Issue 918444  has been merged into this issue.
Yes, we saw it, thank you for your work.
Project Member

Comment 64 by bugdroid1@chromium.org, Jan 16

The following revision refers to this bug:
  https://chromium.googlesource.com/chromium/src.git/+/307c628e7fa88e93a0290d9f9b331a78c9ea981b

commit 307c628e7fa88e93a0290d9f9b331a78c9ea981b
Author: Alexander Guettler <alexander@guettler.io>
Date: Wed Jan 16 03:58:09 2019

Fix MouseLeave bounds check on Windows

Sometimes Windows sends spurious WM_MOUSELEAVE messages
even though the mouse is still in bounds, the previous
check only checked for the parent under the assumption that
WindowFromPoint ignores the LegacyRenderWidgetHostHWND because of
WS_EX_TRANSPARENT, this turns out to be false. See
https://blogs.msdn.microsoft.com/oldnewthing/20101230-00/?p=11873
So we now also check the child window (as in our own).

R=kenrb@chromium.org, lanwei@chromium.org

Bug: 798535
Change-Id: Iac2577a9d76f51a27eb52b1df2a696487fef2353
Reviewed-on: https://chromium-review.googlesource.com/c/1405512
Reviewed-by: Scott Violet <sky@chromium.org>
Reviewed-by: Lan Wei <lanwei@chromium.org>
Commit-Queue: Lan Wei <lanwei@chromium.org>
Cr-Commit-Position: refs/heads/master@{#623087}
[modify] https://crrev.com/307c628e7fa88e93a0290d9f9b331a78c9ea981b/AUTHORS
[modify] https://crrev.com/307c628e7fa88e93a0290d9f9b331a78c9ea981b/content/browser/renderer_host/legacy_render_widget_host_win.cc

Sign in to add a comment