widget/xpwidgets/nsBaseDragService.cpp

Thu, 15 Jan 2015 21:03:48 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 15 Jan 2015 21:03:48 +0100
branch
TOR_BUG_9701
changeset 11
deefc01c0e14
permissions
-rw-r--r--

Integrate friendly tips from Tor colleagues to make (or not) 4.5 alpha 3;
This includes removal of overloaded (but unused) methods, and addition of
a overlooked call to DataStruct::SetData(nsISupports, uint32_t, bool.)

     1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 #include "nsBaseDragService.h"
     7 #include "nsITransferable.h"
     9 #include "nsIServiceManager.h"
    10 #include "nsITransferable.h"
    11 #include "nsISupportsArray.h"
    12 #include "nsSize.h"
    13 #include "nsXPCOM.h"
    14 #include "nsISupportsPrimitives.h"
    15 #include "nsCOMPtr.h"
    16 #include "nsIInterfaceRequestorUtils.h"
    17 #include "nsIFrame.h"
    18 #include "nsIDocument.h"
    19 #include "nsIContent.h"
    20 #include "nsIPresShell.h"
    21 #include "nsViewManager.h"
    22 #include "nsIDOMNode.h"
    23 #include "nsIDOMDragEvent.h"
    24 #include "nsISelection.h"
    25 #include "nsISelectionPrivate.h"
    26 #include "nsPresContext.h"
    27 #include "nsIDOMDataTransfer.h"
    28 #include "nsIImageLoadingContent.h"
    29 #include "imgIContainer.h"
    30 #include "imgIRequest.h"
    31 #include "nsRegion.h"
    32 #include "nsXULPopupManager.h"
    33 #include "nsMenuPopupFrame.h"
    34 #include "mozilla/MouseEvents.h"
    35 #include "mozilla/Preferences.h"
    36 #include "mozilla/gfx/2D.h"
    38 #include "gfxContext.h"
    39 #include "gfxPlatform.h"
    40 #include <algorithm>
    42 using namespace mozilla;
    43 using namespace mozilla::gfx;
    44 using namespace mozilla::dom;
    46 #define DRAGIMAGES_PREF "nglayout.enable_drag_images"
    48 nsBaseDragService::nsBaseDragService()
    49   : mCanDrop(false), mOnlyChromeDrop(false), mDoingDrag(false),
    50     mHasImage(false), mUserCancelled(false),
    51     mDragAction(DRAGDROP_ACTION_NONE), mTargetSize(0,0),
    52     mImageX(0), mImageY(0), mScreenX(-1), mScreenY(-1), mSuppressLevel(0),
    53     mInputSource(nsIDOMMouseEvent::MOZ_SOURCE_MOUSE)
    54 {
    55 }
    57 nsBaseDragService::~nsBaseDragService()
    58 {
    59 }
    61 NS_IMPL_ISUPPORTS(nsBaseDragService, nsIDragService, nsIDragSession)
    63 //---------------------------------------------------------
    64 NS_IMETHODIMP
    65 nsBaseDragService::SetCanDrop(bool aCanDrop)
    66 {
    67   mCanDrop = aCanDrop;
    68   return NS_OK;
    69 }
    71 //---------------------------------------------------------
    72 NS_IMETHODIMP
    73 nsBaseDragService::GetCanDrop(bool * aCanDrop)
    74 {
    75   *aCanDrop = mCanDrop;
    76   return NS_OK;
    77 }
    78 //---------------------------------------------------------
    79 NS_IMETHODIMP
    80 nsBaseDragService::SetOnlyChromeDrop(bool aOnlyChrome)
    81 {
    82   mOnlyChromeDrop = aOnlyChrome;
    83   return NS_OK;
    84 }
    86 //---------------------------------------------------------
    87 NS_IMETHODIMP
    88 nsBaseDragService::GetOnlyChromeDrop(bool* aOnlyChrome)
    89 {
    90   *aOnlyChrome = mOnlyChromeDrop;
    91   return NS_OK;
    92 }
    94 //---------------------------------------------------------
    95 NS_IMETHODIMP
    96 nsBaseDragService::SetDragAction(uint32_t anAction)
    97 {
    98   mDragAction = anAction;
    99   return NS_OK;
   100 }
   102 //---------------------------------------------------------
   103 NS_IMETHODIMP
   104 nsBaseDragService::GetDragAction(uint32_t * anAction)
   105 {
   106   *anAction = mDragAction;
   107   return NS_OK;
   108 }
   110 //---------------------------------------------------------
   111 NS_IMETHODIMP
   112 nsBaseDragService::SetTargetSize(nsSize aDragTargetSize)
   113 {
   114   mTargetSize = aDragTargetSize;
   115   return NS_OK;
   116 }
   118 //---------------------------------------------------------
   119 NS_IMETHODIMP
   120 nsBaseDragService::GetTargetSize(nsSize * aDragTargetSize)
   121 {
   122   *aDragTargetSize = mTargetSize;
   123   return NS_OK;
   124 }
   126 //-------------------------------------------------------------------------
   128 NS_IMETHODIMP
   129 nsBaseDragService::GetNumDropItems(uint32_t * aNumItems)
   130 {
   131   *aNumItems = 0;
   132   return NS_ERROR_FAILURE;
   133 }
   136 //
   137 // GetSourceDocument
   138 //
   139 // Returns the DOM document where the drag was initiated. This will be
   140 // nullptr if the drag began outside of our application.
   141 //
   142 NS_IMETHODIMP
   143 nsBaseDragService::GetSourceDocument(nsIDOMDocument** aSourceDocument)
   144 {
   145   *aSourceDocument = mSourceDocument.get();
   146   NS_IF_ADDREF(*aSourceDocument);
   148   return NS_OK;
   149 }
   151 //
   152 // GetSourceNode
   153 //
   154 // Returns the DOM node where the drag was initiated. This will be
   155 // nullptr if the drag began outside of our application.
   156 //
   157 NS_IMETHODIMP
   158 nsBaseDragService::GetSourceNode(nsIDOMNode** aSourceNode)
   159 {
   160   *aSourceNode = mSourceNode.get();
   161   NS_IF_ADDREF(*aSourceNode);
   163   return NS_OK;
   164 }
   167 //-------------------------------------------------------------------------
   169 NS_IMETHODIMP
   170 nsBaseDragService::GetData(nsITransferable * aTransferable,
   171                            uint32_t aItemIndex)
   172 {
   173   return NS_ERROR_FAILURE;
   174 }
   176 //-------------------------------------------------------------------------
   177 NS_IMETHODIMP
   178 nsBaseDragService::IsDataFlavorSupported(const char *aDataFlavor,
   179                                          bool *_retval)
   180 {
   181   return NS_ERROR_FAILURE;
   182 }
   184 NS_IMETHODIMP
   185 nsBaseDragService::GetDataTransfer(nsIDOMDataTransfer** aDataTransfer)
   186 {
   187   *aDataTransfer = mDataTransfer;
   188   NS_IF_ADDREF(*aDataTransfer);
   189   return NS_OK;
   190 }
   192 NS_IMETHODIMP
   193 nsBaseDragService::SetDataTransfer(nsIDOMDataTransfer* aDataTransfer)
   194 {
   195   mDataTransfer = aDataTransfer;
   196   return NS_OK;
   197 }
   199 //-------------------------------------------------------------------------
   200 NS_IMETHODIMP
   201 nsBaseDragService::InvokeDragSession(nsIDOMNode *aDOMNode,
   202                                      nsISupportsArray* aTransferableArray,
   203                                      nsIScriptableRegion* aDragRgn,
   204                                      uint32_t aActionType)
   205 {
   206   NS_ENSURE_TRUE(aDOMNode, NS_ERROR_INVALID_ARG);
   207   NS_ENSURE_TRUE(mSuppressLevel == 0, NS_ERROR_FAILURE);
   209   // stash the document of the dom node
   210   aDOMNode->GetOwnerDocument(getter_AddRefs(mSourceDocument));
   211   mSourceNode = aDOMNode;
   212   mEndDragPoint = nsIntPoint(0, 0);
   214   // When the mouse goes down, the selection code starts a mouse
   215   // capture. However, this gets in the way of determining drag
   216   // feedback for things like trees because the event coordinates
   217   // are in the wrong coord system, so turn off mouse capture.
   218   nsIPresShell::ClearMouseCapture(nullptr);
   220   return NS_OK;
   221 }
   223 NS_IMETHODIMP
   224 nsBaseDragService::InvokeDragSessionWithImage(nsIDOMNode* aDOMNode,
   225                                               nsISupportsArray* aTransferableArray,
   226                                               nsIScriptableRegion* aRegion,
   227                                               uint32_t aActionType,
   228                                               nsIDOMNode* aImage,
   229                                               int32_t aImageX, int32_t aImageY,
   230                                               nsIDOMDragEvent* aDragEvent,
   231                                               nsIDOMDataTransfer* aDataTransfer)
   232 {
   233   NS_ENSURE_TRUE(aDragEvent, NS_ERROR_NULL_POINTER);
   234   NS_ENSURE_TRUE(aDataTransfer, NS_ERROR_NULL_POINTER);
   235   NS_ENSURE_TRUE(mSuppressLevel == 0, NS_ERROR_FAILURE);
   237   mDataTransfer = aDataTransfer;
   238   mSelection = nullptr;
   239   mHasImage = true;
   240   mDragPopup = nullptr;
   241   mImage = aImage;
   242   mImageX = aImageX;
   243   mImageY = aImageY;
   245   aDragEvent->GetScreenX(&mScreenX);
   246   aDragEvent->GetScreenY(&mScreenY);
   247   aDragEvent->GetMozInputSource(&mInputSource);
   249   return InvokeDragSession(aDOMNode, aTransferableArray, aRegion, aActionType);
   250 }
   252 NS_IMETHODIMP
   253 nsBaseDragService::InvokeDragSessionWithSelection(nsISelection* aSelection,
   254                                                   nsISupportsArray* aTransferableArray,
   255                                                   uint32_t aActionType,
   256                                                   nsIDOMDragEvent* aDragEvent,
   257                                                   nsIDOMDataTransfer* aDataTransfer)
   258 {
   259   NS_ENSURE_TRUE(aSelection, NS_ERROR_NULL_POINTER);
   260   NS_ENSURE_TRUE(aDragEvent, NS_ERROR_NULL_POINTER);
   261   NS_ENSURE_TRUE(mSuppressLevel == 0, NS_ERROR_FAILURE);
   263   mDataTransfer = aDataTransfer;
   264   mSelection = aSelection;
   265   mHasImage = true;
   266   mDragPopup = nullptr;
   267   mImage = nullptr;
   268   mImageX = 0;
   269   mImageY = 0;
   271   aDragEvent->GetScreenX(&mScreenX);
   272   aDragEvent->GetScreenY(&mScreenY);
   273   aDragEvent->GetMozInputSource(&mInputSource);
   275   // just get the focused node from the selection
   276   // XXXndeakin this should actually be the deepest node that contains both
   277   // endpoints of the selection
   278   nsCOMPtr<nsIDOMNode> node;
   279   aSelection->GetFocusNode(getter_AddRefs(node));
   281   return InvokeDragSession(node, aTransferableArray, nullptr, aActionType);
   282 }
   284 //-------------------------------------------------------------------------
   285 NS_IMETHODIMP
   286 nsBaseDragService::GetCurrentSession(nsIDragSession ** aSession)
   287 {
   288   if (!aSession)
   289     return NS_ERROR_INVALID_ARG;
   291   // "this" also implements a drag session, so say we are one but only
   292   // if there is currently a drag going on.
   293   if (!mSuppressLevel && mDoingDrag) {
   294     *aSession = this;
   295     NS_ADDREF(*aSession);      // addRef because we're a "getter"
   296   }
   297   else
   298     *aSession = nullptr;
   300   return NS_OK;
   301 }
   303 //-------------------------------------------------------------------------
   304 NS_IMETHODIMP
   305 nsBaseDragService::StartDragSession()
   306 {
   307   if (mDoingDrag) {
   308     return NS_ERROR_FAILURE;
   309   }
   310   mDoingDrag = true;
   311   // By default dispatch drop also to content.
   312   mOnlyChromeDrop = false;
   314   return NS_OK;
   315 }
   317 void
   318 nsBaseDragService::OpenDragPopup()
   319 {
   320   if (mDragPopup) {
   321     nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
   322     if (pm) {
   323       pm->ShowPopupAtScreen(mDragPopup, mScreenX - mImageX, mScreenY - mImageY, false, nullptr);
   324     }
   325   }
   326 }
   328 //-------------------------------------------------------------------------
   329 NS_IMETHODIMP
   330 nsBaseDragService::EndDragSession(bool aDoneDrag)
   331 {
   332   if (!mDoingDrag) {
   333     return NS_ERROR_FAILURE;
   334   }
   336   if (aDoneDrag && !mSuppressLevel)
   337     FireDragEventAtSource(NS_DRAGDROP_END);
   339   if (mDragPopup) {
   340     nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
   341     if (pm) {
   342       pm->HidePopup(mDragPopup, false, true, false, false);
   343     }
   344   }
   346   mDoingDrag = false;
   348   // release the source we've been holding on to.
   349   mSourceDocument = nullptr;
   350   mSourceNode = nullptr;
   351   mSelection = nullptr;
   352   mDataTransfer = nullptr;
   353   mHasImage = false;
   354   mUserCancelled = false;
   355   mDragPopup = nullptr;
   356   mImage = nullptr;
   357   mImageX = 0;
   358   mImageY = 0;
   359   mScreenX = -1;
   360   mScreenY = -1;
   361   mInputSource = nsIDOMMouseEvent::MOZ_SOURCE_MOUSE;
   363   return NS_OK;
   364 }
   366 NS_IMETHODIMP
   367 nsBaseDragService::FireDragEventAtSource(uint32_t aMsg)
   368 {
   369   if (mSourceNode && !mSuppressLevel) {
   370     nsCOMPtr<nsIDocument> doc = do_QueryInterface(mSourceDocument);
   371     if (doc) {
   372       nsCOMPtr<nsIPresShell> presShell = doc->GetShell();
   373       if (presShell) {
   374         nsEventStatus status = nsEventStatus_eIgnore;
   375         WidgetDragEvent event(true, aMsg, nullptr);
   376         event.inputSource = mInputSource;
   377         if (aMsg == NS_DRAGDROP_END) {
   378           event.refPoint.x = mEndDragPoint.x;
   379           event.refPoint.y = mEndDragPoint.y;
   380           event.userCancelled = mUserCancelled;
   381         }
   383         nsCOMPtr<nsIContent> content = do_QueryInterface(mSourceNode);
   384         return presShell->HandleDOMEventWithTarget(content, &event, &status);
   385       }
   386     }
   387   }
   389   return NS_OK;
   390 }
   392 /* This is used by Windows and Mac to update the position of a popup being
   393  * used as a drag image during the drag. This isn't used on GTK as it manages
   394  * the drag popup itself.
   395  */
   396 NS_IMETHODIMP
   397 nsBaseDragService::DragMoved(int32_t aX, int32_t aY)
   398 {
   399   if (mDragPopup) {
   400     nsIFrame* frame = mDragPopup->GetPrimaryFrame();
   401     if (frame && frame->GetType() == nsGkAtoms::menuPopupFrame) {
   402       (static_cast<nsMenuPopupFrame *>(frame))->MoveTo(aX - mImageX, aY - mImageY, true);
   403     }
   404   }
   406   return NS_OK;
   407 }
   409 static nsIPresShell*
   410 GetPresShellForContent(nsIDOMNode* aDOMNode)
   411 {
   412   nsCOMPtr<nsIContent> content = do_QueryInterface(aDOMNode);
   413   if (!content)
   414     return nullptr;
   416   nsCOMPtr<nsIDocument> document = content->GetCurrentDoc();
   417   if (document) {
   418     document->FlushPendingNotifications(Flush_Display);
   420     return document->GetShell();
   421   }
   423   return nullptr;
   424 }
   426 nsresult
   427 nsBaseDragService::DrawDrag(nsIDOMNode* aDOMNode,
   428                             nsIScriptableRegion* aRegion,
   429                             int32_t aScreenX, int32_t aScreenY,
   430                             nsIntRect* aScreenDragRect,
   431                             RefPtr<SourceSurface>* aSurface,
   432                             nsPresContext** aPresContext)
   433 {
   434   *aSurface = nullptr;
   435   *aPresContext = nullptr;
   437   // use a default size, in case of an error.
   438   aScreenDragRect->x = aScreenX - mImageX;
   439   aScreenDragRect->y = aScreenY - mImageY;
   440   aScreenDragRect->width = 1;
   441   aScreenDragRect->height = 1;
   443   // if a drag image was specified, use that, otherwise, use the source node
   444   nsCOMPtr<nsIDOMNode> dragNode = mImage ? mImage.get() : aDOMNode;
   446   // get the presshell for the node being dragged. If the drag image is not in
   447   // a document or has no frame, get the presshell from the source drag node
   448   nsIPresShell* presShell = GetPresShellForContent(dragNode);
   449   if (!presShell && mImage)
   450     presShell = GetPresShellForContent(aDOMNode);
   451   if (!presShell)
   452     return NS_ERROR_FAILURE;
   454   *aPresContext = presShell->GetPresContext();
   456   // convert mouse position to dev pixels of the prescontext
   457   int32_t sx = aScreenX, sy = aScreenY;
   458   ConvertToUnscaledDevPixels(*aPresContext, &sx, &sy);
   460   aScreenDragRect->x = sx - mImageX;
   461   aScreenDragRect->y = sy - mImageY;
   463   // check if drag images are disabled
   464   bool enableDragImages = Preferences::GetBool(DRAGIMAGES_PREF, true);
   466   // didn't want an image, so just set the screen rectangle to the frame size
   467   if (!enableDragImages || !mHasImage) {
   468     // if a region was specified, set the screen rectangle to the area that
   469     // the region occupies
   470     if (aRegion) {
   471       // the region's coordinates are relative to the root frame
   472       nsIFrame* rootFrame = presShell->GetRootFrame();
   473       if (rootFrame && *aPresContext) {
   474         nsIntRect dragRect;
   475         aRegion->GetBoundingBox(&dragRect.x, &dragRect.y, &dragRect.width, &dragRect.height);
   476         dragRect = dragRect.ToAppUnits(nsPresContext::AppUnitsPerCSSPixel()).
   477                             ToOutsidePixels((*aPresContext)->AppUnitsPerDevPixel());
   479         nsIntRect screenRect = rootFrame->GetScreenRectExternal();
   480         aScreenDragRect->SetRect(screenRect.x + dragRect.x, screenRect.y + dragRect.y,
   481                                  dragRect.width, dragRect.height);
   482       }
   483     }
   484     else {
   485       // otherwise, there was no region so just set the rectangle to
   486       // the size of the primary frame of the content.
   487       nsCOMPtr<nsIContent> content = do_QueryInterface(dragNode);
   488       nsIFrame* frame = content->GetPrimaryFrame();
   489       if (frame) {
   490         nsIntRect screenRect = frame->GetScreenRectExternal();
   491         aScreenDragRect->SetRect(screenRect.x, screenRect.y,
   492                                  screenRect.width, screenRect.height);
   493       }
   494     }
   496     return NS_OK;
   497   }
   499   // draw the image for selections
   500   if (mSelection) {
   501     nsIntPoint pnt(aScreenDragRect->x, aScreenDragRect->y);
   502     *aSurface = presShell->RenderSelection(mSelection, pnt, aScreenDragRect);
   503     return NS_OK;
   504   }
   506   // if a custom image was specified, check if it is an image node and draw
   507   // using the source rather than the displayed image. But if mImage isn't
   508   // an image or canvas, fall through to RenderNode below.
   509   if (mImage) {
   510     nsCOMPtr<nsIContent> content = do_QueryInterface(dragNode);
   511     HTMLCanvasElement *canvas = HTMLCanvasElement::FromContentOrNull(content);
   512     if (canvas) {
   513       return DrawDragForImage(*aPresContext, nullptr, canvas, sx, sy,
   514                               aScreenDragRect, aSurface);
   515     }
   517     nsCOMPtr<nsIImageLoadingContent> imageLoader = do_QueryInterface(dragNode);
   518     // for image nodes, create the drag image from the actual image data
   519     if (imageLoader) {
   520       return DrawDragForImage(*aPresContext, imageLoader, nullptr, sx, sy,
   521                               aScreenDragRect, aSurface);
   522     }
   524     // If the image is a popup, use that as the image. This allows custom drag
   525     // images that can change during the drag, but means that any platform
   526     // default image handling won't occur.
   527     // XXXndeakin this should be chrome-only
   529     nsIFrame* frame = content->GetPrimaryFrame();
   530     if (frame && frame->GetType() == nsGkAtoms::menuPopupFrame) {
   531       mDragPopup = content;
   532     }
   533   }
   535   if (!mDragPopup) {
   536     // otherwise, just draw the node
   537     nsIntRegion clipRegion;
   538     if (aRegion) {
   539       aRegion->GetRegion(&clipRegion);
   540     }
   542     nsIntPoint pnt(aScreenDragRect->x, aScreenDragRect->y);
   543     *aSurface = presShell->RenderNode(dragNode, aRegion ? &clipRegion : nullptr,
   544                                       pnt, aScreenDragRect);
   545   }
   547   // if an image was specified, reposition the drag rectangle to
   548   // the supplied offset in mImageX and mImageY.
   549   if (mImage) {
   550     aScreenDragRect->x = sx - mImageX;
   551     aScreenDragRect->y = sy - mImageY;
   552   }
   554   return NS_OK;
   555 }
   557 nsresult
   558 nsBaseDragService::DrawDragForImage(nsPresContext* aPresContext,
   559                                     nsIImageLoadingContent* aImageLoader,
   560                                     HTMLCanvasElement* aCanvas,
   561                                     int32_t aScreenX, int32_t aScreenY,
   562                                     nsIntRect* aScreenDragRect,
   563                                     RefPtr<SourceSurface>* aSurface)
   564 {
   565   nsCOMPtr<imgIContainer> imgContainer;
   566   if (aImageLoader) {
   567     nsCOMPtr<imgIRequest> imgRequest;
   568     nsresult rv = aImageLoader->GetRequest(nsIImageLoadingContent::CURRENT_REQUEST,
   569                                           getter_AddRefs(imgRequest));
   570     NS_ENSURE_SUCCESS(rv, rv);
   571     if (!imgRequest)
   572       return NS_ERROR_NOT_AVAILABLE;
   574     rv = imgRequest->GetImage(getter_AddRefs(imgContainer));
   575     NS_ENSURE_SUCCESS(rv, rv);
   576     if (!imgContainer)
   577       return NS_ERROR_NOT_AVAILABLE;
   579     // use the size of the image as the size of the drag image
   580     imgContainer->GetWidth(&aScreenDragRect->width);
   581     imgContainer->GetHeight(&aScreenDragRect->height);
   582   }
   583   else {
   584     NS_ASSERTION(aCanvas, "both image and canvas are null");
   585     nsIntSize sz = aCanvas->GetSize();
   586     aScreenDragRect->width = sz.width;
   587     aScreenDragRect->height = sz.height;
   588   }
   590   nsIntSize srcSize = aScreenDragRect->Size();
   591   nsIntSize destSize = srcSize;
   593   if (destSize.width == 0 || destSize.height == 0)
   594     return NS_ERROR_FAILURE;
   596   // if the image is larger than half the screen size, scale it down. This
   597   // scaling algorithm is the same as is used in nsPresShell::PaintRangePaintInfo
   598   nsDeviceContext* deviceContext = aPresContext->DeviceContext();
   599   nsRect maxSize;
   600   deviceContext->GetClientRect(maxSize);
   601   nscoord maxWidth = aPresContext->AppUnitsToDevPixels(maxSize.width >> 1);
   602   nscoord maxHeight = aPresContext->AppUnitsToDevPixels(maxSize.height >> 1);
   603   if (destSize.width > maxWidth || destSize.height > maxHeight) {
   604     float scale = 1.0;
   605     if (destSize.width > maxWidth)
   606       scale = std::min(scale, float(maxWidth) / destSize.width);
   607     if (destSize.height > maxHeight)
   608       scale = std::min(scale, float(maxHeight) / destSize.height);
   610     destSize.width = NSToIntFloor(float(destSize.width) * scale);
   611     destSize.height = NSToIntFloor(float(destSize.height) * scale);
   613     aScreenDragRect->x = NSToIntFloor(aScreenX - float(mImageX) * scale);
   614     aScreenDragRect->y = NSToIntFloor(aScreenY - float(mImageY) * scale);
   615     aScreenDragRect->width = destSize.width;
   616     aScreenDragRect->height = destSize.height;
   617   }
   619   nsresult result = NS_OK;
   620   if (aImageLoader) {
   621     RefPtr<DrawTarget> dt =
   622       gfxPlatform::GetPlatform()->
   623         CreateOffscreenContentDrawTarget(destSize.ToIntSize(),
   624                                          SurfaceFormat::B8G8R8A8);
   625     if (!dt)
   626       return NS_ERROR_FAILURE;
   628     nsRefPtr<gfxContext> ctx = new gfxContext(dt);
   629     if (!ctx)
   630       return NS_ERROR_FAILURE;
   632     gfxRect outRect(0, 0, destSize.width, destSize.height);
   633     gfxMatrix scale =
   634       gfxMatrix().Scale(srcSize.width/outRect.Width(), srcSize.height/outRect.Height());
   635     nsIntRect imgSize(0, 0, srcSize.width, srcSize.height);
   636     imgContainer->Draw(ctx, GraphicsFilter::FILTER_GOOD, scale, outRect, imgSize,
   637                        destSize, nullptr, imgIContainer::FRAME_CURRENT,
   638                        imgIContainer::FLAG_SYNC_DECODE);
   639     *aSurface = dt->Snapshot();
   640   } else {
   641     *aSurface = aCanvas->GetSurfaceSnapshot();
   642   }
   644   return result;
   645 }
   647 void
   648 nsBaseDragService::ConvertToUnscaledDevPixels(nsPresContext* aPresContext,
   649                                               int32_t* aScreenX, int32_t* aScreenY)
   650 {
   651   int32_t adj = aPresContext->DeviceContext()->UnscaledAppUnitsPerDevPixel();
   652   *aScreenX = nsPresContext::CSSPixelsToAppUnits(*aScreenX) / adj;
   653   *aScreenY = nsPresContext::CSSPixelsToAppUnits(*aScreenY) / adj;
   654 }
   656 NS_IMETHODIMP
   657 nsBaseDragService::Suppress()
   658 {
   659   EndDragSession(false);
   660   ++mSuppressLevel;
   661   return NS_OK;
   662 }
   664 NS_IMETHODIMP
   665 nsBaseDragService::Unsuppress()
   666 {
   667   --mSuppressLevel;
   668   return NS_OK;
   669 }

mercurial