]> git.saurik.com Git - wxWidgets.git/blame - src/mac/carbon/dnd.cpp
Fixup Blit so it can be used with a source that is a wxBufferedDC,
[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
DS
266 HFSFlavor* theFile = (HFSFlavor*)theData;
267 wxString name = wxMacFSSpec2MacFilename( &theFile->fileSpec );
268
670f9935 269 if (!name.empty())
de5e599c 270 filenamesPassed += name + wxT("\n");
e40298d5 271 }
51d4293d 272 break;
de5e599c 273
51d4293d 274 default:
e40298d5 275 m_dataObject->SetData( format, dataSize, theData );
51d4293d 276 break;
e40298d5 277 }
6eae1f7d
DS
278
279 delete [] theData;
a07c1212 280 }
51d4293d 281 break;
e40298d5 282 }
a07c1212 283 }
e40298d5 284 }
de5e599c 285
1832043f 286 if (filenamesPassed.length() > 0)
55f5548f
SC
287 {
288 wxCharBuffer buf = filenamesPassed.fn_str();
de5e599c 289 m_dataObject->SetData( wxDataFormat(wxDF_FILENAME), strlen( buf ), (const char*)buf );
55f5548f 290 }
a07c1212 291 }
6eae1f7d 292
51d4293d 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{
51d4293d 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 320{
51d4293d 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
de5e599c
DS
335 if ((m_data == NULL) || (m_data->GetFormatCount() == 0))
336 return (wxDragResult)wxDragNone;
6eae1f7d 337
a07c1212
SC
338 DragReference theDrag;
339 RgnHandle dragRegion;
de5e599c 340
716d0327 341 if (NewDrag( &theDrag ) != noErr)
51d4293d 342 return wxDragNone;
6eae1f7d 343
a07c1212 344 // add data to drag
51d4293d
DS
345 size_t formatCount = m_data->GetFormatCount();
346 wxDataFormat *formats = new wxDataFormat[formatCount];
347 m_data->GetAllFormats( formats );
348 ItemReference theItem = 1;
6eae1f7d 349
51d4293d 350 for ( size_t i = 0; i < formatCount; ++i )
a07c1212 351 {
51d4293d
DS
352 size_t dataSize = m_data->GetDataSize( formats[i] );
353 Ptr dataPtr = new char[dataSize];
354 m_data->GetDataHere( formats[i], dataPtr );
355 OSType type = formats[i].GetFormatId();
6ac23e25 356 if ( type == 'TEXT' || type == 'utxt' )
a07c1212 357 {
6ac23e25 358 if ( dataSize > 0 )
51d4293d
DS
359 dataSize--;
360 dataPtr[ dataSize ] = 0;
6ac23e25
SC
361 if ( type == 'utxt' )
362 {
363 if ( dataSize > 0 )
51d4293d
DS
364 dataSize--;
365 dataPtr[ dataSize ] = 0;
6ac23e25 366 }
6eae1f7d 367
51d4293d 368 AddDragItemFlavor( theDrag, theItem, type, dataPtr, dataSize, 0 );
a07c1212
SC
369 }
370 else if (type == kDragFlavorTypeHFS )
371 {
51d4293d 372 HFSFlavor theFlavor;
e40298d5
JS
373 OSErr err = noErr;
374 CInfoPBRec cat;
6eae1f7d 375
51d4293d 376 wxMacFilename2FSSpec( wxString( dataPtr, *wxConvCurrent ), &theFlavor.fileSpec );
6eae1f7d
DS
377
378 memset( &cat, 0, sizeof(cat) );
e40298d5
JS
379 cat.hFileInfo.ioNamePtr = theFlavor.fileSpec.name;
380 cat.hFileInfo.ioVRefNum = theFlavor.fileSpec.vRefNum;
381 cat.hFileInfo.ioDirID = theFlavor.fileSpec.parID;
382 cat.hFileInfo.ioFDirIndex = 0;
e22ab33a 383 err = PBGetCatInfoSync( &cat );
6eae1f7d 384 if (err == noErr)
e40298d5
JS
385 {
386 theFlavor.fdFlags = cat.hFileInfo.ioFlFndrInfo.fdFlags;
6eae1f7d
DS
387 if (theFlavor.fileSpec.parID == fsRtParID)
388 {
e40298d5
JS
389 theFlavor.fileCreator = 'MACS';
390 theFlavor.fileType = 'disk';
6eae1f7d
DS
391 }
392 else if ((cat.hFileInfo.ioFlAttrib & ioDirMask) != 0)
393 {
e40298d5
JS
394 theFlavor.fileCreator = 'MACS';
395 theFlavor.fileType = 'fold';
6eae1f7d
DS
396 }
397 else
398 {
e40298d5
JS
399 theFlavor.fileCreator = cat.hFileInfo.ioFlFndrInfo.fdCreator;
400 theFlavor.fileType = cat.hFileInfo.ioFlFndrInfo.fdType;
401 }
6eae1f7d 402
51d4293d 403 AddDragItemFlavor( theDrag, theItem, type, &theFlavor, sizeof(theFlavor), 0 );
6eae1f7d 404 }
a07c1212
SC
405 }
406 else
407 {
51d4293d 408 AddDragItemFlavor( theDrag, theItem, type, dataPtr, dataSize, 0 );
a07c1212 409 }
6eae1f7d 410
51d4293d 411 delete [] dataPtr;
a07c1212 412 }
6eae1f7d 413
51d4293d 414 delete [] formats;
6eae1f7d 415
a07c1212 416 dragRegion = NewRgn();
51d4293d 417 RgnHandle tempRgn = NewRgn();
6eae1f7d 418
51d4293d 419 EventRecord* ev = NULL;
6eae1f7d 420
45a0fd37 421#if !TARGET_CARBON // TODO
51d4293d 422 ev = (EventRecord*) wxTheApp->MacGetCurrentEvent();
45a0fd37 423#else
db28a493
SC
424 EventRecord rec;
425 ev = &rec;
426 wxMacConvertEventToRecord( (EventRef) wxTheApp->MacGetCurrentEvent(), &rec );
45a0fd37 427#endif
6eae1f7d 428
51d4293d
DS
429 const short dragRegionOuterBoundary = 10;
430 const short dragRegionInnerBoundary = 9;
6eae1f7d
DS
431
432 SetRectRgn(
51d4293d
DS
433 dragRegion,
434 ev->where.h - dragRegionOuterBoundary,
435 ev->where.v - dragRegionOuterBoundary,
436 ev->where.h + dragRegionOuterBoundary,
437 ev->where.v + dragRegionOuterBoundary );
6eae1f7d
DS
438
439 SetRectRgn(
51d4293d
DS
440 tempRgn,
441 ev->where.h - dragRegionInnerBoundary,
442 ev->where.v - dragRegionInnerBoundary,
443 ev->where.h + dragRegionInnerBoundary,
444 ev->where.v + dragRegionInnerBoundary );
6eae1f7d 445
51d4293d
DS
446 DiffRgn( dragRegion, tempRgn, dragRegion );
447 DisposeRgn( tempRgn );
6eae1f7d 448
e22ab33a
DS
449 // TODO: work with promises in order to return data
450 // only when drag was successfully completed
6eae1f7d 451
e22ab33a 452 gTrackingGlobals.m_currentSource = this;
716d0327 453 TrackDrag( theDrag, ev, dragRegion );
e22ab33a
DS
454 DisposeRgn( dragRegion );
455 DisposeDrag( theDrag );
456 gTrackingGlobals.m_currentSource = NULL;
6eae1f7d 457
e22ab33a
DS
458 bool optionDown = GetCurrentKeyModifiers() & optionKey;
459 wxDragResult dndresult = wxDragCopy;
6eae1f7d 460 if ( flags != wxDrag_CopyOnly )
525ae3fe
SC
461 // on mac the option key is always the indication for copy
462 dndresult = optionDown ? wxDragCopy : wxDragMove;
6eae1f7d 463
f43084de 464 return dndresult;
a07c1212
SC
465}
466
da804130
SC
467bool wxDropSource::MacInstallDefaultCursor(wxDragResult effect)
468{
469 const wxCursor& cursor = GetCursor(effect);
6eae1f7d
DS
470 bool result = cursor.Ok();
471
472 if ( result )
e22ab33a 473 cursor.MacInstall();
da804130 474
6eae1f7d 475 return result;
da804130
SC
476}
477
51d4293d 478bool gTrackingGlobalsInstalled = false;
a07c1212
SC
479
480// passing the globals via refcon is not needed by the CFM and later architectures anymore
481// but I'll leave it in there, just in case...
482
6eae1f7d
DS
483pascal OSErr wxMacWindowDragTrackingHandler(
484 DragTrackingMessage theMessage, WindowPtr theWindow,
e22ab33a 485 void *handlerRefCon, DragReference theDrag );
6eae1f7d
DS
486pascal OSErr wxMacWindowDragReceiveHandler(
487 WindowPtr theWindow, void *handlerRefCon,
e22ab33a 488 DragReference theDrag );
a07c1212
SC
489
490void wxMacEnsureTrackingHandlersInstalled()
e9576ca5 491{
6eae1f7d 492 if ( !gTrackingGlobalsInstalled )
a07c1212 493 {
2e91d506 494 OSStatus err;
a07c1212 495
2e91d506
DS
496 err = InstallTrackingHandler( NewDragTrackingHandlerUPP(wxMacWindowDragTrackingHandler), 0L, &gTrackingGlobals );
497 verify_noerr( err );
6eae1f7d 498
2e91d506
DS
499 err = InstallReceiveHandler( NewDragReceiveHandlerUPP(wxMacWindowDragReceiveHandler), 0L, &gTrackingGlobals );
500 verify_noerr( err );
e9576ca5 501
e22ab33a 502 gTrackingGlobalsInstalled = true;
a07c1212
SC
503 }
504}
505
6eae1f7d
DS
506pascal OSErr wxMacWindowDragTrackingHandler(
507 DragTrackingMessage theMessage, WindowPtr theWindow,
e22ab33a 508 void *handlerRefCon, DragReference theDrag )
6eae1f7d 509{
a07c1212 510 MacTrackingGlobals* trackingGlobals = (MacTrackingGlobals*) handlerRefCon;
e22ab33a 511
a07c1212
SC
512 Point mouse, localMouse;
513 DragAttributes attributes;
e22ab33a
DS
514
515 GetDragAttributes( theDrag, &attributes );
516
51d4293d 517 wxTopLevelWindowMac* toplevel = wxFindWinFromMacWindow( theWindow );
f43084de 518
51d4293d 519 bool optionDown = GetCurrentKeyModifiers() & optionKey;
f43084de
JS
520 wxDragResult result = optionDown ? wxDragCopy : wxDragMove;
521
6eae1f7d 522 switch (theMessage)
a07c1212
SC
523 {
524 case kDragTrackingEnterHandler:
a07c1212
SC
525 case kDragTrackingLeaveHandler:
526 break;
6eae1f7d 527
a07c1212 528 case kDragTrackingEnterWindow:
e22ab33a
DS
529 if (trackingGlobals != NULL)
530 {
51d4293d
DS
531 trackingGlobals->m_currentTargetWindow = NULL;
532 trackingGlobals->m_currentTarget = NULL;
e22ab33a 533 }
a07c1212 534 break;
6eae1f7d 535
a07c1212 536 case kDragTrackingInWindow:
e22ab33a
DS
537 if (trackingGlobals == NULL)
538 break;
a07c1212
SC
539 if (toplevel == NULL)
540 break;
541
e22ab33a 542 GetDragMouse( theDrag, &mouse, 0L );
a07c1212 543 localMouse = mouse;
e22ab33a 544 GlobalToLocal( &localMouse );
f43084de 545
a07c1212 546 {
51d4293d
DS
547 wxWindow *win = NULL;
548 ControlPartCode controlPart;
6eae1f7d 549 ControlRef control = wxMacFindControlUnderMouse(
51d4293d 550 toplevel, localMouse, theWindow, &controlPart );
2877659b 551 if ( control )
51d4293d 552 win = wxFindControlFromMacControl( control );
7adabb9a 553 else
51d4293d 554 win = toplevel;
6eae1f7d 555
51d4293d
DS
556 int localx, localy;
557 localx = localMouse.h;
558 localy = localMouse.v;
7adabb9a 559
a07c1212 560 if ( win )
51d4293d 561 win->MacRootWindowToWindow( &localx, &localy );
a07c1212
SC
562 if ( win != trackingGlobals->m_currentTargetWindow )
563 {
564 if ( trackingGlobals->m_currentTargetWindow )
565 {
566 // this window is left
567 if ( trackingGlobals->m_currentTarget )
568 {
6eae1f7d 569 HideDragHilite( theDrag );
876b960a
DS
570 trackingGlobals->m_currentTarget->SetCurrentDrag( theDrag );
571 trackingGlobals->m_currentTarget->OnLeave();
a07c1212 572 trackingGlobals->m_currentTarget = NULL;
876b960a 573 trackingGlobals->m_currentTargetWindow = NULL;
a07c1212
SC
574 }
575 }
6eae1f7d 576
a07c1212
SC
577 if ( win )
578 {
579 // this window is entered
51d4293d
DS
580 trackingGlobals->m_currentTargetWindow = win;
581 trackingGlobals->m_currentTarget = win->GetDropTarget();
a07c1212 582 {
6eae1f7d
DS
583 if ( trackingGlobals->m_currentTarget )
584 {
51d4293d
DS
585 trackingGlobals->m_currentTarget->SetCurrentDrag( theDrag );
586 result = trackingGlobals->m_currentTarget->OnEnter( localx, localy, result );
da804130 587 }
6eae1f7d 588
da804130 589 if ( result != wxDragNone )
a07c1212 590 {
51d4293d 591 int x, y;
6eae1f7d 592
51d4293d
DS
593 x = y = 0;
594 win->MacWindowToRootWindow( &x, &y );
595 RgnHandle hiliteRgn = NewRgn();
596 Rect r = { y, x, y + win->GetSize().y, x + win->GetSize().x };
597 RectRgn( hiliteRgn, &r );
876b960a 598 ShowDragHilite( theDrag, hiliteRgn, true );
51d4293d 599 DisposeRgn( hiliteRgn );
a07c1212
SC
600 }
601 }
602 }
603 }
604 else
605 {
6eae1f7d 606 if ( trackingGlobals->m_currentTarget )
a07c1212 607 {
51d4293d
DS
608 trackingGlobals->m_currentTarget->SetCurrentDrag( theDrag );
609 trackingGlobals->m_currentTarget->OnDragOver( localx, localy, result );
f43084de
JS
610 }
611 }
612
613 // set cursor for OnEnter and OnDragOver
bf473da7 614 if ( trackingGlobals->m_currentSource && !trackingGlobals->m_currentSource->GiveFeedback( result ) )
f43084de 615 {
6eae1f7d 616 if ( !trackingGlobals->m_currentSource->MacInstallDefaultCursor( result ) )
f43084de 617 {
de5e599c
DS
618 int cursorID = wxCURSOR_NONE;
619
620 switch (result)
f43084de 621 {
2e91d506 622 case wxDragCopy:
de5e599c 623 cursorID = wxCURSOR_COPY_ARROW;
51d4293d 624 break;
6eae1f7d 625
2e91d506 626 case wxDragMove:
de5e599c 627 cursorID = wxCURSOR_ARROW;
51d4293d 628 break;
6eae1f7d 629
2e91d506 630 case wxDragNone:
de5e599c 631 cursorID = wxCURSOR_NO_ENTRY;
51d4293d 632 break;
eb7f8ac5
VZ
633
634 case wxDragError:
635 case wxDragLink:
636 case wxDragCancel:
6eae1f7d 637 default:
eb7f8ac5
VZ
638 // put these here to make gcc happy
639 ;
f43084de 640 }
de5e599c
DS
641
642 if (cursorID != wxCURSOR_NONE)
643 {
644 wxCursor cursor( cursorID );
645 cursor.MacInstall();
646 }
6eae1f7d 647 }
a07c1212 648 }
7adabb9a 649 }
a07c1212 650 break;
6eae1f7d 651
a07c1212 652 case kDragTrackingLeaveWindow:
e22ab33a
DS
653 if (trackingGlobals == NULL)
654 break;
655
6eae1f7d 656 if (trackingGlobals->m_currentTarget)
a07c1212 657 {
876b960a
DS
658 trackingGlobals->m_currentTarget->SetCurrentDrag( theDrag );
659 trackingGlobals->m_currentTarget->OnLeave();
660 HideDragHilite( theDrag );
661 trackingGlobals->m_currentTarget = NULL;
a07c1212 662 }
876b960a 663 trackingGlobals->m_currentTargetWindow = NULL;
a07c1212 664 break;
6eae1f7d
DS
665
666 default:
667 break;
a07c1212 668 }
6eae1f7d
DS
669
670 return noErr;
a07c1212
SC
671}
672
6eae1f7d
DS
673pascal OSErr wxMacWindowDragReceiveHandler(
674 WindowPtr theWindow,
675 void *handlerRefCon,
676 DragReference theDrag)
677{
678 MacTrackingGlobals* trackingGlobals = (MacTrackingGlobals*)handlerRefCon;
a07c1212
SC
679 if ( trackingGlobals->m_currentTarget )
680 {
51d4293d
DS
681 Point mouse, localMouse;
682 int localx, localy;
6eae1f7d 683
51d4293d
DS
684 trackingGlobals->m_currentTarget->SetCurrentDrag( theDrag );
685 GetDragMouse( theDrag, &mouse, 0L );
a07c1212 686 localMouse = mouse;
51d4293d
DS
687 GlobalToLocal( &localMouse );
688 localx = localMouse.h;
689 localy = localMouse.v;
6eae1f7d
DS
690
691 // TODO : should we use client coordinates?
a07c1212 692 if ( trackingGlobals->m_currentTargetWindow )
51d4293d
DS
693 trackingGlobals->m_currentTargetWindow->MacRootWindowToWindow( &localx, &localy );
694 if ( trackingGlobals->m_currentTarget->OnDrop( localx, localy ) )
a07c1212 695 {
51d4293d 696 bool optionDown = GetCurrentKeyModifiers() & optionKey;
f43084de 697 wxDragResult result = optionDown ? wxDragCopy : wxDragMove;
51d4293d 698 trackingGlobals->m_currentTarget->OnData( localx, localy, result );
a07c1212
SC
699 }
700 }
6eae1f7d
DS
701
702 return noErr;
a07c1212 703}
6eae1f7d 704
03e11df5 705#endif