From 1afa8f51bdc3e88dfc3693f2981af55c738f36ba Mon Sep 17 00:00:00 2001 From: benebsiny Date: Sun, 18 Jun 2023 18:29:16 +0800 Subject: [PATCH 1/9] Implement global shortcuts --- astilectron.go | 4 + event.go | 1 + global_shortcut.go | 269 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 274 insertions(+) create mode 100644 global_shortcut.go diff --git a/astilectron.go b/astilectron.go index bd733d3..41889d7 100644 --- a/astilectron.go +++ b/astilectron.go @@ -187,6 +187,10 @@ func (a *Astilectron) Start() (err error) { } else { synchronousFunc(a.worker.Context(), a, nil, "app.event.ready") } + + // Initialize global Shortcuts + InitGlobalShortcuts(a.worker.Context(), a.dispatcher, a.identifier, a.writer) + return nil } diff --git a/event.go b/event.go index 6e02927..bc01a8b 100644 --- a/event.go +++ b/event.go @@ -29,6 +29,7 @@ type Event struct { Displays *EventDisplays `json:"displays,omitempty"` Enable *bool `json:"enable,omitempty"` FilePath string `json:"filePath,omitempty"` + GlobalShortcut *GlobalShortcut `json:"globalShortcut,omitempty"` ID *int `json:"id,omitempty"` Image string `json:"image,omitempty"` Index *int `json:"index,omitempty"` diff --git a/global_shortcut.go b/global_shortcut.go new file mode 100644 index 0000000..8ab5c9a --- /dev/null +++ b/global_shortcut.go @@ -0,0 +1,269 @@ +package astilectron + +import ( + "context" + "errors" + "strings" +) + +const ( + EventNameGlobalShortcutCmdRegister = "global.shortcut.cmd.register" + EventNameGlobalShortcutCmdIsRegistered = "global.shortcut.cmd.is.register" + EventNameGlobalShortcutCmdUnregister = "global.shortcut.cmd.unregister" + EventNameGlobalShortcutCmdUnregisterAll = "global.shortcut.cmd.unregister.all" + EventNameGlobalShortcutEventProcessFinished = "global.shortcut.event.process.finished" // Register or Unregister process is finished + EventNameGlobalShortcutEventTriggered = "global.shortcut.event.triggered" +) + +// GlobalShortcut represents a global shortcut +type GlobalShortcut struct { + *object + Accelerator string `json:"accelerator,omitempty"` // Accelerator of the global globalShortcuts + IsRegistered bool `json:"isRegistered,omitempty"` // Whether the global shortcut is registered + Callback *callback `json:"-"` +} +type callback func() + +var gss = make(map[string]*GlobalShortcut) // Store all registered Global Shortcuts +var obj *object + +// InitGlobalShortcuts initializes the globalShortcuts +func InitGlobalShortcuts(ctx context.Context, d *dispatcher, i *identifier, w *writer) { + obj = newObject(ctx, d, i, w, i.new()) + obj.On(EventNameGlobalShortcutEventTriggered, func(e Event) (deleteListener bool) { // Register the listener for the triggered event + globalShortcutHandler(e.GlobalShortcut.Accelerator) + return + }) +} + +// GlobalShortcutRegister Register global shortcuts +func GlobalShortcutRegister(accelerator string, callback callback) bool { + + // Check if the accelerator is valid + keySet, err := parseAccelerator(accelerator) + if err != nil || len(keySet) == 0 { + obj.w.l.Error(err) + return false + } + + // If CmdOrCtrl is used, replace it with Cmd and Ctrl + if _, ok := keySet["commandorcontrol"]; ok { + + delete(keySet, "commandorcontrol") + + // Replace CmdOrCtrl with Cmd + keySet["command"] = true + var result1 = GlobalShortcutRegister(keySetToString(keySet), callback) + + // Replace CmdOrCtrl with Ctrl + delete(keySet, "command") + keySet["control"] = true + var result2 = GlobalShortcutRegister(keySetToString(keySet), callback) + + return result1 || result2 // Either Cmd or Ctrl is registered successfully + } + + var gs = GlobalShortcut{Accelerator: accelerator, Callback: &callback, object: obj} + + // Send an event to astilectron to register the global shortcut + var event = Event{Name: EventNameGlobalShortcutCmdRegister, TargetID: gs.id, GlobalShortcut: &gs} + result, err := synchronousEvent(gs.ctx, gs, gs.w, event, EventNameGlobalShortcutEventProcessFinished) + + if err != nil { + return false + } + + // If registered successfully, add this `GlobalShortcut` object to the map + if result.GlobalShortcut.IsRegistered { + gss[accelerator] = &gs + } + + return result.GlobalShortcut.IsRegistered +} + +// GlobalShortcutIsRegistered Check if a global shortcut is registered +func GlobalShortcutIsRegistered(accelerator string) bool { + var gs = GlobalShortcut{Accelerator: accelerator, object: obj} + + // Send an event to astilectron to check if global shortcut is registered + var event = Event{Name: EventNameGlobalShortcutCmdIsRegistered, TargetID: gs.id, GlobalShortcut: &gs} + result, err := synchronousEvent(gs.ctx, gs, gs.w, event, EventNameGlobalShortcutEventProcessFinished) + + if err != nil { + return false + } + + return result.GlobalShortcut.IsRegistered +} + +// GlobalShortcutUnregister Unregister a global shortcut +func GlobalShortcutUnregister(accelerator string) { + + // Remove the callback from the map and remove the listener + keySetToUnregister, err := parseAccelerator(accelerator) // Accelerator to unregister + if err != nil || len(keySetToUnregister) == 0 { + obj.w.l.Error(err) + return + } + + // If CmdOrCtrl is used, replace it with Cmd and Ctrl + if _, ok := keySetToUnregister["commandorcontrol"]; ok { + + delete(keySetToUnregister, "commandorcontrol") + + // Replace CmdOrCtrl with Cmd + keySetToUnregister["command"] = true + GlobalShortcutUnregister(keySetToString(keySetToUnregister)) + + // Replace CmdOrCtrl with Ctrl + delete(keySetToUnregister, "command") + keySetToUnregister["control"] = true + GlobalShortcutUnregister(keySetToString(keySetToUnregister)) + + return + } + + // Iterate through all registered global shortcuts to find the equivalent one + for acc, gs := range gss { + keySetRegistered, _ := parseAccelerator(acc) + + var isEqual = isKeySetsEqual(keySetToUnregister, keySetRegistered) + if isEqual { // Found the equivalent global shortcut + + // Send an event to astilectron to unregister the global shortcut + var event = Event{Name: EventNameGlobalShortcutCmdUnregister, TargetID: gs.id, GlobalShortcut: gs} + _, err := synchronousEvent(gs.ctx, gs, gs.w, event, EventNameGlobalShortcutEventProcessFinished) + + if err != nil { + return + } + delete(gss, acc) // Remove this `GlobalShortcut` from the map + + break + } + } +} + +// GlobalShortcutUnregisterAll Unregister all global shortcuts +func GlobalShortcutUnregisterAll() { + + // Send an event to astilectron to unregister all global shortcuts + var event = Event{Name: EventNameGlobalShortcutCmdUnregisterAll, TargetID: obj.id} + _, err := synchronousEvent(obj.ctx, obj, obj.w, event, EventNameGlobalShortcutEventProcessFinished) + + if err != nil { + return + } + + gss = make(map[string]*GlobalShortcut) // Clear the map +} + +// parseAccelerator Parse the accelerator string into a key set +// Note that the boolean value of returned map is meaningless. We just care if the key exists +func parseAccelerator(accelerator string) (map[string]bool, error) { + var tokens = []string{ + "Command", "Control", "CommandOrControl", "Alt", + "Option", "AltGr", "Shift", "Super", "Meta", + "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", + "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", + "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", + "U", "V", "W", "X", "Y", "Z", + "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", + "F9", "F10", "F11", "F12", "F13", "F14", "F15", + "F16", "F17", "F18", "F19", "F20", "F21", "F22", "F23", "F24", + ")", "!", "@", "#", "$", "%", "^", "&", "*", "(", + ":", ";", ":", "+", "=", "<", ",", "_", "-", ">", + ".", "?", "/", "~", "`", "{", "]", "[", "|", "\\", + "}", "\"", + "Plus", "Space", "Tab", "Capslock", "Numlock", + "Scrolllock", "Backspace", "Delete", "Insert", + "Enter", "Up", "Down", "Left", "Right", + "Home", "End", "PageUp", "PageDown", "Escape", + "VolumeUp", "VolumeDown", "VolumeMute", + "MediaNextTrack", "MediaPreviousTrack", "MediaStop", + "MediaPlayPause", "PrintScreen", + "Num0", "Num1", "Num2", "Num3", "Num4", + "Num5", "Num6", "Num7", "Num8", "Num9", + "NumDec", "NumAdd", "NumSub", + "NumMul", "NumDiv", + } + + var tokenAlias = map[string]string{ + "cmd": "Command", + "ctrl": "Control", + "cmdorctrl": "CommandOrControl", + "return": "Enter", + "esc": "Escape", + } + + accelerator = strings.TrimSpace(accelerator) + var keys = strings.Split(accelerator, "+") + keySet := make(map[string]bool) + + for _, key := range keys { + + key = strings.ToLower(key) + + if alias, ok := tokenAlias[key]; ok { // The key is an alias of token + keySet[strings.ToLower(alias)] = true + + } else if isInSlice(tokens, key) { // The key is a token + keySet[key] = true + + } else { + return nil, errors.New("invalid accelerator: " + accelerator) + } + } + + // If CmdOrCtrl and Cmd are both in the key set, remove CmdOrCtrl + // If CmdOrCtrl and Ctrl are both in the key set, remove CmdOrCtrl + if keySet["commandorcontrol"] && keySet["command"] { + delete(keySet, "commandorcontrol") + } else if keySet["commandorcontrol"] && keySet["control"] { + delete(keySet, "commandorcontrol") + } + + return keySet, nil +} + +// Key set to accelerator string +func keySetToString(keySet map[string]bool) string { + var keys []string + for k := range keySet { + keys = append(keys, k) + } + return strings.Join(keys, "+") +} + +// Check if two key sets are equivalent +// Assert that the CmdOrCtrl key doesn't exist in both key sets +func isKeySetsEqual(keySetA map[string]bool, keySetB map[string]bool) bool { + + if len(keySetA) != len(keySetB) { + return false + } + + for k, _ := range keySetA { + if _, ok := keySetB[k]; !ok { + return false + } + } + return true +} + +// isInSlice Checks if an item is in a slice +func isInSlice(slice []string, item string) bool { + for _, s := range slice { + if strings.ToLower(s) == strings.ToLower(item) { + return true + } + } + return false +} + +// globalShortcutHandler Handle the GlobalShortcut event triggered from astilectron +func globalShortcutHandler(accelerator string) { + if gs, ok := gss[accelerator]; ok { + (*(*gs).Callback)() + } +} From 1f1b5ca2a9ab4b86e4afa28463451db414df2ca9 Mon Sep 17 00:00:00 2001 From: benebsiny Date: Mon, 19 Jun 2023 22:06:58 +0800 Subject: [PATCH 2/9] 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. --- global_shortcut.go | 215 +++++++-------------------------------------- 1 file changed, 31 insertions(+), 184 deletions(-) diff --git a/global_shortcut.go b/global_shortcut.go index 8ab5c9a..d6f756c 100644 --- a/global_shortcut.go +++ b/global_shortcut.go @@ -2,8 +2,6 @@ package astilectron import ( "context" - "errors" - "strings" ) const ( @@ -18,13 +16,12 @@ const ( // GlobalShortcut represents a global shortcut type GlobalShortcut struct { *object - Accelerator string `json:"accelerator,omitempty"` // Accelerator of the global globalShortcuts - IsRegistered bool `json:"isRegistered,omitempty"` // Whether the global shortcut is registered - Callback *callback `json:"-"` + Accelerator string `json:"accelerator,omitempty"` // Accelerator of the global globalShortcuts + IsRegistered bool `json:"isRegistered,omitempty"` // Whether the global shortcut is registered } type callback func() -var gss = make(map[string]*GlobalShortcut) // Store all registered Global Shortcuts +var gss = make(map[string]*callback) // Store all registered Global Shortcuts var obj *object // InitGlobalShortcuts initializes the globalShortcuts @@ -37,52 +34,30 @@ func InitGlobalShortcuts(ctx context.Context, d *dispatcher, i *identifier, w *w } // GlobalShortcutRegister Register global shortcuts -func GlobalShortcutRegister(accelerator string, callback callback) bool { +func GlobalShortcutRegister(accelerator string, callback callback) (isRegistered bool, err error) { - // Check if the accelerator is valid - keySet, err := parseAccelerator(accelerator) - if err != nil || len(keySet) == 0 { - obj.w.l.Error(err) - return false - } - - // If CmdOrCtrl is used, replace it with Cmd and Ctrl - if _, ok := keySet["commandorcontrol"]; ok { - - delete(keySet, "commandorcontrol") - - // Replace CmdOrCtrl with Cmd - keySet["command"] = true - var result1 = GlobalShortcutRegister(keySetToString(keySet), callback) - - // Replace CmdOrCtrl with Ctrl - delete(keySet, "command") - keySet["control"] = true - var result2 = GlobalShortcutRegister(keySetToString(keySet), callback) - - return result1 || result2 // Either Cmd or Ctrl is registered successfully - } - - var gs = GlobalShortcut{Accelerator: accelerator, Callback: &callback, object: obj} + var gs = GlobalShortcut{Accelerator: accelerator, object: obj} // Send an event to astilectron to register the global shortcut var event = Event{Name: EventNameGlobalShortcutCmdRegister, TargetID: gs.id, GlobalShortcut: &gs} result, err := synchronousEvent(gs.ctx, gs, gs.w, event, EventNameGlobalShortcutEventProcessFinished) if err != nil { - return false + return } - // If registered successfully, add this `GlobalShortcut` object to the map + // If registered successfully, add the callback to the map if result.GlobalShortcut.IsRegistered { - gss[accelerator] = &gs + gss[accelerator] = &callback } - return result.GlobalShortcut.IsRegistered + isRegistered = result.GlobalShortcut.IsRegistered + return } // GlobalShortcutIsRegistered Check if a global shortcut is registered -func GlobalShortcutIsRegistered(accelerator string) bool { +func GlobalShortcutIsRegistered(accelerator string) (isRegistered bool, err error) { + var gs = GlobalShortcut{Accelerator: accelerator, object: obj} // Send an event to astilectron to check if global shortcut is registered @@ -90,180 +65,52 @@ func GlobalShortcutIsRegistered(accelerator string) bool { result, err := synchronousEvent(gs.ctx, gs, gs.w, event, EventNameGlobalShortcutEventProcessFinished) if err != nil { - return false + return } - return result.GlobalShortcut.IsRegistered + isRegistered = result.GlobalShortcut.IsRegistered + return } // GlobalShortcutUnregister Unregister a global shortcut -func GlobalShortcutUnregister(accelerator string) { +func GlobalShortcutUnregister(accelerator string) (err error) { - // Remove the callback from the map and remove the listener - keySetToUnregister, err := parseAccelerator(accelerator) // Accelerator to unregister - if err != nil || len(keySetToUnregister) == 0 { - obj.w.l.Error(err) - return - } - - // If CmdOrCtrl is used, replace it with Cmd and Ctrl - if _, ok := keySetToUnregister["commandorcontrol"]; ok { - - delete(keySetToUnregister, "commandorcontrol") - - // Replace CmdOrCtrl with Cmd - keySetToUnregister["command"] = true - GlobalShortcutUnregister(keySetToString(keySetToUnregister)) + var gs = GlobalShortcut{Accelerator: accelerator, object: obj} - // Replace CmdOrCtrl with Ctrl - delete(keySetToUnregister, "command") - keySetToUnregister["control"] = true - GlobalShortcutUnregister(keySetToString(keySetToUnregister)) + // Send an event to astilectron to unregister the global shortcut + var event = Event{Name: EventNameGlobalShortcutCmdUnregister, TargetID: gs.id, GlobalShortcut: &gs} + _, err = synchronousEvent(gs.ctx, gs, gs.w, event, EventNameGlobalShortcutEventProcessFinished) + if err != nil { return } - // Iterate through all registered global shortcuts to find the equivalent one - for acc, gs := range gss { - keySetRegistered, _ := parseAccelerator(acc) + // No need to find the callback from the map and delete it + // because that event will no longer be triggerred + // If the same global shortcut is registered again, the original callback will be replaced with the new one - var isEqual = isKeySetsEqual(keySetToUnregister, keySetRegistered) - if isEqual { // Found the equivalent global shortcut - - // Send an event to astilectron to unregister the global shortcut - var event = Event{Name: EventNameGlobalShortcutCmdUnregister, TargetID: gs.id, GlobalShortcut: gs} - _, err := synchronousEvent(gs.ctx, gs, gs.w, event, EventNameGlobalShortcutEventProcessFinished) - - if err != nil { - return - } - delete(gss, acc) // Remove this `GlobalShortcut` from the map - - break - } - } + return } // GlobalShortcutUnregisterAll Unregister all global shortcuts -func GlobalShortcutUnregisterAll() { +func GlobalShortcutUnregisterAll() (err error) { // Send an event to astilectron to unregister all global shortcuts var event = Event{Name: EventNameGlobalShortcutCmdUnregisterAll, TargetID: obj.id} - _, err := synchronousEvent(obj.ctx, obj, obj.w, event, EventNameGlobalShortcutEventProcessFinished) + _, err = synchronousEvent(obj.ctx, obj, obj.w, event, EventNameGlobalShortcutEventProcessFinished) if err != nil { return } - gss = make(map[string]*GlobalShortcut) // Clear the map -} + gss = make(map[string]*callback) // Clear the map -// parseAccelerator Parse the accelerator string into a key set -// Note that the boolean value of returned map is meaningless. We just care if the key exists -func parseAccelerator(accelerator string) (map[string]bool, error) { - var tokens = []string{ - "Command", "Control", "CommandOrControl", "Alt", - "Option", "AltGr", "Shift", "Super", "Meta", - "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", - "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", - "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", - "U", "V", "W", "X", "Y", "Z", - "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", - "F9", "F10", "F11", "F12", "F13", "F14", "F15", - "F16", "F17", "F18", "F19", "F20", "F21", "F22", "F23", "F24", - ")", "!", "@", "#", "$", "%", "^", "&", "*", "(", - ":", ";", ":", "+", "=", "<", ",", "_", "-", ">", - ".", "?", "/", "~", "`", "{", "]", "[", "|", "\\", - "}", "\"", - "Plus", "Space", "Tab", "Capslock", "Numlock", - "Scrolllock", "Backspace", "Delete", "Insert", - "Enter", "Up", "Down", "Left", "Right", - "Home", "End", "PageUp", "PageDown", "Escape", - "VolumeUp", "VolumeDown", "VolumeMute", - "MediaNextTrack", "MediaPreviousTrack", "MediaStop", - "MediaPlayPause", "PrintScreen", - "Num0", "Num1", "Num2", "Num3", "Num4", - "Num5", "Num6", "Num7", "Num8", "Num9", - "NumDec", "NumAdd", "NumSub", - "NumMul", "NumDiv", - } - - var tokenAlias = map[string]string{ - "cmd": "Command", - "ctrl": "Control", - "cmdorctrl": "CommandOrControl", - "return": "Enter", - "esc": "Escape", - } - - accelerator = strings.TrimSpace(accelerator) - var keys = strings.Split(accelerator, "+") - keySet := make(map[string]bool) - - for _, key := range keys { - - key = strings.ToLower(key) - - if alias, ok := tokenAlias[key]; ok { // The key is an alias of token - keySet[strings.ToLower(alias)] = true - - } else if isInSlice(tokens, key) { // The key is a token - keySet[key] = true - - } else { - return nil, errors.New("invalid accelerator: " + accelerator) - } - } - - // If CmdOrCtrl and Cmd are both in the key set, remove CmdOrCtrl - // If CmdOrCtrl and Ctrl are both in the key set, remove CmdOrCtrl - if keySet["commandorcontrol"] && keySet["command"] { - delete(keySet, "commandorcontrol") - } else if keySet["commandorcontrol"] && keySet["control"] { - delete(keySet, "commandorcontrol") - } - - return keySet, nil -} - -// Key set to accelerator string -func keySetToString(keySet map[string]bool) string { - var keys []string - for k := range keySet { - keys = append(keys, k) - } - return strings.Join(keys, "+") -} - -// Check if two key sets are equivalent -// Assert that the CmdOrCtrl key doesn't exist in both key sets -func isKeySetsEqual(keySetA map[string]bool, keySetB map[string]bool) bool { - - if len(keySetA) != len(keySetB) { - return false - } - - for k, _ := range keySetA { - if _, ok := keySetB[k]; !ok { - return false - } - } - return true -} - -// isInSlice Checks if an item is in a slice -func isInSlice(slice []string, item string) bool { - for _, s := range slice { - if strings.ToLower(s) == strings.ToLower(item) { - return true - } - } - return false + return } // globalShortcutHandler Handle the GlobalShortcut event triggered from astilectron func globalShortcutHandler(accelerator string) { - if gs, ok := gss[accelerator]; ok { - (*(*gs).Callback)() + if callback, ok := gss[accelerator]; ok { + (*callback)() } } From 2d214759098a947c8e3567daf2c624cc237d0cf8 Mon Sep 17 00:00:00 2001 From: benebsiny Date: Tue, 20 Jun 2023 13:29:10 +0800 Subject: [PATCH 3/9] Add test case and doc 1. Add test case 2. Add doc to README.md 3. Handle `ctx.Err` in functions --- README.md | 21 +++++++++++++++++++++ global_shortcut.go | 16 ++++++++++++++++ global_shortcut_test.go | 42 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 79 insertions(+) create mode 100644 global_shortcut_test.go diff --git a/README.md b/README.md index c18e5f5..6041025 100644 --- a/README.md +++ b/README.md @@ -446,6 +446,27 @@ var m = d.NewMenu([]*astilectron.MenuItemOptions{ m.Create() ``` +## Global Shortcuts + +Registering a global shortcut. + +```go +// Register a new global shortcut +isRegistered, _ := astilectron.GlobalShortcutRegister("CmdOrCtrl+x", func() { + fmt.Println("CmdOrCtrl+x is pressed") +}) +fmt.Println("CmdOrCtrl+x is registered:", isRegistered) // true + +// Check if a global shortcut is registered +isRegistered, _ = astilectron.GlobalShortcutIsRegistered("Shift+Y") // false + +// Unregister a global shortcut +astilectron.GlobalShortcutUnregister("CmdOrCtrl+x") + +// Unregister all global shortcuts +astilectron.GlobalShortcutUnregisterAll() +``` + ## Dialogs Add the following line at the top of your javascript file : diff --git a/global_shortcut.go b/global_shortcut.go index d6f756c..b4696aa 100644 --- a/global_shortcut.go +++ b/global_shortcut.go @@ -36,6 +36,10 @@ func InitGlobalShortcuts(ctx context.Context, d *dispatcher, i *identifier, w *w // GlobalShortcutRegister Register global shortcuts func GlobalShortcutRegister(accelerator string, callback callback) (isRegistered bool, err error) { + if err = obj.ctx.Err(); err != nil { + return + } + var gs = GlobalShortcut{Accelerator: accelerator, object: obj} // Send an event to astilectron to register the global shortcut @@ -58,6 +62,10 @@ func GlobalShortcutRegister(accelerator string, callback callback) (isRegistered // GlobalShortcutIsRegistered Check if a global shortcut is registered func GlobalShortcutIsRegistered(accelerator string) (isRegistered bool, err error) { + if err = obj.ctx.Err(); err != nil { + return + } + var gs = GlobalShortcut{Accelerator: accelerator, object: obj} // Send an event to astilectron to check if global shortcut is registered @@ -75,6 +83,10 @@ func GlobalShortcutIsRegistered(accelerator string) (isRegistered bool, err erro // GlobalShortcutUnregister Unregister a global shortcut func GlobalShortcutUnregister(accelerator string) (err error) { + if err = obj.ctx.Err(); err != nil { + return + } + var gs = GlobalShortcut{Accelerator: accelerator, object: obj} // Send an event to astilectron to unregister the global shortcut @@ -95,6 +107,10 @@ func GlobalShortcutUnregister(accelerator string) (err error) { // GlobalShortcutUnregisterAll Unregister all global shortcuts func GlobalShortcutUnregisterAll() (err error) { + if err = obj.ctx.Err(); err != nil { + return + } + // Send an event to astilectron to unregister all global shortcuts var event = Event{Name: EventNameGlobalShortcutCmdUnregisterAll, TargetID: obj.id} _, err = synchronousEvent(obj.ctx, obj, obj.w, event, EventNameGlobalShortcutEventProcessFinished) diff --git a/global_shortcut_test.go b/global_shortcut_test.go new file mode 100644 index 0000000..d250d43 --- /dev/null +++ b/global_shortcut_test.go @@ -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{}) + + InitGlobalShortcuts(context.Background(), d, i, w) + + // Register + testObjectAction(t, func() error { + _, e := GlobalShortcutRegister("Ctrl+X", func() {}) + return e + }, obj, wrt, fmt.Sprintf(`{"name":"%s","targetID":"%s","globalShortcut":{"accelerator":"Ctrl+X"}}%s`, EventNameGlobalShortcutCmdRegister, obj.id, "\n"), + EventNameGlobalShortcutEventProcessFinished, &Event{GlobalShortcut: &GlobalShortcut{Accelerator: "Ctrl+X", IsRegistered: true}}) + + // IsRegistered + testObjectAction(t, func() error { + _, e := GlobalShortcutIsRegistered("Ctrl+Y") + return e + }, obj, wrt, fmt.Sprintf(`{"name":"%s","targetID":"%s","globalShortcut":{"accelerator":"Ctrl+Y"}}%s`, EventNameGlobalShortcutCmdIsRegistered, obj.id, "\n"), + EventNameGlobalShortcutEventProcessFinished, &Event{GlobalShortcut: &GlobalShortcut{Accelerator: "Ctrl+Y", IsRegistered: false}}) + + // Unregister + testObjectAction(t, func() error { + return GlobalShortcutUnregister("Ctrl+Z") + }, obj, wrt, fmt.Sprintf(`{"name":"%s","targetID":"%s","globalShortcut":{"accelerator":"Ctrl+Z"}}%s`, EventNameGlobalShortcutCmdUnregister, obj.id, "\n"), + EventNameGlobalShortcutEventProcessFinished, nil) + + // UnregisterAll + testObjectAction(t, func() error { + return GlobalShortcutUnregisterAll() + }, obj, wrt, fmt.Sprintf(`{"name":"%s","targetID":"%s"}%s`, EventNameGlobalShortcutCmdUnregisterAll, obj.id, "\n"), + EventNameGlobalShortcutEventProcessFinished, nil) +} From 7773575dd78f1b176b6bb4c087e5b510e82c25eb Mon Sep 17 00:00:00 2001 From: benebsiny Date: Sat, 2 Sep 2023 12:17:58 +0800 Subject: [PATCH 4/9] Updated --- astilectron.go | 47 +++++++++++---------- event.go | 74 +++++++++++++++++--------------- global_shortcut.go | 93 +++++++++++++++++++---------------------- global_shortcut_test.go | 22 +++++----- 4 files changed, 119 insertions(+), 117 deletions(-) diff --git a/astilectron.go b/astilectron.go index 41889d7..ee28f92 100644 --- a/astilectron.go +++ b/astilectron.go @@ -2,12 +2,11 @@ package astilectron import ( "fmt" + "github.com/asticode/go-astikit" "net" "os/exec" "runtime" "time" - - "github.com/asticode/go-astikit" ) // Versions @@ -41,22 +40,23 @@ const ( // Astilectron represents an object capable of interacting with Astilectron type Astilectron struct { - dispatcher *dispatcher - displayPool *displayPool - dock *Dock - executer Executer - identifier *identifier - l astikit.SeverityLogger - listener net.Listener - options Options - paths *Paths - provisioner Provisioner - reader *reader - stderrWriter *astikit.WriterAdapter - stdoutWriter *astikit.WriterAdapter - supported *Supported - worker *astikit.Worker - writer *writer + dispatcher *dispatcher + displayPool *displayPool + dock *Dock + executer Executer + globalShortcuts *GlobalShortcuts + identifier *identifier + l astikit.SeverityLogger + listener net.Listener + options Options + paths *Paths + provisioner Provisioner + reader *reader + stderrWriter *astikit.WriterAdapter + stdoutWriter *astikit.WriterAdapter + supported *Supported + worker *astikit.Worker + writer *writer } // Options represents Astilectron options @@ -156,6 +156,11 @@ func (a *Astilectron) SetExecuter(e Executer) *Astilectron { return a } +// GlobalShortcuts gets the global shortcuts +func (a *Astilectron) GlobalShortcuts() *GlobalShortcuts { + return a.globalShortcuts +} + // On implements the Listenable interface func (a *Astilectron) On(eventName string, l Listener) { a.dispatcher.addListener(targetIDApp, eventName, l) @@ -188,9 +193,6 @@ func (a *Astilectron) Start() (err error) { synchronousFunc(a.worker.Context(), a, nil, "app.event.ready") } - // Initialize global Shortcuts - InitGlobalShortcuts(a.worker.Context(), a.dispatcher, a.identifier, a.writer) - return nil } @@ -326,6 +328,9 @@ func (a *Astilectron) executeCmd(cmd *exec.Cmd) (err error) { // Create dock a.dock = newDock(a.worker.Context(), a.dispatcher, a.identifier, a.writer) + // Create global shortcuts + a.globalShortcuts = newGlobalShortcuts(a.worker.Context(), a.dispatcher, a.identifier, a.writer) + // Update supported features a.supported = e.Supported return diff --git a/event.go b/event.go index bc01a8b..4a493fe 100644 --- a/event.go +++ b/event.go @@ -20,40 +20,40 @@ type Event struct { // This is a list of all possible payloads. // A choice was made not to use interfaces since it's a pain in the ass asserting each an every payload afterwards // We use pointers so that omitempty works - AuthInfo *EventAuthInfo `json:"authInfo,omitempty"` - Badge string `json:"badge,omitempty"` - BounceType string `json:"bounceType,omitempty"` - Bounds *RectangleOptions `json:"bounds,omitempty"` - CallbackID string `json:"callbackId,omitempty"` - Code string `json:"code,omitempty"` - Displays *EventDisplays `json:"displays,omitempty"` - Enable *bool `json:"enable,omitempty"` - FilePath string `json:"filePath,omitempty"` - GlobalShortcut *GlobalShortcut `json:"globalShortcut,omitempty"` - ID *int `json:"id,omitempty"` - Image string `json:"image,omitempty"` - Index *int `json:"index,omitempty"` - Menu *EventMenu `json:"menu,omitempty"` - MenuItem *EventMenuItem `json:"menuItem,omitempty"` - MenuItemOptions *MenuItemOptions `json:"menuItemOptions,omitempty"` - MenuItemPosition *int `json:"menuItemPosition,omitempty"` - MenuPopupOptions *MenuPopupOptions `json:"menuPopupOptions,omitempty"` - Message *EventMessage `json:"message,omitempty"` - NotificationOptions *NotificationOptions `json:"notificationOptions,omitempty"` - Password string `json:"password,omitempty"` - Path string `json:"path,omitempty"` - Reply string `json:"reply,omitempty"` - Request *EventRequest `json:"request,omitempty"` - SecondInstance *EventSecondInstance `json:"secondInstance,omitempty"` - SessionID string `json:"sessionId,omitempty"` - Supported *Supported `json:"supported,omitempty"` - TrayOptions *TrayOptions `json:"trayOptions,omitempty"` - URL string `json:"url,omitempty"` - URLNew string `json:"newUrl,omitempty"` - URLOld string `json:"oldUrl,omitempty"` - Username string `json:"username,omitempty"` - WindowID string `json:"windowId,omitempty"` - WindowOptions *WindowOptions `json:"windowOptions,omitempty"` + AuthInfo *EventAuthInfo `json:"authInfo,omitempty"` + Badge string `json:"badge,omitempty"` + BounceType string `json:"bounceType,omitempty"` + Bounds *RectangleOptions `json:"bounds,omitempty"` + CallbackID string `json:"callbackId,omitempty"` + Code string `json:"code,omitempty"` + Displays *EventDisplays `json:"displays,omitempty"` + Enable *bool `json:"enable,omitempty"` + FilePath string `json:"filePath,omitempty"` + GlobalShortcuts *EventGlobalShortcuts `json:"globalShortcuts,omitempty"` + ID *int `json:"id,omitempty"` + Image string `json:"image,omitempty"` + Index *int `json:"index,omitempty"` + Menu *EventMenu `json:"menu,omitempty"` + MenuItem *EventMenuItem `json:"menuItem,omitempty"` + MenuItemOptions *MenuItemOptions `json:"menuItemOptions,omitempty"` + MenuItemPosition *int `json:"menuItemPosition,omitempty"` + MenuPopupOptions *MenuPopupOptions `json:"menuPopupOptions,omitempty"` + Message *EventMessage `json:"message,omitempty"` + NotificationOptions *NotificationOptions `json:"notificationOptions,omitempty"` + Password string `json:"password,omitempty"` + Path string `json:"path,omitempty"` + Reply string `json:"reply,omitempty"` + Request *EventRequest `json:"request,omitempty"` + SecondInstance *EventSecondInstance `json:"secondInstance,omitempty"` + SessionID string `json:"sessionId,omitempty"` + Supported *Supported `json:"supported,omitempty"` + TrayOptions *TrayOptions `json:"trayOptions,omitempty"` + URL string `json:"url,omitempty"` + URLNew string `json:"newUrl,omitempty"` + URLOld string `json:"oldUrl,omitempty"` + Username string `json:"username,omitempty"` + WindowID string `json:"windowId,omitempty"` + WindowOptions *WindowOptions `json:"windowOptions,omitempty"` } // EventAuthInfo represents an event auth info @@ -71,6 +71,12 @@ type EventDisplays struct { Primary *DisplayOptions `json:"primary,omitempty"` } +// EventGlobalShortcuts represents event global shortcuts +type EventGlobalShortcuts struct { + Accelerator string `json:"accelerator,omitempty"` + IsRegistered bool `json:"isRegistered,omitempty"` +} + // EventMessage represents an event message type EventMessage struct { i interface{} diff --git a/global_shortcut.go b/global_shortcut.go index b4696aa..bbd0e61 100644 --- a/global_shortcut.go +++ b/global_shortcut.go @@ -1,49 +1,44 @@ package astilectron -import ( - "context" -) +import "context" const ( - EventNameGlobalShortcutCmdRegister = "global.shortcut.cmd.register" - EventNameGlobalShortcutCmdIsRegistered = "global.shortcut.cmd.is.register" - EventNameGlobalShortcutCmdUnregister = "global.shortcut.cmd.unregister" - EventNameGlobalShortcutCmdUnregisterAll = "global.shortcut.cmd.unregister.all" - EventNameGlobalShortcutEventProcessFinished = "global.shortcut.event.process.finished" // Register or Unregister process is finished - EventNameGlobalShortcutEventTriggered = "global.shortcut.event.triggered" + EventNameGlobalShortcutCmdRegister = "global.shortcuts.event.registered" + EventNameGlobalShortcutCmdIsRegistered = "global.shortcuts.event.is.registered" + EventNameGlobalShortcutCmdUnregister = "global.shortcuts.event.unregistered" + EventNameGlobalShortcutCmdUnregisterAll = "global.shortcuts.event.unregistered.all" + EventNameGlobalShortcutEventProcessFinished = "global.shortcuts.event.process.finished" // Register or Unregister process is finished + EventNameGlobalShortcutEventTriggered = "global.shortcuts.event.triggered" ) -// GlobalShortcut represents a global shortcut -type GlobalShortcut struct { +type callback func() + +// GlobalShortcuts represents a global shortcut +type GlobalShortcuts struct { *object - Accelerator string `json:"accelerator,omitempty"` // Accelerator of the global globalShortcuts - IsRegistered bool `json:"isRegistered,omitempty"` // Whether the global shortcut is registered + callbacks map[string]*callback // Store all registered Global Shortcuts } -type callback func() -var gss = make(map[string]*callback) // Store all registered Global Shortcuts -var obj *object +func newGlobalShortcuts(ctx context.Context, d *dispatcher, i *identifier, w *writer) (gs *GlobalShortcuts) { + var obj = newObject(ctx, d, i, w, i.new()) + gs = &GlobalShortcuts{object: obj, callbacks: make(map[string]*callback)} -// InitGlobalShortcuts initializes the globalShortcuts -func InitGlobalShortcuts(ctx context.Context, d *dispatcher, i *identifier, w *writer) { - obj = newObject(ctx, d, i, w, i.new()) obj.On(EventNameGlobalShortcutEventTriggered, func(e Event) (deleteListener bool) { // Register the listener for the triggered event - globalShortcutHandler(e.GlobalShortcut.Accelerator) + globalShortcutHandler(gs, e.GlobalShortcuts.Accelerator) return }) + return } -// GlobalShortcutRegister Register global shortcuts -func GlobalShortcutRegister(accelerator string, callback callback) (isRegistered bool, err error) { +// Register Register global shortcuts +func (gs *GlobalShortcuts) Register(accelerator string, callback callback) (isRegistered bool, err error) { - if err = obj.ctx.Err(); err != nil { + if err = gs.ctx.Err(); err != nil { return } - var gs = GlobalShortcut{Accelerator: accelerator, object: obj} - // Send an event to astilectron to register the global shortcut - var event = Event{Name: EventNameGlobalShortcutCmdRegister, TargetID: gs.id, GlobalShortcut: &gs} + var event = Event{Name: EventNameGlobalShortcutCmdRegister, TargetID: gs.id, GlobalShortcuts: &EventGlobalShortcuts{Accelerator: accelerator}} result, err := synchronousEvent(gs.ctx, gs, gs.w, event, EventNameGlobalShortcutEventProcessFinished) if err != nil { @@ -51,46 +46,42 @@ func GlobalShortcutRegister(accelerator string, callback callback) (isRegistered } // If registered successfully, add the callback to the map - if result.GlobalShortcut.IsRegistered { - gss[accelerator] = &callback + if result.GlobalShortcuts.IsRegistered { + gs.callbacks[accelerator] = &callback } - isRegistered = result.GlobalShortcut.IsRegistered + isRegistered = result.GlobalShortcuts.IsRegistered return } -// GlobalShortcutIsRegistered Check if a global shortcut is registered -func GlobalShortcutIsRegistered(accelerator string) (isRegistered bool, err error) { +// IsRegistered Check if a global shortcut is registered +func (gs *GlobalShortcuts) IsRegistered(accelerator string) (isRegistered bool, err error) { - if err = obj.ctx.Err(); err != nil { + if err = gs.ctx.Err(); err != nil { return } - var gs = GlobalShortcut{Accelerator: accelerator, object: obj} - // Send an event to astilectron to check if global shortcut is registered - var event = Event{Name: EventNameGlobalShortcutCmdIsRegistered, TargetID: gs.id, GlobalShortcut: &gs} + var event = Event{Name: EventNameGlobalShortcutCmdIsRegistered, TargetID: gs.id, GlobalShortcuts: &EventGlobalShortcuts{Accelerator: accelerator}} result, err := synchronousEvent(gs.ctx, gs, gs.w, event, EventNameGlobalShortcutEventProcessFinished) if err != nil { return } - isRegistered = result.GlobalShortcut.IsRegistered + isRegistered = result.GlobalShortcuts.IsRegistered return } -// GlobalShortcutUnregister Unregister a global shortcut -func GlobalShortcutUnregister(accelerator string) (err error) { +// Unregister Unregister a global shortcut +func (gs *GlobalShortcuts) Unregister(accelerator string) (err error) { - if err = obj.ctx.Err(); err != nil { + if err = gs.ctx.Err(); err != nil { return } - var gs = GlobalShortcut{Accelerator: accelerator, object: obj} - // Send an event to astilectron to unregister the global shortcut - var event = Event{Name: EventNameGlobalShortcutCmdUnregister, TargetID: gs.id, GlobalShortcut: &gs} + var event = Event{Name: EventNameGlobalShortcutCmdUnregister, TargetID: gs.id, GlobalShortcuts: &EventGlobalShortcuts{Accelerator: accelerator}} _, err = synchronousEvent(gs.ctx, gs, gs.w, event, EventNameGlobalShortcutEventProcessFinished) if err != nil { @@ -104,29 +95,29 @@ func GlobalShortcutUnregister(accelerator string) (err error) { return } -// GlobalShortcutUnregisterAll Unregister all global shortcuts -func GlobalShortcutUnregisterAll() (err error) { +// UnregisterAll Unregister all global shortcuts +func (gs *GlobalShortcuts) UnregisterAll() (err error) { - if err = obj.ctx.Err(); err != nil { + if err = gs.ctx.Err(); err != nil { return } // Send an event to astilectron to unregister all global shortcuts - var event = Event{Name: EventNameGlobalShortcutCmdUnregisterAll, TargetID: obj.id} - _, err = synchronousEvent(obj.ctx, obj, obj.w, event, EventNameGlobalShortcutEventProcessFinished) + var event = Event{Name: EventNameGlobalShortcutCmdUnregisterAll, TargetID: gs.id} + _, err = synchronousEvent(gs.ctx, gs, gs.w, event, EventNameGlobalShortcutEventProcessFinished) if err != nil { return } - gss = make(map[string]*callback) // Clear the map + gs.callbacks = make(map[string]*callback) // Clear the map return } -// globalShortcutHandler Handle the GlobalShortcut event triggered from astilectron -func globalShortcutHandler(accelerator string) { - if callback, ok := gss[accelerator]; ok { +// globalShortcutHandler Handle the GlobalShortcuts event triggered from astilectron +func globalShortcutHandler(gs *GlobalShortcuts, accelerator string) { + if callback, ok := gs.callbacks[accelerator]; ok { (*callback)() } } diff --git a/global_shortcut_test.go b/global_shortcut_test.go index d250d43..08c1314 100644 --- a/global_shortcut_test.go +++ b/global_shortcut_test.go @@ -12,31 +12,31 @@ func TestGlobalShortcut_Actions(t *testing.T) { var wrt = &mockedWriter{} var w = newWriter(wrt, &logger{}) - InitGlobalShortcuts(context.Background(), d, i, w) + var gs = newGlobalShortcuts(context.Background(), d, i, w) // Register testObjectAction(t, func() error { - _, e := GlobalShortcutRegister("Ctrl+X", func() {}) + _, e := gs.Register("Ctrl+X", func() {}) return e - }, obj, wrt, fmt.Sprintf(`{"name":"%s","targetID":"%s","globalShortcut":{"accelerator":"Ctrl+X"}}%s`, EventNameGlobalShortcutCmdRegister, obj.id, "\n"), - EventNameGlobalShortcutEventProcessFinished, &Event{GlobalShortcut: &GlobalShortcut{Accelerator: "Ctrl+X", IsRegistered: true}}) + }, gs.object, wrt, fmt.Sprintf(`{"name":"%s","targetID":"%s","globalShortcuts":{"accelerator":"Ctrl+X"}}%s`, EventNameGlobalShortcutCmdRegister, gs.id, "\n"), + EventNameGlobalShortcutEventProcessFinished, &Event{GlobalShortcuts: &EventGlobalShortcuts{Accelerator: "Ctrl+X", IsRegistered: true}}) // IsRegistered testObjectAction(t, func() error { - _, e := GlobalShortcutIsRegistered("Ctrl+Y") + _, e := gs.IsRegistered("Ctrl+Y") return e - }, obj, wrt, fmt.Sprintf(`{"name":"%s","targetID":"%s","globalShortcut":{"accelerator":"Ctrl+Y"}}%s`, EventNameGlobalShortcutCmdIsRegistered, obj.id, "\n"), - EventNameGlobalShortcutEventProcessFinished, &Event{GlobalShortcut: &GlobalShortcut{Accelerator: "Ctrl+Y", IsRegistered: false}}) + }, gs.object, wrt, fmt.Sprintf(`{"name":"%s","targetID":"%s","globalShortcuts":{"accelerator":"Ctrl+Y"}}%s`, EventNameGlobalShortcutCmdIsRegistered, gs.id, "\n"), + EventNameGlobalShortcutEventProcessFinished, &Event{GlobalShortcuts: &EventGlobalShortcuts{Accelerator: "Ctrl+Y", IsRegistered: false}}) // Unregister testObjectAction(t, func() error { - return GlobalShortcutUnregister("Ctrl+Z") - }, obj, wrt, fmt.Sprintf(`{"name":"%s","targetID":"%s","globalShortcut":{"accelerator":"Ctrl+Z"}}%s`, EventNameGlobalShortcutCmdUnregister, obj.id, "\n"), + return gs.Unregister("Ctrl+Z") + }, gs.object, wrt, fmt.Sprintf(`{"name":"%s","targetID":"%s","globalShortcuts":{"accelerator":"Ctrl+Z"}}%s`, EventNameGlobalShortcutCmdUnregister, gs.id, "\n"), EventNameGlobalShortcutEventProcessFinished, nil) // UnregisterAll testObjectAction(t, func() error { - return GlobalShortcutUnregisterAll() - }, obj, wrt, fmt.Sprintf(`{"name":"%s","targetID":"%s"}%s`, EventNameGlobalShortcutCmdUnregisterAll, obj.id, "\n"), + return gs.UnregisterAll() + }, gs.object, wrt, fmt.Sprintf(`{"name":"%s","targetID":"%s"}%s`, EventNameGlobalShortcutCmdUnregisterAll, gs.id, "\n"), EventNameGlobalShortcutEventProcessFinished, nil) } From 75762cc0a2abf4ce2aedf75df0cd829f8afecf76 Mon Sep 17 00:00:00 2001 From: benebsiny Date: Mon, 4 Sep 2023 17:02:48 +0800 Subject: [PATCH 5/9] Updated --- global_shortcut.go | 123 ---------------- global_shortcuts.go | 135 ++++++++++++++++++ ...ortcut_test.go => global_shortcuts_test.go | 16 +-- 3 files changed, 143 insertions(+), 131 deletions(-) delete mode 100644 global_shortcut.go create mode 100644 global_shortcuts.go rename global_shortcut_test.go => global_shortcuts_test.go (67%) diff --git a/global_shortcut.go b/global_shortcut.go deleted file mode 100644 index bbd0e61..0000000 --- a/global_shortcut.go +++ /dev/null @@ -1,123 +0,0 @@ -package astilectron - -import "context" - -const ( - EventNameGlobalShortcutCmdRegister = "global.shortcuts.event.registered" - EventNameGlobalShortcutCmdIsRegistered = "global.shortcuts.event.is.registered" - EventNameGlobalShortcutCmdUnregister = "global.shortcuts.event.unregistered" - EventNameGlobalShortcutCmdUnregisterAll = "global.shortcuts.event.unregistered.all" - EventNameGlobalShortcutEventProcessFinished = "global.shortcuts.event.process.finished" // Register or Unregister process is finished - EventNameGlobalShortcutEventTriggered = "global.shortcuts.event.triggered" -) - -type callback func() - -// GlobalShortcuts represents a global shortcut -type GlobalShortcuts struct { - *object - callbacks map[string]*callback // Store all registered Global Shortcuts -} - -func newGlobalShortcuts(ctx context.Context, d *dispatcher, i *identifier, w *writer) (gs *GlobalShortcuts) { - var obj = newObject(ctx, d, i, w, i.new()) - gs = &GlobalShortcuts{object: obj, callbacks: make(map[string]*callback)} - - obj.On(EventNameGlobalShortcutEventTriggered, func(e Event) (deleteListener bool) { // Register the listener for the triggered event - globalShortcutHandler(gs, e.GlobalShortcuts.Accelerator) - return - }) - return -} - -// Register Register global shortcuts -func (gs *GlobalShortcuts) Register(accelerator string, callback callback) (isRegistered bool, err error) { - - if err = gs.ctx.Err(); err != nil { - return - } - - // Send an event to astilectron to register the global shortcut - var event = Event{Name: EventNameGlobalShortcutCmdRegister, TargetID: gs.id, GlobalShortcuts: &EventGlobalShortcuts{Accelerator: accelerator}} - result, err := synchronousEvent(gs.ctx, gs, gs.w, event, EventNameGlobalShortcutEventProcessFinished) - - if err != nil { - return - } - - // If registered successfully, add the callback to the map - if result.GlobalShortcuts.IsRegistered { - gs.callbacks[accelerator] = &callback - } - - isRegistered = result.GlobalShortcuts.IsRegistered - return -} - -// IsRegistered Check if 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 - var event = Event{Name: EventNameGlobalShortcutCmdIsRegistered, TargetID: gs.id, GlobalShortcuts: &EventGlobalShortcuts{Accelerator: accelerator}} - result, err := synchronousEvent(gs.ctx, gs, gs.w, event, EventNameGlobalShortcutEventProcessFinished) - - if err != nil { - return - } - - isRegistered = result.GlobalShortcuts.IsRegistered - return -} - -// Unregister Unregister 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 - var event = Event{Name: EventNameGlobalShortcutCmdUnregister, TargetID: gs.id, GlobalShortcuts: &EventGlobalShortcuts{Accelerator: accelerator}} - _, err = synchronousEvent(gs.ctx, gs, gs.w, event, EventNameGlobalShortcutEventProcessFinished) - - if err != nil { - return - } - - // No need to find the callback from the map and delete it - // because that event will no longer be triggerred - // If the same global shortcut is registered again, the original callback will be replaced with the new one - - return -} - -// UnregisterAll Unregister 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 - var event = Event{Name: EventNameGlobalShortcutCmdUnregisterAll, TargetID: gs.id} - _, err = synchronousEvent(gs.ctx, gs, gs.w, event, EventNameGlobalShortcutEventProcessFinished) - - if err != nil { - return - } - - gs.callbacks = make(map[string]*callback) // Clear the map - - return -} - -// globalShortcutHandler Handle the GlobalShortcuts event triggered from astilectron -func globalShortcutHandler(gs *GlobalShortcuts, accelerator string) { - if callback, ok := gs.callbacks[accelerator]; ok { - (*callback)() - } -} diff --git a/global_shortcuts.go b/global_shortcuts.go new file mode 100644 index 0000000..4bc50e1 --- /dev/null +++ b/global_shortcuts.go @@ -0,0 +1,135 @@ +package astilectron + +import ( + "context" + "sync" +) + +const ( + EventNameGlobalShortcutsCmdRegister = "global.shortcuts.cmd.register" + EventNameGlobalShortcutsCmdIsRegistered = "global.shortcuts.cmd.is.register" + 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 a global shortcut +type GlobalShortcuts struct { + *object + m *sync.Mutex + callbacks map[string]*globalShortcutsCallback // Store all registered Global Shortcuts +} + +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.execCallback(e.GlobalShortcuts.Accelerator) + return + }) + return +} + +// Register Register global shortcuts +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 + var event = Event{Name: EventNameGlobalShortcutsCmdRegister, TargetID: gs.id, GlobalShortcuts: &EventGlobalShortcuts{Accelerator: accelerator}} + result, err := synchronousEvent(gs.ctx, gs, gs.w, event, EventNameGlobalShortcutsEventRegistered) + + if err != nil { + return + } + + // If registered successfully, add the callback to the map + if result.GlobalShortcuts.IsRegistered { + gs.m.Lock() + gs.callbacks[accelerator] = &callback + gs.m.Unlock() + } + + isRegistered = result.GlobalShortcuts.IsRegistered + return +} + +// IsRegistered Check if 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 + var event = Event{Name: EventNameGlobalShortcutsCmdIsRegistered, TargetID: gs.id, GlobalShortcuts: &EventGlobalShortcuts{Accelerator: accelerator}} + result, err := synchronousEvent(gs.ctx, gs, gs.w, event, EventNameGlobalShortcutsEventIsRegistered) + + if err != nil { + return + } + + isRegistered = result.GlobalShortcuts.IsRegistered + return +} + +// Unregister Unregister 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 + var event = Event{Name: EventNameGlobalShortcutsCmdUnregister, TargetID: gs.id, GlobalShortcuts: &EventGlobalShortcuts{Accelerator: accelerator}} + _, err = synchronousEvent(gs.ctx, gs, gs.w, event, EventNameGlobalShortcutsEventUnregistered) + + if err != nil { + return + } + + // No need to find the callback from the map and delete it + // because that event will no longer be triggerred + // If the same global shortcut is registered again, the original callback will be replaced with the new one + + return +} + +// UnregisterAll Unregister 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 + var event = Event{Name: EventNameGlobalShortcutsCmdUnregisterAll, TargetID: gs.id} + _, err = synchronousEvent(gs.ctx, gs, gs.w, event, EventNameGlobalShortcutsEventUnregisteredAll) + + if err != nil { + return + } + + gs.m.Lock() + gs.callbacks = make(map[string]*globalShortcutsCallback) // Clear the map + gs.m.Unlock() + + return +} + +// execCallback Execute the GlobalShortcuts event triggered from astilectron +func (gs *GlobalShortcuts) execCallback(accelerator string) { + gs.m.Lock() + if callback, ok := gs.callbacks[accelerator]; ok { + (*callback)() + } + gs.m.Unlock() +} diff --git a/global_shortcut_test.go b/global_shortcuts_test.go similarity index 67% rename from global_shortcut_test.go rename to global_shortcuts_test.go index 08c1314..12a4e50 100644 --- a/global_shortcut_test.go +++ b/global_shortcuts_test.go @@ -18,25 +18,25 @@ func TestGlobalShortcut_Actions(t *testing.T) { 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`, EventNameGlobalShortcutCmdRegister, gs.id, "\n"), - EventNameGlobalShortcutEventProcessFinished, &Event{GlobalShortcuts: &EventGlobalShortcuts{Accelerator: "Ctrl+X", IsRegistered: true}}) + }, 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`, EventNameGlobalShortcutCmdIsRegistered, gs.id, "\n"), - EventNameGlobalShortcutEventProcessFinished, &Event{GlobalShortcuts: &EventGlobalShortcuts{Accelerator: "Ctrl+Y", IsRegistered: false}}) + }, 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`, EventNameGlobalShortcutCmdUnregister, gs.id, "\n"), - EventNameGlobalShortcutEventProcessFinished, nil) + }, 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`, EventNameGlobalShortcutCmdUnregisterAll, gs.id, "\n"), - EventNameGlobalShortcutEventProcessFinished, nil) + }, gs.object, wrt, fmt.Sprintf(`{"name":"%s","targetID":"%s"}%s`, EventNameGlobalShortcutsCmdUnregisterAll, gs.id, "\n"), + EventNameGlobalShortcutsEventUnregisteredAll, nil) } From a47d53aec608913c8ff8ceb234a19ac09c6af0bb Mon Sep 17 00:00:00 2001 From: benebsiny Date: Thu, 14 Dec 2023 23:46:38 +0800 Subject: [PATCH 6/9] Updated --- README.md | 8 ++--- astilectron.go | 1 - global_shortcuts.go | 79 ++++++++++++++++++++------------------------- 3 files changed, 39 insertions(+), 49 deletions(-) diff --git a/README.md b/README.md index bf2cb12..30ee3f2 100644 --- a/README.md +++ b/README.md @@ -452,19 +452,19 @@ Registering a global shortcut. ```go // Register a new global shortcut -isRegistered, _ := astilectron.GlobalShortcutRegister("CmdOrCtrl+x", func() { +isRegistered, _ := a.GlobalShortcuts().Register("CmdOrCtrl+x", func() { fmt.Println("CmdOrCtrl+x is pressed") }) fmt.Println("CmdOrCtrl+x is registered:", isRegistered) // true // Check if a global shortcut is registered -isRegistered, _ = astilectron.GlobalShortcutIsRegistered("Shift+Y") // false +isRegistered, _ = a.GlobalShortcuts().IsRegistered("Shift+Y") // false // Unregister a global shortcut -astilectron.GlobalShortcutUnregister("CmdOrCtrl+x") +a.GlobalShortcuts().Unregister("CmdOrCtrl+x") // Unregister all global shortcuts -astilectron.GlobalShortcutUnregisterAll() +a.GlobalShortcuts().UnregisterAll() ``` ## Dialogs diff --git a/astilectron.go b/astilectron.go index ee28f92..2c09353 100644 --- a/astilectron.go +++ b/astilectron.go @@ -192,7 +192,6 @@ func (a *Astilectron) Start() (err error) { } else { synchronousFunc(a.worker.Context(), a, nil, "app.event.ready") } - return nil } diff --git a/global_shortcuts.go b/global_shortcuts.go index 4bc50e1..744051f 100644 --- a/global_shortcuts.go +++ b/global_shortcuts.go @@ -7,7 +7,7 @@ import ( const ( EventNameGlobalShortcutsCmdRegister = "global.shortcuts.cmd.register" - EventNameGlobalShortcutsCmdIsRegistered = "global.shortcuts.cmd.is.register" + EventNameGlobalShortcutsCmdIsRegistered = "global.shortcuts.cmd.is.registered" EventNameGlobalShortcutsCmdUnregister = "global.shortcuts.cmd.unregister" EventNameGlobalShortcutsCmdUnregisterAll = "global.shortcuts.cmd.unregister.all" EventNameGlobalShortcutsEventRegistered = "global.shortcuts.event.registered" @@ -19,79 +19,82 @@ const ( type globalShortcutsCallback func() -// GlobalShortcuts represents a global shortcut +// GlobalShortcuts represents global shortcuts type GlobalShortcuts struct { *object - m *sync.Mutex - callbacks map[string]*globalShortcutsCallback // Store all registered Global Shortcuts + m *sync.Mutex } -func newGlobalShortcuts(ctx context.Context, d *dispatcher, i *identifier, w *writer) (gs *GlobalShortcuts) { +var callbacks map[string]*globalShortcutsCallback - gs = &GlobalShortcuts{object: newObject(ctx, d, i, w, i.new()), m: new(sync.Mutex), callbacks: make(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), + } gs.On(EventNameGlobalShortcutEventTriggered, func(e Event) (deleteListener bool) { // Register the listener for the triggered event - gs.execCallback(e.GlobalShortcuts.Accelerator) + gs.m.Lock() + callback, ok := callbacks[e.GlobalShortcuts.Accelerator] + gs.m.Unlock() + if ok { + (*callback)() + } return }) + callbacks = make(map[string]*globalShortcutsCallback) return } -// Register Register global shortcuts +// 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 - var event = Event{Name: EventNameGlobalShortcutsCmdRegister, TargetID: gs.id, GlobalShortcuts: &EventGlobalShortcuts{Accelerator: accelerator}} - result, err := synchronousEvent(gs.ctx, gs, gs.w, event, EventNameGlobalShortcutsEventRegistered) - + 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.IsRegistered { - gs.m.Lock() - gs.callbacks[accelerator] = &callback - gs.m.Unlock() + if result.GlobalShortcuts != nil { + if result.GlobalShortcuts.IsRegistered { + gs.m.Lock() + callbacks[accelerator] = &callback + gs.m.Unlock() + } + isRegistered = result.GlobalShortcuts.IsRegistered } - - isRegistered = result.GlobalShortcuts.IsRegistered return } -// IsRegistered Check if a global shortcut is registered +// 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 - var event = Event{Name: EventNameGlobalShortcutsCmdIsRegistered, TargetID: gs.id, GlobalShortcuts: &EventGlobalShortcuts{Accelerator: accelerator}} - result, err := synchronousEvent(gs.ctx, gs, gs.w, event, EventNameGlobalShortcutsEventIsRegistered) - + result, err := synchronousEvent(gs.ctx, gs, gs.w, Event{Name: EventNameGlobalShortcutsCmdIsRegistered, TargetID: gs.id, GlobalShortcuts: &EventGlobalShortcuts{Accelerator: accelerator}}, EventNameGlobalShortcutsEventIsRegistered) if err != nil { return } - isRegistered = result.GlobalShortcuts.IsRegistered + if result.GlobalShortcuts != nil { + isRegistered = result.GlobalShortcuts.IsRegistered + } return } -// Unregister Unregister a global shortcut +// 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 - var event = Event{Name: EventNameGlobalShortcutsCmdUnregister, TargetID: gs.id, GlobalShortcuts: &EventGlobalShortcuts{Accelerator: accelerator}} - _, err = synchronousEvent(gs.ctx, gs, gs.w, event, EventNameGlobalShortcutsEventUnregistered) - + _, err = synchronousEvent(gs.ctx, gs, gs.w, Event{Name: EventNameGlobalShortcutsCmdUnregister, TargetID: gs.id, GlobalShortcuts: &EventGlobalShortcuts{Accelerator: accelerator}}, EventNameGlobalShortcutsEventUnregistered) if err != nil { return } @@ -103,33 +106,21 @@ func (gs *GlobalShortcuts) Unregister(accelerator string) (err error) { return } -// UnregisterAll Unregister all global shortcuts +// 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 - var event = Event{Name: EventNameGlobalShortcutsCmdUnregisterAll, TargetID: gs.id} - _, err = synchronousEvent(gs.ctx, gs, gs.w, event, EventNameGlobalShortcutsEventUnregisteredAll) - + _, 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 + callbacks = make(map[string]*globalShortcutsCallback) // Clear the map gs.m.Unlock() return } - -// execCallback Execute the GlobalShortcuts event triggered from astilectron -func (gs *GlobalShortcuts) execCallback(accelerator string) { - gs.m.Lock() - if callback, ok := gs.callbacks[accelerator]; ok { - (*callback)() - } - gs.m.Unlock() -} From 35cffd497332392e31b50de68cdf37ed3ff9922b Mon Sep 17 00:00:00 2001 From: benebsiny Date: Sat, 16 Dec 2023 12:13:05 +0800 Subject: [PATCH 7/9] Updated --- global_shortcuts.go | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/global_shortcuts.go b/global_shortcuts.go index 744051f..508219e 100644 --- a/global_shortcuts.go +++ b/global_shortcuts.go @@ -25,7 +25,7 @@ type GlobalShortcuts struct { m *sync.Mutex } -var callbacks map[string]*globalShortcutsCallback +var callbacks map[string]globalShortcutsCallback func newGlobalShortcuts(ctx context.Context, d *dispatcher, i *identifier, w *writer) (gs *GlobalShortcuts) { gs = &GlobalShortcuts{ @@ -37,11 +37,11 @@ func newGlobalShortcuts(ctx context.Context, d *dispatcher, i *identifier, w *wr callback, ok := callbacks[e.GlobalShortcuts.Accelerator] gs.m.Unlock() if ok { - (*callback)() + (callback)() } return }) - callbacks = make(map[string]*globalShortcutsCallback) + callbacks = make(map[string]globalShortcutsCallback) return } @@ -61,7 +61,7 @@ func (gs *GlobalShortcuts) Register(accelerator string, callback globalShortcuts if result.GlobalShortcuts != nil { if result.GlobalShortcuts.IsRegistered { gs.m.Lock() - callbacks[accelerator] = &callback + callbacks[accelerator] = callback gs.m.Unlock() } isRegistered = result.GlobalShortcuts.IsRegistered @@ -96,13 +96,11 @@ func (gs *GlobalShortcuts) Unregister(accelerator string) (err error) { // 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 { + gs.m.Lock() + delete(callbacks, accelerator) + gs.m.Unlock() return } - - // No need to find the callback from the map and delete it - // because that event will no longer be triggerred - // If the same global shortcut is registered again, the original callback will be replaced with the new one - return } @@ -119,7 +117,7 @@ func (gs *GlobalShortcuts) UnregisterAll() (err error) { } gs.m.Lock() - callbacks = make(map[string]*globalShortcutsCallback) // Clear the map + callbacks = make(map[string]globalShortcutsCallback) // Clear the map gs.m.Unlock() return From 6b0bc39713759333a13c95fc1e32451c2431568d Mon Sep 17 00:00:00 2001 From: benebsiny Date: Thu, 21 Dec 2023 15:10:12 +0800 Subject: [PATCH 8/9] Updated --- global_shortcuts.go | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/global_shortcuts.go b/global_shortcuts.go index 508219e..bac6180 100644 --- a/global_shortcuts.go +++ b/global_shortcuts.go @@ -22,26 +22,26 @@ type globalShortcutsCallback func() // GlobalShortcuts represents global shortcuts type GlobalShortcuts struct { *object - m *sync.Mutex + m *sync.Mutex + callbacks map[string]globalShortcutsCallback } -var 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), + 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 := callbacks[e.GlobalShortcuts.Accelerator] + callback, ok := gs.callbacks[e.GlobalShortcuts.Accelerator] gs.m.Unlock() if ok { (callback)() } return }) - callbacks = make(map[string]globalShortcutsCallback) + gs.callbacks = make(map[string]globalShortcutsCallback) return } @@ -61,7 +61,7 @@ func (gs *GlobalShortcuts) Register(accelerator string, callback globalShortcuts if result.GlobalShortcuts != nil { if result.GlobalShortcuts.IsRegistered { gs.m.Lock() - callbacks[accelerator] = callback + gs.callbacks[accelerator] = callback gs.m.Unlock() } isRegistered = result.GlobalShortcuts.IsRegistered @@ -96,11 +96,11 @@ func (gs *GlobalShortcuts) Unregister(accelerator string) (err error) { // 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 { - gs.m.Lock() - delete(callbacks, accelerator) - gs.m.Unlock() return } + gs.m.Lock() + delete(gs.callbacks, accelerator) + gs.m.Unlock() return } @@ -117,7 +117,7 @@ func (gs *GlobalShortcuts) UnregisterAll() (err error) { } gs.m.Lock() - callbacks = make(map[string]globalShortcutsCallback) // Clear the map + gs.callbacks = make(map[string]globalShortcutsCallback) // Clear the map gs.m.Unlock() return From 985de79bc28d798687c042671ddede4cba6ce079 Mon Sep 17 00:00:00 2001 From: benebsiny Date: Thu, 21 Dec 2023 16:49:59 +0800 Subject: [PATCH 9/9] Updated --- astilectron.go | 2 +- global_shortcuts.go | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/astilectron.go b/astilectron.go index 2c09353..8f376d9 100644 --- a/astilectron.go +++ b/astilectron.go @@ -12,7 +12,7 @@ import ( // Versions const ( DefaultAcceptTCPTimeout = 30 * time.Second - DefaultVersionAstilectron = "0.57.0" + DefaultVersionAstilectron = "0.58.0" DefaultVersionElectron = "11.4.3" ) diff --git a/global_shortcuts.go b/global_shortcuts.go index bac6180..1239f50 100644 --- a/global_shortcuts.go +++ b/global_shortcuts.go @@ -41,7 +41,6 @@ func newGlobalShortcuts(ctx context.Context, d *dispatcher, i *identifier, w *wr } return }) - gs.callbacks = make(map[string]globalShortcutsCallback) return }