88---
99--- spoon.InputSourceSwitch:setApplications({
1010--- ["WeChat"] = "Pinyin - Simplified",
11- --- ["Mail"] = "ABC"
11+ --- ["Mail"] = "ABC",
12+ --- -- Use application watcher for apps that window filter can't capture
13+ --- ["kitty-quick-access"] = { source = "ABC", watcher = "application" }
1214--- })
1315---
1416--- spoon.InputSourceSwitch:start()
@@ -21,7 +23,7 @@ obj.__index = obj
2123
2224-- Metadata
2325obj .name = " InputSourceSwitch"
24- obj .version = " 1.0 "
26+ obj .version = " 1.1 "
2527obj .
author = " eks5115 <[email protected] >" 2628obj .homepage = " https://github.com/Hammerspoon/Spoons"
2729obj .license = " MIT - https://opensource.org/licenses/MIT"
@@ -52,43 +54,64 @@ local function isMethod(methodName)
5254 return false
5355end
5456
55- local function setAppInputSource (appName , sourceName , event )
57+ local function switchInputSource (sourceName , appName )
58+ local r = true
59+
60+ if (isLayout (sourceName )) then
61+ r = hs .keycodes .setLayout (sourceName )
62+ elseif isMethod (sourceName ) then
63+ r = hs .keycodes .setMethod (sourceName )
64+ else
65+ hs .alert .show (string.format (' sourceName: %s is not layout or method' , sourceName ))
66+ end
67+
68+ if (not r ) then
69+ hs .alert .show (string.format (' set %s to %s failure' , appName , sourceName ))
70+ end
71+ end
72+
73+ local function setAppInputSourceWithWindowFilter (appName , sourceName , event )
5674 event = event or hs .window .filter .windowFocused
5775
5876 hs .window .filter .new (appName ):subscribe (event , function ()
59- local r = true
60-
61- if (isLayout (sourceName )) then
62- r = hs .keycodes .setLayout (sourceName )
63- elseif isMethod (sourceName ) then
64- r = hs .keycodes .setMethod (sourceName )
65- else
66- hs .alert .show (string.format (' sourceName: %s is not layout or method' , sourceName ))
67- end
77+ switchInputSource (sourceName , appName )
78+ end )
79+ end
6880
69- if (not r ) then
70- hs .alert .show (string.format (' set %s to %s failure' , appName , sourceName ))
81+ local function setAppInputSourceWithAppWatcher (appName , sourceName )
82+ local watcher = hs .application .watcher .new (function (name , eventType , appObj )
83+ if eventType == hs .application .watcher .activated and name == appName then
84+ switchInputSource (sourceName , appName )
7185 end
72- end )
86+ end )
87+ watcher :start ()
88+ return watcher
7389end
7490
7591--- InputSourceSwitch.applicationMap
7692--- Variable
7793--- Mapping the application name to the input source
7894obj .applicationsMap = {}
7995
96+ -- Store application watchers to prevent garbage collection
97+ obj .appWatchers = {}
98+
8099--- InputSourceSwitch:setApplications()
81100--- Method
82101--- Set that mapping the application name to the input source
83102---
84103--- Parameters:
85104--- * applications - A table containing that mapping the application name to the input source
86- --- key is the application name and value is the input source name
105+ --- key is the application name
106+ --- value can be:
107+ --- - a string: the input source name (uses window filter, default)
108+ --- - a table: { source = "input source name", watcher = "window" | "application" }
87109--- example:
88110--- ```
89111--- {
90112--- ["WeChat"] = "Pinyin - Simplified",
91- --- ["Mail"] = "ABC"
113+ --- ["Mail"] = "ABC",
114+ --- ["kitty-quick-access"] = { source = "ABC", watcher = "application" }
92115--- }
93116--- ```
94117function obj :setApplications (applications )
104127--- Parameters:
105128--- * None
106129function obj :start ()
107- for k ,v in pairs (self .applicationsMap ) do
108- setAppInputSource (k , v )
130+ for appName , config in pairs (self .applicationsMap ) do
131+ local sourceName , watcherType
132+
133+ if type (config ) == " string" then
134+ sourceName = config
135+ watcherType = " window"
136+ else
137+ sourceName = config .source
138+ watcherType = config .watcher or " window"
139+ end
140+
141+ if watcherType == " application" then
142+ self .appWatchers [appName ] = setAppInputSourceWithAppWatcher (appName , sourceName )
143+ else
144+ setAppInputSourceWithWindowFilter (appName , sourceName )
145+ end
109146 end
110147 return self
111148end
0 commit comments