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