diff options
| author | joesis | 2017-08-28 15:02:45 +0800 | 
|---|---|---|
| committer | GitHub | 2017-08-28 15:02:45 +0800 | 
| commit | 6f1d1d82e189395fa6266fcdb665a50531918d25 (patch) | |
| tree | 7bb33595a16c1a57b4454f014b48fc08e1ec2406 /systray.go | |
| parent | 0068f6ae40ea39bfd683043e8452024097fff0e4 (diff) | |
| parent | e78cfcfa229acdd9af7489540c20419ee5cb05a8 (diff) | |
| download | systray-6f1d1d82e189395fa6266fcdb665a50531918d25.tar.bz2 | |
Merge pull request #29 from getlantern/flashlight-258
Exit handling improvements
Diffstat (limited to 'systray.go')
| -rw-r--r-- | systray.go | 47 | 
1 files changed, 31 insertions, 16 deletions
| @@ -1,7 +1,9 @@  /* -Package systray is a cross platfrom Go library to place an icon and menu in the notification area. +Package systray is a cross platfrom Go library to place an icon and menu in the +notification area.  Supports Windows, Mac OSX and Linux currently. -Methods can be called from any goroutine except Run(), which should be called at the very beginning of main() to lock at main thread. +Methods can be called from any goroutine except Run(), which should be called +at the very beginning of main() to lock at main thread.  */  package systray @@ -17,7 +19,7 @@ import (  // Don't create it directly, use the one systray.AddMenuItem() returned  type MenuItem struct {  	// ClickedCh is the channel which will be notified when the menu item is clicked -	ClickedCh chan interface{} +	ClickedCh chan struct{}  	// id uniquely identify a menu item, not supposed to be modified  	id int32 @@ -34,8 +36,8 @@ type MenuItem struct {  var (  	log = golog.LoggerFor("systray") -	readyCh       = make(chan interface{}) -	clickedCh     = make(chan interface{}) +	systrayReady  func() +	systrayExit   func()  	menuItems     = make(map[int32]*MenuItem)  	menuItemsLock sync.RWMutex @@ -46,12 +48,29 @@ var (  // callback.  // It blocks until systray.Quit() is called.  // Should be called at the very beginning of main() to lock at main thread. -func Run(onReady func()) { +func Run(onReady func(), onExit func()) {  	runtime.LockOSThread() -	go func() { -		<-readyCh -		onReady() -	}() + +	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()  } @@ -68,7 +87,7 @@ func Quit() {  func AddMenuItem(title string, tooltip string) *MenuItem {  	id := atomic.AddInt32(¤tID, 1)  	item := &MenuItem{nil, id, title, tooltip, false, false} -	item.ClickedCh = make(chan interface{}) +	item.ClickedCh = make(chan struct{})  	item.update()  	return item  } @@ -127,16 +146,12 @@ func (item *MenuItem) update() {  	addOrUpdateMenuItem(item)  } -func systrayReady() { -	readyCh <- nil -} -  func systrayMenuItemSelected(id int32) {  	menuItemsLock.RLock()  	item := menuItems[id]  	menuItemsLock.RUnlock()  	select { -	case item.ClickedCh <- nil: +	case item.ClickedCh <- struct{}{}:  	// in case no one waiting for the channel  	default:  	} | 
