Bug 1288760 - Fix point conversion in nsDragService::StartInvokingDragSession. r?jfkthame draft
authorMasatoshi Kimura <VYV03354@nifty.ne.jp>
Thu, 28 Jul 2016 19:57:28 +0900
changeset 393752 7eedf0dd495a48b103e4c8f486d6b74ceb4ae0b0
parent 393484 db3ed1fdbbeaf5ab1e8fe454780146e7499be3db
child 526664 00c98569f0e50afd203befeedf80845d209b6bda
push id24408
push userVYV03354@nifty.ne.jp
push dateThu, 28 Jul 2016 12:28:13 +0000
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;
 }
 
 //-------------------------------------------------------------------------