ndless/bindings/
input.rs

1//! Getting input from th keypad and touchpad
2//!
3//! This contains functionality to get keys pressed, as well as touchpad information.
4
5use crate::alloc::borrow::Borrow;
6use crate::bindings::input::raw_keys::*;
7use crate::prelude::*;
8
9/// Keys available in the Nspire keypad, including the touchpad.
10#[derive(Eq, PartialEq, Debug, Clone, Copy, Hash)]
11#[non_exhaustive]
12pub enum Key {
13	Key0,
14	Key1,
15	Key2,
16	Key3,
17	Key4,
18	Key5,
19	Key6,
20	Key7,
21	Key8,
22	Key9,
23	A,
24	B,
25	C,
26	D,
27	E,
28	F,
29	G,
30	H,
31	I,
32	J,
33	K,
34	L,
35	M,
36	N,
37	O,
38	P,
39	Q,
40	R,
41	S,
42	T,
43	U,
44	V,
45	W,
46	X,
47	Y,
48	Z,
49	Up,
50	UpRight,
51	Right,
52	RightDown,
53	Down,
54	DownLeft,
55	Left,
56	LeftUp,
57	Click,
58	Catalog,
59	Comma,
60	Ctrl,
61	Del,
62	Divide,
63	Doc,
64	EE,
65	Enter,
66	Equals,
67	Esc,
68	Exponent,
69	Flag,
70	/// To the left of the catalog key
71	Template,
72	/// Also known as "Home"
73	On,
74	LeftParenthesis,
75	Menu,
76	Minus,
77	Multiply,
78	/// To the right of the period, left of enter
79	Negative,
80	Period,
81	/// Under the EE, above the comma, to the left of the H
82	Pi,
83	Plus,
84	/// Above the flag, to the right of the G. It has a question mark, exclamation mark, and
85	/// a rightwards arrow.
86	QuestionExclamation,
87	Return,
88	RightParenthesis,
89	/// The calculator icon, under escape. Shown as *pad* in firebird-emu.
90	Scratchpad,
91	Shift,
92	Space,
93	/// x²
94	Squared,
95	Tab,
96	/// 10ˣ
97	TenExp,
98	Trig,
99	Var,
100	/// eˣ
101	EExp,
102
103	/// Not available on TI-Nspire CX
104	Apostrophe,
105	/// Not available on TI-Nspire CX
106	Bar,
107	/// Not available on TI-Nspire CX
108	Colon,
109	/// Not available on TI-Nspire CX
110	Cos,
111	/// Not available on TI-Nspire CX
112	GreaterThan,
113	/// Not available on TI-Nspire CX
114	II,
115	/// Not available on TI-Nspire CX
116	LessThan,
117	/// Not available on TI-Nspire CX
118	Question,
119	/// Not available on TI-Nspire CX
120	Quote,
121	/// Not available on TI-Nspire CX
122	Sin,
123	/// Not available on TI-Nspire CX
124	Tan,
125	/// Not available on TI-Nspire CX
126	Theta,
127}
128
129impl Key {
130	fn from_arrow(arrow: u8) -> Option<Self> {
131		match u32::from(arrow) {
132			ndless_sys::tpad_arrow_TPAD_ARROW_CLICK => Some(Key::Click),
133			ndless_sys::tpad_arrow_TPAD_ARROW_UP => Some(Key::Up),
134			ndless_sys::tpad_arrow_TPAD_ARROW_UPRIGHT => Some(Key::UpRight),
135			ndless_sys::tpad_arrow_TPAD_ARROW_RIGHT => Some(Key::Right),
136			ndless_sys::tpad_arrow_TPAD_ARROW_RIGHTDOWN => Some(Key::RightDown),
137			ndless_sys::tpad_arrow_TPAD_ARROW_DOWN => Some(Key::Down),
138			ndless_sys::tpad_arrow_TPAD_ARROW_DOWNLEFT => Some(Key::DownLeft),
139			ndless_sys::tpad_arrow_TPAD_ARROW_LEFT => Some(Key::Left),
140			ndless_sys::tpad_arrow_TPAD_ARROW_LEFTUP => Some(Key::LeftUp),
141			_ => None,
142		}
143	}
144}
145
146mod raw_keys {
147	#![allow(non_camel_case_types)]
148	#![allow(non_upper_case_globals)]
149
150	const fn key(row: i32, col: i32) -> ndless_sys::t_key {
151		ndless_sys::t_key {
152			row,
153			col,
154			tpad_row: row,
155			tpad_col: col,
156			tpad_arrow: 0,
157		}
158	}
159
160	const fn key_t_pad(row: i32, col: i32, tpad_row: i32, tpad_col: i32) -> ndless_sys::t_key {
161		ndless_sys::t_key {
162			row,
163			col,
164			tpad_row,
165			tpad_col,
166			tpad_arrow: 0,
167		}
168	}
169
170	const fn key_t_pad_arrow(
171		row: i32,
172		col: i32,
173		tpad_arrow: ndless_sys::tpad_arrow,
174	) -> ndless_sys::t_key {
175		ndless_sys::t_key {
176			row,
177			col,
178			tpad_row: row,
179			tpad_col: col,
180			tpad_arrow,
181		}
182	}
183
184	pub const _KEY_DUMMY_ROW: i32 = 0x1C;
185	pub const _KEY_DUMMY_COL: i32 = 0x400;
186	pub const KEY_NSPIRE_RET: ndless_sys::t_key = key(0x10, 0x001);
187	pub const KEY_NSPIRE_ENTER: ndless_sys::t_key = key(0x10, 0x002);
188	pub const KEY_NSPIRE_SPACE: ndless_sys::t_key = key_t_pad(0x10, 0x004, 0x10, 0x10);
189	pub const KEY_NSPIRE_NEGATIVE: ndless_sys::t_key = key(0x10, 0x008);
190	pub const KEY_NSPIRE_Z: ndless_sys::t_key = key_t_pad(0x10, 0x010, 0x10, 0x20);
191	pub const KEY_NSPIRE_PERIOD: ndless_sys::t_key = key_t_pad(0x10, 0x20, 0x1A, 0x010);
192	pub const KEY_NSPIRE_Y: ndless_sys::t_key = key(0x10, 0x040);
193	pub const KEY_NSPIRE_0: ndless_sys::t_key = key(0x10, 0x080);
194	pub const KEY_NSPIRE_X: ndless_sys::t_key = key_t_pad(0x10, 0x100, 0x12, 0x001);
195	pub const KEY_NSPIRE_THETA: ndless_sys::t_key =
196		key_t_pad(0x10, 0x400, _KEY_DUMMY_ROW, _KEY_DUMMY_COL);
197	pub const KEY_NSPIRE_COMMA: ndless_sys::t_key = key_t_pad(0x12, 0x001, 0x1E, 0x400);
198	pub const KEY_NSPIRE_PLUS: ndless_sys::t_key = key_t_pad(0x12, 0x002, 0x1C, 0x004);
199	pub const KEY_NSPIRE_W: ndless_sys::t_key = key_t_pad(0x12, 0x004, 0x12, 0x002);
200	pub const KEY_NSPIRE_3: ndless_sys::t_key = key(0x12, 0x008);
201	pub const KEY_NSPIRE_V: ndless_sys::t_key = key_t_pad(0x12, 0x010, 0x12, 0x004);
202	pub const KEY_NSPIRE_2: ndless_sys::t_key = key_t_pad(0x12, 0x020, 0x1C, 0x010);
203	pub const KEY_NSPIRE_U: ndless_sys::t_key = key_t_pad(0x12, 0x040, 0x12, 0x010);
204	pub const KEY_NSPIRE_1: ndless_sys::t_key = key(0x12, 0x080);
205	pub const KEY_NSPIRE_T: ndless_sys::t_key = key_t_pad(0x12, 0x100, 0x12, 0x020);
206	pub const KEY_NSPIRE_eEXP: ndless_sys::t_key = key_t_pad(0x12, 0x200, 0x16, 0x200);
207	pub const KEY_NSPIRE_PI: ndless_sys::t_key = key_t_pad(0x12, 0x400, 0x12, 0x100);
208	pub const KEY_NSPIRE_QUES: ndless_sys::t_key =
209		key_t_pad(0x14, 0x001, _KEY_DUMMY_ROW, _KEY_DUMMY_COL);
210	pub const KEY_NSPIRE_QUESEXCL: ndless_sys::t_key =
211		key_t_pad(_KEY_DUMMY_ROW, _KEY_DUMMY_COL, 0x10, 0x100);
212	pub const KEY_NSPIRE_MINUS: ndless_sys::t_key = key_t_pad(0x14, 0x002, 0x1A, 0x004);
213	pub const KEY_NSPIRE_S: ndless_sys::t_key = key_t_pad(0x14, 0x004, 0x12, 0x040);
214	pub const KEY_NSPIRE_6: ndless_sys::t_key = key(0x14, 0x008);
215	pub const KEY_NSPIRE_R: ndless_sys::t_key = key_t_pad(0x14, 0x010, 0x14, 0x001);
216	pub const KEY_NSPIRE_5: ndless_sys::t_key = key_t_pad(0x14, 0x020, 0x1A, 0x040);
217	pub const KEY_NSPIRE_Q: ndless_sys::t_key = key_t_pad(0x14, 0x040, 0x14, 0x002);
218	pub const KEY_NSPIRE_4: ndless_sys::t_key = key(0x14, 0x080);
219	pub const KEY_NSPIRE_P: ndless_sys::t_key = key_t_pad(0x14, 0x100, 0x14, 0x004);
220	pub const KEY_NSPIRE_TENX: ndless_sys::t_key = key_t_pad(0x14, 0x200, 0x12, 0x400);
221	pub const KEY_NSPIRE_EE: ndless_sys::t_key = key_t_pad(0x14, 0x400, 0x14, 0x100);
222	pub const KEY_NSPIRE_COLON: ndless_sys::t_key =
223		key_t_pad(0x16, 0x001, _KEY_DUMMY_ROW, _KEY_DUMMY_COL);
224	pub const KEY_NSPIRE_MULTIPLY: ndless_sys::t_key = key_t_pad(0x16, 0x002, 0x18, 0x100);
225	pub const KEY_NSPIRE_O: ndless_sys::t_key = key_t_pad(0x16, 0x004, 0x14, 0x010);
226	pub const KEY_NSPIRE_9: ndless_sys::t_key = key(0x16, 0x008);
227	pub const KEY_NSPIRE_N: ndless_sys::t_key = key_t_pad(0x16, 0x010, 0x14, 0x020);
228	pub const KEY_NSPIRE_8: ndless_sys::t_key = key_t_pad(0x16, 0x020, 0x1C, 0x040);
229	pub const KEY_NSPIRE_M: ndless_sys::t_key = key_t_pad(0x16, 0x040, 0x14, 0x040);
230	pub const KEY_NSPIRE_7: ndless_sys::t_key = key(0x16, 0x080);
231	pub const KEY_NSPIRE_L: ndless_sys::t_key = key_t_pad(0x16, 0x100, 0x16, 0x001);
232	pub const KEY_NSPIRE_SQU: ndless_sys::t_key = key_t_pad(0x16, 0x200, 0x14, 0x200);
233	pub const KEY_NSPIRE_II: ndless_sys::t_key =
234		key_t_pad(0x16, 0x400, _KEY_DUMMY_ROW, _KEY_DUMMY_COL);
235	pub const KEY_NSPIRE_QUOTE: ndless_sys::t_key =
236		key_t_pad(0x18, 0x001, _KEY_DUMMY_ROW, _KEY_DUMMY_COL);
237	pub const KEY_NSPIRE_DIVIDE: ndless_sys::t_key = key_t_pad(0x18, 0x002, 0x16, 0x100);
238	pub const KEY_NSPIRE_K: ndless_sys::t_key = key_t_pad(0x18, 0x004, 0x16, 0x002);
239	pub const KEY_NSPIRE_TAN: ndless_sys::t_key = key(0x18, 0x008);
240	pub const KEY_NSPIRE_J: ndless_sys::t_key = key_t_pad(0x18, 0x010, 0x16, 0x004);
241	pub const KEY_NSPIRE_COS: ndless_sys::t_key =
242		key_t_pad(0x18, 0x020, _KEY_DUMMY_ROW, _KEY_DUMMY_COL);
243	pub const KEY_NSPIRE_I: ndless_sys::t_key = key_t_pad(0x18, 0x040, 0x16, 0x010);
244	pub const KEY_NSPIRE_SIN: ndless_sys::t_key =
245		key_t_pad(0x18, 0x080, _KEY_DUMMY_ROW, _KEY_DUMMY_COL);
246	pub const KEY_NSPIRE_H: ndless_sys::t_key = key_t_pad(0x18, 0x100, 0x16, 0x020);
247	pub const KEY_NSPIRE_EXP: ndless_sys::t_key = key_t_pad(0x18, 0x200, 0x18, 0x200);
248	pub const KEY_NSPIRE_GTHAN: ndless_sys::t_key =
249		key_t_pad(0x18, 0x400, _KEY_DUMMY_ROW, _KEY_DUMMY_COL);
250	pub const KEY_NSPIRE_APOSTROPHE: ndless_sys::t_key = key(0x1A, 0x001);
251	pub const KEY_NSPIRE_CAT: ndless_sys::t_key = key_t_pad(0x1A, 0x002, 0x1A, 0x080);
252	pub const KEY_NSPIRE_FRAC: ndless_sys::t_key =
253		key_t_pad(_KEY_DUMMY_ROW, _KEY_DUMMY_COL, 0x1A, 0x100);
254	pub const KEY_NSPIRE_G: ndless_sys::t_key = key_t_pad(0x1A, 0x004, 0x16, 0x040);
255	pub const KEY_NSPIRE_RP: ndless_sys::t_key = key_t_pad(0x1A, 0x008, 0x1A, 0x008);
256	pub const KEY_NSPIRE_F: ndless_sys::t_key = key_t_pad(0x1A, 0x010, 0x18, 0x001);
257	pub const KEY_NSPIRE_LP: ndless_sys::t_key = key_t_pad(0x1A, 0x020, 0x1A, 0x020);
258	pub const KEY_NSPIRE_E: ndless_sys::t_key = key_t_pad(0x1A, 0x040, 0x18, 0x002);
259	pub const KEY_NSPIRE_VAR: ndless_sys::t_key = key_t_pad(0x1A, 0x080, 0x1A, 0x002);
260	pub const KEY_NSPIRE_D: ndless_sys::t_key = key_t_pad(0x1A, 0x100, 0x18, 0x004);
261	pub const KEY_NSPIRE_DEL: ndless_sys::t_key = key_t_pad(0x1E, 0x100, 0x1A, 0x200);
262	pub const KEY_NSPIRE_LTHAN: ndless_sys::t_key =
263		key_t_pad(0x1A, 0x400, _KEY_DUMMY_ROW, _KEY_DUMMY_COL);
264	pub const KEY_NSPIRE_FLAG: ndless_sys::t_key = key(0x1C, 0x001);
265	pub const KEY_NSPIRE_CLICK: ndless_sys::t_key =
266		key_t_pad_arrow(0x1C, 0x002, ndless_sys::tpad_arrow_TPAD_ARROW_CLICK);
267	pub const KEY_NSPIRE_C: ndless_sys::t_key = key_t_pad(0x1C, 0x004, 0x18, 0x010);
268	pub const KEY_NSPIRE_HOME: ndless_sys::t_key = key_t_pad(0x1C, 0x008, 0x10, 0x200);
269	pub const KEY_NSPIRE_B: ndless_sys::t_key = key_t_pad(0x1C, 0x010, 0x18, 0x020);
270	pub const KEY_NSPIRE_MENU: ndless_sys::t_key = key(0x1C, 0x020);
271	pub const KEY_NSPIRE_A: ndless_sys::t_key = key_t_pad(0x1C, 0x040, 0x18, 0x040);
272	pub const KEY_NSPIRE_ESC: ndless_sys::t_key = key(0x1C, 0x080);
273	pub const KEY_NSPIRE_BAR: ndless_sys::t_key = key(0x1C, 0x100);
274	pub const KEY_NSPIRE_TAB: ndless_sys::t_key = key(0x1C, 0x200);
275	pub const KEY_NSPIRE_EQU: ndless_sys::t_key = key_t_pad(0x1E, 0x400, 0x18, 0x080);
276	pub const KEY_NSPIRE_UP: ndless_sys::t_key =
277		key_t_pad_arrow(0x1E, 0x001, ndless_sys::tpad_arrow_TPAD_ARROW_UP);
278	pub const KEY_NSPIRE_UPRIGHT: ndless_sys::t_key =
279		key_t_pad_arrow(0x1E, 0x002, ndless_sys::tpad_arrow_TPAD_ARROW_UPRIGHT);
280	pub const KEY_NSPIRE_RIGHT: ndless_sys::t_key =
281		key_t_pad_arrow(0x1E, 0x004, ndless_sys::tpad_arrow_TPAD_ARROW_RIGHT);
282	pub const KEY_NSPIRE_RIGHTDOWN: ndless_sys::t_key =
283		key_t_pad_arrow(0x1E, 0x008, ndless_sys::tpad_arrow_TPAD_ARROW_RIGHTDOWN);
284	pub const KEY_NSPIRE_DOWN: ndless_sys::t_key =
285		key_t_pad_arrow(0x1E, 0x010, ndless_sys::tpad_arrow_TPAD_ARROW_DOWN);
286	pub const KEY_NSPIRE_DOWNLEFT: ndless_sys::t_key =
287		key_t_pad_arrow(0x1E, 0x020, ndless_sys::tpad_arrow_TPAD_ARROW_DOWNLEFT);
288	pub const KEY_NSPIRE_LEFT: ndless_sys::t_key =
289		key_t_pad_arrow(0x1E, 0x040, ndless_sys::tpad_arrow_TPAD_ARROW_LEFT);
290	pub const KEY_NSPIRE_LEFTUP: ndless_sys::t_key =
291		key_t_pad_arrow(0x1E, 0x080, ndless_sys::tpad_arrow_TPAD_ARROW_LEFTUP);
292	pub const KEY_NSPIRE_SHIFT: ndless_sys::t_key = key_t_pad(0x1A, 0x200, 0x1E, 0x100);
293	pub const KEY_NSPIRE_CTRL: ndless_sys::t_key = key(0x1E, 0x200);
294	pub const KEY_NSPIRE_DOC: ndless_sys::t_key =
295		key_t_pad(_KEY_DUMMY_ROW, _KEY_DUMMY_COL, 0x1C, 0x008);
296	pub const KEY_NSPIRE_TRIG: ndless_sys::t_key =
297		key_t_pad(_KEY_DUMMY_ROW, _KEY_DUMMY_COL, 0x12, 0x200);
298	pub const KEY_NSPIRE_SCRATCHPAD: ndless_sys::t_key =
299		key_t_pad(_KEY_DUMMY_ROW, _KEY_DUMMY_COL, 0x1A, 0x400);
300}
301
302const KEY_MAPPING: &[(ndless_sys::t_key, Key)] = &[
303	(KEY_NSPIRE_0, Key::Key0),
304	(KEY_NSPIRE_1, Key::Key1),
305	(KEY_NSPIRE_2, Key::Key2),
306	(KEY_NSPIRE_3, Key::Key3),
307	(KEY_NSPIRE_4, Key::Key4),
308	(KEY_NSPIRE_5, Key::Key5),
309	(KEY_NSPIRE_6, Key::Key6),
310	(KEY_NSPIRE_7, Key::Key7),
311	(KEY_NSPIRE_8, Key::Key8),
312	(KEY_NSPIRE_9, Key::Key9),
313	(KEY_NSPIRE_A, Key::A),
314	(KEY_NSPIRE_APOSTROPHE, Key::Apostrophe),
315	(KEY_NSPIRE_B, Key::B),
316	(KEY_NSPIRE_BAR, Key::Bar),
317	(KEY_NSPIRE_C, Key::C),
318	(KEY_NSPIRE_CAT, Key::Catalog),
319	(KEY_NSPIRE_CLICK, Key::Click),
320	(KEY_NSPIRE_COLON, Key::Colon),
321	(KEY_NSPIRE_COMMA, Key::Comma),
322	(KEY_NSPIRE_COS, Key::Cos),
323	(KEY_NSPIRE_CTRL, Key::Ctrl),
324	(KEY_NSPIRE_D, Key::D),
325	(KEY_NSPIRE_DEL, Key::Del),
326	(KEY_NSPIRE_DIVIDE, Key::Divide),
327	(KEY_NSPIRE_DOC, Key::Doc),
328	(KEY_NSPIRE_DOWN, Key::Down),
329	(KEY_NSPIRE_DOWNLEFT, Key::DownLeft),
330	(KEY_NSPIRE_E, Key::E),
331	(KEY_NSPIRE_EE, Key::EE),
332	(KEY_NSPIRE_ENTER, Key::Enter),
333	(KEY_NSPIRE_EQU, Key::Equals),
334	(KEY_NSPIRE_ESC, Key::Esc),
335	(KEY_NSPIRE_EXP, Key::Exponent),
336	(KEY_NSPIRE_F, Key::F),
337	(KEY_NSPIRE_FLAG, Key::Flag),
338	(KEY_NSPIRE_FRAC, Key::Template),
339	(KEY_NSPIRE_G, Key::G),
340	(KEY_NSPIRE_GTHAN, Key::GreaterThan),
341	(KEY_NSPIRE_H, Key::H),
342	(KEY_NSPIRE_HOME, Key::On),
343	(KEY_NSPIRE_I, Key::I),
344	(KEY_NSPIRE_II, Key::II),
345	(KEY_NSPIRE_J, Key::J),
346	(KEY_NSPIRE_K, Key::K),
347	(KEY_NSPIRE_L, Key::L),
348	(KEY_NSPIRE_LEFT, Key::Left),
349	(KEY_NSPIRE_LEFTUP, Key::LeftUp),
350	(KEY_NSPIRE_LP, Key::LeftParenthesis),
351	(KEY_NSPIRE_LTHAN, Key::LessThan),
352	(KEY_NSPIRE_M, Key::M),
353	(KEY_NSPIRE_MENU, Key::Menu),
354	(KEY_NSPIRE_MINUS, Key::Minus),
355	(KEY_NSPIRE_MULTIPLY, Key::Multiply),
356	(KEY_NSPIRE_N, Key::N),
357	(KEY_NSPIRE_NEGATIVE, Key::Negative),
358	(KEY_NSPIRE_O, Key::O),
359	(KEY_NSPIRE_P, Key::P),
360	(KEY_NSPIRE_PERIOD, Key::Period),
361	(KEY_NSPIRE_PI, Key::Pi),
362	(KEY_NSPIRE_PLUS, Key::Plus),
363	(KEY_NSPIRE_Q, Key::Q),
364	(KEY_NSPIRE_QUES, Key::Question),
365	(KEY_NSPIRE_QUESEXCL, Key::QuestionExclamation),
366	(KEY_NSPIRE_QUOTE, Key::Quote),
367	(KEY_NSPIRE_R, Key::R),
368	(KEY_NSPIRE_RET, Key::Return),
369	(KEY_NSPIRE_RIGHT, Key::Right),
370	(KEY_NSPIRE_RIGHTDOWN, Key::RightDown),
371	(KEY_NSPIRE_RP, Key::RightParenthesis),
372	(KEY_NSPIRE_S, Key::S),
373	(KEY_NSPIRE_SCRATCHPAD, Key::Scratchpad),
374	(KEY_NSPIRE_SHIFT, Key::Shift),
375	(KEY_NSPIRE_SIN, Key::Sin),
376	(KEY_NSPIRE_SPACE, Key::Space),
377	(KEY_NSPIRE_SQU, Key::Squared),
378	(KEY_NSPIRE_T, Key::T),
379	(KEY_NSPIRE_TAB, Key::Tab),
380	(KEY_NSPIRE_TAN, Key::Tan),
381	(KEY_NSPIRE_TENX, Key::TenExp),
382	(KEY_NSPIRE_THETA, Key::Theta),
383	(KEY_NSPIRE_TRIG, Key::Trig),
384	(KEY_NSPIRE_U, Key::U),
385	(KEY_NSPIRE_UP, Key::Up),
386	(KEY_NSPIRE_UPRIGHT, Key::UpRight),
387	(KEY_NSPIRE_V, Key::V),
388	(KEY_NSPIRE_VAR, Key::Var),
389	(KEY_NSPIRE_W, Key::W),
390	(KEY_NSPIRE_X, Key::X),
391	(KEY_NSPIRE_Y, Key::Y),
392	(KEY_NSPIRE_Z, Key::Z),
393	(KEY_NSPIRE_eEXP, Key::EExp),
394];
395
396/// A more efficient way to get keys being pressed than [`get_keys`],
397/// as `iter_keys` does not allocate.
398///
399/// However, it must be used immediately, as each iteration of the
400/// loop checks if the key is being pressed at that time. For example:
401///
402///  ```
403///  use ndless::prelude::*;
404///  use ndless::input::iter_keys;
405///  for key in iter_keys() {
406///      println!("Key {:?} is being pressed.", key);
407///  }
408///  ```
409///
410///  Additionally, it may be used like any other [`Iterator`] in Rust:
411///
412///  ```
413///  // Print all keys except escape
414///  use ndless::prelude::*;
415///  use ndless::input::{iter_keys, Key};
416///  iter_keys()
417///      .filter(|key| key != Key::Esc)
418///      .for_each(|key| println!("Key {:?} is being pressed.", key));
419///  ```
420pub fn iter_keys() -> impl Iterator<Item = Key> + 'static {
421	KEY_MAPPING
422		.iter()
423		.filter(|(raw_key, _key)| unsafe { ndless_sys::isKeyPressed(raw_key) } == 1)
424		.map(|(_, key)| *key)
425}
426
427/// Returns a [`Vec`] of pressed keys.
428///
429/// # Example
430/// ```
431/// use ndless::input::{get_keys, Key};
432///
433/// let keys = get_keys();
434/// if keys.len() == 0 { /* No keys currently pressed */ }
435/// ```
436pub fn get_keys() -> Vec<Key> {
437	iter_keys().collect()
438}
439
440/// Returns true if the specific key is pressed.
441/// Note that you may pass either an owned [`Key`] or a borrowed [`&Key`][Key].
442pub fn is_key_pressed(key: impl Borrow<Key>) -> bool {
443	KEY_MAPPING
444		.iter()
445		.find(|(_, other)| other == key.borrow())
446		.map_or(
447			false,
448			|(raw_key, _key)| unsafe { ndless_sys::isKeyPressed(raw_key) } == 1,
449		)
450}
451
452/// Returns true if any buttons are currently pressed, including pushing the touchpad.
453pub fn any_key_pressed() -> bool {
454	unsafe { ndless_sys::any_key_pressed() > 0 }
455}
456
457/// Returns true if the "On" key is currently pressed.
458pub fn key_on_pressed() -> bool {
459	unsafe { ndless_sys::on_key_pressed() > 0 }
460}
461
462/// Suspends the program until [`any_key_pressed`] returns true.
463pub fn wait_key_pressed() {
464	unsafe { ndless_sys::wait_key_pressed() }
465}
466
467/// Suspends the program until [`any_key_pressed`]  returns false.
468pub fn wait_no_key_pressed() {
469	unsafe { ndless_sys::wait_no_key_pressed() }
470}
471
472pub mod touchpad {
473	pub use ndless_sys::touchpad_info_t as touchpad_info;
474	use ndless_sys::touchpad_report_t as touchpad_report;
475
476	use super::Key;
477
478	#[derive(Eq, PartialEq, Debug, Clone, Copy, Hash)]
479	pub struct TouchpadReport {
480		pub contact: bool,
481		pub proximity: u8,
482		pub x: u16,
483		pub y: u16,
484		pub x_vel: u8,
485		pub y_vel: u8,
486		pub pressed: bool,
487		pub arrow: Option<Key>,
488	}
489
490	impl From<touchpad_report> for TouchpadReport {
491		fn from(report: touchpad_report) -> Self {
492			Self {
493				contact: report.contact > 0, // A C bool is often represented as a char with a nonzero value
494				proximity: report.proximity,
495				x: report.x,
496				y: report.y,
497				x_vel: report.x_velocity,
498				y_vel: report.y_velocity,
499				pressed: report.contact > 0,
500				arrow: Key::from_arrow(report.arrow),
501			}
502		}
503	}
504
505	pub fn touchpad_scan() -> Result<TouchpadReport, i32> {
506		let mut report = touchpad_report {
507			contact: 0,
508			proximity: 0,
509			x: 0,
510			y: 0,
511			x_velocity: 0,
512			y_velocity: 0,
513			dummy: 0,
514			pressed: 0,
515			arrow: 0,
516		};
517		let status = unsafe { ndless_sys::touchpad_scan(&mut report) };
518		match status {
519			0 => Ok(report.into()),
520			x => Err(x),
521		}
522	}
523
524	pub fn get_touchpad_info() -> Result<touchpad_info, ()> {
525		match unsafe { ndless_sys::touchpad_getinfo().as_ref() } {
526			Some(ret) => Ok(*ret),
527			None => Err(()),
528		}
529	}
530}