Обнаружение глобального перетаскивания в MacOS для файлов и обещанных файлов
Я работаю над приложением для MacOS, которое может обрабатывать изображения. Идея заключается в том, что приложение большую часть времени скрывается, но если вы перетащите изображение из другого приложения или искателя, мое приложение отобразится, и вы можете перетащить изображение поверх него. В основном это зона дропа в режиме ожидания, когда вам это нужно.
Все работает отлично, за исключением того, что я не могу понять, как отображать приложение только для определенных типов перетаскиваемых элементов (URL-адресов, fileURL, FilePromises и изображений). То, что у меня сейчас есть, показывает приложение для любого вида перетаскивания, даже для выделения текста на странице или щелчка и перетаскивания по строке меню.
Я пробовал смотреть на NSPasteboard для перетаскивания, но, похоже, он не обновляется во время перетаскивания. Я видел несколько сообщений об использовании специальных возможностей, чтобы увидеть, что находится под мышкой, но это кажется хрупким, и я еще не понимаю, как это сделать.
Вот код, который я использую для обнаружения глобального перетаскивания:
dragMonitor = NSEvent.addGlobalMonitorForEvents(matching:.leftMouseDragged) { event in
if !self.isDragging {
self.isDragging = true
if let dropzoneViewController = self.dropzoneViewController, dropzoneViewController.shouldShowForDrag(event: event) {
self.show()
}
}
}
upMonitor = NSEvent.addGlobalMonitorForEvents(matching:.leftMouseUp) { event in
if self.isDragging {
self.hide()
self.isDragging = false
}
}
Эта функция, в свою очередь, вызывает следующее, которое применяет логику приложения для определения, обрабатывать перетаскивание или нет.
func shouldShowForDrag(event: NSEvent) -> Bool {
return self.dropTarget.canHandleDrop(NSPasteboard(name: .drag))
}
Для ясности, вот как приложение обрабатывает перетаскивание, когда оно оказывается над окном приложения:
override func performDragOperation(_ draggingInfo: NSDraggingInfo) -> Bool {
isReceivingDrag = false
if let dropTarget = dropTarget, dropTarget.canHandleDrop(draggingInfo.draggingPasteboard) {
dropTarget.handleDrop(draggingInfo.draggingPasteboard)
return true
} else {
return false
}
}
Единственная разница между этими двумя проверками - это глобальная проверка (
Наконец, вот основная логика для определения того, какие перетаскивания следует принимать:
func canHandleDrop(_ pasteBoard: NSPasteboard) -> Bool {
let urlFilteringOptions = [NSPasteboard.ReadingOptionKey.urlReadingContentsConformToTypes:NSImage.imageTypes]
if let urls = pasteBoard.readObjects(forClasses: [NSURL.self], options:urlFilteringOptions) as? [URL], urls.count > 0 {
return true
} else if let filePromises = pasteBoard.readObjects(forClasses: [NSFilePromiseReceiver.self], options: nil) as? [NSFilePromiseReceiver], filePromises.count > 0 {
return true
} else if let images = pasteBoard.readObjects(forClasses: [NSImage.self], options: [:]) as? [NSImage], images.count > 0 {
return true
}
return false
}
Первые два пункта являются наиболее важными. Обнаружение NSImages не обязательно.
Я знаю, что это можно сделать, потому что я использую другие приложения (чтобы делать похожие, но разные вещи), и они работают точно так же, как я пытаюсь достичь. Но пока бьюсь головой об стену.
Спасибо