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