~registry/dolphin-emu/triforce

« back to all changes in this revision

Viewing changes to Externals/wxWidgets3/src/osx/carbon/dnd.cpp

  • Committer: Sérgio Benjamim
  • Date: 2015-02-13 05:54:40 UTC
  • Revision ID: sergio_br2@yahoo.com.br-20150213055440-ey2rt3sjpy27km78
Dolphin Triforce branch from code.google, commit b957980 (4.0-315).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
///////////////////////////////////////////////////////////////////////////////
 
2
// Name:        src/osx/carbon/dnd.cpp
 
3
// Purpose:     wxDropTarget, wxDropSource implementations
 
4
// Author:      Stefan Csomor
 
5
// Modified by:
 
6
// Created:     1998-01-01
 
7
// Copyright:   (c) 1998 Stefan Csomor
 
8
// Licence:     wxWindows licence
 
9
///////////////////////////////////////////////////////////////////////////////
 
10
 
 
11
#include "wx/wxprec.h"
 
12
 
 
13
#if wxUSE_DRAG_AND_DROP
 
14
 
 
15
#include "wx/dnd.h"
 
16
 
 
17
#ifndef WX_PRECOMP
 
18
    #include "wx/app.h"
 
19
    #include "wx/toplevel.h"
 
20
    #include "wx/gdicmn.h"
 
21
#endif // WX_PRECOMP
 
22
 
 
23
#include "wx/osx/private.h"
 
24
 
 
25
// ----------------------------------------------------------------------------
 
26
// globals
 
27
// ----------------------------------------------------------------------------
 
28
 
 
29
typedef struct
 
30
{
 
31
    wxWindow *m_currentTargetWindow;
 
32
    wxDropTarget *m_currentTarget;
 
33
    wxDropSource *m_currentSource;
 
34
    wxDragResult m_result;
 
35
    int m_flags;
 
36
} MacTrackingGlobals;
 
37
 
 
38
MacTrackingGlobals gTrackingGlobals;
 
39
 
 
40
void wxMacEnsureTrackingHandlersInstalled();
 
41
 
 
42
OSStatus wxMacPromiseKeeper(PasteboardRef WXUNUSED(inPasteboard),
 
43
                            PasteboardItemID WXUNUSED(inItem),
 
44
                            CFStringRef WXUNUSED(inFlavorType),
 
45
                            void * WXUNUSED(inContext))
 
46
{
 
47
    OSStatus  err = noErr;
 
48
 
 
49
    // we might add promises here later, inContext is the wxDropSource*
 
50
 
 
51
    return err;
 
52
}
 
53
 
 
54
wxDropTarget::wxDropTarget( wxDataObject *data )
 
55
            : wxDropTargetBase( data )
 
56
{
 
57
    wxMacEnsureTrackingHandlersInstalled();
 
58
}
 
59
 
 
60
 
 
61
//-------------------------------------------------------------------------
 
62
// wxDropSource
 
63
//-------------------------------------------------------------------------
 
64
 
 
65
wxDropSource::wxDropSource(wxWindow *win,
 
66
                           const wxCursor &cursorCopy,
 
67
                           const wxCursor &cursorMove,
 
68
                           const wxCursor &cursorStop)
 
69
            : wxDropSourceBase(cursorCopy, cursorMove, cursorStop)
 
70
{
 
71
    wxMacEnsureTrackingHandlersInstalled();
 
72
 
 
73
    m_window = win;
 
74
}
 
75
 
 
76
wxDropSource* wxDropSource::GetCurrentDropSource()
 
77
{
 
78
    return gTrackingGlobals.m_currentSource;
 
79
}
 
80
 
 
81
wxDropSource::wxDropSource(wxDataObject& data,
 
82
                           wxWindow *win,
 
83
                           const wxCursor &cursorCopy,
 
84
                           const wxCursor &cursorMove,
 
85
                           const wxCursor &cursorStop)
 
86
            : wxDropSourceBase(cursorCopy, cursorMove, cursorStop)
 
87
{
 
88
    wxMacEnsureTrackingHandlersInstalled();
 
89
 
 
90
    SetData( data );
 
91
    m_window = win;
 
92
}
 
93
 
 
94
wxDragResult wxDropSource::DoDragDrop(int flags)
 
