swiftcocoansapplicationnspasteboard

How to check "Copied text is from which Application"?


Recently, I am working on an application based on Pasteboard. I want to find out that copied text is not stored in pasteboard from the selected running application. Anyone have idea?


Solution

  • Although your question is a bit unclear, what I understand is that you want to know which application just added something to the pasteboard (and of course you also want the content of the pasteboard).

    While there is no API, there's a way. It's kind of a hack but that's how Apple does it themselves in their examples, so I guess it's ok.

    The main idea is to regularly poll the pasteboard with a timer, and to observe .NSWorkspaceDidActivateApplication at the same time: this way we can know which application is active when something new appears in the pasteboard.

    Here's an example of a class that does this:

    class PasteboardWatcher {
    
        private let pasteboard = NSPasteboard.general()
    
        // Keep track of the changes in the pasteboard.
        private var changeCount: Int
    
        // Used to regularly poll the pasteboard for changes.
        private var timer: Timer?
    
        private var frontmostApp: (name: String, bundle: String)?
    
        init() {
            // On launch, we mirror the pasteboard context.
            self.changeCount = pasteboard.changeCount
    
            // Registers if any application becomes active (or comes frontmost) and calls a method if it's the case.
            NSWorkspace.shared().notificationCenter.addObserver(self, selector: #selector(activeApp(sender:)), name: .NSWorkspaceDidActivateApplication, object: nil)
    
            if let types = pasteboard.types {
                print("Available pasteboards: \(types)")
            }
        }
    
        // Start polling for changes in pasteboard.
        func startPolling() {
            self.timer = Timer.scheduledTimer(timeInterval: 0.2, target: self, selector: #selector(checkForChangesInPasteboard), userInfo: nil, repeats: true)
        }
    
        // Called by NSWorkspace when any application becomes active or comes frontmost.
        @objc private func activeApp(sender: NSNotification) {
            if let info = sender.userInfo,
                let content = info[NSWorkspaceApplicationKey] as? NSRunningApplication,
                let name = content.localizedName,
                let bundle = content.bundleIdentifier
            {
                frontmostApp = (name: name, bundle: bundle)
            }
        }
    
        @objc private func checkForChangesInPasteboard() {
            if pasteboard.changeCount != changeCount {
                changeCount = pasteboard.changeCount
                if let copied = pasteboard.string(forType: NSStringPboardType),
                    let app = frontmostApp
                {
                    print("Copied string is: '\(copied)' from \(app.name) (\(app.bundle))")
                }
            }
        }
    
    }
    

    Use it simply like this:

    let watcher = PasteboardWatcher()
    watcher.startPolling()
    

    And it prints the copied string in the console, with also the name and bundle of the app.