Open josharian opened 8 years ago
Yeah, your Go code is fine, and shiny is designed to handle multiple windows, but I'm not sure if the gldriver actually implements that yet or if it's just a TODO. There's certainly a TODO about it for the X11 flavor of gldriver (not to be mistaken for x11driver), and I wouldn't be surprised if some work remains on the Cocoa flavor. It's been a long time since I did any Obj-C / Cocoa programming, though, so I'm not exactly sure what needs doing, and what subtleties there are around trying to use multiple windows (and multiple OpenGL contexts). @crawshaw knows this better than I do, but I can't speak for when he will have any time to look at this.
On gldriver/cocoa at least, the problem is much simpler:
func main() {
driver.Main(func(s screen.Screen) {
w, err := s.NewWindow(nil)
if err != nil {
log.Fatal(err)
}
_ = w
select{}
})
}
In this code, the window never appears and the main draw loop isn't running. Cocoa is waiting for something, and I'm not sure what. In particular, doShowWindow is called and returns, but the async event it sends to the main cocoa thread is never run.
I'll try to poke at this a bit more between meetings today.
OK, it's getting stuck in - (void)drawRect
.
Approximately: Cocoa wants the first frame to be drawn before displaying the window, which means the main thread is blocked until w.Publish() is called on the new window.
So a quick workaround is to start the event loop for the first window before opening the second:
package main
import (
"log"
"golang.org/x/exp/shiny/driver"
"golang.org/x/exp/shiny/screen"
"golang.org/x/mobile/event/paint"
)
func main() {
driver.Main(func(s screen.Screen) {
openWindow(s, "window 1")
openWindow(s, "window 2")
select {}
})
}
func openWindow(s screen.Screen, name string) {
w, err := s.NewWindow(nil)
if err != nil {
log.Fatal(err)
}
go func() {
for {
e := w.NextEvent()
log.Printf("%s: %#+v", name, e)
switch e.(type) {
case paint.Event:
w.Publish()
}
}
}()
}
Thanks, @crawshaw! That works. Unfortunately, I'm getting glitchy output (intermittent blinking black window content) when doing that. Maybe Publish
or some of the other drawing functionality isn't quite concurrency-safe yet.
For the moment, I'll just write some simple/throwaway layout code and use a single window.
I am attempting to create multiple windows, to avoid having to write any layout or windowing code myself.
This hangs at the second call to
NewWindow
. Backtrace:The interesting goroutine is goroutine 19, which is blocked in the cgo
doNewWindow
call, atdispatch_sync(dispatch_get_main_queue(), ...
. I've confirmed that at the time of the call, the current thread and the main thread are different. So either (a) the main thread is blocked somewhere else, (b) the main thread's run loop is stopped, or (c) the main thread's run loop is in the wrong mode.Workaround suggestions would be very welcome, no matter how hacky.
/cc @nigeltao @crawshaw