use std::ffi::CStr;
use std::mem;
use libc::c_int;
use std::ptr;
use std::borrow::ToOwned;
use std::iter::FromIterator;
use std::convert::TryFrom;
use std::marker::PhantomData;
use std::collections::HashMap;
use std::sync::Mutex;
use std::mem::transmute;
use libc::c_void;
use crate::controller;
use crate::controller::{Axis, Button};
use crate::joystick;
use crate::joystick::HatState;
use crate::keyboard;
use crate::keyboard::Mod;
use crate::keyboard::Keycode;
use crate::mouse;
use crate::mouse::{MouseButton, MouseState, MouseWheelDirection};
use crate::keyboard::Scancode;
use crate::get_error;
use crate::sys;
use crate::sys::SDL_EventType;
struct CustomEventTypeMaps {
sdl_id_to_type_id: HashMap<u32, ::std::any::TypeId>,
type_id_to_sdl_id: HashMap<::std::any::TypeId, u32>
}
impl CustomEventTypeMaps {
fn new() -> Self {
CustomEventTypeMaps {
sdl_id_to_type_id: HashMap::new(),
type_id_to_sdl_id: HashMap::new()
}
}
}
lazy_static! {
static ref CUSTOM_EVENT_TYPES : Mutex<CustomEventTypeMaps> = { Mutex::new(CustomEventTypeMaps::new()) };
}
impl crate::EventSubsystem {
pub fn flush_event(&self, event_type: EventType) {
unsafe { sys::SDL_FlushEvent(event_type as u32) };
}
pub fn flush_events(&self, min_type: u32, max_type: u32) {
unsafe { sys::SDL_FlushEvents(min_type, max_type) };
}
pub fn peek_events<B>(&self, max_amount: u32) -> B
where B: FromIterator<Event>
{
unsafe {
let mut events = Vec::with_capacity(max_amount as usize);
let result = {
let events_ptr = events.as_mut_ptr();
sys::SDL_PeepEvents(
events_ptr,
max_amount as c_int,
sys::SDL_eventaction::SDL_PEEKEVENT,
SDL_EventType::SDL_FIRSTEVENT as u32,
SDL_EventType::SDL_LASTEVENT as u32
)
};
if result < 0 {
panic!(get_error());
} else {
events.set_len(result as usize);
events.into_iter().map(|event_raw| {
Event::from_ll(event_raw)
}).collect()
}
}
}
pub fn push_event(&self, event: Event) -> Result<(), String> {
self.event_sender().push_event(event)
}
#[inline(always)]
pub unsafe fn register_event(&self) -> Result<u32, String> {
Ok(*self.register_events(1)?.first().unwrap())
}
pub unsafe fn register_events(&self, nr: u32) -> Result<Vec<u32>, String> {
let result = sys::SDL_RegisterEvents(nr as ::libc::c_int);
const ERR_NR:u32 = ::std::u32::MAX - 1;
match result {
ERR_NR => {
Err("No more user events can be created; SDL_LASTEVENT reached"
.to_owned())
},
_ => {
let event_ids = (result..(result+nr)).collect();
Ok(event_ids)
}
}
}
#[inline(always)]
pub fn register_custom_event<T: ::std::any::Any>(&self)
-> Result<(), String> {
use ::std::any::TypeId;
let event_id = *(unsafe { self.register_events(1) })?.first().unwrap();
let mut cet = CUSTOM_EVENT_TYPES.lock().unwrap();
let type_id = TypeId::of::<Box<T>>();
if cet.type_id_to_sdl_id.contains_key(&type_id) {
return Err(
"The same event type can not be registered twice!".to_owned()
);
}
cet.sdl_id_to_type_id.insert(event_id, type_id);
cet.type_id_to_sdl_id.insert(type_id, event_id);
Ok(())
}
pub fn push_custom_event<T: ::std::any::Any>(&self, event:T)
-> Result<(), String> {
self.event_sender().push_custom_event(event)
}
pub fn event_sender(&self) -> EventSender {
EventSender {
_priv: (),
}
}
}
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
#[repr(u32)]
pub enum EventType {
First = SDL_EventType::SDL_FIRSTEVENT as u32,
Quit = SDL_EventType::SDL_QUIT as u32,
AppTerminating = SDL_EventType::SDL_APP_TERMINATING as u32,
AppLowMemory = SDL_EventType::SDL_APP_LOWMEMORY as u32,
AppWillEnterBackground = SDL_EventType::SDL_APP_WILLENTERBACKGROUND as u32,
AppDidEnterBackground = SDL_EventType::SDL_APP_DIDENTERBACKGROUND as u32,
AppWillEnterForeground = SDL_EventType::SDL_APP_WILLENTERFOREGROUND as u32,
AppDidEnterForeground = SDL_EventType::SDL_APP_DIDENTERFOREGROUND as u32,
Window = SDL_EventType::SDL_WINDOWEVENT as u32,
KeyDown = SDL_EventType::SDL_KEYDOWN as u32,
KeyUp = SDL_EventType::SDL_KEYUP as u32,
TextEditing = SDL_EventType::SDL_TEXTEDITING as u32,
TextInput = SDL_EventType::SDL_TEXTINPUT as u32,
MouseMotion = SDL_EventType::SDL_MOUSEMOTION as u32,
MouseButtonDown = SDL_EventType::SDL_MOUSEBUTTONDOWN as u32,
MouseButtonUp = SDL_EventType::SDL_MOUSEBUTTONUP as u32,
MouseWheel = SDL_EventType::SDL_MOUSEWHEEL as u32,
JoyAxisMotion = SDL_EventType::SDL_JOYAXISMOTION as u32,
JoyBallMotion = SDL_EventType::SDL_JOYBALLMOTION as u32,
JoyHatMotion = SDL_EventType::SDL_JOYHATMOTION as u32,
JoyButtonDown = SDL_EventType::SDL_JOYBUTTONDOWN as u32,
JoyButtonUp = SDL_EventType::SDL_JOYBUTTONUP as u32,
JoyDeviceAdded = SDL_EventType::SDL_JOYDEVICEADDED as u32,
JoyDeviceRemoved = SDL_EventType::SDL_JOYDEVICEREMOVED as u32,
ControllerAxisMotion = SDL_EventType::SDL_CONTROLLERAXISMOTION as u32,
ControllerButtonDown = SDL_EventType::SDL_CONTROLLERBUTTONDOWN as u32,
ControllerButtonUp = SDL_EventType::SDL_CONTROLLERBUTTONUP as u32,
ControllerDeviceAdded = SDL_EventType::SDL_CONTROLLERDEVICEADDED as u32,
ControllerDeviceRemoved = SDL_EventType::SDL_CONTROLLERDEVICEREMOVED as u32,
ControllerDeviceRemapped = SDL_EventType::SDL_CONTROLLERDEVICEREMAPPED as u32,
FingerDown = SDL_EventType::SDL_FINGERDOWN as u32,
FingerUp = SDL_EventType::SDL_FINGERUP as u32,
FingerMotion = SDL_EventType::SDL_FINGERMOTION as u32,
DollarGesture = SDL_EventType::SDL_DOLLARGESTURE as u32,
DollarRecord = SDL_EventType::SDL_DOLLARRECORD as u32,
MultiGesture = SDL_EventType::SDL_MULTIGESTURE as u32,
ClipboardUpdate = SDL_EventType::SDL_CLIPBOARDUPDATE as u32,
DropFile = SDL_EventType::SDL_DROPFILE as u32,
DropText = SDL_EventType::SDL_DROPTEXT as u32,
DropBegin = SDL_EventType::SDL_DROPBEGIN as u32,
DropComplete = SDL_EventType::SDL_DROPCOMPLETE as u32,
AudioDeviceAdded = SDL_EventType::SDL_AUDIODEVICEADDED as u32,
AudioDeviceRemoved = SDL_EventType::SDL_AUDIODEVICEREMOVED as u32,
RenderTargetsReset = SDL_EventType::SDL_RENDER_TARGETS_RESET as u32,
RenderDeviceReset = SDL_EventType::SDL_RENDER_DEVICE_RESET as u32,
User = SDL_EventType::SDL_USEREVENT as u32,
Last = SDL_EventType::SDL_LASTEVENT as u32,
}
impl TryFrom<u32> for EventType {
type Error = ();
fn try_from(n: u32) -> Result<Self, Self::Error> {
use self::EventType::*;
use crate::sys::SDL_EventType::*;
Ok( match unsafe { transmute(n) } {
SDL_FIRSTEVENT => First,
SDL_QUIT => Quit,
SDL_APP_TERMINATING => AppTerminating,
SDL_APP_LOWMEMORY => AppLowMemory,
SDL_APP_WILLENTERBACKGROUND => AppWillEnterBackground,
SDL_APP_DIDENTERBACKGROUND => AppDidEnterBackground,
SDL_APP_WILLENTERFOREGROUND => AppWillEnterForeground,
SDL_APP_DIDENTERFOREGROUND => AppDidEnterForeground,
SDL_WINDOWEVENT => Window,
SDL_KEYDOWN => KeyDown,
SDL_KEYUP => KeyUp,
SDL_TEXTEDITING => TextEditing,
SDL_TEXTINPUT => TextInput,
SDL_MOUSEMOTION => MouseMotion,
SDL_MOUSEBUTTONDOWN => MouseButtonDown,
SDL_MOUSEBUTTONUP => MouseButtonUp,
SDL_MOUSEWHEEL => MouseWheel,
SDL_JOYAXISMOTION => JoyAxisMotion,
SDL_JOYBALLMOTION => JoyBallMotion,
SDL_JOYHATMOTION => JoyHatMotion,
SDL_JOYBUTTONDOWN => JoyButtonDown,
SDL_JOYBUTTONUP => JoyButtonUp,
SDL_JOYDEVICEADDED => JoyDeviceAdded,
SDL_JOYDEVICEREMOVED => JoyDeviceRemoved,
SDL_CONTROLLERAXISMOTION => ControllerAxisMotion,
SDL_CONTROLLERBUTTONDOWN => ControllerButtonDown,
SDL_CONTROLLERBUTTONUP => ControllerButtonUp,
SDL_CONTROLLERDEVICEADDED => ControllerDeviceAdded,
SDL_CONTROLLERDEVICEREMOVED => ControllerDeviceRemoved,
SDL_CONTROLLERDEVICEREMAPPED => ControllerDeviceRemapped,
SDL_FINGERDOWN => FingerDown,
SDL_FINGERUP => FingerUp,
SDL_FINGERMOTION => FingerMotion,
SDL_DOLLARGESTURE => DollarGesture,
SDL_DOLLARRECORD => DollarRecord,
SDL_MULTIGESTURE => MultiGesture,
SDL_CLIPBOARDUPDATE => ClipboardUpdate,
SDL_DROPFILE => DropFile,
SDL_DROPTEXT => DropText,
SDL_DROPBEGIN => DropBegin,
SDL_DROPCOMPLETE => DropComplete,
SDL_AUDIODEVICEADDED => AudioDeviceAdded,
SDL_AUDIODEVICEREMOVED => AudioDeviceRemoved,
SDL_RENDER_TARGETS_RESET => RenderTargetsReset,
SDL_RENDER_DEVICE_RESET => RenderDeviceReset,
SDL_USEREVENT => User,
SDL_LASTEVENT => Last,
_ => return Err(()),
})
}
}
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
pub enum WindowEvent {
None,
Shown,
Hidden,
Exposed,
Moved(i32,i32),
Resized(i32,i32),
SizeChanged(i32,i32),
Minimized,
Maximized,
Restored,
Enter,
Leave,
FocusGained,
FocusLost,
Close,
TakeFocus,
HitTest,
}
impl WindowEvent {
#[allow(clippy::match_same_arms)]
fn from_ll(id: u8, data1: i32, data2: i32) -> WindowEvent {
match id {
0 => WindowEvent::None,
1 => WindowEvent::Shown,
2 => WindowEvent::Hidden,
3 => WindowEvent::Exposed,
4 => WindowEvent::Moved(data1,data2),
5 => WindowEvent::Resized(data1,data2),
6 => WindowEvent::SizeChanged(data1,data2),
7 => WindowEvent::Minimized,
8 => WindowEvent::Maximized,
9 => WindowEvent::Restored,
10 => WindowEvent::Enter,
11 => WindowEvent::Leave,
12 => WindowEvent::FocusGained,
13 => WindowEvent::FocusLost,
14 => WindowEvent::Close,
15 => WindowEvent::TakeFocus,
16 => WindowEvent::HitTest,
_ => WindowEvent::None
}
}
fn to_ll(&self) -> (u8, i32, i32) {
match *self {
WindowEvent::None => (0, 0, 0),
WindowEvent::Shown => (1, 0, 0),
WindowEvent::Hidden => (2, 0, 0),
WindowEvent::Exposed => (3, 0, 0),
WindowEvent::Moved(d1,d2) => (4, d1, d2),
WindowEvent::Resized(d1,d2) => (5, d1, d2),
WindowEvent::SizeChanged(d1,d2) => (6, d1, d2),
WindowEvent::Minimized => (7, 0, 0),
WindowEvent::Maximized => (8, 0, 0),
WindowEvent::Restored => (9, 0, 0),
WindowEvent::Enter => (10, 0, 0),
WindowEvent::Leave => (11, 0, 0),
WindowEvent::FocusGained => (12, 0, 0),
WindowEvent::FocusLost => (13, 0, 0),
WindowEvent::Close => (14, 0, 0),
WindowEvent::TakeFocus => (15, 0, 0),
WindowEvent::HitTest => (16, 0, 0),
}
}
pub fn is_same_kind_as(&self, other: &WindowEvent) -> bool {
match (self, other) {
(Self::None, Self::None)
| (Self::Shown, Self::Shown)
| (Self::Hidden, Self::Hidden)
| (Self::Exposed, Self::Exposed)
| (Self::Moved(_, _), Self::Moved(_, _))
| (Self::Resized(_, _), Self::Resized(_, _))
| (Self::SizeChanged(_, _), Self::SizeChanged(_, _))
| (Self::Minimized, Self::Minimized)
| (Self::Maximized, Self::Maximized)
| (Self::Restored, Self::Restored)
| (Self::Enter, Self::Enter)
| (Self::Leave, Self::Leave)
| (Self::FocusGained, Self::FocusGained)
| (Self::FocusLost, Self::FocusLost)
| (Self::Close, Self::Close)
| (Self::TakeFocus, Self::TakeFocus)
| (Self::HitTest, Self::HitTest) => true,
_ => false,
}
}
}
#[derive(Clone, PartialEq, Debug)]
pub enum Event {
Quit { timestamp: u32 },
AppTerminating { timestamp: u32 },
AppLowMemory { timestamp: u32 },
AppWillEnterBackground { timestamp: u32 },
AppDidEnterBackground { timestamp: u32 },
AppWillEnterForeground { timestamp: u32 },
AppDidEnterForeground { timestamp: u32 },
Window {
timestamp: u32,
window_id: u32,
win_event: WindowEvent,
},
KeyDown {
timestamp: u32,
window_id: u32,
keycode: Option<Keycode>,
scancode: Option<Scancode>,
keymod: Mod,
repeat: bool
},
KeyUp {
timestamp: u32,
window_id: u32,
keycode: Option<Keycode>,
scancode: Option<Scancode>,
keymod: Mod,
repeat: bool
},
TextEditing {
timestamp: u32,
window_id: u32,
text: String,
start: i32,
length: i32
},
TextInput {
timestamp: u32,
window_id: u32,
text: String
},
MouseMotion {
timestamp: u32,
window_id: u32,
which: u32,
mousestate: MouseState,
x: i32,
y: i32,
xrel: i32,
yrel: i32
},
MouseButtonDown {
timestamp: u32,
window_id: u32,
which: u32,
mouse_btn: MouseButton,
clicks: u8,
x: i32,
y: i32
},
MouseButtonUp {
timestamp: u32,
window_id: u32,
which: u32,
mouse_btn: MouseButton,
clicks: u8,
x: i32,
y: i32
},
MouseWheel {
timestamp: u32,
window_id: u32,
which: u32,
x: i32,
y: i32,
direction: MouseWheelDirection,
},
JoyAxisMotion {
timestamp: u32,
which: u32,
axis_idx: u8,
value: i16
},
JoyBallMotion {
timestamp: u32,
which: u32,
ball_idx: u8,
xrel: i16,
yrel: i16
},
JoyHatMotion {
timestamp: u32,
which: u32,
hat_idx: u8,
state: HatState
},
JoyButtonDown {
timestamp: u32,
which: u32,
button_idx: u8
},
JoyButtonUp {
timestamp: u32,
which: u32,
button_idx: u8
},
JoyDeviceAdded {
timestamp: u32,
which: u32
},
JoyDeviceRemoved {
timestamp: u32,
which: u32
},
ControllerAxisMotion {
timestamp: u32,
which: u32,
axis: Axis,
value: i16
},
ControllerButtonDown {
timestamp: u32,
which: u32,
button: Button
},
ControllerButtonUp {
timestamp: u32,
which: u32,
button: Button
},
ControllerDeviceAdded {
timestamp: u32,
which: u32
},
ControllerDeviceRemoved {
timestamp: u32,
which: u32
},
ControllerDeviceRemapped {
timestamp: u32,
which: u32
},
FingerDown {
timestamp: u32,
touch_id: i64,
finger_id: i64,
x: f32,
y: f32,
dx: f32,
dy: f32,
pressure: f32
},
FingerUp {
timestamp: u32,
touch_id: i64,
finger_id: i64,
x: f32,
y: f32,
dx: f32,
dy: f32,
pressure: f32
},
FingerMotion {
timestamp: u32,
touch_id: i64,
finger_id: i64,
x: f32,
y: f32,
dx: f32,
dy: f32,
pressure: f32
},
DollarGesture {
timestamp: u32,
touch_id: i64,
gesture_id: i64,
num_fingers: u32,
error: f32,
x: f32,
y: f32
},
DollarRecord {
timestamp: u32,
touch_id: i64,
gesture_id: i64,
num_fingers: u32,
error: f32,
x: f32,
y: f32
},
MultiGesture {
timestamp: u32,
touch_id: i64,
d_theta: f32,
d_dist: f32,
x: f32,
y: f32,
num_fingers: u16
},
ClipboardUpdate {
timestamp: u32
},
DropFile {
timestamp: u32,
window_id: u32,
filename: String
},
DropText {
timestamp: u32,
window_id: u32,
filename: String
},
DropBegin {
timestamp: u32,
window_id: u32,
},
DropComplete {
timestamp: u32,
window_id: u32,
},
AudioDeviceAdded {
timestamp: u32,
which: u32,
iscapture: bool,
},
AudioDeviceRemoved {
timestamp: u32,
which: u32,
iscapture: bool,
},
RenderTargetsReset {
timestamp: u32,
},
RenderDeviceReset {
timestamp: u32,
},
User {
timestamp: u32,
window_id: u32,
type_: u32,
code: i32,
data1: *mut c_void,
data2: *mut c_void
},
Unknown {
timestamp: u32,
type_: u32
}
}
unsafe impl Send for Event {}
unsafe impl Sync for Event {}
fn mk_keysym<S, K>(scancode: S,
keycode: K,
keymod: Mod) -> sys::SDL_Keysym
where S: Into<Option<Scancode>>,
K: Into<Option<Keycode>>,
{
let scancode = scancode.into()
.map(|sc| unsafe { transmute::<u32, sys::SDL_Scancode>(sc as u32) })
.unwrap_or(sys::SDL_Scancode::SDL_SCANCODE_UNKNOWN);
let keycode = keycode.into()
.map(|kc| kc as sys::SDL_Keycode)
.unwrap_or(sys::SDLK_UNKNOWN as i32);
let keymod = keymod.bits() as u16;
sys::SDL_Keysym {
scancode,
sym: keycode,
mod_: keymod,
unused: 0,
}
}
impl Event {
fn to_ll(&self) -> Option<sys::SDL_Event> {
let mut ret = mem::MaybeUninit::uninit();
match *self {
Event::User { window_id, type_, code, data1, data2, timestamp} => {
let event = sys::SDL_UserEvent {
type_: type_ as u32,
timestamp,
windowID: window_id,
code: code as i32,
data1,
data2
};
unsafe {
ptr::copy(&event, ret.as_mut_ptr() as *mut sys::SDL_UserEvent, 1);
Some(ret.assume_init())
}
},
Event::Quit{timestamp} => {
let event = sys::SDL_QuitEvent {
type_: SDL_EventType::SDL_QUIT as u32,
timestamp,
};
unsafe {
ptr::copy(&event, ret.as_mut_ptr() as *mut sys::SDL_QuitEvent, 1);
Some(ret.assume_init())
}
},
Event::Window{
timestamp,
window_id,
win_event
} => {
let (win_event_id, data1, data2) = win_event.to_ll();
let event = sys::SDL_WindowEvent {
type_: SDL_EventType::SDL_WINDOWEVENT as u32,
timestamp,
windowID: window_id,
event: win_event_id,
padding1: 0,
padding2: 0,
padding3: 0,
data1,
data2,
};
unsafe {
ptr::copy(&event, ret.as_mut_ptr() as *mut sys::SDL_WindowEvent, 1);
Some(ret.assume_init())
}
},
Event::KeyDown{
timestamp,
window_id,
keycode,
scancode,
keymod,
repeat,
} => {
let keysym = mk_keysym(scancode, keycode, keymod);
let event = sys::SDL_KeyboardEvent{
type_: SDL_EventType::SDL_KEYDOWN as u32,
timestamp,
windowID: window_id,
state: sys::SDL_PRESSED as u8,
repeat: repeat as u8,
padding2: 0,
padding3: 0,
keysym,
};
unsafe {
ptr::copy(&event, ret.as_mut_ptr() as *mut sys::SDL_KeyboardEvent, 1);
Some(ret.assume_init())
}
},
Event::KeyUp {
timestamp,
window_id,
keycode,
scancode,
keymod,
repeat,
} => {
let keysym = mk_keysym(scancode, keycode, keymod);
let event = sys::SDL_KeyboardEvent{
type_: SDL_EventType::SDL_KEYUP as u32,
timestamp,
windowID: window_id,
state: sys::SDL_RELEASED as u8,
repeat: repeat as u8,
padding2: 0,
padding3: 0,
keysym,
};
unsafe {
ptr::copy(&event, ret.as_mut_ptr() as *mut sys::SDL_KeyboardEvent, 1);
Some(ret.assume_init())
}
},
Event::MouseMotion{
timestamp,
window_id,
which,
mousestate,
x,
y,
xrel,
yrel
} => {
let state = mousestate.to_sdl_state();
let event = sys::SDL_MouseMotionEvent {
type_: SDL_EventType::SDL_MOUSEMOTION as u32,
timestamp,
windowID: window_id,
which,
state,
x,
y,
xrel,
yrel,
};
unsafe {
ptr::copy(&event, ret.as_mut_ptr() as *mut sys::SDL_MouseMotionEvent, 1);
Some(ret.assume_init())
}
},
Event::MouseButtonDown{
timestamp,
window_id,
which,
mouse_btn,
clicks,
x,
y
} => {
let event = sys::SDL_MouseButtonEvent {
type_: SDL_EventType::SDL_MOUSEBUTTONDOWN as u32,
timestamp,
windowID: window_id,
which,
button: mouse_btn as u8,
state: sys::SDL_PRESSED as u8,
clicks,
padding1: 0,
x,
y
};
unsafe {
ptr::copy(&event, ret.as_mut_ptr() as *mut sys::SDL_MouseButtonEvent, 1);
Some(ret.assume_init())
}
},
Event::MouseButtonUp{
timestamp,
window_id,
which,
mouse_btn,
clicks,
x,
y
} => {
let event = sys::SDL_MouseButtonEvent {
type_: SDL_EventType::SDL_MOUSEBUTTONUP as u32,
timestamp,
windowID: window_id,
which,
button: mouse_btn as u8,
state: sys::SDL_RELEASED as u8,
clicks,
padding1: 0,
x,
y
};
unsafe {
ptr::copy(&event, ret.as_mut_ptr() as *mut sys::SDL_MouseButtonEvent, 1);
Some(ret.assume_init())
}
},
Event::MouseWheel{
timestamp,
window_id,
which,
x,
y,
direction,
} => {
let event = sys::SDL_MouseWheelEvent {
type_: SDL_EventType::SDL_MOUSEWHEEL as u32,
timestamp,
windowID: window_id,
which,
x,
y,
direction : direction.to_ll(),
};
unsafe {
ptr::copy(&event, ret.as_mut_ptr() as *mut sys::SDL_MouseWheelEvent, 1);
Some(ret.assume_init())
}
},
Event::JoyAxisMotion{
timestamp,
which,
axis_idx,
value
} => {
let event = sys::SDL_JoyAxisEvent {
type_: SDL_EventType::SDL_JOYAXISMOTION as u32,
timestamp,
which: which as i32,
axis: axis_idx,
value,
padding1: 0,
padding2: 0,
padding3: 0,
padding4: 0
};
unsafe {
ptr::copy(&event, ret.as_mut_ptr() as *mut sys::SDL_JoyAxisEvent, 1);
Some(ret.assume_init())
}
},
Event::JoyBallMotion{
timestamp,
which,
ball_idx,
xrel,
yrel
} => {
let event = sys::SDL_JoyBallEvent {
type_: SDL_EventType::SDL_JOYBALLMOTION as u32,
timestamp,
which: which as i32,
ball: ball_idx,
xrel,
yrel,
padding1: 0,
padding2: 0,
padding3: 0
};
unsafe {
ptr::copy(&event, ret.as_mut_ptr() as *mut sys::SDL_JoyBallEvent, 1);
Some(ret.assume_init())
}
},
Event::JoyHatMotion{
timestamp,
which,
hat_idx,
state,
} => {
let hatvalue = state.to_raw();
let event = sys::SDL_JoyHatEvent {
type_: SDL_EventType::SDL_JOYHATMOTION as u32,
timestamp,
which: which as i32,
hat: hat_idx,
value: hatvalue,
padding1: 0,
padding2: 0
};
unsafe {
ptr::copy(&event, ret.as_mut_ptr() as *mut sys::SDL_JoyHatEvent, 1);
Some(ret.assume_init())
}
},
Event::JoyButtonDown{
timestamp,
which,
button_idx
} => {
let event = sys::SDL_JoyButtonEvent {
type_: SDL_EventType::SDL_JOYBUTTONDOWN as u32,
timestamp,
which: which as i32,
button: button_idx,
state: sys::SDL_PRESSED as u8,
padding1: 0,
padding2: 0,
};
unsafe {
ptr::copy(&event, ret.as_mut_ptr() as *mut sys::SDL_JoyButtonEvent, 1);
Some(ret.assume_init())
}
},
Event::JoyButtonUp{
timestamp,
which,
button_idx,
} => {
let event = sys::SDL_JoyButtonEvent {
type_: SDL_EventType::SDL_JOYBUTTONUP as u32,
timestamp,
which: which as i32,
button: button_idx,
state: sys::SDL_RELEASED as u8,
padding1: 0,
padding2: 0,
};
unsafe {
ptr::copy(&event, ret.as_mut_ptr() as *mut sys::SDL_JoyButtonEvent, 1);
Some(ret.assume_init())
}
},
Event::JoyDeviceAdded{
timestamp,
which,
} => {
let event = sys::SDL_JoyDeviceEvent {
type_: SDL_EventType::SDL_JOYDEVICEADDED as u32,
timestamp,
which: which as i32,
};
unsafe {
ptr::copy(&event, ret.as_mut_ptr() as *mut sys::SDL_JoyDeviceEvent, 1);
Some(ret.assume_init())
}
},
Event::JoyDeviceRemoved{
timestamp,
which,
} => {
let event = sys::SDL_JoyDeviceEvent {
type_: SDL_EventType::SDL_JOYDEVICEREMOVED as u32,
timestamp,
which: which as i32,
};
unsafe {
ptr::copy(&event, ret.as_mut_ptr() as *mut sys::SDL_JoyDeviceEvent, 1);
Some(ret.assume_init())
}
},
Event::ControllerAxisMotion{
timestamp,
which,
axis,
value,
} => {
let axisval = axis.to_ll();
let event = sys::SDL_ControllerAxisEvent {
type_: SDL_EventType::SDL_CONTROLLERAXISMOTION as u32,
timestamp,
which: which as i32,
axis: axisval as u8,
value,
padding1: 0,
padding2: 0,
padding3: 0,
padding4: 0,
};
unsafe {
ptr::copy(&event, ret.as_mut_ptr() as *mut sys::SDL_ControllerAxisEvent, 1);
Some(ret.assume_init())
}
},
Event::ControllerButtonDown{
timestamp,
which,
button,
} => {
let buttonval = button.to_ll();
let event = sys::SDL_ControllerButtonEvent {
type_: SDL_EventType::SDL_CONTROLLERBUTTONDOWN as u32,
timestamp,
which: which as i32,
button: buttonval as u8,
state: sys::SDL_PRESSED as u8,
padding1: 0,
padding2: 0,
};
unsafe {
ptr::copy(&event, ret.as_mut_ptr() as *mut sys::SDL_ControllerButtonEvent, 1);
Some(ret.assume_init())
}
},
Event::ControllerButtonUp{
timestamp,
which,
button,
} => {
let buttonval = button.to_ll();
let event = sys::SDL_ControllerButtonEvent {
type_: SDL_EventType::SDL_CONTROLLERBUTTONUP as u32,
timestamp,
which: which as i32,
button: buttonval as u8,
state: sys::SDL_RELEASED as u8,
padding1: 0,
padding2: 0,
};
unsafe {
ptr::copy(&event, ret.as_mut_ptr() as *mut sys::SDL_ControllerButtonEvent, 1);
Some(ret.assume_init())
}
},
Event::ControllerDeviceAdded{
timestamp,
which,
} => {
let event = sys::SDL_ControllerDeviceEvent {
type_: SDL_EventType::SDL_CONTROLLERDEVICEADDED as u32,
timestamp,
which: which as i32,
};
unsafe {
ptr::copy(&event, ret.as_mut_ptr() as *mut sys::SDL_ControllerDeviceEvent, 1);
Some(ret.assume_init())
}
},
Event::ControllerDeviceRemoved{
timestamp,
which,
} => {
let event = sys::SDL_ControllerDeviceEvent {
type_: SDL_EventType::SDL_CONTROLLERDEVICEREMOVED as u32,
timestamp,
which: which as i32,
};
unsafe {
ptr::copy(&event, ret.as_mut_ptr() as *mut sys::SDL_ControllerDeviceEvent, 1);
Some(ret.assume_init())
}
},
Event::ControllerDeviceRemapped{
timestamp,
which,
} => {
let event = sys::SDL_ControllerDeviceEvent {
type_: SDL_EventType::SDL_CONTROLLERDEVICEREMAPPED as u32,
timestamp,
which: which as i32,
};
unsafe {
ptr::copy(&event, ret.as_mut_ptr() as *mut sys::SDL_ControllerDeviceEvent, 1);
Some(ret.assume_init())
}
},
Event::FingerDown{..} |
Event::FingerUp{..} |
Event::FingerMotion{..} |
Event::DollarGesture{..} |
Event::DollarRecord{..} |
Event::MultiGesture{..} |
Event::ClipboardUpdate{..} |
Event::DropFile{..} |
Event::TextEditing{..} |
Event::TextInput{..} |
Event::Unknown{..} |
_ => {
None
}
}
}
fn from_ll(raw: sys::SDL_Event) -> Event {
let raw_type = unsafe { raw.type_ };
let event_type: EventType = EventType::try_from(raw_type as u32).unwrap_or(EventType::User);
unsafe { match event_type {
EventType::Quit => {
let event = raw.quit;
Event::Quit { timestamp: event.timestamp }
}
EventType::AppTerminating => {
let event = raw.common;
Event::AppTerminating { timestamp: event.timestamp }
}
EventType::AppLowMemory => {
let event = raw.common;
Event::AppLowMemory { timestamp: event.timestamp }
}
EventType::AppWillEnterBackground => {
let event = raw.common;
Event::AppWillEnterBackground { timestamp: event.timestamp }
}
EventType::AppDidEnterBackground => {
let event = raw.common;
Event::AppDidEnterBackground { timestamp: event.timestamp }
}
EventType::AppWillEnterForeground => {
let event = raw.common;
Event::AppWillEnterForeground { timestamp: event.timestamp }
}
EventType::AppDidEnterForeground => {
let event = raw.common;
Event::AppDidEnterForeground { timestamp: event.timestamp }
}
EventType::Window => {
let event = raw.window;
Event::Window {
timestamp: event.timestamp,
window_id: event.windowID,
win_event: WindowEvent::from_ll(event.event, event.data1, event.data2),
}
}
EventType::KeyDown => {
let event = raw.key;
Event::KeyDown {
timestamp: event.timestamp,
window_id: event.windowID,
keycode: Keycode::from_i32(event.keysym.sym as i32),
scancode: Scancode::from_i32(event.keysym.scancode as i32),
keymod: keyboard::Mod::from_bits_truncate(event.keysym.mod_),
repeat: event.repeat != 0
}
}
EventType::KeyUp => {
let event = raw.key;
Event::KeyUp {
timestamp: event.timestamp,
window_id: event.windowID,
keycode: Keycode::from_i32(event.keysym.sym as i32),
scancode: Scancode::from_i32(event.keysym.scancode as i32),
keymod: keyboard::Mod::from_bits_truncate(event.keysym.mod_),
repeat: event.repeat != 0
}
}
EventType::TextEditing => {
let event = raw.edit;
let text = String::from_utf8(
event.text.iter()
.take_while(|&b| (*b) != 0)
.map(|&b| b as u8)
.collect::<Vec<u8>>()
).expect("Invalid TextEditing string");
Event::TextEditing {
timestamp: event.timestamp,
window_id: event.windowID,
text,
start: event.start,
length: event.length
}
}
EventType::TextInput => {
let event = raw.text;
let text = String::from_utf8(
event.text.iter()
.take_while(|&b| (*b) != 0)
.map(|&b| b as u8)
.collect::<Vec<u8>>()
).expect("Invalid TextInput string");
Event::TextInput {
timestamp: event.timestamp,
window_id: event.windowID,
text
}
}
EventType::MouseMotion => {
let event = raw.motion;
Event::MouseMotion {
timestamp: event.timestamp,
window_id: event.windowID,
which: event.which as u32,
mousestate: mouse::MouseState::from_sdl_state(event.state),
x: event.x,
y: event.y,
xrel: event.xrel,
yrel: event.yrel
}
}
EventType::MouseButtonDown => {
let event = raw.button;
Event::MouseButtonDown {
timestamp: event.timestamp,
window_id: event.windowID,
which: event.which as u32,
mouse_btn: mouse::MouseButton::from_ll(event.button),
clicks: event.clicks,
x: event.x,
y: event.y
}
}
EventType::MouseButtonUp => {
let event = raw.button;
Event::MouseButtonUp {
timestamp: event.timestamp,
window_id: event.windowID,
which: event.which as u32,
mouse_btn: mouse::MouseButton::from_ll(event.button),
clicks: event.clicks,
x: event.x,
y: event.y
}
}
EventType::MouseWheel => {
let event = raw.wheel;
Event::MouseWheel {
timestamp: event.timestamp,
window_id: event.windowID,
which: event.which as u32,
x: event.x,
y: event.y,
direction: mouse::MouseWheelDirection::from_ll(event.direction),
}
}
EventType::JoyAxisMotion => {
let event = raw.jaxis;
Event::JoyAxisMotion {
timestamp: event.timestamp,
which: event.which as u32,
axis_idx: event.axis,
value: event.value
}
}
EventType::JoyBallMotion => {
let event = raw.jball;
Event::JoyBallMotion {
timestamp: event.timestamp,
which: event.which as u32,
ball_idx: event.ball,
xrel: event.xrel,
yrel: event.yrel
}
}
EventType::JoyHatMotion => {
let event = raw.jhat;
Event::JoyHatMotion {
timestamp: event.timestamp,
which: event.which as u32,
hat_idx: event.hat,
state: joystick::HatState::from_raw(event.value),
}
}
EventType::JoyButtonDown => {
let event = raw.jbutton;
Event::JoyButtonDown {
timestamp: event.timestamp,
which: event.which as u32,
button_idx: event.button
}
}
EventType::JoyButtonUp => {
let event = raw.jbutton;
Event::JoyButtonUp {
timestamp: event.timestamp,
which: event.which as u32,
button_idx: event.button
}
}
EventType::JoyDeviceAdded => {
let event = raw.jdevice;
Event::JoyDeviceAdded {
timestamp: event.timestamp,
which: event.which as u32,
}
}
EventType::JoyDeviceRemoved => {
let event = raw.jdevice;
Event::JoyDeviceRemoved {
timestamp: event.timestamp,
which: event.which as u32,
}
}
EventType::ControllerAxisMotion => {
let event = raw.caxis;
let axis = controller::Axis::from_ll(transmute(event.axis as i32)).unwrap();
Event::ControllerAxisMotion {
timestamp: event.timestamp,
which: event.which as u32,
axis,
value: event.value
}
}
EventType::ControllerButtonDown => {
let event = raw.cbutton;
let button = controller::Button::from_ll(transmute(event.button as i32)).unwrap();
Event::ControllerButtonDown {
timestamp: event.timestamp,
which: event.which as u32,
button
}
}
EventType::ControllerButtonUp => {
let event = raw.cbutton;
let button = controller::Button::from_ll(transmute(event.button as i32)).unwrap();
Event::ControllerButtonUp {
timestamp: event.timestamp,
which: event.which as u32,
button
}
}
EventType::ControllerDeviceAdded => {
let event = raw.cdevice;
Event::ControllerDeviceAdded {
timestamp: event.timestamp,
which: event.which as u32,
}
}
EventType::ControllerDeviceRemoved => {
let event = raw.cdevice;
Event::ControllerDeviceRemoved {
timestamp: event.timestamp,
which: event.which as u32,
}
}
EventType::ControllerDeviceRemapped => {
let event = raw.cdevice;
Event::ControllerDeviceRemapped {
timestamp: event.timestamp,
which: event.which as u32,
}
}
EventType::FingerDown => {
let event = raw.tfinger;
Event::FingerDown {
timestamp: event.timestamp,
touch_id: event.touchId,
finger_id: event.fingerId,
x: event.x,
y: event.y,
dx: event.dx,
dy: event.dy,
pressure: event.pressure
}
}
EventType::FingerUp => {
let event = raw.tfinger;
Event::FingerUp {
timestamp: event.timestamp,
touch_id: event.touchId,
finger_id: event.fingerId,
x: event.x,
y: event.y,
dx: event.dx,
dy: event.dy,
pressure: event.pressure
}
}
EventType::FingerMotion => {
let event = raw.tfinger;
Event::FingerMotion {
timestamp: event.timestamp,
touch_id: event.touchId,
finger_id: event.fingerId,
x: event.x,
y: event.y,
dx: event.dx,
dy: event.dy,
pressure: event.pressure
}
}
EventType::DollarGesture => {
let event = raw.dgesture;
Event::DollarGesture {
timestamp: event.timestamp,
touch_id: event.touchId,
gesture_id: event.gestureId,
num_fingers: event.numFingers,
error: event.error,
x: event.x,
y: event.y
}
}
EventType::DollarRecord => {
let event = raw.dgesture;
Event::DollarRecord {
timestamp: event.timestamp,
touch_id: event.touchId,
gesture_id: event.gestureId,
num_fingers: event.numFingers,
error: event.error,
x: event.x,
y: event.y
}
}
EventType::MultiGesture => {
let event = raw.mgesture;
Event::MultiGesture {
timestamp: event.timestamp,
touch_id: event.touchId,
d_theta: event.dTheta,
d_dist: event.dDist,
x: event.x,
y: event.y,
num_fingers: event.numFingers
}
}
EventType::ClipboardUpdate => {
let event = raw.common;
Event::ClipboardUpdate {
timestamp: event.timestamp
}
}
EventType::DropFile => {
let event = raw.drop;
let buf = CStr::from_ptr(event.file as *const _).to_bytes();
let text = String::from_utf8_lossy(buf).to_string();
sys::SDL_free(event.file as *mut c_void);
Event::DropFile {
timestamp: event.timestamp,
window_id: event.windowID,
filename: text
}
},
EventType::DropText => {
let event = raw.drop;
let buf = CStr::from_ptr(event.file as *const _).to_bytes();
let text = String::from_utf8_lossy(buf).to_string();
sys::SDL_free(event.file as *mut c_void);
Event::DropText {
timestamp: event.timestamp,
window_id: event.windowID,
filename: text
}
},
EventType::DropBegin => {
let event = raw.drop;
Event::DropBegin {
timestamp: event.timestamp,
window_id: event.windowID,
}
},
EventType::DropComplete => {
let event = raw.drop;
Event::DropComplete {
timestamp: event.timestamp,
window_id: event.windowID,
}
},
EventType::AudioDeviceAdded => {
let event = raw.adevice;
Event::AudioDeviceAdded {
timestamp: event.timestamp,
which: event.which,
iscapture: event.iscapture != 0,
}
},
EventType::AudioDeviceRemoved => {
let event = raw.adevice;
Event::AudioDeviceRemoved {
timestamp: event.timestamp,
which: event.which,
iscapture: event.iscapture != 0,
}
},
EventType::RenderTargetsReset => {
Event::RenderTargetsReset {
timestamp: raw.common.timestamp
}
},
EventType::RenderDeviceReset => {
Event::RenderDeviceReset {
timestamp: raw.common.timestamp
}
},
EventType::First => panic!("Unused event, EventType::First, was encountered"),
EventType::Last => panic!("Unusable event, EventType::Last, was encountered"),
EventType::User => {
if raw_type < 32_768 {
let event = raw.common;
Event::Unknown {
timestamp: event.timestamp,
type_: event.type_
}
} else {
let event = raw.user;
Event::User {
timestamp: event.timestamp,
window_id: event.windowID,
type_: raw_type,
code: event.code,
data1: event.data1,
data2: event.data2
}
}
}
}}
}
fn unwrap_keymod(keymod_option: Option<keyboard::Mod>) -> keyboard::Mod {
match keymod_option {
None => keyboard::Mod::empty(),
Some(x) => x,
}
}
pub fn is_user_event(&self) -> bool {
match *self {
Event::User { .. } => true,
_ => false
}
}
pub fn as_user_event_type<T: ::std::any::Any>(&self) -> Option<T> {
use ::std::any::TypeId;
let type_id = TypeId::of::<Box<T>>();
let (event_id, event_box_ptr) = match *self {
Event::User { type_, data1, .. } => { (type_, data1) },
_ => { return None }
};
let cet = CUSTOM_EVENT_TYPES.lock().unwrap();
let event_type_id = match cet.sdl_id_to_type_id.get(&event_id) {
Some(id) => id,
None => { panic!("internal error; could not find typeid") }
};
if &type_id != event_type_id {
return None;
}
let event_box : Box<T> = unsafe { Box::from_raw(event_box_ptr as *mut T) };
Some(*event_box)
}
pub fn is_same_kind_as(&self, other: &Event) -> bool {
match (self, other) {
(Self::Quit { .. }, Self::Quit { .. })
| (Self::AppTerminating { .. }, Self::AppTerminating { .. })
| (Self::AppLowMemory { .. }, Self::AppLowMemory { .. })
| (Self::AppWillEnterBackground { .. }, Self::AppWillEnterBackground { .. })
| (Self::AppDidEnterBackground { .. }, Self::AppDidEnterBackground { .. })
| (Self::AppWillEnterForeground { .. }, Self::AppWillEnterForeground { .. })
| (Self::AppDidEnterForeground { .. }, Self::AppDidEnterForeground { .. })
| (Self::Window { .. }, Self::Window { .. })
| (Self::KeyDown { .. }, Self::KeyDown { .. })
| (Self::KeyUp { .. }, Self::KeyUp { .. })
| (Self::TextEditing { .. }, Self::TextEditing { .. })
| (Self::TextInput { .. }, Self::TextInput { .. })
| (Self::MouseMotion { .. }, Self::MouseMotion { .. })
| (Self::MouseButtonDown { .. }, Self::MouseButtonDown { .. })
| (Self::MouseButtonUp { .. }, Self::MouseButtonUp { .. })
| (Self::MouseWheel { .. }, Self::MouseWheel { .. })
| (Self::JoyAxisMotion { .. }, Self::JoyAxisMotion { .. })
| (Self::JoyBallMotion { .. }, Self::JoyBallMotion { .. })
| (Self::JoyHatMotion { .. }, Self::JoyHatMotion { .. })
| (Self::JoyButtonDown { .. }, Self::JoyButtonDown { .. })
| (Self::JoyButtonUp { .. }, Self::JoyButtonUp { .. })
| (Self::JoyDeviceAdded { .. }, Self::JoyDeviceAdded { .. })
| (Self::JoyDeviceRemoved { .. }, Self::JoyDeviceRemoved { .. })
| (Self::ControllerAxisMotion { .. }, Self::ControllerAxisMotion { .. })
| (Self::ControllerButtonDown { .. }, Self::ControllerButtonDown { .. })
| (Self::ControllerButtonUp { .. }, Self::ControllerButtonUp { .. })
| (Self::ControllerDeviceAdded { .. }, Self::ControllerDeviceAdded { .. })
| (Self::ControllerDeviceRemoved { .. }, Self::ControllerDeviceRemoved { .. })
| (Self::ControllerDeviceRemapped { .. }, Self::ControllerDeviceRemapped { .. })
| (Self::FingerDown { .. }, Self::FingerDown { .. })
| (Self::FingerUp { .. }, Self::FingerUp { .. })
| (Self::FingerMotion { .. }, Self::FingerMotion { .. })
| (Self::DollarGesture { .. }, Self::DollarGesture { .. })
| (Self::DollarRecord { .. }, Self::DollarRecord { .. })
| (Self::MultiGesture { .. }, Self::MultiGesture { .. })
| (Self::ClipboardUpdate { .. }, Self::ClipboardUpdate { .. })
| (Self::DropFile { .. }, Self::DropFile { .. })
| (Self::DropText { .. }, Self::DropText { .. })
| (Self::DropBegin { .. }, Self::DropBegin { .. })
| (Self::DropComplete { .. }, Self::DropComplete { .. })
| (Self::AudioDeviceAdded { .. }, Self::AudioDeviceAdded { .. })
| (Self::AudioDeviceRemoved { .. }, Self::AudioDeviceRemoved { .. })
| (Self::RenderTargetsReset { .. }, Self::RenderTargetsReset { .. })
| (Self::RenderDeviceReset { .. }, Self::RenderDeviceReset { .. })
| (Self::User { .. }, Self::User { .. })
| (Self::Unknown { .. }, Self::Unknown { .. }) => true,
_ => false,
}
}
pub fn get_timestamp(&self) -> u32 {
*match self {
Self::Quit { timestamp, .. } => timestamp,
Self::AppTerminating { timestamp, .. } => timestamp,
Self::AppLowMemory { timestamp, .. } => timestamp,
Self::AppWillEnterBackground { timestamp, .. } => timestamp,
Self::AppDidEnterBackground { timestamp, .. } => timestamp,
Self::AppWillEnterForeground { timestamp, .. } => timestamp,
Self::AppDidEnterForeground { timestamp, .. } => timestamp,
Self::Window { timestamp, .. } => timestamp,
Self::KeyDown { timestamp, .. } => timestamp,
Self::KeyUp { timestamp, .. } => timestamp,
Self::TextEditing { timestamp, .. } => timestamp,
Self::TextInput { timestamp, .. } => timestamp,
Self::MouseMotion { timestamp, .. } => timestamp,
Self::MouseButtonDown { timestamp, .. } => timestamp,
Self::MouseButtonUp { timestamp, .. } => timestamp,
Self::MouseWheel { timestamp, .. } => timestamp,
Self::JoyAxisMotion { timestamp, .. } => timestamp,
Self::JoyBallMotion { timestamp, .. } => timestamp,
Self::JoyHatMotion { timestamp, .. } => timestamp,
Self::JoyButtonDown { timestamp, .. } => timestamp,
Self::JoyButtonUp { timestamp, .. } => timestamp,
Self::JoyDeviceAdded { timestamp, .. } => timestamp,
Self::JoyDeviceRemoved { timestamp, .. } => timestamp,
Self::ControllerAxisMotion { timestamp, .. } => timestamp,
Self::ControllerButtonDown { timestamp, .. } => timestamp,
Self::ControllerButtonUp { timestamp, .. } => timestamp,
Self::ControllerDeviceAdded { timestamp, .. } => timestamp,
Self::ControllerDeviceRemoved { timestamp, .. } => timestamp,
Self::ControllerDeviceRemapped { timestamp, .. } => timestamp,
Self::FingerDown { timestamp, .. } => timestamp,
Self::FingerUp { timestamp, .. } => timestamp,
Self::FingerMotion { timestamp, .. } => timestamp,
Self::DollarGesture { timestamp, .. } => timestamp,
Self::DollarRecord { timestamp, .. } => timestamp,
Self::MultiGesture { timestamp, .. } => timestamp,
Self::ClipboardUpdate { timestamp, .. } => timestamp,
Self::DropFile { timestamp, .. } => timestamp,
Self::DropText { timestamp, .. } => timestamp,
Self::DropBegin { timestamp, .. } => timestamp,
Self::DropComplete { timestamp, .. } => timestamp,
Self::AudioDeviceAdded { timestamp, .. } => timestamp,
Self::AudioDeviceRemoved { timestamp, .. } => timestamp,
Self::RenderTargetsReset { timestamp, .. } => timestamp,
Self::RenderDeviceReset { timestamp, .. } => timestamp,
Self::User { timestamp, .. } => timestamp,
Self::Unknown { timestamp, .. } => timestamp,
}
}
pub fn get_window_id(&self) -> Option<u32> {
match self {
Self::Window { window_id, .. } => Some(*window_id),
Self::KeyDown { window_id, .. } => Some(*window_id),
Self::KeyUp { window_id, .. } => Some(*window_id),
Self::TextEditing { window_id, .. } => Some(*window_id),
Self::TextInput { window_id, .. } => Some(*window_id),
Self::MouseMotion { window_id, .. } => Some(*window_id),
Self::MouseButtonDown { window_id, .. } => Some(*window_id),
Self::MouseButtonUp { window_id, .. } => Some(*window_id),
Self::MouseWheel { window_id, .. } => Some(*window_id),
Self::DropFile { window_id, .. } => Some(*window_id),
Self::DropText { window_id, .. } => Some(*window_id),
Self::DropBegin { window_id, .. } => Some(*window_id),
Self::DropComplete { window_id, .. } => Some(*window_id),
Self::User { window_id, .. } => Some(*window_id),
_ => None,
}
}
pub fn is_window(&self) -> bool {
match self {
Self::Quit { .. }
| Self::AppTerminating { .. }
| Self::AppLowMemory { .. }
| Self::AppWillEnterBackground { .. }
| Self::AppDidEnterBackground { .. }
| Self::AppWillEnterForeground { .. }
| Self::AppDidEnterForeground { .. }
| Self::Window { .. } => true,
_ => false,
}
}
pub fn is_keyboard(&self) -> bool {
match self {
Self::KeyDown { .. }
| Self::KeyUp { .. } => true,
_ => false,
}
}
pub fn is_text(&self) -> bool {
match self {
Self::TextEditing { .. }
| Self::TextInput { .. } => true,
_ => false,
}
}
pub fn is_mouse(&self) -> bool {
match self {
Self::MouseMotion { .. }
| Self::MouseButtonDown { .. }
| Self::MouseButtonUp { .. }
| Self::MouseWheel { .. } => true,
_ => false,
}
}
pub fn is_controller(&self) -> bool {
match self {
Self::ControllerAxisMotion { .. }
| Self::ControllerButtonDown { .. }
| Self::ControllerButtonUp { .. }
| Self::ControllerDeviceAdded { .. }
| Self::ControllerDeviceRemoved { .. }
| Self::ControllerDeviceRemapped { .. } => true,
_ => false,
}
}
pub fn is_joy(&self) -> bool {
match self {
Self::JoyAxisMotion { .. }
| Self::JoyBallMotion { .. }
| Self::JoyHatMotion { .. }
| Self::JoyButtonDown { .. }
| Self::JoyButtonUp { .. }
| Self::JoyDeviceAdded { .. }
| Self::JoyDeviceRemoved { .. } => true,
_ => false,
}
}
pub fn is_finger(&self) -> bool {
match self {
Self::FingerDown { .. }
| Self::FingerUp { .. }
| Self::FingerMotion { .. } => true,
_ => false,
}
}
pub fn is_dollar(&self) -> bool {
match self {
Self::DollarGesture { .. }
| Self::DollarRecord { .. } => true,
_ => false,
}
}
pub fn is_drop(&self) -> bool {
match self {
Self::DropFile { .. }
| Self::DropText { .. }
| Self::DropBegin { .. }
| Self::DropComplete { .. } => true,
_ => false,
}
}
pub fn is_audio(&self) -> bool {
match self {
Self::AudioDeviceAdded { .. }
| Self::AudioDeviceRemoved { .. } => true,
_ => false,
}
}
pub fn is_render(&self) -> bool {
match self {
Self::RenderTargetsReset { .. }
| Self::RenderDeviceReset { .. } => true,
_ => false,
}
}
pub fn is_user(&self) -> bool {
match self {
Self::User { .. } => true,
_ => false,
}
}
pub fn is_unknown(&self) -> bool {
match self {
Self::Unknown { .. } => true,
_ => false,
}
}
}
unsafe fn poll_event() -> Option<Event> {
let mut raw = mem::MaybeUninit::uninit();
let has_pending = sys::SDL_PollEvent(raw.as_mut_ptr()) == 1;
if has_pending { Some(Event::from_ll(raw.assume_init())) }
else { None }
}
unsafe fn wait_event() -> Event {
let mut raw = mem::MaybeUninit::uninit();
let success = sys::SDL_WaitEvent(raw.as_mut_ptr()) == 1;
if success { Event::from_ll(raw.assume_init()) }
else { panic!(get_error()) }
}
unsafe fn wait_event_timeout(timeout: u32) -> Option<Event> {
let mut raw = mem::MaybeUninit::uninit();
let success = sys::SDL_WaitEventTimeout(raw.as_mut_ptr(), timeout as c_int) == 1;
if success { Some(Event::from_ll(raw.assume_init())) }
else { None }
}
impl crate::EventPump {
pub fn is_event_enabled(&self, event_type: EventType) -> bool {
let result = unsafe { sys::SDL_EventState(event_type as u32, sys::SDL_QUERY) };
result != sys::SDL_DISABLE as u8
}
pub fn enable_event(&mut self, event_type: EventType) -> bool {
let result = unsafe { sys::SDL_EventState(event_type as u32, sys::SDL_ENABLE as c_int) };
result != sys::SDL_DISABLE as u8
}
pub fn disable_event(&mut self, event_type: EventType) -> bool {
let result = unsafe { sys::SDL_EventState(event_type as u32, sys::SDL_DISABLE as c_int) };
result != sys::SDL_DISABLE as u8
}
pub fn poll_event(&mut self) -> Option<Event> {
unsafe { poll_event() }
}
pub fn poll_iter(&mut self) -> EventPollIterator {
EventPollIterator {
_marker: PhantomData
}
}
pub fn pump_events(&mut self) {
unsafe { sys::SDL_PumpEvents(); };
}
pub fn wait_event(&mut self) -> Event {
unsafe { wait_event() }
}
pub fn wait_event_timeout(&mut self, timeout: u32) -> Option<Event> {
unsafe { wait_event_timeout(timeout) }
}
pub fn wait_iter(&mut self) -> EventWaitIterator {
EventWaitIterator {
_marker: PhantomData
}
}
pub fn wait_timeout_iter(&mut self, timeout: u32) -> EventWaitTimeoutIterator {
EventWaitTimeoutIterator {
_marker: PhantomData,
timeout
}
}
#[inline]
pub fn keyboard_state(&self) -> crate::keyboard::KeyboardState {
crate::keyboard::KeyboardState::new(self)
}
#[inline]
pub fn mouse_state(&self) -> crate::mouse::MouseState {
crate::mouse::MouseState::new(self)
}
#[inline]
pub fn relative_mouse_state(&self) -> crate::mouse::RelativeMouseState {
crate::mouse::RelativeMouseState::new(self)
}
}
#[must_use = "iterators are lazy and do nothing unless consumed"]
pub struct EventPollIterator<'a> {
_marker: PhantomData<&'a ()>
}
impl<'a> Iterator for EventPollIterator<'a> {
type Item = Event;
fn next(&mut self) -> Option<Event> { unsafe { poll_event() } }
}
#[must_use = "iterators are lazy and do nothing unless consumed"]
pub struct EventWaitIterator<'a> {
_marker: PhantomData<&'a ()>
}
impl<'a> Iterator for EventWaitIterator<'a> {
type Item = Event;
fn next(&mut self) -> Option<Event> { unsafe { Some(wait_event()) } }
}
#[must_use = "iterators are lazy and do nothing unless consumed"]
pub struct EventWaitTimeoutIterator<'a> {
_marker: PhantomData<&'a ()>,
timeout: u32
}
impl<'a> Iterator for EventWaitTimeoutIterator<'a> {
type Item = Event;
fn next(&mut self) -> Option<Event> { unsafe { wait_event_timeout(self.timeout) } }
}
#[cfg(test)]
mod test {
use super::Event;
use super::WindowEvent;
use super::super::controller::{Button, Axis};
use super::super::joystick::{HatState};
use super::super::mouse::{MouseButton, MouseState, MouseWheelDirection};
use super::super::keyboard::{Keycode, Scancode, Mod};
#[test]
fn test_to_from_ll() {
{
let e = Event::Quit{timestamp: 0};
let e2 = Event::from_ll(e.clone().to_ll().unwrap());
assert_eq!(e, e2);
}
{
let e = Event::Window{
timestamp: 0,
window_id: 0,
win_event: WindowEvent::Resized(1, 2),
};
let e2 = Event::from_ll(e.clone().to_ll().unwrap());
assert_eq!(e, e2);
}
{
let e = Event::KeyDown{
timestamp: 0,
window_id: 1,
keycode: None,
scancode: Some(Scancode::Q),
keymod: Mod::all(),
repeat: false,
};
let e2 = Event::from_ll(e.clone().to_ll().unwrap());
assert_eq!(e, e2);
}
{
let e = Event::KeyUp{
timestamp: 123,
window_id: 0,
keycode: Some(Keycode::R),
scancode: Some(Scancode::R),
keymod: Mod::empty(),
repeat: true,
};
let e2 = Event::from_ll(e.clone().to_ll().unwrap());
assert_eq!(e, e2);
}
{
let e = Event::MouseMotion{
timestamp: 0,
window_id: 0,
which: 1,
mousestate: MouseState::from_sdl_state(1),
x: 3,
y: 91,
xrel: -1,
yrel: 43,
};
let e2 = Event::from_ll(e.clone().to_ll().unwrap());
assert_eq!(e, e2);
}
{
let e = Event::MouseButtonDown{
timestamp: 5634,
window_id: 2,
which: 0,
mouse_btn: MouseButton::Left,
clicks: 1,
x: 543,
y: 345,
};
let e2 = Event::from_ll(e.clone().to_ll().unwrap());
assert_eq!(e, e2);
}
{
let e = Event::MouseButtonUp{
timestamp: 0,
window_id: 2,
which: 0,
mouse_btn: MouseButton::Left,
clicks: 1,
x: 543,
y: 345,
};
let e2 = Event::from_ll(e.clone().to_ll().unwrap());
assert_eq!(e, e2);
}
{
let e = Event::MouseWheel{
timestamp: 1,
window_id: 0,
which: 32,
x: 23,
y: 91,
direction: MouseWheelDirection::Flipped,
};
let e2 = Event::from_ll(e.clone().to_ll().unwrap());
assert_eq!(e, e2);
}
{
let e = Event::JoyAxisMotion{
timestamp: 0,
which: 1,
axis_idx: 1,
value: 12,
};
let e2 = Event::from_ll(e.clone().to_ll().unwrap());
assert_eq!(e, e2);
}
{
let e = Event::JoyBallMotion{
timestamp: 0,
which: 0,
ball_idx: 1,
xrel: 123,
yrel: 321,
};
let e2 = Event::from_ll(e.clone().to_ll().unwrap());
assert_eq!(e, e2);
}
{
let e = Event::JoyHatMotion{
timestamp: 0,
which: 3,
hat_idx: 1,
state: HatState::Left,
};
let e2 = Event::from_ll(e.clone().to_ll().unwrap());
assert_eq!(e, e2);
}
{
let e = Event::JoyButtonDown{
timestamp: 0,
which: 0,
button_idx: 3
};
let e2 = Event::from_ll(e.clone().to_ll().unwrap());
assert_eq!(e, e2);
}
{
let e = Event::JoyButtonUp{
timestamp: 9876,
which: 1,
button_idx: 2,
};
let e2 = Event::from_ll(e.clone().to_ll().unwrap());
assert_eq!(e, e2);
}
{
let e = Event::JoyDeviceAdded{
timestamp: 0,
which: 1
};
let e2 = Event::from_ll(e.clone().to_ll().unwrap());
assert_eq!(e, e2);
}
{
let e = Event::JoyDeviceRemoved{
timestamp: 0,
which: 2,
};
let e2 = Event::from_ll(e.clone().to_ll().unwrap());
assert_eq!(e, e2);
}
{
let e = Event::ControllerAxisMotion{
timestamp: 53,
which: 0,
axis: Axis::LeftX,
value: 3
};
let e2 = Event::from_ll(e.clone().to_ll().unwrap());
assert_eq!(e, e2);
}
{
let e = Event::ControllerButtonDown{
timestamp: 0,
which: 1,
button: Button::Guide,
};
let e2 = Event::from_ll(e.clone().to_ll().unwrap());
assert_eq!(e, e2);
}
{
let e = Event::ControllerButtonUp{
timestamp: 654214,
which: 0,
button: Button::DPadRight,
};
let e2 = Event::from_ll(e.clone().to_ll().unwrap());
assert_eq!(e, e2);
}
{
let e = Event::ControllerDeviceAdded{
timestamp: 543,
which: 3
};
let e2 = Event::from_ll(e.clone().to_ll().unwrap());
assert_eq!(e, e2);
}
{
let e = Event::ControllerDeviceRemoved{
timestamp: 555,
which: 3
};
let e2 = Event::from_ll(e.clone().to_ll().unwrap());
assert_eq!(e, e2);
}
{
let e = Event::ControllerDeviceRemapped{
timestamp: 654,
which: 0
};
let e2 = Event::from_ll(e.clone().to_ll().unwrap());
assert_eq!(e, e2);
}
}
#[test]
fn test_from_ll_keymod_keydown_unknown_bits() {
let mut raw_event = Event::KeyDown {
timestamp: 0,
window_id: 1,
keycode: None,
scancode: Some(Scancode::Q),
keymod: Mod::empty(),
repeat: false,
}.to_ll().unwrap();
raw_event.key.keysym.mod_ = 0xffff;
if let Event::KeyDown { keymod, .. } = Event::from_ll(raw_event) {
assert_eq!(keymod, Mod::all());
} else {
panic!()
}
}
#[test]
fn test_from_ll_keymod_keyup_unknown_bits() {
let mut raw_event = Event::KeyUp {
timestamp: 0,
window_id: 1,
keycode: None,
scancode: Some(Scancode::Q),
keymod: Mod::empty(),
repeat: false,
}.to_ll().unwrap();
raw_event.key.keysym.mod_ = 0xffff;
if let Event::KeyUp { keymod, .. } = Event::from_ll(raw_event) {
assert_eq!(keymod, Mod::all());
} else {
panic!()
}
}
}
pub struct EventSender {
_priv: (),
}
impl EventSender {
pub fn push_event(&self, event: Event) -> Result<(), String> {
match event.to_ll() {
Some(mut raw_event) => {
let ok = unsafe { sys::SDL_PushEvent(&mut raw_event) == 1 };
if ok { Ok(()) }
else { Err(get_error()) }
},
None => {
Err("Cannot push unsupported event type to the queue".to_owned())
}
}
}
pub fn push_custom_event<T: ::std::any::Any>(&self, event:T)
-> Result<(), String> {
use ::std::any::TypeId;
let cet = CUSTOM_EVENT_TYPES.lock().unwrap();
let type_id = TypeId::of::<Box<T>>();
let user_event_id = *match cet.type_id_to_sdl_id.get(&type_id) {
Some(id) => id,
None => {
return Err(
"Type is not registered as a custom event type!".to_owned()
);
}
};
let event_box = Box::new(event);
let event = Event::User {
timestamp: 0,
window_id: 0,
type_: user_event_id,
code: 0,
data1: Box::into_raw(event_box) as *mut c_void,
data2: ::std::ptr::null_mut()
};
self.push_event(event)?;
Ok(())
}
}