LCOV - app.info - widget/xpwidgets/nsBaseDragService.cpp

LCOV - code coverage report
| Current view: | directory - widget/xpwidgets - nsBaseDragService.cpp (source / functions) |  | Found | Hit | Coverage |
| Test: | app.info | Lines: | 296 | 0 | 0.0 %
| Date: | 2012-04-21 | Functions: | 36 | 0 | 0.0 %

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

Generated by: LCOV version 1.7