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:
@@ -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
|
||||||
|
@@ -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] )
|
||||||
|
Reference in New Issue
Block a user