1// Copyright 2015 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5//go:generate stringer -type=Code
6
7// Package key defines an event for physical keyboard keys.
8//
9// On-screen software keyboards do not send key events.
10//
11// See the golang.org/x/mobile/app package for details on the event model.
12package key
13
14import (
15	"fmt"
16	"strings"
17)
18
19// Event is a key event.
20type Event struct {
21	// Rune is the meaning of the key event as determined by the
22	// operating system. The mapping is determined by system-dependent
23	// current layout, modifiers, lock-states, etc.
24	//
25	// If non-negative, it is a Unicode codepoint: pressing the 'a' key
26	// generates different Runes 'a' or 'A' (but the same Code) depending on
27	// the state of the shift key.
28	//
29	// If -1, the key does not generate a Unicode codepoint. To distinguish
30	// them, look at Code.
31	Rune rune
32
33	// Code is the identity of the physical key relative to a notional
34	// "standard" keyboard, independent of current layout, modifiers,
35	// lock-states, etc
36	//
37	// For standard key codes, its value matches USB HID key codes.
38	// Compare its value to uint32-typed constants in this package, such
39	// as CodeLeftShift and CodeEscape.
40	//
41	// Pressing the regular '2' key and number-pad '2' key (with Num-Lock)
42	// generate different Codes (but the same Rune).
43	Code Code
44
45	// Modifiers is a bitmask representing a set of modifier keys: ModShift,
46	// ModAlt, etc.
47	Modifiers Modifiers
48
49	// Direction is the direction of the key event: DirPress, DirRelease,
50	// or DirNone (for key repeats).
51	Direction Direction
52
53	// TODO: add a Device ID, for multiple input devices?
54	// TODO: add a time.Time?
55}
56
57func (e Event) String() string {
58	if e.Rune >= 0 {
59		return fmt.Sprintf("key.Event{%q (%v), %v, %v}", e.Rune, e.Code, e.Modifiers, e.Direction)
60	}
61	return fmt.Sprintf("key.Event{(%v), %v, %v}", e.Code, e.Modifiers, e.Direction)
62}
63
64// Direction is the direction of the key event.
65type Direction uint8
66
67const (
68	DirNone    Direction = 0
69	DirPress   Direction = 1
70	DirRelease Direction = 2
71)
72
73// Modifiers is a bitmask representing a set of modifier keys.
74type Modifiers uint32
75
76const (
77	ModShift   Modifiers = 1 << 0
78	ModControl Modifiers = 1 << 1
79	ModAlt     Modifiers = 1 << 2
80	ModMeta    Modifiers = 1 << 3 // called "Command" on OS X
81)
82
83// Code is the identity of a key relative to a notional "standard" keyboard.
84type Code uint32
85
86// Physical key codes.
87//
88// For standard key codes, its value matches USB HID key codes.
89// TODO: add missing codes.
90const (
91	CodeUnknown Code = 0
92
93	CodeA Code = 4
94	CodeB Code = 5
95	CodeC Code = 6
96	CodeD Code = 7
97	CodeE Code = 8
98	CodeF Code = 9
99	CodeG Code = 10
100	CodeH Code = 11
101	CodeI Code = 12
102	CodeJ Code = 13
103	CodeK Code = 14
104	CodeL Code = 15
105	CodeM Code = 16
106	CodeN Code = 17
107	CodeO Code = 18
108	CodeP Code = 19
109	CodeQ Code = 20
110	CodeR Code = 21
111	CodeS Code = 22
112	CodeT Code = 23
113	CodeU Code = 24
114	CodeV Code = 25
115	CodeW Code = 26
116	CodeX Code = 27
117	CodeY Code = 28
118	CodeZ Code = 29
119
120	Code1 Code = 30
121	Code2 Code = 31
122	Code3 Code = 32
123	Code4 Code = 33
124	Code5 Code = 34
125	Code6 Code = 35
126	Code7 Code = 36
127	Code8 Code = 37
128	Code9 Code = 38
129	Code0 Code = 39
130
131	CodeReturnEnter        Code = 40
132	CodeEscape             Code = 41
133	CodeDeleteBackspace    Code = 42
134	CodeTab                Code = 43
135	CodeSpacebar           Code = 44
136	CodeHyphenMinus        Code = 45 // -
137	CodeEqualSign          Code = 46 // =
138	CodeLeftSquareBracket  Code = 47 // [
139	CodeRightSquareBracket Code = 48 // ]
140	CodeBackslash          Code = 49 // \
141	CodeSemicolon          Code = 51 // ;
142	CodeApostrophe         Code = 52 // '
143	CodeGraveAccent        Code = 53 // `
144	CodeComma              Code = 54 // ,
145	CodeFullStop           Code = 55 // .
146	CodeSlash              Code = 56 // /
147	CodeCapsLock           Code = 57
148
149	CodeF1  Code = 58
150	CodeF2  Code = 59
151	CodeF3  Code = 60
152	CodeF4  Code = 61
153	CodeF5  Code = 62
154	CodeF6  Code = 63
155	CodeF7  Code = 64
156	CodeF8  Code = 65
157	CodeF9  Code = 66
158	CodeF10 Code = 67
159	CodeF11 Code = 68
160	CodeF12 Code = 69
161
162	CodePause         Code = 72
163	CodeInsert        Code = 73
164	CodeHome          Code = 74
165	CodePageUp        Code = 75
166	CodeDeleteForward Code = 76
167	CodeEnd           Code = 77
168	CodePageDown      Code = 78
169
170	CodeRightArrow Code = 79
171	CodeLeftArrow  Code = 80
172	CodeDownArrow  Code = 81
173	CodeUpArrow    Code = 82
174
175	CodeKeypadNumLock     Code = 83
176	CodeKeypadSlash       Code = 84 // /
177	CodeKeypadAsterisk    Code = 85 // *
178	CodeKeypadHyphenMinus Code = 86 // -
179	CodeKeypadPlusSign    Code = 87 // +
180	CodeKeypadEnter       Code = 88
181	CodeKeypad1           Code = 89
182	CodeKeypad2           Code = 90
183	CodeKeypad3           Code = 91
184	CodeKeypad4           Code = 92
185	CodeKeypad5           Code = 93
186	CodeKeypad6           Code = 94
187	CodeKeypad7           Code = 95
188	CodeKeypad8           Code = 96
189	CodeKeypad9           Code = 97
190	CodeKeypad0           Code = 98
191	CodeKeypadFullStop    Code = 99  // .
192	CodeKeypadEqualSign   Code = 103 // =
193
194	CodeF13 Code = 104
195	CodeF14 Code = 105
196	CodeF15 Code = 106
197	CodeF16 Code = 107
198	CodeF17 Code = 108
199	CodeF18 Code = 109
200	CodeF19 Code = 110
201	CodeF20 Code = 111
202	CodeF21 Code = 112
203	CodeF22 Code = 113
204	CodeF23 Code = 114
205	CodeF24 Code = 115
206
207	CodeHelp Code = 117
208
209	CodeMute       Code = 127
210	CodeVolumeUp   Code = 128
211	CodeVolumeDown Code = 129
212
213	CodeLeftControl  Code = 224
214	CodeLeftShift    Code = 225
215	CodeLeftAlt      Code = 226
216	CodeLeftGUI      Code = 227
217	CodeRightControl Code = 228
218	CodeRightShift   Code = 229
219	CodeRightAlt     Code = 230
220	CodeRightGUI     Code = 231
221
222	// The following codes are not part of the standard USB HID Usage IDs for
223	// keyboards. See http://www.usb.org/developers/hidpage/Hut1_12v2.pdf
224	//
225	// Usage IDs are uint16s, so these non-standard values start at 0x10000.
226
227	// CodeCompose is the Code for a compose key, sometimes called a multi key,
228	// used to input non-ASCII characters such as ñ being composed of n and ~.
229	//
230	// See https://en.wikipedia.org/wiki/Compose_key
231	CodeCompose Code = 0x10000
232)
233
234// TODO: Given we use runes outside the unicode space, should we provide a
235// printing function? Related: it's a little unfortunate that printing a
236// key.Event with %v gives not very readable output like:
237//	{100 7 key.Modifiers() Press}
238
239var mods = [...]struct {
240	m Modifiers
241	s string
242}{
243	{ModShift, "Shift"},
244	{ModControl, "Control"},
245	{ModAlt, "Alt"},
246	{ModMeta, "Meta"},
247}
248
249func (m Modifiers) String() string {
250	var match []string
251	for _, mod := range mods {
252		if mod.m&m != 0 {
253			match = append(match, mod.s)
254		}
255	}
256	return "key.Modifiers(" + strings.Join(match, "|") + ")"
257}
258
259func (d Direction) String() string {
260	switch d {
261	case DirNone:
262		return "None"
263	case DirPress:
264		return "Press"
265	case DirRelease:
266		return "Release"
267	default:
268		return fmt.Sprintf("key.Direction(%d)", d)
269	}
270}
271