forked from laishulu/macism
-
-
Notifications
You must be signed in to change notification settings - Fork 9
/
Copy pathAppDelegate.swift
156 lines (130 loc) · 5.42 KB
/
AppDelegate.swift
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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
import Cocoa
class AppDelegate: NSObject, NSApplicationDelegate, KeyboardManagerDelegate {
let statusBarManager = StatusBarManager()
// 存储允许的应用bundle identifiers
var allowedApps: Set<String> {
get { UserPreferences.shared.allowedApps }
set { UserPreferences.shared.allowedApps = newValue }
}
// 用于存储系统中的应用列表
var systemApps: [(name: String, bundleId: String)] = []
func applicationDidFinishLaunching(_ notification: Notification) {
print("应用程序开始初始化...")
// 确保应用程序被激活
NSApp.activate(ignoringOtherApps: true)
print("应用程序已激活")
// 确保应用不会随终端退出
ProcessInfo.processInfo.enableSuddenTermination()
print("已启用突然终止")
// 加载系统应用列表
loadSystemApps()
print("已加载系统应用列表,共 \(systemApps.count) 个应用")
// 设置代理
KeyboardManager.shared.delegate = self
statusBarManager.appDelegate = self
print("已设置键盘管理器代理")
// 设置状态栏和菜单
print("开始设置状态栏和菜单...")
DispatchQueue.main.async { [weak self] in
self?.statusBarManager.setupStatusBarItem()
print("状态栏和菜单设置完成")
}
// 启动键盘管理器
print("开始启动键盘管理器...")
KeyboardManager.shared.start()
print("键盘管理器启动完成")
// 显示初始使用提示
DispatchQueue.main.async { [weak self] in
self?.showInitialInstructions()
print("初始使用提示已显示")
}
print("应用程序初始化完成")
}
// 加载系统应用列表
private func loadSystemApps() {
let workspace = NSWorkspace.shared
// 获取常用应用程序目录
let appDirs = [
"/Applications",
"~/Applications",
"/System/Applications"
].map { NSString(string: $0).expandingTildeInPath }
var apps: [(name: String, bundleId: String)] = []
// 遍历应用程序目录
for dir in appDirs {
if let contents = try? FileManager.default.contentsOfDirectory(atPath: dir) {
for item in contents {
if item.hasSuffix(".app") {
let path = (dir as NSString).appendingPathComponent(item)
if let bundle = Bundle(path: path),
let bundleId = bundle.bundleIdentifier,
let appName = bundle.infoDictionary?["CFBundleName"] as? String {
apps.append((name: appName, bundleId: bundleId))
}
}
}
}
}
// 添加当前正在运行的应用
let runningApps = workspace.runningApplications
for app in runningApps {
if let bundleId = app.bundleIdentifier,
let appName = app.localizedName,
!apps.contains(where: { $0.bundleId == bundleId }) {
apps.append((name: appName, bundleId: bundleId))
}
}
// 按应用名称排序
systemApps = apps.sorted { $0.name < $1.name }
}
@objc func toggleApp(_ sender: NSMenuItem) {
guard let bundleId = sender.representedObject as? String else { return }
if allowedApps.contains(bundleId) {
allowedApps.remove(bundleId)
sender.state = .off
} else {
allowedApps.insert(bundleId)
sender.state = .on
}
}
@objc func refreshAppList() {
loadSystemApps()
statusBarManager.createAndShowMenu()
}
// 检查当前应用是否允许使用ESC切换输入法
private func isCurrentAppAllowed() -> Bool {
if let frontmostApp = NSWorkspace.shared.frontmostApplication {
return allowedApps.contains(frontmostApp.bundleIdentifier ?? "")
}
return false
}
// 在切换输入法前检查当前应用
func shouldSwitchInputSource() -> Bool {
return isCurrentAppAllowed()
}
// 实现代理方法
func keyboardManagerDidUpdateState() {
statusBarManager.updateStatusBarIcon()
}
private func showInitialInstructions() {
let alert = NSAlert()
alert.messageText = "MacVimSwitch 使用说明"
alert.informativeText = """
重要示:
1. 先关闭输入法中的"使用 Shift 切换中英文"选项,否则会产生冲突
2. 具体操作:打开输入法偏好设置 → 关闭"使用 Shift 切换中英文"
功能说明:
1. 按 ESC 键会自动切换到英文输入法 ABC(仅在指定的应用中生效)
2. 按 Shift 键可以在中英文输入法之间切换(可在菜单栏中关闭)
3. 提示:在 Mac 上,CapsLock 短按可以切换输入法,长按才是锁定大写
配置说明:
1. 点击菜单栏图标 → 启用的应用,可以选择需要启用ESC切换功能的应用
2. 如果没有看到某个应用,可以点击"刷新应用列表"更新
"""
alert.alertStyle = .warning
alert.addButton(withTitle: "我已了解")
DispatchQueue.main.async {
alert.runModal()
}
}
}