Skip to content

Commit 30b843f

Browse files
committed
all: allow unregister hotkeys (linux, x11)
Updates #5, #7
1 parent 05d9e57 commit 30b843f

File tree

5 files changed

+55
-18
lines changed

5 files changed

+55
-18
lines changed

hotkey_linux.go

Lines changed: 41 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,11 @@ int displayTest();
1515
int waitHotkey(unsigned int mod, int key);
1616
*/
1717
import "C"
18-
import "context"
18+
import (
19+
"context"
20+
"errors"
21+
"sync"
22+
)
1923

2024
const errmsg = `Failed to initialize the X11 display, and the clipboard package
2125
will not work properly. Install the following dependency may help:
@@ -36,17 +40,46 @@ func init() {
3640
}
3741
}
3842

43+
type platformHotkey struct {
44+
mu sync.Mutex
45+
registered bool
46+
ctx context.Context
47+
cancel context.CancelFunc
48+
canceled chan struct{}
49+
}
50+
3951
// Nothing needs to do for register
40-
func (hk *Hotkey) register() error { return nil }
52+
func (hk *Hotkey) register() error {
53+
hk.mu.Lock()
54+
if hk.registered {
55+
hk.mu.Unlock()
56+
return errors.New("hotkey already registered.")
57+
}
58+
hk.registered = true
59+
hk.ctx, hk.cancel = context.WithCancel(context.Background())
60+
hk.canceled = make(chan struct{})
61+
hk.mu.Unlock()
62+
63+
go hk.handle()
64+
return nil
65+
}
4166

4267
// Nothing needs to do for unregister
43-
func (hk *Hotkey) unregister() {}
68+
func (hk *Hotkey) unregister() error {
69+
hk.mu.Lock()
70+
defer hk.mu.Unlock()
71+
if !hk.registered {
72+
return errors.New("hotkey is not registered.")
73+
}
74+
hk.cancel()
75+
hk.registered = false
76+
<-hk.canceled
77+
return nil
78+
}
4479

4580
// handle registers an application global hotkey to the system,
4681
// and returns a channel that will signal if the hotkey is triggered.
47-
//
48-
// No customization for the hotkey, the hotkey is always: Ctrl+Mod4+s
49-
func (hk *Hotkey) handle(ctx context.Context) {
82+
func (hk *Hotkey) handle() {
5083
// KNOWN ISSUE: if a hotkey is grabbed by others, C side will crash the program
5184

5285
var mod Modifier
@@ -55,7 +88,8 @@ func (hk *Hotkey) handle(ctx context.Context) {
5588
}
5689
for {
5790
select {
58-
case <-ctx.Done():
91+
case <-hk.ctx.Done():
92+
close(hk.canceled)
5993
return
6094
default:
6195
ret := C.waitHotkey(C.uint(mod), C.int(hk.key))

hotkey_linux_test.go

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,24 +21,20 @@ import (
2121
// This is a test to run and for manually testing, registered combination:
2222
// Ctrl+Alt+A (Ctrl+Mod2+Mod4+A on Linux)
2323
func TestHotkey(t *testing.T) {
24-
tt := time.Second * 5
25-
26-
ctx, cancel := context.WithTimeout(context.Background(), tt)
24+
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
2725
defer cancel()
2826

29-
hk, err := hotkey.Register([]hotkey.Modifier{
27+
hk := hotkey.New([]hotkey.Modifier{
3028
hotkey.ModCtrl, hotkey.Mod2, hotkey.Mod4}, hotkey.KeyA)
31-
if err != nil {
29+
if err := hk.Register(); err != nil {
3230
t.Errorf("failed to register hotkey: %v", err)
3331
return
3432
}
35-
36-
trigger := hk.Listen(ctx)
3733
for {
3834
select {
3935
case <-ctx.Done():
4036
return
41-
case <-trigger:
37+
case <-hk.Listen():
4238
fmt.Println("triggered")
4339
}
4440
}

hotkey_nocgo.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ package hotkey
1010

1111
import "context"
1212

13+
type platformHotkey struct{}
14+
1315
// Modifier represents a modifier
1416
type Modifier uint32
1517

@@ -21,7 +23,7 @@ func (hk *Hotkey) register() error {
2123
}
2224

2325
// unregister deregisteres a system hotkey.
24-
func (hk *Hotkey) unregister() {
26+
func (hk *Hotkey) unregister() error {
2527
panic("hotkey: cannot use when CGO_ENABLED=0")
2628
}
2729

hotkey_nocgo_test.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,5 +25,10 @@ func TestHotkey(t *testing.T) {
2525
t.Fatalf("expect to fail when CGO_ENABLED=0")
2626
}()
2727

28-
hotkey.Register([]hotkey.Modifier{}, hotkey.Key(0))
28+
hk := hotkey.New([]hotkey.Modifier{}, hotkey.Key(0))
29+
err := hk.Register()
30+
if err != nil {
31+
t.Fatal(err)
32+
}
33+
hk.Unregister()
2934
}

mainthread/os.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
//
55
// Written by Changkun Ou <changkun.de>
66

7-
//go:build !darwin
7+
//go:build windows || linux || (darwin && !cgo)
88

99
package mainthread
1010

0 commit comments

Comments
 (0)