Window-level mouse exit events fail to NotifyMouseOut when sent to a different ESM than the currently hovered one

VERIFIED FIXED in mozilla6

Status

()

Core
Event Handling
VERIFIED FIXED
7 years ago
6 years ago

People

(Reporter: smaug, Assigned: mstange)

Tracking

(Depends on: 1 bug)

Trunk
mozilla6
Points:
---
Dependency tree / graph

Firefox Tracking Flags

(Not tracked)

Details

Attachments

(1 attachment, 3 obsolete attachments)

(Reporter)

Description

7 years ago
See Bug 593959

Hover works in a different way than :active. Only one document can be
in :active, but :hover works in nested subdocuments.

bug 130078 may have just exposed the :hover handling we have for web content to
also chrome-content.
(Reporter)

Comment 1

7 years ago
Markus, any chance you could write a testcase.

<xul:browser> and <html:iframe> should work nowadays the same way.
(Assignee)

Comment 2

7 years ago
Thinking about this again, I've realized that this doesn't have to do much with bug 593959 at all, and not with releasing the mouse either. I'll update the title.
Summary: Investigate if/how :hover tracking gets out of sync when releasing the mouse over a different document → Window-level mouse exit events fail to NotifyMouseOut when sent to a different ESM than the currently hovered one
(Assignee)

Comment 3

7 years ago
Repeating the steps to reproduce from bug 593959 comment 3:
1. Be on a Mac.
2. Make sure "Tabs on Top" is *not* checked.
3. Deactivate / unfocus the Firefox window.
4. Move the mouse to the title bar.
5. Move the mouse down into the content area, passing over a tab on the way down. 

Most of the time, the tab you passed over will now still be in :hover state, and a tooltip opens that only goes away when you move your mouse over it.

So how is this related to the bug summary:

Mac Widget sends a window-level mouse exit event when the mouse moves into the content area because the <browser> has clickthrough="never" set on it. However, this event is sent at the point where the mouse is *after it has already exited chrome*, so it's now over content and the event is sent to the content ESM. The content ESM gets confused because the hovered element is stored in the chrome ESM, so NotifyMouseOut doesn't do anything in the content ESM.
(Assignee)

Comment 4

7 years ago
I don't know if it's possible to create a testcase for this. The clickthrough attribute only works on XUL (which is now blocked) and it only has effect on Mac.
(Assignee)

Updated

7 years ago
Assignee: nobody → mstange
Status: NEW → ASSIGNED
(Assignee)

Comment 5

7 years ago
Created attachment 505705 [details] [diff] [review]
v1
Attachment #505705 - Flags: review?(Olli.Pettay)
(Reporter)

Comment 6

7 years ago
Comment on attachment 505705 [details] [diff] [review]
v1

Why does mac send window level mouse exit when the mouse isn't exiting
window?

Does this affect badly to performance if we have very deep document hierarchy.
Say 100 nested iframes or something. Do we need to call the parent
ESM both for NS_MOUSE_MOVE and NS_MOUSE_EXIT?
The latter one doesn't happen too often, but the first one is very common.


The patch is not safe. parentESM may be deleted while handling GenerateMouseEnterExit(). You should keep parentShell->GetPresContext()
in a strong pointer.
Attachment #505705 - Flags: review?(Olli.Pettay) → review-
(Assignee)

Comment 7

6 years ago
Created attachment 517734 [details] [diff] [review]
alternative patch

(In reply to comment #6)
> Comment on attachment 505705 [details] [diff] [review]
> v1
> 
> Why does mac send window level mouse exit when the mouse isn't exiting
> window?

Because we want to behave as if the mouse wasn't over the window, e.g. we want to clear :hover states and send mouse out events.

There are two cases we send window-level mouse exit events even though technically the mouse is still over the window:
Case 1 is when the window is inactive and the user moves the mouse from an element that allows click-through to an element that doesn't. Both of these elements can be inside the same window. For example, click-through is allowed over Firefox chrome but blocked over content.
Case 2 is when the window starts out active with the mouse over a click-through blocked area (e.g. Firefox content area), and then is made inactive (for example using Cmd+Tab). When deactivating the window, all :hover states in the window should be cleared, so we send a window-level mouse exit event.

Here's a patch that uses a different approach from the last one: Instead of first looking for the ESM under the mouse and then traversing back up, we just always use the root ESM for window-level mouse exit events in PresShell::HandleEvent.

I'll send this to the tryserver in a minute.
Attachment #505705 - Attachment is obsolete: true
Attachment #517734 - Flags: review?(Olli.Pettay)
(Assignee)

Comment 8

6 years ago
Tryserver is green.
(Assignee)

Comment 9

6 years ago
The test uses enablePrivilege, so I guess I need to convert it to a chrome test?
(Reporter)

Comment 10

6 years ago
Yes, or wait ted's patch to enable DOMWindowUtils in SpecialPowers
(Assignee)

Updated

6 years ago
Depends on: 643803
(Reporter)

Comment 11

6 years ago
Comment on attachment 517734 [details] [diff] [review]
alternative patch

Waiting for updated tests.
Attachment #517734 - Flags: review?(Olli.Pettay)
(Assignee)

Comment 12

6 years ago
Created attachment 523330 [details] [diff] [review]
without enablePrivilege

Duh, the test already was a chrome test, so the enablePrivilege call was completely unnecessary. I've removed it.
Attachment #517734 - Attachment is obsolete: true
Attachment #523330 - Flags: review?(Olli.Pettay)
(Reporter)

Comment 13

6 years ago
So what if you have a window which doesn't have any borders and that
window has content page. Then you hover over some content element
(which is right at the edge of the page) and move mouse out from the window.
Does the hover get cleared?
(Assignee)

Updated

6 years ago
Blocks: 642423
(Reporter)

Comment 14

6 years ago
Waiting answer for the question above.
(I don't have a macbook with me atm, so can't test.)
(Assignee)

Comment 15

6 years ago
Created attachment 525454 [details] [diff] [review]
also test :hover clearance

(In reply to comment #13)
> So what if you have a window which doesn't have any borders and that
> window has content page. Then you hover over some content element
> (which is right at the edge of the page) and move mouse out from the window.
> Does the hover get cleared?

Yes, it does, because nsEventStateManager::NotifyMouseOut recurses down into subdocuments and calls SetContentState(nsnull, NS_EVENT_STATE_HOVER) when we're moving out of everything.
I've added that scenario to the test.
Attachment #523330 - Attachment is obsolete: true
Attachment #525454 - Flags: review?(Olli.Pettay)
Attachment #523330 - Flags: review?(Olli.Pettay)
(Reporter)

Updated

6 years ago
Attachment #525454 - Flags: review?(Olli.Pettay) → review+
(Assignee)

Comment 16

6 years ago
http://hg.mozilla.org/mozilla-central/rev/81bd19f483d0
Status: ASSIGNED → RESOLVED
Last Resolved: 6 years ago
Hardware: x86 → All
Resolution: --- → FIXED
Target Milestone: --- → mozilla6
Version: unspecified → Trunk

Comment 17

6 years ago
Setting resolution to Verified Fixed on Mozilla/5.0 (Windows NT 6.1; rv:6.0) Gecko/20100101 Firefox/6.0b3
Status: RESOLVED → VERIFIED
This bug's test "test_bug596600.xul" appears to be one of the largest sources of randomorange right now -- it's failing intermittently multiple times per day (an average of twice per day since it's been checked in).

The randomorange is tracked in bug 661099.  Anything we can do to fix/improve the situation there?
Depends on: 661099
You need to log in before you can comment on or make changes to this bug.