macOS new DragSession API (#1919)

* new dragsession API

* Update src/osx/cocoa/dnd.mm

Co-authored-by: VZ <vz-github@zeitlins.org>

* Update src/osx/cocoa/dnd.mm

Co-authored-by: VZ <vz-github@zeitlins.org>

* Update src/osx/cocoa/dnd.mm

Co-authored-by: VZ <vz-github@zeitlins.org>

* avoid NSDragOperationDelete

* adding SDK 10.10 compatibility

* remove conditional compilation, upgrading travis to Xcode 7.3

* adding typedef NSPasteboardType for SDK < 10.13

Co-authored-by: VZ <vz-github@zeitlins.org>
This commit is contained in:
Stefan Csomor
2020-07-05 11:04:09 +02:00
committed by GitHub
parent 1666f58bc6
commit c15d805a9f
2 changed files with 66 additions and 33 deletions

View File

@@ -32,10 +32,10 @@ matrix:
env: wxGTK_VERSION=3 wxTOOLSET=cmake wxCMAKE_GENERATOR="Unix Makefiles" env: wxGTK_VERSION=3 wxTOOLSET=cmake wxCMAKE_GENERATOR="Unix Makefiles"
name: wxGTK 3 CMake Ubuntu 18.04 name: wxGTK 3 CMake Ubuntu 18.04
- os: osx - os: osx
osx_image: xcode6.4 osx_image: xcode7.3
compiler: clang compiler: clang
env: wxCONFIGURE_FLAGS="--enable-cxx11" wxMAKEFILE_FLAGS="CXXFLAGS=-std=c++11" wxSKIP_SAMPLES=1 env: wxCONFIGURE_FLAGS="--enable-cxx11" wxMAKEFILE_FLAGS="CXXFLAGS=-std=c++11" wxSKIP_SAMPLES=1
name: wxOSX Xcode 6.4 name: wxOSX Xcode 7.3
- os: osx - os: osx
osx_image: xcode9.4 osx_image: xcode9.4
compiler: clang compiler: clang

View File

@@ -260,13 +260,15 @@ wxDragResult NSDragOperationToWxDragResult(NSDragOperation code)
return wxDragLink; return wxDragLink;
case NSDragOperationNone: case NSDragOperationNone:
return wxDragNone; return wxDragNone;
case NSDragOperationDelete:
return wxDragNone;
default: default:
wxFAIL_MSG("Unexpected result code"); wxFAIL_MSG("Unexpected result code");
} }
return wxDragNone; return wxDragNone;
} }
@interface DropSourceDelegate : NSObject @interface DropSourceDelegate : NSObject<NSDraggingSource>
{ {
BOOL dragFinished; BOOL dragFinished;
int resultCode; int resultCode;
@@ -279,7 +281,7 @@ wxDragResult NSDragOperationToWxDragResult(NSDragOperation code)
- (void)setImplementation:(wxDropSource *)dropSource flags:(int)flags; - (void)setImplementation:(wxDropSource *)dropSource flags:(int)flags;
- (BOOL)finished; - (BOOL)finished;
- (NSDragOperation)code; - (NSDragOperation)code;
- (NSDragOperation)draggingSourceOperationMaskForLocal:(BOOL)forLocal; - (NSDragOperation)draggingSession:(nonnull NSDraggingSession *)session sourceOperationMaskForDraggingContext:(NSDraggingContext)context;
- (void)draggedImage:(NSImage *)anImage movedTo:(NSPoint)aPoint; - (void)draggedImage:(NSImage *)anImage movedTo:(NSPoint)aPoint;
- (void)draggedImage:(NSImage *)anImage endedAt:(NSPoint)aPoint operation:(NSDragOperation)operation; - (void)draggedImage:(NSImage *)anImage endedAt:(NSPoint)aPoint operation:(NSDragOperation)operation;
@end @end
@@ -314,28 +316,23 @@ wxDragResult NSDragOperationToWxDragResult(NSDragOperation code)
return resultCode; return resultCode;
} }
- (NSDragOperation)draggingSourceOperationMaskForLocal:(BOOL)forLocal - (NSDragOperation)draggingSession:(nonnull NSDraggingSession *)session sourceOperationMaskForDraggingContext:(NSDraggingContext)context
{ {
/*
By default drag targets receive a mask of NSDragOperationAll (0xf)
which, despite its name, does not include the later added
NSDragOperationMove (0x10) that sometimes is wanted.
Use NSDragOperationEvery instead because it includes all flags.
Note that this, compared to the previous behaviour, adds
NSDragOperationDelete to the mask which seems harmless.
We are also keeping NSDragOperationLink and NSDragOperationPrivate
in to preserve previous behaviour.
*/
NSDragOperation allowedDragOperations = NSDragOperationEvery; NSDragOperation allowedDragOperations = NSDragOperationEvery;
// NSDragOperationGeneric also makes a drag to the trash possible
// resulting in something we don't support (NSDragOperationDelete)
allowedDragOperations &= ~(NSDragOperationDelete | NSDragOperationGeneric);
if (m_dragFlags == wxDrag_CopyOnly) if (m_dragFlags == wxDrag_CopyOnly)
{ {
allowedDragOperations &= ~NSDragOperationMove; allowedDragOperations &= ~NSDragOperationMove;
} }
// we might adapt flags here in the future
// context can be NSDraggingContextOutsideApplication or NSDraggingContextWithinApplication
return allowedDragOperations; return allowedDragOperations;
} }
@@ -434,6 +431,45 @@ wxDropSource* wxDropSource::GetCurrentDropSource()
return gCurrentSource; return gCurrentSource;
} }
@interface wxPasteBoardWriter : NSObject<NSPasteboardWriting>
{
wxDataObject* m_data;
}
- (id) initWithDataObject:(wxDataObject*) obj;
@end
@implementation wxPasteBoardWriter
- (id) initWithDataObject:(wxDataObject*) obj
{
m_data = obj;
return self;
}
#if __MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_13
typedef NSString* NSPasteboardType;
#endif
- (nullable id)pasteboardPropertyListForType:(nonnull NSPasteboardType)type
{
wxDataFormat format((wxDataFormat::NativeFormat) type);
size_t size = m_data->GetDataSize(format);
CFMutableDataRef data = CFDataCreateMutable(kCFAllocatorDefault,size );
m_data->GetDataHere(format, CFDataGetMutableBytePtr(data));
CFDataSetLength(data, size);
return (id) data;
}
- (nonnull NSArray<NSPasteboardType> *)writableTypesForPasteboard:(nonnull NSPasteboard *)pasteboard
{
wxCFMutableArrayRef<CFStringRef> typesarray;
m_data->AddSupportedTypes(typesarray);
return (NSArray<NSPasteboardType>*) typesarray.autorelease();
}
@end
wxDragResult wxDropSource::DoDragDrop(int flags) wxDragResult wxDropSource::DoDragDrop(int flags)
{ {
wxASSERT_MSG( m_data, wxT("Drop source: no data") ); wxASSERT_MSG( m_data, wxT("Drop source: no data") );
@@ -445,22 +481,14 @@ wxDragResult wxDropSource::DoDragDrop(int flags)
NSView* view = m_window->GetPeer()->GetWXWidget(); NSView* view = m_window->GetPeer()->GetWXWidget();
if (view) if (view)
{ {
NSPasteboard *pboard = [NSPasteboard pasteboardWithName:NSDragPboard];
wxOSXPasteboard dragPasteboard( pboard );
dragPasteboard.Clear();
m_data->WriteToSink( &dragPasteboard);
dragPasteboard.Flush();
NSEvent* theEvent = (NSEvent*)wxTheApp->MacGetCurrentEvent(); NSEvent* theEvent = (NSEvent*)wxTheApp->MacGetCurrentEvent();
wxASSERT_MSG(theEvent, "DoDragDrop must be called in response to a mouse down or drag event."); wxASSERT_MSG(theEvent, "DoDragDrop must be called in response to a mouse down or drag event.");
NSPoint down = [theEvent locationInWindow];
NSPoint p = [view convertPoint:down fromView:nil];
gCurrentSource = this; gCurrentSource = this;
DropSourceDelegate* delegate = [[DropSourceDelegate alloc] init];
[delegate setImplementation:this flags:flags];
// add a dummy square as dragged image for the moment, // add a dummy square as dragged image for the moment,
// TODO: proper drag image for data // TODO: proper drag image for data
NSSize sz = NSMakeSize(16,16); NSSize sz = NSMakeSize(16,16);
@@ -476,10 +504,15 @@ wxDragResult wxDropSource::DoDragDrop(int flags)
[image unlockFocus]; [image unlockFocus];
DropSourceDelegate* delegate = [[DropSourceDelegate alloc] init]; NSPoint down = [theEvent locationInWindow];
[delegate setImplementation:this flags:flags]; NSPoint p = [view convertPoint:down fromView:nil];
[view dragImage:image at:p offset:NSMakeSize(0.0,0.0)
event: theEvent pasteboard: pboard source:delegate slideBack: NO]; wxPasteBoardWriter* writer = [[wxPasteBoardWriter alloc] initWithDataObject:m_data];
wxCFMutableArrayRef<NSDraggingItem*> items;
NSDraggingItem* item = [[NSDraggingItem alloc] initWithPasteboardWriter:writer];
[item setDraggingFrame:NSMakeRect(p.x, p.y, 16, 16) contents:image];
items.push_back(item);
[view beginDraggingSessionWithItems:items event:theEvent source:delegate];
wxEventLoopBase * const loop = wxEventLoop::GetActive(); wxEventLoopBase * const loop = wxEventLoop::GetActive();
while ( ![delegate finished] ) while ( ![delegate finished] )