-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathapplicationWatcher.lua
255 lines (213 loc) · 6.48 KB
/
applicationWatcher.lua
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
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
-- Application Watcher
-- listen application's events, such as keystroke and application starts
local json_encode = hs.json.encode
local json_decode = hs.json.decode
local M = {}
M.logger = hs.logger.new('appWatch')
local yabai = require('window')
local myApp = require("app.app")
local log = M.logger
log.setLogLevel('debug')
local HYPER = { 'ctrl', 'alt', 'cmd', 'shift' }
local HYPER_MINUS_SHIFT = { 'ctrl', 'alt', 'cmd' }
local emacsCtrlSpaceSwitchIM = hs.hotkey.new('ctrl', 'space', function()
local topWindow = hs.window:frontmostWindow()
if topWindow ~= nil then
local topApp = topWindow:application()
if topApp ~= nil then
local bunderID = topApp:bundleID()
logger:d('bunderID is: ', bunderID)
if bunderID == 'org.gnu.Emacs' then hs.eventtap.keyStroke({ 'ctrl' }, '\\') end
end
end
end)
local vscodeGitLens = hs.hotkey.new(HYPER_MINUS_SHIFT, "g", function()
local win = hs.window.focusedWindow()
if (win == nil) or (win:id() == nil) then return end
local app = win:application()
local appBundleID = app:bundleID()
-- log.ef('appBundleID is: ' .. appBundleID)
if appBundleID == 'com.microsoft.VSCode' or appBundleID == 'com.microsoft.VSCodeInsiders' then
hs.eventtap.keyStroke({ 'ctrl', 'shift' }, 'g', app)
end
end)
-- -- space control
-- local function getSpacesList()
-- local spaces_list = {}
-- local layout = hs.spaces.allSpaces()
-- for _, screen in ipairs(hs.screen.allScreens()) do
-- for _, space in ipairs(layout[screen:getUUID()]) do
-- table.insert(spaces_list, space)
-- end
-- end
-- return spaces_list
-- end
-- local function switchToSpace(index)
-- local space = getSpacesList()[index]
-- if not space then
-- return
-- end
-- hs.spaces.gotoSpace(space)
-- end
-- local function moveWindowToSpace(index)
-- local focused_window = hs.window.focusedWindow()
-- if not focused_window then
-- return
-- end
-- local space = getSpacesList()[index]
-- if not space then
-- return
-- end
-- if hs.spaces.spaceType(space) ~= "user" then
-- return
-- end
-- local screen = hs.screen.find(hs.spaces.spaceDisplay(space))
-- if not screen then
-- return
-- end
-- hs.spaces.moveWindowToSpace(focused_window, space)
-- hs.spaces.gotoSpace(space)
-- end
local moveAppToSpace = function(app, destSpaceLabel)
if not app then
log.e("app is nil")
return
end
if not destSpaceLabel then
log.e("destSpaceLabel is nil")
return
end
local space = yabai:get_space_with_label(destSpaceLabel)
if not space then
log.e("space is nil")
return
end
local appName = app:name()
local win = app:focusedWindow()
if not win then
log.ef("win is nil, appName: %s", appName)
return
end
local spaceId = space.mId
if not spaceId then
log.ef("spaceId is nil")
return
end
local spaceType = hs.spaces.spaceType(spaceId)
if spaceType ~= "user" then
log.ef("spaceType is not user: %s", spaceType)
return
end
local screen = hs.screen.find(hs.spaces.spaceDisplay(spaceId))
if not screen then
log.ef("move to space, not screen")
return
end
local oldSpace = hs.spaces.focusedSpace()
if oldSpace == spaceId then
-- log.ef("oldSpaceId: %d is equal to destSpaceId: %d",
-- oldSpace, spaceId)
return
end
log.df("move %s to space: %d, oldSpace: %d", appName, space.mId, oldSpace)
local ok, err = hs.spaces.moveWindowToSpace(win, spaceId, true)
if not ok then
log.ef("error move window to space: %s", err)
return
end
-- log.df("space: %s", json_encode(space))
ok, err = hs.spaces.gotoSpace(spaceId)
if not ok then
log.ef("error goto space: %s", err)
return
end
-- focuse window
win:focus()
end
local emacsFocusIn = function(app, statup)
if startup then
-- move to space 2
moveAppToSpace(app, "Emacs")
end
emacsCtrlSpaceSwitchIM:enable()
myApp:updateInputMethod()
-- hs.timer.doAfter(1, function()
-- -- make maximaze window
-- local win = app and app:focusedWindow()
-- if win then
-- win:maximize()
-- end
-- end)
end
local emacsFocusOut = function(app) emacsCtrlSpaceSwitchIM:disable() end
-- NOTE: Use local function for any internal funciton not exported (not included as a part of the return)
local applicationWatcher = function(appName, event, app)
local emacsAppName = 'Emacs'
local vsCodeAppName = "Code"
local isEmacsApp = emacsAppName == appName
local isVscodeApp = vsCodeAppName == appName
local isBrowersApp = appName == "Google Chrome" or appName == "Firefox" or appName ==
"Stack Next SE" or appName == 'Safari'
-- log.df("event is, app: %s, event: %s, isEmacsApp: %s, isdDeactivated: %s",
-- appName, event, tostring(isEmacsApp), tostring(event == hs.application.watcher.deactivated))
-- if (event == hs.application.watcher.activated) then
if (event == hs.application.watcher.deactivated) then
if isEmacsApp then emacsCtrlSpaceSwitchIM:disable() end
if isVscodeApp then vscodeGitLens:disable() end
-- elseif (eventType == hs.application.watcher.launched) then
-- if isEmacsApp then
-- hs.eventtap.keyStroke({
-- 'alt',
-- }, 'F10')
-- end
else
if (appName == "Finder") then
app:selectMenuItem({ "Window", "Bring All to Front" }) -- Bring all Finder windows forward when one gets activated
elseif isEmacsApp then
emacsCtrlSpaceSwitchIM:enable()
elseif isVscodeApp then
vscodeGitLens:enable()
elseif isBrowersApp then
-- make frontMostApp maximum
-- yabai:force_fullscreen()
end
end
end
M.watcher = hs.application.watcher.new(applicationWatcher)
local function urlEvent(eventName, params)
local action = params and params.action
local pid = params and params.pid
if pid and pid ~= '' then pid = tonumber(pid) end
-- log.df("pid is: %d", (params.pid or ''))
if not pid then
log.ef("pid is not number: %s", (params.pid or ''))
return
end
local app = hs.application.applicationForPID(pid)
if not app then
log.ef("process does not exist")
return
end
if eventName == 'Emacs' then
if action == "FocusIn" then
emacsFocusIn(app, false)
elseif action == "StartUp" then
emacsFocusIn(app, true)
elseif action == "FocusOut" then
emacsFocusOut(app)
end
end
end
function M:start()
log.i("Starting Application Watcher")
M.watcher:start()
-- bind emacs event
hs.urlevent.bind('Emacs', urlEvent)
return M
end
function M:stop()
log.i("Stopping Application Watcher")
M.watcher:stop()
return M
end
return M