mirror of
https://github.com/netbirdio/systray.git
synced 2026-05-22 17:08:41 -07:00
Merge pull request #28 from getlantern/flashlight-258-ox
Made onExit run reliably and process terminate on quit
This commit is contained in:
@@ -6,3 +6,4 @@ Release
|
||||
Debug
|
||||
*.sdf
|
||||
dll/systray_unsigned.dll
|
||||
out.txt
|
||||
|
||||
@@ -5,7 +5,7 @@ Tested on Windows 8, Mac OSX, Ubuntu 14.10 and Debian 7.6.
|
||||
```go
|
||||
func main() {
|
||||
// Should be called at the very beginning of main().
|
||||
systray.Run(onReady)
|
||||
systray.Run(onReady, onExit)
|
||||
}
|
||||
|
||||
func onReady() {
|
||||
@@ -14,6 +14,10 @@ func onReady() {
|
||||
systray.SetTooltip("Pretty awesome超级棒")
|
||||
mQuit := systray.AddMenuItem("Quit", "Quit the whole app")
|
||||
}
|
||||
|
||||
func onExit() {
|
||||
// clean up here
|
||||
}
|
||||
```
|
||||
Menu item can be checked and / or disabled. Methods except `Run()` can be invoked from any goroutine. See demo code under `example` folder.
|
||||
|
||||
|
||||
Binary file not shown.
Executable
BIN
Binary file not shown.
Binary file not shown.
Executable
BIN
Binary file not shown.
+8
-10
@@ -2,7 +2,8 @@ package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"io/ioutil"
|
||||
"time"
|
||||
|
||||
"github.com/getlantern/systray"
|
||||
"github.com/getlantern/systray/example/icon"
|
||||
@@ -10,15 +11,11 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
file, err := os.Create("out.txt")
|
||||
if err != nil {
|
||||
fmt.Println("Couldn't create out.txt")
|
||||
return
|
||||
}
|
||||
defer file.Close()
|
||||
onExit := func() {
|
||||
file.Write([]byte("On Exit..."))
|
||||
file.Sync()
|
||||
fmt.Println("Starting onExit")
|
||||
now := time.Now()
|
||||
ioutil.WriteFile(fmt.Sprintf(`on_exit_%d.txt`, now.UnixNano()), []byte(now.String()), 0644)
|
||||
fmt.Println("Finished onExit")
|
||||
}
|
||||
// Should be called at the very beginning of main().
|
||||
systray.Run(onReady, onExit)
|
||||
@@ -31,8 +28,9 @@ func onReady() {
|
||||
mQuit := systray.AddMenuItem("Quit", "Quit the whole app")
|
||||
go func() {
|
||||
<-mQuit.ClickedCh
|
||||
fmt.Println("Requesting quit")
|
||||
systray.Quit()
|
||||
fmt.Println("Quit now...")
|
||||
fmt.Println("Finished quitting")
|
||||
}()
|
||||
|
||||
// We can manipulate the systray in other goroutines
|
||||
|
||||
+2
-1
@@ -21,4 +21,5 @@ then
|
||||
echo "Installing osslsigncode"
|
||||
brew install osslsigncode || die "Could not install osslsigncode"
|
||||
fi
|
||||
osslsigncode sign -pkcs12 "$BNS_CERT" -pass "$BNS_CERT_PASS" -in dll/systray_unsigned.dll -out dll/systray.dll || die "Could not sign windows dll"
|
||||
osslsigncode sign -pkcs12 "$BNS_CERT" -pass "$BNS_CERT_PASS" -in dll/systray386.dll_unsigned -out dll/systray386.dll || die "Could not sign windows 386 dll"
|
||||
osslsigncode sign -pkcs12 "$BNS_CERT" -pass "$BNS_CERT_PASS" -in dll/systrayamd64.dll_unsigned -out dll/systrayamd64.dll || die "Could not sign windows 386 dll"
|
||||
|
||||
+22
-20
@@ -36,8 +36,8 @@ type MenuItem struct {
|
||||
var (
|
||||
log = golog.LoggerFor("systray")
|
||||
|
||||
readyCh = make(chan struct{})
|
||||
exitCh = make(chan struct{})
|
||||
systrayReady func()
|
||||
systrayExit func()
|
||||
menuItems = make(map[int32]*MenuItem)
|
||||
menuItemsLock sync.RWMutex
|
||||
|
||||
@@ -50,17 +50,27 @@ var (
|
||||
// Should be called at the very beginning of main() to lock at main thread.
|
||||
func Run(onReady func(), onExit func()) {
|
||||
runtime.LockOSThread()
|
||||
go func() {
|
||||
for {
|
||||
select {
|
||||
case <-readyCh:
|
||||
onReady()
|
||||
case <-exitCh:
|
||||
onExit()
|
||||
return
|
||||
}
|
||||
|
||||
if onReady == nil {
|
||||
systrayReady = func() {}
|
||||
} else {
|
||||
// Run onReady on separate goroutine to avoid blocking event loop
|
||||
readyCh := make(chan interface{})
|
||||
go func() {
|
||||
<-readyCh
|
||||
onReady()
|
||||
}()
|
||||
systrayReady = func() {
|
||||
close(readyCh)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
// unlike onReady, onExit runs in the event loop to make sure it has time to
|
||||
// finish before the process terminates
|
||||
if onExit == nil {
|
||||
onExit = func() {}
|
||||
}
|
||||
systrayExit = onExit
|
||||
|
||||
nativeLoop()
|
||||
}
|
||||
@@ -136,14 +146,6 @@ func (item *MenuItem) update() {
|
||||
addOrUpdateMenuItem(item)
|
||||
}
|
||||
|
||||
func systrayReady() {
|
||||
readyCh <- struct{}{}
|
||||
}
|
||||
|
||||
func systrayExit() {
|
||||
exitCh <- struct{}{}
|
||||
}
|
||||
|
||||
func systrayMenuItemSelected(id int32) {
|
||||
menuItemsLock.RLock()
|
||||
item := menuItems[id]
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
extern void systray_ready();
|
||||
extern void systray_on_exit();
|
||||
extern void systray_menu_item_selected(int menu_id);
|
||||
int nativeLoop(void);
|
||||
|
||||
|
||||
@@ -63,11 +63,17 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||
}
|
||||
break;
|
||||
case WM_DESTROY:
|
||||
printf("Window destroyed\n");
|
||||
systray_on_exit(0/*ignored*/);
|
||||
Shell_NotifyIcon(NIM_DELETE, &nid);
|
||||
PostQuitMessage(0);
|
||||
break;
|
||||
case WM_ENDSESSION:
|
||||
printf("Session ending\n");
|
||||
// When the system shuts down (or logs off), we don't receive WM_DESTROY,
|
||||
// so we capture WM_ENDSESSION instead and call on_exit here too.
|
||||
systray_on_exit(0/*ignored*/);
|
||||
Shell_NotifyIcon(NIM_DELETE, &nid);
|
||||
break;
|
||||
case WM_SYSTRAY_MESSAGE:
|
||||
switch(lParam) {
|
||||
@@ -216,5 +222,5 @@ void add_or_update_menu_item(int menuId, wchar_t* title, wchar_t* tooltip, short
|
||||
}
|
||||
|
||||
void quit() {
|
||||
Shell_NotifyIcon(NIM_DELETE, &nid);
|
||||
PostMessage(hWnd, WM_CLOSE, 0, 0);
|
||||
}
|
||||
|
||||
+6
-1
@@ -58,6 +58,11 @@
|
||||
systray_ready();
|
||||
}
|
||||
|
||||
- (void)applicationWillTerminate:(NSNotification *)aNotification
|
||||
{
|
||||
systray_on_exit();
|
||||
}
|
||||
|
||||
- (void)setIcon:(NSImage *)image {
|
||||
[statusItem setImage:image];
|
||||
}
|
||||
@@ -105,7 +110,7 @@
|
||||
|
||||
- (void) quit
|
||||
{
|
||||
[[NSStatusBar systemStatusBar] removeStatusItem: statusItem];
|
||||
[NSApp terminate:self];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -34,6 +34,7 @@ int nativeLoop(void) {
|
||||
global_temp_icon_file_names = g_array_new(TRUE, FALSE, sizeof(char*));
|
||||
systray_ready();
|
||||
gtk_main();
|
||||
systray_on_exit();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -65,6 +65,11 @@ func systray_ready() {
|
||||
systrayReady()
|
||||
}
|
||||
|
||||
//export systray_on_exit
|
||||
func systray_on_exit() {
|
||||
systrayExit()
|
||||
}
|
||||
|
||||
//export systray_menu_item_selected
|
||||
func systray_menu_item_selected(cID C.int) {
|
||||
systrayMenuItemSelected(int32(cID))
|
||||
|
||||
+150
-96
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user