Closed dirslashls closed 8 months ago
It cannot be replicated with your code as you provide no setup to demonstrate that the icon appears...
This function certainly does work as it's required by Fyne toolkit as well. If you can provide an actual replication code we can look into it further.
Thank you @andydotxyz for quick response. I have created a standalone test case at https://github.com/dirslashls/windows11-systray-gioui
The simple program can be invoked in external and normal mode. When invoked in external mode, the menu is not being displayed for me in Windows 11.
I know why RunWithExternalLoop doesn't work on Windows although I don't know how to fix it. The problem is that the GUI thread, which is the main thread, is different from the go routine thread eventually called via RunWithExternalLoop. The GetMessageW API on which this routine waits for events is using a different context. I tried to see if it is possible to force a go routine to a specific OS thread. Unfortunately, that API only makes it sticky into the current thread it is already running on.
I restructured my code such that I only use systray.Run command. It so happens that on Windows and Linux, the app.Main of GUI are practically noops (with just select {}
) and so there is no real benefit of using RunWithExternalLoop and then blocking with app.Main. If ever GioUI also wants to block the main thread, then we will have issues integrating both GioUI and systray.
Thanks @andydotxyz for all your support. I am closing this now and will also be removing the above mentioned test case repo I created.
I know why RunWithExternalLoop doesn't work on Windows although I don't know how to fix it. The problem is that the GUI thread, which is the main thread, is different from the go routine thread eventually called via RunWithExternalLoop. The GetMessageW API on which this routine waits for events is using a different context. I tried to see if it is possible to force a go routine to a specific OS thread. Unfortunately, that API only makes it sticky into the current thread it is already running on.
I restructured my code such that I only use systray.Run command. It so happens that on Windows and Linux, the app.Main of GUI are practically noops (with just
select {}
) and so there is no real benefit of using RunWithExternalLoop and then blocking with app.Main. If ever GioUI also wants to block the main thread, then we will have issues integrating both GioUI and systray.Thanks @andydotxyz for all your support. I am closing this now and will also be removing the above mentioned test case repo I created.
Ok thanks for this. What was spawning a new goroutines? The runloop is expected to be running on main because most OS require that...
I restructured my code such that I only use systray.Run command. It so happens that on Windows and Linux, the app.Main of GUI are practically noops (with just select {}) and so there is no real benefit of using RunWithExternalLoop and then blocking with app.Main. If ever GioUI also wants to block the main thread, then we will have issues integrating both GioUI and systray.
It certainly should work. Fyne uses RunWithExternalLoop and it works correctly on all platforms. Are you certain there were no other goroutines created with the GioUI integration in your code?
I tried to see if it is possible to force a go routine to a specific OS thread. Unfortunately, that API only makes it sticky into the current thread it is already running on.
Would it help to lock to the thread before invoking any systray code?
As far as I know you can't schedule a go routine to a specific thread.
I used go lang windows api to print the thread id and so with RunWithExternalLoop it always ended up in a separate thread. What is surprising is that using "go systray.Run" which is equivalent, ended up on the same thread (perhaps most of the time as even that didn't work a couple of times). I don't think we have any guarantees from go runtime on which go routine is scheduled on what thread.
There are guarantees in https://pkg.go.dev/runtime#LockOSThread
Yes, you can call it from within the go routine to make it sticky to the thread it is already assigned. How do you start it on a specific thread, like the main thread?
By calling that in your init function. I think that is in their docs.
init runs within main I think. But go routine that is spawned from main doesn't inherit the thread due to LockOSThread. I think there is an open issue in golang asking to let the child go routines inherit the parent context.
I guess I'm out of ideas sorry. I know this works but can't figure out why it's not working for you.
No worries, I changed my logic to use Run for Windows. It works on Mac, Windows and Linux. BTW, it is a completely free and fully functional desktop app with no expiration if you want to try it. It can be downloaded at https://sqlframes.com/docs-sheets-bi/sheets-bi/desktop/installation/ . I am waiting on getting a DUNS number for Apple developer team account so I can sign the app. For now, it is unsigned.
Hello, I have systray integrated with gioui and they work together great on Mac. However, on Windows 11 the app icon is present in the tray but the menu items added are not showing up.
Works:
Not working:
Any suggestion on how to get this working?