exp/draw/x11 KeyboardChan not working on MacOSX 10.5.8

13 views
Skip to first unread message

sreguera

unread,
Aug 21, 2010, 9:19:27 PM8/21/10
to golang-nuts
Does this program work for anyone else in MacOSX 10.5.8?

package main

import (
"exp/draw/x11"
)

func main() {
context, _ := x11.NewWindow()
<-context.KeyboardChan()
}

The expected result is that the program terminates when any key is
pressed, but in my computer nothing happens. If I use MouseChan
instead of KeyboardChan the program ends as soon as I move or click
the mouse.

QuitChan and ResizeChan don't work either, so maybe I'm
misunderstanding the API or have a problem with the X11 server?

BTW, the go release I'm using is 07d3a97302be release/release.
2010-08-11

Nigel Tao

unread,
Aug 22, 2010, 1:17:12 AM8/22/10
to sreguera, golang-nuts
On 22 August 2010 07:19, sreguera <sreg...@gmail.com> wrote:
> Does this program work for anyone else in MacOSX 10.5.8?
>
> package main
>
> import (
>        "exp/draw/x11"
> )
>
> func main() {
>        context, _ := x11.NewWindow()
>        <-context.KeyboardChan()
> }
>
> The expected result is that the program terminates when any key is
> pressed, but in my computer nothing happens. If I use MouseChan
> instead of KeyboardChan the program ends as soon as I move or click
> the mouse.
>
> QuitChan and ResizeChan don't work either, so maybe I'm
> misunderstanding the API or have a problem with the X11 server?

I suspect that your X11 window is trying to first send the main
goroutine a mouse event (e.g. if you click to focus) followed by a key
event. Because you're not reading context.MouseChan(), the key event
is forever waiting second in line, but you never read the mouse event
that would move the key event to the front. Try the code example below
instead.

I've been thinking about replacing the draw.Context's multiple
channels (KeyboardChan, MouseChan, ResizeChan, QuitChan) with a single
EventChan for exactly this reason. It would also allow adding new
event types in the future (e.g. accelerometer, voice input) without
requiring older code to add explicit select cases to avoid blocking
like this.

An alternative API design would be for a Context to not send mouse
events unless ctx.MouseChan() had been called at least once, but I
think the single input channel is nicer.

Another alternative is for the x11 Context implementation to decouple
its events so that a blocked mousechan doesn't hold up the
keyboardchan, but again I think the single input channel is nicer.

This is still all hand-wavy, though. I haven't tried implementing it yet.

----------------
package main

import (
"exp/draw/x11"
)

func main() {
c, err := x11.NewWindow()
if err != nil {
println("err:", err.String())
}
loop:
for {
println("waiting...")
select {
case k := <-c.KeyboardChan():
println("key:", k)
break loop
case <-c.MouseChan():
case <-c.ResizeChan():
case <-c.QuitChan():
}
}
println("done")
}
----------------

sreguera

unread,
Aug 22, 2010, 6:47:15 AM8/22/10
to golang-nuts
That did work, thanks!

Looking back, my problem was that, first, I was assuming that the API
worked as in your alternative proposals 2 and 3, and second, when I
tried to write something similar to your code I was thinking in C and
assumed that the break w/o label would take me out of the for loop.

I agree that your first proposal, a single event queue, would be the
best solution.
Reply all
Reply to author
Forward
0 new messages