 |
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 * Pierre Phaneuf <pp@ludusdesign.com>
24 * Paul Ashford
25 * Fredrik Holmqvist <thesuckiestemail@yahoo.se>
26 *
27 * Alternatively, the contents of this file may be used under the terms of
28 * either the GNU General Public License Version 2 or later (the "GPL"), or
29 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
30 * in which case the provisions of the GPL or the LGPL are applicable instead
31 * of those above. If you wish to allow use of your version of this file only
32 * under the terms of either the GPL or the LGPL, and not to allow others to
33 * use your version of this file under the terms of the MPL, indicate your
34 * decision by deleting the provisions above and replace them with the notice
35 * and other provisions required by the GPL or the LGPL. If you do not delete
36 * the provisions above, a recipient may use your version of this file under
37 * the terms of any one of the MPL, the GPL or the LGPL.
38 *
39 * ***** END LICENSE BLOCK ***** */
40
41 #include <stdio.h>
42 #include "nsDragService.h"
43 #include "nsIDocument.h"
44 #include "nsIRegion.h"
45 #include "nsITransferable.h"
46 #include "nsIServiceManager.h"
47 #include "nsISupportsPrimitives.h"
48 #include "nsVoidArray.h"
49 #include "nsXPIDLString.h"
50 #include "nsPrimitiveHelpers.h"
51 #include "nsUnitConversion.h"
52 #include "nsWidgetsCID.h"
53 #include "nsCRT.h"
54
55 // if we want to do Image-dragging, also need to change Makefile.in
56 // to add
57 // -I$(topsrcdir)/gfx/src/beos \
58 // in INCLUDES
59 // and bug 294234 to be done.
60 // #include "nsIImage.h"
61 // #include "nsIImageBeOS.h"
62 //#include <Bitmap.h>
63
64 #include <AppDefs.h>
65 #include <TypeConstants.h>
66 #include <DataIO.h>
67 #include <Mime.h>
68 #include <Rect.h>
69 #include <Region.h>
70 #include <String.h>
71 #include <View.h>
72
73 #include "prlog.h"
74 #include "nsIPresShell.h"
75 #include "nsPresContext.h"
76 #include "nsIFrame.h"
77 #include "nsIView.h"
78 #include "nsIWidget.h"
79
80 static NS_DEFINE_CID(kCDragServiceCID, NS_DRAGSERVICE_CID);
81
82 static PRLogModuleInfo *sDragLm = NULL;
83
84 static nsIFrame*
85 GetPrimaryFrameFor(nsIDOMNode *aDOMNode)
86 {
87 nsCOMPtr<nsIContent> aContent = do_QueryInterface(aDOMNode);
88 if (nsnull == aContent)
89 return nsnull;
90
91 nsIDocument* doc = aContent->GetCurrentDoc();
92 if (nsnull == doc)
93 return nsnull;
94 nsIPresShell* presShell = doc->GetShellAt(0);
95 if ( nsnull == presShell)
96 return nsnull;
97 nsIFrame *frame;
98 presShell->GetPrimaryFrameFor(aContent, &frame);
99 return frame;
100 }
101
102 static bool
103 IsInternalDrag(BMessage * aMsg)
104 {
105 BString orig;
106 // We started this drag if originater is 'BeZilla'
107 return (nsnull != aMsg && B_OK == aMsg->FindString("be:originator", &orig) &&
108 0 == orig.Compare("BeZilla"));
109 }
110
111 NS_IMPL_THREADSAFE_ISUPPORTS4(nsDragService, nsIDragService,
112 nsIDragService_1_8_BRANCH, nsIDragSession,
113 nsIDragSessionBeOS)
114 //NS_IMPL_THREADSAFE_ISUPPORTS1(nsBaseDragService, nsIDragSessionBeOS)
115
116 //-------------------------------------------------------------------------
117 //
118 // DragService constructor
119 // Enable logging: 'export NSPR_LOG_MODULES=nsDragService:5'
120 //-------------------------------------------------------------------------
121 nsDragService::nsDragService()
122 {
123 // set up our logging module
124 if (!sDragLm)
125 sDragLm = PR_NewLogModule("nsDragService");
126 PR_LOG(sDragLm, PR_LOG_DEBUG, ("\n\nnsDragService::nsDragService"));
127
128 mDragMessage = NULL;
129 mCanDrop = PR_FALSE;
130 }
131
132 //-------------------------------------------------------------------------
133 //
134 // DragService destructor
135 //
136 //-------------------------------------------------------------------------
137 nsDragService::~nsDragService()
138 {
139 PR_LOG(sDragLm, PR_LOG_DEBUG, ("nsDragService::~nsDragService"));
140 ResetDragInfo();
141 }
142
143 //-------------------------------------------------------------------------
144 //
145 // nsIDragService : InvokeDragSession
146 //
147 // Called when a drag is being initiated from within mozilla
148 // The code here gets the BView, the dragRect, builds the DragMessage and
149 // starts the drag.
150 //
151 //-------------------------------------------------------------------------
152 NS_IMETHODIMP
153 nsDragService::InvokeDragSession (nsIDOMNode *aDOMNode,
154 nsISupportsArray * aArrayTransferables,
155 nsIScriptableRegion * aRegion,
156 PRUint32 aActionType)
157 {
158 PR_LOG(sDragLm, PR_LOG_DEBUG, ("nsDragService::InvokeDragSession"));
159 nsresult rv = nsBaseDragService::InvokeDragSession(aDOMNode,
160 aArrayTransferables,
161 aRegion, aActionType);
162 NS_ENSURE_SUCCESS(rv, rv);
163
164 ResetDragInfo();
165 // make sure that we have an array of transferables to use
166 if (nsnull == aArrayTransferables)
167 return NS_ERROR_INVALID_ARG;
168
169 // set our reference to the transferables. this will also addref
170 // the transferables since we're going to hang onto this beyond the
171 // length of this call
172 mSourceDataItems = aArrayTransferables;
173
174 // Get a box or a bitmap to drag
175 bool haveRect = false;
176 BRect dragRect;
177
178 if (nsnull != aRegion)
179 {
180 PRInt32 aX, aY, aWidth, aHeight;
181 // TODO. Region may represent multiple rects - when dragging multiple items.
182 aRegion->GetBoundingBox(&aX, &aY, &aWidth, &aHeight);
183 dragRect.Set( aX, aY, aX + aWidth, aY + aHeight);
184 haveRect = true;
185 // does this need to be offset?
186 }
187
188 // Get the frame for this content node (note: frames are not refcounted)
189 nsIFrame *aFrame = GetPrimaryFrameFor(aDOMNode);
190 if (nsnull == aFrame)
191 return PR_FALSE;
192
193 // Now that we have the frame, we have to convert its coordinates into global screen
194 // coordinates.
195 nsRect aRect = aFrame->GetRect();
196
197 // Find offset from our view
198 nsIView *containingView = nsnull;
199 nsPoint viewOffset(0,0);
200 aFrame->GetOffsetFromView(viewOffset, &containingView);
201 NS_ASSERTION(containingView, "No containing view!");
202 if (nsnull == containingView)
203 return PR_FALSE;
204
205 // get the widget associated with the containing view.
206 nsPoint aWidgetOffset;
207 nsCOMPtr<nsIWidget> aWidget = containingView->GetNearestWidget(&aWidgetOffset);
208 if (nsnull == aWidget)
209 return PR_FALSE;
210
211 BView *view = (BView *) aWidget->GetNativeData(NS_NATIVE_WIDGET);
212 // Don't have the rect yet, try to get it from the dom node
213 if (nsnull==haveRect)
214 {
215 float t2p = aFrame->GetPresContext()->TwipsToPixels();
216 // GetOffsetFromWidget() actually returns the _parent's_ offset from its widget, so we
217 // still have to add in the offset to |containingView|'s parent ourselves.
218 nsPoint aViewPos = containingView->GetPosition();
219
220 // Shift our offset rect by offset into our view, the view's offset to its parent, and
221 // the parent's offset to the closest widget. Then convert that to global coordinates.
222 // Recall that WidgetToScreen() will give us the global coordinates of the rectangle we
223 // give it, but it expects everything to be in pixels.
224 nsRect screenOffset;
225 screenOffset.MoveBy ( NSTwipsToIntPixels(aWidgetOffset.x + aViewPos.x + viewOffset.x, t2p),
226 NSTwipsToIntPixels(aWidgetOffset.y + aViewPos.y + viewOffset.y, t2p));
227 aWidget->WidgetToScreen ( screenOffset, screenOffset );
228
229 dragRect.Set(screenOffset.x, screenOffset.y,
230 screenOffset.x + NSTwipsToIntPixels(aRect.width, t2p),
231 screenOffset.y + NSTwipsToIntPixels(aRect.height, t2p));
232 haveRect = true;
233 }
234
235 mDragAction = aActionType;
236 mDragMessage = CreateDragMessage();
237
238 if (!view || !mDragMessage)
239 return PR_FALSE;
240
241 // Set the original click location, how to get this or is it needed ?
242 // sourceMessage->AddPoint("click_location", mPoint);
243
244 if (!view->LockLooper())
245 return PR_FALSE;
246
247 // Well, let's just use the view frame, maybe?
248 if (!haveRect)
249 {
250 dragRect = view->Frame();
251 // do we need to offset?
252 }
253
254 PR_LOG(sDragLm, PR_LOG_DEBUG, ("invoking mDragView->DragMessage"));
255 bool noBitmap = true;
256
257 //This is the code for image-dragging, currently disabled. See comments in beginning of file.
258 # ifdef 0
259 do
260 {
261 PRUint32 dataSize;
262 PRUint32 noItems;
263 mSourceDataItems->Count(&noItems);
264 if (noItems!=1)
265 {
266 PR_LOG(sDragLm, PR_LOG_DEBUG, ("Transferables are not ==1, no drag bitmap!"));
267 break;
268 }
269
270 nsCOMPtr<nsISupports> genericItem;
271 aArrayTransferables->GetElementAt(0, getter_AddRefs(genericItem));
272 nsCOMPtr<nsITransferable> aTransferable (do_QueryInterface(genericItem));
273
274 nsCOMPtr<nsISupports> genericDataWrapper;
275 nsresult rv = aTransferable->GetTransferData(kNativeImageMime, getter_AddRefs(genericDataWrapper), &dataSize);
276 if (NS_FAILED(rv))
277 {
278 PR_LOG(sDragLm, PR_LOG_DEBUG, ("Could not get nativeimage, no drag bitmap!"));
279 break;
280 }
281
282 nsCOMPtr<nsISupportsInterfacePointer> ptrPrimitive (do_QueryInterface(genericDataWrapper));
283 if (ptrPrimitive == NULL)
284 {
285 PR_LOG(sDragLm, PR_LOG_DEBUG, ("Could not get ptrPrimitive, no drag bitmap!"));
286 break;
287 }
288
289 nsCOMPtr<nsISupports> genericData;
290 ptrPrimitive->GetData(getter_AddRefs(genericData));
291 if (genericData == NULL)
292 {
293 PR_LOG(sDragLm, PR_LOG_DEBUG, ("Could not get data, no drag bitmap!"));
294 break;
295 }
296
297 //dependent on bug 294234 and how it's implemented. This code was for attachment 183634.
298 nsCOMPtr<nsIImageBeOS> image (do_QueryInterface(genericData));
299 if (image == NULL)
300 {
301 PR_LOG(sDragLm, PR_LOG_DEBUG, ("Could not get nsImage, no drag bitmap!"));
302 break;
303 }
304
305 BBitmap *aBitmap;
306 image->GetBitmap(&aBitmap);
307 if (aBitmap==NULL || !aBitmap->IsValid()) {
308 PR_LOG(sDragLm, PR_LOG_DEBUG, ("Could not get BBitmap, no drag bitmap %s!", aBitmap==NULL?"(null)":"(not valid)" ));
309 break;
310 }
311
312 view->DragMessage(mDragMessage, aBitmap, B_OP_OVER, BPoint(-4,-4), view);
313 noBitmap = false;
314 } while(false);
315 # endif
316
317 if (noBitmap)
318 view->DragMessage(mDragMessage, dragRect, view);
319
320 StartDragSession();
321 view->UnlockLooper();
322 return NS_OK;
323 }
324
325 //-------------------------------------------------------------------------
326 //
327 // nsIDragService : StartDragSession
328 //
329 // We overwrite this so we can log it
330 //
331 //-------------------------------------------------------------------------
332 NS_IMETHODIMP
333 nsDragService::StartDragSession()
334 {
335 PR_LOG(sDragLm, PR_LOG_DEBUG, ("nsDragService::StartDragSession()"));
336 return nsBaseDragService::StartDragSession();
337 }
338
339 //-------------------------------------------------------------------------
340 //
341 // nsIDragService : EndDragSession
342 //
343 // We overwrite this so we can log it
344 //
345 //-------------------------------------------------------------------------
346 NS_IMETHODIMP
347 nsDragService::EndDragSession()
348 {
349 PR_LOG(sDragLm, PR_LOG_DEBUG, ("nsDragService::EndDragSession()"));
350 //Don't reset drag info, keep it until there is a new drag, in case a negotiated drag'n'drop wants the info.
351 //We need the draginfo as we are ending starting the dragsession
352 //on entering/exiting different views (nsWindows) now.
353 //That way the dragsession is always ended when we go outside mozilla windows, but we do throw away the
354 // mSourceDocument and mSourceNode. We do hold on to the nsTransferable if it was a internal drag.
355 //ResetDragInfo();
356 return nsBaseDragService::EndDragSession();
357 }
358
359 //-------------------------------------------------------------------------
360 //
361 // nsIDragSession : SetCanDrop
362 //
363 // We overwrite this so we can log it
364 //
365 //-------------------------------------------------------------------------
366 NS_IMETHODIMP
367 nsDragService::SetCanDrop(PRBool aCanDrop)
368 {
369 PR_LOG(sDragLm, PR_LOG_DEBUG, ("nsDragService::SetCanDrop(%s)",
370 aCanDrop == PR_TRUE?"TRUE":"FALSE"));
371 return nsBaseDragService::SetCanDrop(aCanDrop);
372 }
373
374
375 //-------------------------------------------------------------------------
376 //
377 // nsIDragSession : GetCanDrop
378 //
379 // We overwrite this so we can log it
380 //
381 //-------------------------------------------------------------------------
382 NS_IMETHODIMP
383 nsDragService::GetCanDrop(PRBool *aCanDrop)
384 {
385 PR_LOG(sDragLm, PR_LOG_DEBUG, ("nsDragService::GetCanDrop()"));
386 return nsBaseDragService::GetCanDrop(aCanDrop);
387 }
388
389 //-------------------------------------------------------------------------
390 //
391 // nsIDragSession : GetNumDropItems
392 //
393 // Gets the number of items currently being dragged
394 //
395 //-------------------------------------------------------------------------
396 NS_IMETHODIMP
397 nsDragService::GetNumDropItems(PRUint32 * aNumItems)
398 {
399 PR_LOG(sDragLm, PR_LOG_DEBUG, ("nsDragService::GetNumDropItems()"));
400 if (nsnull == mDragMessage)
401 {
402 *aNumItems = 0;
403 PR_LOG(sDragLm, PR_LOG_DEBUG, ("nsDragService::GetNumDropItems(): WARNING! No dragmessage"));
404 return NS_OK;
405 }
406 // Did we start this drag?
407 if (IsInternalDrag(mDragMessage))
408 mSourceDataItems->Count(aNumItems);
409 else
410 // The only thing native that I can think of that may have multiple items
411 // would be file references, DND-docs don't say anything about multiple items.
412 *aNumItems = 1;
413
414
415 PR_LOG(sDragLm, PR_LOG_DEBUG, ("nsDragService::GetNumDropItems():%d", *aNumItems));
416 return NS_OK;
417 }
418
419
420 //-------------------------------------------------------------------------
421 //
422 // nsIDragSession : GetData
423 //
424 // Copies the data at the given index into the given nsITransferable
425 //
426 // This is usually called on Drop, but can be called before that
427 //
428 //-------------------------------------------------------------------------
429 NS_IMETHODIMP
430 nsDragService::GetData(nsITransferable * aTransferable, PRUint32 aItemIndex)
431 {
432 PR_LOG(sDragLm, PR_LOG_DEBUG, ("nsDragService::GetData %d", aItemIndex));
433
434 if (nsnull==mDragMessage)
435 return NS_ERROR_INVALID_ARG;
436
437 // get flavor list that includes all acceptable flavors (including
438 // ones obtained through conversion). Flavors are nsISupportsStrings
439 // so that they can be seen from JS.
440 nsresult rv = NS_ERROR_FAILURE;
441 nsCOMPtr<nsISupportsArray> flavorList;
442 rv = aTransferable->FlavorsTransferableCanImport(getter_AddRefs(flavorList));
443 if (NS_FAILED(rv))
444 return rv;
445
446 // count the number of flavors
447 PRUint32 cnt;
448 flavorList->Count (&cnt);
449
450 nsCOMPtr<nsISupports> genericWrapper;
451 nsCOMPtr<nsISupportsCString> currentFlavor;
452 nsXPIDLCString flavorStr;
453 nsCOMPtr<nsISupports> genericItem;
454 nsCOMPtr<nsISupports> data;
455 PRUint32 tmpDataLen = 0;
456 for (unsigned int i= 0; i < cnt; ++i )
457 {
458 flavorList->GetElementAt(i, getter_AddRefs(genericWrapper));
459 currentFlavor = do_QueryInterface(genericWrapper);
460 if (!currentFlavor)
461 continue;
462 currentFlavor->ToString(getter_Copies(flavorStr));
463
464 PR_LOG(sDragLm, PR_LOG_DEBUG, ("tnsDragService::GetData trying to get transfer data for %s",
465 (const char *)flavorStr));
466
467 if (IsInternalDrag(mDragMessage))
468 {
469 mSourceDataItems->GetElementAt(aItemIndex, getter_AddRefs(genericItem));
470 nsCOMPtr<nsITransferable> item (do_QueryInterface(genericItem));
471 if (!item)
472 continue;
473 rv = item->GetTransferData(flavorStr, getter_AddRefs(data), &tmpDataLen);
474 if (NS_FAILED(rv))
475 continue;
476 PR_LOG(sDragLm, PR_LOG_DEBUG, ("tnsDragService::GetData setting data."));
477 return aTransferable->SetTransferData(flavorStr, data, tmpDataLen);
478 }
479 else
480 {
481 //Check if transfer message is simple_data or older type of DND
482 //Check if message has data else continue
483 //Negotiate for data (if possible) or get data
484 //set and return
485 }
486 }
487 PR_LOG(sDragLm, PR_LOG_DEBUG, ("tnsDragService::GetData failed"));
488 return NS_ERROR_FAILURE;
489 }
490
491
492 //-------------------------------------------------------------------------
493 //
494 // nsIDragSession : IsDataFlavorSupported
495 //
496 // Tells whether the given flavor is supported by the current drag object
497 //
498 // Called on MouseOver events
499 //
500 //-------------------------------------------------------------------------
501 NS_IMETHODIMP
502 nsDragService::IsDataFlavorSupported (const char *aDataFlavor,
503 PRBool *_retval)
504 {
505 PR_LOG(sDragLm, PR_LOG_DEBUG, ("nsDragService::IsDataFlavorSupported %s", aDataFlavor));
506 if (!_retval)
507 return NS_ERROR_INVALID_ARG;
508
509 // set this to no by default
510 *_retval = PR_FALSE;
511
512 // check to make sure that we have a drag object set, here
513 if (nsnull == mDragMessage) {
514 PR_LOG(sDragLm, PR_LOG_DEBUG, ("*** warning: IsDataFlavorSupported called without a valid drag context!"));
515 return NS_OK;
516 }
517
518 if (IsInternalDrag(mDragMessage))
519 {
520 PRUint32 numDragItems = 0;
521 // if we don't have mDataItems we didn't start this drag so it's
522 // an external client trying to fool us.
523 if (nsnull == mSourceDataItems)
524 return NS_OK;
525 mSourceDataItems->Count(&numDragItems);
526 if (0 == numDragItems)
527 PR_LOG(sDragLm, PR_LOG_DEBUG, ("*** warning: Number of dragged items is zero!"));
528
529 // For all dragged items compare their flavors to the one wanted. If there is a match DataFlavor is supported.
530 nsCOMPtr<nsISupports> genericItem;
531 nsCOMPtr <nsISupportsArray> flavorList;
532 PRUint32 numFlavors;
533 for (PRUint32 itemIndex = 0; itemIndex < numDragItems; ++itemIndex)
534 {
535 mSourceDataItems->GetElementAt(itemIndex, getter_AddRefs(genericItem));
536 nsCOMPtr<nsITransferable> currItem (do_QueryInterface(genericItem));
537 if (nsnull == currItem)
538 continue;
539 currItem->FlavorsTransferableCanExport(getter_AddRefs(flavorList));
540 if (nsnull == flavorList)
541 continue;
542 flavorList->Count( &numFlavors );
543
544 nsCOMPtr<nsISupports> genericWrapper;
545 nsXPIDLCString flavorStr;
546 for ( PRUint32 flavorIndex = 0; flavorIndex < numFlavors ; ++flavorIndex ) {
547 flavorList->GetElementAt (flavorIndex, getter_AddRefs(genericWrapper));
548 nsCOMPtr<nsISupportsCString> currentFlavor = do_QueryInterface(genericWrapper);
549 if (nsnull == currentFlavor)
550 continue;
551 currentFlavor->ToString ( getter_Copies(flavorStr) );
552 PR_LOG(sDragLm, PR_LOG_DEBUG, ("nsDragService::IsDataFlavorSupported checking %s against %s", (const char *)flavorStr, aDataFlavor));
553 if (0 != strcmp(flavorStr, aDataFlavor))
554 continue;
555 PR_LOG(sDragLm, PR_LOG_DEBUG, ("nsDragService::IsDataFlavorSupported Got the flavor!"));
556 *_retval = PR_TRUE;
557 return NS_OK;
558 }
559 }
560 }
561 else
562 {
563 PR_LOG(sDragLm, PR_LOG_DEBUG, ("*** warning: Native drag not implemented."));
564 // TODO: implement native checking
565 }
566 PR_LOG(sDragLm, PR_LOG_DEBUG, ("nsDragService::IsDataFlavorSupported FALSE"));
567 return NS_OK;
568 }
569
570 //-------------------------------------------------------------------------
571 //
572 // nsDragServoce : CreateDragMessage
573 //
574 // Builds the drag message needed for BeOS negotiated DND.
575 //
576 //-------------------------------------------------------------------------
577 BMessage *
578 nsDragService::CreateDragMessage()
579 {
580 PR_LOG(sDragLm, PR_LOG_DEBUG, ("nsDragService::GetInitialDragMessage"));
581 if (nsnull == mSourceDataItems)
582 return NULL;
583
584 unsigned int numDragItems = 0;
585 mSourceDataItems->Count(&numDragItems);
586
587 BMessage * returnMsg = new BMessage(B_SIMPLE_DATA);
588
589 returnMsg->AddString("be:originator", "BeZilla");
590 returnMsg->AddString("be:clip_name","BeZilla Drag Item");
591
592 if (mDragAction & DRAGDROP_ACTION_COPY)
593 returnMsg->AddInt32("be:actions",B_COPY_TARGET);
594 if (mDragAction & DRAGDROP_ACTION_MOVE)
595 returnMsg->AddInt32("be:actions",B_MOVE_TARGET);
596 if (mDragAction & DRAGDROP_ACTION_LINK)
597 returnMsg->AddInt32("be:actions",B_LINK_TARGET);
598
599 // Check to see if we're dragging > 1 item. If we are then we use
600 // an internal only type.
601 if (numDragItems > 1)
602 {
603 PR_LOG(sDragLm, PR_LOG_DEBUG, ("nsDragService:: Dragging a list of items ..."));
604 // returnMsg->AddString("be:types", gMimeListType);
605 // returnMsg->AddString("be:types", B_FILE_MIME_TYPE);
606 // returnMsg->AddString("be:filetypes", gMimeListType);
607 // returnMsg->AddString("be:type_descriptions", gMimeListType);
608 return returnMsg;
609 }
610
611 PRBool addedType = PR_FALSE;
612
613 nsCOMPtr<nsISupports> genericItem;
614 nsCOMPtr <nsISupportsArray> flavorList;
615 PRUint32 numFlavors;
616 nsCOMPtr<nsISupports> genericWrapper;
617 nsXPIDLCString flavorStr;
618
619 for (unsigned int itemIndex = 0; itemIndex < numDragItems; ++itemIndex)
620 {
621 mSourceDataItems->GetElementAt(itemIndex, getter_AddRefs(genericItem));
622 nsCOMPtr<nsITransferable> currItem (do_QueryInterface(genericItem));
623 if (nsnull == currItem)
624 continue;
625
626 currItem->FlavorsTransferableCanExport(getter_AddRefs(flavorList));
627 if (nsnull == flavorList)
628 continue;
629 flavorList->Count( &numFlavors );
630 for (PRUint32 flavorIndex = 0; flavorIndex < numFlavors ; ++flavorIndex )
631 {
632 flavorList->GetElementAt(flavorIndex, getter_AddRefs(genericWrapper));
633 nsCOMPtr<nsISupportsCString> currentFlavor = do_QueryInterface(genericWrapper);
634 if (nsnull == currentFlavor)
635 continue;
636 currentFlavor->ToString ( getter_Copies(flavorStr) );
637
638 PR_LOG(sDragLm, PR_LOG_DEBUG, ("nsDragService:: Adding a flavor to our message: %s",flavorStr.get()));
639
640 type_code aCode;
641 if (B_OK == returnMsg->GetInfo(flavorStr.get(), &aCode))
642 continue;
643 returnMsg->AddString("be:types",flavorStr.get());
644
645 //returnMsg->AddString("be:types", B_FILE_MIME_TYPE);
646 returnMsg->AddString("be:filetypes",flavorStr.get());
647 returnMsg->AddString("be:type_descriptions",flavorStr.get());
648
649 addedType = PR_TRUE;
650 // Check to see if this is text/unicode. If it is, add
651 // text/plain since we automatically support text/plain if
652 // we support text/unicode.
653 //tqh: but this may cause duplicates?
654 if (0 == strcmp(flavorStr, kUnicodeMime))
655 {
656 PR_LOG(sDragLm, PR_LOG_DEBUG, ("nsDragService:: Adding a TextMime for the UnicodeMime"));
657 returnMsg->AddString("be:types",kTextMime);
658 //returnMsg->AddString("be:types", B_FILE_MIME_TYPE);
659 returnMsg->AddString("be:filetypes",kTextMime);
660 returnMsg->AddString("be:type_descriptions",kTextMime);
661 }
662 }
663 }
664
665 if (addedType) {
666 returnMsg->AddString("be:types", B_FILE_MIME_TYPE);
667 }
668 returnMsg->PrintToStream();
669 // If we did not add a type, we can't drag
670 NS_ASSERTION(addedType == PR_TRUE, "No flavor/mime in the drag message!");
671 return returnMsg;
672 }
673
674 //-------------------------------------------------------------------------
675 //
676 // nsIDragSessionBeOS : UpdateDragMessageIfNeeded
677 //
678 // Updates the drag message from the old one if we enter a mozilla view with
679 // a dragmessage from outside. IE one where "be:originator"-key != "BeZilla"
680 //
681 //-------------------------------------------------------------------------
682 NS_IMETHODIMP
683 nsDragService::UpdateDragMessageIfNeeded(BMessage *aDragMessage)
684 {
685 PR_LOG(sDragLm, PR_LOG_DEBUG, ("nsDragService::UpdateDragMessageIfNeeded()"));
686 if (aDragMessage == mDragMessage)
687 return NS_OK;
688
689 // Did we start this drag?
690 //It's already set properly by InvokeDragSession, so don't do anything and avoid throwing away
691 //mSourceDataItems
692 if (IsInternalDrag(aDragMessage))
693 return NS_OK;
694
695 PR_LOG(sDragLm, PR_LOG_DEBUG, ("updating."));
696 ResetDragInfo();
697 mDragMessage = aDragMessage;
698 return NS_OK;
699 }
700
701
702 //-------------------------------------------------------------------------
703 //
704 // nsIDragSessionBeOS : TransmitData
705 //
706 // When a negotiated drag'n'drop to another app occurs nsWindow
707 // calls this method with the other apps message which contains
708 // the info on what data the app wants. This function checks the
709 // message and transmits the data to the app, thereby ending the
710 // drag'n'drop to another app.
711 //-------------------------------------------------------------------------
712 NS_IMETHODIMP
713 nsDragService::TransmitData(BMessage *aNegotiationReply)
714 {
715 PR_LOG(sDragLm, PR_LOG_DEBUG, ("nsDragService::TransmitData()"));
716 /*
717 unsigned int numDragItems = 0;
718 mSourceDataItems->Count(&numDragItems);
719
720 returnMsg->AddString("be:originator", "BeZilla");
721 returnMsg->AddString("be:clip_name","BeZilla Drag Item");
722
723 // Check to see if we're dragging > 1 item. If we are then we use
724 // an internal only type.
725 if (numDragItems > 1)
726 {
727 PR_LOG(sDragLm, PR_LOG_DEBUG, ("nsDragService:: Dragging a list of items ..."));
728 delete aNegotiationReply;
729 return;
730 }
731 BMessage aReply = new BMessage(B_MIME_DATA);
732 char * aMimeType;
733 aNegotiationReply->FindString("be:types", &aMimeType);
734 nsCOMPtr<nsITransferable> item;
735 item->addDataFlavor(aMimeType);
736 GetData(item, 0);
737 aReply->AddData(aMimeType, item->);
738 */
739 aNegotiationReply->PrintToStream();
740 delete aNegotiationReply;
741 return NS_OK;
742 }
743
744 //-------------------------------------------------------------------------
745 //
746 // nsIDragService : ResetDragInfo
747 //
748 // Resets the stored drag information.
749 //
750 //-------------------------------------------------------------------------
751 void
752 nsDragService::ResetDragInfo()
753 {
754 PR_LOG(sDragLm, PR_LOG_DEBUG, ("nsDragService::ResetDragInfo()"));
755 if (nsnull != mDragMessage) delete mDragMessage;
756 mDragMessage = NULL;
757 mSourceDataItems = NULL;
758 }
759
760 const char *
761 nsDragService::FlavorToBeMime(const char * flavor)
762 {
763 //text/plain ok
764 //text/unicode -> text/plain
765 if (0 == strcmp(flavor,kUnicodeMime)) return kTextMime;
766 //text/html ok
767 //AOLMAIL ignore!!
768 //image/png ok
769 //image/jpg
770 if (0 == strcmp(flavor,kJPEGImageMime)) return "image/jpeg";
771 //image/gif ok
772 //application/x-moz-file
773 if (0 == strcmp(flavor,kFileMime)) return "application/octet-stream";
774 //text/x-moz-url (only support this as a filetype (Be bookmark))
775 if (0 == strcmp(flavor,kURLMime)) return "application/x-vnd.Be-bookmark";
776 //text/x-moz-url-data - we need to read data to find out what type of URL.
777 //text/x-moz-url-desc - a url-description (same as title?)
778 //kNativeImageMime - don't support as BeOS image
779 //kNativeHTMLMime - don't support on BeOS side
780 //kFilePromiseURLMime
781 //kFilePromiseDestFilename
782 //kFilePromiseMime
783 //kFilePromiseDirectoryMime
784
785 // if (0==strcmp(flavor,kUnicodeMime))
786 }
787