1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
|
package gui
import (
"fmt"
"image"
)
// Event is something that can happen in an environment.
//
// This package defines only one kind of event: Resize. Other packages implementing environments
// may implement more kinds of events. For example, the win package implements all kinds of
// events for mouse and keyboard.
type Event interface {
String() string
}
// Resize is an event that happens when the environment changes the size of its drawing area.
type Resize struct {
image.Rectangle
}
func (r Resize) String() string {
return fmt.Sprintf("resize/%d/%d/%d/%d", r.Min.X, r.Min.Y, r.Max.X, r.Max.Y)
}
// makeEventsChan implements a channel of events with an unlimited capacity. It does so
// by creating a goroutine that queues incoming events. Sending to this channel never blocks
// and no events get lost.
//
// The unlimited capacity channel is very suitable for delivering events because the consumer
// may be unavailable for some time (doing a heavy computation), but will get to the events
// later.
//
// An unlimited capacity channel has its dangers in general, but is completely fine for
// the purpose of delivering events. This is because the production of events is fairly
// infrequent and should never out-run their consumption in the long term.
func makeEventsChan() (<-chan Event, chan<- Event) {
out, in := make(chan Event), make(chan Event)
go func() {
var queue []Event
for {
x, ok := <-in
if !ok {
close(out)
return
}
queue = append(queue, x)
for len(queue) > 0 {
select {
case out <- queue[0]:
queue = queue[1:]
case x, ok := <-in:
if !ok {
for _, x := range queue {
out <- x
}
close(out)
return
}
queue = append(queue, x)
}
}
}
}()
return out, in
}
// Button indicates a mouse button in an event.
type Button string
// List of all mouse buttons.
const (
ButtonLeft Button = "left"
ButtonRight Button = "right"
ButtonMiddle Button = "middle"
)
// Key indicates a keyboard key in an event.
type Key string
// List of all keyboard keys.
const (
KeyLeft Key = "left"
KeyRight Key = "right"
KeyUp Key = "up"
KeyDown Key = "down"
KeyEscape Key = "escape"
KeySpace Key = "space"
KeyBackspace Key = "backspace"
KeyDelete Key = "delete"
KeyEnter Key = "enter"
KeyTab Key = "tab"
KeyHome Key = "home"
KeyEnd Key = "end"
KeyPageUp Key = "pageup"
KeyPageDown Key = "pagedown"
KeyShift Key = "shift"
KeyCtrl Key = "ctrl"
KeyAlt Key = "alt"
)
type (
// WiClose is an event that happens when the user presses the close button on the window.
WiClose struct{}
// MoMove is an event that happens when the mouse gets moved across the window.
MoMove struct{ image.Point }
// MoDown is an event that happens when a mouse button gets pressed.
MoDown struct {
image.Point
Button Button
}
// MoUp is an event that happens when a mouse button gets released.
MoUp struct {
image.Point
Button Button
}
// MoScroll is an event that happens on scrolling the mouse.
//
// The Point field tells the amount scrolled in each direction.
MoScroll struct{ image.Point }
// KbType is an event that happens when a Unicode character gets typed on the keyboard.
KbType struct{ Rune rune }
// KbDown is an event that happens when a key on the keyboard gets pressed.
KbDown struct{ Key Key }
// KbUp is an event that happens when a key on the keyboard gets released.
KbUp struct{ Key Key }
// KbRepeat is an event that happens when a key on the keyboard gets repeated.
//
// This happens when its held down for some time.
KbRepeat struct{ Key Key }
)
func (wc WiClose) String() string { return "wi/close" }
func (mm MoMove) String() string { return fmt.Sprintf("mo/move/%d/%d", mm.X, mm.Y) }
func (md MoDown) String() string { return fmt.Sprintf("mo/down/%d/%d/%s", md.X, md.Y, md.Button) }
func (mu MoUp) String() string { return fmt.Sprintf("mo/up/%d/%d/%s", mu.X, mu.Y, mu.Button) }
func (ms MoScroll) String() string { return fmt.Sprintf("mo/scroll/%d/%d", ms.X, ms.Y) }
func (kt KbType) String() string { return fmt.Sprintf("kb/type/%d", kt.Rune) }
func (kd KbDown) String() string { return fmt.Sprintf("kb/down/%s", kd.Key) }
func (ku KbUp) String() string { return fmt.Sprintf("kb/up/%s", ku.Key) }
func (kr KbRepeat) String() string { return fmt.Sprintf("kb/repeat/%s", kr.Key) }
|