diff options
Diffstat (limited to 'src/mac.m')
-rw-r--r-- | src/mac.m | 204 |
1 files changed, 175 insertions, 29 deletions
@@ -363,6 +363,111 @@ dispatchCurrentChildViewConfiguration(PuglView* const view) reshaped = true; } +- (NSDragOperation)draggingEntered:(id<NSDraggingInfo>)sender +{ + dragSource = sender; + dragOperation = NSDragOperationNone; + droppedUriList = nil; + + const NSPoint wloc = [sender draggingLocation]; + const NSPoint rloc = {0, 0}; // FIXME + const PuglEventDataOffer offer = { + PUGL_DATA_OFFER, + 0, + mach_absolute_time() / 1e9, + wloc.x, + wloc.y, + rloc.x, + [[NSScreen mainScreen] frame].size.height - rloc.y, + PUGL_CLIPBOARD_DRAG, + }; + + PuglEvent offerEvent; + offerEvent.offer = offer; + puglDispatchEvent(puglview, &offerEvent); + return self->dragOperation; +} + +- (NSDragOperation)draggingUpdated:(id<NSDraggingInfo>)sender +{ + assert(dragSource == sender); + + const NSPoint wloc = [sender draggingLocation]; + const NSPoint rloc = {0, 0}; // FIXME + const PuglEventDataOffer offer = { + PUGL_DATA_OFFER, + 0, + mach_absolute_time() / 1e9, + wloc.x, + wloc.y, + rloc.x, + [[NSScreen mainScreen] frame].size.height - rloc.y, + PUGL_CLIPBOARD_DRAG, + }; + + PuglEvent offerEvent; + offerEvent.offer = offer; + puglDispatchEvent(puglview, &offerEvent); + return self->dragOperation; +} + +- (void)draggingEnded:(id<NSDraggingInfo>)sender +{ + NSPasteboard* const pasteboard = [sender draggingPasteboard]; + const NSPoint wloc = [sender draggingLocation]; + const NSPoint rloc = {0, 0}; // FIXME + + const NSArray<NSPasteboardType>* const types = [pasteboard types]; + if (dragTypeIndex >= [types count]) { + return; + } + + NSString* const uti = [types objectAtIndex:dragTypeIndex]; + if ([uti isEqualToString:@"public.file-url"] || + [uti isEqualToString:@"com.apple.pasteboard.promised-file-url"]) { + // Convert file URI items into a single text/uri-list + droppedUriList = [NSString string]; + for (const NSPasteboardItem* item in [pasteboard pasteboardItems]) { + NSString* const value = [item stringForType:uti]; + if (!value) { + continue; + } + + NSURL* const idUri = [NSURL URLWithString:value]; + const char* const pathRep = [idUri fileSystemRepresentation]; + NSString* const path = [NSString stringWithUTF8String:pathRep]; + NSString* const pathUri = [[NSURL fileURLWithPath:path] absoluteString]; + + droppedUriList = [droppedUriList stringByAppendingString:pathUri]; + droppedUriList = [droppedUriList stringByAppendingFormat:@"\n"]; + } + } + + const PuglEventData data = { + PUGL_DATA, + 0, + mach_absolute_time() / 1e9, + wloc.x, + wloc.y, + rloc.x, + [[NSScreen mainScreen] frame].size.height - rloc.y, + PUGL_CLIPBOARD_DRAG, + (uint32_t)dragTypeIndex, // FIXME: ? + }; + + PuglEvent dataEvent; + dataEvent.data = data; + puglDispatchEvent(puglview, &dataEvent); + + dragSource = nil; +} + +- (void)draggingExited:(id<NSDraggingInfo>)sender +{ + assert(dragSource == sender); + dragSource = nil; +} + static uint32_t getModifiers(const NSEvent* const ev) { @@ -1867,14 +1972,63 @@ puglSetTransientParent(PuglView* view, PuglNativeView parent) return PUGL_FAILURE; } +static void +addRegisteredDragType(PuglView* const view, NSString* uti) +{ + if (!view->impl->registeredDragTypes) { + view->impl->registeredDragTypes = [[NSMutableArray alloc] init]; + } + + [view->impl->registeredDragTypes addObject:uti]; +} + +PuglStatus +puglRegisterDragType(PuglView* const view, const char* const type) +{ + PuglWrapperView* const wrapper = view->impl->wrapperView; + + CFStringRef mimeType = + CFStringCreateWithCString(NULL, type, kCFStringEncodingUTF8); + + // First register any types in the internal map that map to this MIME type + bool registered = false; + for (const Datatype* datatype = datatypes; datatype->mimeType; ++datatype) { + if (!strcmp(type, datatype->mimeType)) { + NSString* uti = [NSString stringWithUTF8String:datatype->uti]; + + addRegisteredDragType(view, uti); + registered = true; + } + } + + // Try to get the UTI from the system + if (!registered) { + NSString* uti = utiForMimeType((__bridge NSString*)mimeType); + if (uti) { + addRegisteredDragType(view, uti); + } + } + + if (wrapper) { + [wrapper registerForDraggedTypes:view->impl->registeredDragTypes]; + } + + return PUGL_SUCCESS; +} + static NSPasteboard* getPasteboard(const PuglView* const view, const PuglClipboard clipboard) { - (void)view; - switch (clipboard) { case PUGL_CLIPBOARD_GENERAL: return [NSPasteboard generalPasteboard]; + + case PUGL_CLIPBOARD_DRAG: + if (view->impl->wrapperView->dragSource) { + return [view->impl->wrapperView->dragSource draggingPasteboard]; + } + + break; } return NULL; @@ -1883,10 +2037,13 @@ getPasteboard(const PuglView* const view, const PuglClipboard clipboard) PuglStatus puglPaste(PuglView* const view) { - const PuglDataOfferEvent offer = { + const PuglEventDataOffer offer = { PUGL_DATA_OFFER, 0, puglGetTime(view->world), + 0, + 0, + PUGL_CLIPBOARD_GENERAL, }; PuglEvent offerEvent; @@ -1895,19 +2052,19 @@ puglPaste(PuglView* const view) return PUGL_SUCCESS; } -uint32_t +size_t puglGetNumClipboardTypes(const PuglView* const view, const PuglClipboard clipboard) { NSPasteboard* const pasteboard = getPasteboard(view, clipboard); - return pasteboard ? (uint32_t)[[pasteboard types] count] : 0; + return pasteboard ? [[pasteboard types] count] : 0; } const char* -puglGetClipboardType(const PuglView* const view, - const PuglClipboard clipboard, - const uint32_t typeIndex) +puglGetClipboardType(PuglView* const view, + const PuglClipboard clipboard, + const size_t typeIndex) { NSPasteboard* const pasteboard = getPasteboard(view, clipboard); if (!pasteboard) { @@ -1927,16 +2084,16 @@ puglGetClipboardType(const PuglView* const view, } static NSDragOperation -getDragOperation(const PuglAction action) +getDragOperation(const PuglDropAction action) { switch (action) { - case PUGL_ACTION_COPY: + case PUGL_DROP_ACTION_COPY: return NSDragOperationCopy; - case PUGL_ACTION_LINK: + case PUGL_DROP_ACTION_LINK: return NSDragOperationLink; - case PUGL_ACTION_MOVE: + case PUGL_DROP_ACTION_MOVE: return NSDragOperationMove; - case PUGL_ACTION_PRIVATE: + case PUGL_DROP_ACTION_PRIVATE: break; } @@ -1945,14 +2102,14 @@ getDragOperation(const PuglAction action) PuglStatus puglAcceptOffer(PuglView* const view, - const PuglDataOfferEvent* const offer, - const uint32_t typeIndex, - const PuglAction action, + const PuglEventDataOffer* const offer, + const size_t typeIndex, + PuglDropAction action, const PuglRect region) { PuglWrapperView* const wrapper = view->impl->wrapperView; NSPasteboard* const pasteboard = getPasteboard(view, offer->clipboard); - if (!pasteboard) { + if (!pasteboard || offer->clipboard == PUGL_CLIPBOARD_GENERAL) { return PUGL_BAD_PARAMETER; } @@ -1963,24 +2120,13 @@ puglAcceptOffer(PuglView* const view, wrapper->dragOperation = getDragOperation(action); wrapper->dragTypeIndex = typeIndex; - - const PuglDataEvent data = {PUGL_DATA, - 0U, - puglGetTime(view->world), - (double)region.x, - (double)region.y, - (uint32_t)typeIndex}; - - PuglEvent dataEvent; - dataEvent.data = data; - puglDispatchEvent(view, &dataEvent); return PUGL_SUCCESS; } const void* puglGetClipboard(PuglView* const view, const PuglClipboard clipboard, - const uint32_t typeIndex, + const size_t typeIndex, size_t* const len) { *len = 0; |