95
{
 
96
    wxASSERT_MSG( m_data, wxT("Drop source: no data") );
 
97
 
 
98
    if ((m_data == NULL) || (m_data->GetFormatCount() == 0))
 
99
        return (wxDragResult)wxDragNone;
 
100
 
 
101
    DragReference theDrag;
 
102
    RgnHandle dragRegion;
 
103
    OSStatus err = noErr;
 
104
    PasteboardRef   pasteboard;
 
105
 
 
106
    // add data to drag
 
107
 
 
108
    err = PasteboardCreate( kPasteboardUniqueName, &pasteboard );
 
109
    if ( err != noErr )
 
110
        return wxDragNone;
 
111
 
 
112
    // we add a dummy promise keeper because of strange messages when linking against carbon debug
 
113
    err = PasteboardSetPromiseKeeper( pasteboard, wxMacPromiseKeeper, this );
 
114
    if ( err != noErr )
 
115
    {
 
116
        CFRelease( pasteboard );
 
117
        return wxDragNone;
 
118
    }
 
119
 
 
120
    err = PasteboardClear( pasteboard );
 
121
    if ( err != noErr )
 
122
    {
 
123
        CFRelease( pasteboard );
 
124
        return wxDragNone;
 
125
    }
 
126
    PasteboardSynchronize( pasteboard );
 
127
 
 
128
    m_data->AddToPasteboard( pasteboard, 1 );
 
129
 
 
130
    if (NewDragWithPasteboard( pasteboard , &theDrag) != noErr)
 
131
    {
 
132
        CFRelease( pasteboard );
 
133
        return wxDragNone;
 
134
    }
 
135
 
 
136
    dragRegion = NewRgn();
 
137
    RgnHandle tempRgn = NewRgn();
 
138
 
 
139
    EventRecord rec;
 
140
    ConvertEventRefToEventRecord(  (EventRef) wxTheApp->MacGetCurrentEvent(), &rec );
 
141
 
 
142
    const short dragRegionOuterBoundary = 10;
 
143
    const short dragRegionInnerBoundary = 9;
 
144
 
 
145
    SetRectRgn(
 
146
        dragRegion,
 
147
        rec.where.h - dragRegionOuterBoundary,
 
148
        rec.where.v  - dragRegionOuterBoundary,
 
149
        rec.where.h + dragRegionOuterBoundary,
 
150
        rec.where.v + dragRegionOuterBoundary );
 
151
 
 
152
    SetRectRgn(
 
153
        tempRgn,
 
154
        rec.where.h - dragRegionInnerBoundary,
 
155
        rec.where.v - dragRegionInnerBoundary,
 
156
        rec.where.h + dragRegionInnerBoundary,
 
157
        rec.where.v + dragRegionInnerBoundary );
 
158
 
 
159
    DiffRgn( dragRegion, tempRgn, dragRegion );
 
160
    DisposeRgn( tempRgn );
 
161
 
 
162
    // TODO: work with promises in order to return data
 
163
    // only when drag was successfully completed
 
164
 
 
165
    gTrackingGlobals.m_currentSource = this;
 
166
    gTrackingGlobals.m_result = wxDragNone;
 
167
    gTrackingGlobals.m_flags = flags;
 
168
 
 
169
    err = TrackDrag( theDrag, &rec, dragRegion );
 
170
 
 
171
    DisposeRgn( dragRegion );
 
172
    DisposeDrag( theDrag );
 
173
    CFRelease( pasteboard );
 
174
    gTrackingGlobals.m_currentSource = NULL;
 
175
 
 
176
    return gTrackingGlobals.m_result;
 
177
}
 
178
 
 
179
bool gTrackingGlobalsInstalled = false;
 
180
 
 
181
// passing the globals via refcon is not needed by the CFM and later architectures anymore
 
182
// but I'll leave it in there, just in case...
 
183
 
 
184
pascal OSErr wxMacWindowDragTrackingHandler(
 
185
    DragTrackingMessage theMessage, WindowPtr theWindow,
 
186
    void *handlerRefCon, DragReference theDrag );
 
187
pascal OSErr wxMacWindowDragReceiveHandler(
 
188
    WindowPtr theWindow, void *handlerRefCon,
 
189
    DragReference theDrag );
 
190
 
 
191
void wxMacEnsureTrackingHandlersInstalled()
 
192
{
 
193
    if ( !gTrackingGlobalsInstalled )
 
194
    {
 
195
        OSStatus err;
 
196
 
 
197
        err = InstallTrackingHandler( NewDragTrackingHandlerUPP(wxMacWindowDragTrackingHandler), 0L, &gTrackingGlobals );
 
198
        verify_noerr( err );
 
199
 
 
200
        err = InstallReceiveHandler( NewDragReceiveHandlerUPP(wxMacWindowDragReceiveHandler), 0L, &gTrackingGlobals );
 
201
        verify_noerr( err );
 
202
 
 
203
        gTrackingGlobalsInstalled = true;
 
204
    }
 
205
}
 
206
 
 
207
pascal OSErr wxMacWindowDragTrackingHandler(
 
208
    DragTrackingMessage theMessage, WindowPtr theWindow,
 
209
    void *handlerRefCon, DragReference theDrag )
 
