-
-
Notifications
You must be signed in to change notification settings - Fork 10
/
hotkey_darwin.go
176 lines (155 loc) · 3.81 KB
/
hotkey_darwin.go
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
// Copyright 2021 The golang.design Initiative Authors.
// All rights reserved. Use of this source code is governed
// by a MIT license that can be found in the LICENSE file.
//
// Written by Changkun Ou <changkun.de>
//go:build darwin
package hotkey
/*
#cgo CFLAGS: -x objective-c
#cgo LDFLAGS: -framework Cocoa -framework Carbon
#include <stdint.h>
#import <Cocoa/Cocoa.h>
#import <Carbon/Carbon.h>
extern void keydownCallback(uintptr_t handle);
extern void keyupCallback(uintptr_t handle);
int registerHotKey(int mod, int key, uintptr_t handle, EventHotKeyRef* ref);
int unregisterHotKey(EventHotKeyRef ref);
*/
import "C"
import (
"errors"
"runtime/cgo"
"sync"
)
// Hotkey is a combination of modifiers and key to trigger an event
type platformHotkey struct {
mu sync.Mutex
registered bool
hkref C.EventHotKeyRef
}
func (hk *Hotkey) register() error {
hk.mu.Lock()
defer hk.mu.Unlock()
if hk.registered {
return errors.New("hotkey already registered")
}
// Note: we use handle number as hotkey id in the C side.
// A cgo handle could ran out of space, but since in hotkey purpose
// we won't have that much number of hotkeys. So this should be fine.
h := cgo.NewHandle(hk)
var mod Modifier
for _, m := range hk.mods {
mod += m
}
ret := C.registerHotKey(C.int(mod), C.int(hk.key), C.uintptr_t(h), &hk.hkref)
if ret == C.int(-1) {
return errors.New("failed to register the hotkey")
}
hk.registered = true
return nil
}
func (hk *Hotkey) unregister() error {
hk.mu.Lock()
defer hk.mu.Unlock()
if !hk.registered {
return errors.New("hotkey is not registered")
}
ret := C.unregisterHotKey(hk.hkref)
if ret == C.int(-1) {
return errors.New("failed to unregister the current hotkey")
}
hk.registered = false
return nil
}
//export keydownCallback
func keydownCallback(h uintptr) {
hk := cgo.Handle(h).Value().(*Hotkey)
hk.keydownIn <- Event{}
}
//export keyupCallback
func keyupCallback(h uintptr) {
hk := cgo.Handle(h).Value().(*Hotkey)
hk.keyupIn <- Event{}
}
// Modifier represents a modifier.
// See: /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/HIToolbox.framework/Versions/A/Headers/Events.h
type Modifier uint32
// All kinds of Modifiers
const (
ModCtrl Modifier = 0x1000
ModShift Modifier = 0x200
ModOption Modifier = 0x800
ModCmd Modifier = 0x100
)
// Key represents a key.
// See: /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/HIToolbox.framework/Versions/A/Headers/Events.h
type Key uint8
// All kinds of keys
const (
KeySpace Key = 49
Key1 Key = 18
Key2 Key = 19
Key3 Key = 20
Key4 Key = 21
Key5 Key = 23
Key6 Key = 22
Key7 Key = 26
Key8 Key = 28
Key9 Key = 25
Key0 Key = 29
KeyA Key = 0
KeyB Key = 11
KeyC Key = 8
KeyD Key = 2
KeyE Key = 14
KeyF Key = 3
KeyG Key = 5
KeyH Key = 4
KeyI Key = 34
KeyJ Key = 38
KeyK Key = 40
KeyL Key = 37
KeyM Key = 46
KeyN Key = 45
KeyO Key = 31
KeyP Key = 35
KeyQ Key = 12
KeyR Key = 15
KeyS Key = 1
KeyT Key = 17
KeyU Key = 32
KeyV Key = 9
KeyW Key = 13
KeyX Key = 7
KeyY Key = 16
KeyZ Key = 6
KeyReturn Key = 0x24
KeyEscape Key = 0x35
KeyDelete Key = 0x33
KeyTab Key = 0x30
KeyLeft Key = 0x7B
KeyRight Key = 0x7C
KeyUp Key = 0x7E
KeyDown Key = 0x7D
KeyF1 Key = 0x7A
KeyF2 Key = 0x78
KeyF3 Key = 0x63
KeyF4 Key = 0x76
KeyF5 Key = 0x60
KeyF6 Key = 0x61
KeyF7 Key = 0x62
KeyF8 Key = 0x64
KeyF9 Key = 0x65
KeyF10 Key = 0x6D
KeyF11 Key = 0x67
KeyF12 Key = 0x6F
KeyF13 Key = 0x69
KeyF14 Key = 0x6B
KeyF15 Key = 0x71
KeyF16 Key = 0x6A
KeyF17 Key = 0x40
KeyF18 Key = 0x4F
KeyF19 Key = 0x50
KeyF20 Key = 0x5A
)