Skip to content

Commit 7432369

Browse files
committed
Merge branch 'copilot/implement-todo-line-1723' of https://github.com/kovidgoyal/kitty
2 parents e9b4151 + d3b1203 commit 7432369

2 files changed

Lines changed: 74 additions & 6 deletions

File tree

glfw/cocoa_platform.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ typedef struct _GLFWDropData {
123123
id pasteboard;
124124
id data_mapping;
125125
id file_promise_mapping;
126+
id file_promise_temp_dir; // NSURL* for the unique temp dir used when receiving file promises for text/uri-list
126127
} _GLFWDropData;
127128

128129
// Cocoa-specific per-window data

glfw/cocoa_window.m

Lines changed: 73 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1492,10 +1492,15 @@ - (BOOL)wantsPeriodicDraggingUpdates
14921492
for (NSString *key in window->ns.drop_data.file_promise_mapping) {
14931493
NSArray *pair = [window->ns.drop_data.file_promise_mapping objectForKey:key];
14941494
error = nil; if (pair[1] != [NSNull null]) [pair[1] closeAndReturnError:&error];
1495-
error = nil; [fileManager removeItemAtURL:pair[0] error:&error];
1495+
if (pair[0] != [NSNull null]) { error = nil; [fileManager removeItemAtURL:pair[0] error:&error]; }
14961496
}
14971497
[window->ns.drop_data.file_promise_mapping release];
14981498
}
1499+
if (window->ns.drop_data.file_promise_temp_dir) {
1500+
NSError *error = nil;
1501+
[[NSFileManager defaultManager] removeItemAtURL:window->ns.drop_data.file_promise_temp_dir error:&error];
1502+
[window->ns.drop_data.file_promise_temp_dir release];
1503+
}
14991504
memset(&window->ns.drop_data, 0, sizeof(_GLFWDropData));
15001505
}
15011506

@@ -1720,11 +1725,73 @@ - (BOOL)performDragOperation:(id <NSDraggingInfo>)sender
17201725
data = [uri_list dataUsingEncoding:NSUTF8StringEncoding];
17211726
} else {
17221727
window->ns.drop_data.file_promise_mapping[@(mime)] = @[[NSNull null], [NSNull null], [NSNull null]];
1723-
// TODO: store all file promise based items that conform to UTTypeFileURL into a temp dir
1724-
// and once that's complete, generate a response with file:// URLs pointing to the items in that temp dir
1725-
// This must be done in the background but remember to send the GLFW_DROP_DATA_AVAILABLE event on main thread.
1726-
// The temporary directory must live until the next drop event for this window starts.
1727-
// It must also be deleted when the window is destroyed.
1728+
// Create a unique temp directory that lives until the next drop event or window destruction
1729+
NSError *mkdirError = nil;
1730+
NSString *tmpDirPath = [NSTemporaryDirectory() stringByAppendingPathComponent:
1731+
[[NSUUID UUID] UUIDString]];
1732+
NSURL *tmpDirURL = [NSURL fileURLWithPath:tmpDirPath isDirectory:YES];
1733+
if (![[NSFileManager defaultManager] createDirectoryAtURL:tmpDirURL
1734+
withIntermediateDirectories:YES attributes:nil error:&mkdirError]) {
1735+
NSLog(@"Failed to create temp dir for file promises: %@", mkdirError);
1736+
return 0;
1737+
}
1738+
window->ns.drop_data.file_promise_temp_dir = [tmpDirURL retain];
1739+
// Collect file promise receivers whose UTIs conform to UTTypeFileURL
1740+
NSArray *all_receivers = [pasteboard readObjectsForClasses:@[[NSFilePromiseReceiver class]] options:@{}];
1741+
NSMutableArray *file_receivers = [NSMutableArray array];
1742+
for (NSFilePromiseReceiver *receiver in all_receivers) {
1743+
for (NSString *ruti in receiver.fileTypes) {
1744+
UTType *promisedType = [UTType typeWithIdentifier:ruti];
1745+
if (promisedType && [promisedType conformsToType:UTTypeFileURL]) {
1746+
[file_receivers addObject:receiver];
1747+
break;
1748+
}
1749+
}
1750+
}
1751+
if ([file_receivers count] == 0) {
1752+
// Nothing to receive; emit an empty uri-list immediately
1753+
if (window->ns.drop_data.data_mapping == nil)
1754+
window->ns.drop_data.data_mapping = [[NSMutableDictionary alloc] init];
1755+
window->ns.drop_data.data_mapping[@(mime)] = @[[NSData data], @0];
1756+
[window->ns.drop_data.file_promise_mapping removeObjectForKey:@(mime)];
1757+
send_data_available_event_on_next_event_loop_tick(wid, mime);
1758+
return 0;
1759+
}
1760+
char *mt = _glfw_strdup(mime);
1761+
NSMutableArray *collected_urls = [[NSMutableArray alloc] init];
1762+
dispatch_group_t group = dispatch_group_create();
1763+
NSOperationQueue *opQueue = [[NSOperationQueue alloc] init];
1764+
opQueue.maxConcurrentOperationCount = 1; // serial: safe to append to collected_urls
1765+
for (NSFilePromiseReceiver *receiver in file_receivers) {
1766+
dispatch_group_enter(group);
1767+
[receiver receivePromisedFilesAtDestination:tmpDirURL options:@{}
1768+
operationQueue:opQueue
1769+
reader:^(NSURL *fileURL, NSError *errorOrNil) {
1770+
if (!errorOrNil && fileURL) [collected_urls addObject:fileURL];
1771+
dispatch_group_leave(group);
1772+
}];
1773+
}
1774+
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
1775+
dispatch_release(group);
1776+
_GLFWwindow *w = _glfwWindowForId(wid);
1777+
if (w && w->ns.drop_data.file_promise_mapping) {
1778+
if (w->ns.drop_data.data_mapping == nil)
1779+
w->ns.drop_data.data_mapping = [[NSMutableDictionary alloc] init];
1780+
NSMutableString *uri_list = [NSMutableString stringWithCapacity:4096];
1781+
for (NSURL *url in collected_urls) {
1782+
if ([uri_list length] > 0) [uri_list appendString:@"\n"];
1783+
[uri_list appendString:url.absoluteString];
1784+
}
1785+
NSData *result = [uri_list dataUsingEncoding:NSUTF8StringEncoding];
1786+
w->ns.drop_data.data_mapping[@(mt)] = @[result, @0];
1787+
[w->ns.drop_data.file_promise_mapping removeObjectForKey:@(mt)];
1788+
const char *mimes[1] = {mt};
1789+
_glfwInputDropEvent(w, GLFW_DROP_DATA_AVAILABLE, 0, 0, mimes, 1, false);
1790+
}
1791+
[collected_urls release];
1792+
[opQueue release];
1793+
free(mt);
1794+
});
17281795
return 0;
17291796
}
17301797
} else if (strcmp(mime, "text/plain") == 0 || strcmp(mime, "text/plain;charset=utf-8") == 0) {

0 commit comments

Comments
 (0)