mirror of
https://github.com/encounter/rust-sdl2.git
synced 2026-07-10 21:18:41 -07:00
Merge pull request #915 from kosyak/event-sender
EventSubsystem::push_event should be callable from non-main threads.
This commit is contained in:
+93
-35
@@ -112,16 +112,7 @@ impl crate::EventSubsystem {
|
||||
|
||||
/// Pushes an event to the event queue.
|
||||
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())
|
||||
}
|
||||
}
|
||||
self.event_sender().push_event(event)
|
||||
}
|
||||
|
||||
|
||||
@@ -232,32 +223,17 @@ impl crate::EventSubsystem {
|
||||
/// ```
|
||||
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>>();
|
||||
self.event_sender().push_custom_event(event)
|
||||
}
|
||||
|
||||
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()
|
||||
};
|
||||
|
||||
r#try!(self.push_event(event));
|
||||
|
||||
Ok(())
|
||||
/// Create an event sender that can be sent to other threads.
|
||||
///
|
||||
/// An `EventSender` will not keep the event subsystem alive. If the event subsystem is
|
||||
/// shut down calls to `push_event` and `push_custom_event` will return errors.
|
||||
pub fn event_sender(&self) -> EventSender {
|
||||
EventSender {
|
||||
_priv: (),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2046,3 +2022,85 @@ mod test {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/// A sendible type that can push events to the event queue.
|
||||
pub struct EventSender {
|
||||
_priv: (),
|
||||
}
|
||||
|
||||
impl EventSender {
|
||||
/// Pushes an event to the event queue.
|
||||
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())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Push a custom event
|
||||
///
|
||||
/// If the event type ``T`` was not registered using
|
||||
/// [EventSubsystem::register_custom_event]
|
||||
/// (../struct.EventSubsystem.html#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)
|
||||
-> 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()
|
||||
};
|
||||
|
||||
r#try!(self.push_event(event));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
extern crate sdl2;
|
||||
|
||||
use sdl2::event;
|
||||
|
||||
#[test]
|
||||
@@ -98,3 +99,25 @@ fn test4(ev: &sdl2::EventSubsystem, ep: &mut sdl2::EventPump) {
|
||||
assert_eq!(e2.a, 42);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_event_sender_no_subsystem() {
|
||||
let sdl = sdl2::init().unwrap();
|
||||
let ev = sdl.event().unwrap();
|
||||
let tx = ev.event_sender();
|
||||
|
||||
assert!(tx.push_event(sdl2::event::Event::Window {
|
||||
timestamp: 0,
|
||||
window_id: 0,
|
||||
win_event: sdl2::event::WindowEvent::Shown,
|
||||
}).is_ok());
|
||||
|
||||
drop(ev);
|
||||
|
||||
// Should return an error now the evet subsystem has been shut down
|
||||
assert!(tx.push_event(sdl2::event::Event::Window {
|
||||
timestamp: 0,
|
||||
window_id: 0,
|
||||
win_event: sdl2::event::WindowEvent::Hidden,
|
||||
}).is_err());
|
||||
}
|
||||
Reference in New Issue
Block a user