CLOSED TREE: TraceMonkey merge head. (a=blockers)
[mozilla-central.git] / widget / src / xpwidgets / nsBaseDragService.cpp
blob3d0fcaf60f6c2c206afbfb2c0bd9abd307dc5312
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
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/
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.
15 * The Original Code is mozilla.org code.
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.
22 * Contributor(s):
23 * Mats Palmgren <mats.palmgren@bredband.net>
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.
37 * ***** END LICENSE BLOCK ***** */
39 #include "nsBaseDragService.h"
40 #include "nsITransferable.h"
42 #include "nsIServiceManager.h"
43 #include "nsITransferable.h"
44 #include "nsISupportsArray.h"
45 #include "nsSize.h"
46 #include "nsIRegion.h"
47 #include "nsXPCOM.h"
48 #include "nsISupportsPrimitives.h"
49 #include "nsCOMPtr.h"
50 #include "nsIInterfaceRequestorUtils.h"
51 #include "nsIFrame.h"
52 #include "nsIDocument.h"
53 #include "nsIContent.h"
54 #include "nsIPresShell.h"
55 #include "nsIViewManager.h"
56 #include "nsIDOMNode.h"
57 #include "nsIDOMDragEvent.h"
58 #include "nsISelection.h"
59 #include "nsISelectionPrivate.h"
60 #include "nsPresContext.h"
61 #include "nsIDOMDataTransfer.h"
62 #include "nsIEventStateManager.h"
63 #include "nsICanvasElementExternal.h"
64 #include "nsIImageLoadingContent.h"
65 #include "imgIContainer.h"
66 #include "imgIRequest.h"
67 #include "nsIViewObserver.h"
68 #include "nsRegion.h"
69 #include "nsGUIEvent.h"
70 #include "nsIPrefService.h"
72 #include "gfxContext.h"
73 #include "gfxPlatform.h"
75 #define DRAGIMAGES_PREF "nglayout.enable_drag_images"
77 nsBaseDragService::nsBaseDragService()
78 : mCanDrop(PR_FALSE), mOnlyChromeDrop(PR_FALSE), mDoingDrag(PR_FALSE),
79 mHasImage(PR_FALSE), mUserCancelled(PR_FALSE),
80 mDragAction(DRAGDROP_ACTION_NONE), mTargetSize(0,0),
81 mImageX(0), mImageY(0), mScreenX(-1), mScreenY(-1), mSuppressLevel(0),
82 mInputSource(nsIDOMNSMouseEvent::MOZ_SOURCE_MOUSE)
86 nsBaseDragService::~nsBaseDragService()
90 NS_IMPL_ISUPPORTS2(nsBaseDragService, nsIDragService, nsIDragSession)
92 //---------------------------------------------------------
93 NS_IMETHODIMP
94 nsBaseDragService::SetCanDrop(PRBool aCanDrop)
96 mCanDrop = aCanDrop;
97 return NS_OK;
100 //---------------------------------------------------------
101 NS_IMETHODIMP
102 nsBaseDragService::GetCanDrop(PRBool * aCanDrop)
104 *aCanDrop = mCanDrop;
105 return NS_OK;
107 //---------------------------------------------------------
108 NS_IMETHODIMP
109 nsBaseDragService::SetOnlyChromeDrop(PRBool aOnlyChrome)
111 mOnlyChromeDrop = aOnlyChrome;
112 return NS_OK;
115 //---------------------------------------------------------
116 NS_IMETHODIMP
117 nsBaseDragService::GetOnlyChromeDrop(PRBool* aOnlyChrome)
119 *aOnlyChrome = mOnlyChromeDrop;
120 return NS_OK;
123 //---------------------------------------------------------
124 NS_IMETHODIMP
125 nsBaseDragService::SetDragAction(PRUint32 anAction)
127 mDragAction = anAction;
128 return NS_OK;
131 //---------------------------------------------------------
132 NS_IMETHODIMP
133 nsBaseDragService::GetDragAction(PRUint32 * anAction)
135 *anAction = mDragAction;
136 return NS_OK;
139 //---------------------------------------------------------
140 NS_IMETHODIMP
141 nsBaseDragService::SetTargetSize(nsSize aDragTargetSize)
143 mTargetSize = aDragTargetSize;
144 return NS_OK;
147 //---------------------------------------------------------
148 NS_IMETHODIMP
149 nsBaseDragService::GetTargetSize(nsSize * aDragTargetSize)
151 *aDragTargetSize = mTargetSize;
152 return NS_OK;
155 //-------------------------------------------------------------------------
157 NS_IMETHODIMP
158 nsBaseDragService::GetNumDropItems(PRUint32 * aNumItems)
160 *aNumItems = 0;
161 return NS_ERROR_FAILURE;
166 // GetSourceDocument
168 // Returns the DOM document where the drag was initiated. This will be
169 // nsnull if the drag began outside of our application.
171 NS_IMETHODIMP
172 nsBaseDragService::GetSourceDocument(nsIDOMDocument** aSourceDocument)
174 *aSourceDocument = mSourceDocument.get();
175 NS_IF_ADDREF(*aSourceDocument);
177 return NS_OK;
181 // GetSourceNode
183 // Returns the DOM node where the drag was initiated. This will be
184 // nsnull if the drag began outside of our application.
186 NS_IMETHODIMP
187 nsBaseDragService::GetSourceNode(nsIDOMNode** aSourceNode)
189 *aSourceNode = mSourceNode.get();
190 NS_IF_ADDREF(*aSourceNode);
192 return NS_OK;
196 //-------------------------------------------------------------------------
198 NS_IMETHODIMP
199 nsBaseDragService::GetData(nsITransferable * aTransferable,
200 PRUint32 aItemIndex)
202 return NS_ERROR_FAILURE;
205 //-------------------------------------------------------------------------
206 NS_IMETHODIMP
207 nsBaseDragService::IsDataFlavorSupported(const char *aDataFlavor,
208 PRBool *_retval)
210 return NS_ERROR_FAILURE;
213 NS_IMETHODIMP
214 nsBaseDragService::GetDataTransfer(nsIDOMDataTransfer** aDataTransfer)
216 *aDataTransfer = mDataTransfer;
217 NS_IF_ADDREF(*aDataTransfer);
218 return NS_OK;
221 NS_IMETHODIMP
222 nsBaseDragService::SetDataTransfer(nsIDOMDataTransfer* aDataTransfer)
224 mDataTransfer = aDataTransfer;
225 return NS_OK;
228 //-------------------------------------------------------------------------
229 NS_IMETHODIMP
230 nsBaseDragService::InvokeDragSession(nsIDOMNode *aDOMNode,
231 nsISupportsArray* aTransferableArray,
232 nsIScriptableRegion* aDragRgn,
233 PRUint32 aActionType)
235 NS_ENSURE_TRUE(aDOMNode, NS_ERROR_INVALID_ARG);
236 NS_ENSURE_TRUE(mSuppressLevel == 0, NS_ERROR_FAILURE);
238 // stash the document of the dom node
239 aDOMNode->GetOwnerDocument(getter_AddRefs(mSourceDocument));
240 mSourceNode = aDOMNode;
241 mEndDragPoint = nsIntPoint(0, 0);
243 // When the mouse goes down, the selection code starts a mouse
244 // capture. However, this gets in the way of determining drag
245 // feedback for things like trees because the event coordinates
246 // are in the wrong coord system, so turn off mouse capture.
247 nsCOMPtr<nsIDocument> doc = do_QueryInterface(mSourceDocument);
248 if (doc) {
249 nsCOMPtr<nsIViewObserver> viewObserver = do_QueryInterface(doc->GetShell());
250 if (viewObserver) {
251 viewObserver->ClearMouseCapture(nsnull);
255 return NS_OK;
258 NS_IMETHODIMP
259 nsBaseDragService::InvokeDragSessionWithImage(nsIDOMNode* aDOMNode,
260 nsISupportsArray* aTransferableArray,
261 nsIScriptableRegion* aRegion,
262 PRUint32 aActionType,
263 nsIDOMNode* aImage,
264 PRInt32 aImageX, PRInt32 aImageY,
265 nsIDOMDragEvent* aDragEvent,
266 nsIDOMDataTransfer* aDataTransfer)
268 NS_ENSURE_TRUE(aDragEvent, NS_ERROR_NULL_POINTER);
269 NS_ENSURE_TRUE(aDataTransfer, NS_ERROR_NULL_POINTER);
270 NS_ENSURE_TRUE(mSuppressLevel == 0, NS_ERROR_FAILURE);
272 mDataTransfer = aDataTransfer;
273 mSelection = nsnull;
274 mHasImage = PR_TRUE;
275 mImage = aImage;
276 mImageX = aImageX;
277 mImageY = aImageY;
279 aDragEvent->GetScreenX(&mScreenX);
280 aDragEvent->GetScreenY(&mScreenY);
282 nsCOMPtr<nsIDOMNSMouseEvent> mouseEvent = do_QueryInterface(aDragEvent);
283 mouseEvent->GetMozInputSource(&mInputSource);
285 return InvokeDragSession(aDOMNode, aTransferableArray, aRegion, aActionType);
288 NS_IMETHODIMP
289 nsBaseDragService::InvokeDragSessionWithSelection(nsISelection* aSelection,
290 nsISupportsArray* aTransferableArray,
291 PRUint32 aActionType,
292 nsIDOMDragEvent* aDragEvent,
293 nsIDOMDataTransfer* aDataTransfer)
295 NS_ENSURE_TRUE(aSelection, NS_ERROR_NULL_POINTER);
296 NS_ENSURE_TRUE(aDragEvent, NS_ERROR_NULL_POINTER);
297 NS_ENSURE_TRUE(mSuppressLevel == 0, NS_ERROR_FAILURE);
299 mDataTransfer = aDataTransfer;
300 mSelection = aSelection;
301 mHasImage = PR_TRUE;
302 mImage = nsnull;
303 mImageX = 0;
304 mImageY = 0;
306 aDragEvent->GetScreenX(&mScreenX);
307 aDragEvent->GetScreenY(&mScreenY);
309 nsCOMPtr<nsIDOMNSMouseEvent> mouseEvent = do_QueryInterface(aDragEvent);
310 mouseEvent->GetMozInputSource(&mInputSource);
312 // just get the focused node from the selection
313 // XXXndeakin this should actually be the deepest node that contains both
314 // endpoints of the selection
315 nsCOMPtr<nsIDOMNode> node;
316 aSelection->GetFocusNode(getter_AddRefs(node));
318 return InvokeDragSession(node, aTransferableArray, nsnull, aActionType);
321 //-------------------------------------------------------------------------
322 NS_IMETHODIMP
323 nsBaseDragService::GetCurrentSession(nsIDragSession ** aSession)
325 if (!aSession)
326 return NS_ERROR_INVALID_ARG;
328 // "this" also implements a drag session, so say we are one but only
329 // if there is currently a drag going on.
330 if (!mSuppressLevel && mDoingDrag) {
331 *aSession = this;
332 NS_ADDREF(*aSession); // addRef because we're a "getter"
334 else
335 *aSession = nsnull;
337 return NS_OK;
340 //-------------------------------------------------------------------------
341 NS_IMETHODIMP
342 nsBaseDragService::StartDragSession()
344 if (mDoingDrag) {
345 return NS_ERROR_FAILURE;
347 mDoingDrag = PR_TRUE;
348 // By default dispatch drop also to content.
349 mOnlyChromeDrop = PR_FALSE;
350 return NS_OK;
353 //-------------------------------------------------------------------------
354 NS_IMETHODIMP
355 nsBaseDragService::EndDragSession(PRBool aDoneDrag)
357 if (!mDoingDrag) {
358 return NS_ERROR_FAILURE;
361 if (aDoneDrag && !mSuppressLevel)
362 FireDragEventAtSource(NS_DRAGDROP_END);
364 mDoingDrag = PR_FALSE;
366 // release the source we've been holding on to.
367 mSourceDocument = nsnull;
368 mSourceNode = nsnull;
369 mSelection = nsnull;
370 mDataTransfer = nsnull;
371 mHasImage = PR_FALSE;
372 mUserCancelled = PR_FALSE;
373 mImage = nsnull;
374 mImageX = 0;
375 mImageY = 0;
376 mScreenX = -1;
377 mScreenY = -1;
378 mInputSource = nsIDOMNSMouseEvent::MOZ_SOURCE_MOUSE;
380 return NS_OK;
383 NS_IMETHODIMP
384 nsBaseDragService::FireDragEventAtSource(PRUint32 aMsg)
386 if (mSourceNode && !mSuppressLevel) {
387 nsCOMPtr<nsIDocument> doc = do_QueryInterface(mSourceDocument);
388 if (doc) {
389 nsCOMPtr<nsIPresShell> presShell = doc->GetShell();
390 if (presShell) {
391 nsEventStatus status = nsEventStatus_eIgnore;
392 nsDragEvent event(PR_TRUE, aMsg, nsnull);
393 event.inputSource = mInputSource;
394 if (aMsg == NS_DRAGDROP_END) {
395 event.refPoint.x = mEndDragPoint.x;
396 event.refPoint.y = mEndDragPoint.y;
397 event.userCancelled = mUserCancelled;
400 nsCOMPtr<nsIContent> content = do_QueryInterface(mSourceNode);
401 return presShell->HandleDOMEventWithTarget(content, &event, &status);
406 return NS_OK;
409 static nsIPresShell*
410 GetPresShellForContent(nsIDOMNode* aDOMNode)
412 nsCOMPtr<nsIContent> content = do_QueryInterface(aDOMNode);
413 if (!content)
414 return nsnull;
416 nsCOMPtr<nsIDocument> document = content->GetCurrentDoc();
417 if (document) {
418 document->FlushPendingNotifications(Flush_Display);
420 return document->GetShell();
423 return nsnull;
426 nsresult
427 nsBaseDragService::DrawDrag(nsIDOMNode* aDOMNode,
428 nsIScriptableRegion* aRegion,
429 PRInt32 aScreenX, PRInt32 aScreenY,
430 nsIntRect* aScreenDragRect,
431 gfxASurface** aSurface,
432 nsPresContext** aPresContext)
434 *aSurface = nsnull;
435 *aPresContext = nsnull;
437 // use a default size, in case of an error.
438 aScreenDragRect->x = aScreenX - mImageX;
439 aScreenDragRect->y = aScreenY - mImageY;
440 aScreenDragRect->width = 20;
441 aScreenDragRect->height = 20;
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 // check if drag images are disabled
457 PRBool enableDragImages = PR_TRUE;
458 nsCOMPtr<nsIPrefBranch> prefs(do_GetService(NS_PREFSERVICE_CONTRACTID));
459 if (prefs)
460 prefs->GetBoolPref(DRAGIMAGES_PREF, &enableDragImages);
462 // didn't want an image, so just set the screen rectangle to the frame size
463 if (!enableDragImages || !mHasImage) {
464 // if a region was specified, set the screen rectangle to the area that
465 // the region occupies
466 if (aRegion) {
467 // the region's coordinates are relative to the root frame
468 nsIFrame* rootFrame = presShell->GetRootFrame();
469 if (rootFrame && *aPresContext) {
470 nsIntRect dragRect;
471 aRegion->GetBoundingBox(&dragRect.x, &dragRect.y, &dragRect.width, &dragRect.height);
472 dragRect = dragRect.ToAppUnits(nsPresContext::AppUnitsPerCSSPixel()).
473 ToOutsidePixels((*aPresContext)->AppUnitsPerDevPixel());
475 nsIntRect screenRect = rootFrame->GetScreenRectExternal();
476 aScreenDragRect->SetRect(screenRect.x + dragRect.x, screenRect.y + dragRect.y,
477 dragRect.width, dragRect.height);
480 else {
481 // otherwise, there was no region so just set the rectangle to
482 // the size of the primary frame of the content.
483 nsCOMPtr<nsIContent> content = do_QueryInterface(dragNode);
484 nsIFrame* frame = content->GetPrimaryFrame();
485 if (frame) {
486 nsIntRect screenRect = frame->GetScreenRectExternal();
487 aScreenDragRect->SetRect(screenRect.x, screenRect.y,
488 screenRect.width, screenRect.height);
492 return NS_OK;
495 // draw the image for selections
496 if (mSelection) {
497 nsIntPoint pnt(aScreenDragRect->x, aScreenDragRect->y);
498 nsRefPtr<gfxASurface> surface = presShell->RenderSelection(mSelection, pnt, aScreenDragRect);
499 *aSurface = surface;
500 NS_IF_ADDREF(*aSurface);
501 return NS_OK;
504 // if an custom image was specified, check if it is an image node and draw
505 // using the source rather than the displayed image. But if mImage isn't
506 // an image, fall through to RenderNode below.
507 if (mImage) {
508 nsCOMPtr<nsICanvasElementExternal> canvas = do_QueryInterface(dragNode);
509 if (canvas) {
510 return DrawDragForImage(*aPresContext, nsnull, canvas, aScreenX,
511 aScreenY, aScreenDragRect, aSurface);
514 nsCOMPtr<nsIImageLoadingContent> imageLoader = do_QueryInterface(dragNode);
515 // for image nodes, create the drag image from the actual image data
516 if (imageLoader) {
517 return DrawDragForImage(*aPresContext, imageLoader, nsnull, aScreenX,
518 aScreenY, aScreenDragRect, aSurface);
522 // otherwise, just draw the node
523 nsIntRegion clipRegion;
524 if (aRegion) {
525 nsCOMPtr<nsIRegion> clipIRegion;
526 aRegion->GetRegion(getter_AddRefs(clipIRegion));
527 if (clipIRegion) {
528 clipRegion = clipIRegion->GetUnderlyingRegion();
532 nsIntPoint pnt(aScreenDragRect->x, aScreenDragRect->y);
533 nsRefPtr<gfxASurface> surface =
534 presShell->RenderNode(dragNode, aRegion ? &clipRegion : nsnull,
535 pnt, aScreenDragRect);
537 // if an image was specified, reposition the drag rectangle to
538 // the supplied offset in mImageX and mImageY.
539 if (mImage) {
540 aScreenDragRect->x = aScreenX - mImageX;
541 aScreenDragRect->y = aScreenY - mImageY;
544 *aSurface = surface;
545 NS_IF_ADDREF(*aSurface);
547 return NS_OK;
550 nsresult
551 nsBaseDragService::DrawDragForImage(nsPresContext* aPresContext,
552 nsIImageLoadingContent* aImageLoader,
553 nsICanvasElementExternal* aCanvas,
554 PRInt32 aScreenX, PRInt32 aScreenY,
555 nsIntRect* aScreenDragRect,
556 gfxASurface** aSurface)
558 nsCOMPtr<imgIContainer> imgContainer;
559 if (aImageLoader) {
560 nsCOMPtr<imgIRequest> imgRequest;
561 nsresult rv = aImageLoader->GetRequest(nsIImageLoadingContent::CURRENT_REQUEST,
562 getter_AddRefs(imgRequest));
563 NS_ENSURE_SUCCESS(rv, rv);
564 if (!imgRequest)
565 return NS_ERROR_NOT_AVAILABLE;
567 rv = imgRequest->GetImage(getter_AddRefs(imgContainer));
568 NS_ENSURE_SUCCESS(rv, rv);
569 if (!imgContainer)
570 return NS_ERROR_NOT_AVAILABLE;
572 // use the size of the image as the size of the drag image
573 imgContainer->GetWidth(&aScreenDragRect->width);
574 imgContainer->GetHeight(&aScreenDragRect->height);
576 else {
577 NS_ASSERTION(aCanvas, "both image and canvas are null");
578 nsIntSize sz = aCanvas->GetSizeExternal();
579 aScreenDragRect->width = sz.width;
580 aScreenDragRect->height = sz.height;
583 nsIntSize srcSize = aScreenDragRect->Size();
584 nsIntSize destSize = srcSize;
586 if (destSize.width == 0 || destSize.height == 0)
587 return NS_ERROR_FAILURE;
589 // if the image is larger than half the screen size, scale it down. This
590 // scaling algorithm is the same as is used in nsPresShell::PaintRangePaintInfo
591 nsIDeviceContext* deviceContext = aPresContext->DeviceContext();
592 nsRect maxSize;
593 deviceContext->GetClientRect(maxSize);
594 nscoord maxWidth = aPresContext->AppUnitsToDevPixels(maxSize.width >> 1);
595 nscoord maxHeight = aPresContext->AppUnitsToDevPixels(maxSize.height >> 1);
596 if (destSize.width > maxWidth || destSize.height > maxHeight) {
597 float scale = 1.0;
598 if (destSize.width > maxWidth)
599 scale = PR_MIN(scale, float(maxWidth) / destSize.width);
600 if (destSize.height > maxHeight)
601 scale = PR_MIN(scale, float(maxHeight) / destSize.height);
603 destSize.width = NSToIntFloor(float(destSize.width) * scale);
604 destSize.height = NSToIntFloor(float(destSize.height) * scale);
606 aScreenDragRect->x = NSToIntFloor(aScreenX - float(mImageX) * scale);
607 aScreenDragRect->y = NSToIntFloor(aScreenY - float(mImageY) * scale);
608 aScreenDragRect->width = destSize.width;
609 aScreenDragRect->height = destSize.height;
612 nsRefPtr<gfxASurface> surface =
613 gfxPlatform::GetPlatform()->CreateOffscreenSurface(gfxIntSize(destSize.width, destSize.height),
614 gfxASurface::CONTENT_COLOR_ALPHA);
615 if (!surface)
616 return NS_ERROR_FAILURE;
618 nsRefPtr<gfxContext> ctx = new gfxContext(surface);
619 if (!ctx)
620 return NS_ERROR_FAILURE;
622 *aSurface = surface;
623 NS_ADDREF(*aSurface);
625 if (aImageLoader) {
626 gfxRect outRect(0, 0, destSize.width, destSize.height);
627 gfxMatrix scale =
628 gfxMatrix().Scale(srcSize.width/outRect.Width(), srcSize.height/outRect.Height());
629 nsIntRect imgSize(0, 0, srcSize.width, srcSize.height);
630 imgContainer->Draw(ctx, gfxPattern::FILTER_GOOD, scale, outRect, imgSize,
631 destSize, imgIContainer::FLAG_SYNC_DECODE);
632 return NS_OK;
633 } else {
634 return aCanvas->RenderContextsExternal(ctx, gfxPattern::FILTER_GOOD);
638 void
639 nsBaseDragService::ConvertToUnscaledDevPixels(nsPresContext* aPresContext,
640 PRInt32* aScreenX, PRInt32* aScreenY)
642 PRInt32 adj = aPresContext->DeviceContext()->UnscaledAppUnitsPerDevPixel();
643 *aScreenX = nsPresContext::CSSPixelsToAppUnits(*aScreenX) / adj;
644 *aScreenY = nsPresContext::CSSPixelsToAppUnits(*aScreenY) / adj;
647 NS_IMETHODIMP
648 nsBaseDragService::Suppress()
650 EndDragSession(PR_FALSE);
651 ++mSuppressLevel;
652 return NS_OK;
655 NS_IMETHODIMP
656 nsBaseDragService::Unsuppress()
658 --mSuppressLevel;
659 return NS_OK;