Files
Snaggle/GreenshotMac/App/AppDelegate.swift
T
2026-09-17 15:15:45 -05:00

60 lines
2.4 KiB
Swift

// AppDelegate.swift
// GreenshotMac
import AppKit
@MainActor
final class AppDelegate: NSObject, NSApplicationDelegate {
private var statusMenu: StatusMenuController?
func applicationDidFinishLaunching(_ notification: Notification) {
// A second copy would install its own menu bar item and register the same global
// hotkeys, which the first copy already owns. Hand over to the running instance.
if let other = AppDelegate.otherRunningInstance() {
NSLog("GreenshotMac: another instance is already running (pid \(other.processIdentifier)); exiting.")
other.activate()
Notifier.show(title: "GreenshotMac is already running",
body: "Use the camera icon in the menu bar.")
NSApp.terminate(nil)
return
}
NSApp.setActivationPolicy(.accessory)
statusMenu = StatusMenuController()
MainMenuBuilder.install()
HotkeyBindings.shared.registerAll()
if !CGPreflightScreenCaptureAccess() {
// Triggers the system prompt on first launch so the first capture just works.
CGRequestScreenCaptureAccess()
}
}
/// Another process running the same bundle identifier, if there is one.
static func otherRunningInstance() -> NSRunningApplication? {
guard let bundleID = Bundle.main.bundleIdentifier else { return nil }
let current = NSRunningApplication.current
return NSRunningApplication.runningApplications(withBundleIdentifier: bundleID)
.first { $0.processIdentifier != current.processIdentifier && !$0.isTerminated }
}
func applicationWillTerminate(_ notification: Notification) {
HotkeyManager.shared.unregisterAll()
}
func applicationSupportsSecureRestorableState(_ app: NSApplication) -> Bool { true }
func application(_ application: NSApplication, open urls: [URL]) {
for url in urls {
guard let image = NSImage(contentsOf: url),
let cgImage = image.cgImage(forProposedRect: nil, context: nil, hints: nil) else { continue }
var details = CaptureDetails()
details.captureMode = .importedFile
details.title = url.deletingPathExtension().lastPathComponent
details.scaleFactor = CGFloat(cgImage.width) / max(1, image.size.width)
EditorWindowController.open(with: Capture(image: cgImage, details: details))
}
}
}