Skip to content

Instantly share code, notes, and snippets.

@dagronf
Last active April 9, 2025 14:04
Show Gist options
  • Save dagronf/b71315a999678aece610838497fe9d0e to your computer and use it in GitHub Desktop.
Save dagronf/b71315a999678aece610838497fe9d0e to your computer and use it in GitHub Desktop.
Swift command-line tool to find which application is stealing your Mac's focus [macOS, script, steal, focus]
#!/usr/bin/swift
import Foundation
import AppKit.NSWorkspace
// Returns the name of the frontmost app, or <none> if no app is frontmost
func currentFocusApp() -> String {
NSWorkspace.shared.frontmostApplication?.localizedName ?? "<none>"
}
var prev_name = currentFocusApp()
Swift.print("New focus: \(prev_name)")
// Schedule a timer to check every second
let updateTimer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true, block: { _ in
let new_name = currentFocusApp()
if prev_name != new_name {
Swift.print("New focus: \(new_name)")
prev_name = new_name
}
})
// Detect Ctrl-C to stop observing
let sigintSrc = DispatchSource.makeSignalSource(signal: SIGINT, queue: .main)
sigintSrc.setEventHandler {
Swift.print("")
exit(0)
}
sigintSrc.resume()
RunLoop.current.run(mode: .default, before: .distantFuture)
@edmundcraske-bjss
Copy link

I've updated this a little to print the current time at the beginning of each output line, and to make it check every 0.1 second rather than every second:

#!/usr/bin/swift

import Foundation
import AppKit.NSWorkspace

func printTime() -> String {
    let date = Date()
    let formatter = DateFormatter()
    formatter.dateFormat = "HH:mm:ss.SSS"
    return formatter.string(from: date)
}

// Returns the name of the frontmost app, or <none> if no app is frontmost
func currentFocusApp() -> String {
   NSWorkspace.shared.frontmostApplication?.localizedName ?? "<none>"
}

var prev_name = currentFocusApp()
Swift.print(printTime() + " New focus: \(prev_name)")

// Schedule a timer to check every second
let updateTimer = Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true, block: { _ in
   let new_name = currentFocusApp()
   if prev_name != new_name {
      Swift.print(printTime() + " New focus: \(new_name)")
      prev_name = new_name
   }
})

// Detect Ctrl-C to stop observing
let sigintSrc = DispatchSource.makeSignalSource(signal: SIGINT, queue: .main)
sigintSrc.setEventHandler {
   Swift.print("")
   exit(0)
}
sigintSrc.resume()

RunLoop.current.run(mode: .default, before: .distantFuture)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment