From 7dab9892b3ad296d3d3664576f1d590f5fddf6bc Mon Sep 17 00:00:00 2001 From: Kevin Ollivier Date: Wed, 3 Feb 2010 05:31:31 +0000 Subject: [PATCH] Refactor DND code into Carbon and Cocoa parts, and provide a basic OS X Cocoa implementation for wxDropSource::DoDragDrop. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@63365 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- build/bakefiles/files.bkl | 4 +- src/osx/carbon/dnd.cpp | 92 ++---------------- src/osx/cocoa/dnd.mm | 194 ++++++++++++++++++++++++++++++++++++++ src/osx/cocoa/evtloop.mm | 2 + src/osx/dnd_osx.cpp | 87 +++++++++++++++++ 5 files changed, 296 insertions(+), 83 deletions(-) create mode 100644 src/osx/cocoa/dnd.mm create mode 100644 src/osx/dnd_osx.cpp diff --git a/build/bakefiles/files.bkl b/build/bakefiles/files.bkl index 5b0caa525c..9b26b772bd 100644 --- a/build/bakefiles/files.bkl +++ b/build/bakefiles/files.bkl @@ -2236,6 +2236,7 @@ IMPORTANT: please read docs/tech/tn0016.txt before modifying this file! src/osx/checklst_osx.cpp src/osx/choice_osx.cpp src/osx/combobox_osx.cpp + src/osx/dnd_osx.cpp src/osx/gauge_osx.cpp src/osx/listbox_osx.cpp src/osx/menu_osx.cpp @@ -2277,7 +2278,6 @@ IMPORTANT: please read docs/tech/tn0016.txt before modifying this file! src/osx/carbon/dcscreen.cpp src/osx/core/glgrab.cpp src/osx/carbon/graphics.cpp - src/osx/carbon/dnd.cpp src/osx/carbon/font.cpp src/osx/carbon/frame.cpp src/osx/carbon/mdi.cpp @@ -2317,6 +2317,7 @@ IMPORTANT: please read docs/tech/tn0016.txt before modifying this file! src/osx/carbon/colordlg.cpp src/osx/carbon/dialog.cpp src/osx/carbon/dirdlg.cpp + src/osx/carbon/dnd.cpp src/osx/carbon/evtloop.cpp src/osx/carbon/filedlg.cpp src/osx/carbon/gauge.cpp @@ -2473,6 +2474,7 @@ IMPORTANT: please read docs/tech/tn0016.txt before modifying this file! src/osx/cocoa/combobox.mm src/osx/cocoa/dialog.mm src/osx/cocoa/dirdlg.mm + src/osx/cocoa/dnd.mm src/osx/cocoa/evtloop.mm src/osx/cocoa/filedlg.mm src/osx/cocoa/gauge.mm diff --git a/src/osx/carbon/dnd.cpp b/src/osx/carbon/dnd.cpp index 5ece3e0d09..b46737b0aa 100644 --- a/src/osx/carbon/dnd.cpp +++ b/src/osx/carbon/dnd.cpp @@ -40,48 +40,22 @@ MacTrackingGlobals gTrackingGlobals; void wxMacEnsureTrackingHandlersInstalled(); -//---------------------------------------------------------------------------- -// wxDropTarget -//---------------------------------------------------------------------------- - -wxDropTarget::wxDropTarget( wxDataObject *data ) - : wxDropTargetBase( data ) -{ - wxMacEnsureTrackingHandlersInstalled(); -} - -wxDragResult wxDropTarget::OnDragOver( - wxCoord WXUNUSED(x), wxCoord WXUNUSED(y), - wxDragResult def ) -{ - return CurrentDragHasSupportedFormat() ? def : wxDragNone; -} - -wxDataFormat wxDropTarget::GetMatchingPair() +OSStatus wxMacPromiseKeeper(PasteboardRef WXUNUSED(inPasteboard), + PasteboardItemID WXUNUSED(inItem), + CFStringRef WXUNUSED(inFlavorType), + void * WXUNUSED(inContext)) { - wxFAIL_MSG("wxDropTarget::GetMatchingPair() not implemented in src/osx/carbon/dnd.cpp"); - return wxDF_INVALID; -} + OSStatus err = noErr; -bool wxDropTarget::OnDrop( wxCoord WXUNUSED(x), wxCoord WXUNUSED(y) ) -{ - if (m_dataObject == NULL) - return false; + // we might add promises here later, inContext is the wxDropSource* - return CurrentDragHasSupportedFormat(); + return err; } -wxDragResult wxDropTarget::OnData( - wxCoord WXUNUSED(x), wxCoord WXUNUSED(y), - wxDragResult def ) +wxDropTarget::wxDropTarget( wxDataObject *data ) + : wxDropTargetBase( data ) { - if (m_dataObject == NULL) - return wxDragNone; - - if (!CurrentDragHasSupportedFormat()) - return wxDragNone; - - return GetData() ? def : wxDragNone; + wxMacEnsureTrackingHandlersInstalled(); } bool wxDropTarget::CurrentDragHasSupportedFormat() @@ -177,9 +151,6 @@ bool wxDropTarget::GetData() // wxDropSource //------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -// drag request - wxDropSource::wxDropSource(wxWindow *win, const wxCursor &cursorCopy, const wxCursor &cursorMove, @@ -204,22 +175,6 @@ wxDropSource::wxDropSource(wxDataObject& data, m_window = win; } -wxDropSource::~wxDropSource() -{ -} - -OSStatus wxMacPromiseKeeper(PasteboardRef WXUNUSED(inPasteboard), - PasteboardItemID WXUNUSED(inItem), - CFStringRef WXUNUSED(inFlavorType), - void * WXUNUSED(inContext)) -{ - OSStatus err = noErr; - - // we might add promises here later, inContext is the wxDropSource* - - return err; -} - wxDragResult wxDropSource::DoDragDrop(int flags) { wxASSERT_MSG( m_data, wxT("Drop source: no data") ); @@ -227,7 +182,6 @@ wxDragResult wxDropSource::DoDragDrop(int flags) if ((m_data == NULL) || (m_data->GetFormatCount() == 0)) return (wxDragResult)wxDragNone; -#if wxOSX_USE_CARBON DragReference theDrag; RgnHandle dragRegion; OSStatus err = noErr; @@ -302,41 +256,24 @@ wxDragResult wxDropSource::DoDragDrop(int flags) DisposeDrag( theDrag ); CFRelease( pasteboard ); gTrackingGlobals.m_currentSource = NULL; -#else - wxUnusedVar(flags); -#endif return gTrackingGlobals.m_result; } -bool wxDropSource::MacInstallDefaultCursor(wxDragResult effect) -{ - const wxCursor& cursor = GetCursor(effect); - bool result = cursor.Ok(); - - if ( result ) - cursor.MacInstall(); - - return result; -} - bool gTrackingGlobalsInstalled = false; // passing the globals via refcon is not needed by the CFM and later architectures anymore // but I'll leave it in there, just in case... -#if wxOSX_USE_CARBON pascal OSErr wxMacWindowDragTrackingHandler( DragTrackingMessage theMessage, WindowPtr theWindow, void *handlerRefCon, DragReference theDrag ); pascal OSErr wxMacWindowDragReceiveHandler( WindowPtr theWindow, void *handlerRefCon, DragReference theDrag ); -#endif void wxMacEnsureTrackingHandlersInstalled() { -#if wxOSX_USE_CARBON if ( !gTrackingGlobalsInstalled ) { OSStatus err; @@ -349,10 +286,8 @@ void wxMacEnsureTrackingHandlersInstalled() gTrackingGlobalsInstalled = true; } -#endif } -#if wxOSX_USE_CARBON pascal OSErr wxMacWindowDragTrackingHandler( DragTrackingMessage theMessage, WindowPtr theWindow, void *handlerRefCon, DragReference theDrag ) @@ -420,9 +355,7 @@ pascal OSErr wxMacWindowDragTrackingHandler( // this window is left if ( trackingGlobals->m_currentTarget ) { -#ifndef __LP64__ HideDragHilite( theDrag ); -#endif trackingGlobals->m_currentTarget->SetCurrentDragPasteboard( pasteboard ); trackingGlobals->m_currentTarget->OnLeave(); trackingGlobals->m_currentTarget = NULL; @@ -451,9 +384,7 @@ pascal OSErr wxMacWindowDragTrackingHandler( RgnHandle hiliteRgn = NewRgn(); Rect r = { y, x, y + win->GetSize().y, x + win->GetSize().x }; RectRgn( hiliteRgn, &r ); -#ifndef __LP64__ ShowDragHilite( theDrag, hiliteRgn, true ); -#endif DisposeRgn( hiliteRgn ); } } @@ -516,9 +447,7 @@ pascal OSErr wxMacWindowDragTrackingHandler( { trackingGlobals->m_currentTarget->SetCurrentDragPasteboard( pasteboard ); trackingGlobals->m_currentTarget->OnLeave(); -#ifndef __LP64__ HideDragHilite( theDrag ); -#endif trackingGlobals->m_currentTarget = NULL; } trackingGlobals->m_currentTargetWindow = NULL; @@ -572,7 +501,6 @@ pascal OSErr wxMacWindowDragReceiveHandler( return noErr; } -#endif #endif // wxUSE_DRAG_AND_DROP diff --git a/src/osx/cocoa/dnd.mm b/src/osx/cocoa/dnd.mm new file mode 100644 index 0000000000..4429d80708 --- /dev/null +++ b/src/osx/cocoa/dnd.mm @@ -0,0 +1,194 @@ +/////////////////////////////////////////////////////////////////////////////// +// Name: src/osx/cocoa/dnd.mm +// Purpose: wxDropTarget, wxDropSource implementations +// Author: Stefan Csomor +// Modified by: +// Created: 1998-01-01 +// RCS-ID: $Id: dnd.cpp 61724 2009-08-21 10:41:26Z VZ $ +// Copyright: (c) 1998 Stefan Csomor +// Licence: wxWindows licence +/////////////////////////////////////////////////////////////////////////////// + +#include "wx/wxprec.h" + +#if wxUSE_DRAG_AND_DROP + +#include "wx/dnd.h" + +#ifndef WX_PRECOMP + #include "wx/app.h" + #include "wx/evtloop.h" + #include "wx/toplevel.h" + #include "wx/gdicmn.h" + #include "wx/wx.h" +#endif // WX_PRECOMP + +#include +#include "wx/osx/private.h" + +wxDragResult NSDragOperationToWxDragResult(NSDragOperation code) +{ + switch (code) + { + case NSDragOperationCopy: + return wxDragCopy; + case NSDragOperationMove: + return wxDragMove; + case NSDragOperationLink: + return wxDragLink; + case NSDragOperationNone: + return wxDragNone; + default: + wxFAIL_MSG("Unexpected result code"); + } +} + +@interface DropSourceDelegate : NSObject +{ + BOOL dragFinished; + int resultCode; + wxDropSource* impl; +} + +- (void)setImplementation: (wxDropSource *)dropSource; +- (BOOL)finished; +- (NSDragOperation)code; +- (void)draggedImage:(NSImage *)anImage endedAt:(NSPoint)aPoint operation:(NSDragOperation)operation; +@end + +@implementation DropSourceDelegate + +- (id)init +{ + [super init]; + dragFinished = NO; + resultCode = NSDragOperationNone; + impl = 0; + return self; +} + +- (void)setImplementation: (wxDropSource *)dropSource +{ + impl = dropSource; +} + +- (BOOL)finished +{ + return dragFinished; +} + +- (NSDragOperation)code +{ + return resultCode; +} + +- (void)draggedImage:(NSImage *)anImage endedAt:(NSPoint)aPoint operation:(NSDragOperation)operation +{ + resultCode = operation; + dragFinished = YES; +} + +@end + +wxDropTarget::wxDropTarget( wxDataObject *data ) + : wxDropTargetBase( data ) +{ + +} + +bool wxDropTarget::CurrentDragHasSupportedFormat() +{ + if (m_dataObject == NULL) + return false; + + return m_dataObject->HasDataInPasteboard( m_currentDragPasteboard ); +} + +bool wxDropTarget::GetData() +{ + if (m_dataObject == NULL) + return false; + + if ( !CurrentDragHasSupportedFormat() ) + return false; + + return m_dataObject->GetFromPasteboard( m_currentDragPasteboard ); +} + +//------------------------------------------------------------------------- +// wxDropSource +//------------------------------------------------------------------------- + +wxDropSource::wxDropSource(wxWindow *win, + const wxCursor &cursorCopy, + const wxCursor &cursorMove, + const wxCursor &cursorStop) + : wxDropSourceBase(cursorCopy, cursorMove, cursorStop) +{ + m_window = win; +} + +wxDropSource::wxDropSource(wxDataObject& data, + wxWindow *win, + const wxCursor &cursorCopy, + const wxCursor &cursorMove, + const wxCursor &cursorStop) + : wxDropSourceBase(cursorCopy, cursorMove, cursorStop) +{ + SetData( data ); + m_window = win; +} + +wxDragResult wxDropSource::DoDragDrop(int flags) +{ + wxASSERT_MSG( m_data, wxT("Drop source: no data") ); + + wxDragResult result = wxDragNone; + if ((m_data == NULL) || (m_data->GetFormatCount() == 0)) + return result; + + NSView* view = m_window->GetPeer()->GetWXWidget(); + if (view) + { + NSPasteboard *pboard; + + pboard = [NSPasteboard pasteboardWithName:NSDragPboard]; + + OSStatus err = noErr; + PasteboardRef pboardRef; + PasteboardCreate((CFStringRef)[pboard name], &pboardRef); + + err = PasteboardClear( pboardRef ); + if ( err != noErr ) + { + CFRelease( pboardRef ); + return wxDragNone; + } + PasteboardSynchronize( pboardRef ); + + m_data->AddToPasteboard( pboardRef, 1 ); + + NSEvent* theEvent = (NSEvent*)wxTheApp->MacGetCurrentEvent(); + wxASSERT_MSG(theEvent, "DoDragDrop must be called in response to a mouse down or drag event."); + + NSImage* image = [[NSImage alloc] initWithSize: NSMakeSize(16,16)]; + DropSourceDelegate* delegate = [[DropSourceDelegate alloc] init]; + [delegate setImplementation: this]; + [view dragImage:image at:NSMakePoint(0.0, 16.0) offset:NSMakeSize(0.0,0.0) + event: theEvent pasteboard: pboard source:delegate slideBack: NO]; + + wxEventLoopBase * const loop = wxEventLoop::GetActive(); + while ( ![delegate finished] ) + loop->Dispatch(); + + result = NSDragOperationToWxDragResult([delegate code]); + [delegate release]; + [image release]; + } + + + return result; +} + +#endif // wxUSE_DRAG_AND_DROP + diff --git a/src/osx/cocoa/evtloop.mm b/src/osx/cocoa/evtloop.mm index 4798214f02..ecd63279c2 100644 --- a/src/osx/cocoa/evtloop.mm +++ b/src/osx/cocoa/evtloop.mm @@ -121,6 +121,8 @@ bool wxGUIEventLoop::Dispatch() inMode:NSDefaultRunLoopMode dequeue: YES]) { + if (wxTheApp) + wxTheApp->MacSetCurrentEvent(event, NULL); m_sleepTime = 0.0; [NSApp sendEvent: event]; } diff --git a/src/osx/dnd_osx.cpp b/src/osx/dnd_osx.cpp new file mode 100644 index 0000000000..c19bf6eb8f --- /dev/null +++ b/src/osx/dnd_osx.cpp @@ -0,0 +1,87 @@ +/////////////////////////////////////////////////////////////////////////////// +// Name: src/osx/dnd_osx.cpp +// Purpose: Mac common wxDropTarget, wxDropSource implementations +// Author: Stefan Csomor +// Modified by: +// Created: 1998-01-01 +// RCS-ID: $Id: dnd.cpp 61724 2009-08-21 10:41:26Z VZ $ +// Copyright: (c) 1998 Stefan Csomor +// Licence: wxWindows licence +/////////////////////////////////////////////////////////////////////////////// + +#include "wx/wxprec.h" + +#if wxUSE_DRAG_AND_DROP + +#include "wx/dnd.h" + +#ifndef WX_PRECOMP + #include "wx/app.h" + #include "wx/toplevel.h" + #include "wx/gdicmn.h" +#endif // WX_PRECOMP + +#include "wx/osx/private.h" + +//---------------------------------------------------------------------------- +// wxDropTarget +//---------------------------------------------------------------------------- + +wxDragResult wxDropTarget::OnDragOver( + wxCoord WXUNUSED(x), wxCoord WXUNUSED(y), + wxDragResult def ) +{ + return CurrentDragHasSupportedFormat() ? def : wxDragNone; +} + +wxDataFormat wxDropTarget::GetMatchingPair() +{ + wxFAIL_MSG("wxDropTarget::GetMatchingPair() not implemented in src/osx/carbon/dnd.cpp"); + return wxDF_INVALID; +} + +bool wxDropTarget::OnDrop( wxCoord WXUNUSED(x), wxCoord WXUNUSED(y) ) +{ + if (m_dataObject == NULL) + return false; + + return CurrentDragHasSupportedFormat(); +} + +wxDragResult wxDropTarget::OnData( + wxCoord WXUNUSED(x), wxCoord WXUNUSED(y), + wxDragResult def ) +{ + if (m_dataObject == NULL) + return wxDragNone; + + if (!CurrentDragHasSupportedFormat()) + return wxDragNone; + + return GetData() ? def : wxDragNone; +} + +//------------------------------------------------------------------------- +// wxDropSource +//------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// drag request + +wxDropSource::~wxDropSource() +{ +} + +bool wxDropSource::MacInstallDefaultCursor(wxDragResult effect) +{ + const wxCursor& cursor = GetCursor(effect); + bool result = cursor.Ok(); + + if ( result ) + cursor.MacInstall(); + + return result; +} + +#endif // wxUSE_DRAG_AND_DROP + -- 2.47.2