iOS/Sources/MacBridge/MacBridgeImpl.swift
Zac West 0a4b6ad101
Fix device name reporting "iPad" on macOS 13 (#2303)
## Summary
Instead of showing "iPad" we now show the correct name again.

## Any other notes
`UIDevice.current.name` on Catalyst incorrectly protects the computer
name behind an entitlement which isn't granted on Mac (we have it on
other platforms). Since Mac doesn't have this entitlement, bridge to
AppKit land and grab the value from there.
2023-02-08 22:39:24 -08:00

133 lines
4.5 KiB
Swift

import AppKit
import Foundation
import ServiceManagement
import SystemConfiguration
@objc(HAMacBridgeImpl) final class MacBridgeImpl: NSObject, MacBridge {
let networkMonitor: MacBridgeNetworkMonitor
let statusItem: MacBridgeStatusItem?
override init() {
if Bundle.main.isRunningInExtension {
// status item can't talk to the status bar in an extension or it will crash
self.statusItem = nil
} else {
self.statusItem = MacBridgeStatusItem()
}
self.networkMonitor = MacBridgeNetworkMonitor()
super.init()
MacBridgeAppDelegateHandler.swizzleAppDelegate()
for name: Notification.Name in [
NSApplication.didFinishLaunchingNotification,
NSApplication.didFinishRestoringWindowsNotification,
NSWindow.didBecomeKeyNotification,
] {
NotificationCenter.default.addObserver(self, selector: #selector(fixWindows), name: name, object: nil)
}
}
var deviceName: String {
SCDynamicStoreCopyComputerName(nil, nil) as? String ?? "Unknown"
}
var terminationWillBeginNotification: Notification.Name {
MacBridgeAppDelegateHandler.terminationWillBeginNotification
}
var distributedNotificationCenter: NotificationCenter {
DistributedNotificationCenter.default()
}
var workspaceNotificationCenter: NotificationCenter {
NSWorkspace.shared.notificationCenter
}
var networkConnectivity: MacBridgeNetworkConnectivity {
networkMonitor.networkConnectivity
}
var networkConnectivityDidChangeNotification: Notification.Name {
MacBridgeNetworkMonitor.connectivityDidChangeNotification
}
var screens: [MacBridgeScreen] {
NSScreen.screens.map(MacBridgeScreenImpl.init(screen:))
}
var screensWillChangeNotification: Notification.Name {
NSApplication.didChangeScreenParametersNotification
}
var frontmostApplication: MacBridgeRunningApplication? {
NSWorkspace.shared.frontmostApplication
}
var frontmostApplicationDidChangeNotification: Notification.Name {
NSWorkspace.didActivateApplicationNotification
}
var activationPolicy: MacBridgeActivationPolicy {
get {
switch NSApplication.shared.activationPolicy() {
case .regular: return .regular
case .accessory: return .accessory
case .prohibited: return .prohibited
@unknown default: return .regular
}
}
set {
if newValue != activationPolicy {
NSApplication.shared.setActivationPolicy({
switch newValue {
case .regular: return .regular
case .accessory: return .accessory
case .prohibited: return .prohibited
}
}())
NSApplication.shared.activate(ignoringOtherApps: true)
}
}
}
func configureStatusItem(using configuration: MacBridgeStatusItemConfiguration) {
statusItem?.configure(using: configuration)
}
func configureStatusItem(title: String) {
statusItem?.configure(title: title)
}
private static func userDefaultsKey(forLoginItemBundleIdentifier identifier: String) -> String {
"LoginItemEnabled-\(identifier)"
}
func setLoginItem(forBundleIdentifier identifier: String, enabled: Bool) -> Bool {
let success = SMLoginItemSetEnabled(identifier as CFString, enabled)
if success {
UserDefaults.standard.set(enabled, forKey: Self.userDefaultsKey(forLoginItemBundleIdentifier: identifier))
}
return success
}
func isLoginItemEnabled(forBundleIdentifier identifier: String) -> Bool {
// TODO: SMJobIsEnabled is the Apple-suggested method of getting this info, and it's also private API. lol.
UserDefaults.standard.bool(forKey: Self.userDefaultsKey(forLoginItemBundleIdentifier: identifier))
}
@objc private func fixWindows() {
// macOS 13 when using Xcode 14 breaks our window display, see: https://developer.apple.com/forums/thread/716623
guard #available(macOS 13, *) else { return }
for window in NSApplication.shared.windows {
if window.toolbar == nil || window.toolbar?.items.isEmpty == true {
window.titlebarAppearsTransparent = true
}
}
}
}
extension NSRunningApplication: MacBridgeRunningApplication {}