summaryrefslogtreecommitdiff
path: root/macos/Sources/Helpers/Extensions/NSApplication+Extension.swift
blob: 0bc79fb6af8d0106614b85f0b1e8339ae01a42f8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
import AppKit
import Cocoa

// MARK: Presentation Options

extension NSApplication {
    private static var presentationOptionCounts: [NSApplication.PresentationOptions.Element: UInt] = [:]

    /// Add a presentation option to the application and main a reference count so that and equal
    /// number of pops is required to disable it. This is useful so that multiple classes can affect global
    /// app state without overriding others.
    func acquirePresentationOption(_ option: NSApplication.PresentationOptions.Element) {
        Self.presentationOptionCounts[option, default: 0] += 1
        presentationOptions.insert(option)
    }

    /// See acquirePresentationOption
    func releasePresentationOption(_ option: NSApplication.PresentationOptions.Element) {
        guard let value = Self.presentationOptionCounts[option] else { return }
        guard value > 0 else { return }
        if (value == 1) {
            presentationOptions.remove(option)
            Self.presentationOptionCounts.removeValue(forKey: option)
        } else {
            Self.presentationOptionCounts[option] = value - 1
        }
    }
}

extension NSApplication.PresentationOptions.Element: @retroactive Hashable {
    public func hash(into hasher: inout Hasher) {
        hasher.combine(rawValue)
    }
}

// MARK: Frontmost

extension NSApplication {
    /// True if the application is frontmost. This isn't exactly the same as isActive because
    /// an app can be active but not be frontmost if the window with activity is an NSPanel.
    var isFrontmost: Bool {
        NSWorkspace.shared.frontmostApplication?.bundleIdentifier == Bundle.main.bundleIdentifier
    }
}