Update error/rect fork with the changes from the event pull request on master.

This commit is contained in:
Machtan
2016-02-11 20:28:50 +01:00
5 changed files with 283 additions and 10 deletions
+7 -1
View File
@@ -4,7 +4,7 @@ name = "sdl2"
description = "SDL2 bindings for Rust"
repository = "https://github.com/AngryLawyer/rust-sdl2"
documentation = "http://angrylawyer.github.io/rust-sdl2/sdl2/"
version = "0.13.0"
version = "0.14.0"
license = "MIT"
authors = [ "Tony Aldridge <tony@angry-lawyer.com>" ]
keywords = ["SDL", "windowing", "graphics"]
@@ -14,11 +14,17 @@ keywords = ["SDL", "windowing", "graphics"]
name = "sdl2"
path = "src/sdl2/lib.rs"
[[test]]
name="events"
harness=false
[dependencies]
num = "0.1"
bitflags = "0.3"
libc = "0.2"
rand = "0.3"
lazy_static="0.1"
[dependencies.sdl2-sys]
+1 -1
View File
@@ -98,7 +98,7 @@ download through Crates.io:
```toml
[dependencies]
sdl2 = "0.12"
sdl2 = "0.14"
```
Alternatively, pull it from GitHub
+190 -7
View File
@@ -10,6 +10,8 @@ use std::ptr;
use std::borrow::ToOwned;
use std::iter::FromIterator;
use std::marker::PhantomData;
use std::collections::HashMap;
use std::sync::Mutex;
use controller;
use controller::{Axis, Button};
@@ -26,6 +28,24 @@ use get_error;
use sys::event as ll;
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 ::EventSubsystem {
/// Removes all events in the event queue that match the specified event type.
pub fn flush_event(&self, event_type: EventType) {
@@ -101,6 +121,133 @@ impl ::EventSubsystem {
}
}
}
/// Register a custom SDL event.
///
/// When pushing a user event, you must make sure that the ``type_`` field is set to a
/// registered SDL event number.
///
/// The ``code``, ``data1``, and ``data2`` fields can be used to store user defined data.
///
/// See the [SDL documentation](https://wiki.libsdl.org/SDL_UserEvent) for more information.
///
/// # Example
/// ```
/// let sdl = sdl2::init().unwrap();
/// let ev = sdl.event().unwrap();
///
/// let custom_event_type_id = unsafe { ev.register_event().unwrap() };
/// let event = sdl2::event::Event::User {
/// timestamp: 0,
/// window_id: 0,
/// type_: custom_event_type_id,
/// code: 456,
/// data1: 0x1234 as *mut ::sdl2::libc::c_void,
/// data2: 0x5678 as *mut ::sdl2::libc::c_void,
/// };
///
/// ev.push_event(event);
///
/// ```
#[inline(always)]
pub unsafe fn register_event(&self) -> SdlResult<u32> {
Ok(*try!(self.register_events(1)).first().unwrap())
}
/// Registers custom SDL events.
///
/// Returns an error, if no more user events can be created.
pub unsafe fn register_events(&self, nr: u32) -> SdlResult<Vec<u32>> {
let result = unsafe { ll::SDL_RegisterEvents(nr as ::libc::c_int) };
const ERR_NR:u32 = ::std::u32::MAX - 1;
match result {
ERR_NR => { Err(ErrorMessage("No more user events can be created; SDL_LASTEVENT reached".to_owned())) },
_ => {
let event_ids = (result..(result+nr)).collect();
Ok(event_ids)
}
}
}
/// Register a custom event
///
/// It returns an error when the same type is registered twice.
///
/// # Example
/// See [push_custom_event](#method.push_custom_event)
#[inline(always)]
pub fn register_custom_event<T: ::std::any::Any>(&self) -> SdlResult<()> {
use ::std::any::TypeId;
let event_id = *try!(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(ErrorMessage("Can not register the same event type twice!".into()));
}
cet.sdl_id_to_type_id.insert(event_id, type_id);
cet.type_id_to_sdl_id.insert(type_id, event_id);
Ok(())
}
/// Push a custom event
///
/// If the event type ``T`` was not registered using
/// [register_custom_event](#method.register_custom_event),
/// this method will panic.
///
/// # Example: pushing and receiving a custom event
/// ```
/// struct SomeCustomEvent {
/// a: i32
/// }
///
/// let sdl = sdl2::init().unwrap();
/// let ev = sdl.event().unwrap();
/// let mut ep = sdl.event_pump().unwrap();
///
/// ev.register_custom_event::<SomeCustomEvent>().unwrap();
///
/// let event = SomeCustomEvent { a: 42 };
///
/// ev.push_custom_event(event);
///
/// let received = ep.poll_event().unwrap(); // or within a for event in ep.poll_iter()
/// if received.is_user_event() {
/// let e2 = received.as_user_event_type::<SomeCustomEvent>().unwrap();
/// assert_eq!(e2.a, 42);
/// }
/// ```
pub fn push_custom_event<T: ::std::any::Any>(&self, event:T) -> SdlResult<()> {
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(ErrorMessage("Type is not registered as a custom event type!".into())); }
};
let event_box = Box::new(event);
let type_id_box = Box::new(type_id);
let event = Event::User {
timestamp: 0,
window_id: 0,
type_: user_event_id,
code: 0,
data1: Box::into_raw(event_box) as *mut ::libc::c_void,
data2: ::std::ptr::null_mut()
};
self.push_event(event);
Ok(())
}
}
/// Types of events that can be delivered.
@@ -496,7 +643,9 @@ pub enum Event {
timestamp: u32,
window_id: u32,
type_: u32,
code: i32
code: i32,
data1: *mut c_void,
data2: *mut c_void
},
Unknown {
@@ -556,15 +705,14 @@ impl Event {
fn to_ll(self) -> Option<ll::SDL_Event> {
let mut ret = unsafe { mem::uninitialized() };
match self {
// just ignore timestamp
Event::User { window_id, type_, code, .. } => {
Event::User { window_id, type_, code, data1, data2, timestamp} => {
let event = ll::SDL_UserEvent {
type_: type_ as uint32_t,
timestamp: 0,
timestamp: timestamp,
windowID: window_id,
code: code as i32,
data1: ptr::null_mut(),
data2: ptr::null_mut(),
data1: data1,
data2: data2
};
unsafe {
ptr::copy(&event, &mut ret as *mut ll::SDL_Event as *mut ll::SDL_UserEvent, 1);
@@ -967,12 +1115,46 @@ impl Event {
timestamp: event.timestamp,
window_id: event.windowID,
type_: raw_type,
code: event.code
code: event.code,
data1: event.data1,
data2: event.data2
}
}
}
}} // close unsafe & match
}
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 mut 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)
}
}
unsafe fn poll_event() -> Option<Event> {
@@ -1125,3 +1307,4 @@ impl<'a> Iterator for EventWaitTimeoutIterator<'a> {
type Item = Event;
fn next(&mut self) -> Option<Event> { unsafe { wait_event_timeout(self.timeout) } }
}
+6 -1
View File
@@ -2,7 +2,12 @@
#![crate_type = "lib"]
extern crate num;
extern crate libc;
extern crate libc as libc_crate;
pub use libc_crate as libc;
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate bitflags;
extern crate sdl2_sys as sys;
+79
View File
@@ -0,0 +1,79 @@
extern crate sdl2;
use sdl2::event;
fn main() {
let sdl = sdl2::init().unwrap();
let ev = sdl.event().unwrap();
let mut ep = sdl.event_pump().unwrap();
test1(&ev);
test2(&ev, &mut ep);
test3(&ev);
test4(&ev, &mut ep);
}
fn test1(ev: &sdl2::EventSubsystem) {
let user_event1_id = unsafe { ev.register_event().unwrap() };
let user_event2_id = unsafe { ev.register_event().unwrap() };
assert!(user_event1_id != user_event2_id);
}
fn test2(ev: &sdl2::EventSubsystem, ep: &mut sdl2::EventPump) {
let user_event_id = unsafe { ev.register_event().unwrap() };
let event = event::Event::User {
timestamp: 0,
window_id: 0,
type_: user_event_id,
code: 456,
data1: 0x1234 as *mut ::sdl2::libc::c_void,
data2: 0x5678 as *mut ::sdl2::libc::c_void,
};
let (t1, a1, a2) = match event {
event::Event::User { type_: t1, data1: a1, data2: a2, .. } => { (t1, a1, a2) }
_ => { panic!("expected user event") }
};
ev.push_event(event.clone()).unwrap();
let received = ep.poll_event().unwrap();
assert_eq!(&event, &received);
match &received {
&event::Event::User { type_: t2, data1: b1, data2: b2, .. } => {
assert_eq!(t1, t2);
assert_eq!(a1, b1);
assert_eq!(a2, b2);
}
other => { panic!("Received non User event: {:?}", other) }
}
}
struct SomeEventType_test3 {
a: u32
}
struct SomeOtherEventType_test3 {
b: u32
}
fn test3(ev: &sdl2::EventSubsystem) {
ev.register_custom_event::<SomeEventType_test3>().unwrap();
ev.register_custom_event::<SomeOtherEventType_test3>().unwrap();
assert!(ev.register_custom_event::<SomeEventType_test3>().is_err());
}
struct SomeEventType_test4 {
a: u32
}
fn test4(ev: &sdl2::EventSubsystem, ep: &mut sdl2::EventPump) {
ev.register_custom_event::<SomeEventType_test4>().unwrap();
let event = SomeEventType_test4 { a: 42 };
ev.push_custom_event(event);
let received = ep.poll_event().unwrap();
if received.is_user_event() {
let e2 = received.as_user_event_type::<SomeEventType_test4>().unwrap();
assert_eq!(e2.a, 42);
}
}