ndless_sdl/
event.rs

1use core::mem;
2use core::slice;
3use core::str;
4
5use cstr_core::CStr;
6use cty::*;
7use ndless::prelude::*;
8use num::FromPrimitive;
9
10pub mod ll {
11	#![allow(non_camel_case_types)]
12
13	use core::mem;
14
15	use cty::{c_char as c_schar, c_int, c_uchar, c_uint, c_void, int16_t, uint16_t, uint8_t};
16
17	pub use crate::keysym::*;
18
19	pub type SDL_EventType = c_uint;
20	pub type SDLMod = c_uint;
21	pub type SDL_SysWMmsg = c_void;
22
23	pub const SDL_NOEVENT: SDL_EventType = 0;
24	pub const SDL_ACTIVEEVENT: SDL_EventType = 1;
25	pub const SDL_KEYDOWN: SDL_EventType = 2;
26	pub const SDL_KEYUP: SDL_EventType = 3;
27	pub const SDL_MOUSEMOTION: SDL_EventType = 4;
28	pub const SDL_MOUSEBUTTONDOWN: SDL_EventType = 5;
29	pub const SDL_MOUSEBUTTONUP: SDL_EventType = 6;
30	pub const SDL_JOYAXISMOTION: SDL_EventType = 7;
31	pub const SDL_JOYBALLMOTION: SDL_EventType = 8;
32	pub const SDL_JOYHATMOTION: SDL_EventType = 9;
33	pub const SDL_JOYBUTTONDOWN: SDL_EventType = 10;
34	pub const SDL_JOYBUTTONUP: SDL_EventType = 11;
35	pub const SDL_QUIT: SDL_EventType = 12;
36	pub const SDL_SYSWMEVENT: SDL_EventType = 13;
37	pub const SDL_VIDEORESIZE: SDL_EventType = 16;
38	pub const SDL_VIDEOEXPOSE: SDL_EventType = 17;
39	pub const SDL_USEREVENT: SDL_EventType = 24;
40
41	pub const SDL_DISABLE: c_int = 0;
42	pub const SDL_ENABLE: c_int = 1;
43	pub const SDL_QUERY: c_int = -1;
44
45	pub const SDL_APPMOUSEFOCUS: c_int = 0x01;
46	pub const SDL_APPINPUTFOCUS: c_int = 0x02;
47	pub const SDL_APPACTIVE: c_int = 0x04;
48
49	#[repr(C)]
50	#[derive(Debug, Copy, Clone)]
51	pub struct SDL_keysym {
52		pub scancode: uint8_t,
53		pub sym: SDLKey,
54		pub _mod: SDLMod,
55		pub unicode: uint16_t,
56	}
57
58	#[repr(C)]
59	#[derive(Debug, Copy, Clone)]
60	pub struct SDL_Event {
61		pub data: [c_uchar; 24],
62	}
63
64	#[repr(C)]
65	#[derive(Debug, Copy, Clone)]
66	pub struct SDL_ActiveEvent {
67		pub _type: uint8_t,
68		pub gain: uint8_t,
69		pub state: uint8_t,
70	}
71
72	#[repr(C)]
73	#[derive(Debug, Copy, Clone)]
74	pub struct SDL_KeyboardEvent {
75		pub _type: uint8_t,
76		pub which: uint8_t,
77		pub state: uint8_t,
78		pub keysym: SDL_keysym,
79	}
80
81	#[repr(C)]
82	#[derive(Debug, Copy, Clone)]
83	pub struct SDL_MouseMotionEvent {
84		pub _type: uint8_t,
85		pub which: uint8_t,
86		pub state: uint8_t,
87		pub x: uint16_t,
88		pub y: uint16_t,
89		pub xrel: int16_t,
90		pub yrel: int16_t,
91	}
92
93	#[repr(C)]
94	#[derive(Debug, Copy, Clone)]
95	pub struct SDL_MouseButtonEvent {
96		pub _type: uint8_t,
97		pub which: uint8_t,
98		pub button: uint8_t,
99		pub state: uint8_t,
100		pub x: uint16_t,
101		pub y: uint16_t,
102	}
103
104	#[repr(C)]
105	#[derive(Debug, Copy, Clone)]
106	pub struct SDL_ResizeEvent {
107		pub _type: uint8_t,
108		pub w: c_int,
109		pub h: c_int,
110	}
111
112	#[repr(C)]
113	#[derive(Debug, Copy, Clone)]
114	pub struct SDL_ExposeEvent {
115		pub _type: uint8_t,
116	}
117
118	#[repr(C)]
119	#[derive(Debug, Copy, Clone)]
120	pub struct SDL_QuitEvent {
121		pub _type: uint8_t,
122	}
123
124	#[repr(C)]
125	#[derive(Debug, Copy, Clone)]
126	pub struct SDL_UserEvent {
127		pub _type: uint8_t,
128		pub code: c_int,
129		pub data1: *mut c_void,
130		pub data2: *mut c_void,
131	}
132
133	#[repr(C)]
134	#[derive(Debug, Copy, Clone)]
135	pub struct SDL_SysWMEvent {
136		pub _type: uint8_t,
137		pub msg: *mut SDL_SysWMmsg,
138	}
139
140	impl SDL_Event {
141		pub fn _type(&self) -> *const uint8_t {
142			unsafe { mem::transmute_copy(&self) }
143		}
144
145		pub fn active(&self) -> *const SDL_ActiveEvent {
146			unsafe { mem::transmute_copy(&self) }
147		}
148
149		pub fn key(&self) -> *const SDL_KeyboardEvent {
150			unsafe { mem::transmute_copy(&self) }
151		}
152
153		pub fn motion(&self) -> *const SDL_MouseMotionEvent {
154			unsafe { mem::transmute_copy(&self) }
155		}
156
157		pub fn button(&self) -> *const SDL_MouseButtonEvent {
158			unsafe { mem::transmute_copy(&self) }
159		}
160
161		pub fn resize(&self) -> *const SDL_ResizeEvent {
162			unsafe { mem::transmute_copy(&self) }
163		}
164
165		pub fn expose(&self) -> *const SDL_ExposeEvent {
166			unsafe { mem::transmute_copy(&self) }
167		}
168
169		pub fn quit(&self) -> *const SDL_QuitEvent {
170			unsafe { mem::transmute_copy(&self) }
171		}
172
173		pub fn user(&self) -> *const SDL_UserEvent {
174			unsafe { mem::transmute_copy(&self) }
175		}
176
177		pub fn syswm(&self) -> *const SDL_SysWMEvent {
178			unsafe { mem::transmute_copy(&self) }
179		}
180	}
181
182	extern "C" {
183		pub fn SDL_PollEvent(event: *mut SDL_Event) -> c_int;
184		pub fn SDL_WaitEvent(event: *mut SDL_Event) -> c_int;
185		pub fn SDL_EventState(_type: uint8_t, state: c_int) -> uint8_t;
186		pub fn SDL_GetKeyState(numkeys: *mut c_int) -> *mut uint8_t;
187		pub fn SDL_GetModState() -> SDLMod;
188		pub fn SDL_GetKeyName(key: SDLKey) -> *mut c_schar;
189		pub fn SDL_GetAppState() -> uint8_t;
190		pub fn SDL_EnableUNICODE(enable: c_int) -> c_int;
191		pub fn SDL_EnableKeyRepeat(delay: c_int, interval: c_int) -> c_int;
192		pub fn SDL_SetModState(modstate: SDLMod);
193		pub fn SDL_PumpEvents();
194	}
195}
196
197#[derive(Debug, PartialEq, Eq, Copy, Clone)]
198pub enum AppState {
199	MouseFocus = ll::SDL_APPMOUSEFOCUS as isize,
200	InputFocus = ll::SDL_APPINPUTFOCUS as isize,
201	Active = ll::SDL_APPACTIVE as isize,
202}
203
204fn wrap_app_state(bitflags: u8) -> Vec<AppState> {
205	let flags = [AppState::MouseFocus, AppState::InputFocus, AppState::Active];
206
207	flags
208		.iter()
209		.filter_map(|&flag| {
210			if bitflags & (flag as u8) != 0 {
211				Some(flag)
212			} else {
213				None
214			}
215		})
216		.collect()
217}
218
219#[derive(PartialEq, Copy, Clone)]
220pub enum RepeatDelay {
221	Default,
222	Custom(isize),
223}
224
225#[derive(PartialEq, Copy, Clone)]
226pub enum RepeatInterval {
227	Default,
228	Custom(isize),
229}
230
231#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Copy, Clone)]
232pub enum Key {
233	Unknown = ll::SDLK_UNKNOWN as isize,
234	Backspace = ll::SDLK_BACKSPACE as isize,
235	Tab = ll::SDLK_TAB as isize,
236	Clear = ll::SDLK_CLEAR as isize,
237	Return = ll::SDLK_RETURN as isize,
238	Pause = ll::SDLK_PAUSE as isize,
239	Escape = ll::SDLK_ESCAPE as isize,
240	Space = ll::SDLK_SPACE as isize,
241	Exclaim = ll::SDLK_EXCLAIM as isize,
242	Quotedbl = ll::SDLK_QUOTEDBL as isize,
243	Hash = ll::SDLK_HASH as isize,
244	Dollar = ll::SDLK_DOLLAR as isize,
245	Ampersand = ll::SDLK_AMPERSAND as isize,
246	Quote = ll::SDLK_QUOTE as isize,
247	LeftParen = ll::SDLK_LEFTPAREN as isize,
248	RightParen = ll::SDLK_RIGHTPAREN as isize,
249	Asterisk = ll::SDLK_ASTERISK as isize,
250	Plus = ll::SDLK_PLUS as isize,
251	Comma = ll::SDLK_COMMA as isize,
252	Minus = ll::SDLK_MINUS as isize,
253	Period = ll::SDLK_PERIOD as isize,
254	Slash = ll::SDLK_SLASH as isize,
255	Num0 = ll::SDLK_0 as isize,
256	Num1 = ll::SDLK_1 as isize,
257	Num2 = ll::SDLK_2 as isize,
258	Num3 = ll::SDLK_3 as isize,
259	Num4 = ll::SDLK_4 as isize,
260	Num5 = ll::SDLK_5 as isize,
261	Num6 = ll::SDLK_6 as isize,
262	Num7 = ll::SDLK_7 as isize,
263	Num8 = ll::SDLK_8 as isize,
264	Num9 = ll::SDLK_9 as isize,
265	Colon = ll::SDLK_COLON as isize,
266	Semicolon = ll::SDLK_SEMICOLON as isize,
267	Less = ll::SDLK_LESS as isize,
268	Equals = ll::SDLK_EQUALS as isize,
269	Greater = ll::SDLK_GREATER as isize,
270	Question = ll::SDLK_QUESTION as isize,
271	At = ll::SDLK_AT as isize,
272	LeftBracket = ll::SDLK_LEFTBRACKET as isize,
273	Backslash = ll::SDLK_BACKSLASH as isize,
274	RightBracket = ll::SDLK_RIGHTBRACKET as isize,
275	Caret = ll::SDLK_CARET as isize,
276	Underscore = ll::SDLK_UNDERSCORE as isize,
277	Backquote = ll::SDLK_BACKQUOTE as isize,
278	A = ll::SDLK_a as isize,
279	B = ll::SDLK_b as isize,
280	C = ll::SDLK_c as isize,
281	D = ll::SDLK_d as isize,
282	E = ll::SDLK_e as isize,
283	F = ll::SDLK_f as isize,
284	G = ll::SDLK_g as isize,
285	H = ll::SDLK_h as isize,
286	I = ll::SDLK_i as isize,
287	J = ll::SDLK_j as isize,
288	K = ll::SDLK_k as isize,
289	L = ll::SDLK_l as isize,
290	M = ll::SDLK_m as isize,
291	N = ll::SDLK_n as isize,
292	O = ll::SDLK_o as isize,
293	P = ll::SDLK_p as isize,
294	Q = ll::SDLK_q as isize,
295	R = ll::SDLK_r as isize,
296	S = ll::SDLK_s as isize,
297	T = ll::SDLK_t as isize,
298	U = ll::SDLK_u as isize,
299	V = ll::SDLK_v as isize,
300	W = ll::SDLK_w as isize,
301	X = ll::SDLK_x as isize,
302	Y = ll::SDLK_y as isize,
303	Z = ll::SDLK_z as isize,
304	Delete = ll::SDLK_DELETE as isize,
305	World0 = ll::SDLK_WORLD_0 as isize,
306	World1 = ll::SDLK_WORLD_1 as isize,
307	World2 = ll::SDLK_WORLD_2 as isize,
308	World3 = ll::SDLK_WORLD_3 as isize,
309	World4 = ll::SDLK_WORLD_4 as isize,
310	World5 = ll::SDLK_WORLD_5 as isize,
311	World6 = ll::SDLK_WORLD_6 as isize,
312	World7 = ll::SDLK_WORLD_7 as isize,
313	World8 = ll::SDLK_WORLD_8 as isize,
314	World9 = ll::SDLK_WORLD_9 as isize,
315	World10 = ll::SDLK_WORLD_10 as isize,
316	World11 = ll::SDLK_WORLD_11 as isize,
317	World12 = ll::SDLK_WORLD_12 as isize,
318	World13 = ll::SDLK_WORLD_13 as isize,
319	World14 = ll::SDLK_WORLD_14 as isize,
320	World15 = ll::SDLK_WORLD_15 as isize,
321	World16 = ll::SDLK_WORLD_16 as isize,
322	World17 = ll::SDLK_WORLD_17 as isize,
323	World18 = ll::SDLK_WORLD_18 as isize,
324	World19 = ll::SDLK_WORLD_19 as isize,
325	World20 = ll::SDLK_WORLD_20 as isize,
326	World21 = ll::SDLK_WORLD_21 as isize,
327	World22 = ll::SDLK_WORLD_22 as isize,
328	World23 = ll::SDLK_WORLD_23 as isize,
329	World24 = ll::SDLK_WORLD_24 as isize,
330	World25 = ll::SDLK_WORLD_25 as isize,
331	World26 = ll::SDLK_WORLD_26 as isize,
332	World27 = ll::SDLK_WORLD_27 as isize,
333	World28 = ll::SDLK_WORLD_28 as isize,
334	World29 = ll::SDLK_WORLD_29 as isize,
335	World30 = ll::SDLK_WORLD_30 as isize,
336	World31 = ll::SDLK_WORLD_31 as isize,
337	World32 = ll::SDLK_WORLD_32 as isize,
338	World33 = ll::SDLK_WORLD_33 as isize,
339	World34 = ll::SDLK_WORLD_34 as isize,
340	World35 = ll::SDLK_WORLD_35 as isize,
341	World36 = ll::SDLK_WORLD_36 as isize,
342	World37 = ll::SDLK_WORLD_37 as isize,
343	World38 = ll::SDLK_WORLD_38 as isize,
344	World39 = ll::SDLK_WORLD_39 as isize,
345	World40 = ll::SDLK_WORLD_40 as isize,
346	World41 = ll::SDLK_WORLD_41 as isize,
347	World42 = ll::SDLK_WORLD_42 as isize,
348	World43 = ll::SDLK_WORLD_43 as isize,
349	World44 = ll::SDLK_WORLD_44 as isize,
350	World45 = ll::SDLK_WORLD_45 as isize,
351	World46 = ll::SDLK_WORLD_46 as isize,
352	World47 = ll::SDLK_WORLD_47 as isize,
353	World48 = ll::SDLK_WORLD_48 as isize,
354	World49 = ll::SDLK_WORLD_49 as isize,
355	World50 = ll::SDLK_WORLD_50 as isize,
356	World51 = ll::SDLK_WORLD_51 as isize,
357	World52 = ll::SDLK_WORLD_52 as isize,
358	World53 = ll::SDLK_WORLD_53 as isize,
359	World54 = ll::SDLK_WORLD_54 as isize,
360	World55 = ll::SDLK_WORLD_55 as isize,
361	World56 = ll::SDLK_WORLD_56 as isize,
362	World57 = ll::SDLK_WORLD_57 as isize,
363	World58 = ll::SDLK_WORLD_58 as isize,
364	World59 = ll::SDLK_WORLD_59 as isize,
365	World60 = ll::SDLK_WORLD_60 as isize,
366	World61 = ll::SDLK_WORLD_61 as isize,
367	World62 = ll::SDLK_WORLD_62 as isize,
368	World63 = ll::SDLK_WORLD_63 as isize,
369	World64 = ll::SDLK_WORLD_64 as isize,
370	World65 = ll::SDLK_WORLD_65 as isize,
371	World66 = ll::SDLK_WORLD_66 as isize,
372	World67 = ll::SDLK_WORLD_67 as isize,
373	World68 = ll::SDLK_WORLD_68 as isize,
374	World69 = ll::SDLK_WORLD_69 as isize,
375	World70 = ll::SDLK_WORLD_70 as isize,
376	World71 = ll::SDLK_WORLD_71 as isize,
377	World72 = ll::SDLK_WORLD_72 as isize,
378	World73 = ll::SDLK_WORLD_73 as isize,
379	World74 = ll::SDLK_WORLD_74 as isize,
380	World75 = ll::SDLK_WORLD_75 as isize,
381	World76 = ll::SDLK_WORLD_76 as isize,
382	World77 = ll::SDLK_WORLD_77 as isize,
383	World78 = ll::SDLK_WORLD_78 as isize,
384	World79 = ll::SDLK_WORLD_79 as isize,
385	World80 = ll::SDLK_WORLD_80 as isize,
386	World81 = ll::SDLK_WORLD_81 as isize,
387	World82 = ll::SDLK_WORLD_82 as isize,
388	World83 = ll::SDLK_WORLD_83 as isize,
389	World84 = ll::SDLK_WORLD_84 as isize,
390	World85 = ll::SDLK_WORLD_85 as isize,
391	World86 = ll::SDLK_WORLD_86 as isize,
392	World87 = ll::SDLK_WORLD_87 as isize,
393	World88 = ll::SDLK_WORLD_88 as isize,
394	World89 = ll::SDLK_WORLD_89 as isize,
395	World90 = ll::SDLK_WORLD_90 as isize,
396	World91 = ll::SDLK_WORLD_91 as isize,
397	World92 = ll::SDLK_WORLD_92 as isize,
398	World93 = ll::SDLK_WORLD_93 as isize,
399	World94 = ll::SDLK_WORLD_94 as isize,
400	World95 = ll::SDLK_WORLD_95 as isize,
401	Kp0 = ll::SDLK_KP0 as isize,
402	Kp1 = ll::SDLK_KP1 as isize,
403	Kp2 = ll::SDLK_KP2 as isize,
404	Kp3 = ll::SDLK_KP3 as isize,
405	Kp4 = ll::SDLK_KP4 as isize,
406	Kp5 = ll::SDLK_KP5 as isize,
407	Kp6 = ll::SDLK_KP6 as isize,
408	Kp7 = ll::SDLK_KP7 as isize,
409	Kp8 = ll::SDLK_KP8 as isize,
410	Kp9 = ll::SDLK_KP9 as isize,
411	KpPeriod = ll::SDLK_KP_PERIOD as isize,
412	KpDivide = ll::SDLK_KP_DIVIDE as isize,
413	KpMultiply = ll::SDLK_KP_MULTIPLY as isize,
414	KpMinus = ll::SDLK_KP_MINUS as isize,
415	KpPlus = ll::SDLK_KP_PLUS as isize,
416	KpEnter = ll::SDLK_KP_ENTER as isize,
417	KpEquals = ll::SDLK_KP_EQUALS as isize,
418	Up = ll::SDLK_UP as isize,
419	Down = ll::SDLK_DOWN as isize,
420	Right = ll::SDLK_RIGHT as isize,
421	Left = ll::SDLK_LEFT as isize,
422	Insert = ll::SDLK_INSERT as isize,
423	Home = ll::SDLK_HOME as isize,
424	End = ll::SDLK_END as isize,
425	PageUp = ll::SDLK_PAGEUP as isize,
426	PageDown = ll::SDLK_PAGEDOWN as isize,
427	F1 = ll::SDLK_F1 as isize,
428	F2 = ll::SDLK_F2 as isize,
429	F3 = ll::SDLK_F3 as isize,
430	F4 = ll::SDLK_F4 as isize,
431	F5 = ll::SDLK_F5 as isize,
432	F6 = ll::SDLK_F6 as isize,
433	F7 = ll::SDLK_F7 as isize,
434	F8 = ll::SDLK_F8 as isize,
435	F9 = ll::SDLK_F9 as isize,
436	F10 = ll::SDLK_F10 as isize,
437	F11 = ll::SDLK_F11 as isize,
438	F12 = ll::SDLK_F12 as isize,
439	F13 = ll::SDLK_F13 as isize,
440	F14 = ll::SDLK_F14 as isize,
441	F15 = ll::SDLK_F15 as isize,
442	NumLock = ll::SDLK_NUMLOCK as isize,
443	CapsLock = ll::SDLK_CAPSLOCK as isize,
444	ScrolLock = ll::SDLK_SCROLLOCK as isize,
445	RShift = ll::SDLK_RSHIFT as isize,
446	LShift = ll::SDLK_LSHIFT as isize,
447	RCtrl = ll::SDLK_RCTRL as isize,
448	LCtrl = ll::SDLK_LCTRL as isize,
449	RAlt = ll::SDLK_RALT as isize,
450	LAlt = ll::SDLK_LALT as isize,
451	RMeta = ll::SDLK_RMETA as isize,
452	LMeta = ll::SDLK_LMETA as isize,
453	LSuper = ll::SDLK_LSUPER as isize,
454	RSuper = ll::SDLK_RSUPER as isize,
455	Mode = ll::SDLK_MODE as isize,
456	Compose = ll::SDLK_COMPOSE as isize,
457	Help = ll::SDLK_HELP as isize,
458	Print = ll::SDLK_PRINT as isize,
459	SysReq = ll::SDLK_SYSREQ as isize,
460	Break = ll::SDLK_BREAK as isize,
461	Menu = ll::SDLK_MENU as isize,
462	Power = ll::SDLK_POWER as isize,
463	Euro = ll::SDLK_EURO as isize,
464	Undo = ll::SDLK_UNDO as isize,
465	Last,
466}
467
468impl FromPrimitive for Key {
469	fn from_i64(n: i64) -> Option<Key> {
470		use self::Key::*;
471
472		Some(match n as ll::SDLKey {
473			ll::SDLK_UNKNOWN => Unknown,
474			ll::SDLK_BACKSPACE => Backspace,
475			ll::SDLK_TAB => Tab,
476			ll::SDLK_CLEAR => Clear,
477			ll::SDLK_RETURN => Return,
478			ll::SDLK_PAUSE => Pause,
479			ll::SDLK_ESCAPE => Escape,
480			ll::SDLK_SPACE => Space,
481			ll::SDLK_EXCLAIM => Exclaim,
482			ll::SDLK_QUOTEDBL => Quotedbl,
483			ll::SDLK_HASH => Hash,
484			ll::SDLK_DOLLAR => Dollar,
485			ll::SDLK_AMPERSAND => Ampersand,
486			ll::SDLK_QUOTE => Quote,
487			ll::SDLK_LEFTPAREN => LeftParen,
488			ll::SDLK_RIGHTPAREN => RightParen,
489			ll::SDLK_ASTERISK => Asterisk,
490			ll::SDLK_PLUS => Plus,
491			ll::SDLK_COMMA => Comma,
492			ll::SDLK_MINUS => Minus,
493			ll::SDLK_PERIOD => Period,
494			ll::SDLK_SLASH => Slash,
495			ll::SDLK_0 => Num0,
496			ll::SDLK_1 => Num1,
497			ll::SDLK_2 => Num2,
498			ll::SDLK_3 => Num3,
499			ll::SDLK_4 => Num4,
500			ll::SDLK_5 => Num5,
501			ll::SDLK_6 => Num6,
502			ll::SDLK_7 => Num7,
503			ll::SDLK_8 => Num8,
504			ll::SDLK_9 => Num9,
505			ll::SDLK_COLON => Colon,
506			ll::SDLK_SEMICOLON => Semicolon,
507			ll::SDLK_LESS => Less,
508			ll::SDLK_EQUALS => Equals,
509			ll::SDLK_GREATER => Greater,
510			ll::SDLK_QUESTION => Question,
511			ll::SDLK_AT => At,
512			ll::SDLK_LEFTBRACKET => LeftBracket,
513			ll::SDLK_BACKSLASH => Backslash,
514			ll::SDLK_RIGHTBRACKET => RightBracket,
515			ll::SDLK_CARET => Caret,
516			ll::SDLK_UNDERSCORE => Underscore,
517			ll::SDLK_BACKQUOTE => Backquote,
518			ll::SDLK_a => A,
519			ll::SDLK_b => B,
520			ll::SDLK_c => C,
521			ll::SDLK_d => D,
522			ll::SDLK_e => E,
523			ll::SDLK_f => F,
524			ll::SDLK_g => G,
525			ll::SDLK_h => H,
526			ll::SDLK_i => I,
527			ll::SDLK_j => J,
528			ll::SDLK_k => K,
529			ll::SDLK_l => L,
530			ll::SDLK_m => M,
531			ll::SDLK_n => N,
532			ll::SDLK_o => O,
533			ll::SDLK_p => P,
534			ll::SDLK_q => Q,
535			ll::SDLK_r => R,
536			ll::SDLK_s => S,
537			ll::SDLK_t => T,
538			ll::SDLK_u => U,
539			ll::SDLK_v => V,
540			ll::SDLK_w => W,
541			ll::SDLK_x => X,
542			ll::SDLK_y => Y,
543			ll::SDLK_z => Z,
544			ll::SDLK_DELETE => Delete,
545			ll::SDLK_WORLD_0 => World0,
546			ll::SDLK_WORLD_1 => World1,
547			ll::SDLK_WORLD_2 => World2,
548			ll::SDLK_WORLD_3 => World3,
549			ll::SDLK_WORLD_4 => World4,
550			ll::SDLK_WORLD_5 => World5,
551			ll::SDLK_WORLD_6 => World6,
552			ll::SDLK_WORLD_7 => World7,
553			ll::SDLK_WORLD_8 => World8,
554			ll::SDLK_WORLD_9 => World9,
555			ll::SDLK_WORLD_10 => World10,
556			ll::SDLK_WORLD_11 => World11,
557			ll::SDLK_WORLD_12 => World12,
558			ll::SDLK_WORLD_13 => World13,
559			ll::SDLK_WORLD_14 => World14,
560			ll::SDLK_WORLD_15 => World15,
561			ll::SDLK_WORLD_16 => World16,
562			ll::SDLK_WORLD_17 => World17,
563			ll::SDLK_WORLD_18 => World18,
564			ll::SDLK_WORLD_19 => World19,
565			ll::SDLK_WORLD_20 => World20,
566			ll::SDLK_WORLD_21 => World21,
567			ll::SDLK_WORLD_22 => World22,
568			ll::SDLK_WORLD_23 => World23,
569			ll::SDLK_WORLD_24 => World24,
570			ll::SDLK_WORLD_25 => World25,
571			ll::SDLK_WORLD_26 => World26,
572			ll::SDLK_WORLD_27 => World27,
573			ll::SDLK_WORLD_28 => World28,
574			ll::SDLK_WORLD_29 => World29,
575			ll::SDLK_WORLD_30 => World30,
576			ll::SDLK_WORLD_31 => World31,
577			ll::SDLK_WORLD_32 => World32,
578			ll::SDLK_WORLD_33 => World33,
579			ll::SDLK_WORLD_34 => World34,
580			ll::SDLK_WORLD_35 => World35,
581			ll::SDLK_WORLD_36 => World36,
582			ll::SDLK_WORLD_37 => World37,
583			ll::SDLK_WORLD_38 => World38,
584			ll::SDLK_WORLD_39 => World39,
585			ll::SDLK_WORLD_40 => World40,
586			ll::SDLK_WORLD_41 => World41,
587			ll::SDLK_WORLD_42 => World42,
588			ll::SDLK_WORLD_43 => World43,
589			ll::SDLK_WORLD_44 => World44,
590			ll::SDLK_WORLD_45 => World45,
591			ll::SDLK_WORLD_46 => World46,
592			ll::SDLK_WORLD_47 => World47,
593			ll::SDLK_WORLD_48 => World48,
594			ll::SDLK_WORLD_49 => World49,
595			ll::SDLK_WORLD_50 => World50,
596			ll::SDLK_WORLD_51 => World51,
597			ll::SDLK_WORLD_52 => World52,
598			ll::SDLK_WORLD_53 => World53,
599			ll::SDLK_WORLD_54 => World54,
600			ll::SDLK_WORLD_55 => World55,
601			ll::SDLK_WORLD_56 => World56,
602			ll::SDLK_WORLD_57 => World57,
603			ll::SDLK_WORLD_58 => World58,
604			ll::SDLK_WORLD_59 => World59,
605			ll::SDLK_WORLD_60 => World60,
606			ll::SDLK_WORLD_61 => World61,
607			ll::SDLK_WORLD_62 => World62,
608			ll::SDLK_WORLD_63 => World63,
609			ll::SDLK_WORLD_64 => World64,
610			ll::SDLK_WORLD_65 => World65,
611			ll::SDLK_WORLD_66 => World66,
612			ll::SDLK_WORLD_67 => World67,
613			ll::SDLK_WORLD_68 => World68,
614			ll::SDLK_WORLD_69 => World69,
615			ll::SDLK_WORLD_70 => World70,
616			ll::SDLK_WORLD_71 => World71,
617			ll::SDLK_WORLD_72 => World72,
618			ll::SDLK_WORLD_73 => World73,
619			ll::SDLK_WORLD_74 => World74,
620			ll::SDLK_WORLD_75 => World75,
621			ll::SDLK_WORLD_76 => World76,
622			ll::SDLK_WORLD_77 => World77,
623			ll::SDLK_WORLD_78 => World78,
624			ll::SDLK_WORLD_79 => World79,
625			ll::SDLK_WORLD_80 => World80,
626			ll::SDLK_WORLD_81 => World81,
627			ll::SDLK_WORLD_82 => World82,
628			ll::SDLK_WORLD_83 => World83,
629			ll::SDLK_WORLD_84 => World84,
630			ll::SDLK_WORLD_85 => World85,
631			ll::SDLK_WORLD_86 => World86,
632			ll::SDLK_WORLD_87 => World87,
633			ll::SDLK_WORLD_88 => World88,
634			ll::SDLK_WORLD_89 => World89,
635			ll::SDLK_WORLD_90 => World90,
636			ll::SDLK_WORLD_91 => World91,
637			ll::SDLK_WORLD_92 => World92,
638			ll::SDLK_WORLD_93 => World93,
639			ll::SDLK_WORLD_94 => World94,
640			ll::SDLK_WORLD_95 => World95,
641			ll::SDLK_KP0 => Kp0,
642			ll::SDLK_KP1 => Kp1,
643			ll::SDLK_KP2 => Kp2,
644			ll::SDLK_KP3 => Kp3,
645			ll::SDLK_KP4 => Kp4,
646			ll::SDLK_KP5 => Kp5,
647			ll::SDLK_KP6 => Kp6,
648			ll::SDLK_KP7 => Kp7,
649			ll::SDLK_KP8 => Kp8,
650			ll::SDLK_KP9 => Kp9,
651			ll::SDLK_KP_PERIOD => KpPeriod,
652			ll::SDLK_KP_DIVIDE => KpDivide,
653			ll::SDLK_KP_MULTIPLY => KpMultiply,
654			ll::SDLK_KP_MINUS => KpMinus,
655			ll::SDLK_KP_PLUS => KpPlus,
656			ll::SDLK_KP_ENTER => KpEnter,
657			ll::SDLK_KP_EQUALS => KpEquals,
658			ll::SDLK_UP => Up,
659			ll::SDLK_DOWN => Down,
660			ll::SDLK_RIGHT => Right,
661			ll::SDLK_LEFT => Left,
662			ll::SDLK_INSERT => Insert,
663			ll::SDLK_HOME => Home,
664			ll::SDLK_END => End,
665			ll::SDLK_PAGEUP => PageUp,
666			ll::SDLK_PAGEDOWN => PageDown,
667			ll::SDLK_F1 => F1,
668			ll::SDLK_F2 => F2,
669			ll::SDLK_F3 => F3,
670			ll::SDLK_F4 => F4,
671			ll::SDLK_F5 => F5,
672			ll::SDLK_F6 => F6,
673			ll::SDLK_F7 => F7,
674			ll::SDLK_F8 => F8,
675			ll::SDLK_F9 => F9,
676			ll::SDLK_F10 => F10,
677			ll::SDLK_F11 => F11,
678			ll::SDLK_F12 => F12,
679			ll::SDLK_F13 => F13,
680			ll::SDLK_F14 => F14,
681			ll::SDLK_F15 => F15,
682			ll::SDLK_NUMLOCK => NumLock,
683			ll::SDLK_CAPSLOCK => CapsLock,
684			ll::SDLK_SCROLLOCK => ScrolLock,
685			ll::SDLK_RSHIFT => RShift,
686			ll::SDLK_LSHIFT => LShift,
687			ll::SDLK_RCTRL => RCtrl,
688			ll::SDLK_LCTRL => LCtrl,
689			ll::SDLK_RALT => RAlt,
690			ll::SDLK_LALT => LAlt,
691			ll::SDLK_RMETA => RMeta,
692			ll::SDLK_LMETA => LMeta,
693			ll::SDLK_LSUPER => LSuper,
694			ll::SDLK_RSUPER => RSuper,
695			ll::SDLK_MODE => Mode,
696			ll::SDLK_COMPOSE => Compose,
697			ll::SDLK_HELP => Help,
698			ll::SDLK_PRINT => Print,
699			ll::SDLK_SYSREQ => SysReq,
700			ll::SDLK_BREAK => Break,
701			ll::SDLK_MENU => Menu,
702			ll::SDLK_POWER => Power,
703			ll::SDLK_EURO => Euro,
704			ll::SDLK_UNDO => Undo,
705			_ => return None,
706		})
707	}
708
709	fn from_u64(n: u64) -> Option<Key> {
710		FromPrimitive::from_i64(n as i64)
711	}
712}
713
714fn wrap_key(i: ll::SDLKey) -> Option<Key> {
715	FromPrimitive::from_usize(i as usize)
716}
717
718#[derive(Debug, PartialEq, Eq, Copy, Clone)]
719pub enum Mod {
720	None = 0x0000,
721	LShift = 0x0001,
722	RShift = 0x0002,
723	LCtrl = 0x0040,
724	RCtrl = 0x0080,
725	LAlt = 0x0100,
726	RAlt = 0x0200,
727	LMeta = 0x0400,
728	RMeta = 0x0800,
729	Num = 0x1000,
730	Caps = 0x2000,
731	Mode = 0x4000,
732	Reserved = 0x8000,
733}
734
735fn wrap_mod_state(bitflags: ll::SDLMod) -> Vec<Mod> {
736	let flags = [
737		Mod::None,
738		Mod::LShift,
739		Mod::RShift,
740		Mod::LCtrl,
741		Mod::RCtrl,
742		Mod::LAlt,
743		Mod::RAlt,
744		Mod::LMeta,
745		Mod::RMeta,
746		Mod::Num,
747		Mod::Caps,
748		Mod::Mode,
749		Mod::Reserved,
750	];
751
752	flags
753		.iter()
754		.filter_map(|&flag| {
755			if bitflags & (flag as ll::SDLMod) != 0 {
756				Some(flag)
757			} else {
758				None
759			}
760		})
761		.collect()
762}
763
764#[derive(Debug, PartialEq, Eq, Copy, Clone)]
765pub enum HatState {
766	Centered,
767	Up,
768	Right,
769	Down,
770	Left,
771}
772
773#[derive(Debug, PartialEq, Eq, Copy, Clone)]
774pub enum Mouse {
775	Left = 1,
776	Middle,
777	Right,
778	WheelUp,
779	WheelDown,
780}
781
782impl FromPrimitive for Mouse {
783	fn from_i64(n: i64) -> Option<Mouse> {
784		Some(match n {
785			1 => Mouse::Left,
786			2 => Mouse::Middle,
787			3 => Mouse::Right,
788			4 => Mouse::WheelUp,
789			5 => Mouse::WheelDown,
790			_ => return None,
791		})
792	}
793
794	fn from_u64(n: u64) -> Option<Mouse> {
795		FromPrimitive::from_i64(n as i64)
796	}
797}
798
799fn wrap_mouse(bitflags: u8) -> Option<Mouse> {
800	FromPrimitive::from_u8(bitflags)
801}
802
803#[derive(Debug, PartialEq, Eq, Copy, Clone)]
804pub enum MouseState {
805	Left = 1,
806	Middle,
807	Right,
808	WheelUp,
809	WheelDown,
810	X1,
811	X2,
812}
813
814fn wrap_mouse_state(bitflags: u8) -> Vec<MouseState> {
815	let flags = [
816		MouseState::Left,
817		MouseState::Middle,
818		MouseState::Right,
819		MouseState::WheelUp,
820		MouseState::WheelDown,
821		MouseState::X1,
822		MouseState::X2,
823	];
824
825	flags
826		.iter()
827		.filter_map(|&flag| {
828			if bitflags & (flag as u8) != 0 {
829				Some(flag)
830			} else {
831				None
832			}
833		})
834		.collect()
835}
836
837#[derive(Debug, PartialEq)]
838pub enum Event {
839	// TODO: TextInput, TextEditing
840	None,
841	Active(bool, Vec<AppState>),
842	Key(Key, bool, Vec<Mod>, u16),
843	// RFC: do you need the scancode?
844	MouseMotion(Vec<MouseState>, u16, u16, i16, i16),
845	MouseButton(Mouse, bool, u16, u16),
846	JoyAxis(isize, isize, i16),
847	JoyBall(isize, isize, i16, i16),
848	JoyHat(isize, isize, Vec<HatState>),
849	JoyButton(isize, isize, bool),
850	Quit,
851	// TODO: SysWm
852	Resize(isize, isize),
853	Expose,
854	// TODO: User
855}
856
857fn null_event() -> ll::SDL_Event {
858	ll::SDL_Event { data: [0; 24] }
859}
860
861fn wrap_event(raw: ll::SDL_Event) -> Event {
862	unsafe {
863		let ty = raw._type();
864		let ty = if ty.is_null() {
865			return Event::None;
866		} else {
867			*ty
868		};
869
870		let ty: EventType = match FromPrimitive::from_usize(ty as usize) {
871			Some(ty) => ty,
872			None => return Event::None,
873		};
874
875		match ty {
876			EventType::None => Event::None,
877			EventType::Active => {
878				let active = raw.active();
879				let active = if active.is_null() {
880					return Event::None;
881				} else {
882					*active
883				};
884
885				Event::Active(active.gain == 1, wrap_app_state(active.state))
886			}
887			EventType::KeyDown | EventType::KeyUp => {
888				let key = raw.key();
889				let (key, okey) = if key.is_null() {
890					return Event::None;
891				} else {
892					((*key).keysym, *key)
893				};
894
895				match wrap_key(key.sym) {
896					Some(sym) => {
897						Event::Key(sym, okey.state == 1, wrap_mod_state(key._mod), key.unicode)
898					}
899					None => Event::None,
900				}
901			}
902			EventType::MouseMotion => {
903				let motion = raw.motion();
904				let motion = if motion.is_null() {
905					return Event::None;
906				} else {
907					*motion
908				};
909
910				Event::MouseMotion(
911					wrap_mouse_state(motion.state),
912					motion.x,
913					motion.y,
914					motion.xrel,
915					motion.yrel,
916				)
917			}
918			EventType::MouseButtonDown | EventType::MouseButtonUp => {
919				let obutton = raw.button();
920				let obutton = if obutton.is_null() {
921					return Event::None;
922				} else {
923					*obutton
924				};
925
926				match wrap_mouse(obutton.button) {
927					Some(button) => {
928						Event::MouseButton(button, obutton.state == 1, obutton.x, obutton.y)
929					}
930					None => Event::None,
931				}
932			}
933			EventType::Quit => Event::Quit,
934			EventType::Resize => {
935				let resize = raw.resize();
936				let resize = if resize.is_null() {
937					return Event::None;
938				} else {
939					*resize
940				};
941
942				Event::Resize(resize.w as isize, resize.h as isize)
943			}
944			EventType::Expose => Event::Expose,
945			_ => Event::None,
946		}
947	}
948}
949
950#[derive(Debug, PartialEq, Eq, Copy, Clone)]
951pub enum EventType {
952	// TODO: TextInput, TextEditing
953	None = ll::SDL_NOEVENT as isize,
954	Active = ll::SDL_ACTIVEEVENT as isize,
955	KeyDown = ll::SDL_KEYDOWN as isize,
956	KeyUp = ll::SDL_KEYUP as isize,
957	MouseMotion = ll::SDL_MOUSEMOTION as isize,
958	MouseButtonDown = ll::SDL_MOUSEBUTTONDOWN as isize,
959	MouseButtonUp = ll::SDL_MOUSEBUTTONUP as isize,
960	JoyAxisMotion = ll::SDL_JOYAXISMOTION as isize,
961	JoyBallMotion = ll::SDL_JOYBALLMOTION as isize,
962	JoyHatMotion = ll::SDL_JOYHATMOTION as isize,
963	JoyButtonDown = ll::SDL_JOYBUTTONDOWN as isize,
964	JoyButtonUp = ll::SDL_JOYBUTTONUP as isize,
965	Quit = ll::SDL_QUIT as isize,
966	SysWM = ll::SDL_SYSWMEVENT as isize,
967	Resize = ll::SDL_VIDEORESIZE as isize,
968	Expose = ll::SDL_VIDEOEXPOSE as isize,
969	User = ll::SDL_USEREVENT as isize,
970}
971
972impl EventType {
973	pub fn get_state(self) -> bool {
974		get_event_state(self)
975	}
976	pub fn set_state(self, state: bool) {
977		set_event_state(self, state)
978	}
979}
980
981impl FromPrimitive for EventType {
982	fn from_i64(n: i64) -> Option<EventType> {
983		Some(match n as ll::SDL_EventType {
984			ll::SDL_NOEVENT => EventType::None,
985			ll::SDL_ACTIVEEVENT => EventType::Active,
986			ll::SDL_KEYDOWN => EventType::KeyDown,
987			ll::SDL_KEYUP => EventType::KeyUp,
988			ll::SDL_MOUSEMOTION => EventType::MouseMotion,
989			ll::SDL_MOUSEBUTTONDOWN => EventType::MouseButtonDown,
990			ll::SDL_MOUSEBUTTONUP => EventType::MouseButtonUp,
991			ll::SDL_JOYAXISMOTION => EventType::JoyAxisMotion,
992			ll::SDL_JOYBALLMOTION => EventType::JoyBallMotion,
993			ll::SDL_JOYHATMOTION => EventType::JoyHatMotion,
994			ll::SDL_JOYBUTTONDOWN => EventType::JoyButtonDown,
995			ll::SDL_JOYBUTTONUP => EventType::JoyButtonUp,
996			ll::SDL_QUIT => EventType::Quit,
997			ll::SDL_SYSWMEVENT => EventType::SysWM,
998			ll::SDL_VIDEORESIZE => EventType::Resize,
999			ll::SDL_VIDEOEXPOSE => EventType::Expose,
1000			ll::SDL_USEREVENT => EventType::User,
1001			_ => return None,
1002		})
1003	}
1004
1005	fn from_u64(n: u64) -> Option<EventType> {
1006		FromPrimitive::from_i64(n as i64)
1007	}
1008}
1009
1010pub fn pump_events() {
1011	unsafe {
1012		ll::SDL_PumpEvents();
1013	}
1014}
1015
1016// TODO: peep_events (a tricky one but doable)
1017
1018pub fn wait_event() -> Event {
1019	let mut raw = null_event();
1020	let success = unsafe { ll::SDL_WaitEvent(&mut raw) == 1 as c_int };
1021
1022	if success {
1023		wrap_event(raw)
1024	} else {
1025		Event::None
1026	}
1027}
1028
1029pub fn poll_event() -> Event {
1030	pump_events();
1031
1032	let mut raw = null_event();
1033	let have = unsafe { ll::SDL_PollEvent(&mut raw) };
1034
1035	if have != 1 {
1036		return Event::None;
1037	}
1038
1039	wrap_event(raw)
1040}
1041
1042// TODO: set_event_filter, get_event_filter
1043
1044pub fn set_event_state(ty: EventType, state: bool) {
1045	unsafe {
1046		ll::SDL_EventState(ty as u8, state as c_int);
1047	}
1048}
1049
1050pub fn get_event_state(ty: EventType) -> bool {
1051	unsafe { ll::SDL_EventState(ty as u8, ll::SDL_QUERY as c_int) == ll::SDL_ENABLE as u8 }
1052}
1053
1054pub fn get_key_state() -> Vec<(Key, bool)> {
1055	let mut num = 0;
1056	let data = unsafe { ll::SDL_GetKeyState(&mut num) };
1057	let mut i = -1isize;
1058
1059	let buf = data as *const u8;
1060	let buf = unsafe { slice::from_raw_parts(buf, num as usize) };
1061	buf.iter()
1062		.filter_map(|&state| {
1063			i += 1;
1064
1065			match wrap_key(i as ll::SDLKey) {
1066				Some(key) => Some((key, state == 1)),
1067				None => None,
1068			}
1069		})
1070		.collect()
1071}
1072
1073pub fn get_mod_state() -> Vec<Mod> {
1074	unsafe { wrap_mod_state(ll::SDL_GetModState()) }
1075}
1076
1077pub fn set_mod_state(states: &[Mod]) {
1078	unsafe {
1079		ll::SDL_SetModState(
1080			states
1081				.iter()
1082				.fold(0u32, |states, &state| states | state as ll::SDLMod),
1083		);
1084	}
1085}
1086
1087pub fn get_key_name(key: Key) -> String {
1088	unsafe {
1089		let cstr = ll::SDL_GetKeyName(key as ll::SDLKey);
1090
1091		str::from_utf8(CStr::from_ptr(mem::transmute_copy(&cstr)).to_bytes())
1092			.unwrap()
1093			.to_string()
1094	}
1095}
1096
1097pub fn get_app_state() -> Vec<AppState> {
1098	let bitflags = unsafe { ll::SDL_GetAppState() };
1099
1100	wrap_app_state(bitflags)
1101}
1102
1103pub fn enable_unicode(enable: bool) {
1104	unsafe {
1105		ll::SDL_EnableUNICODE(enable as c_int);
1106	}
1107}
1108
1109pub fn is_unicode_enabled() -> bool {
1110	unsafe { ll::SDL_EnableUNICODE(-1 as c_int) == 1 }
1111}
1112
1113pub fn enable_key_repeat(delay: RepeatDelay, interval: RepeatInterval) -> bool {
1114	let delay = match delay {
1115		RepeatDelay::Default => 500,
1116		RepeatDelay::Custom(delay) => delay,
1117	};
1118	let interval = match interval {
1119		RepeatInterval::Default => 30,
1120		RepeatInterval::Custom(interval) => interval,
1121	};
1122
1123	unsafe { ll::SDL_EnableKeyRepeat(delay as c_int, interval as c_int) == 0 as c_int }
1124}
1125
1126// get_mouse_state, get_relative_mouse_state, start_text_input, stop_text_input,
1127// set_text_input_rect