Bug 1288760 - Fix point conversion in nsDragService::StartInvokingDragSession. r?jfkthame
MozReview-Commit-ID: DgNtnsvEPnR
--- 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;
}
//-------------------------------------------------------------------------