@@ -2,31 +2,147 @@ import Cocoa
22
33class AppDelegate : NSObject , NSApplicationDelegate , KeyboardManagerDelegate {
44 let statusBarManager = StatusBarManager ( )
5-
5+ // 存储允许的应用bundle identifiers
6+ var allowedApps : Set < String > = [ ]
7+ // 用于存储系统中的应用列表
8+ var systemApps : [ ( name: String , bundleId: String ) ] = [ ]
9+
610 func applicationDidFinishLaunching( _ notification: Notification ) {
11+ print ( " 应用程序开始初始化... " )
12+
713 // 确保应用程序被激活
814 NSApp . activate ( ignoringOtherApps: true )
15+ print ( " 应用程序已激活 " )
916
1017 // 确保应用不会随终端退出
1118 ProcessInfo . processInfo. enableSuddenTermination ( )
19+ print ( " 已启用突然终止 " )
20+
21+ // 加载默认配置
22+ loadDefaultConfig ( )
23+ print ( " 已加载默认配置 " )
24+
25+ // 加载系统应用列表
26+ loadSystemApps ( )
27+ print ( " 已加载系统应用列表,共 \( systemApps. count) 个应用 " )
1228
1329 // 设置代理
1430 KeyboardManager . shared. delegate = self
31+ statusBarManager. appDelegate = self
32+ print ( " 已设置键盘管理器代理 " )
1533
16- // 先设置状态栏
34+ // 设置状态栏和菜单
35+ print ( " 开始设置状态栏和菜单... " )
1736 DispatchQueue . main. async { [ weak self] in
1837 self ? . statusBarManager. setupStatusBarItem ( )
38+ print ( " 状态栏和菜单设置完成 " )
1939 }
2040
21- // 然后启动键盘管理器
41+ // 启动键盘管理器
42+ print ( " 开始启动键盘管理器... " )
2243 KeyboardManager . shared. start ( )
44+ print ( " 键盘管理器启动完成 " )
2345
2446 // 显示初始使用提示
2547 DispatchQueue . main. async { [ weak self] in
2648 self ? . showInitialInstructions ( )
49+ print ( " 初始使用提示已显示 " )
50+ }
51+
52+ print ( " 应用程序初始化完成 " )
53+ }
54+
55+ // 加载默认配置
56+ private func loadDefaultConfig( ) {
57+ allowedApps = Set ( [
58+ " com.apple.Terminal " ,
59+ " com.microsoft.VSCode " ,
60+ " com.vim.MacVim " ,
61+ " com.exafunction.windsurf " ,
62+ " md.obsidian " ,
63+ " dev.warp.Warp-Stable " ,
64+ " com.todesktop.230313mzl4w4u92 "
65+ ] )
66+ }
67+
68+ // 加载系统应用列表
69+ private func loadSystemApps( ) {
70+ let workspace = NSWorkspace . shared
71+
72+ // 获取常用应用程序目录
73+ let appDirs = [
74+ " /Applications " ,
75+ " ~/Applications " ,
76+ " /System/Applications "
77+ ] . map { NSString ( string: $0) . expandingTildeInPath }
78+
79+ var apps : [ ( name: String , bundleId: String ) ] = [ ]
80+
81+ // 遍历应用程序目录
82+ for dir in appDirs {
83+ if let contents = try ? FileManager . default. contentsOfDirectory ( atPath: dir) {
84+ for item in contents {
85+ if item. hasSuffix ( " .app " ) {
86+ let path = ( dir as NSString ) . appendingPathComponent ( item)
87+ if let bundle = Bundle ( path: path) ,
88+ let bundleId = bundle. bundleIdentifier,
89+ let appName = bundle. infoDictionary ? [ " CFBundleName " ] as? String {
90+ apps. append ( ( name: appName, bundleId: bundleId) )
91+ }
92+ }
93+ }
94+ }
95+ }
96+
97+ // 添加当前正在运行的应用
98+ let runningApps = workspace. runningApplications
99+ for app in runningApps {
100+ if let bundleId = app. bundleIdentifier,
101+ let appName = app. localizedName,
102+ !apps. contains ( where: { $0. bundleId == bundleId } ) {
103+ apps. append ( ( name: appName, bundleId: bundleId) )
104+ }
105+ }
106+
107+ // 按应用名称排序
108+ systemApps = apps. sorted { $0. name < $1. name }
109+ }
110+
111+ @objc func toggleApp( _ sender: NSMenuItem ) {
112+ guard let bundleId = sender. representedObject as? String else { return }
113+
114+ if allowedApps. contains ( bundleId) {
115+ allowedApps. remove ( bundleId)
116+ sender. state = . off
117+ } else {
118+ allowedApps. insert ( bundleId)
119+ sender. state = . on
120+ }
121+ }
122+
123+ @objc func refreshAppList( ) {
124+ loadSystemApps ( )
125+ statusBarManager. createAndShowMenu ( )
126+ }
127+
128+ // 检查当前应用是否允许使用ESC切换输入法
129+ private func isCurrentAppAllowed( ) -> Bool {
130+ if let frontmostApp = NSWorkspace . shared. frontmostApplication {
131+ return allowedApps. contains ( frontmostApp. bundleIdentifier ?? " " )
27132 }
133+ return false
28134 }
29-
135+
136+ // 在切换输入法前检查当前应用
137+ func shouldSwitchInputSource( ) -> Bool {
138+ return isCurrentAppAllowed ( )
139+ }
140+
141+ // 实现代理方法
142+ func keyboardManagerDidUpdateState( ) {
143+ statusBarManager. updateStatusBarIcon ( )
144+ }
145+
30146 private func showInitialInstructions( ) {
31147 let alert = NSAlert ( )
32148 alert. messageText = " MacVimSwitch 使用说明 "
@@ -36,34 +152,19 @@ class AppDelegate: NSObject, NSApplicationDelegate, KeyboardManagerDelegate {
36152 2. 具体操作:打开输入法偏好设置 → 关闭 " 使用 Shift 切换中英文 "
37153
38154 功能说明:
39- 1. 按 ESC 键会自动切换到英文输入法 ABC
155+ 1. 按 ESC 键会自动切换到英文输入法 ABC(仅在指定的应用中生效)
40156 2. 按 Shift 键可以在中英文输入法之间切换(可在菜单栏中关闭)
41157 3. 提示:在 Mac 上,CapsLock 短按可以切换输入法,长按才是锁定大写
158+
159+ 配置说明:
160+ 1. 点击菜单栏图标 → 启用的应用,可以选择需要启用ESC切换功能的应用
161+ 2. 如果没有看到某个应用,可以点击 " 刷新应用列表 " 更新
42162 """
43163 alert. alertStyle = . warning
44164 alert. addButton ( withTitle: " 我已了解 " )
45165
46166 DispatchQueue . main. async {
47- let window = NSWindow (
48- contentRect: NSRect ( x: 0 , y: 0 , width: 100 , height: 100 ) ,
49- styleMask: [ . titled] ,
50- backing: . buffered,
51- defer: false
52- )
53- window. level = . floating
54-
55- NSApp . activate ( ignoringOtherApps: true )
56167 alert. runModal ( )
57168 }
58169 }
59-
60- // 实现代理方法
61- func keyboardManagerDidUpdateState( ) {
62- statusBarManager. updateStatusBarIcon ( )
63- statusBarManager. createAndShowMenu ( )
64- }
65-
66- func applicationWillTerminate( _ notification: Notification ) {
67- KeyboardManager . shared. disableEventTap ( )
68- }
69170}
0 commit comments