use crate::geom::Vector;
pub use blinds::event::{
FocusChangedEvent, GamepadAxisEvent, GamepadButtonEvent, GamepadConnectedEvent,
GamepadDisconnectedEvent, KeyboardEvent, ModifiersChangedEvent, PointerEnteredEvent,
PointerInputEvent, PointerLeftEvent, ReceivedCharacterEvent, ScaleFactorChangedEvent,
ScrollDelta,
};
#[cfg(feature = "event-cache")]
use blinds::event_cache::EventCache;
#[cfg(feature = "event-cache")]
pub use blinds::event_cache::GamepadState;
pub use blinds::{GamepadAxis, GamepadButton, GamepadId, Key, MouseButton, PointerId};
pub struct Input {
source: blinds::EventStream,
#[cfg(feature = "event-cache")]
cache: EventCache,
}
impl Input {
pub(crate) fn new(source: blinds::EventStream) -> Input {
Input {
source,
#[cfg(feature = "event-cache")]
cache: EventCache::new(),
}
}
pub async fn next_event(&mut self) -> Option<Event> {
while let Some(ev) = self.source.next_event().await {
#[cfg(feature = "event-cache")]
self.cache.process_event(&ev);
if let Some(ev) = conv(ev) {
return Some(ev);
}
}
None
}
}
#[cfg(feature = "event-cache")]
impl Input {
pub fn key_down(&self, key: Key) -> bool {
self.cache.key(key)
}
pub fn mouse(&self) -> PointerState {
self.cache.mouse().into()
}
#[allow(clippy::trivially_copy_pass_by_ref)]
pub fn pointer(&self, id: &PointerId) -> Option<PointerState> {
self.cache.pointer(id).map(|p| p.into())
}
pub fn pointers(&self) -> impl Iterator<Item = (&PointerId, PointerState)> {
self.cache.pointers().map(|(id, p)| (id, p.into()))
}
pub fn gamepad(&self, id: &GamepadId) -> Option<&GamepadState> {
self.cache.gamepad(id)
}
pub fn gamepads(&self) -> impl Iterator<Item = (&GamepadId, &GamepadState)> {
self.cache.gamepads()
}
}
#[cfg(feature = "event-cache")]
pub struct PointerState {
left: bool,
right: bool,
middle: bool,
location: Vector,
}
#[cfg(feature = "event-cache")]
impl PointerState {
pub fn left(&self) -> bool {
self.left
}
pub fn right(&self) -> bool {
self.right
}
pub fn middle(&self) -> bool {
self.middle
}
pub fn location(&self) -> Vector {
self.location
}
}
#[cfg(feature = "event-cache")]
impl From<&blinds::event_cache::PointerState> for PointerState {
fn from(ps: &blinds::event_cache::PointerState) -> PointerState {
PointerState {
left: ps.left(),
right: ps.right(),
middle: ps.middle(),
location: ps.location().into(),
}
}
}
#[derive(Clone, Debug)]
#[non_exhaustive]
pub enum Event {
Resized(ResizedEvent),
ScaleFactorChanged(ScaleFactorChangedEvent),
FocusChanged(FocusChangedEvent),
ReceivedCharacter(ReceivedCharacterEvent),
KeyboardInput(KeyboardEvent),
PointerEntered(PointerEnteredEvent),
PointerLeft(PointerLeftEvent),
PointerMoved(PointerMovedEvent),
PointerInput(PointerInputEvent),
ScrollInput(ScrollDelta),
ModifiersChanged(ModifiersChangedEvent),
GamepadConnected(GamepadConnectedEvent),
GamepadDisconnected(GamepadDisconnectedEvent),
GamepadButton(GamepadButtonEvent),
GamepadAxis(GamepadAxisEvent),
}
#[derive(Clone, Debug)]
pub struct ResizedEvent {
size: Vector,
}
impl ResizedEvent {
pub fn size(&self) -> Vector {
self.size
}
}
#[derive(Clone, Debug)]
pub struct PointerMovedEvent {
id: PointerId,
location: Vector,
}
impl PointerMovedEvent {
pub fn pointer(&self) -> &PointerId {
&self.id
}
pub fn location(&self) -> Vector {
self.location
}
}
fn conv(ev: blinds::Event) -> Option<Event> {
use Event::*;
Some(match ev {
blinds::Event::Resized(x) => Resized(ResizedEvent {
size: x.logical_size().into(),
}),
blinds::Event::ScaleFactorChanged(x) => ScaleFactorChanged(x),
blinds::Event::FocusChanged(x) => FocusChanged(x),
blinds::Event::ReceivedCharacter(x) => ReceivedCharacter(x),
blinds::Event::KeyboardInput(x) => KeyboardInput(x),
blinds::Event::PointerEntered(x) => PointerEntered(x),
blinds::Event::PointerLeft(x) => PointerLeft(x),
blinds::Event::PointerMoved(x) => PointerMoved(PointerMovedEvent {
id: *x.pointer(),
location: x.location().into(),
}),
blinds::Event::PointerInput(x) => PointerInput(x),
blinds::Event::ScrollInput(x) => ScrollInput(x),
blinds::Event::ModifiersChanged(x) => ModifiersChanged(x),
blinds::Event::GamepadConnected(x) => GamepadConnected(x),
blinds::Event::GamepadDisconnected(x) => GamepadDisconnected(x),
blinds::Event::GamepadButton(x) => GamepadButton(x),
blinds::Event::GamepadAxis(x) => GamepadAxis(x),
_ => return None,
})
}