210
{
 
211
    MacTrackingGlobals* trackingGlobals = (MacTrackingGlobals*) handlerRefCon;
 
212
 
 
213
    Point mouse, localMouse;
 
214
    DragAttributes attributes;
 
215
 
 
216
    GetDragAttributes( theDrag, &attributes );
 
217
    PasteboardRef   pasteboard = 0;
 
218
    GetDragPasteboard( theDrag, &pasteboard );
 
219
    wxNonOwnedWindow* toplevel = wxNonOwnedWindow::GetFromWXWindow( (WXWindow) theWindow );
 
220
 
 
221
    bool optionDown = GetCurrentKeyModifiers() & optionKey;
 
222
    wxDragResult result = optionDown ? wxDragCopy : wxDragMove;
 
223
 
 
224
    switch (theMessage)
 
225
    {
 
226
        case kDragTrackingEnterHandler:
 
227
        case kDragTrackingLeaveHandler:
 
228
            break;
 
229
 
 
230
        case kDragTrackingEnterWindow:
 
231
            if (trackingGlobals != NULL)
 
232
            {
 
233
                trackingGlobals->m_currentTargetWindow = NULL;
 
234
                trackingGlobals->m_currentTarget = NULL;
 
235
            }
 
236
            break;
 
237
 
 
238
        case kDragTrackingInWindow:
 
239
            if (trackingGlobals == NULL)
 
240
                break;
 
241
            if (toplevel == NULL)
 
242
                break;
 
243
 
 
244
            GetDragMouse( theDrag, &mouse, 0L );
 
245
            {
 
246
                int x = mouse.h ;
 
247
                int y = mouse.v ;
 
248
                toplevel->GetNonOwnedPeer()->ScreenToWindow( &x, &y );
 
249
                localMouse.h = x;
 
250
                localMouse.v = y;
 
251
 
 
252
                {
 
253
                    wxWindow *win = NULL;
 
254
                    ControlPartCode controlPart;
 
255
                    ControlRef control = FindControlUnderMouse( localMouse, theWindow, &controlPart );
 
256
                    if ( control )
 
257
                        win = wxFindWindowFromWXWidget( (WXWidget) control );
 
258
                    else
 
259
                        win = toplevel;
 
260
 
 
261
                    int localx, localy;
 
262
                    localx = localMouse.h;
 
263
                    localy = localMouse.v;
 
264
 
 
265
                    if ( win )
 
266
                        win->MacRootWindowToWindow( &localx, &localy );
 
267
                    if ( win != trackingGlobals->m_currentTargetWindow )
 
268
                    {
 
269
                        if ( trackingGlobals->m_currentTargetWindow )
 
270
                        {
 
271
                            // this window is left
 
272
                            if ( trackingGlobals->m_currentTarget )
 
273
                            {
 
274
                                HideDragHilite( theDrag );
 
275
                                trackingGlobals->m_currentTarget->SetCurrentDragPasteboard( pasteboard );
 
276
                                trackingGlobals->m_currentTarget->OnLeave();
 
277
                                trackingGlobals->m_currentTarget = NULL;
 
278
                                trackingGlobals->m_currentTargetWindow = NULL;
 
279
                            }
 
280
                        }
 
281
 
 
282
                        if ( win )
 
283
                        {
 
284
                            // this window is entered
 
285
                            trackingGlobals->m_currentTargetWindow = win;
 
286
                            trackingGlobals->m_currentTarget = win->GetDropTarget();
 
287
                            {
 
288
                                if ( trackingGlobals->m_currentTarget )
 
289
                                {
 
290
                                    trackingGlobals->m_currentTarget->SetCurrentDragPasteboard( pasteboard );
 
291
                                    result = trackingGlobals->m_currentTarget->OnEnter( localx, localy, result );
 
292
                                }
 
293
 
 
294
                                if ( result != wxDragNone )
 
295
                                {
 
296
                                    int x, y;
 
297
 
 
298
                                    x = y = 0;
 
299
                                    win->MacWindowToRootWindow( &x, &y );
 
300
                                    RgnHandle hiliteRgn = NewRgn();
 
301
                                    Rect r = { y, x, y + win->GetSize().y, x + win->GetSize().x };
 
302
                                    RectRgn( hiliteRgn, &r );
 
303
                                    ShowDragHilite( theDrag, hiliteRgn, true );
 
304
                                    DisposeRgn( hiliteRgn );
 
305
                                }
 
306
                            }
 
307
                        }
 
308
                    }
 
309
                    else
 
310
                    {
 
311
                        if ( trackingGlobals->m_currentTarget )
 
312
                        {
 
313
                            trackingGlobals->m_currentTarget->SetCurrentDragPasteboard( pasteboard );
 
314
                            result = trackingGlobals->m_currentTarget->OnDragOver( localx, localy, result );
 
315
                        }
 
316
                    }
 
317
 
 
318
                    // set cursor for OnEnter and OnDragOver
 
319
                    if ( trackingGlobals->m_currentSource && !trackingGlobals->m_currentSource->GiveFeedback( result ) )
 
320
                    {
 
321
                        if ( !trackingGlobals->m_currentSource->MacInstallDefaultCursor( result ) )
 
322
                        {
 
323
                            wxStockCursor cursorID = wxCURSOR_NONE;
 
324
 
 
325
                            switch (result)
 
326
                            {
 
327
                                case wxDragCopy:
 
328
                                    cursorID = wxCURSOR_COPY_ARROW;
 
329
                                    break;
 
330
 
 
331
                                case wxDragMove:
 
332
                                    cursorID = wxCURSOR_ARROW;
 
333
                                    break;
 
334
 
 
335
                                case wxDragNone:
 
336
                                    cursorID = wxCURSOR_NO_ENTRY;
 
337
                                    break;
 
338
 
 
339
                                case wxDragError:
 
340
                                case wxDragLink:
 
341
                                case wxDragCancel:
 
342
                                default:
 
343
                                    // put these here to make gcc happy
 
344
                                    ;
 
345
                            }
 
346
 
 
347
                            if (cursorID != wxCURSOR_NONE)
 
348
                            {
 
349
                                wxCursor cursor( cursorID );
 
350
                                cursor.MacInstall();
 
351
                            }
 
352
                        }
 
353
                    }
 
354
                }
 
355
            }
 
356
            break;
 
357
 
 
358
        case kDragTrackingLeaveWindow:
 
359
            if (trackingGlobals == NULL)
 
360
                break;
 
361
 
 
362
            if (trackingGlobals->m_currentTarget)
 
363
            {
 
364
                trackingGlobals->m_currentTarget->SetCurrentDragPasteboard( pasteboard );
 
365
                trackingGlobals->m_currentTarget->OnLeave();
 
366
                HideDragHilite( theDrag );
 
367
                trackingGlobals->m_currentTarget = NULL;
 
368
            }
 
369
            trackingGlobals->m_currentTargetWindow = NULL;
 
370
            break;
 
371
 
 
372
        default:
 
373
            break;
 
374
    }
 
375
 
 
376
    return noErr;
 
377
}
 
