diff --git a/input/dnd.c b/input/dnd.c index b03b2bb4869a2..7075cf97df188 100644 --- a/input/dnd.c +++ b/input/dnd.c @@ -140,6 +140,23 @@ static MP_THREAD_VOID mpv_event_loop_fn(void *arg) MP_THREAD_RETURN(); } +void mp_dnd_load_file(mpv_handle *mpv, int num_files, char **files, enum mp_dnd_action action) +{ + mpv_node *items = talloc_zero_array(NULL, mpv_node, num_files); + mpv_node_list list = {.values = items, .num = num_files}; + mpv_node node = {.format = MPV_FORMAT_NODE_ARRAY, .u = {.list = &list}}; + for (int n = 0; n < num_files; n++) { + items[n] = (mpv_node){.format = MPV_FORMAT_STRING, + .u = {.string = files[n]}}; + } + + char *actionstr = action == DND_REPLACE ? "replace" : + action == DND_APPEND ? "append" : + action == DND_INSERT_NEXT ? "insert-next" : + "none"; + handle_dnd(mpv, &node, actionstr); +} + void mp_dnd_init(mpv_handle *mpv) { mp_thread mpv_event_loop; diff --git a/input/dnd.h b/input/dnd.h index 8bb9f0ed9d7ea..ddb0503772d2e 100644 --- a/input/dnd.h +++ b/input/dnd.h @@ -18,4 +18,7 @@ #include "player/client.h" +#include "event.h" + +void mp_dnd_load_file(mpv_handle *ctx, int num_files, char **files, enum mp_dnd_action action); void mp_dnd_init(mpv_handle *mpv); diff --git a/osdep/mac/app_bridge_objc.h b/osdep/mac/app_bridge_objc.h index bcde2caf8a6cd..b317e2f9cd94e 100644 --- a/osdep/mac/app_bridge_objc.h +++ b/osdep/mac/app_bridge_objc.h @@ -28,6 +28,7 @@ #include "common/global.h" #include "input/input.h" #include "input/event.h" +#include "input/dnd.h" #include "input/keycodes.h" #include "video/out/win_state.h" diff --git a/osdep/mac/app_hub.swift b/osdep/mac/app_hub.swift index 879b084ca5aad..b050bb124abe4 100644 --- a/osdep/mac/app_hub.swift +++ b/osdep/mac/app_hub.swift @@ -39,6 +39,7 @@ class AppHub: NSObject { var isApplication: Bool { return NSApp is Application } var isBundle: Bool { return ProcessInfo.processInfo.environment["MPVBUNDLE"] == "true" } var openEvents: Int = 0 + var openFiles: [String] = [] private override init() { input = InputHelper() @@ -113,9 +114,22 @@ class AppHub: NSObject { return strL.localizedStandardCompare(strR) == .orderedAscending } log.verbose("\(openEvents > 0 ? "Appending" : "Opening") dropped files: \(files)") - input.open(files: files, append: openEvents > 0) - openEvents += 1 + DispatchQueue.main.async { + self.open(files: files, append: self.openEvents > 0) + self.openEvents += 1 + } DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { self.openEvents -= 1 } + + } + + func open(files: [String], append: Bool = false) { + openFiles += files + guard let mpv = mpv else { return } + + input.open(files: files, append: append) { (filesPtr, action) in + mp_dnd_load_file(mpv, Int32(openFiles.count), &filesPtr, action) + } + openFiles = [] } func getIcon() -> NSImage { diff --git a/osdep/mac/input_helper.swift b/osdep/mac/input_helper.swift index 3833dc9fc5db2..c84d71971471f 100644 --- a/osdep/mac/input_helper.swift +++ b/osdep/mac/input_helper.swift @@ -249,20 +249,27 @@ class InputHelper: NSObject { return String(utf16CodeUnits: chars, count: length) } - @objc func open(files: [String], append: Bool = false) { + @objc func handleDnd(files: [String]) { lock.withLock { guard let input = input else { return } - var action = DND_APPEND - if !append { - action = NSEvent.modifierFlags.contains(.shift) ? DND_APPEND : DND_REPLACE + open(files: files) { (filesPtr, action) in + mp_input_drop_files(input, Int32(files.count), &filesPtr, action) } + } + } - let filesClean = files.map { $0.hasPrefix("file:///.file/id=") ? (URL(string: $0)?.path ?? $0) : $0 } - var filesPtr = filesClean.map { UnsafeMutablePointer(strdup($0)) } - mp_input_drop_files(input, Int32(files.count), &filesPtr, action) - for charPtr in filesPtr { free(UnsafeMutablePointer(mutating: charPtr)) } + func open(files: [String], append: Bool = false, + completion: (inout [UnsafeMutablePointer?], mp_dnd_action) -> Void) { + var action = DND_APPEND + if !append { + action = NSEvent.modifierFlags.contains(.shift) ? DND_APPEND : DND_REPLACE } + + let filesClean = files.map { $0.hasPrefix("file:///.file/id=") ? (URL(string: $0)?.path ?? $0) : $0 } + var filesPtr = filesClean.map { UnsafeMutablePointer(strdup($0)) } + completion(&filesPtr, action) + for charPtr in filesPtr { free(UnsafeMutablePointer(mutating: charPtr)) } } private func useAltGr() -> Bool { diff --git a/osdep/mac/menu_bar.swift b/osdep/mac/menu_bar.swift index 2a830ff17b32f..e3b34a8029e24 100644 --- a/osdep/mac/menu_bar.swift +++ b/osdep/mac/menu_bar.swift @@ -334,7 +334,7 @@ class MenuBar: NSObject, EventSubscriber { @objc func openFiles() { guard let files = dialog.openFiles(path: currentDir) else { return } - appHub.input.open(files: files) + appHub.open(files: files) } @objc func openPlaylist() { @@ -344,7 +344,7 @@ class MenuBar: NSObject, EventSubscriber { @objc func openUrl() { guard let file = dialog.openUrl() else { return } - appHub.input.open(files: [file]) + appHub.open(files: [file]) } @objc func command(_ menuItem: MenuItem) { diff --git a/video/out/mac/view.swift b/video/out/mac/view.swift index c341b3154a5af..f8cc6254ae975 100644 --- a/video/out/mac/view.swift +++ b/video/out/mac/view.swift @@ -92,7 +92,7 @@ class View: NSView, CALayerDelegate { } } if files.isEmpty { return false } - input?.open(files: files) + input?.handleDnd(files: files) return true }