Merge pull request #28 from getlantern/flashlight-258-ox

Made onExit run reliably and process terminate on quit
This commit is contained in:
joesis
2017-08-28 15:02:20 +08:00
committed by GitHub
15 changed files with 208 additions and 130 deletions
+1
View File
@@ -6,3 +6,4 @@ Release
Debug
*.sdf
dll/systray_unsigned.dll
out.txt
+5 -1
View File
@@ -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.
BIN
View File
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.
+8 -10
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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);
+7 -1
View File
@@ -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
View File
@@ -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
+1
View File
@@ -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;
}
+5
View File
@@ -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
View File
File diff suppressed because one or more lines are too long