Bug 1288760 - Fix point conversion in nsDragService::StartInvokingDragSession. r=jfkthame
authorMasatoshi Kimura <VYV03354@nifty.ne.jp>
Thu, 28 Jul 2016 19:57:28 +0900
changeset 332123 10fccfc043b7390f5599499c0fff7d4aab3fb9fc
parent 332122 fc0cdec774074ca00e388c1ecd68cef0b1b7e3ce
child 332124 b722fac1af4b88f9ed41f620b0eef2e851f04faa
push id9858
push userjlund@mozilla.com
push dateMon, 01 Aug 2016 14:37:10 +0000
treeherdermozilla-aurora@203106ef6cb6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjfkthame
bugs1288760
milestone50.0a1
Bug 1288760 - Fix point conversion in nsDragService::StartInvokingDragSession. r=jfkthame MozReview-Commit-ID: DgNtnsvEPnR
widget/windows/nsDragService.cpp
--- a/widget/windows/nsDragService.cpp
+++ b/widget/windows/nsDragService.cpp
@@ -21,16 +21,17 @@
 #include "nsNativeDragSource.h"
 #include "nsClipboard.h"
 #include "nsISupportsArray.h"
 #include "nsIDocument.h"
 #include "nsDataObjCollection.h"
 
 #include "nsString.h"
 #include "nsEscape.h"
+#include "nsIScreenManager.h"
 #include "nsISupportsPrimitives.h"
 #include "nsIURL.h"
 #include "nsCWebBrowserPersist.h"
 #include "nsToolkit.h"
 #include "nsCRT.h"
 #include "nsDirectoryServiceDefs.h"
 #include "nsUnicharUtils.h"
 #include "gfxContext.h"
@@ -247,16 +248,50 @@ nsDragService::InvokeDragSessionImpl(nsI
     }
     pdsh->Release();
   }
 
   // Kick off the native drag session
   return StartInvokingDragSession(itemToDrag, aActionType);
 }
 
+static bool
+LayoutDevicePointToCSSPoint(const LayoutDevicePoint& aDevPos,
+                            CSSPoint& aCSSPos)
+{
+  nsCOMPtr<nsIScreenManager> screenMgr =
+    do_GetService("@mozilla.org/gfx/screenmanager;1");
+  if (!screenMgr) {
+    return false;
+  }
+
+  nsCOMPtr<nsIScreen> screen;
+  screenMgr->ScreenForRect(NSToIntRound(aDevPos.x), NSToIntRound(aDevPos.y),
+                           1, 1, getter_AddRefs(screen));
+  if (!screen) {
+    return false;
+  }
+
+  int32_t w,h; // unused
+  LayoutDeviceIntPoint screenOriginDev;
+  screen->GetRect(&screenOriginDev.x, &screenOriginDev.y, &w, &h);
+
+  double scale;
+  screen->GetDefaultCSSScaleFactor(&scale);
+  LayoutDeviceToCSSScale devToCSSScale =
+    CSSToLayoutDeviceScale(scale).Inverse();
+
+  // Desktop pixels and CSS pixels share the same screen origin.
+  CSSIntPoint screenOriginCSS;
+  screen->GetRectDisplayPix(&screenOriginCSS.x, &screenOriginCSS.y, &w, &h);
+
+  aCSSPos = (aDevPos - screenOriginDev) * devToCSSScale + screenOriginCSS;
+  return true;
+}
+
 //-------------------------------------------------------------------------
 NS_IMETHODIMP
 nsDragService::StartInvokingDragSession(IDataObject * aDataObj,
                                         uint32_t aActionType)
 {
   // To do the drag we need to create an object that
   // implements the IDataObject interface (for OLE)
   RefPtr<nsNativeDragSource> nativeDragSrc =
@@ -321,22 +356,32 @@ nsDragService::StartInvokingDragSession(
   mUserCancelled = nativeDragSrc->UserCancelled();
 
   // We're done dragging, get the cursor position and end the drag
   // Use GetMessagePos to get the position of the mouse at the last message
   // seen by the event loop. (Bug 489729)
   // Note that we must convert this from device pixels back to Windows logical
   // pixels (bug 818927).
   DWORD pos = ::GetMessagePos();
-  POINT pt = { GET_X_LPARAM(pos), GET_Y_LPARAM(pos) };
-  HMONITOR monitor = ::MonitorFromPoint(pt, MONITOR_DEFAULTTOPRIMARY);
-  double dpiScale = widget::WinUtils::LogToPhysFactor(monitor);
-  nsIntPoint logPos(NSToIntRound(GET_X_LPARAM(pos) / dpiScale),
-                    NSToIntRound(GET_Y_LPARAM(pos) / dpiScale));
-  SetDragEndPoint(logPos);
+  CSSPoint cssPos;
+  if (!LayoutDevicePointToCSSPoint(LayoutDevicePoint(GET_X_LPARAM(pos),
+                                                     GET_Y_LPARAM(pos)),
+                                   cssPos)) {
+    // fallback to the simple scaling
+    POINT pt = { GET_X_LPARAM(pos), GET_Y_LPARAM(pos) };
+    HMONITOR monitor = ::MonitorFromPoint(pt, MONITOR_DEFAULTTOPRIMARY);
+    double dpiScale = widget::WinUtils::LogToPhysFactor(monitor);
+    cssPos.x = GET_X_LPARAM(pos) / dpiScale;
+    cssPos.y = GET_Y_LPARAM(pos) / dpiScale;
+  }
+  // We have to abuse SetDragEndPoint to pass CSS pixels because
+  // Event::GetScreenCoords will not convert pixels for dragend events
+  // until bug 1224754 is fixed.
+  SetDragEndPoint(LayoutDeviceIntPoint(NSToIntRound(cssPos.x),
+                                       NSToIntRound(cssPos.y)));
   EndDragSession(true);
 
   mDoingDrag = false;
 
   return DRAGDROP_S_DROP == res ? NS_OK : NS_ERROR_FAILURE;
 }
 
 //-------------------------------------------------------------------------