Bug 376578, drag feedback is offset when dpi is changed, r+sr=roc

This commit is contained in:
enndeakin@sympatico.ca 2008-01-08 14:03:53 -08:00
parent eed089c22f
commit e6ce27c055
5 changed files with 49 additions and 20 deletions

View File

@ -164,9 +164,10 @@ nsDragService::ConstructDragImage(nsIDOMNode* aDOMNode,
screenPoint.y = NSMaxY([[[NSScreen screens] objectAtIndex:0] frame]) - screenPoint.y;
nsRefPtr<gfxASurface> surface;
nsPresContext* pc;
nsresult rv = DrawDrag(aDOMNode, aRegion,
NSToIntRound(screenPoint.x), NSToIntRound(screenPoint.y),
aDragRect, getter_AddRefs(surface));
aDragRect, getter_AddRefs(surface), &pc);
if (!aDragRect->width || !aDragRect->height) {
// just use some suitable defaults
aDragRect->SetRect(NSToIntRound(screenPoint.x), NSToIntRound(screenPoint.y), 20, 20);

View File

@ -59,6 +59,9 @@
#include "gfxASurface.h"
#include "nsImageToPixbuf.h"
#include "nsIPresShell.h"
#include "nsPresContext.h"
#include "nsIDocument.h"
static PRLogModuleInfo *sDragLm = NULL;
@ -197,20 +200,24 @@ nsDragService::InvokeDragSession(nsIDOMNode *aDOMNode,
GdkPixbuf* dragPixbuf = nsnull;
nsRect dragRect;
nsPresContext* pc;
if (mHasImage || mSelection) {
nsRefPtr<gfxASurface> surface;
DrawDrag(aDOMNode, aRegion, mScreenX, mScreenY,
&dragRect, getter_AddRefs(surface));
&dragRect, getter_AddRefs(surface), &pc);
if (surface) {
dragPixbuf =
nsImageToPixbuf::SurfaceToPixbuf(surface, dragRect.width, dragRect.height);
}
}
if (dragPixbuf)
if (dragPixbuf) {
PRInt32 sx = mScreenX, sy = mScreenY;
ConvertToUnscaledDevPixels(pc, &sx, &sy);
gtk_drag_set_icon_pixbuf(context, dragPixbuf,
mScreenX - NSToIntRound(dragRect.x),
mScreenY - NSToIntRound(dragRect.y));
sx - NSToIntRound(dragRect.x),
sy - NSToIntRound(dragRect.y));
}
else
gtk_drag_set_icon_default(context);

View File

@ -111,9 +111,10 @@ nsDragService::CreateDragImage(nsIDOMNode *aDOMNode,
// Prepare the drag image
nsRect dragRect;
nsRefPtr<gfxASurface> surface;
nsPresContext* pc;
DrawDrag(aDOMNode, aRegion,
mScreenX, mScreenY,
&dragRect, getter_AddRefs(surface));
&dragRect, getter_AddRefs(surface), &pc);
if (!surface)
return PR_FALSE;
@ -169,10 +170,10 @@ nsDragService::CreateDragImage(nsIDOMNode *aDOMNode,
psdi->ptOffset.x = (PRUint32)((float)bmWidth/2.0f);
psdi->ptOffset.y = (PRUint32)((float)bmHeight/2.0f);
} else {
PRInt32 xOffset = mScreenX - dragRect.x;
PRInt32 yOffset = mScreenY - dragRect.y;
psdi->ptOffset.x = xOffset;
psdi->ptOffset.y = yOffset;
PRInt32 sx = mScreenX, sy = mScreenY;
ConvertToUnscaledDevPixels(pc, &sx, &sy);
psdi->ptOffset.x = sx - dragRect.x;
psdi->ptOffset.y = sy - dragRect.y;
}
DeleteDC(hdcSrc);

View File

