Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swift: How to activate and unhide window of ANY application?

I see pretty strange behaviour of NSRunningApplicationInstance.activate() method.

Let's imagine that I have found app named "Finder". This app at the moment is:

Not active and/or hidden

I have really simple code:

let activeOptions: NSApplication.ActivationOptions = [.activateAllWindows, .activateIgnoringOtherApps]

print("1. isActive: \(app.isActive); isHidden: \(app.isHidden)")
if (!app.isActive)
{
   app.activate(options: activeOptions)
}

if ( app.isHidden )
{
   app.unhide()
}
print("2. isActive: \(app.isActive); isHidden: \(app.isHidden)")

for finding needed app you can use the following code:

let app = NSWorkspace.shared.runningApplications.filter{ $0.localizedName = "NameOfApp"}

2 times runned code result:

  1. isActive: false; isHidden: false
  2. isActive: false; isHidden: false
  3. isActive: true; isHidden: false
  4. isActive: true; isHidden: false

If you will try it... :

  1. Code is will show me menu of the app: enter image description here

  2. BUT only on second code run! (Why?)

  3. Will not show me app window! (Why?)

And I see similar behaviour with a lot of applications, not only with Finder.

As example SourceTree app.


Can somebody explain the logic and how do display window of the ANY of runned app by some code IN ANY CASE?

like image 700
Andrew Avatar asked Oct 16 '25 14:10

Andrew


1 Answers

Here is working Playground module. The approach is to use KVO for observable properties to be informed when exactly desired state for target application occurs. Hope it would be helpful somehow.

import Cocoa

class AppActivator: NSObject {

    private var application: NSRunningApplication!
    private let filterName: String

    init(appName: String) {
        filterName = appName
    }
    
    func activate() {
        guard let app = NSWorkspace.shared.runningApplications.filter ({
            return $0.localizedName == self.filterName || $0.bundleIdentifier?.contains(self.filterName) ?? false
        }).first else {
            print("Application \(self.filterName) not found")
            return
        }

        guard app.activationPolicy != .prohibited else {
            print("Application \(self.filterName) prohibits activation")
            return
        }

        self.application = app
        
        self.unhideAppIfNeeded()
        self.activateAppIfNeeded()
    }
    
    private func unhideAppIfNeeded() {
        if application.isHidden {
            application.addObserver(self, forKeyPath: "isHidden", options: .new, context: nil)
            application.unhide()
        }
    }
    
    private func activateAppIfNeeded() {
        if !application.isHidden && !application.isActive {
            application.addObserver(self, forKeyPath: "isActive", options: .new, context: nil)
            application.activate(options: .activateIgnoringOtherApps)
        }
    }
    
    override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
        if keyPath == "isHidden" {
            application.removeObserver(self, forKeyPath: "isHidden")
            activateAppIfNeeded()
        } else if keyPath == "isActive" {
            application.removeObserver(self, forKeyPath: "isActive")
            print("Application \(application.localizedName) - ACTIVATED!")
        }
    }
}

let activator = AppActivator(appName: "Finder")
activator.activate()
like image 122
Asperi Avatar answered Oct 18 '25 13:10

Asperi



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!