]> git.saurik.com Git - wxWidgets.git/blame - src/mac/carbon/dnd.cpp
make wxChoice and wxListBox inherit from wxControlWithItems and not wxControl for...
[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;
56d152b2
VZ
40 wxDragResult m_result;
41 int m_flags;
716d0327 42} MacTrackingGlobals;
e9576ca5 43
e22ab33a 44MacTrackingGlobals gTrackingGlobals;
6eae1f7d 45
51d4293d 46void wxMacEnsureTrackingHandlersInstalled();
e9576ca5 47
a07c1212
SC
48//----------------------------------------------------------------------------
49// wxDropTarget
50//----------------------------------------------------------------------------
e9576ca5 51
a07c1212
SC
52wxDropTarget::wxDropTarget( wxDataObject *data )
53 : wxDropTargetBase( data )
e9576ca5 54{
51d4293d 55 wxMacEnsureTrackingHandlersInstalled();
e9576ca5
SC
56}
57
51d4293d
DS
58wxDragResult wxDropTarget::OnDragOver(
59 wxCoord WXUNUSED(x), wxCoord WXUNUSED(y),
60 wxDragResult def )
e9576ca5 61{
a07c1212
SC
62 return CurrentDragHasSupportedFormat() ? def : wxDragNone;
63}
e9576ca5 64
a07c1212 65bool wxDropTarget::OnDrop( wxCoord WXUNUSED(x), wxCoord WXUNUSED(y) )
e9576ca5 66{
876b960a 67 if (m_dataObject == NULL)
6eae1f7d 68 return false;
a07c1212 69
51d4293d 70 return CurrentDragHasSupportedFormat();
e9576ca5
SC
71}
72
51d4293d
DS
73wxDragResult wxDropTarget::OnData(
74 wxCoord WXUNUSED(x), wxCoord WXUNUSED(y),
75 wxDragResult def )
e9576ca5 76{
876b960a 77 if (m_dataObject == NULL)
a07c1212
SC
78 return wxDragNone;
79
80 if (!CurrentDragHasSupportedFormat())
81 return wxDragNone;
82
83 return GetData() ? def : wxDragNone;
e9576ca5
SC
84}
85
6eae1f7d 86bool wxDropTarget::CurrentDragHasSupportedFormat()
e9576ca5 87{
51d4293d 88 bool supported = false;
876b960a 89
a07c1212
SC
90 if ( gTrackingGlobals.m_currentSource != NULL )
91 {
51d4293d 92 wxDataObject* data = gTrackingGlobals.m_currentSource->GetDataObject();
6eae1f7d 93
e40298d5 94 if ( data )
a07c1212 95 {
51d4293d 96 size_t formatcount = data->GetFormatCount();
876b960a 97 wxDataFormat *array = new wxDataFormat[formatcount];
e40298d5 98 data->GetAllFormats( array );
51d4293d 99 for (size_t i = 0; !supported && i < formatcount; i++)
a07c1212 100 {
51d4293d 101 wxDataFormat format = array[i];
6eae1f7d 102 if ( m_dataObject->IsSupported( format ) )
e40298d5 103 {
51d4293d
DS
104 supported = true;
105 break;
e40298d5 106 }
a07c1212 107 }
6eae1f7d 108
51d4293d 109 delete [] array;
a07c1212 110 }
a07c1212 111 }
6eae1f7d 112
a07c1212
SC
113 if ( !supported )
114 {
51d4293d 115 UInt16 items;
6eae1f7d 116 ItemReference theItem;
51d4293d
DS
117 FlavorType theType;
118 UInt16 flavors = 0;
6eae1f7d 119
e22ab33a 120 CountDragItems( (DragReference)m_currentDrag, &items );
876b960a 121 for (UInt16 index = 1; index <= items && !supported; ++index)
e40298d5 122 {
51d4293d 123 flavors = 0;
876b960a
DS
124 GetDragItemReferenceNumber( (DragReference)m_currentDrag, index, &theItem );
125 CountDragItemFlavors( (DragReference)m_currentDrag, theItem, &flavors );
6eae1f7d 126
51d4293d 127 for ( UInt16 flavor = 1; flavor <= flavors; ++flavor )
a07c1212 128 {
716d0327 129 GetFlavorType( (DragReference)m_currentDrag, theItem, flavor, &theType );
e40298d5
JS
130 if ( m_dataObject->IsSupportedFormat( wxDataFormat( theType ) ) )
131 {
51d4293d
DS
132 supported = true;
133 break;
e40298d5 134 }
a07c1212 135 }
e40298d5 136 }
a07c1212 137 }
6eae1f7d 138
51d4293d 139 return supported;
e9576ca5
SC
140}
141
a07c1212 142bool wxDropTarget::GetData()
e9576ca5 143{
e22ab33a 144 if (m_dataObject == NULL)
6eae1f7d
DS
145 return false;
146
a07c1212 147 if ( !CurrentDragHasSupportedFormat() )
2e91d506 148 return false;
6eae1f7d 149
2e91d506 150 bool transferred = false;
a07c1212
SC
151 if ( gTrackingGlobals.m_currentSource != NULL )
152 {
2e91d506 153 wxDataObject* data = gTrackingGlobals.m_currentSource->GetDataObject();
6eae1f7d 154
2e91d506 155 if (data != NULL)
a07c1212 156 {
2e91d506 157 size_t formatcount = data->GetFormatCount();
6eae1f7d 158 wxDataFormat *array = new wxDataFormat[formatcount];
e40298d5 159 data->GetAllFormats( array );
2e91d506 160 for (size_t i = 0; !transferred && i < formatcount; i++)
a07c1212 161 {
2e91d506 162 wxDataFormat format = array[i];
6eae1f7d 163 if ( m_dataObject->IsSupported( format ) )
e40298d5
JS
164 {
165 int size = data->GetDataSize( format );
2e91d506 166 transferred = true;
6eae1f7d
DS
167
168 if (size == 0)
e40298d5 169 {
2e91d506 170 m_dataObject->SetData( format, 0, 0 );
e40298d5
JS
171 }
172 else
173 {
174 char *d = new char[size];
2e91d506
DS
175 data->GetDataHere( format, (void*)d );
176 m_dataObject->SetData( format, size, d );
177 delete [] d;
e40298d5
JS
178 }
179 }
a07c1212 180 }
6eae1f7d 181
2e91d506 182 delete [] array;
e40298d5 183 }
a07c1212 184 }
6eae1f7d 185
a07c1212
SC
186 if ( !transferred )
187 {
51d4293d 188 UInt16 items;
e40298d5 189 OSErr result;
6eae1f7d 190 ItemReference theItem;
51d4293d 191 FlavorType theType;
6eae1f7d 192 FlavorFlags theFlags;
51d4293d 193 UInt16 flavors;
de5e599c 194 wxString filenamesPassed;
6eae1f7d 195
876b960a 196 CountDragItems( (DragReference)m_currentDrag, &items );
6eae1f7d 197 for (UInt16 index = 1; index <= items; ++index)
e40298d5 198 {
51d4293d 199 flavors = 0;
876b960a 200 GetDragItemReferenceNumber( (DragReference)m_currentDrag, index, &theItem );
51d4293d 201 CountDragItemFlavors( (DragReference)m_currentDrag, theItem, &flavors );
e22ab33a 202 wxDataFormat preferredFormat = m_dataObject->GetPreferredFormat( wxDataObject::Set );
51d4293d 203 bool hasPreferredFormat = false;
6eae1f7d 204
de5e599c 205 for (UInt16 flavor = 1; flavor <= flavors; ++flavor)
a07c1212 206 {
876b960a
DS
207 result = GetFlavorType( (DragReference)m_currentDrag, theItem, flavor, &theType );
208 wxDataFormat format( theType );
de5e599c 209 if (preferredFormat == format)
6db6bfd1 210 {
51d4293d
DS
211 hasPreferredFormat = true;
212 break;
6db6bfd1
SC
213 }
214 }
6eae1f7d 215
de5e599c 216 for (UInt16 flavor = 1; flavor <= flavors; ++flavor)
6db6bfd1 217 {
e22ab33a 218 result = GetFlavorType( (DragReference)m_currentDrag, theItem, flavor, &theType );
51d4293d 219 wxDataFormat format( theType );
de5e599c 220 if ((hasPreferredFormat && format == preferredFormat)
876b960a 221 || (!hasPreferredFormat && m_dataObject->IsSupportedFormat( format )))
e40298d5 222 {
876b960a 223 result = GetFlavorFlags( (DragReference)m_currentDrag, theItem, theType, &theFlags );
6eae1f7d 224 if (result == noErr)
a07c1212 225 {
51d4293d
DS
226 Size dataSize;
227 Ptr theData;
6eae1f7d 228
876b960a 229 GetFlavorDataSize( (DragReference)m_currentDrag, theItem, theType, &dataSize );
de5e599c 230 if (theType == kScrapFlavorTypeText)
e40298d5 231 {
e22ab33a
DS
232 // this increment is only valid for allocating:
233 // on the next GetFlavorData call it is reset again to the original value
51d4293d 234 dataSize++;
e40298d5 235 }
de5e599c 236 else if (theType == kScrapFlavorTypeUnicode)
2b2832ef 237 {
e22ab33a
DS
238 // this increment is only valid for allocating:
239 // on the next GetFlavorData call it is reset again to the original value
51d4293d
DS
240 dataSize++;
241 dataSize++;
2b2832ef 242 }
6eae1f7d 243
2e91d506
DS
244 if (dataSize > 0)
245 theData = new char[dataSize];
246 else
247 theData = NULL;
876b960a 248
de5e599c 249 GetFlavorData( (DragReference)m_currentDrag, theItem, theType, (void*)theData, &dataSize, 0L );
51d4293d 250 switch (theType)
2b2832ef 251 {
51d4293d
DS
252 case kScrapFlavorTypeText:
253 theData[dataSize] = 0;
254 m_dataObject->SetData( wxDataFormat(wxDF_TEXT), dataSize, theData );
255 break;
256
63c6e6c8 257#if wxUSE_UNICODE
51d4293d 258 case kScrapFlavorTypeUnicode:
876b960a 259 theData[dataSize + 0] =
51d4293d
DS
260 theData[dataSize + 1] = 0;
261 m_dataObject->SetData( wxDataFormat(wxDF_UNICODETEXT), dataSize, theData );
262 break;
63c6e6c8 263#endif
63c6e6c8 264
51d4293d 265 case kDragFlavorTypeHFS:
de5e599c 266 if (theData != NULL)
e40298d5 267 {
de5e599c 268 HFSFlavor* theFile = (HFSFlavor*)theData;
4913272f 269#ifndef __LP64__
de5e599c
DS
270 wxString name = wxMacFSSpec2MacFilename( &theFile->fileSpec );
271
670f9935 272 if (!name.empty())
de5e599c 273 filenamesPassed += name + wxT("\n");
4913272f 274#endif
e40298d5 275 }
51d4293d 276 break;
de5e599c 277
51d4293d 278 default:
e40298d5 279 m_dataObject->SetData( format, dataSize, theData );
51d4293d 280 break;
e40298d5 281 }
6eae1f7d
DS
282
283 delete [] theData;
a07c1212 284 }
51d4293d 285 break;
e40298d5 286 }
a07c1212 287 }
e40298d5 288 }
de5e599c 289
1832043f 290 if (filenamesPassed.length() > 0)
55f5548f
SC
291 {
292 wxCharBuffer buf = filenamesPassed.fn_str();
de5e599c 293 m_dataObject->SetData( wxDataFormat(wxDF_FILENAME), strlen( buf ), (const char*)buf );
55f5548f 294 }
a07c1212 295 }
6eae1f7d 296
51d4293d 297 return true;
e9576ca5
SC
298}
299
300//-------------------------------------------------------------------------
301// wxDropSource
302//-------------------------------------------------------------------------
303
304//-----------------------------------------------------------------------------
305// drag request
306
a07c1212 307wxDropSource::wxDropSource(wxWindow *win,
da804130
SC
308 const wxCursor &cursorCopy,
309 const wxCursor &cursorMove,
310 const wxCursor &cursorStop)
311 : wxDropSourceBase(cursorCopy, cursorMove, cursorStop)
e9576ca5 312{
51d4293d 313 wxMacEnsureTrackingHandlersInstalled();
e22ab33a 314
a07c1212
SC
315 m_window = win;
316}
e9576ca5 317
a07c1212
SC
318wxDropSource::wxDropSource(wxDataObject& data,
319 wxWindow *win,
da804130
SC
320 const wxCursor &cursorCopy,
321 const wxCursor &cursorMove,
322 const wxCursor &cursorStop)
323 : wxDropSourceBase(cursorCopy, cursorMove, cursorStop)
a07c1212 324{
51d4293d 325 wxMacEnsureTrackingHandlersInstalled();
e22ab33a 326
a07c1212
SC
327 SetData( data );
328 m_window = win;
329}
e9576ca5 330
a07c1212 331wxDropSource::~wxDropSource()
e9576ca5 332{
a07c1212 333}
e9576ca5 334
525ae3fe 335wxDragResult wxDropSource::DoDragDrop(int flags)
e9576ca5 336{
a07c1212 337 wxASSERT_MSG( m_data, wxT("Drop source: no data") );
6eae1f7d 338
de5e599c
DS
339 if ((m_data == NULL) || (m_data->GetFormatCount() == 0))
340 return (wxDragResult)wxDragNone;
6eae1f7d 341
a07c1212
SC
342 DragReference theDrag;
343 RgnHandle dragRegion;
de5e599c 344
716d0327 345 if (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 );
4913272f 352 ItemReference theItem = (ItemReference) 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 377 OSErr err = noErr;
4913272f 378#ifndef __LP64__
e40298d5 379 CInfoPBRec cat;
6eae1f7d 380
51d4293d 381 wxMacFilename2FSSpec( wxString( dataPtr, *wxConvCurrent ), &theFlavor.fileSpec );
6eae1f7d
DS
382
383 memset( &cat, 0, sizeof(cat) );
e40298d5
JS
384 cat.hFileInfo.ioNamePtr = theFlavor.fileSpec.name;
385 cat.hFileInfo.ioVRefNum = theFlavor.fileSpec.vRefNum;
386 cat.hFileInfo.ioDirID = theFlavor.fileSpec.parID;
387 cat.hFileInfo.ioFDirIndex = 0;
e22ab33a 388 err = PBGetCatInfoSync( &cat );
4913272f
SC
389#endif
390 if (err == noErr)
e40298d5 391 {
4913272f 392#ifndef __LP64__
e40298d5 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 }
4913272f 409#endif
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 459 gTrackingGlobals.m_currentSource = this;
56d152b2
VZ
460 gTrackingGlobals.m_result = wxDragNone;
461 gTrackingGlobals.m_flags = flags;
462
716d0327 463 TrackDrag( theDrag, ev, dragRegion );
e22ab33a
DS
464 DisposeRgn( dragRegion );
465 DisposeDrag( theDrag );
466 gTrackingGlobals.m_currentSource = NULL;
6eae1f7d 467
56d152b2 468 return gTrackingGlobals.m_result;
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;
4913272f 548 wxMacGlobalToLocal( theWindow, &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 {
4913272f 573#ifndef __LP64__
6eae1f7d 574 HideDragHilite( theDrag );
4913272f 575#endif
876b960a
DS
576 trackingGlobals->m_currentTarget->SetCurrentDrag( theDrag );
577 trackingGlobals->m_currentTarget->OnLeave();
a07c1212 578 trackingGlobals->m_currentTarget = NULL;
876b960a 579 trackingGlobals->m_currentTargetWindow = NULL;
a07c1212
SC
580 }
581 }
6eae1f7d 582
a07c1212
SC
583 if ( win )
584 {
585 // this window is entered
51d4293d
DS
586 trackingGlobals->m_currentTargetWindow = win;
587 trackingGlobals->m_currentTarget = win->GetDropTarget();
a07c1212 588 {
6eae1f7d
DS
589 if ( trackingGlobals->m_currentTarget )
590 {
51d4293d
DS
591 trackingGlobals->m_currentTarget->SetCurrentDrag( theDrag );
592 result = trackingGlobals->m_currentTarget->OnEnter( localx, localy, result );
da804130 593 }
6eae1f7d 594
da804130 595 if ( result != wxDragNone )
a07c1212 596 {
51d4293d 597 int x, y;
6eae1f7d 598
51d4293d
DS
599 x = y = 0;
600 win->MacWindowToRootWindow( &x, &y );
601 RgnHandle hiliteRgn = NewRgn();
602 Rect r = { y, x, y + win->GetSize().y, x + win->GetSize().x };
603 RectRgn( hiliteRgn, &r );
4913272f 604#ifndef __LP64__
876b960a 605 ShowDragHilite( theDrag, hiliteRgn, true );
4913272f 606#endif
51d4293d 607 DisposeRgn( hiliteRgn );
a07c1212
SC
608 }
609 }
610 }
611 }
612 else
613 {
6eae1f7d 614 if ( trackingGlobals->m_currentTarget )
a07c1212 615 {
51d4293d
DS
616 trackingGlobals->m_currentTarget->SetCurrentDrag( theDrag );
617 trackingGlobals->m_currentTarget->OnDragOver( localx, localy, result );
f43084de
JS
618 }
619 }
620
621 // set cursor for OnEnter and OnDragOver
bf473da7 622 if ( trackingGlobals->m_currentSource && !trackingGlobals->m_currentSource->GiveFeedback( result ) )
f43084de 623 {
6eae1f7d 624 if ( !trackingGlobals->m_currentSource->MacInstallDefaultCursor( result ) )
f43084de 625 {
de5e599c
DS
626 int cursorID = wxCURSOR_NONE;
627
628 switch (result)
f43084de 629 {
2e91d506 630 case wxDragCopy:
de5e599c 631 cursorID = wxCURSOR_COPY_ARROW;
51d4293d 632 break;
6eae1f7d 633
2e91d506 634 case wxDragMove:
de5e599c 635 cursorID = wxCURSOR_ARROW;
51d4293d 636 break;
6eae1f7d 637
2e91d506 638 case wxDragNone:
de5e599c 639 cursorID = wxCURSOR_NO_ENTRY;
51d4293d 640 break;
eb7f8ac5
VZ
641
642 case wxDragError:
643 case wxDragLink:
644 case wxDragCancel:
6eae1f7d 645 default:
eb7f8ac5
VZ
646 // put these here to make gcc happy
647 ;
f43084de 648 }
de5e599c
DS
649
650 if (cursorID != wxCURSOR_NONE)
651 {
652 wxCursor cursor( cursorID );
653 cursor.MacInstall();
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();
4913272f 668#ifndef __LP64__
876b960a 669 HideDragHilite( theDrag );
4913272f 670#endif
876b960a 671 trackingGlobals->m_currentTarget = NULL;
a07c1212 672 }
876b960a 673 trackingGlobals->m_currentTargetWindow = NULL;
a07c1212 674 break;
6eae1f7d
DS
675
676 default:
677 break;
a07c1212 678 }
6eae1f7d
DS
679
680 return noErr;
a07c1212
SC
681}
682
6eae1f7d
DS
683pascal OSErr wxMacWindowDragReceiveHandler(
684 WindowPtr theWindow,
685 void *handlerRefCon,
686 DragReference theDrag)
687{
688 MacTrackingGlobals* trackingGlobals = (MacTrackingGlobals*)handlerRefCon;
a07c1212
SC
689 if ( trackingGlobals->m_currentTarget )
690 {
51d4293d
DS
691 Point mouse, localMouse;
692 int localx, localy;
6eae1f7d 693
51d4293d
DS
694 trackingGlobals->m_currentTarget->SetCurrentDrag( theDrag );
695 GetDragMouse( theDrag, &mouse, 0L );
a07c1212 696 localMouse = mouse;
4913272f 697 wxMacGlobalToLocal( theWindow, &localMouse );
51d4293d
DS
698 localx = localMouse.h;
699 localy = localMouse.v;
6eae1f7d
DS
700
701 // TODO : should we use client coordinates?
a07c1212 702 if ( trackingGlobals->m_currentTargetWindow )
51d4293d
DS
703 trackingGlobals->m_currentTargetWindow->MacRootWindowToWindow( &localx, &localy );
704 if ( trackingGlobals->m_currentTarget->OnDrop( localx, localy ) )
a07c1212 705 {
56d152b2
VZ
706 // the option key indicates copy in Mac UI, if it's not pressed do
707 // move by default if it's allowed at all
708 wxDragResult
709 result = !(trackingGlobals->m_flags & wxDrag_AllowMove) ||
710 (GetCurrentKeyModifiers() & optionKey)
711 ? wxDragCopy
712 : wxDragMove;
713 trackingGlobals->m_result =
714 trackingGlobals->m_currentTarget->OnData( localx, localy, result );
a07c1212
SC
715 }
716 }
6eae1f7d
DS
717
718 return noErr;
a07c1212 719}
6eae1f7d 720
56d152b2
VZ
721#endif // wxUSE_DRAG_AND_DROP
722