mirror of
https://github.com/encounter/rust-sdl2.git
synced 2026-07-10 21:18:41 -07:00
Merge remote-tracking branch 'upstream/master' into fixed
Conflicts: examples/game_controller.rs examples/joystick.rs src/sdl2/sdl.rs
This commit is contained in:
@@ -21,7 +21,7 @@ impl AudioCallback for MyCallback {
|
||||
}
|
||||
|
||||
fn main() {
|
||||
sdl2::init(sdl2::INIT_AUDIO);
|
||||
let _sdl_context = sdl2::init(sdl2::INIT_AUDIO).unwrap();
|
||||
|
||||
let desired_spec = AudioSpecDesired {
|
||||
freq: 44100,
|
||||
|
||||
+16
-15
@@ -3,12 +3,10 @@ extern crate sdl2;
|
||||
use sdl2::video::{Window, WindowPos, OPENGL};
|
||||
use sdl2::render::{RenderDriverIndex, ACCELERATED, Renderer};
|
||||
use sdl2::pixels::Color;
|
||||
use sdl2::event::poll_event;
|
||||
use sdl2::event::Event::{Quit, KeyDown};
|
||||
use sdl2::keycode::KeyCode;
|
||||
|
||||
pub fn main() {
|
||||
sdl2::init(sdl2::INIT_VIDEO);
|
||||
let sdl_context = sdl2::init(sdl2::INIT_VIDEO).unwrap();
|
||||
|
||||
let window = match Window::new("rust-sdl2 demo: Video", WindowPos::PosCentered, WindowPos::PosCentered, 800, 600, OPENGL) {
|
||||
Ok(window) => window,
|
||||
@@ -25,17 +23,20 @@ pub fn main() {
|
||||
drawer.clear();
|
||||
drawer.present();
|
||||
|
||||
loop {
|
||||
match poll_event() {
|
||||
Quit{..} => break,
|
||||
KeyDown { keycode: key, .. } => {
|
||||
if key == KeyCode::Escape {
|
||||
break;
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
let mut running = true;
|
||||
let mut event_pump = sdl_context.event_pump();
|
||||
|
||||
sdl2::quit();
|
||||
while running {
|
||||
for event in event_pump.poll_iter() {
|
||||
use sdl2::event::Event;
|
||||
|
||||
match event {
|
||||
Event::Quit {..} | Event::KeyDown { keycode: KeyCode::Escape, .. } => {
|
||||
running = false
|
||||
},
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
// The rest of the game loop goes here...
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,16 +1,13 @@
|
||||
#![feature(old_io, std_misc, core)]
|
||||
#![feature(core)]
|
||||
|
||||
extern crate sdl2;
|
||||
|
||||
use sdl2::{joystick, controller};
|
||||
use sdl2::event::Event;
|
||||
use sdl2::controller::GameController;
|
||||
use std::old_io::timer::sleep;
|
||||
use std::time::duration::Duration;
|
||||
use std::num::SignedInt;
|
||||
|
||||
fn main() {
|
||||
sdl2::init(sdl2::INIT_GAME_CONTROLLER);
|
||||
let sdl_context = sdl2::init(sdl2::INIT_GAME_CONTROLLER).unwrap();
|
||||
|
||||
let available =
|
||||
match joystick::num_joysticks() {
|
||||
@@ -44,7 +41,7 @@ fn main() {
|
||||
}
|
||||
}
|
||||
|
||||
let controller =
|
||||
let controller =
|
||||
match controller {
|
||||
Some(c) => c,
|
||||
None => panic!("Couldn't open any controller"),
|
||||
@@ -52,8 +49,12 @@ fn main() {
|
||||
|
||||
println!("Controller mapping: {}", controller.mapping());
|
||||
|
||||
loop {
|
||||
match sdl2::event::poll_event() {
|
||||
let mut event_pump = sdl_context.event_pump();
|
||||
|
||||
for event in event_pump.wait_iter() {
|
||||
use sdl2::event::Event;
|
||||
|
||||
match event {
|
||||
Event::ControllerAxisMotion{ axis, value: val, .. } => {
|
||||
// Axis motion is an absolute value in the range
|
||||
// [-32768, 32767]. Let's simulate a very rough dead
|
||||
@@ -67,12 +68,7 @@ fn main() {
|
||||
Event::ControllerButtonUp{ button, .. } =>
|
||||
println!("Button {:?} up", button),
|
||||
Event::Quit{..} => break,
|
||||
Event::None =>
|
||||
// Don't hog the CPU while waiting for events
|
||||
sleep(Duration::milliseconds(100)),
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
sdl2::quit();
|
||||
}
|
||||
|
||||
+9
-13
@@ -1,15 +1,12 @@
|
||||
#![feature(old_io, std_misc, core)]
|
||||
#![feature(core)]
|
||||
|
||||
extern crate sdl2;
|
||||
|
||||
use sdl2::joystick::{Joystick, num_joysticks};
|
||||
use sdl2::event::Event;
|
||||
use std::old_io::timer::sleep;
|
||||
use std::time::duration::Duration;
|
||||
use std::num::SignedInt;
|
||||
|
||||
fn main() {
|
||||
sdl2::init(sdl2::INIT_JOYSTICK);
|
||||
let sdl_context = sdl2::init(sdl2::INIT_JOYSTICK).unwrap();
|
||||
|
||||
let available =
|
||||
match num_joysticks() {
|
||||
@@ -34,12 +31,16 @@ fn main() {
|
||||
}
|
||||
}
|
||||
|
||||
if joystick.is_none() {
|
||||
if joystick.is_none() {
|
||||
panic!("Couldn't open any joystick");
|
||||
};
|
||||
|
||||
loop {
|
||||
match sdl2::event::poll_event() {
|
||||
let mut event_pump = sdl_context.event_pump();
|
||||
|
||||
for event in event_pump.wait_iter() {
|
||||
use sdl2::event::Event;
|
||||
|
||||
match event {
|
||||
Event::JoyAxisMotion{ axis_idx, value: val, .. } => {
|
||||
// Axis motion is an absolute value in the range
|
||||
// [-32768, 32767]. Let's simulate a very rough dead
|
||||
@@ -55,12 +56,7 @@ fn main() {
|
||||
Event::JoyHatMotion{ hat_idx, state, .. } =>
|
||||
println!("Hat {} moved to {:?}", hat_idx, state),
|
||||
Event::Quit{..} => break,
|
||||
Event::None =>
|
||||
// Don't hog the CPU while waiting for events
|
||||
sleep(Duration::milliseconds(100)),
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
sdl2::quit();
|
||||
}
|
||||
|
||||
@@ -4,12 +4,10 @@ use sdl2::video::{Window, WindowPos, OPENGL};
|
||||
use sdl2::render::{RenderDriverIndex, ACCELERATED, Renderer};
|
||||
use sdl2::pixels::PixelFormatEnum;
|
||||
use sdl2::rect::Rect;
|
||||
use sdl2::event::poll_event;
|
||||
use sdl2::event::Event::{Quit, KeyDown};
|
||||
use sdl2::keycode::KeyCode;
|
||||
|
||||
pub fn main() {
|
||||
sdl2::init(sdl2::INIT_VIDEO);
|
||||
let sdl_context = sdl2::init(sdl2::INIT_VIDEO).unwrap();
|
||||
|
||||
let window = match Window::new("rust-sdl2 demo: Renderer + Texture", WindowPos::PosCentered, WindowPos::PosCentered, 800, 600, OPENGL) {
|
||||
Ok(window) => window,
|
||||
@@ -40,17 +38,20 @@ pub fn main() {
|
||||
drawer.copy_ex(&texture, None, Some(Rect::new(450, 100, 256, 256)), 30.0, None, (false, false));
|
||||
drawer.present();
|
||||
|
||||
loop {
|
||||
match poll_event() {
|
||||
Quit{..} => break,
|
||||
KeyDown { keycode: key, .. } => {
|
||||
if key == KeyCode::Escape {
|
||||
break;
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
let mut running = true;
|
||||
let mut event_pump = sdl_context.event_pump();
|
||||
|
||||
sdl2::quit();
|
||||
while running {
|
||||
for event in event_pump.poll_iter() {
|
||||
use sdl2::event::Event;
|
||||
|
||||
match event {
|
||||
Event::Quit {..} | Event::KeyDown { keycode: KeyCode::Escape, .. } => {
|
||||
running = false
|
||||
},
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
// The rest of the game loop goes here...
|
||||
}
|
||||
}
|
||||
|
||||
+16
-15
@@ -4,12 +4,10 @@ use sdl2::video::{Window, WindowPos, SHOWN};
|
||||
use sdl2::render::{RenderDriverIndex, ACCELERATED, Renderer};
|
||||
use sdl2::pixels::PixelFormatEnum;
|
||||
use sdl2::rect::Rect;
|
||||
use sdl2::event::poll_event;
|
||||
use sdl2::event::Event::{Quit, KeyDown};
|
||||
use sdl2::keycode::KeyCode;
|
||||
|
||||
pub fn main() {
|
||||
sdl2::init(sdl2::INIT_VIDEO);
|
||||
let sdl_context = sdl2::init(sdl2::INIT_VIDEO).unwrap();
|
||||
|
||||
let window = match Window::new("rust-sdl2 demo: YUV", WindowPos::PosCentered, WindowPos::PosCentered, 800, 600, SHOWN) {
|
||||
Ok(window) => window,
|
||||
@@ -56,17 +54,20 @@ pub fn main() {
|
||||
drawer.copy(&texture, None, Some(Rect::new(100, 100, 256, 256)));
|
||||
drawer.present();
|
||||
|
||||
loop {
|
||||
match poll_event() {
|
||||
Quit{..} => break,
|
||||
KeyDown { keycode: key, .. } => {
|
||||
if key == KeyCode::Escape {
|
||||
break;
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
let mut running = true;
|
||||
let mut event_pump = sdl_context.event_pump();
|
||||
|
||||
sdl2::quit();
|
||||
while running {
|
||||
for event in event_pump.poll_iter() {
|
||||
use sdl2::event::Event;
|
||||
|
||||
match event {
|
||||
Event::Quit {..} | Event::KeyDown { keycode: KeyCode::Escape, .. } => {
|
||||
running = false
|
||||
},
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
// The rest of the game loop goes here...
|
||||
}
|
||||
}
|
||||
|
||||
@@ -444,9 +444,9 @@ pub type SDL_EventFilter =
|
||||
extern "C" {
|
||||
pub fn SDL_free(mem: *const c_void);
|
||||
pub fn SDL_PumpEvents();
|
||||
/*pub fn SDL_PeepEvents(events: &[SDL_Event], numevents: c_int,
|
||||
action: SDL_eventaction, minType: uint32_t,
|
||||
maxType: uint32_t) -> c_int;*/
|
||||
pub fn SDL_PeepEvents(events: *mut SDL_Event, numevents: c_int,
|
||||
action: SDL_eventaction,
|
||||
minType: uint32_t, maxType: uint32_t) -> c_int;
|
||||
pub fn SDL_HasEvent(_type: uint32_t) -> SDL_bool;
|
||||
pub fn SDL_HasEvents(minType: uint32_t, maxType: uint32_t) ->
|
||||
SDL_bool;
|
||||
|
||||
+209
-114
@@ -8,6 +8,8 @@ use libc::{c_int, c_void, uint32_t};
|
||||
use std::num::FromPrimitive;
|
||||
use std::ptr;
|
||||
use std::borrow::ToOwned;
|
||||
use std::iter::FromIterator;
|
||||
use std::marker::{NoCopy, PhantomData};
|
||||
|
||||
use controller;
|
||||
use controller::{Axis, Button};
|
||||
@@ -125,9 +127,6 @@ impl WindowEventId {
|
||||
|
||||
/// Different event types.
|
||||
pub enum Event {
|
||||
None,
|
||||
|
||||
|
||||
Quit { timestamp: u32 },
|
||||
AppTerminating { timestamp: u32 },
|
||||
AppLowMemory { timestamp: u32 },
|
||||
@@ -361,12 +360,16 @@ pub enum Event {
|
||||
_type: u32,
|
||||
code: i32
|
||||
},
|
||||
|
||||
Unknown {
|
||||
timestamp: u32,
|
||||
type_: u32
|
||||
}
|
||||
}
|
||||
|
||||
impl ::std::fmt::Debug for Event {
|
||||
fn fmt(&self, out: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
|
||||
out.write_str(match *self {
|
||||
Event::None => "Event::None",
|
||||
Event::Quit{..} => "Event::Quit",
|
||||
Event::AppTerminating{..} => "Event::AppTerminating",
|
||||
Event::AppLowMemory{..} => "Event::AppLowMemory",
|
||||
@@ -405,6 +408,7 @@ impl ::std::fmt::Debug for Event {
|
||||
Event::ClipboardUpdate{..} => "Event::ClipboardUpdate",
|
||||
Event::DropFile{..} => "Event::DropFile",
|
||||
Event::User{..} => "Event::User",
|
||||
Event::Unknown{..} => "Event::Unknown",
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -412,7 +416,7 @@ impl ::std::fmt::Debug for Event {
|
||||
// TODO: Remove this when from_utf8 is updated in Rust
|
||||
impl Event {
|
||||
fn to_ll(self) -> Option<ll::SDL_Event> {
|
||||
let ret = null_event();
|
||||
let ret = unsafe { mem::uninitialized() };
|
||||
match self {
|
||||
// just ignore timestamp
|
||||
Event::User { window_id, _type, code, .. } => {
|
||||
@@ -439,7 +443,7 @@ impl Event {
|
||||
fn from_ll(raw: &ll::SDL_Event) -> Event {
|
||||
let raw_type = raw._type();
|
||||
let raw_type = if raw_type.is_null() {
|
||||
return Event::None;
|
||||
panic!("Event payload is null")
|
||||
} else {
|
||||
unsafe { *raw_type }
|
||||
};
|
||||
@@ -809,142 +813,233 @@ impl Event {
|
||||
}
|
||||
}
|
||||
|
||||
EventType::First | EventType::Last => Event::None,
|
||||
EventType::First => panic!("Unused event, EventType::First, was encountered"),
|
||||
EventType::Last => panic!("Unusable event, EventType::Last, was encountered"),
|
||||
|
||||
// If we have no other match and the event type is >= 32768
|
||||
// this is a user event
|
||||
EventType::User => {
|
||||
if raw_type < 32768 {
|
||||
return Event::None;
|
||||
}
|
||||
// The type is unknown to us.
|
||||
// It's a newer SDL2 type.
|
||||
let ref event = *raw.common();
|
||||
|
||||
let ref event = *raw.user();
|
||||
Event::Unknown {
|
||||
timestamp: event.timestamp,
|
||||
type_: event._type
|
||||
}
|
||||
} else {
|
||||
let ref event = *raw.user();
|
||||
|
||||
Event::User {
|
||||
timestamp: event.timestamp,
|
||||
window_id: event.windowID,
|
||||
_type: raw_type,
|
||||
code: event.code
|
||||
Event::User {
|
||||
timestamp: event.timestamp,
|
||||
window_id: event.windowID,
|
||||
_type: raw_type,
|
||||
code: event.code
|
||||
}
|
||||
}
|
||||
}
|
||||
}} // close unsafe & match
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
fn null_event() -> ll::SDL_Event {
|
||||
ll::SDL_Event { data: [0; 56] }
|
||||
/// A thread-safe type that encapsulates SDL event-pumping functions.
|
||||
pub struct EventPump<'sdl> {
|
||||
_marker: NoCopy,
|
||||
_sdl: PhantomData<&'sdl ()>
|
||||
}
|
||||
|
||||
/// Pump the event loop, gathering events from the input devices.
|
||||
pub fn pump_events() {
|
||||
unsafe { ll::SDL_PumpEvents(); }
|
||||
}
|
||||
/// Prevents the event pump from moving to other threads.
|
||||
/// SDL events can only be pumped on the main thread.
|
||||
impl<'sdl> !Send for EventPump<'sdl> {}
|
||||
|
||||
/// Check for the existence of certain event types in the event queue.
|
||||
pub fn has_event(_type: EventType) -> bool {
|
||||
unsafe { ll::SDL_HasEvent(_type as uint32_t ) == 1 }
|
||||
}
|
||||
impl<'sdl> EventPump<'sdl> {
|
||||
/// Polls for currently pending events.
|
||||
///
|
||||
/// If no events are pending, `None` is returned.
|
||||
pub fn poll_event(&mut self) -> Option<Event> {
|
||||
let raw = unsafe { mem::uninitialized() };
|
||||
let has_pending = unsafe { ll::SDL_PollEvent(&raw) == 1 as c_int };
|
||||
|
||||
/// Check for the existence of a range of event types in the event queue.
|
||||
pub fn has_events(min: EventType, max: EventType) -> bool {
|
||||
unsafe { ll::SDL_HasEvents(min as uint32_t, max as uint32_t) == 1 }
|
||||
}
|
||||
if has_pending { Some(Event::from_ll(&raw)) }
|
||||
else { None }
|
||||
}
|
||||
|
||||
/// Clear events from the event queue.
|
||||
pub fn flush_event(_type: EventType) {
|
||||
unsafe { ll::SDL_FlushEvent(_type as uint32_t) }
|
||||
}
|
||||
/// Returns a polling iterator that calls `poll_event()`.
|
||||
/// The iterator will terminate once there are no more pending events.
|
||||
///
|
||||
/// # Example
|
||||
/// ```no_run
|
||||
/// let mut sdl_context = sdl2::init(sdl2::INIT_EVERYTHING).unwrap();
|
||||
///
|
||||
/// let mut event_pump = sdl_context.event_pump();
|
||||
/// for event in event_pump.poll_iter() {
|
||||
/// use sdl2::event::Event;
|
||||
/// match event {
|
||||
/// Event::KeyDown {..} => { /*...*/ },
|
||||
/// _ => ()
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
pub fn poll_iter(&mut self) -> EventPollIterator {
|
||||
EventPollIterator {
|
||||
event_pump: unsafe { EventPump::_unchecked_new() }
|
||||
}
|
||||
}
|
||||
|
||||
/// Clear events from the event queue of a range of event types.
|
||||
pub fn flush_events(min: EventType, max: EventType) {
|
||||
unsafe { ll::SDL_FlushEvents(min as uint32_t, max as uint32_t) }
|
||||
}
|
||||
/// Pumps the event loop, gathering events from the input devices.
|
||||
pub fn pump_events(&mut self) {
|
||||
unsafe { ll::SDL_PumpEvents(); };
|
||||
}
|
||||
|
||||
/// Poll for currently pending events.
|
||||
pub fn poll_event() -> Event {
|
||||
pump_events();
|
||||
/// Waits indefinitely for the next available event.
|
||||
pub fn wait_event(&mut self) -> Event {
|
||||
unsafe {
|
||||
let raw = mem::uninitialized();
|
||||
let success = ll::SDL_WaitEvent(&raw) == 1;
|
||||
|
||||
let raw = null_event();
|
||||
let success = unsafe { ll::SDL_PollEvent(&raw) == 1 as c_int };
|
||||
if success { Event::from_ll(&raw) }
|
||||
else { panic!(get_error()) }
|
||||
}
|
||||
}
|
||||
|
||||
if success { Event::from_ll(&raw) }
|
||||
else { Event::None }
|
||||
}
|
||||
/// Waits until the specified timeout (in milliseconds) for the next available event.
|
||||
pub fn wait_event_timeout(&mut self, timeout: u32) -> Option<Event> {
|
||||
unsafe {
|
||||
let raw = mem::uninitialized();
|
||||
let success = ll::SDL_WaitEventTimeout(&raw, timeout as c_int) == 1;
|
||||
|
||||
/// Wait indefinitely for the next available event.
|
||||
pub fn wait_event() -> SdlResult<Event> {
|
||||
let raw = null_event();
|
||||
let success = unsafe { ll::SDL_WaitEvent(&raw) == 1 as c_int };
|
||||
if success { Some(Event::from_ll(&raw)) }
|
||||
else { None }
|
||||
}
|
||||
}
|
||||
|
||||
if success { Ok(Event::from_ll(&raw)) }
|
||||
else { Err(get_error()) }
|
||||
}
|
||||
/// Returns a waiting iterator that calls `wait_event()`.
|
||||
///
|
||||
/// Note: The iterator will never terminate.
|
||||
pub fn wait_iter(&mut self) -> EventWaitIterator {
|
||||
EventWaitIterator {
|
||||
event_pump: unsafe { EventPump::_unchecked_new() }
|
||||
}
|
||||
}
|
||||
|
||||
/// Wait until the specified timeout (in milliseconds) for the next available event.
|
||||
pub fn wait_event_timeout(timeout: i32) -> SdlResult<Event> {
|
||||
let raw = null_event();
|
||||
let success = unsafe { ll::SDL_WaitEventTimeout(&raw, timeout as c_int) ==
|
||||
1 as c_int };
|
||||
/// Returns a waiting iterator that calls `wait_event_timeout()`.
|
||||
///
|
||||
/// Note: The iterator will never terminate, unless waiting for an event
|
||||
/// exceeds the specified timeout.
|
||||
pub fn wait_timeout_iter(&mut self, timeout: u32) -> EventWaitTimeoutIterator {
|
||||
EventWaitTimeoutIterator {
|
||||
event_pump: unsafe { EventPump::_unchecked_new() },
|
||||
timeout: timeout
|
||||
}
|
||||
}
|
||||
|
||||
if success { Ok(Event::from_ll(&raw)) }
|
||||
else { Err(get_error()) }
|
||||
}
|
||||
|
||||
extern "C" fn event_filter_wrapper(userdata: *const c_void, event: *const ll::SDL_Event) -> c_int {
|
||||
let filter: extern fn(event: Event) -> bool = unsafe { mem::transmute(userdata) };
|
||||
if event.is_null() { 1 }
|
||||
else { filter(Event::from_ll(unsafe { &*event })) as c_int }
|
||||
}
|
||||
|
||||
/// Set up a filter to process all events before they change internal state and are posted to the internal event queue.
|
||||
pub fn set_event_filter(filter_func: extern fn(event: Event) -> bool) {
|
||||
unsafe { ll::SDL_SetEventFilter(event_filter_wrapper,
|
||||
filter_func as *const _) }
|
||||
}
|
||||
|
||||
/// Add a callback to be triggered when an event is added to the event queue.
|
||||
pub fn add_event_watch(filter_func: extern fn(event: Event) -> bool) {
|
||||
unsafe { ll::SDL_AddEventWatch(event_filter_wrapper,
|
||||
filter_func as *const _) }
|
||||
}
|
||||
|
||||
/// Remove an event watch callback added.
|
||||
pub fn delete_event_watch(filter_func: extern fn(event: Event) -> bool) {
|
||||
unsafe { ll::SDL_DelEventWatch(event_filter_wrapper,
|
||||
filter_func as *const _) }
|
||||
}
|
||||
|
||||
/// Run a specific filter function on the current event queue, removing any events for which the filter returns 0.
|
||||
pub fn filter_events(filter_func: extern fn(event: Event) -> bool) {
|
||||
unsafe { ll::SDL_FilterEvents(event_filter_wrapper,
|
||||
filter_func as *const _) }
|
||||
}
|
||||
|
||||
/// Set the state of processing events.
|
||||
pub fn set_event_state(_type: EventType, state: bool) {
|
||||
unsafe { ll::SDL_EventState(_type as uint32_t,
|
||||
state as ll::SDL_EventState); }
|
||||
}
|
||||
|
||||
/// Get the state of processing events.
|
||||
pub fn get_event_state(_type: EventType) -> bool {
|
||||
unsafe { ll::SDL_EventState(_type as uint32_t, ll::SDL_QUERY)
|
||||
== ll::SDL_ENABLE }
|
||||
}
|
||||
|
||||
/// allocate a set of user-defined events, and return the beginning event number for that set of events
|
||||
pub fn register_events(num_events: i32) -> Option<u32> {
|
||||
let ret = unsafe { ll::SDL_RegisterEvents(num_events as c_int) };
|
||||
if ret == (-1 as uint32_t) {
|
||||
None
|
||||
} else {
|
||||
Some(ret as u32)
|
||||
/// Internal use only; used by `sdl2::Sdl::event_pump()`
|
||||
#[doc(hidden)]
|
||||
pub unsafe fn _unchecked_new<'a>() -> EventPump<'a> {
|
||||
EventPump {
|
||||
_marker: NoCopy,
|
||||
_sdl: PhantomData
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// add an event to the event queue
|
||||
/// An iterator that calls `EventPump::poll_event()`.
|
||||
#[must_use = "iterators are lazy and do nothing unless consumed"]
|
||||
pub struct EventPollIterator<'a> {
|
||||
event_pump: EventPump<'a>
|
||||
}
|
||||
|
||||
impl<'a> Iterator for EventPollIterator<'a> {
|
||||
pub type Item = Event;
|
||||
|
||||
fn next(&mut self) -> Option<Event> {
|
||||
self.event_pump.poll_event()
|
||||
}
|
||||
}
|
||||
|
||||
/// An iterator that calls `EventPump::wait_event()`.
|
||||
#[must_use = "iterators are lazy and do nothing unless consumed"]
|
||||
pub struct EventWaitIterator<'a> {
|
||||
event_pump: EventPump<'a>
|
||||
}
|
||||
|
||||
impl<'a> Iterator for EventWaitIterator<'a> {
|
||||
pub type Item = Event;
|
||||
fn next(&mut self) -> Option<Event> { Some(self.event_pump.wait_event()) }
|
||||
}
|
||||
|
||||
/// An iterator that calls `EventPump::wait_event_timeout()`.
|
||||
#[must_use = "iterators are lazy and do nothing unless consumed"]
|
||||
pub struct EventWaitTimeoutIterator<'a> {
|
||||
event_pump: EventPump<'a>,
|
||||
timeout: u32
|
||||
}
|
||||
|
||||
impl<'a> Iterator for EventWaitTimeoutIterator<'a> {
|
||||
pub type Item = Event;
|
||||
fn next(&mut self) -> Option<Event> { self.event_pump.wait_event_timeout(self.timeout) }
|
||||
}
|
||||
|
||||
/// Removes all events in the event queue that match the specified event type.
|
||||
pub fn flush_event(event_type: EventType) {
|
||||
unsafe { ll::SDL_FlushEvent(event_type as uint32_t) };
|
||||
}
|
||||
|
||||
/// Removes all events in the event queue that match the specified type range.
|
||||
pub fn flush_events(min_type: u32, max_type: u32) {
|
||||
unsafe { ll::SDL_FlushEvents(min_type, max_type) };
|
||||
}
|
||||
|
||||
/// Reads the events at the front of the event queue, until the maximum amount
|
||||
/// of events is read.
|
||||
///
|
||||
/// The events will _not_ be removed from the queue.
|
||||
///
|
||||
/// # Example
|
||||
/// ```no_run
|
||||
/// use sdl2::event::{Event, peek_events};
|
||||
///
|
||||
/// // Read up to 1024 events
|
||||
/// let events: Vec<Event> = peek_events(1024);
|
||||
///
|
||||
/// // Print each one
|
||||
/// for event in events {
|
||||
/// println!("{:?}", event);
|
||||
/// }
|
||||
/// ```
|
||||
pub fn peek_events<B>(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_slice().as_mut_ptr();
|
||||
|
||||
ll::SDL_PeepEvents(
|
||||
events_ptr,
|
||||
max_amount as c_int,
|
||||
ll::SDL_PEEKEVENT,
|
||||
ll::SDL_FIRSTEVENT,
|
||||
ll::SDL_LASTEVENT
|
||||
)
|
||||
};
|
||||
|
||||
if result < 0 {
|
||||
// The only error possible is "Couldn't lock event queue"
|
||||
panic!(get_error());
|
||||
} else {
|
||||
events.set_len(max_amount as usize);
|
||||
|
||||
events.iter().map(|event_raw| {
|
||||
Event::from_ll(event_raw)
|
||||
}).collect()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Pushes an event to the event queue.
|
||||
pub fn push_event(event: Event) -> SdlResult<()> {
|
||||
match event.to_ll() {
|
||||
Some(raw_event) => {
|
||||
@@ -953,7 +1048,7 @@ pub fn push_event(event: Event) -> SdlResult<()> {
|
||||
else { Err(get_error()) }
|
||||
},
|
||||
None => {
|
||||
Err("Unsupport event type to push back to queue.".to_owned())
|
||||
Err(format!("Cannot push unsupported event type to the queue"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+108
-13
@@ -1,6 +1,8 @@
|
||||
use std::ffi::{CStr, CString};
|
||||
use std::marker::{NoCopy, PhantomData};
|
||||
|
||||
use sys::sdl as ll;
|
||||
use event::EventPump;
|
||||
|
||||
bitflags! {
|
||||
flags InitFlag: u32 {
|
||||
@@ -27,30 +29,123 @@ pub enum Error {
|
||||
|
||||
pub type SdlResult<T> = Result<T, String>;
|
||||
|
||||
pub fn init(flags: InitFlag) -> bool {
|
||||
unsafe {
|
||||
ll::SDL_Init(flags.bits()) == 0
|
||||
use std::sync::atomic::{AtomicBool, ATOMIC_BOOL_INIT};
|
||||
/// Only one Sdl context can be alive at a time.
|
||||
/// Set to false by default (not alive).
|
||||
static IS_SDL_CONTEXT_ALIVE: AtomicBool = ATOMIC_BOOL_INIT;
|
||||
|
||||
/// The SDL context type. Initialize with `sdl2::init()`.
|
||||
///
|
||||
/// From a thread-safety perspective, `Sdl` represents the main thread.
|
||||
/// Only one instance of `Sdl` is allowed per process, and cannot be moved or
|
||||
/// used across non-main threads.
|
||||
///
|
||||
/// As such, `Sdl` is a useful type for ensuring that SDL types that can only
|
||||
/// be used on the main thread are initialized that way.
|
||||
///
|
||||
/// For instance, `SDL_PumpEvents()` is not thread safe, and may only be
|
||||
/// called on the main thread.
|
||||
/// All functionality that calls `SDL_PumpEvents()` is thus put into an
|
||||
/// `EventPump` type, which can only be obtained through `Sdl`.
|
||||
/// This guarantees that the only way to call event-pumping functions is on
|
||||
/// the main thread.
|
||||
pub struct Sdl {
|
||||
_marker: NoCopy
|
||||
}
|
||||
|
||||
impl !Send for Sdl {}
|
||||
impl !Sync for Sdl {}
|
||||
|
||||
impl Sdl {
|
||||
/// Initializes specific SDL subsystems.
|
||||
pub fn init_subsystem(&self, flags: InitFlag) -> SdlResult<Subsystem> {
|
||||
unsafe {
|
||||
if ll::SDL_InitSubSystem(flags.bits()) == 0 {
|
||||
Ok(Subsystem {
|
||||
flags: flags,
|
||||
_marker: PhantomData
|
||||
})
|
||||
} else {
|
||||
Err(get_error())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the mask of the specified subsystems which have previously been initialized.
|
||||
pub fn was_init(&self, flags: InitFlag) -> InitFlag {
|
||||
unsafe {
|
||||
let raw = ll::SDL_WasInit(flags.bits());
|
||||
flags & InitFlag::from_bits(raw).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
/// Obtains the SDL event pump.
|
||||
pub fn event_pump(&self) -> EventPump {
|
||||
unsafe { EventPump::_unchecked_new() }
|
||||
}
|
||||
}
|
||||
|
||||
pub fn init_subsystem(flags: InitFlag) -> bool {
|
||||
unsafe {
|
||||
ll::SDL_InitSubSystem(flags.bits()) == 0
|
||||
impl Drop for Sdl {
|
||||
fn drop(&mut self) {
|
||||
use std::sync::atomic::Ordering;
|
||||
|
||||
let was_alive = IS_SDL_CONTEXT_ALIVE.swap(false, Ordering::Relaxed);
|
||||
assert!(was_alive);
|
||||
|
||||
unsafe { ll::SDL_Quit(); }
|
||||
}
|
||||
}
|
||||
|
||||
pub fn quit_subsystem(flags: InitFlag) {
|
||||
unsafe { ll::SDL_QuitSubSystem(flags.bits()); }
|
||||
/// A RAII value representing initalized SDL subsystems. See `sdl2::Sdl::init_subsystem()`.
|
||||
///
|
||||
/// Subsystem initialization is ref-counted. Once `Subsystem::drop()` is called,
|
||||
/// the specified subsystems' ref-counts are decremented via `SDL_QuitSubSystem`.
|
||||
pub struct Subsystem<'sdl> {
|
||||
flags: InitFlag,
|
||||
_marker: PhantomData<&'sdl Sdl>
|
||||
}
|
||||
|
||||
pub fn quit() {
|
||||
unsafe { ll::SDL_Quit(); }
|
||||
#[unsafe_destructor]
|
||||
impl<'sdl> Drop for Subsystem<'sdl> {
|
||||
fn drop(&mut self) {
|
||||
unsafe { ll::SDL_QuitSubSystem(self.flags.bits()); }
|
||||
}
|
||||
}
|
||||
|
||||
pub fn was_inited(flags: InitFlag) -> InitFlag {
|
||||
/// Initializes the SDL library.
|
||||
/// This must be called before using any other SDL function.
|
||||
///
|
||||
/// # Example
|
||||
/// ```no_run
|
||||
/// let sdl_context = sdl2::init(sdl2::INIT_EVERYTHING).unwrap();
|
||||
///
|
||||
/// let mut event_pump = sdl_context.event_pump();
|
||||
/// for event in event_pump.poll_iter() {
|
||||
/// // ...
|
||||
/// }
|
||||
///
|
||||
/// // SDL_Quit() is called here as `sdl_context` is dropped.
|
||||
/// ```
|
||||
pub fn init(flags: InitFlag) -> SdlResult<Sdl> {
|
||||
unsafe {
|
||||
let raw = ll::SDL_WasInit(flags.bits());
|
||||
flags & InitFlag::from_bits(raw).unwrap()
|
||||
use std::sync::atomic::Ordering;
|
||||
|
||||
// Atomically switch the `IS_SDL_CONTEXT_ALIVE` global to true
|
||||
let was_alive = IS_SDL_CONTEXT_ALIVE.swap(true, Ordering::Relaxed);
|
||||
|
||||
if was_alive {
|
||||
IS_SDL_CONTEXT_ALIVE.swap(false, Ordering::Relaxed);
|
||||
Err(format!("Cannot have more than one `Sdl` in use at the same time"))
|
||||
} else {
|
||||
if ll::SDL_Init(flags.bits()) == 0 {
|
||||
Ok(Sdl {
|
||||
_marker: NoCopy
|
||||
})
|
||||
} else {
|
||||
IS_SDL_CONTEXT_ALIVE.swap(false, Ordering::Relaxed);
|
||||
Err(get_error())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+3
-3
@@ -79,7 +79,7 @@ extern "C" fn c_timer_callback(_interval: u32, param: *const c_void) -> uint32_t
|
||||
fn test_timer_runs_multiple_times() {
|
||||
use std::sync::{Arc, Mutex};
|
||||
let _running = TIMER_INIT_LOCK.lock().unwrap();
|
||||
::sdl::init(::sdl::INIT_TIMER);
|
||||
::sdl::init(::sdl::INIT_TIMER).unwrap();
|
||||
|
||||
let local_num = Arc::new(Mutex::new(0));
|
||||
let timer_num = local_num.clone();
|
||||
@@ -104,7 +104,7 @@ fn test_timer_runs_multiple_times() {
|
||||
fn test_timer_runs_at_least_once() {
|
||||
use std::sync::{Arc, Mutex};
|
||||
let _running = TIMER_INIT_LOCK.lock().unwrap();
|
||||
::sdl::init(::sdl::INIT_TIMER);
|
||||
::sdl::init(::sdl::INIT_TIMER).unwrap();
|
||||
|
||||
let local_flag = Arc::new(Mutex::new(false));
|
||||
let timer_flag = local_flag.clone();
|
||||
@@ -123,7 +123,7 @@ fn test_timer_runs_at_least_once() {
|
||||
fn test_timer_can_be_recreated() {
|
||||
use std::sync::{Arc, Mutex};
|
||||
let _running = TIMER_INIT_LOCK.lock().unwrap();
|
||||
::sdl::init(::sdl::INIT_TIMER);
|
||||
::sdl::init(::sdl::INIT_TIMER).unwrap();
|
||||
|
||||
let local_num = Arc::new(Mutex::new(0));
|
||||
let timer_num = local_num.clone();
|
||||
|
||||
@@ -4,8 +4,6 @@ extern crate sdl2;
|
||||
|
||||
#[test]
|
||||
fn audio_spec_wav() {
|
||||
sdl2::init(sdl2::INIT_AUDIO);
|
||||
|
||||
let wav = sdl2::audio::AudioSpecWAV::load_wav(&Path::new("./tests/sine.wav")).unwrap();
|
||||
|
||||
assert_eq!(wav.freq, 22050);
|
||||
@@ -14,6 +12,4 @@ fn audio_spec_wav() {
|
||||
|
||||
let buffer = wav.get_buffer();
|
||||
assert_eq!(buffer.len(), 4410);
|
||||
|
||||
sdl2::quit();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user