moa/emulator/libraries/host/src/mouse.rs

110 lines
2.8 KiB
Rust

#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum MouseButton {
Left,
Right,
Middle,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum MouseEventType {
Down(MouseButton),
Up(MouseButton),
Move,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct MouseEvent {
pub etype: MouseEventType,
pub pos: (u32, u32),
}
#[derive(Copy, Clone, Default, PartialEq, Eq)]
pub struct MouseState {
pub buttons: [bool; 3],
pub pos: (u32, u32),
}
impl MouseEvent {
pub fn new(etype: MouseEventType, pos: (u32, u32)) -> Self {
Self {
etype,
pos,
}
}
}
impl From<usize> for MouseButton {
fn from(index: usize) -> MouseButton {
match index {
0 => MouseButton::Left,
1 => MouseButton::Right,
2 => MouseButton::Middle,
_ => panic!("unexpected mouse button index: {:?}", index),
}
}
}
impl From<MouseButton> for usize {
fn from(button: MouseButton) -> usize {
match button {
MouseButton::Left => 0,
MouseButton::Right => 1,
MouseButton::Middle => 2,
}
}
}
impl MouseState {
pub fn with(left: bool, right: bool, middle: bool, x: u32, y: u32) -> Self {
Self {
buttons: [left, right, middle],
pos: (x, y),
}
}
pub fn to_events(&mut self, next_state: MouseState) -> Vec<MouseEvent> {
if *self != next_state {
self.pos = next_state.pos;
let events: Vec<MouseEvent> = self
.buttons.into_iter()
.zip(next_state.buttons.into_iter())
.enumerate()
.filter_map(|(i, (prev, next))| {
if prev != next {
self.buttons[i] = next;
let button = MouseButton::from(i);
let etype = if next {
MouseEventType::Down(button)
} else {
MouseEventType::Up(button)
};
Some(MouseEvent::new(etype, next_state.pos))
} else {
None
}
})
.collect();
if !events.is_empty() {
events
} else {
vec![MouseEvent::new(MouseEventType::Move, next_state.pos)]
}
} else {
vec![]
}
}
pub fn update_with(&mut self, event: MouseEvent) {
self.pos = event.pos;
match event.etype {
MouseEventType::Up(button) => self.buttons[usize::from(button)] = false,
MouseEventType::Down(button) => self.buttons[usize::from(button)] = true,
MouseEventType::Move => { },
}
}
}