378
 
 
379
pascal OSErr wxMacWindowDragReceiveHandler(
 
380
    WindowPtr theWindow,
 
381
    void *handlerRefCon,
 
382
    DragReference theDrag)
 
383
{
 
384
    MacTrackingGlobals* trackingGlobals = (MacTrackingGlobals*)handlerRefCon;
 
385
    if ( trackingGlobals->m_currentTarget )
 
386
    {
 
387
        Point mouse, localMouse;
 
388
        int localx, localy;
 
389
 
 
390
        PasteboardRef   pasteboard = 0;
 
391
        GetDragPasteboard( theDrag, &pasteboard );
 
392
        trackingGlobals->m_currentTarget->SetCurrentDragPasteboard( pasteboard );
 
393
        GetDragMouse( theDrag, &mouse, 0L );
 
394
        localMouse = mouse;
 
395
        localx = localMouse.h;
 
396
        localy = localMouse.v;
 
397
        wxNonOwnedWindow* tlw = wxNonOwnedWindow::GetFromWXWindow((WXWindow) theWindow);
 
398
        if ( tlw )
 
399
            tlw->GetNonOwnedPeer()->ScreenToWindow( &localx, &localy );
 
400
 
 
401
        // TODO : should we use client coordinates?
 
402
        if ( trackingGlobals->m_currentTargetWindow )
 
403
            trackingGlobals->m_currentTargetWindow->MacRootWindowToWindow( &localx, &localy );
 
404
        if ( trackingGlobals->m_currentTarget->OnDrop( localx, localy ) )
 
405
        {
 
406
            // the option key indicates copy in Mac UI, if it's not pressed do
 
407
            // move by default if it's allowed at all
 
408
            wxDragResult
 
409
                result = !(trackingGlobals->m_flags & wxDrag_AllowMove) ||
 
410
                            (GetCurrentKeyModifiers() & optionKey)
 
411
                            ? wxDragCopy
 
412
                            : wxDragMove;
 
413
            trackingGlobals->m_result =
 
414
                trackingGlobals->m_currentTarget->OnData( localx, localy, result );
 
415
        }
 
416
    }
 
417
 
 
418
    return noErr;
 
419
}
 
420
 
 
421
#endif // wxUSE_DRAG_AND_DROP
 
422