diff --git a/changelog.md b/changelog.md index 9212bbfe4c..8a579ea176 100644 --- a/changelog.md +++ b/changelog.md @@ -5,6 +5,8 @@ when upgrading from a version of rust-sdl2 to another. [PR #1164](https://github.com/Rust-SDL2/rust-sdl2/pull/1164) Added raw-window-handle support for Android +[PR #1165](https://github.com/Rust-SDL2/rust-sdl2/pull/1165) Added binding for `SDL_GetDisplayOrientation` and `SDL_DISPLAYEVENT` + ### v0.35.0 * **BREAKING CHANGE** Update `sdl2-sys/sdl_bindings.rs` to use enums instead of consts. If you were using `sdl2-sys`'s diff --git a/src/sdl2/event.rs b/src/sdl2/event.rs index 2c6540739e..a0b3b67f48 100644 --- a/src/sdl2/event.rs +++ b/src/sdl2/event.rs @@ -2,8 +2,6 @@ Event Handling */ -use libc::c_int; -use libc::c_void; use std::borrow::ToOwned; use std::collections::HashMap; use std::convert::TryFrom; @@ -15,6 +13,9 @@ use std::mem::transmute; use std::ptr; use std::sync::Mutex; +use libc::c_int; +use libc::c_void; + use crate::controller; use crate::controller::{Axis, Button}; use crate::get_error; @@ -26,10 +27,10 @@ use crate::keyboard::Mod; use crate::keyboard::Scancode; use crate::mouse; use crate::mouse::{MouseButton, MouseState, MouseWheelDirection}; - use crate::sys; use crate::sys::SDL_EventFilter; use crate::sys::SDL_EventType; +use crate::video::Orientation; struct CustomEventTypeMaps { sdl_id_to_type_id: HashMap, @@ -272,6 +273,7 @@ pub enum EventType { AppWillEnterForeground = SDL_EventType::SDL_APP_WILLENTERFOREGROUND as u32, AppDidEnterForeground = SDL_EventType::SDL_APP_DIDENTERFOREGROUND as u32, + Display = SDL_EventType::SDL_DISPLAYEVENT as u32, Window = SDL_EventType::SDL_WINDOWEVENT as u32, // TODO: SysWM = sys::SDL_SYSWMEVENT as u32, KeyDown = SDL_EventType::SDL_KEYDOWN as u32, @@ -342,6 +344,7 @@ impl TryFrom for EventType { SDL_APP_WILLENTERFOREGROUND => AppWillEnterForeground, SDL_APP_DIDENTERFOREGROUND => AppDidEnterForeground, + SDL_DISPLAYEVENT => Display, SDL_WINDOWEVENT => Window, SDL_KEYDOWN => KeyDown, @@ -398,6 +401,66 @@ impl TryFrom for EventType { } } +#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] +/// An enum of display events. +pub enum DisplayEvent { + None, + Orientation(Orientation), + Connected, + Disconnected, +} + +impl DisplayEvent { + #[allow(clippy::match_same_arms)] + fn from_ll(id: u8, data1: i32) -> DisplayEvent { + if id > sys::SDL_DisplayEventID::SDL_DISPLAYEVENT_DISCONNECTED as u8 { + return DisplayEvent::None; + } + match unsafe { transmute(id as u32) } { + sys::SDL_DisplayEventID::SDL_DISPLAYEVENT_NONE => DisplayEvent::None, + sys::SDL_DisplayEventID::SDL_DISPLAYEVENT_ORIENTATION => { + let orientation = if data1 as u32 + > sys::SDL_DisplayOrientation::SDL_ORIENTATION_PORTRAIT_FLIPPED as u32 + { + Orientation::Unknown + } else { + Orientation::from_ll(unsafe { transmute(data1 as u32) }) + }; + DisplayEvent::Orientation(orientation) + } + sys::SDL_DisplayEventID::SDL_DISPLAYEVENT_CONNECTED => DisplayEvent::Connected, + sys::SDL_DisplayEventID::SDL_DISPLAYEVENT_DISCONNECTED => DisplayEvent::Disconnected, + } + } + + fn to_ll(&self) -> (u8, i32) { + match *self { + DisplayEvent::None => (sys::SDL_DisplayEventID::SDL_DISPLAYEVENT_NONE as u8, 0), + DisplayEvent::Orientation(orientation) => ( + sys::SDL_DisplayEventID::SDL_DISPLAYEVENT_ORIENTATION as u8, + orientation.to_ll() as i32, + ), + DisplayEvent::Connected => { + (sys::SDL_DisplayEventID::SDL_DISPLAYEVENT_CONNECTED as u8, 0) + } + DisplayEvent::Disconnected => ( + sys::SDL_DisplayEventID::SDL_DISPLAYEVENT_DISCONNECTED as u8, + 0, + ), + } + } + + pub fn is_same_kind_as(&self, other: &DisplayEvent) -> bool { + match (self, other) { + (Self::None, Self::None) + | (Self::Orientation(_), Self::Orientation(_)) + | (Self::Connected, Self::Connected) + | (Self::Disconnected, Self::Disconnected) => true, + _ => false, + } + } +} + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] /// An enum of window events. pub enum WindowEvent { @@ -516,6 +579,11 @@ pub enum Event { timestamp: u32, }, + Display { + timestamp: u32, + display_index: i32, + display_event: DisplayEvent, + }, Window { timestamp: u32, window_id: u32, @@ -810,6 +878,7 @@ pub enum Event { /// store pointers to types that are `!Send`. Dereferencing these as pointers /// requires using `unsafe` and ensuring your own safety guarantees. unsafe impl Send for Event {} + /// This does not auto-derive because `User`'s `data` fields can be used to /// store pointers to types that are `!Sync`. Dereferencing these as pointers /// requires using `unsafe` and ensuring your own safety guarantees. @@ -880,6 +949,28 @@ impl Event { } } + Event::Display { + timestamp, + display_index, + display_event, + } => { + let (display_event_id, data1) = display_event.to_ll(); + let event = sys::SDL_DisplayEvent { + type_: SDL_EventType::SDL_DISPLAYEVENT as u32, + timestamp, + display: display_index as u32, + event: display_event_id, + padding1: 0, + padding2: 0, + padding3: 0, + data1, + }; + unsafe { + ptr::copy(&event, ret.as_mut_ptr() as *mut sys::SDL_DisplayEvent, 1); + Some(ret.assume_init()) + } + } + Event::Window { timestamp, window_id, @@ -1389,6 +1480,15 @@ impl Event { } } + EventType::Display => { + let event = raw.display; + + Event::Display { + timestamp: event.timestamp, + display_index: event.display as i32, + display_event: DisplayEvent::from_ll(event.event, event.data1), + } + } EventType::Window => { let event = raw.window; @@ -1885,6 +1985,7 @@ impl Event { | (Self::AppDidEnterBackground { .. }, Self::AppDidEnterBackground { .. }) | (Self::AppWillEnterForeground { .. }, Self::AppWillEnterForeground { .. }) | (Self::AppDidEnterForeground { .. }, Self::AppDidEnterForeground { .. }) + | (Self::Display { .. }, Self::Display { .. }) | (Self::Window { .. }, Self::Window { .. }) | (Self::KeyDown { .. }, Self::KeyDown { .. }) | (Self::KeyUp { .. }, Self::KeyUp { .. }) @@ -1953,6 +2054,7 @@ impl Event { Self::AppDidEnterBackground { timestamp, .. } => timestamp, Self::AppWillEnterForeground { timestamp, .. } => timestamp, Self::AppDidEnterForeground { timestamp, .. } => timestamp, + Self::Display { timestamp, .. } => timestamp, Self::Window { timestamp, .. } => timestamp, Self::KeyDown { timestamp, .. } => timestamp, Self::KeyUp { timestamp, .. } => timestamp, @@ -2496,7 +2598,7 @@ impl crate::EventPump { /// for event in event_pump.poll_iter() { /// use sdl2::event::Event; /// match event { - /// Event::KeyDown {..} => { /*...*/ }, + /// Event::KeyDown {..} => { /*...*/ } /// _ => () /// } /// } @@ -2608,6 +2710,8 @@ mod test { use super::super::joystick::HatState; use super::super::keyboard::{Keycode, Mod, Scancode}; use super::super::mouse::{MouseButton, MouseState, MouseWheelDirection}; + use super::super::video::Orientation; + use super::DisplayEvent; use super::Event; use super::WindowEvent; @@ -2620,6 +2724,15 @@ mod test { let e2 = Event::from_ll(e.clone().to_ll().unwrap()); assert_eq!(e, e2); } + { + let e = Event::Display { + timestamp: 0, + display_index: 1, + display_event: DisplayEvent::Orientation(Orientation::LandscapeFlipped), + }; + let e2 = Event::from_ll(e.clone().to_ll().unwrap()); + assert_eq!(e, e2); + } { let e = Event::Window { timestamp: 0, diff --git a/src/sdl2/video.rs b/src/sdl2/video.rs index 7e75ecb99d..e22925144e 100644 --- a/src/sdl2/video.rs +++ b/src/sdl2/video.rs @@ -591,6 +591,52 @@ impl From for SwapInterval { } } +/// Represents orientation of a display. +#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] +#[repr(i32)] +pub enum Orientation { + /// The display orientation can’t be determined + Unknown = sys::SDL_DisplayOrientation::SDL_ORIENTATION_UNKNOWN as i32, + /// The display is in landscape mode, with the right side up, relative to portrait mode + Landscape = sys::SDL_DisplayOrientation::SDL_ORIENTATION_LANDSCAPE as i32, + /// The display is in landscape mode, with the left side up, relative to portrait mode + LandscapeFlipped = sys::SDL_DisplayOrientation::SDL_ORIENTATION_LANDSCAPE_FLIPPED as i32, + /// The display is in portrait mode + Portrait = sys::SDL_DisplayOrientation::SDL_ORIENTATION_PORTRAIT as i32, + /// The display is in portrait mode, upside down + PortraitFlipped = sys::SDL_DisplayOrientation::SDL_ORIENTATION_PORTRAIT_FLIPPED as i32, +} + +impl Orientation { + pub fn from_ll(orientation: sys::SDL_DisplayOrientation) -> Orientation { + match orientation { + sys::SDL_DisplayOrientation::SDL_ORIENTATION_UNKNOWN => Orientation::Unknown, + sys::SDL_DisplayOrientation::SDL_ORIENTATION_LANDSCAPE => Orientation::Landscape, + sys::SDL_DisplayOrientation::SDL_ORIENTATION_LANDSCAPE_FLIPPED => { + Orientation::LandscapeFlipped + } + sys::SDL_DisplayOrientation::SDL_ORIENTATION_PORTRAIT => Orientation::Portrait, + sys::SDL_DisplayOrientation::SDL_ORIENTATION_PORTRAIT_FLIPPED => { + Orientation::PortraitFlipped + } + } + } + + pub fn to_ll(self) -> sys::SDL_DisplayOrientation { + match self { + Orientation::Unknown => sys::SDL_DisplayOrientation::SDL_ORIENTATION_UNKNOWN, + Orientation::Landscape => sys::SDL_DisplayOrientation::SDL_ORIENTATION_LANDSCAPE, + Orientation::LandscapeFlipped => { + sys::SDL_DisplayOrientation::SDL_ORIENTATION_LANDSCAPE_FLIPPED + } + Orientation::Portrait => sys::SDL_DisplayOrientation::SDL_ORIENTATION_PORTRAIT, + Orientation::PortraitFlipped => { + sys::SDL_DisplayOrientation::SDL_ORIENTATION_PORTRAIT_FLIPPED + } + } + } +} + /// Represents the "shell" of a `Window`. /// /// You can set get and set many of the `SDL_Window` properties (i.e., border, size, `PixelFormat`, etc) @@ -781,6 +827,12 @@ impl VideoSubsystem { } } + /// Return orientation of a display or Unknown if orientation could not be determined. + #[doc(alias = "SDL_GetDisplayOrientation")] + pub fn display_orientation(&self, display_index: i32) -> Orientation { + Orientation::from_ll(unsafe { sys::SDL_GetDisplayOrientation(display_index as c_int) }) + } + #[doc(alias = "SDL_IsScreenSaverEnabled")] pub fn is_screen_saver_enabled(&self) -> bool { unsafe { sys::SDL_IsScreenSaverEnabled() == sys::SDL_bool::SDL_TRUE }