getlantern / systray

a cross platfrom Go library to place an icon and menu in the notification area
Apache License 2.0
3.28k stars 451 forks source link

Terminating process leaves icon visible #237

Open andrewfstratton opened 2 years ago

andrewfstratton commented 2 years ago

(Run on Win 11)

When I terminate the go application - the tray icon is left visible in the sys tray (possibly off screen) and will remain there until mouse over - it then disappears. This happens when:

If I run the application several times and keep restarting, a new icon is generated every time - where only the latest one is a valid running application.

Note: this is not to do with properly exited (quit) applications - which works fine - but when the process is terminated, it seems the icon is not tidied up.

Crosse commented 2 years ago

This sounds like your application is not handling Ctrl-C and performing cleanup, but I could be wrong. Killing the app with VSCode will also not let the app do any cleanup it needs to do. Any time you unceremoniously kill an app that has an icon in the system tray, the icon will get left behind; at least that's my experience.

andrewfstratton commented 2 years ago

That is exactly correct - I guess you're saying that systray won't tidy up after itself - and the example code in the Readme.md also has the same issue (I think).

Could/should systray maybe handle an OS Interrupt and exit gracefully?

andrewfstratton commented 2 years ago

I tried adding a handler for Ctrl C - see below (modified from https://golangcode.com/handle-ctrl-c-exit-in-terminal/).

The output after hitting Ctrl-C in the command line shows (correctly) Quit... then Exit..., but again, the icon still remains in the system tray until I mouse over it - then it disappears. So calling systray.Quit() doesn't seem to tidy up the icon.

I then checked quitting through the systray menu - and the icon only disappears if I happen to have the mouse over the icon at the time...so this doesn't seem to work either.

Any help/suggestions please?

func Run() {
    // handle OS interrupt
    interrupt_channel := make(chan os.Signal)
    signal.Notify(interrupt_channel, os.Interrupt)
    go handleInterrupt(interrupt_channel)
    // N.B. next line blocks until quit...
    systray.Run(setup, close)
}

func handleInterrupt(interrupt chan os.Signal) {
    <-interrupt
    fmt.Println("Quit...")
    systray.Quit()
    fmt.Println("Exit...")
    os.Exit(0)
}
andrewfstratton commented 2 years ago

Solved - I added a 1 second delay after systray.Quit() before closing everything else down - and the icon disappears correctly...i.e. after menu quitting and after Ctrl-C.

So it looks like systray.Quit() doesn't get enough time to tidy up if you just exit the application. Possibly this could be fixed by making it return only when the icon has been removed (?).

Still doesn't work when VSCode halts and then kills the application - but I can live with that :)