@ -375,9 +375,11 @@ nsBaseDragService::DrawDrag(nsIDOMNode* aDOMNode,
nsIScriptableRegion* aRegion,
PRInt32 aScreenX, PRInt32 aScreenY,
nsRect* aScreenDragRect,
gfxASurface** aSurface)
gfxASurface** aSurface,
nsPresContext** aPresContext)
{
*aSurface = nsnull;
*aPresContext = nsnull;
// use a default size, in case of an error.
aScreenDragRect->x = aScreenX - mImageX;
@ -396,6 +398,8 @@ nsBaseDragService::DrawDrag(nsIDOMNode* aDOMNode,
if (!presShell)
return NS_ERROR_FAILURE;
*aPresContext = presShell->GetPresContext();
// check if drag images are disabled
PRBool enableDragImages = PR_TRUE;
nsCOMPtr<nsIPrefBranch> prefs(do_GetService(NS_PREFSERVICE_CONTRACTID));
@ -408,13 +412,12 @@ nsBaseDragService::DrawDrag(nsIDOMNode* aDOMNode,
// the region occupies
if (aRegion) {
// the region's coordinates are relative to the root frame
nsPresContext* pc = presShell->GetPresContext();
nsIFrame* rootFrame = presShell->GetRootFrame();
if (rootFrame && pc) {
if (rootFrame && *aPresContext) {
nsRect dragRect;
aRegion->GetBoundingBox(&dragRect.x, &dragRect.y, &dragRect.width, &dragRect.height);
dragRect.ScaleRoundOut(nsPresContext::AppUnitsPerCSSPixel());
dragRect.ScaleRoundOut(1.0 / pc->AppUnitsPerDevPixel());
dragRect.ScaleRoundOut(1.0 / (*aPresContext)->AppUnitsPerDevPixel());
nsIntRect screenRect = rootFrame->GetScreenRectExternal();
aScreenDragRect->SetRect(screenRect.x + dragRect.x, screenRect.y + dragRect.y,
@ -452,11 +455,7 @@ nsBaseDragService::DrawDrag(nsIDOMNode* aDOMNode,
nsCOMPtr<nsIImageLoadingContent> imageLoader = do_QueryInterface(dragNode);
// for image nodes, create the drag image from the actual image data
if (imageLoader) {
nsPresContext* pc = presShell->GetPresContext();
if (!pc)
return NS_ERROR_FAILURE;
return DrawDragForImage(pc, imageLoader, aScreenX, aScreenY,
return DrawDragForImage(*aPresContext, imageLoader, aScreenX, aScreenY,
aScreenDragRect, aSurface);
}
}
@ -569,3 +568,13 @@ nsBaseDragService::DrawDragForImage(nsPresContext* aPresContext,
gfxRect outRect = gfxRect(destRect.x, destRect.y, destRect.width, destRect.height);
return img->Draw(*rc, inRect, outRect);
}
void
nsBaseDragService::ConvertToUnscaledDevPixels(nsPresContext* aPresContext,
PRInt32* aScreenX, PRInt32* aScreenY)
{
PRInt32 adj = aPresContext->DeviceContext()->UnscaledAppUnitsPerDevPixel();
*aScreenX = nsPresContext::CSSPixelsToAppUnits(*aScreenX) / adj;
*aScreenY = nsPresContext::CSSPixelsToAppUnits(*aScreenY) / adj;
}

View File

@ -94,12 +94,16 @@ protected:
*
* If there is no drag image, the returned surface will be null, but
* aScreenDragRect will still be set to the drag area.
*
* aPresContext will be set to the nsPresContext used determined from
* whichever of mImage or aDOMNode is used.
*/
nsresult DrawDrag(nsIDOMNode* aDOMNode,
nsIScriptableRegion* aRegion,
PRInt32 aScreenX, PRInt32 aScreenY,
nsRect* aScreenDragRect,
gfxASurface** aSurface);
gfxASurface** aSurface,
nsPresContext **aPresContext);
/**
* Draw a drag image for an image node. This is called by DrawDrag.
@ -110,6 +114,13 @@ protected:
nsRect* aScreenDragRect,
gfxASurface** aSurface);
/**
* Convert aScreenX and aScreenY from CSS pixels into unscaled device pixels.
*/
void
ConvertToUnscaledDevPixels(nsPresContext* aPresContext,
PRInt32* aScreenX, PRInt32* aScreenY);
PRPackedBool mCanDrop;
PRPackedBool mDoingDrag;
// true if mImage should be used to set a drag image