M app/app.go => app/app.go +0 -12
@@ 120,18 120,6 @@ func DataDir() (string, error) {
return dataDir()
}
-// Main must be called last from the program main function.
-// On most platforms Main blocks forever, for Android and
-// iOS it returns immediately to give control of the main
-// thread back to the system.
-//
-// Calling Main is necessary because some operating systems
-// require control of the main thread of the program for
-// running windows.
-func Main() {
- osMain()
-}
-
func (FrameEvent) ImplementsEvent() {}
func init() {
M app/doc.go => app/doc.go +5 -21
@@ 33,28 33,12 @@ For example:
A program must keep receiving events from the event channel until
[DestroyEvent] is received.
-# Main
+# Main Thread
-The Main function must be called from a program's main function, to hand over
-control of the main thread to operating systems that need it.
-
-Because Main is also blocking on some platforms, the event loop of a Window must run in a goroutine.
-
-For example, to display a blank but otherwise functional window:
-
- package main
-
- import "gioui.org/app"
-
- func main() {
- go func() {
- w := app.NewWindow()
- for {
- w.Event()
- }
- }()
- app.Main()
- }
+Some GUI platform need access to the main thread of the program. To avoid a
+deadlock on such platforms, at least one Window must have its Event method
+called by the main goroutine. It doesn't have to be any particular Window;
+even a destroyed Window suffices.
# Permissions
M app/os_android.go => app/os_android.go +0 -3
@@ 1317,9 1317,6 @@ func findClass(env *C.JNIEnv, name string) C.jclass {
return C.jni_FindClass(env, cn)
}
-func osMain() {
-}
-
func newWindow(window *callbacks, options []Option) {
mainWindow.in <- windowAndConfig{window, options}
<-mainWindow.windows
M app/os_ios.go => app/os_ios.go +0 -3
@@ 388,9 388,6 @@ func newWindow(win *callbacks, options []Option) {
<-mainWindow.windows
}
-func osMain() {
-}
-
//export gio_runMain
func gio_runMain() {
runMain()
M app/os_js.go => app/os_js.go +0 -4
@@ 741,10 741,6 @@ func (w *window) navigationColor(c color.NRGBA) {
theme.Set("content", fmt.Sprintf("#%06X", []uint8{rgba.R, rgba.G, rgba.B}))
}
-func osMain() {
- select {}
-}
-
func translateKey(k string) (key.Name, bool) {
var n key.Name
M app/os_macos.go => app/os_macos.go +0 -9
@@ 1012,15 1012,6 @@ func (w *window) init() error {
return nil
}
-func osMain() {
- C.gio_initApp()
- close(launched)
- for {
- C.dispatchEvent()
- gio_dispatchMainFuncs()
- }
-}
-
func convertKey(k rune) (key.Name, bool) {
var n key.Name
switch k {
M app/os_unix.go => app/os_unix.go +0 -4
@@ 33,10 33,6 @@ type WaylandViewEvent struct {
func (WaylandViewEvent) implementsViewEvent() {}
func (WaylandViewEvent) ImplementsEvent() {}
-func osMain() {
- select {}
-}
-
type windowDriver func(*callbacks, []Option) error
// Instead of creating files with build tags for each combination of wayland +/- x11
M app/os_windows.go => app/os_windows.go +0 -4
@@ 85,10 85,6 @@ var resources struct {
cursor syscall.Handle
}
-func osMain() {
- select {}
-}
-
func newWindow(win *callbacks, options []Option) {
done := make(chan struct{})
go func() {
M app/runmain.go => app/runmain.go +1 -1
@@ 25,6 25,6 @@ func runMain() {
// Indirect call, since the linker does not know the address of main when
// laying down this package.
fn := mainMain
- fn()
+ go fn()
})
}
M app/window.go => app/window.go +7 -0
@@ 684,6 684,13 @@ func (w *Window) processEvent(e event.Event) bool {
// Event blocks until an event is received from the window, such as
// [FrameEvent], or until [Invalidate] is called.
+//
+// Note: if more than one Window is active, at least one must have
+// its Event called from the main goroutine that runs the main
+// function. This is necessary because some operating system GUI
+// implementations require control of the main thread.
+// For this reason, it is allowed to call Event even after a
+// DestroyEvent has been received.
func (w *Window) Event() event.Event {
w.init()
return w.basic.Event()