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 347089 10fccfc043b7390f5599499c0fff7d4aab3fb9fc
parent 347088 fc0cdec774074ca00e388c1ecd68cef0b1b7e3ce
child 347090 b722fac1af4b88f9ed41f620b0eef2e851f04faa
push id6389
push userraliiev@mozilla.com
push dateMon, 19 Sep 2016 13:38:22 +0000
treeherdermozilla-beta@01d67bfe6c81 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjfkthame
bugs1288760
milestone50.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 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;
 }
 
 //-------------------------------------------------------------------------