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
diff --git a/src/pkg/exp/draw/event.go b/src/pkg/exp/draw/event.go
index 29cdb5f..05237c2 100644
--- a/src/pkg/exp/draw/event.go
+++ b/src/pkg/exp/draw/event.go
@@ -16,35 +16,33 @@
 	// 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 7436e19..fd51aa2 100644
--- a/src/pkg/exp/draw/x11/conn.go
+++ b/src/pkg/exp/draw/x11/conn.go
@@ -45,11 +45,8 @@
 	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 @@
 	_ = 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 @@
 			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 @@
 				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 @@
 	}
 
 	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()