aboutsummaryrefslogtreecommitdiffstats
path: root/src/mac.m
diff options
context:
space:
mode:
Diffstat (limited to 'src/mac.m')
-rw-r--r--src/mac.m204
1 files changed, 175 insertions, 29 deletions
diff --git a/src/mac.m b/src/mac.m
index 107cadb..f09081a 100644
--- a/src/mac.m
+++ b/src/mac.m
@@ -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;