MacOS 上的文件和承诺文件的全局拖放检测

问题描述 投票:0回答:1

我正在开发一个可以处理图像的 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
    }
}

这两个检查之间的唯一区别是全局检查 (

shouldShowForDrag(event:)
) 使用
NSPasteboard(name: .drag)
,它在
NSEvent.addGlobalMonitorForEvents(matching:)
触发时不是当前的。可拖动进入我的窗口时的逻辑使用提供的粘贴板 (
draggingInfo.draggingPasteboard
),当然,它对于所拖动的内容是准确的。

最后,这是确定接受哪些拖动的基本逻辑:

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 并不是严格要求的。

我知道这是可以做到的,因为我正在使用其他应用程序(做类似但不同的事情),并且它们的工作原理与我想要实现的目标完全相同。但到目前为止我还在用头撞墙。

谢谢

macos drag-and-drop nsurl nspasteboard nsfilepromiseprovider
1个回答
0
投票

您可以简单地检查拖动粘贴板的内容类型

let pasteboard = NSPasteboard(name: .drag)
if let types = pasteboard.types, types.contain(.fileURL) {
    if !self.isDragging {
    self.isDragging = true
    if let dropzoneViewController = self.dropzoneViewController, dropzoneViewController.shouldShowForDrag(event: event) {
        self.show()
        }
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.