This repository has been archived by the owner on Feb 16, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 343
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Implement global shortcuts * No need to remove callback from map when unregistering a shortcut The relevant event will no longer be triggered after the shortcut is unregistered. If the same key is registered again, the original callback will be replaced with new one. Therefore, we don't need to find the registered key from the map. Besides, we don't need to parse the accelerator, too. An error will be returned if the method failed. * Add test case and doc 1. Add test case 2. Add doc to README.md 3. Handle `ctx.Err` in functions * Updated * Updated * Updated * Updated * Updated * Updated
- Loading branch information
Showing
5 changed files
with
253 additions
and
52 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
package astilectron | ||
|
||
import ( | ||
"context" | ||
"sync" | ||
) | ||
|
||
const ( | ||
EventNameGlobalShortcutsCmdRegister = "global.shortcuts.cmd.register" | ||
EventNameGlobalShortcutsCmdIsRegistered = "global.shortcuts.cmd.is.registered" | ||
EventNameGlobalShortcutsCmdUnregister = "global.shortcuts.cmd.unregister" | ||
EventNameGlobalShortcutsCmdUnregisterAll = "global.shortcuts.cmd.unregister.all" | ||
EventNameGlobalShortcutsEventRegistered = "global.shortcuts.event.registered" | ||
EventNameGlobalShortcutsEventIsRegistered = "global.shortcuts.event.is.registered" | ||
EventNameGlobalShortcutsEventUnregistered = "global.shortcuts.event.unregistered" | ||
EventNameGlobalShortcutsEventUnregisteredAll = "global.shortcuts.event.unregistered.all" | ||
EventNameGlobalShortcutEventTriggered = "global.shortcuts.event.triggered" | ||
) | ||
|
||
type globalShortcutsCallback func() | ||
|
||
// GlobalShortcuts represents global shortcuts | ||
type GlobalShortcuts struct { | ||
*object | ||
m *sync.Mutex | ||
callbacks map[string]globalShortcutsCallback | ||
} | ||
|
||
func newGlobalShortcuts(ctx context.Context, d *dispatcher, i *identifier, w *writer) (gs *GlobalShortcuts) { | ||
gs = &GlobalShortcuts{ | ||
object: newObject(ctx, d, i, w, i.new()), | ||
m: new(sync.Mutex), | ||
callbacks: make(map[string]globalShortcutsCallback), | ||
} | ||
gs.On(EventNameGlobalShortcutEventTriggered, func(e Event) (deleteListener bool) { // Register the listener for the triggered event | ||
gs.m.Lock() | ||
callback, ok := gs.callbacks[e.GlobalShortcuts.Accelerator] | ||
gs.m.Unlock() | ||
if ok { | ||
(callback)() | ||
} | ||
return | ||
}) | ||
return | ||
} | ||
|
||
// Register registers a global shortcut | ||
func (gs *GlobalShortcuts) Register(accelerator string, callback globalShortcutsCallback) (isRegistered bool, err error) { | ||
if err = gs.ctx.Err(); err != nil { | ||
return | ||
} | ||
|
||
// Send an event to astilectron to register the global shortcut | ||
result, err := synchronousEvent(gs.ctx, gs, gs.w, Event{Name: EventNameGlobalShortcutsCmdRegister, TargetID: gs.id, GlobalShortcuts: &EventGlobalShortcuts{Accelerator: accelerator}}, EventNameGlobalShortcutsEventRegistered) | ||
if err != nil { | ||
return | ||
} | ||
|
||
// If registered successfully, add the callback to the map | ||
if result.GlobalShortcuts != nil { | ||
if result.GlobalShortcuts.IsRegistered { | ||
gs.m.Lock() | ||
gs.callbacks[accelerator] = callback | ||
gs.m.Unlock() | ||
} | ||
isRegistered = result.GlobalShortcuts.IsRegistered | ||
} | ||
return | ||
} | ||
|
||
// IsRegistered checks whether a global shortcut is registered | ||
func (gs *GlobalShortcuts) IsRegistered(accelerator string) (isRegistered bool, err error) { | ||
if err = gs.ctx.Err(); err != nil { | ||
return | ||
} | ||
|
||
// Send an event to astilectron to check if global shortcut is registered | ||
result, err := synchronousEvent(gs.ctx, gs, gs.w, Event{Name: EventNameGlobalShortcutsCmdIsRegistered, TargetID: gs.id, GlobalShortcuts: &EventGlobalShortcuts{Accelerator: accelerator}}, EventNameGlobalShortcutsEventIsRegistered) | ||
if err != nil { | ||
return | ||
} | ||
|
||
if result.GlobalShortcuts != nil { | ||
isRegistered = result.GlobalShortcuts.IsRegistered | ||
} | ||
return | ||
} | ||
|
||
// Unregister unregisters a global shortcut | ||
func (gs *GlobalShortcuts) Unregister(accelerator string) (err error) { | ||
if err = gs.ctx.Err(); err != nil { | ||
return | ||
} | ||
|
||
// Send an event to astilectron to unregister the global shortcut | ||
_, err = synchronousEvent(gs.ctx, gs, gs.w, Event{Name: EventNameGlobalShortcutsCmdUnregister, TargetID: gs.id, GlobalShortcuts: &EventGlobalShortcuts{Accelerator: accelerator}}, EventNameGlobalShortcutsEventUnregistered) | ||
if err != nil { | ||
return | ||
} | ||
gs.m.Lock() | ||
delete(gs.callbacks, accelerator) | ||
gs.m.Unlock() | ||
return | ||
} | ||
|
||
// UnregisterAll unregisters all global shortcuts | ||
func (gs *GlobalShortcuts) UnregisterAll() (err error) { | ||
if err = gs.ctx.Err(); err != nil { | ||
return | ||
} | ||
|
||
// Send an event to astilectron to unregister all global shortcuts | ||
_, err = synchronousEvent(gs.ctx, gs, gs.w, Event{Name: EventNameGlobalShortcutsCmdUnregisterAll, TargetID: gs.id}, EventNameGlobalShortcutsEventUnregisteredAll) | ||
if err != nil { | ||
return | ||
} | ||
|
||
gs.m.Lock() | ||
gs.callbacks = make(map[string]globalShortcutsCallback) // Clear the map | ||
gs.m.Unlock() | ||
|
||
return | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
package astilectron | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"testing" | ||
) | ||
|
||
func TestGlobalShortcut_Actions(t *testing.T) { | ||
var d = newDispatcher() | ||
var i = newIdentifier() | ||
var wrt = &mockedWriter{} | ||
var w = newWriter(wrt, &logger{}) | ||
|
||
var gs = newGlobalShortcuts(context.Background(), d, i, w) | ||
|
||
// Register | ||
testObjectAction(t, func() error { | ||
_, e := gs.Register("Ctrl+X", func() {}) | ||
return e | ||
}, gs.object, wrt, fmt.Sprintf(`{"name":"%s","targetID":"%s","globalShortcuts":{"accelerator":"Ctrl+X"}}%s`, EventNameGlobalShortcutsCmdRegister, gs.id, "\n"), | ||
EventNameGlobalShortcutsEventRegistered, &Event{GlobalShortcuts: &EventGlobalShortcuts{Accelerator: "Ctrl+X", IsRegistered: true}}) | ||
|
||
// IsRegistered | ||
testObjectAction(t, func() error { | ||
_, e := gs.IsRegistered("Ctrl+Y") | ||
return e | ||
}, gs.object, wrt, fmt.Sprintf(`{"name":"%s","targetID":"%s","globalShortcuts":{"accelerator":"Ctrl+Y"}}%s`, EventNameGlobalShortcutsCmdIsRegistered, gs.id, "\n"), | ||
EventNameGlobalShortcutsEventIsRegistered, &Event{GlobalShortcuts: &EventGlobalShortcuts{Accelerator: "Ctrl+Y", IsRegistered: false}}) | ||
|
||
// Unregister | ||
testObjectAction(t, func() error { | ||
return gs.Unregister("Ctrl+Z") | ||
}, gs.object, wrt, fmt.Sprintf(`{"name":"%s","targetID":"%s","globalShortcuts":{"accelerator":"Ctrl+Z"}}%s`, EventNameGlobalShortcutsCmdUnregister, gs.id, "\n"), | ||
EventNameGlobalShortcutsEventUnregistered, nil) | ||
|
||
// UnregisterAll | ||
testObjectAction(t, func() error { | ||
return gs.UnregisterAll() | ||
}, gs.object, wrt, fmt.Sprintf(`{"name":"%s","targetID":"%s"}%s`, EventNameGlobalShortcutsCmdUnregisterAll, gs.id, "\n"), | ||
EventNameGlobalShortcutsEventUnregisteredAll, nil) | ||
} |