From 143a8203bdfef86cf174309e701f51f82df8fe42 Mon Sep 17 00:00:00 2001 From: Dimitri Schoolwerth Date: Wed, 27 May 2015 19:44:36 +0400 Subject: [PATCH] Fix dragging always resulting in wxDragLink on OS X Commit f40e8bf uncovered a problem with dragging where when the NSDragOperationLink bit is set in the drag mask (which by default always is the case) the result is a wxDragLink operation instead of wxDragCopy or wxDragMove. To fix this give priority to move and copy instead when converting the drag mask to a wxDrag result. This fixes copying through DND in wxRichTextCtrl. See #13819. --- src/osx/cocoa/window.mm | 50 ++++++++++++++++++++++++++++++++--------- 1 file changed, 39 insertions(+), 11 deletions(-) diff --git a/src/osx/cocoa/window.mm b/src/osx/cocoa/window.mm index e4eabe8eea..d98cd3a682 100644 --- a/src/osx/cocoa/window.mm +++ b/src/osx/cocoa/window.mm @@ -1173,6 +1173,23 @@ unsigned int wxOnDraggingEnteredOrUpdated(wxWidgetCocoaImpl* viewImpl, { id sender = (id ) s; NSPasteboard *pboard = [sender draggingPasteboard]; + /* + sourceDragMask contains a flag field with drag operations permitted by + the source: + NSDragOperationCopy = 1, + NSDragOperationLink = 2, + NSDragOperationGeneric = 4, + NSDragOperationPrivate = 8, + NSDragOperationMove = 16, + NSDragOperationDelete = 32 + + By default, pressing modifier keys changes sourceDragMask: + Control ANDs it with NSDragOperationLink (2) + Option ANDs it with NSDragOperationCopy (1) + Command ANDs it with NSDragOperationGeneric (4) + + The end result can be a mask that's 0 (NSDragOperationNone). + */ NSDragOperation sourceDragMask = [sender draggingSourceOperationMask]; wxWindow* wxpeer = viewImpl->GetWXPeer(); @@ -1183,16 +1200,26 @@ unsigned int wxOnDraggingEnteredOrUpdated(wxWidgetCocoaImpl* viewImpl, if ( target == NULL ) return NSDragOperationNone; - wxDragResult result = wxDragNone; NSPoint nspoint = [viewImpl->GetWXWidget() convertPoint:[sender draggingLocation] fromView:nil]; wxPoint pt = wxFromNSPoint( viewImpl->GetWXWidget(), nspoint ); - if ( sourceDragMask & NSDragOperationLink ) - result = wxDragLink; - else if ( sourceDragMask & NSDragOperationCopy ) - result = wxDragCopy; - else if ( sourceDragMask & NSDragOperationMove ) + /* + Convert the incoming mask to wxDragResult. This is a lossy conversion + because wxDragResult contains a single value and not a flag field. + When dragging the bottom part of the DND sample ("Drag text from here!") + sourceDragMask contains copy, link, generic, and private flags. Formerly + this would result in wxDragLink which is not what is expected for text. + Give precedence to the move and copy flag instead. + */ + wxDragResult result = wxDragNone; + + if (sourceDragMask & NSDragOperationMove) result = wxDragMove; + else if ( sourceDragMask & NSDragOperationCopy + || sourceDragMask & NSDragOperationGeneric) + result = wxDragCopy; + else if (sourceDragMask & NSDragOperationLink) + result = wxDragLink; PasteboardRef pboardRef; PasteboardCreate((CFStringRef)[pboard name], &pboardRef); @@ -1276,12 +1303,13 @@ bool wxWidgetCocoaImpl::performDragOperation(void* s, WXWidget WXUNUSED(slf), vo NSPoint nspoint = [m_osxView convertPoint:[sender draggingLocation] fromView:nil]; wxPoint pt = wxFromNSPoint( m_osxView, nspoint ); - if ( sourceDragMask & NSDragOperationLink ) - result = wxDragLink; - else if ( sourceDragMask & NSDragOperationCopy ) - result = wxDragCopy; - else if ( sourceDragMask & NSDragOperationMove ) + if (sourceDragMask & NSDragOperationMove) result = wxDragMove; + else if ( sourceDragMask & NSDragOperationCopy + || sourceDragMask & NSDragOperationGeneric) + result = wxDragCopy; + else if (sourceDragMask & NSDragOperationLink) + result = wxDragLink; PasteboardRef pboardRef; PasteboardCreate((CFStringRef)[pboard name], &pboardRef);