use qualia::{modifier, CatchResult, InputCode, InputValue, KeyState};
use qualia::{InputForwarding, InputHandling};
use inputs::codes;
use virtual_terminal::VirtualTerminal;
pub struct InputGateway {
modifiers: modifier::ModifierType,
handler: Box<InputHandling>,
forwarder: Box<InputForwarding>,
vt: Option<VirtualTerminal>,
modifier_keys: Vec<(InputCode, modifier::ModifierType)>,
}
impl InputGateway {
pub fn new(handler: Box<InputHandling>,
forwarder: Box<InputForwarding>,
vt: Option<VirtualTerminal>)
-> Self {
InputGateway {
modifiers: modifier::NONE,
handler: handler,
forwarder: forwarder,
vt: vt,
modifier_keys: vec![(codes::KEY_LEFTCTRL as InputCode, modifier::LCTL),
(codes::KEY_RIGHTCTRL as InputCode, modifier::RCTL),
(codes::KEY_LEFTSHIFT as InputCode, modifier::LSHF),
(codes::KEY_RIGHTSHIFT as InputCode, modifier::RSHF),
(codes::KEY_LEFTALT as InputCode, modifier::LALT),
(codes::KEY_RIGHTALT as InputCode, modifier::RALT),
(codes::KEY_LEFTMETA as InputCode, modifier::LMTA),
(codes::KEY_RIGHTMETA as InputCode, modifier::RMTA)],
}
}
}
impl InputForwarding for InputGateway {
fn emit_key(&mut self, code: u16, value: i32) {
if (value != KeyState::Pressed as InputValue) && (value != KeyState::Released as InputValue) {
return;
}
if self.update_modifiers(code, value) != CatchResult::Passed {
return;
}
if self.catch_key(code, value) != CatchResult::Passed {
return;
}
if self.handler.catch_key(code, value, self.modifiers) == CatchResult::Passed {
self.forwarder.emit_key(code, value);
}
}
fn emit_motion(&mut self, x: isize, y: isize) {
self.forwarder.emit_motion(x, y);
}
fn emit_position(&mut self, x: Option<isize>, y: Option<isize>) {
self.forwarder.emit_position(x, y);
}
fn emit_button(&mut self, code: u16, value: i32) {
if self.handler.catch_button(code, value, self.modifiers) == CatchResult::Passed {
self.forwarder.emit_button(code, value);
}
}
fn emit_axis(&mut self, horizontal: isize, vertical: isize) {
self.forwarder.emit_axis(horizontal, vertical);
}
fn emit_position_reset(&mut self) {
self.forwarder.emit_position_reset();
}
fn emit_system_activity_event(&mut self) {
self.forwarder.emit_system_activity_event();
}
}
impl InputGateway {
fn update_modifiers(&mut self, code: InputCode, value: InputValue) -> CatchResult {
let mut result = CatchResult::Passed;
for &(modifier_code, modifier_flag) in self.modifier_keys.iter() {
if code == modifier_code {
if value == KeyState::Pressed as InputValue {
if (self.modifiers & modifier_flag) != 0x0 {
result = CatchResult::Caught;
} else {
self.modifiers |= modifier_flag;
}
} else {
self.modifiers &= !modifier_flag;
}
break;
}
}
result
}
fn catch_key(&self, code: InputCode, value: InputValue) -> CatchResult {
if (codes::KEY_F1 <= code) && (code <= codes::KEY_F12) {
if (self.modifiers == (modifier::LALT | modifier::LCTL)) ||
(self.modifiers == (modifier::LALT | modifier::RCTL)) ||
(self.modifiers == (modifier::RALT | modifier::LCTL)) ||
(self.modifiers == (modifier::RALT | modifier::RCTL)) {
if value == KeyState::Pressed as InputValue {
self.switch_vt((code + 1 - codes::KEY_F1) as i32);
}
return CatchResult::Caught;
}
}
CatchResult::Passed
}
fn switch_vt(&self, num: i32) {
log_info1!("Switching to virtual terminal {}", num);
if let Some(vt) = self.vt {
if let Err(err) = vt.switch_to(num as u8) {
log_warn1!("Failed to switch terminals: {:?}", err);
}
} else {
log_warn1!("Virtual terminals were not set up properly");
}
}
}