use crate::*;
use phosphor::*;
use std::collections::VecDeque;
const CONTROL: u8 = 0x80;
const ALT: u8 = 0x40;
const SHIFT: u8 = 0x20;
const UP: u8 = 0x80;
const DOWN: u8 = 0x40;
const LEFT: u8 = 0x20;
const RIGHT: u8 = 0x10;
const CONFIRM: u8 = 0x08;
const CANCEL: u8 = 0x04;
const NEXT: u8 = 0x02;
const PREVIOUS: u8 = 0x01;
macro_rules! test { ($value:expr, $mask:expr) => { $value & $mask != 0 }; }
pub struct InputDevice {
pub wake_flag: bool,
pub pointer_position: ScreenPosition,
pub pointer_buttons: u8,
pub pointer_active: bool,
pub horizontal_scroll: i8,
pub vertical_scroll: i8,
pub horizontal_scroll_delta: f64,
pub vertical_scroll_delta: f64,
pub text_queue: VecDeque<u8>,
pub modifiers: u8,
pub navigation: u8,
pub controller_1: u8,
pub controller_2: u8,
pub controller_3: u8,
pub controller_4: u8,
}
impl InputDevice {
pub fn new() -> Self {
Self {
wake_flag: false,
pointer_position: ScreenPosition::ZERO,
pointer_buttons: 0x00,
pointer_active: false,
horizontal_scroll: 0x00,
vertical_scroll: 0x00,
horizontal_scroll_delta: 0.0,
vertical_scroll_delta: 0.0,
text_queue: VecDeque::new(),
modifiers: 0x00,
navigation: 0x00,
controller_1: 0x00,
controller_2: 0x00,
controller_3: 0x00,
controller_4: 0x00,
}
}
pub fn read_horizontal_scroll(&mut self) -> u8 {
std::mem::take(&mut self.horizontal_scroll) as u8
}
pub fn read_vertical_scroll(&mut self) -> u8 {
std::mem::take(&mut self.vertical_scroll) as u8
}
pub fn on_pointer_button(&mut self, mask: u8, action: Action) {
let new_buttons = match action {
Action::Pressed => self.pointer_buttons | mask,
Action::Released => self.pointer_buttons & !mask,
};
if new_buttons != self.pointer_buttons {
self.pointer_buttons = new_buttons;
self.wake_flag = true;
}
}
pub fn on_pointer_move(&mut self, position: ScreenPosition) {
if position != self.pointer_position {
self.pointer_position = position;
self.wake_flag = true;
}
}
pub fn on_scroll_horizontal(&mut self, delta: f64) {
self.horizontal_scroll_delta += delta;
while self.horizontal_scroll_delta >= 1.0 {
self.horizontal_scroll = self.horizontal_scroll.saturating_add(1);
self.horizontal_scroll_delta -= 1.0;
self.wake_flag = true;
}
while self.horizontal_scroll_delta <= -1.0 {
self.horizontal_scroll = self.horizontal_scroll.saturating_sub(1);
self.horizontal_scroll_delta += 1.0;
self.wake_flag = true;
}
}
pub fn on_scroll_vertical(&mut self, delta: f64) {
self.vertical_scroll_delta += delta;
while self.vertical_scroll_delta >= 1.0 {
self.vertical_scroll = self.vertical_scroll.saturating_add(1);
self.vertical_scroll_delta -= 1.0;
self.wake_flag = true;
}
while self.vertical_scroll_delta <= -1.0 {
self.vertical_scroll = self.vertical_scroll.saturating_sub(1);
self.vertical_scroll_delta += 1.0;
self.wake_flag = true;
}
}
pub fn on_character_input(&mut self, input: char) {
if let Ok(byte) = u8::try_from(u32::from(input)) {
self.text_queue.push_back(byte);
self.wake_flag = true;
}
}
pub fn on_keyboard_input(&mut self, input: KeyboardInput) {
let mask = match input.key {
KeyCode::Up => UP,
KeyCode::Down => DOWN,
KeyCode::Left => LEFT,
KeyCode::Right => RIGHT,
KeyCode::Return => CONFIRM,
KeyCode::Escape => CANCEL,
KeyCode::Tab => match test!(self.modifiers, SHIFT) {
false => NEXT,
true => PREVIOUS
},
_ => return,
};
let navigation = match input.action {
Action::Pressed => self.navigation | mask,
Action::Released => self.navigation & !mask,
};
if navigation != self.navigation {
self.navigation = navigation;
self.wake_flag = true;
}
}
pub fn on_modifier_change(&mut self, modifiers: ModifiersState) {
let mut new_modifiers = 0x00;
if modifiers.ctrl() { new_modifiers |= CONTROL }
if modifiers.alt() { new_modifiers |= ALT }
if modifiers.shift() { new_modifiers |= SHIFT }
if new_modifiers != self.modifiers {
self.modifiers = new_modifiers;
self.wake_flag = true;
}
}
}