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
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
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"
name: wxGTK 3 CMake Ubuntu 18.04
- os: osx
osx_image: xcode6.4
osx_image: xcode7.3
compiler: clang
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
osx_image: xcode9.4
compiler: clang

View File

@ -260,13 +260,15 @@ wxDragResult NSDragOperationToWxDragResult(NSDragOperation code)
return wxDragLink;
case NSDragOperationNone:
return wxDragNone;
case NSDragOperationDelete:
return wxDragNone;
default:
wxFAIL_MSG("Unexpected result code");
}
return wxDragNone;
}
@interface DropSourceDelegate : NSObject
@interface DropSourceDelegate : NSObject<NSDraggingSource>
{
BOOL dragFinished;
int resultCode;
@ -279,7 +281,7 @@ wxDragResult NSDragOperationToWxDragResult(NSDragOperation code)
- (void)setImplementation:(wxDropSource *)dropSource flags:(int)flags;
- (BOOL)finished;
- (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 endedAt:(NSPoint)aPoint operation:(NSDragOperation)operation;
@end
@ -314,28 +316,23 @@ wxDragResult NSDragOperationToWxDragResult(NSDragOperation code)
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;
// 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)
{
allowedDragOperations &= ~NSDragOperationMove;
}
// we might adapt flags here in the future
// context can be NSDraggingContextOutsideApplication or NSDraggingContextWithinApplication
return allowedDragOperations;
}
@ -434,6 +431,45 @@ wxDropSource* wxDropSource::GetCurrentDropSource()
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)
{
wxASSERT_MSG( m_data, wxT("Drop source: no data") );
@ -445,22 +481,14 @@ wxDragResult wxDropSource::DoDragDrop(int flags)
NSView* view = m_window->GetPeer()->GetWXWidget();
if (view)
{
NSPasteboard *pboard = [NSPasteboard pasteboardWithName:NSDragPboard];
wxOSXPasteboard dragPasteboard( pboard );
dragPasteboard.Clear();
m_data->WriteToSink( &dragPasteboard);
dragPasteboard.Flush();
NSEvent* theEvent = (NSEvent*)wxTheApp->MacGetCurrentEvent();
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;
DropSourceDelegate* delegate = [[DropSourceDelegate alloc] init];
[delegate setImplementation:this flags:flags];
// add a dummy square as dragged image for the moment,
// TODO: proper drag image for data
NSSize sz = NSMakeSize(16,16);
@ -476,10 +504,15 @@ wxDragResult wxDropSource::DoDragDrop(int flags)
[image unlockFocus];
DropSourceDelegate* delegate = [[DropSourceDelegate alloc] init];
[delegate setImplementation:this flags:flags];
[view dragImage:image at:p offset:NSMakeSize(0.0,0.0)
event: theEvent pasteboard: pboard source:delegate slideBack: NO];
NSPoint down = [theEvent locationInWindow];
NSPoint p = [view convertPoint:down fromView:nil];
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();
while ( ![delegate finished] )