]> git.saurik.com Git - wxWidgets.git/blame - src/mac/carbon/dnd.cpp
filedata implementation streamlined
[wxWidgets.git] / src / mac / carbon / dnd.cpp
CommitLineData
e9576ca5
SC
1///////////////////////////////////////////////////////////////////////////////
2// Name: dnd.cpp
6eae1f7d 3// Purpose: wxDropTarget, wxDropSource implementations
a31a5f85 4// Author: Stefan Csomor
e9576ca5 5// Modified by:
a31a5f85 6// Created: 1998-01-01
e9576ca5 7// RCS-ID: $Id$
a31a5f85 8// Copyright: (c) 1998 Stefan Csomor
65571936 9// Licence: wxWindows licence
e9576ca5
SC
10///////////////////////////////////////////////////////////////////////////////
11
3d1a4878 12#include "wx/wxprec.h"
ff143598
GD
13
14#if wxUSE_DRAG_AND_DROP
15
e9576ca5
SC
16#include "wx/dnd.h"
17#include "wx/window.h"
ff143598 18#include "wx/toplevel.h"
e9576ca5
SC
19#include "wx/app.h"
20#include "wx/gdicmn.h"
76a5e5d2 21#include "wx/mac/private.h"
e9576ca5 22
64179ebc
DS
23#ifndef __DARWIN__
24 #include <Scrap.h>
25#endif
26
e22ab33a 27
e9576ca5 28// ----------------------------------------------------------------------------
6eae1f7d 29// globals
e9576ca5
SC
30// ----------------------------------------------------------------------------
31
6eae1f7d 32typedef struct
e9576ca5 33{
51d4293d
DS
34 wxWindow *m_currentTargetWindow;
35 wxDropTarget *m_currentTarget;
36 wxDropSource *m_currentSource;
6eae1f7d 37}
e22ab33a 38MacTrackingGlobals;
e9576ca5 39
e22ab33a 40MacTrackingGlobals gTrackingGlobals;
6eae1f7d 41
51d4293d 42void wxMacEnsureTrackingHandlersInstalled();
e9576ca5 43
a07c1212
SC
44//----------------------------------------------------------------------------
45// wxDropTarget
46//----------------------------------------------------------------------------
e9576ca5 47
a07c1212
SC
48wxDropTarget::wxDropTarget( wxDataObject *data )
49 : wxDropTargetBase( data )
e9576ca5 50{
51d4293d 51 wxMacEnsureTrackingHandlersInstalled();
e9576ca5
SC
52}
53
51d4293d
DS
54wxDragResult wxDropTarget::OnDragOver(
55 wxCoord WXUNUSED(x), wxCoord WXUNUSED(y),
56 wxDragResult def )
e9576ca5 57{
a07c1212
SC
58 return CurrentDragHasSupportedFormat() ? def : wxDragNone;
59}
e9576ca5 60
a07c1212 61bool wxDropTarget::OnDrop( wxCoord WXUNUSED(x), wxCoord WXUNUSED(y) )
e9576ca5 62{
876b960a 63 if (m_dataObject == NULL)
6eae1f7d 64 return false;
a07c1212 65
51d4293d 66 return CurrentDragHasSupportedFormat();
e9576ca5
SC
67}
68
51d4293d
DS
69wxDragResult wxDropTarget::OnData(
70 wxCoord WXUNUSED(x), wxCoord WXUNUSED(y),
71 wxDragResult def )
e9576ca5 72{
876b960a 73 if (m_dataObject == NULL)
a07c1212
SC
74 return wxDragNone;
75
76 if (!CurrentDragHasSupportedFormat())
77 return wxDragNone;
78
79 return GetData() ? def : wxDragNone;
e9576ca5
SC
80}
81
6eae1f7d 82bool wxDropTarget::CurrentDragHasSupportedFormat()
e9576ca5 83{
51d4293d 84 bool supported = false;
876b960a 85
a07c1212
SC
86 if ( gTrackingGlobals.m_currentSource != NULL )
87 {
51d4293d 88 wxDataObject* data = gTrackingGlobals.m_currentSource->GetDataObject();
6eae1f7d 89
e40298d5 90 if ( data )
a07c1212 91 {
51d4293d 92 size_t formatcount = data->GetFormatCount();
876b960a 93 wxDataFormat *array = new wxDataFormat[formatcount];
e40298d5 94 data->GetAllFormats( array );
51d4293d 95 for (size_t i = 0; !supported && i < formatcount; i++)
a07c1212 96 {
51d4293d 97 wxDataFormat format = array[i];
6eae1f7d 98 if ( m_dataObject->IsSupported( format ) )
e40298d5 99 {
51d4293d
DS
100 supported = true;
101 break;
e40298d5 102 }
a07c1212 103 }
6eae1f7d 104
51d4293d 105 delete [] array;
a07c1212 106 }
a07c1212 107 }
6eae1f7d 108
a07c1212
SC
109 if ( !supported )
110 {
51d4293d 111 UInt16 items;
e40298d5 112 OSErr result;
6eae1f7d 113 ItemReference theItem;
51d4293d
DS
114 FlavorType theType;
115 UInt16 flavors = 0;
6eae1f7d 116
e22ab33a 117 CountDragItems( (DragReference)m_currentDrag, &items );
876b960a 118 for (UInt16 index = 1; index <= items && !supported; ++index)
e40298d5 119 {
51d4293d 120 flavors = 0;
876b960a
DS
121 GetDragItemReferenceNumber( (DragReference)m_currentDrag, index, &theItem );
122 CountDragItemFlavors( (DragReference)m_currentDrag, theItem, &flavors );
6eae1f7d 123
51d4293d 124 for ( UInt16 flavor = 1; flavor <= flavors; ++flavor )
a07c1212 125 {
876b960a 126 result = GetFlavorType( (DragReference)m_currentDrag, theItem, flavor, &theType );
e40298d5
JS
127 if ( m_dataObject->IsSupportedFormat( wxDataFormat( theType ) ) )
128 {
51d4293d
DS
129 supported = true;
130 break;
e40298d5 131 }
a07c1212 132 }
e40298d5 133 }
a07c1212 134 }
6eae1f7d 135
51d4293d 136 return supported;
e9576ca5
SC
137}
138
a07c1212 139bool wxDropTarget::GetData()
e9576ca5 140{
e22ab33a 141 if (m_dataObject == NULL)
6eae1f7d
DS
142 return false;
143
a07c1212 144 if ( !CurrentDragHasSupportedFormat() )
2e91d506 145 return false;
6eae1f7d 146
2e91d506 147 bool transferred = false;
a07c1212
SC
148 if ( gTrackingGlobals.m_currentSource != NULL )
149 {
2e91d506 150 wxDataObject* data = gTrackingGlobals.m_currentSource->GetDataObject();
6eae1f7d 151
2e91d506 152 if (data != NULL)
a07c1212 153 {
2e91d506 154 size_t formatcount = data->GetFormatCount();
6eae1f7d 155 wxDataFormat *array = new wxDataFormat[formatcount];
e40298d5 156 data->GetAllFormats( array );
2e91d506 157 for (size_t i = 0; !transferred && i < formatcount; i++)
a07c1212 158 {
2e91d506 159 wxDataFormat format = array[i];
6eae1f7d 160 if ( m_dataObject->IsSupported( format ) )
e40298d5
JS
161 {
162 int size = data->GetDataSize( format );
2e91d506 163 transferred = true;
6eae1f7d
DS
164
165 if (size == 0)
e40298d5 166 {
2e91d506 167 m_dataObject->SetData( format, 0, 0 );
e40298d5
JS
168 }
169 else
170 {
171 char *d = new char[size];
2e91d506
DS
172 data->GetDataHere( format, (void*)d );
173 m_dataObject->SetData( format, size, d );
174 delete [] d;
e40298d5
JS
175 }
176 }
a07c1212 177 }
6eae1f7d 178
2e91d506 179 delete [] array;
e40298d5 180 }
a07c1212 181 }
6eae1f7d 182
a07c1212
SC
183 if ( !transferred )
184 {
51d4293d 185 UInt16 items;
e40298d5 186 OSErr result;
6eae1f7d 187 ItemReference theItem;
51d4293d 188 FlavorType theType;
6eae1f7d 189 FlavorFlags theFlags;
51d4293d
DS
190 UInt16 flavors;
191 bool firstFileAdded = false;
55f5548f
SC
192
193 wxString filenamesPassed ;
6eae1f7d 194
876b960a 195 CountDragItems( (DragReference)m_currentDrag, &items );
6eae1f7d 196 for (UInt16 index = 1; index <= items; ++index)
e40298d5 197 {
51d4293d 198 flavors = 0;
876b960a 199 GetDragItemReferenceNumber( (DragReference)m_currentDrag, index, &theItem );
51d4293d 200 CountDragItemFlavors( (DragReference)m_currentDrag, theItem, &flavors );
e22ab33a 201 wxDataFormat preferredFormat = m_dataObject->GetPreferredFormat( wxDataObject::Set );
51d4293d 202 bool hasPreferredFormat = false;
6eae1f7d 203
51d4293d 204 for ( UInt16 flavor = 1; flavor <= flavors; ++flavor )
a07c1212 205 {
876b960a
DS
206 result = GetFlavorType( (DragReference)m_currentDrag, theItem, flavor, &theType );
207 wxDataFormat format( theType );
6db6bfd1
SC
208 if ( preferredFormat == format )
209 {
51d4293d
DS
210 hasPreferredFormat = true;
211 break;
6db6bfd1
SC
212 }
213 }
6eae1f7d 214
51d4293d 215 for ( UInt16 flavor = 1; flavor <= flavors; ++flavor )
6db6bfd1 216 {
e22ab33a 217 result = GetFlavorType( (DragReference)m_currentDrag, theItem, flavor, &theType );
51d4293d 218 wxDataFormat format( theType );
876b960a
DS
219 if ( (hasPreferredFormat && format == preferredFormat)
220 || (!hasPreferredFormat && m_dataObject->IsSupportedFormat( format )))
e40298d5 221 {
876b960a 222 result = GetFlavorFlags( (DragReference)m_currentDrag, theItem, theType, &theFlags );
6eae1f7d 223 if (result == noErr)
a07c1212 224 {
51d4293d
DS
225 Size dataSize;
226 Ptr theData;
6eae1f7d 227
876b960a 228 GetFlavorDataSize( (DragReference)m_currentDrag, theItem, theType, &dataSize );
2b2832ef 229 if ( theType == kScrapFlavorTypeText )
e40298d5 230 {
e22ab33a
DS
231 // this increment is only valid for allocating:
232 // on the next GetFlavorData call it is reset again to the original value
51d4293d 233 dataSize++;
e40298d5 234 }
2b2832ef
SC
235 else if ( theType == kScrapFlavorTypeUnicode )
236 {
e22ab33a
DS
237 // this increment is only valid for allocating:
238 // on the next GetFlavorData call it is reset again to the original value
51d4293d
DS
239 dataSize++;
240 dataSize++;
2b2832ef 241 }
6eae1f7d 242
2e91d506
DS
243 if (dataSize > 0)
244 theData = new char[dataSize];
245 else
246 theData = NULL;
876b960a
DS
247
248 GetFlavorData( (DragReference)m_currentDrag, theItem, theType, (void*) theData, &dataSize, 0L );
51d4293d 249 switch (theType)
2b2832ef 250 {
51d4293d
DS
251 case kScrapFlavorTypeText:
252 theData[dataSize] = 0;
253 m_dataObject->SetData( wxDataFormat(wxDF_TEXT), dataSize, theData );
254 break;
255
63c6e6c8 256#if wxUSE_UNICODE
51d4293d 257 case kScrapFlavorTypeUnicode:
876b960a 258 theData[dataSize + 0] =
51d4293d
DS
259 theData[dataSize + 1] = 0;
260 m_dataObject->SetData( wxDataFormat(wxDF_UNICODETEXT), dataSize, theData );
261 break;
63c6e6c8 262#endif
63c6e6c8 263
51d4293d 264 case kDragFlavorTypeHFS:
e40298d5 265 {
55f5548f 266 if (theData != NULL)
63c6e6c8 267 {
51d4293d
DS
268 HFSFlavor* theFile = (HFSFlavor*) theData;
269 wxString name = wxMacFSSpec2MacFilename( &theFile->fileSpec );
270
51d4293d 271 if (!name.IsEmpty())
55f5548f 272 filenamesPassed += name + wxT("\n");
63c6e6c8 273 }
e40298d5 274 }
51d4293d
DS
275 break;
276
277 default:
e40298d5 278 m_dataObject->SetData( format, dataSize, theData );
51d4293d 279 break;
e40298d5 280 }
6eae1f7d
DS
281
282 delete [] theData;
a07c1212 283 }
51d4293d 284 break;
e40298d5 285 }
a07c1212 286 }
e40298d5 287 }
55f5548f
SC
288 if ( filenamesPassed.Len() > 0 )
289 {
290 wxCharBuffer buf = filenamesPassed.fn_str();
291 m_dataObject->SetData( wxDataFormat( wxDF_FILENAME ) , strlen( buf ) , (const char*) buf );
292 }
a07c1212 293 }
6eae1f7d 294
51d4293d 295 return true;
e9576ca5
SC
296}
297
298//-------------------------------------------------------------------------
299// wxDropSource
300//-------------------------------------------------------------------------
301
302//-----------------------------------------------------------------------------
303// drag request
304
a07c1212 305wxDropSource::wxDropSource(wxWindow *win,
da804130
SC
306 const wxCursor &cursorCopy,
307 const wxCursor &cursorMove,
308 const wxCursor &cursorStop)
309 : wxDropSourceBase(cursorCopy, cursorMove, cursorStop)
e9576ca5 310{
51d4293d 311 wxMacEnsureTrackingHandlersInstalled();
e22ab33a 312
a07c1212
SC
313 m_window = win;
314}
e9576ca5 315
a07c1212
SC
316wxDropSource::wxDropSource(wxDataObject& data,
317 wxWindow *win,
da804130
SC
318 const wxCursor &cursorCopy,
319 const wxCursor &cursorMove,
320 const wxCursor &cursorStop)
321 : wxDropSourceBase(cursorCopy, cursorMove, cursorStop)
a07c1212 322{
51d4293d 323 wxMacEnsureTrackingHandlersInstalled();
e22ab33a 324
a07c1212
SC
325 SetData( data );
326 m_window = win;
327}
e9576ca5 328
a07c1212 329wxDropSource::~wxDropSource()
e9576ca5 330{
a07c1212 331}
e9576ca5 332
525ae3fe 333wxDragResult wxDropSource::DoDragDrop(int flags)
e9576ca5 334{
a07c1212 335 wxASSERT_MSG( m_data, wxT("Drop source: no data") );
6eae1f7d 336
a07c1212
SC
337 if (!m_data)
338 return (wxDragResult) wxDragNone;
a07c1212
SC
339 if (m_data->GetFormatCount() == 0)
340 return (wxDragResult) wxDragNone;
6eae1f7d 341
2e91d506 342 OSStatus result;
a07c1212
SC
343 DragReference theDrag;
344 RgnHandle dragRegion;
6eae1f7d 345 if ((result = NewDrag(&theDrag)) != noErr)
51d4293d 346 return wxDragNone;
6eae1f7d 347
a07c1212 348 // add data to drag
51d4293d
DS
349 size_t formatCount = m_data->GetFormatCount();
350 wxDataFormat *formats = new wxDataFormat[formatCount];
351 m_data->GetAllFormats( formats );
352 ItemReference theItem = 1;
6eae1f7d 353
51d4293d 354 for ( size_t i = 0; i < formatCount; ++i )
a07c1212 355 {
51d4293d
DS
356 size_t dataSize = m_data->GetDataSize( formats[i] );
357 Ptr dataPtr = new char[dataSize];
358 m_data->GetDataHere( formats[i], dataPtr );
359 OSType type = formats[i].GetFormatId();
6ac23e25 360 if ( type == 'TEXT' || type == 'utxt' )
a07c1212 361 {
6ac23e25 362 if ( dataSize > 0 )
51d4293d
DS
363 dataSize--;
364 dataPtr[ dataSize ] = 0;
6ac23e25
SC
365 if ( type == 'utxt' )
366 {
367 if ( dataSize > 0 )
51d4293d
DS
368 dataSize--;
369 dataPtr[ dataSize ] = 0;
6ac23e25 370 }
6eae1f7d 371
51d4293d 372 AddDragItemFlavor( theDrag, theItem, type, dataPtr, dataSize, 0 );
a07c1212
SC
373 }
374 else if (type == kDragFlavorTypeHFS )
375 {
51d4293d 376 HFSFlavor theFlavor;
e40298d5
JS
377 OSErr err = noErr;
378 CInfoPBRec cat;
6eae1f7d 379
51d4293d 380 wxMacFilename2FSSpec( wxString( dataPtr, *wxConvCurrent ), &theFlavor.fileSpec );
6eae1f7d
DS
381
382 memset( &cat, 0, sizeof(cat) );
e40298d5
JS
383 cat.hFileInfo.ioNamePtr = theFlavor.fileSpec.name;
384 cat.hFileInfo.ioVRefNum = theFlavor.fileSpec.vRefNum;
385 cat.hFileInfo.ioDirID = theFlavor.fileSpec.parID;
386 cat.hFileInfo.ioFDirIndex = 0;
e22ab33a 387 err = PBGetCatInfoSync( &cat );
6eae1f7d 388 if (err == noErr)
e40298d5
JS
389 {
390 theFlavor.fdFlags = cat.hFileInfo.ioFlFndrInfo.fdFlags;
6eae1f7d
DS
391 if (theFlavor.fileSpec.parID == fsRtParID)
392 {
e40298d5
JS
393 theFlavor.fileCreator = 'MACS';
394 theFlavor.fileType = 'disk';
6eae1f7d
DS
395 }
396 else if ((cat.hFileInfo.ioFlAttrib & ioDirMask) != 0)
397 {
e40298d5
JS
398 theFlavor.fileCreator = 'MACS';
399 theFlavor.fileType = 'fold';
6eae1f7d
DS
400 }
401 else
402 {
e40298d5
JS
403 theFlavor.fileCreator = cat.hFileInfo.ioFlFndrInfo.fdCreator;
404 theFlavor.fileType = cat.hFileInfo.ioFlFndrInfo.fdType;
405 }
6eae1f7d 406
51d4293d 407 AddDragItemFlavor( theDrag, theItem, type, &theFlavor, sizeof(theFlavor), 0 );
6eae1f7d 408 }
a07c1212
SC
409 }
410 else
411 {
51d4293d 412 AddDragItemFlavor( theDrag, theItem, type, dataPtr, dataSize, 0 );
a07c1212 413 }
6eae1f7d 414
51d4293d 415 delete [] dataPtr;
a07c1212 416 }
6eae1f7d 417
51d4293d 418 delete [] formats;
6eae1f7d 419
a07c1212 420 dragRegion = NewRgn();
51d4293d 421 RgnHandle tempRgn = NewRgn();
6eae1f7d 422
51d4293d 423 EventRecord* ev = NULL;
6eae1f7d 424
45a0fd37 425#if !TARGET_CARBON // TODO
51d4293d 426 ev = (EventRecord*) wxTheApp->MacGetCurrentEvent();
45a0fd37 427#else
db28a493
SC
428 EventRecord rec;
429 ev = &rec;
430 wxMacConvertEventToRecord( (EventRef) wxTheApp->MacGetCurrentEvent(), &rec );
45a0fd37 431#endif
6eae1f7d 432
51d4293d
DS
433 const short dragRegionOuterBoundary = 10;
434 const short dragRegionInnerBoundary = 9;
6eae1f7d
DS
435
436 SetRectRgn(
51d4293d
DS
437 dragRegion,
438 ev->where.h - dragRegionOuterBoundary,
439 ev->where.v - dragRegionOuterBoundary,
440 ev->where.h + dragRegionOuterBoundary,
441 ev->where.v + dragRegionOuterBoundary );
6eae1f7d
DS
442
443 SetRectRgn(
51d4293d
DS
444 tempRgn,
445 ev->where.h - dragRegionInnerBoundary,
446 ev->where.v - dragRegionInnerBoundary,
447 ev->where.h + dragRegionInnerBoundary,
448 ev->where.v + dragRegionInnerBoundary );
6eae1f7d 449
51d4293d
DS
450 DiffRgn( dragRegion, tempRgn, dragRegion );
451 DisposeRgn( tempRgn );
6eae1f7d 452
e22ab33a
DS
453 // TODO: work with promises in order to return data
454 // only when drag was successfully completed
6eae1f7d 455
e22ab33a
DS
456 gTrackingGlobals.m_currentSource = this;
457 result = TrackDrag( theDrag, ev, dragRegion );
458 DisposeRgn( dragRegion );
459 DisposeDrag( theDrag );
460 gTrackingGlobals.m_currentSource = NULL;
6eae1f7d 461
e22ab33a
DS
462 bool optionDown = GetCurrentKeyModifiers() & optionKey;
463 wxDragResult dndresult = wxDragCopy;
6eae1f7d 464 if ( flags != wxDrag_CopyOnly )
525ae3fe
SC
465 // on mac the option key is always the indication for copy
466 dndresult = optionDown ? wxDragCopy : wxDragMove;
6eae1f7d 467
f43084de 468 return dndresult;
a07c1212
SC
469}
470
da804130
SC
471bool wxDropSource::MacInstallDefaultCursor(wxDragResult effect)
472{
473 const wxCursor& cursor = GetCursor(effect);
6eae1f7d
DS
474 bool result = cursor.Ok();
475
476 if ( result )
e22ab33a 477 cursor.MacInstall();
da804130 478
6eae1f7d 479 return result;
da804130
SC
480}
481
51d4293d 482bool gTrackingGlobalsInstalled = false;
a07c1212
SC
483
484// passing the globals via refcon is not needed by the CFM and later architectures anymore
485// but I'll leave it in there, just in case...
486
6eae1f7d
DS
487pascal OSErr wxMacWindowDragTrackingHandler(
488 DragTrackingMessage theMessage, WindowPtr theWindow,
e22ab33a 489 void *handlerRefCon, DragReference theDrag );
6eae1f7d
DS
490pascal OSErr wxMacWindowDragReceiveHandler(
491 WindowPtr theWindow, void *handlerRefCon,
e22ab33a 492 DragReference theDrag );
a07c1212
SC
493
494void wxMacEnsureTrackingHandlersInstalled()
e9576ca5 495{
6eae1f7d 496 if ( !gTrackingGlobalsInstalled )
a07c1212 497 {
2e91d506 498 OSStatus err;
a07c1212 499
2e91d506
DS
500 err = InstallTrackingHandler( NewDragTrackingHandlerUPP(wxMacWindowDragTrackingHandler), 0L, &gTrackingGlobals );
501 verify_noerr( err );
6eae1f7d 502
2e91d506
DS
503 err = InstallReceiveHandler( NewDragReceiveHandlerUPP(wxMacWindowDragReceiveHandler), 0L, &gTrackingGlobals );
504 verify_noerr( err );
e9576ca5 505
e22ab33a 506 gTrackingGlobalsInstalled = true;
a07c1212
SC
507 }
508}
509
6eae1f7d
DS
510pascal OSErr wxMacWindowDragTrackingHandler(
511 DragTrackingMessage theMessage, WindowPtr theWindow,
e22ab33a 512 void *handlerRefCon, DragReference theDrag )
6eae1f7d 513{
a07c1212 514 MacTrackingGlobals* trackingGlobals = (MacTrackingGlobals*) handlerRefCon;
e22ab33a 515
a07c1212
SC
516 Point mouse, localMouse;
517 DragAttributes attributes;
e22ab33a
DS
518
519 GetDragAttributes( theDrag, &attributes );
520
51d4293d 521 wxTopLevelWindowMac* toplevel = wxFindWinFromMacWindow( theWindow );
f43084de 522
51d4293d 523 bool optionDown = GetCurrentKeyModifiers() & optionKey;
f43084de
JS
524 wxDragResult result = optionDown ? wxDragCopy : wxDragMove;
525
6eae1f7d 526 switch (theMessage)
a07c1212
SC
527 {
528 case kDragTrackingEnterHandler:
a07c1212
SC
529 case kDragTrackingLeaveHandler:
530 break;
6eae1f7d 531
a07c1212 532 case kDragTrackingEnterWindow:
e22ab33a
DS
533 if (trackingGlobals != NULL)
534 {
51d4293d
DS
535 trackingGlobals->m_currentTargetWindow = NULL;
536 trackingGlobals->m_currentTarget = NULL;
e22ab33a 537 }
a07c1212 538 break;
6eae1f7d 539
a07c1212 540 case kDragTrackingInWindow:
e22ab33a
DS
541 if (trackingGlobals == NULL)
542 break;
a07c1212
SC
543 if (toplevel == NULL)
544 break;
545
e22ab33a 546 GetDragMouse( theDrag, &mouse, 0L );
a07c1212 547 localMouse = mouse;
e22ab33a 548 GlobalToLocal( &localMouse );
f43084de 549
a07c1212 550 {
51d4293d
DS
551 wxWindow *win = NULL;
552 ControlPartCode controlPart;
6eae1f7d 553 ControlRef control = wxMacFindControlUnderMouse(
51d4293d 554 toplevel, localMouse, theWindow, &controlPart );
2877659b 555 if ( control )
51d4293d 556 win = wxFindControlFromMacControl( control );
7adabb9a 557 else
51d4293d 558 win = toplevel;
6eae1f7d 559
51d4293d
DS
560 int localx, localy;
561 localx = localMouse.h;
562 localy = localMouse.v;
7adabb9a 563
a07c1212 564 if ( win )
51d4293d 565 win->MacRootWindowToWindow( &localx, &localy );
a07c1212
SC
566 if ( win != trackingGlobals->m_currentTargetWindow )
567 {
568 if ( trackingGlobals->m_currentTargetWindow )
569 {
570 // this window is left
571 if ( trackingGlobals->m_currentTarget )
572 {
6eae1f7d 573 HideDragHilite( theDrag );
876b960a
DS
574 trackingGlobals->m_currentTarget->SetCurrentDrag( theDrag );
575 trackingGlobals->m_currentTarget->OnLeave();
a07c1212 576 trackingGlobals->m_currentTarget = NULL;
876b960a 577 trackingGlobals->m_currentTargetWindow = NULL;
a07c1212
SC
578 }
579 }
6eae1f7d 580
a07c1212
SC
581 if ( win )
582 {
583 // this window is entered
51d4293d
DS
584 trackingGlobals->m_currentTargetWindow = win;
585 trackingGlobals->m_currentTarget = win->GetDropTarget();
a07c1212 586 {
6eae1f7d
DS
587 if ( trackingGlobals->m_currentTarget )
588 {
51d4293d
DS
589 trackingGlobals->m_currentTarget->SetCurrentDrag( theDrag );
590 result = trackingGlobals->m_currentTarget->OnEnter( localx, localy, result );
da804130 591 }
6eae1f7d 592
da804130 593 if ( result != wxDragNone )
a07c1212 594 {
51d4293d 595 int x, y;
6eae1f7d 596
51d4293d
DS
597 x = y = 0;
598 win->MacWindowToRootWindow( &x, &y );
599 RgnHandle hiliteRgn = NewRgn();
600 Rect r = { y, x, y + win->GetSize().y, x + win->GetSize().x };
601 RectRgn( hiliteRgn, &r );
876b960a 602 ShowDragHilite( theDrag, hiliteRgn, true );
51d4293d 603 DisposeRgn( hiliteRgn );
a07c1212
SC
604 }
605 }
606 }
607 }
608 else
609 {
6eae1f7d 610 if ( trackingGlobals->m_currentTarget )
a07c1212 611 {
51d4293d
DS
612 trackingGlobals->m_currentTarget->SetCurrentDrag( theDrag );
613 trackingGlobals->m_currentTarget->OnDragOver( localx, localy, result );
f43084de
JS
614 }
615 }
616
617 // set cursor for OnEnter and OnDragOver
bf473da7 618 if ( trackingGlobals->m_currentSource && !trackingGlobals->m_currentSource->GiveFeedback( result ) )
f43084de 619 {
6eae1f7d 620 if ( !trackingGlobals->m_currentSource->MacInstallDefaultCursor( result ) )
f43084de 621 {
6eae1f7d 622 switch ( result )
f43084de 623 {
2e91d506 624 case wxDragCopy:
eb7f8ac5 625 {
51d4293d
DS
626 wxCursor cursor(wxCURSOR_COPY_ARROW);
627 cursor.MacInstall();
eb7f8ac5 628 }
51d4293d 629 break;
6eae1f7d 630
2e91d506 631 case wxDragMove:
eb7f8ac5 632 {
51d4293d
DS
633 wxCursor cursor(wxCURSOR_ARROW);
634 cursor.MacInstall();
eb7f8ac5 635 }
51d4293d 636 break;
6eae1f7d 637
2e91d506 638 case wxDragNone:
eb7f8ac5 639 {
51d4293d
DS
640 wxCursor cursor(wxCURSOR_NO_ENTRY);
641 cursor.MacInstall();
eb7f8ac5 642 }
51d4293d 643 break;
eb7f8ac5
VZ
644
645 case wxDragError:
646 case wxDragLink:
647 case wxDragCancel:
6eae1f7d 648 default:
eb7f8ac5
VZ
649 // put these here to make gcc happy
650 ;
f43084de 651 }
6eae1f7d 652 }
a07c1212 653 }
7adabb9a 654 }
a07c1212 655 break;
6eae1f7d 656
a07c1212 657 case kDragTrackingLeaveWindow:
e22ab33a
DS
658 if (trackingGlobals == NULL)
659 break;
660
6eae1f7d 661 if (trackingGlobals->m_currentTarget)
a07c1212 662 {
876b960a
DS
663 trackingGlobals->m_currentTarget->SetCurrentDrag( theDrag );
664 trackingGlobals->m_currentTarget->OnLeave();
665 HideDragHilite( theDrag );
666 trackingGlobals->m_currentTarget = NULL;
a07c1212 667 }
876b960a 668 trackingGlobals->m_currentTargetWindow = NULL;
a07c1212 669 break;
6eae1f7d
DS
670
671 default:
672 break;
a07c1212 673 }
6eae1f7d
DS
674
675 return noErr;
a07c1212
SC
676}
677
6eae1f7d
DS
678pascal OSErr wxMacWindowDragReceiveHandler(
679 WindowPtr theWindow,
680 void *handlerRefCon,
681 DragReference theDrag)
682{
683 MacTrackingGlobals* trackingGlobals = (MacTrackingGlobals*)handlerRefCon;
a07c1212
SC
684 if ( trackingGlobals->m_currentTarget )
685 {
51d4293d
DS
686 Point mouse, localMouse;
687 int localx, localy;
6eae1f7d 688
51d4293d
DS
689 trackingGlobals->m_currentTarget->SetCurrentDrag( theDrag );
690 GetDragMouse( theDrag, &mouse, 0L );
a07c1212 691 localMouse = mouse;
51d4293d
DS
692 GlobalToLocal( &localMouse );
693 localx = localMouse.h;
694 localy = localMouse.v;
6eae1f7d
DS
695
696 // TODO : should we use client coordinates?
a07c1212 697 if ( trackingGlobals->m_currentTargetWindow )
51d4293d
DS
698 trackingGlobals->m_currentTargetWindow->MacRootWindowToWindow( &localx, &localy );
699 if ( trackingGlobals->m_currentTarget->OnDrop( localx, localy ) )
a07c1212 700 {
51d4293d 701 bool optionDown = GetCurrentKeyModifiers() & optionKey;
f43084de 702 wxDragResult result = optionDown ? wxDragCopy : wxDragMove;
51d4293d 703 trackingGlobals->m_currentTarget->OnData( localx, localy, result );
a07c1212
SC
704 }
705 }
6eae1f7d
DS
706
707 return noErr;
a07c1212 708}
6eae1f7d 709
03e11df5 710#endif