]> git.saurik.com Git - wxWidgets.git/blame - src/mac/carbon/dnd.cpp
fixing a scope error introduced in 1.41
[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;
6eae1f7d 192
876b960a 193 CountDragItems( (DragReference)m_currentDrag, &items );
6eae1f7d 194 for (UInt16 index = 1; index <= items; ++index)
e40298d5 195 {
51d4293d 196 flavors = 0;
876b960a 197 GetDragItemReferenceNumber( (DragReference)m_currentDrag, index, &theItem );
51d4293d 198 CountDragItemFlavors( (DragReference)m_currentDrag, theItem, &flavors );
e22ab33a 199 wxDataFormat preferredFormat = m_dataObject->GetPreferredFormat( wxDataObject::Set );
51d4293d 200 bool hasPreferredFormat = false;
6eae1f7d 201
51d4293d 202 for ( UInt16 flavor = 1; flavor <= flavors; ++flavor )
a07c1212 203 {
876b960a
DS
204 result = GetFlavorType( (DragReference)m_currentDrag, theItem, flavor, &theType );
205 wxDataFormat format( theType );
6db6bfd1
SC
206 if ( preferredFormat == format )
207 {
51d4293d
DS
208 hasPreferredFormat = true;
209 break;
6db6bfd1
SC
210 }
211 }
6eae1f7d 212
51d4293d 213 for ( UInt16 flavor = 1; flavor <= flavors; ++flavor )
6db6bfd1 214 {
e22ab33a 215 result = GetFlavorType( (DragReference)m_currentDrag, theItem, flavor, &theType );
51d4293d 216 wxDataFormat format( theType );
876b960a
DS
217 if ( (hasPreferredFormat && format == preferredFormat)
218 || (!hasPreferredFormat && m_dataObject->IsSupportedFormat( format )))
e40298d5 219 {
876b960a 220 result = GetFlavorFlags( (DragReference)m_currentDrag, theItem, theType, &theFlags );
6eae1f7d 221 if (result == noErr)
a07c1212 222 {
51d4293d
DS
223 Size dataSize;
224 Ptr theData;
6eae1f7d 225
876b960a 226 GetFlavorDataSize( (DragReference)m_currentDrag, theItem, theType, &dataSize );
2b2832ef 227 if ( theType == kScrapFlavorTypeText )
e40298d5 228 {
e22ab33a
DS
229 // this increment is only valid for allocating:
230 // on the next GetFlavorData call it is reset again to the original value
51d4293d 231 dataSize++;
e40298d5 232 }
2b2832ef
SC
233 else if ( theType == kScrapFlavorTypeUnicode )
234 {
e22ab33a
DS
235 // this increment is only valid for allocating:
236 // on the next GetFlavorData call it is reset again to the original value
51d4293d
DS
237 dataSize++;
238 dataSize++;
2b2832ef 239 }
6eae1f7d 240
2e91d506
DS
241 if (dataSize > 0)
242 theData = new char[dataSize];
243 else
244 theData = NULL;
876b960a
DS
245
246 GetFlavorData( (DragReference)m_currentDrag, theItem, theType, (void*) theData, &dataSize, 0L );
51d4293d 247 switch (theType)
2b2832ef 248 {
51d4293d
DS
249 case kScrapFlavorTypeText:
250 theData[dataSize] = 0;
251 m_dataObject->SetData( wxDataFormat(wxDF_TEXT), dataSize, theData );
252 break;
253
63c6e6c8 254#if wxUSE_UNICODE
51d4293d 255 case kScrapFlavorTypeUnicode:
876b960a 256 theData[dataSize + 0] =
51d4293d
DS
257 theData[dataSize + 1] = 0;
258 m_dataObject->SetData( wxDataFormat(wxDF_UNICODETEXT), dataSize, theData );
259 break;
63c6e6c8 260#endif
63c6e6c8 261
51d4293d 262 case kDragFlavorTypeHFS:
e40298d5 263 {
51d4293d
DS
264 wxFileDataObject *fdo = dynamic_cast<wxFileDataObject*>(m_dataObject);
265 wxASSERT( fdo != NULL );
63c6e6c8 266
51d4293d 267 if ((theData != NULL) && (fdo != NULL))
63c6e6c8 268 {
51d4293d
DS
269 HFSFlavor* theFile = (HFSFlavor*) theData;
270 wxString name = wxMacFSSpec2MacFilename( &theFile->fileSpec );
271
272 if ( !firstFileAdded )
273 {
274 // reset file list
275 fdo->SetData( 0, "" );
276 firstFileAdded = true;
277 }
278
279 if (!name.IsEmpty())
280 fdo->AddFile( name );
63c6e6c8 281 }
e40298d5 282 }
51d4293d
DS
283 break;
284
285 default:
e40298d5 286 m_dataObject->SetData( format, dataSize, theData );
51d4293d 287 break;
e40298d5 288 }
6eae1f7d
DS
289
290 delete [] theData;
a07c1212 291 }
51d4293d 292 break;
e40298d5 293 }
a07c1212 294 }
e40298d5 295 }
a07c1212 296 }
6eae1f7d 297
51d4293d 298 return true;
e9576ca5
SC
299}
300
301//-------------------------------------------------------------------------
302// wxDropSource
303//-------------------------------------------------------------------------
304
305//-----------------------------------------------------------------------------
306// drag request
307
a07c1212 308wxDropSource::wxDropSource(wxWindow *win,
da804130
SC
309 const wxCursor &cursorCopy,
310 const wxCursor &cursorMove,
311 const wxCursor &cursorStop)
312 : wxDropSourceBase(cursorCopy, cursorMove, cursorStop)
e9576ca5 313{
51d4293d 314 wxMacEnsureTrackingHandlersInstalled();
e22ab33a 315
a07c1212
SC
316 m_window = win;
317}
e9576ca5 318
a07c1212
SC
319wxDropSource::wxDropSource(wxDataObject& data,
320 wxWindow *win,
da804130
SC
321 const wxCursor &cursorCopy,
322 const wxCursor &cursorMove,
323 const wxCursor &cursorStop)
324 : wxDropSourceBase(cursorCopy, cursorMove, cursorStop)
a07c1212 325{
51d4293d 326 wxMacEnsureTrackingHandlersInstalled();
e22ab33a 327
a07c1212
SC
328 SetData( data );
329 m_window = win;
330}
e9576ca5 331
a07c1212 332wxDropSource::~wxDropSource()
e9576ca5 333{
a07c1212 334}
e9576ca5 335
525ae3fe 336wxDragResult wxDropSource::DoDragDrop(int flags)
e9576ca5 337{
a07c1212 338 wxASSERT_MSG( m_data, wxT("Drop source: no data") );
6eae1f7d 339
a07c1212
SC
340 if (!m_data)
341 return (wxDragResult) wxDragNone;
a07c1212
SC
342 if (m_data->GetFormatCount() == 0)
343 return (wxDragResult) wxDragNone;
6eae1f7d 344
2e91d506 345 OSStatus result;
a07c1212
SC
346 DragReference theDrag;
347 RgnHandle dragRegion;
6eae1f7d 348 if ((result = NewDrag(&theDrag)) != noErr)
51d4293d 349 return wxDragNone;
6eae1f7d 350
a07c1212 351 // add data to drag
51d4293d
DS
352 size_t formatCount = m_data->GetFormatCount();
353 wxDataFormat *formats = new wxDataFormat[formatCount];
354 m_data->GetAllFormats( formats );
355 ItemReference theItem = 1;
6eae1f7d 356
51d4293d 357 for ( size_t i = 0; i < formatCount; ++i )
a07c1212 358 {
51d4293d
DS
359 size_t dataSize = m_data->GetDataSize( formats[i] );
360 Ptr dataPtr = new char[dataSize];
361 m_data->GetDataHere( formats[i], dataPtr );
362 OSType type = formats[i].GetFormatId();
6ac23e25 363 if ( type == 'TEXT' || type == 'utxt' )
a07c1212 364 {
6ac23e25 365 if ( dataSize > 0 )
51d4293d
DS
366 dataSize--;
367 dataPtr[ dataSize ] = 0;
6ac23e25
SC
368 if ( type == 'utxt' )
369 {
370 if ( dataSize > 0 )
51d4293d
DS
371 dataSize--;
372 dataPtr[ dataSize ] = 0;
6ac23e25 373 }
6eae1f7d 374
51d4293d 375 AddDragItemFlavor( theDrag, theItem, type, dataPtr, dataSize, 0 );
a07c1212
SC
376 }
377 else if (type == kDragFlavorTypeHFS )
378 {
51d4293d 379 HFSFlavor theFlavor;
e40298d5
JS
380 OSErr err = noErr;
381 CInfoPBRec cat;
6eae1f7d 382
51d4293d 383 wxMacFilename2FSSpec( wxString( dataPtr, *wxConvCurrent ), &theFlavor.fileSpec );
6eae1f7d
DS
384
385 memset( &cat, 0, sizeof(cat) );
e40298d5
JS
386 cat.hFileInfo.ioNamePtr = theFlavor.fileSpec.name;
387 cat.hFileInfo.ioVRefNum = theFlavor.fileSpec.vRefNum;
388 cat.hFileInfo.ioDirID = theFlavor.fileSpec.parID;
389 cat.hFileInfo.ioFDirIndex = 0;
e22ab33a 390 err = PBGetCatInfoSync( &cat );
6eae1f7d 391 if (err == noErr)
e40298d5
JS
392 {
393 theFlavor.fdFlags = cat.hFileInfo.ioFlFndrInfo.fdFlags;
6eae1f7d
DS
394 if (theFlavor.fileSpec.parID == fsRtParID)
395 {
e40298d5
JS
396 theFlavor.fileCreator = 'MACS';
397 theFlavor.fileType = 'disk';
6eae1f7d
DS
398 }
399 else if ((cat.hFileInfo.ioFlAttrib & ioDirMask) != 0)
400 {
e40298d5
JS
401 theFlavor.fileCreator = 'MACS';
402 theFlavor.fileType = 'fold';
6eae1f7d
DS
403 }
404 else
405 {
e40298d5
JS
406 theFlavor.fileCreator = cat.hFileInfo.ioFlFndrInfo.fdCreator;
407 theFlavor.fileType = cat.hFileInfo.ioFlFndrInfo.fdType;
408 }
6eae1f7d 409
51d4293d 410 AddDragItemFlavor( theDrag, theItem, type, &theFlavor, sizeof(theFlavor), 0 );
6eae1f7d 411 }
a07c1212
SC
412 }
413 else
414 {
51d4293d 415 AddDragItemFlavor( theDrag, theItem, type, dataPtr, dataSize, 0 );
a07c1212 416 }
6eae1f7d 417
51d4293d 418 delete [] dataPtr;
a07c1212 419 }
6eae1f7d 420
51d4293d 421 delete [] formats;
6eae1f7d 422
a07c1212 423 dragRegion = NewRgn();
51d4293d 424 RgnHandle tempRgn = NewRgn();
6eae1f7d 425
51d4293d 426 EventRecord* ev = NULL;
6eae1f7d 427
45a0fd37 428#if !TARGET_CARBON // TODO
51d4293d 429 ev = (EventRecord*) wxTheApp->MacGetCurrentEvent();
45a0fd37 430#else
db28a493
SC
431 EventRecord rec;
432 ev = &rec;
433 wxMacConvertEventToRecord( (EventRef) wxTheApp->MacGetCurrentEvent(), &rec );
45a0fd37 434#endif
6eae1f7d 435
51d4293d
DS
436 const short dragRegionOuterBoundary = 10;
437 const short dragRegionInnerBoundary = 9;
6eae1f7d
DS
438
439 SetRectRgn(
51d4293d
DS
440 dragRegion,
441 ev->where.h - dragRegionOuterBoundary,
442 ev->where.v - dragRegionOuterBoundary,
443 ev->where.h + dragRegionOuterBoundary,
444 ev->where.v + dragRegionOuterBoundary );
6eae1f7d
DS
445
446 SetRectRgn(
51d4293d
DS
447 tempRgn,
448 ev->where.h - dragRegionInnerBoundary,
449 ev->where.v - dragRegionInnerBoundary,
450 ev->where.h + dragRegionInnerBoundary,
451 ev->where.v + dragRegionInnerBoundary );
6eae1f7d 452
51d4293d
DS
453 DiffRgn( dragRegion, tempRgn, dragRegion );
454 DisposeRgn( tempRgn );
6eae1f7d 455
e22ab33a
DS
456 // TODO: work with promises in order to return data
457 // only when drag was successfully completed
6eae1f7d 458
e22ab33a
DS
459 gTrackingGlobals.m_currentSource = this;
460 result = TrackDrag( theDrag, ev, dragRegion );
461 DisposeRgn( dragRegion );
462 DisposeDrag( theDrag );
463 gTrackingGlobals.m_currentSource = NULL;
6eae1f7d 464
e22ab33a
DS
465 bool optionDown = GetCurrentKeyModifiers() & optionKey;
466 wxDragResult dndresult = wxDragCopy;
6eae1f7d 467 if ( flags != wxDrag_CopyOnly )
525ae3fe
SC
468 // on mac the option key is always the indication for copy
469 dndresult = optionDown ? wxDragCopy : wxDragMove;
6eae1f7d 470
f43084de 471 return dndresult;
a07c1212
SC
472}
473
da804130
SC
474bool wxDropSource::MacInstallDefaultCursor(wxDragResult effect)
475{
476 const wxCursor& cursor = GetCursor(effect);
6eae1f7d
DS
477 bool result = cursor.Ok();
478
479 if ( result )
e22ab33a 480 cursor.MacInstall();
da804130 481
6eae1f7d 482 return result;
da804130
SC
483}
484
51d4293d 485bool gTrackingGlobalsInstalled = false;
a07c1212
SC
486
487// passing the globals via refcon is not needed by the CFM and later architectures anymore
488// but I'll leave it in there, just in case...
489
6eae1f7d
DS
490pascal OSErr wxMacWindowDragTrackingHandler(
491 DragTrackingMessage theMessage, WindowPtr theWindow,
e22ab33a 492 void *handlerRefCon, DragReference theDrag );
6eae1f7d
DS
493pascal OSErr wxMacWindowDragReceiveHandler(
494 WindowPtr theWindow, void *handlerRefCon,
e22ab33a 495 DragReference theDrag );
a07c1212
SC
496
497void wxMacEnsureTrackingHandlersInstalled()
e9576ca5 498{
6eae1f7d 499 if ( !gTrackingGlobalsInstalled )
a07c1212 500 {
2e91d506 501 OSStatus err;
a07c1212 502
2e91d506
DS
503 err = InstallTrackingHandler( NewDragTrackingHandlerUPP(wxMacWindowDragTrackingHandler), 0L, &gTrackingGlobals );
504 verify_noerr( err );
6eae1f7d 505
2e91d506
DS
506 err = InstallReceiveHandler( NewDragReceiveHandlerUPP(wxMacWindowDragReceiveHandler), 0L, &gTrackingGlobals );
507 verify_noerr( err );
e9576ca5 508
e22ab33a 509 gTrackingGlobalsInstalled = true;
a07c1212
SC
510 }
511}
512
6eae1f7d
DS
513pascal OSErr wxMacWindowDragTrackingHandler(
514 DragTrackingMessage theMessage, WindowPtr theWindow,
e22ab33a 515 void *handlerRefCon, DragReference theDrag )
6eae1f7d 516{
a07c1212 517 MacTrackingGlobals* trackingGlobals = (MacTrackingGlobals*) handlerRefCon;
e22ab33a 518
a07c1212
SC
519 Point mouse, localMouse;
520 DragAttributes attributes;
e22ab33a
DS
521
522 GetDragAttributes( theDrag, &attributes );
523
51d4293d 524 wxTopLevelWindowMac* toplevel = wxFindWinFromMacWindow( theWindow );
f43084de 525
51d4293d 526 bool optionDown = GetCurrentKeyModifiers() & optionKey;
f43084de
JS
527 wxDragResult result = optionDown ? wxDragCopy : wxDragMove;
528
6eae1f7d 529 switch (theMessage)
a07c1212
SC
530 {
531 case kDragTrackingEnterHandler:
a07c1212
SC
532 case kDragTrackingLeaveHandler:
533 break;
6eae1f7d 534
a07c1212 535 case kDragTrackingEnterWindow:
e22ab33a
DS
536 if (trackingGlobals != NULL)
537 {
51d4293d
DS
538 trackingGlobals->m_currentTargetWindow = NULL;
539 trackingGlobals->m_currentTarget = NULL;
e22ab33a 540 }
a07c1212 541 break;
6eae1f7d 542
a07c1212 543 case kDragTrackingInWindow:
e22ab33a
DS
544 if (trackingGlobals == NULL)
545 break;
a07c1212
SC
546 if (toplevel == NULL)
547 break;
548
e22ab33a 549 GetDragMouse( theDrag, &mouse, 0L );
a07c1212 550 localMouse = mouse;
e22ab33a 551 GlobalToLocal( &localMouse );
f43084de 552
a07c1212 553 {
51d4293d
DS
554 wxWindow *win = NULL;
555 ControlPartCode controlPart;
6eae1f7d 556 ControlRef control = wxMacFindControlUnderMouse(
51d4293d 557 toplevel, localMouse, theWindow, &controlPart );
2877659b 558 if ( control )
51d4293d 559 win = wxFindControlFromMacControl( control );
7adabb9a 560 else
51d4293d 561 win = toplevel;
6eae1f7d 562
51d4293d
DS
563 int localx, localy;
564 localx = localMouse.h;
565 localy = localMouse.v;
7adabb9a 566
a07c1212 567 if ( win )
51d4293d 568 win->MacRootWindowToWindow( &localx, &localy );
a07c1212
SC
569 if ( win != trackingGlobals->m_currentTargetWindow )
570 {
571 if ( trackingGlobals->m_currentTargetWindow )
572 {
573 // this window is left
574 if ( trackingGlobals->m_currentTarget )
575 {
6eae1f7d 576 HideDragHilite( theDrag );
876b960a
DS
577 trackingGlobals->m_currentTarget->SetCurrentDrag( theDrag );
578 trackingGlobals->m_currentTarget->OnLeave();
a07c1212 579 trackingGlobals->m_currentTarget = NULL;
876b960a 580 trackingGlobals->m_currentTargetWindow = NULL;
a07c1212
SC
581 }
582 }
6eae1f7d 583
a07c1212
SC
584 if ( win )
585 {
586 // this window is entered
51d4293d
DS
587 trackingGlobals->m_currentTargetWindow = win;
588 trackingGlobals->m_currentTarget = win->GetDropTarget();
a07c1212 589 {
6eae1f7d
DS
590 if ( trackingGlobals->m_currentTarget )
591 {
51d4293d
DS
592 trackingGlobals->m_currentTarget->SetCurrentDrag( theDrag );
593 result = trackingGlobals->m_currentTarget->OnEnter( localx, localy, result );
da804130 594 }
6eae1f7d 595
da804130 596 if ( result != wxDragNone )
a07c1212 597 {
51d4293d 598 int x, y;
6eae1f7d 599
51d4293d
DS
600 x = y = 0;
601 win->MacWindowToRootWindow( &x, &y );
602 RgnHandle hiliteRgn = NewRgn();
603 Rect r = { y, x, y + win->GetSize().y, x + win->GetSize().x };
604 RectRgn( hiliteRgn, &r );
876b960a 605 ShowDragHilite( theDrag, hiliteRgn, true );
51d4293d 606 DisposeRgn( hiliteRgn );
a07c1212
SC
607 }
608 }
609 }
610 }
611 else
612 {
6eae1f7d 613 if ( trackingGlobals->m_currentTarget )
a07c1212 614 {
51d4293d
DS
615 trackingGlobals->m_currentTarget->SetCurrentDrag( theDrag );
616 trackingGlobals->m_currentTarget->OnDragOver( localx, localy, result );
f43084de
JS
617 }
618 }
619
620 // set cursor for OnEnter and OnDragOver
bf473da7 621 if ( trackingGlobals->m_currentSource && !trackingGlobals->m_currentSource->GiveFeedback( result ) )
f43084de 622 {
6eae1f7d 623 if ( !trackingGlobals->m_currentSource->MacInstallDefaultCursor( result ) )
f43084de 624 {
6eae1f7d 625 switch ( result )
f43084de 626 {
2e91d506 627 case wxDragCopy:
eb7f8ac5 628 {
51d4293d
DS
629 wxCursor cursor(wxCURSOR_COPY_ARROW);
630 cursor.MacInstall();
eb7f8ac5 631 }
51d4293d 632 break;
6eae1f7d 633
2e91d506 634 case wxDragMove:
eb7f8ac5 635 {
51d4293d
DS
636 wxCursor cursor(wxCURSOR_ARROW);
637 cursor.MacInstall();
eb7f8ac5 638 }
51d4293d 639 break;
6eae1f7d 640
2e91d506 641 case wxDragNone:
eb7f8ac5 642 {
51d4293d
DS
643 wxCursor cursor(wxCURSOR_NO_ENTRY);
644 cursor.MacInstall();
eb7f8ac5 645 }
51d4293d 646 break;
eb7f8ac5
VZ
647
648 case wxDragError:
649 case wxDragLink:
650 case wxDragCancel:
6eae1f7d 651 default:
eb7f8ac5
VZ
652 // put these here to make gcc happy
653 ;
f43084de 654 }
6eae1f7d 655 }
a07c1212 656 }
7adabb9a 657 }
a07c1212 658 break;
6eae1f7d 659
a07c1212 660 case kDragTrackingLeaveWindow:
e22ab33a
DS
661 if (trackingGlobals == NULL)
662 break;
663
6eae1f7d 664 if (trackingGlobals->m_currentTarget)
a07c1212 665 {
876b960a
DS
666 trackingGlobals->m_currentTarget->SetCurrentDrag( theDrag );
667 trackingGlobals->m_currentTarget->OnLeave();
668 HideDragHilite( theDrag );
669 trackingGlobals->m_currentTarget = NULL;
a07c1212 670 }
876b960a 671 trackingGlobals->m_currentTargetWindow = NULL;
a07c1212 672 break;
6eae1f7d
DS
673
674 default:
675 break;
a07c1212 676 }
6eae1f7d
DS
677
678 return noErr;
a07c1212
SC
679}
680
6eae1f7d
DS
681pascal OSErr wxMacWindowDragReceiveHandler(
682 WindowPtr theWindow,
683 void *handlerRefCon,
684 DragReference theDrag)
685{
686 MacTrackingGlobals* trackingGlobals = (MacTrackingGlobals*)handlerRefCon;
a07c1212
SC
687 if ( trackingGlobals->m_currentTarget )
688 {
51d4293d
DS
689 Point mouse, localMouse;
690 int localx, localy;
6eae1f7d 691
51d4293d
DS
692 trackingGlobals->m_currentTarget->SetCurrentDrag( theDrag );
693 GetDragMouse( theDrag, &mouse, 0L );
a07c1212 694 localMouse = mouse;
51d4293d
DS
695 GlobalToLocal( &localMouse );
696 localx = localMouse.h;
697 localy = localMouse.v;
6eae1f7d
DS
698
699 // TODO : should we use client coordinates?
a07c1212 700 if ( trackingGlobals->m_currentTargetWindow )
51d4293d
DS
701 trackingGlobals->m_currentTargetWindow->MacRootWindowToWindow( &localx, &localy );
702 if ( trackingGlobals->m_currentTarget->OnDrop( localx, localy ) )
a07c1212 703 {
51d4293d 704 bool optionDown = GetCurrentKeyModifiers() & optionKey;
f43084de 705 wxDragResult result = optionDown ? wxDragCopy : wxDragMove;
51d4293d 706 trackingGlobals->m_currentTarget->OnData( localx, localy, result );
a07c1212
SC
707 }
708 }
6eae1f7d
DS
709
710 return noErr;
a07c1212 711}
6eae1f7d 712
03e11df5 713#endif