From c849b23ce9f8c72dd14392ad7b4d2bf7a97622ee Mon Sep 17 00:00:00 2001 From: Nigel Tao Date: Mon, 6 Sep 2010 19:22:49 +1000 Subject: [PATCH] exp/draw: unify a draw.Context's keyboard, mouse, etc. channels into a single event channel. A quit event is now represented by closing that channel. R=r, rsc, nigeltao CC=golang-dev https://golang.org/cl/2114042 --- src/pkg/exp/draw/event.go | 50 +++++++++++++++++------------------- src/pkg/exp/draw/x11/conn.go | 31 +++++++--------------- 2 files changed, 33 insertions(+), 48 deletions(-) diff --git a/src/pkg/exp/draw/event.go b/src/pkg/exp/draw/event.go index 29cdb5f2faa..05237c21780 100644 --- a/src/pkg/exp/draw/event.go +++ b/src/pkg/exp/draw/event.go @@ -16,35 +16,33 @@ type Context interface { // FlushImage flushes changes made to Screen() back to screen. FlushImage() - // KeyboardChan returns a channel carrying keystrokes. - // An event is sent each time a key is pressed or released. + // EventChan returns a channel carrying UI events such as key presses, + // mouse movements and window resizes. + EventChan() <-chan interface{} +} + +// A KeyEvent is sent for a key press or release. +type KeyEvent struct { // The value k represents key k being pressed. // The value -k represents key k being released. // The specific set of key values is not specified, - // but ordinary character represent themselves. - KeyboardChan() <-chan int - - // MouseChan returns a channel carrying mouse events. - // A new event is sent each time the mouse moves or a - // button is pressed or released. - MouseChan() <-chan Mouse - - // ResizeChan returns a channel carrying resize events. - // An event is sent each time the window is resized; - // the client should respond by calling Screen() to obtain - // the new screen image. - // The value sent on the channel is always ``true'' and can be ignored. - ResizeChan() <-chan bool - - // QuitChan returns a channel carrying quit requests. - // After reading a value from the quit channel, the application - // should exit. - QuitChan() <-chan bool + // but ordinary characters represent themselves. + Key int } -// A Mouse represents the state of the mouse. -type Mouse struct { - Buttons int // bit mask of buttons: 1<<0 is left, 1<<1 middle, 1<<2 right - image.Point // location of cursor - Nsec int64 // time stamp +// A MouseEvent is sent for a button press or release or for a mouse movement. +type MouseEvent struct { + // Buttons is a bit mask of buttons: 1<<0 is left, 1<<1 middle, 1<<2 right. + // It represents button state and not necessarily the state delta: bit 0 + // being on means that the left mouse button is down, but does not imply + // that the same button was up in the previous MouseEvent. + Buttons int + // Loc is the location of the cursor. + Loc image.Point +} + +// A ConfigEvent is sent each time the window's color model or size changes. +// The client should respond by calling Context.Screen to obtain a new image. +type ConfigEvent struct { + Config image.Config } diff --git a/src/pkg/exp/draw/x11/conn.go b/src/pkg/exp/draw/x11/conn.go index 7436e19d5ed..fd51aa2b8be 100644 --- a/src/pkg/exp/draw/x11/conn.go +++ b/src/pkg/exp/draw/x11/conn.go @@ -45,11 +45,8 @@ type conn struct { gc, window, root, visual resID img *image.RGBA - kbd chan int - mouse chan draw.Mouse - resize chan bool - quit chan bool - mouseState draw.Mouse + eventc chan interface{} + mouseState draw.MouseEvent buf [256]byte // General purpose scratch buffer. @@ -134,13 +131,7 @@ func (c *conn) FlushImage() { _ = c.flush <- false } -func (c *conn) KeyboardChan() <-chan int { return c.kbd } - -func (c *conn) MouseChan() <-chan draw.Mouse { return c.mouse } - -func (c *conn) ResizeChan() <-chan bool { return c.resize } - -func (c *conn) QuitChan() <-chan bool { return c.quit } +func (c *conn) EventChan() <-chan interface{} { return c.eventc } // pumper runs in its own goroutine, reading X events and demuxing them over the kbd / mouse / resize / quit chans. func (c *conn) pumper() { @@ -209,7 +200,7 @@ func (c *conn) pumper() { if c.buf[0] == 0x03 { keysym = -keysym } - c.kbd <- keysym + c.eventc <- draw.KeyEvent{keysym} case 0x04, 0x05: // Button press, button release. mask := 1 << (c.buf[1] - 1) if c.buf[0] == 0x04 { @@ -218,12 +209,12 @@ func (c *conn) pumper() { c.mouseState.Buttons &^= mask } // TODO(nigeltao): update mouseState's timestamp. - c.mouse <- c.mouseState + c.eventc <- c.mouseState case 0x06: // Motion notify. - c.mouseState.Point.X = int(c.buf[25])<<8 | int(c.buf[24]) - c.mouseState.Point.Y = int(c.buf[27])<<8 | int(c.buf[26]) + c.mouseState.Loc.X = int(c.buf[25])<<8 | int(c.buf[24]) + c.mouseState.Loc.Y = int(c.buf[27])<<8 | int(c.buf[26]) // TODO(nigeltao): update mouseState's timestamp. - c.mouse <- c.mouseState + c.eventc <- c.mouseState case 0x0c: // Expose. // A single user action could trigger multiple expose events (e.g. if moving another // window with XShape'd rounded corners over our window). In that case, the X server @@ -619,11 +610,7 @@ func NewWindowDisplay(display string) (draw.Context, os.Error) { } c.img = image.NewRGBA(windowWidth, windowHeight) - // TODO(nigeltao): Should these channels be buffered? - c.kbd = make(chan int) - c.mouse = make(chan draw.Mouse) - c.resize = make(chan bool) - c.quit = make(chan bool) + c.eventc = make(chan interface{}) c.flush = make(chan bool, 1) go c.flusher() go c.pumper()