Обнаружение глобального перетаскивания в 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 не обязательно.

Я знаю, что это можно сделать, потому что я использую другие приложения (чтобы делать похожие, но разные вещи), и они работают точно так же, как я пытаюсь достичь. Но пока бьюсь головой об стену.

Спасибо

0 ответов

Другие вопросы по тегам