Expose runOnMain as public API

Running a function on the main thread is impossible and occupied by Gio internally. The reason is that some OS or graphical APIs require to be executed on the main thread.

This fundamentally limits developers to extend unimplemented Gio applications, such as registering a hotkey.

It would be beneficial if "app" package can provide a public API to execute functions on the main thread, the API signature can be:

package app

func CallOnMainThread(f func())

The name can be "RunOnMainThread" or other preferred names.

For a specific example, the package "https://pkg.go.dev/golang.design/x/hotkey@v0.3.0-alpha" collaborates with Gio, which is an unimplemented feature.

Here is a proof-of-concept change that exposes runOnMain: https://github.com/changkun/gio/commit/976e5ed303a0ee2fa192c5a686e3b31fc1e8163a

Here is a complete example that benefits the public version of runOnMain: https://github.com/changkun/demos/blob/main/hotkeys/gioapp/main.go

Any thoughts?

Assigned to
2 years ago
2 years ago
No labels applied.

~inkeliz 2 years ago*

It's current possible, using window.Run(): https://pkg.go.dev/gioui.org@v0.0.0-20211230092323-cce0a121e1b8/app#Window.Run

You need the window (which is from app.NewWindow()) and then you can call go window.Run(func(){ /* your func */ }).

You can see one usage of window.Run() on explorer (file-dialog) for macOS and iOS: https://github.com/gioui/gio-x/blob/f5f715dc3294a74c6071a559717ef3d9f290cddc/explorer/explorer_ios.go#L86-L90

There's any advantage of app.CallOnMainThread instead of window.Run()?

~changkun 2 years ago

The main difference between app.(*Window).Run and app.CallOnMainThread is that: app.(*Window).Run only calls the given f on a customized event loop rather than the OS main event loop, whereas the app.CallOnMainThread communicates to the main event loop, occupied and running internally in by [NSApp run].

The above hotkey example does not work when using app.(*Window).Run.

~eliasnaur 2 years ago

Why not have Hotkey.Register run on the main thread automatically? I assume its implementation calls into Cocoa anyway.

~changkun 2 years ago

  1. When it collaborates with Gio, it is impossible to run on the main thread automatically because Gio occupies it.
  2. Even the register is called on the main thread before the Gio app.Main() starts, a user may still wish to dynamically register/unregister the hotkeys at runtime. At this point, it is already impossible to do as runOnMain is not exposed to the public.

~changkun 2 years ago

I think the hotkey register is an example of demonstrating why running on mainthread is necessary for developers. Indeed, an NSObject method permits developers on darwin to run any function on mainthread. Still, the benefits of Gio providing an API for it would be, such execution can be managed from Gio. Similar to the previously mentioned app.(*Window).Run.

Another example would be that Android might also be a platform that developers would like to access mainthread. One more example would be that developers who wrap C code that need mainthread on whatever platform will also be benefit from such an API.

~eliasnaur REPORTED WONT_FIX 2 years ago

I agree that runOnMain is beneficial, but I'm not convinced it belongs in Gio. First, it can be done as a separately maintained Go package. Second, if you need the main thread, you're likely doing something platform-specific and your own runOnMain implementation is not a great additional burden.

Register here or Log in to comment, or comment via email.