-
-
Notifications
You must be signed in to change notification settings - Fork 2
/
photkey.lua
118 lines (104 loc) · 2.54 KB
/
photkey.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
local photkey = {}
local keyDown = hs.eventtap.event.types.keyDown
local knu = hs.loadSpoon("Knu")
local runtime = knu.runtime
local utils = knu.utils
local keyboard = knu.keyboard
photkey.methods = {
-- Provide hotkey compatible API for convenience
enable = function (self)
return self:start()
end,
disable = function (self)
return self:stop()
end,
delete = function (self)
return runtime.unguard(self:stop())
end,
}
local meta = {
__index = function (self, key)
local tap = self.tap
local value = photkey.methods[key] or tap[key]
if type(value) == "function" then
return function (self, ...)
local ret = value(tap, ...)
if ret == tap then
return self
end
return ret
end
else
return value
end
end
}
-- Creates a pseudo hotkey
--
-- A pseudo hotkey is implemented by using eventtap, allowing for
-- specifying pseudo modifiers listed below:
--
-- * leftshift, rightshift, leftctrl, rightctrl, leftalt, rightalt,
-- leftcmd, rightcmd and fn
--
-- The handler function is called with a key event.
--
-- The types paramter specifies the event types to capture, defaulted
-- to { hs.eventtap.event.types.keyDown }.
photkey.new = function (pmods, key, fn, types)
types = types or { keyDown }
local modState = keyboard.getModifierState()
local mods = {}
local modLr = {}
for _, pmod in ipairs(pmods) do
local mod = pmod:match("left(.+)")
if mod then
modLr[mod] = (modLr[mod] or 0) | 1
else
mod = pmod:match("right(.+)")
if mod then
modLr[mod] = (modLr[mod] or 0) | 2
else
mod = pmod
end
end
if modState[mod] == nil then
error("unknown modifier: " .. pmod)
end
mods[#mods+1] = mod
end
local code
if type(key) == "number" then
code = key
else
code = hs.keycodes.map[key]
end
local tap = hs.eventtap.new(
types,
function (e)
if e:getKeyCode() ~= code or not e:getFlags():containExactly(mods) then
return
end
for mod, lr in pairs(modLr) do
local modStateLr = 0
if modState[mod][1] then
modStateLr = modStateLr | 1
end
if modState[mod][2] then
modStateLr = modStateLr | 2
end
if modStateLr ~= lr then
return
end
end
fn(e)
return true
end
)
return runtime.guard(setmetatable({ tap = tap }, meta))
end
-- Shortcut for knu.photkey.new(...):start()
photkey.bind = function (...)
return photkey.new(...):start()
end
return photkey