66 lines
2.7 KiB
Swift
66 lines
2.7 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)
|
|
Theme.apply()
|
|
NotificationCenter.default.addObserver(forName: .appearanceChanged,
|
|
object: nil,
|
|
queue: .main) { _ in
|
|
MainActor.assumeIsolated { Theme.apply() }
|
|
}
|
|
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))
|
|
}
|
|
}
|
|
}
|