Bug 1244546 part 2 - Align the center point for pointerlock to meet widget's requirement. r=smaug
authorXidorn Quan <quanxunzhen@gmail.com>
Fri, 11 Mar 2016 19:10:44 +0800
changeset 288268 04ba63cdb181cf7efba193c1455e3ab506a699cc
parent 288267 560ae259d391cd537ca004cbc0c3caebcc6223fb
child 288269 1992eff1a02d5cfc227c2045754a3ba48a13065c
push id30079
push userryanvm@gmail.com
push dateSat, 12 Mar 2016 20:24:19 +0000
treeherdermozilla-central@d1d47ba19ce9 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs1244546
milestone48.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1244546 part 2 - Align the center point for pointerlock to meet widget's requirement. r=smaug MozReview-Commit-ID: I4BS1pfyMLD
dom/events/EventStateManager.cpp
--- a/dom/events/EventStateManager.cpp
+++ b/dom/events/EventStateManager.cpp
@@ -4159,58 +4159,34 @@ EventStateManager::NotifyMouseOver(Widge
     wrapper->mLastOverFrame = nullptr;
     wrapper->mLastOverElement = nullptr;
   }
 
   // Turn recursion protection back off
   wrapper->mFirstOverEventElement = nullptr;
 }
 
-// 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, the same units that
-// UIEvent::refPoint is in.
-//
-// XXX Hack alert: XXX
-// However, we do the computation in integer CSS pixels, NOT device pix,
-// in order to fudge around the one-pixel error in innerHeight in fullscreen
-// mode (see bug 799523 comment 35, and bug 729011). Using integer CSS pix
-// makes us throw away the fractional error that results, rather than having
-// it manifest as a potential one-device-pix discrepancy.
+// Returns the center point of the window's client area. This is
+// in widget coordinates, i.e. relative to the widget's top-left
+// corner, not in screen coordinates, the same units that UIEvent::
+// refpoint is in. It may not be the exact center of the window if
+// the platform requires rounding the coordinate.
 static LayoutDeviceIntPoint
-GetWindowInnerRectCenter(nsPIDOMWindowOuter* aWindow,
-                         nsIWidget* aWidget,
-                         nsPresContext* aContext)
+GetWindowClientRectCenter(nsIWidget* aWidget)
 {
-  NS_ENSURE_TRUE(aWindow && aWidget && aContext, LayoutDeviceIntPoint(0, 0));
-
-  nsGlobalWindow* window = nsGlobalWindow::Cast(aWindow);
-
-  float cssInnerX = window->GetMozInnerScreenXOuter();
-  int32_t innerX = int32_t(NS_round(cssInnerX));
-
-  float cssInnerY = window->GetMozInnerScreenYOuter();
-  int32_t innerY = int32_t(NS_round(cssInnerY));
-
-  ErrorResult dummy;
-  int32_t innerWidth = window->GetInnerWidthOuter(dummy);
-  dummy.SuppressException();
-
-  int32_t innerHeight = window->GetInnerHeightOuter(dummy);
-  dummy.SuppressException();
-
-  LayoutDeviceIntRect screen;
-  aWidget->GetScreenBounds(screen);
-
-  int32_t cssScreenX = aContext->DevPixelsToIntCSSPixels(screen.x);
-  int32_t cssScreenY = aContext->DevPixelsToIntCSSPixels(screen.y);
-
-  return LayoutDeviceIntPoint(
-    aContext->CSSPixelsToDevPixels(innerX - cssScreenX + innerWidth / 2),
-    aContext->CSSPixelsToDevPixels(innerY - cssScreenY + innerHeight / 2));
+  NS_ENSURE_TRUE(aWidget, LayoutDeviceIntPoint(0, 0));
+
+  LayoutDeviceIntRect rect;
+  aWidget->GetClientBounds(rect);
+  LayoutDeviceIntPoint point(rect.x + rect.width / 2,
+                             rect.y + rect.height / 2);
+  int32_t round = aWidget->RoundsWidgetCoordinatesTo();
+  point.x = point.x / round * round;
+  point.y = point.y / round * round;
+  return point - aWidget->WidgetToScreenOffset();
 }
 
 void
 EventStateManager::GeneratePointerEnterExit(EventMessage aMessage,
                                             WidgetMouseEvent* aEvent)
 {
   WidgetPointerEvent pointerEvent(*aEvent);
   pointerEvent.mMessage = aMessage;
@@ -4236,18 +4212,17 @@ EventStateManager::GenerateMouseEnterExi
       if (sIsPointerLocked && aMouseEvent->widget) {
         // The pointer is locked. If the pointer is not located at the center of
         // the window, dispatch a synthetic mousemove to return the pointer there.
         // Doing this between "real" pointer moves gives the impression that the
         // (locked) pointer can continue moving and won't stop at the screen
         // boundary. We cancel the synthetic event so that we don't end up
         // dispatching the centering move event to content.
         LayoutDeviceIntPoint center =
-          GetWindowInnerRectCenter(mDocument->GetWindow(), aMouseEvent->widget,
-                                   mPresContext);
+          GetWindowClientRectCenter(aMouseEvent->widget);
         aMouseEvent->lastRefPoint = center;
         if (aMouseEvent->refPoint != center) {
           // Mouse move doesn't finish at the center of the window. Dispatch a
           // synthetic native mouse event to move the pointer back to the center
           // of the window, to faciliate more movement. But first, record that
           // we've dispatched a synthetic mouse movement, so we can cancel it
           // in the other branch here.
           sSynthCenteringPoint = center;
@@ -4381,19 +4356,17 @@ EventStateManager::SetPointerLock(nsIWid
 
   if (sIsPointerLocked) {
     // Store the last known ref point so we can reposition the pointer after unlock.
     mPreLockPoint = sLastRefPoint;
 
     // Fire a synthetic mouse move to ensure event state is updated. We first
     // set the mouse to the center of the window, so that the mouse event
     // doesn't report any movement.
-    sLastRefPoint = GetWindowInnerRectCenter(aElement->OwnerDoc()->GetWindow(),
-                                             aWidget,
-                                             mPresContext);
+    sLastRefPoint = GetWindowClientRectCenter(aWidget);
     aWidget->SynthesizeNativeMouseMove(sLastRefPoint + aWidget->WidgetToScreenOffset(),
                                        nullptr);
 
     // Retarget all events to this element via capture.
     nsIPresShell::SetCapturingContent(aElement, CAPTURE_POINTERLOCK);
 
     // Suppress DnD
     if (dragService) {