Closed
Bug 756936
Opened 13 years ago
Closed 12 years ago
Incorrect MouseEvent.mozMovement{X,Y} values when pointer locked on secondary monitor
Categories
(Core :: DOM: Core & HTML, defect)
Core
DOM: Core & HTML
Tracking
()
RESOLVED
FIXED
mozilla16
Tracking | Status | |
---|---|---|
firefox13 | --- | unaffected |
firefox14 | --- | affected |
firefox15 | --- | fixed |
firefox16 | --- | fixed |
firefox-esr10 | --- | unaffected |
People
(Reporter: cpearce, Assigned: cpearce)
References
(Blocks 1 open bug)
Details
(Whiteboard: [games:p2])
Attachments
(2 files, 4 obsolete files)
(deleted),
patch
|
smaug
:
review+
akeybl
:
approval-mozilla-aurora+
|
Details | Diff | Splinter Review |
(deleted),
patch
|
smaug
:
review+
|
Details | Diff | Splinter Review |
On my Windows7 x64 machine, when you lock the pointer with the browser window fullscreen on my secondary monitor, the mozMovement{X,Y} values in the generated MouseEvent events are stuck at a constant value.
It doesn't seem to matter where I position my secondary monitor WRT my primary (i.e. above, below, left, right, etc). It's just pointer lock requests in the secondary monitor seem to have fairly constant mozMovement{X,Y} values.
I'm not sure if this bug exists on non-windows platforms.
Testing on Mozilla/5.0 (Windows NT 6.1; WOW64; rv:15.0) Gecko/15.0 Firefox/15.0a1
STR:
1. Configure your system to have a secondary monitor.
2. Open http://pearce.org.nz/fullscreen in Firefox Nightly.
3. With the firefox window on your primary display, press the 'p' key, or click "Fullscreen with pointer lock" button.
4. Move the mouse. Observe the "Pointer: delta=(*, *) screen=(*, *) client=(*, *)" text being updated as MouseEvents are dispatched.
5. Press ESC to exit fullscreen, move the Firefox window to your secondary monitor, press 'p', or click "Fullscreen with pointer lock" button.
4. Observe that the "Pointer: ..." text doesn't update the same as when pointer locked on the primary monitor. The "delta" values (the mozMovement{X,Y} values) are fairly constant.
Assignee | ||
Comment 1•13 years ago
|
||
On my linux box when I lock the pointer on my secondary display (following the STR in comment0) the mouse jumps to appear as visible on my primary, but remains hidden on my secondary display, and I still get incoherent mozMovement{X,Y} values.
OS: Windows 7 → All
Hardware: x86_64 → All
Assignee | ||
Comment 2•13 years ago
|
||
Also note that the mozMovement{X,Y} values are coherent when in fullscreen move on the secondary monitor, it's only once the pointer is locked that they start reporting bogus values.
Updated•13 years ago
|
Whiteboard: [games:p2]
Assignee | ||
Comment 3•13 years ago
|
||
So when I change nsIntPoint nsEventStateManager::GetMouseCoords(nsIntRect aBounds) to just return (innerWidth/2, innerHeight/2), I get what looks like correct behaviour, and the mochitests still pass... Note aBounds has negative values in some fields in the secondary monitor case, whereas in the primary monitor case they're all >=0.
Humph: Why do you need to pass the bounds into this function?
And why is innerHeight used in the calculation but innerWidth isn't?
It looks like SynthesizeNativeMouseEvent takes coords relative to the window/widget's top-left corner, rather than in system pixel coords, at least on windows it looks like it does:
http://mxr.mozilla.org/mozilla-central/source/widget/windows/nsWindow.cpp#5716
Should nsIntPoint nsEventStateManager::GetMouseCoords() just be returning (innerWidth/2, innerHeight/2)?
Assignee | ||
Updated•12 years ago
|
blocking-basecamp: --- → ?
blocking-kilimanjaro: --- → ?
Assignee | ||
Updated•12 years ago
|
Assignee: nobody → cpearce
Status: NEW → ASSIGNED
Assignee | ||
Comment 4•12 years ago
|
||
The problem in brief is that we're using the widget's bounds in screen coords to calculate the mouse position and movement deltas, but the mouse/dom events and widget synthetic dispatch always assume the coords are in widget coords (i.e. offset from the widget origin, not the primary screen's origin).
Specifically, nsEventStateManager::GetMouseCoords(bounds) is being used to calulate the center of the window containing the mouse event, but GetMouseCoords() is passed screenBounds (bounds in screen coords) and using that to seed its calculations causing the calculated mouse position to be in screen coords. We're dispatching synthetic mouse events to the screen coords, but the synthetic dispatch expects widget coords, causing the problem.
Changes in this patch:
* Change the window center calculation to return an offset relative to the widget's origin. This fixes the base problem.
* Remove the "if (aEvent->refPoint == aEvent->lastRefPoint) aEvent->refPoint = sLastRefPoint;" case in nsEventStateManager::GenerateMouseEnterExit. In my testing this branch was only taken when aEvent->refPoint == sLastRefPoint, so it has no effect.
* Save the mouse position in widget coords before going into pointer lock in nsEventStateManager::mPreLockPoint (previously it was saved in screen coords).
* Synthesize mouse move to nsEventStateManager::mPreLockPoint when exiting, so mouse returns to same position upon pointer lock exit (previously mPreLockPoint was write only, and sLastScreenPoint was used for this purpose, except sLastScreenPoint is in screen coords, so it would behave incorrectly on secondary monitors).
* Set nsEventStateManager::sLastRefPoint before entering/exiting pointer lock so that the synthetic mouse move fired when entering/exiting doesn't report movement as ((mouse position before lock) - (center of window)) as it did previously. (If that's not learn, play with http://pearce.org.nz/fullscreen/pointerlock-position.html and you should see what I mean)
Attachment #633389 -
Flags: review?(bugs)
Assignee | ||
Comment 5•12 years ago
|
||
While figuring out how pointer lock worked I added comments, removed some unused code, and simplified nsDOMUIEvent::GetMovementPoint(). This should make it easier to understand the pointer lock code in future.
Note the nsDOMUIEvent::GetMovementPoint() code was converting from widget to screen to app units then back to pixels and then diffing, whereas we can instead simply just subtract the event's refPoint from the previous to get the delta. Much simpler this way.
Attachment #633393 -
Flags: review?(bugs)
Assignee | ||
Updated•12 years ago
|
status-firefox-esr10:
--- → unaffected
status-firefox13:
--- → unaffected
status-firefox14:
--- → affected
status-firefox15:
--- → affected
status-firefox16:
--- → affected
Comment 6•12 years ago
|
||
Comment on attachment 633389 [details] [diff] [review]
Patch 1 v1: Coords relative to widget, not screen.
>- aEvent->widget->SynthesizeNativeMouseMove(aEvent->lastRefPoint);
>+ nsIntPoint center = GetWidgetCenter(aEvent->widget);
>+ aEvent->lastRefPoint = center;
>+ // If this mouse move doesn't finish at the center of the widget,
>+ // dispatch a synthetic mouse move to return the mouse back to the
>+ // center.
>+ if (aEvent->refPoint != center) {
>+ aEvent->widget->SynthesizeNativeMouseMove(center);
> }
Why do we want to center in widget, and not in the web page?
If browser chrome takes lots of space, the center can be over chrome.
Attachment #633389 -
Flags: review?(bugs) → review-
Assignee | ||
Comment 7•12 years ago
|
||
Attachment #633389 -
Attachment is obsolete: true
Attachment #634254 -
Flags: review?(bugs)
Assignee | ||
Comment 8•12 years ago
|
||
Ooops, some of the changes from Patch 2 made it into this one.
The new patch finds the center of the inner content area, rather than the center of the outer window/widget.
Attachment #634254 -
Attachment is obsolete: true
Attachment #634254 -
Flags: review?(bugs)
Attachment #634256 -
Flags: review?(bugs)
Assignee | ||
Comment 9•12 years ago
|
||
Rebased on new patch 1.
Attachment #633393 -
Attachment is obsolete: true
Attachment #633393 -
Flags: review?(bugs)
Attachment #634259 -
Flags: review?(bugs)
Comment 10•12 years ago
|
||
Comment on attachment 634256 [details] [diff] [review]
Patch 1 v3: Coords relative to widget, not screen.
>+// Returns the center point of the window's inner content area.
>+// This is in widget coordinates, i.e. relative to the widget's top
>+// left corner, not in screen coordinates.
>+static nsIntPoint
>+GetWindowInnerRectCenter(nsPIDOMWindow* aWindow,
>+ nsIWidget* aWidget,
>+ nsPresContext* aContext)
>+{
>+ NS_ENSURE_TRUE(aWindow != nsnull, nsIntPoint(0,0));
>+ NS_ENSURE_TRUE(aWidget != nsnull, nsIntPoint(0,0));
>+ NS_ENSURE_TRUE(aContext != nsnull, nsIntPoint(0,0));
NS_ENSURE_TRUE(aWindow && aWidget && aContext, nsIntPoint(0,0));
Attachment #634256 -
Flags: review?(bugs) → review+
Comment 11•12 years ago
|
||
(In reply to Chris Pearce (:cpearce) from comment #5)
> Note the nsDOMUIEvent::GetMovementPoint() code was converting from widget to
> screen to app units then back to pixels and then diffing, whereas we can
> instead simply just subtract the event's refPoint from the previous to get
> the delta. Much simpler this way.
I don't understand this. The result should be in CSS pixels. With your patch, what guarantees that?
(Perhaps I'm just missing something.)
Updated•12 years ago
|
Attachment #634259 -
Flags: review?(bugs)
Assignee | ||
Comment 13•12 years ago
|
||
(In reply to Olli Pettay [:smaug] from comment #11)
> (In reply to Chris Pearce (:cpearce) from comment #5)
> > Note the nsDOMUIEvent::GetMovementPoint() code was converting from widget to
> > screen to app units then back to pixels and then diffing, whereas we can
> > instead simply just subtract the event's refPoint from the previous to get
> > the delta. Much simpler this way.
> I don't understand this. The result should be in CSS pixels. With your
> patch, what guarantees that?
> (Perhaps I'm just missing something.)
Ah yes, my mistake. You're correct, I was converting to dev pixels, not CSS pixels. I'll fix that.
The change I'm trying to make here is to remove the unnecessary conversion from widget offset to screen coords. Let me update the patch again...
Assignee | ||
Comment 14•12 years ago
|
||
Attachment #634661 -
Flags: review?(bugs)
Comment 15•12 years ago
|
||
Since it's tagged as a games P2, we are not going to track this.
blocking-kilimanjaro: ? → -
Updated•12 years ago
|
Attachment #634661 -
Flags: review?(bugs) → review+
Assignee | ||
Comment 16•12 years ago
|
||
https://hg.mozilla.org/integration/mozilla-inbound/rev/4be7471e7a95
https://hg.mozilla.org/integration/mozilla-inbound/rev/d047caf12f04
Target Milestone: --- → mozilla16
Comment 17•12 years ago
|
||
https://hg.mozilla.org/mozilla-central/rev/4be7471e7a95
https://hg.mozilla.org/mozilla-central/rev/d047caf12f04
Status: ASSIGNED → RESOLVED
Closed: 12 years ago
Resolution: --- → FIXED
Updated•12 years ago
|
status-firefox16:
affected → ---
Assignee | ||
Updated•12 years ago
|
status-firefox16:
--- → fixed
Assignee | ||
Updated•12 years ago
|
Attachment #634259 -
Attachment is obsolete: true
Comment 18•12 years ago
|
||
Can we are get this on Aurora (fx15)?
Assignee | ||
Comment 19•12 years ago
|
||
Comment on attachment 634256 [details] [diff] [review]
Patch 1 v3: Coords relative to widget, not screen.
[Approval Request Comment]
Bug caused by (feature/regressing bug #): Mouse/pointer lock (bug 633602)
User impact if declined: Pointer lock reports incorrect mouse movement values when the mouse is locked on a secondary monitor. Games etc won't work. FF15 is our big bang HTML5 Games Are Awesome Release, so it would be good to get this in FF15.
Testing completed (on m-c, etc.): Local testing, and it's been on m-c for weeks.
Risk to taking this patch (and alternatives if risky): Pretty low risk.
String or UUID changes made by this patch: None.
Attachment #634256 -
Flags: approval-mozilla-aurora?
Comment 20•12 years ago
|
||
Comment on attachment 634256 [details] [diff] [review]
Patch 1 v3: Coords relative to widget, not screen.
[Triage Comment]
Low risk, and in support of a big bang :). Approved for Aurora 15.
Attachment #634256 -
Flags: approval-mozilla-aurora? → approval-mozilla-aurora+
Assignee | ||
Comment 21•12 years ago
|
||
Assignee | ||
Updated•12 years ago
|
Target Milestone: mozilla16 → mozilla15
Assignee | ||
Comment 23•12 years ago
|
||
This is fixed in mozilla 15, so why shouldn't the target milestone be 15?
Or is target milestone supposed to be for the release in which it first was pushed to m-c?
Comment 24•12 years ago
|
||
(In reply to Chris Pearce (:cpearce) from comment #23)
> Or is target milestone supposed to be for the release in which it first was
> pushed to m-c?
Yes.
Updated•6 years ago
|
Component: DOM → DOM: Core & HTML
You need to log in
before you can comment on or make changes to this bug.
Description
•