pub mod qwery;
pub use self::qwery::*;
use std::time::Duration;
use std::thread;
use std::sync::Arc;
use std::time::Instant;
use Basalt;
use crossbeam::channel::{self,Sender};
use std::collections::{BTreeMap,HashMap};
use std::sync::atomic::{self,AtomicUsize};
use interface::hook::InputEvent as ItfInputEvent;
pub type InputHookID = u64;
pub type InputHookFn = Arc<dyn Fn(&InputHookData) -> InputHookRes + Send + Sync>;
#[derive(Debug,Clone,PartialEq,Eq)]
pub enum InputHookRes {
Remove,
Success,
Warning(String),
Error(String),
}
#[derive(Debug,Clone,Copy,PartialEq,Eq,Hash)]
pub enum MouseButton {
Left,
Right,
Middle,
Other(u8),
}
#[derive(Debug,Clone,Copy,PartialEq,Eq)]
pub enum KeyOrMouseButton {
Key(Qwery),
MouseButton(MouseButton),
}
#[derive(Debug,Clone,PartialEq)]
pub enum InputHook {
Press {
global: bool,
keys: Vec<Qwery>,
mouse_buttons: Vec<MouseButton>,
},
Hold {
global: bool,
keys: Vec<Qwery>,
mouse_buttons: Vec<MouseButton>,
initial_delay: Duration,
interval: Duration,
accel: f32,
},
Release {
global: bool,
keys: Vec<Qwery>,
mouse_buttons: Vec<MouseButton>,
},
Character,
MouseEnter,
MouseLeave,
MouseMove,
MouseMotion,
MouseScroll,
WindowFocused,
WindowLostFocus,
AnyMouseOrKeyPress {
global: bool,
},
AnyMousePress {
global: bool,
},
AnyKeyPress {
global: bool,
},
AnyMouseOrKeyRelease {
global: bool,
},
AnyMouseRelease {
global: bool,
},
AnyKeyRelease {
global: bool,
},
}
impl InputHook {
pub fn into_data(&self) -> InputHookData {
match self {
InputHook::Press {
global,
keys,
mouse_buttons,
} => {
let mut key_active = HashMap::new();
let mut mouse_active = HashMap::new();
for key in keys {
key_active.insert(*key, false);
}
for button in mouse_buttons {
mouse_active.insert(*button, false);
}
InputHookData::Press {
global: *global,
mouse_x: 0.0,
mouse_y: 0.0,
key_active,
mouse_active,
}
},
InputHook::Hold {
global,
keys,
mouse_buttons,
initial_delay,
interval,
accel,
} => {
let mut key_active = HashMap::new();
let mut mouse_active = HashMap::new();
for key in keys {
key_active.insert(*key, false);
}
for button in mouse_buttons {
mouse_active.insert(*button, false);
}
InputHookData::Hold {
global: *global,
active: false,
mouse_x: 0.0,
mouse_y: 0.0,
first_call: Instant::now(),
last_call: Instant::now(),
is_first_call: true,
initial_delay: initial_delay.clone(),
initial_delay_elapsed: false,
interval: interval.clone(),
accel: *accel,
key_active,
mouse_active,
}
},
InputHook::Release {
global,
keys,
mouse_buttons,
} => {
let mut key_active = HashMap::new();
let mut mouse_active = HashMap::new();
for key in keys {
key_active.insert(*key, false);
}
for button in mouse_buttons {
mouse_active.insert(*button, false);
}
InputHookData::Release {
global: *global,
pressed: false,
key_active,
mouse_active,
}
},
InputHook::Character => {
InputHookData::Character {
character: Character::Value(' '),
}
},
InputHook::MouseEnter => {
InputHookData::MouseEnter {
mouse_x: 0.0,
mouse_y: 0.0,
}
},
InputHook::MouseLeave => {
InputHookData::MouseLeave {
mouse_x: 0.0,
mouse_y: 0.0,
}
},
InputHook::MouseMove => {
InputHookData::MouseMove {
mouse_x: 0.0,
mouse_y: 0.0,
mouse_dx: 0.0,
mouse_dy: 0.0,
}
},
InputHook::MouseMotion => {
InputHookData::MouseMotion {
x: 0.0,
y: 0.0,
}
},
InputHook::MouseScroll => {
InputHookData::MouseScroll {
scroll_amt: 0.0,
mouse_x: 0.0,
mouse_y: 0.0,
}
},
InputHook::WindowFocused => InputHookData::WindowFocused,
InputHook::WindowLostFocus => InputHookData::WindowLostFocus,
InputHook::AnyMouseOrKeyPress {
global,
} => {
InputHookData::AnyMouseOrKeyPress {
global: *global,
either: KeyOrMouseButton::Key(Qwery::Space),
}
}
InputHook::AnyMousePress {
global,
} => {
InputHookData::AnyMousePress {
global: *global,
button: MouseButton::Left,
}
},
InputHook::AnyKeyPress {
global,
} => {
InputHookData::AnyKeyPress {
global: *global,
key: Qwery::Space,
}
},
InputHook::AnyMouseOrKeyRelease {
global,
} => {
InputHookData::AnyMouseOrKeyRelease {
global: *global,
either: KeyOrMouseButton::Key(Qwery::Space),
}
},
InputHook::AnyMouseRelease {
global,
} => {
InputHookData::AnyMouseRelease {
global: *global,
button: MouseButton::Left,
}
},
InputHook::AnyKeyRelease {
global,
} => {
InputHookData::AnyKeyRelease {
global: *global,
key: Qwery::Space,
}
},
}
}
pub fn ty(&self) -> InputHookTy {
match self {
InputHook::Press { .. } => InputHookTy::Press,
InputHook::Hold { .. } => InputHookTy::Hold,
InputHook::Release { .. } => InputHookTy::Release,
InputHook::Character => InputHookTy::Character,
InputHook::MouseEnter => InputHookTy::MouseEnter,
InputHook::MouseLeave => InputHookTy::MouseLeave,
InputHook::MouseMove => InputHookTy::MouseMove,
InputHook::MouseMotion { .. } => InputHookTy::MouseMotion,
InputHook::MouseScroll => InputHookTy::MouseScroll,
InputHook::WindowFocused => InputHookTy::WindowFocused,
InputHook::WindowLostFocus => InputHookTy::WindowLostFocus,
InputHook::AnyMouseOrKeyPress { .. } => InputHookTy::AnyMouseOrKeyPress,
InputHook::AnyMousePress { .. } => InputHookTy::AnyMousePress,
InputHook::AnyKeyPress { .. } => InputHookTy::AnyKeyPress,
InputHook::AnyMouseOrKeyRelease { .. } => InputHookTy::AnyMouseOrKeyRelease,
InputHook::AnyMouseRelease { .. } => InputHookTy::AnyMouseRelease,
InputHook::AnyKeyRelease { .. } => InputHookTy::AnyKeyRelease,
}
}
}
#[derive(Debug,Clone,PartialEq,Eq)]
pub enum InputHookTy {
Press,
Hold,
Release,
Character,
MouseEnter,
MouseLeave,
MouseMove,
MouseMotion,
MouseScroll,
WindowFocused,
WindowLostFocus,
AnyMouseOrKeyPress,
AnyMousePress,
AnyKeyPress,
AnyMouseOrKeyRelease,
AnyMouseRelease,
AnyKeyRelease,
}
#[derive(Debug,Clone)]
pub enum InputHookData {
Press {
global: bool,
mouse_x: f32,
mouse_y: f32,
key_active: HashMap<Qwery, bool>,
mouse_active: HashMap<MouseButton, bool>,
},
Hold {
global: bool,
active: bool,
mouse_x: f32,
mouse_y: f32,
first_call: Instant,
last_call: Instant,
is_first_call: bool,
initial_delay: Duration,
initial_delay_elapsed: bool,
interval: Duration,
accel: f32,
key_active: HashMap<Qwery, bool>,
mouse_active: HashMap<MouseButton, bool>,
},
Release {
global: bool,
pressed: bool,
key_active: HashMap<Qwery, bool>,
mouse_active: HashMap<MouseButton, bool>,
},
Character {
character: Character,
},
MouseEnter {
mouse_x: f32,
mouse_y: f32,
},
MouseLeave {
mouse_x: f32,
mouse_y: f32,
},
MouseMove {
mouse_x: f32,
mouse_y: f32,
mouse_dx: f32,
mouse_dy: f32,
},
MouseMotion {
x: f32,
y: f32,
},
MouseScroll {
mouse_x: f32,
mouse_y: f32,
scroll_amt: f32,
},
WindowFocused,
WindowLostFocus,
AnyMouseOrKeyPress {
global: bool,
either: KeyOrMouseButton
},
AnyMousePress {
global: bool,
button: MouseButton,
},
AnyKeyPress {
global: bool,
key: Qwery,
},
AnyMouseOrKeyRelease {
global: bool,
either: KeyOrMouseButton
},
AnyMouseRelease {
global: bool,
button: MouseButton,
},
AnyKeyRelease {
global: bool,
key: Qwery,
},
}
impl InputHookData {
pub fn ty(&self) -> InputHookTy {
match self {
InputHookData::Press { .. } => InputHookTy::Press,
InputHookData::Hold { .. } => InputHookTy::Hold,
InputHookData::Release { .. } => InputHookTy::Release,
InputHookData::Character { .. } => InputHookTy::Character,
InputHookData::MouseEnter { .. } => InputHookTy::MouseEnter,
InputHookData::MouseLeave { .. } => InputHookTy::MouseLeave,
InputHookData::MouseMove { .. } => InputHookTy::MouseMove,
InputHookData::MouseMotion { .. } => InputHookTy::MouseMotion,
InputHookData::MouseScroll { .. } => InputHookTy::MouseScroll,
InputHookData::WindowFocused => InputHookTy::WindowFocused,
InputHookData::WindowLostFocus => InputHookTy::WindowLostFocus,
InputHookData::AnyMouseOrKeyPress { .. } => InputHookTy::AnyMouseOrKeyPress,
InputHookData::AnyMousePress { .. } => InputHookTy::AnyMousePress,
InputHookData::AnyKeyPress { .. } => InputHookTy::AnyKeyPress,
InputHookData::AnyMouseOrKeyRelease { .. } => InputHookTy::AnyMouseOrKeyRelease,
InputHookData::AnyMouseRelease { .. } => InputHookTy::AnyMouseRelease,
InputHookData::AnyKeyRelease { .. } => InputHookTy::AnyKeyRelease,
}
}
pub fn cond_met(&self) -> bool {
match self {
InputHookData::Press {
key_active,
mouse_active,
..
} => {
for v in key_active.values() {
if !v {
return false;
}
}
for v in mouse_active.values() {
if !v {
return false;
}
}
},
InputHookData::Hold {
key_active,
mouse_active,
..
} => {
for v in key_active.values() {
if !v {
return false;
}
}
for v in mouse_active.values() {
if !v {
return false;
}
}
},
InputHookData::Release {
key_active,
mouse_active,
..
} => {
for v in key_active.values() {
if !v {
return false;
}
}
for v in mouse_active.values() {
if !v {
return false;
}
}
},
_ => ()
}
true
}
}
pub enum Event {
KeyPress(Qwery),
KeyRelease(Qwery),
MousePress(MouseButton),
MouseRelease(MouseButton),
MouseMotion(f32, f32),
MousePosition(f32, f32),
MouseScroll(f32),
MouseEnter,
MouseLeave,
WindowResized,
WindowFocused,
WindowLostFocus,
AddHook(InputHookID, InputHook, InputHookFn),
DelHook(InputHookID),
}
pub struct Input {
basalt: Arc<Basalt>,
event_send: Sender<Event>,
hook_id_count: AtomicUsize,
}
impl Input {
pub fn send_event(&self, event: Event) {
self.event_send.send(event).unwrap();
}
pub fn add_hook(&self, hook: InputHook, func: InputHookFn) -> InputHookID {
let id = self.hook_id_count.fetch_add(1, atomic::Ordering::SeqCst) as u64;
self.event_send.send(Event::AddHook(id, hook, func)).unwrap();
id
}
pub fn remove_hook(&self, id: InputHookID) {
self.event_send.send(Event::DelHook(id)).unwrap();
}
pub fn on_key_press(&self, key: Qwery, func: InputHookFn) -> InputHookID {
self.on_key_combo_press(vec![key], func)
}
pub fn on_key_hold(&self, key: Qwery, init: Duration, int: Duration, func: InputHookFn) -> InputHookID {
self.on_key_combo_hold(vec![key], init, int, func)
}
pub fn on_key_release(&self, key: Qwery, func: InputHookFn) -> InputHookID {
self.on_key_combo_release(vec![key], func)
}
pub fn on_key_combo_press(&self, combo: Vec<Qwery>, func: InputHookFn) -> InputHookID {
let id = self.hook_id_count.fetch_add(1, atomic::Ordering::SeqCst) as u64;
self.event_send.send(Event::AddHook(id, InputHook::Press {
global: false,
keys: combo,
mouse_buttons: Vec::new()
}, func)).unwrap();
id
}
pub fn on_key_combo_hold(&self, combo: Vec<Qwery>, init: Duration, int: Duration, func: InputHookFn) -> InputHookID {
let id = self.hook_id_count.fetch_add(1, atomic::Ordering::SeqCst) as u64;
self.event_send.send(Event::AddHook(id, InputHook::Hold {
global: false,
keys: combo,
mouse_buttons: Vec::new(),
initial_delay: init,
interval: int,
accel: 0.0,
}, func)).unwrap();
id
}
pub fn on_key_combo_release(&self, combo: Vec<Qwery>, func: InputHookFn) -> InputHookID {
let id = self.hook_id_count.fetch_add(1, atomic::Ordering::SeqCst) as u64;
self.event_send.send(Event::AddHook(id, InputHook::Release {
global: false,
keys: combo,
mouse_buttons: Vec::new()
}, func)).unwrap();
id
}
pub fn on_mouse_press(&self, button: MouseButton, func: InputHookFn) -> InputHookID {
let id = self.hook_id_count.fetch_add(1, atomic::Ordering::SeqCst) as u64;
self.event_send.send(Event::AddHook(id, InputHook::Press {
global: false,
keys: Vec::new(),
mouse_buttons: vec![button],
}, func)).unwrap();
id
}
pub fn on_mouse_hold(&self, button: MouseButton, init: Duration, int: Duration, func: InputHookFn) -> InputHookID {
let id = self.hook_id_count.fetch_add(1, atomic::Ordering::SeqCst) as u64;
self.event_send.send(Event::AddHook(id, InputHook::Hold {
global: false,
keys: Vec::new(),
mouse_buttons: vec![button],
initial_delay: init,
interval: int,
accel: 0.0,
}, func)).unwrap();
id
}
pub fn on_mouse_release(&self, button: MouseButton, func: InputHookFn) -> InputHookID {
let id = self.hook_id_count.fetch_add(1, atomic::Ordering::SeqCst) as u64;
self.event_send.send(Event::AddHook(id, InputHook::Release {
global: false,
keys: Vec::new(),
mouse_buttons: vec![button]
}, func)).unwrap();
id
}
pub(crate) fn new(basalt: Arc<Basalt>) -> Arc<Self> {
let (event_send, event_recv) = channel::unbounded();
let input_ret = Arc::new(Input {
basalt,
event_send,
hook_id_count: AtomicUsize::new(0),
});
let input = input_ret.clone();
unsafe {
use std::mem::transmute;
let interface = input.basalt.interface();
input.add_hook(InputHook::AnyKeyPress { global: false }, Arc::new(move |data| {
if let InputHookData::AnyKeyPress { key, .. } = data {
interface.hook_manager.send_event(ItfInputEvent::KeyPress(key.clone()));
}
InputHookRes::Success
}));
let interface = input.basalt.interface();
input.add_hook(InputHook::AnyKeyRelease { global: false }, Arc::new(move |data| {
if let InputHookData::AnyKeyRelease { key, .. } = data {
interface.hook_manager.send_event(ItfInputEvent::KeyRelease(key.clone()));
}
InputHookRes::Success
}));
let interface = input.basalt.interface();
input.add_hook(InputHook::AnyMousePress { global: false }, Arc::new(move |data| {
if let InputHookData::AnyMousePress { button, .. } = data {
interface.hook_manager.send_event(ItfInputEvent::MousePress(transmute(button.clone())));
}
InputHookRes::Success
}));
let interface = input.basalt.interface();
input.add_hook(InputHook::AnyMouseRelease { global: false }, Arc::new(move |data| {
if let InputHookData::AnyMouseRelease { button, .. } = data {
interface.hook_manager.send_event(ItfInputEvent::MouseRelease(transmute(button.clone())));
}
InputHookRes::Success
}));
let interface = input.basalt.interface();
input.add_hook(InputHook::MouseMove, Arc::new(move |data| {
if let InputHookData::MouseMove {
mouse_x,
mouse_y,
mouse_dx,
mouse_dy,
} = data {
interface.hook_manager.send_event(ItfInputEvent::MousePosition(*mouse_x, *mouse_y));
interface.hook_manager.send_event(ItfInputEvent::MouseDelta(*mouse_dx, *mouse_dy));
}
InputHookRes::Success
}));
let interface = input.basalt.interface();
input.add_hook(InputHook::MouseScroll, Arc::new(move |data| {
if let InputHookData::MouseScroll { scroll_amt, .. } = data {
interface.hook_manager.send_event(ItfInputEvent::Scroll(*scroll_amt));
}
InputHookRes::Success
}));
}
thread::spawn(move || {
let mut key_state: HashMap<Qwery, bool> = HashMap::new();
let mut mouse_state = HashMap::new();
let mut global_key_state = HashMap::new();
let mut global_mouse_state = HashMap::new();
let mut mouse_pos_x = 0.0;
let mut mouse_pos_y = 0.0;
let mut window_focused = true;
let mut mouse_inside = true;
let mut hook_map: BTreeMap<InputHookID, (InputHookData, InputHookFn)> = BTreeMap::new();
loop {
let start = Instant::now();
let mut mouse_motion_x = 0.0;
let mut mouse_motion_y = 0.0;
let mut mouse_motion = false;
let mut mouse_moved = false;
let mut m_scroll_amt = 0.0;
let mut scrolled = false;
let mut events = Vec::new();
while let Ok(event) = event_recv.try_recv() {
events.push(event);
}
events.retain(|e| {
match e {
Event::AddHook(id, hook_data, func) => {
hook_map.insert(*id, (hook_data.into_data(), func.clone()));
false
},
Event::DelHook(id) => {
hook_map.remove(&id);
false
},
_ => true
}
});
let mut window_focus_lost = false;
events.retain(|e| {
match e {
Event::MouseEnter => {
for (_hook_id, (hook_data, hook_func)) in &hook_map {
if hook_data.ty() == InputHookTy::MouseEnter {
hook_func(hook_data);
}
}
mouse_inside = true;
false
},
Event::MouseLeave => {
for (_hook_id, (hook_data, hook_func)) in &hook_map {
if hook_data.ty() == InputHookTy::MouseLeave {
hook_func(hook_data);
}
}
mouse_inside = false;
false
},
Event::WindowResized => {
input.basalt.force_resize();
false
},
Event::WindowFocused => {
window_focused = true;
for (_hook_id, (hook_data, hook_func)) in &hook_map {
if hook_data.ty() == InputHookTy::WindowFocused {
hook_func(hook_data);
}
}
false
},
Event::WindowLostFocus => {
window_focused = false;
window_focus_lost = true;
for (_hook_id, (hook_data, hook_func)) in &hook_map {
if hook_data.ty() == InputHookTy::WindowLostFocus {
hook_func(hook_data);
}
}
false
},
_ => true
}
});
if window_focus_lost {
for (k, v) in key_state.iter_mut() {
if *v {
*v = false;
events.push(Event::KeyRelease(k.clone()));
}
}
}
for e in events {
match e {
Event::KeyPress(k) => {
if window_focused {
for (_hook_id, (ref mut hook_data, hook_func)) in &mut hook_map {
let mut call = false;
if let InputHookData::Character {
character
} = hook_data {
let shift = *key_state.entry(Qwery::LShift).or_insert(false)
|| *key_state.entry(Qwery::RShift).or_insert(false);
*character = match k.into_char(shift) {
Some(some) => some,
None => continue
};
call = true;
}
if call {
hook_func(&hook_data);
}
}
}
let global_entry = global_key_state.entry(k).or_insert(false);
let entry = key_state.entry(k).or_insert(false);
let global_reject = *global_entry;
if *entry && *global_entry {
continue;
}
*global_entry = true;
if window_focused {
*entry = true;
}
for (_hook_id, (ref mut hook_data, hook_func)) in &mut hook_map {
let mut call = false;
match hook_data.ty() {
InputHookTy::AnyMouseOrKeyPress
=> if let InputHookData::AnyMouseOrKeyPress {
global,
either
} = hook_data {
if (*global && !global_reject) || (!*global && window_focused) {
*either = KeyOrMouseButton::Key(k.clone());
call = true;
}
},
InputHookTy::AnyKeyPress
=> if let InputHookData::AnyKeyPress {
global,
key
} = hook_data {
if (*global && !global_reject) || (!*global && window_focused) {
*key = k.clone();
call = true;
}
},
_ => (),
}
if call {
hook_func(hook_data);
}
}
},
Event::KeyRelease(k) => {
if !window_focus_lost {
let entry = global_key_state.entry(k).or_insert(true);
if !*entry {
continue;
}
*entry = false;
}
if window_focused {
*key_state.entry(k).or_insert(false) = false;
}
for (_hook_id, (ref mut hook_data, hook_func)) in &mut hook_map {
let mut call = false;
match hook_data.ty() {
InputHookTy::AnyMouseOrKeyRelease
=> if let InputHookData::AnyMouseOrKeyRelease {
global,
either
} = hook_data {
if (*global && !window_focus_lost) || (!*global && (window_focused || window_focus_lost)) {
*either = KeyOrMouseButton::Key(k.clone());
call = true;
}
},
InputHookTy::AnyKeyRelease
=> if let InputHookData::AnyKeyRelease {
global,
key
} = hook_data {
if (*global && !window_focus_lost) || (!*global && (window_focused || window_focus_lost)) {
*key = k.clone();
call = true;
}
},
_ => (),
}
if call {
hook_func(hook_data);
}
}
},
Event::MousePress(b) => {
*global_mouse_state.entry(b).or_insert(true) = true;
if window_focused {
*mouse_state.entry(b).or_insert(true) = true;
}
for (_hook_id, (ref mut hook_data, hook_func)) in &mut hook_map {
let mut call = false;
match hook_data.ty() {
InputHookTy::AnyMouseOrKeyPress
=> if let InputHookData::AnyMouseOrKeyPress {
global,
either
} = hook_data {
if *global || window_focused {
*either = KeyOrMouseButton::MouseButton(b.clone());
call = true;
}
},
InputHookTy::AnyMousePress
=> if let InputHookData::AnyMousePress {
global,
button
} = hook_data {
if *global || window_focused {
*button = b.clone();
call = true;
}
},
_ => (),
}
if call {
hook_func(hook_data);
}
}
},
Event::MouseRelease(b) => {
*global_mouse_state.entry(b).or_insert(false) = false;
if window_focused {
*mouse_state.entry(b).or_insert(false) = false;
}
for (_hook_id, (ref mut hook_data, hook_func)) in &mut hook_map {
let mut call = false;
match hook_data.ty() {
InputHookTy::AnyMouseOrKeyRelease
=> if let InputHookData::AnyMouseOrKeyRelease {
global,
either
} = hook_data {
if *global || window_focused {
*either = KeyOrMouseButton::MouseButton(b.clone());
call = true;
}
},
InputHookTy::AnyMouseRelease
=> if let InputHookData::AnyMouseRelease {
global,
button
} = hook_data {
if *global || window_focused {
*button = b.clone();
call = true;
}
},
_ => (),
}
if call {
hook_func(hook_data);
}
}
},
Event::MouseMotion(x, y) => {
mouse_motion_x += x;
mouse_motion_y += y;
mouse_motion = true;
},
Event::MousePosition(x, y) => {
mouse_pos_x = x;
mouse_pos_y = y;
mouse_moved = true;
},
Event::MouseScroll(v) => {
m_scroll_amt += v;
scrolled = true;
},
_ => unreachable!()
}
}
for (_hook_id, (ref mut hook_data, hook_func)) in &mut hook_map {
let mut call = false;
match hook_data {
InputHookData::MouseMotion {
x,
y,
} => {
if mouse_motion && window_focused {
*x = mouse_motion_x;
*y = mouse_motion_y;
call = true;
}
},
InputHookData::MouseMove {
mouse_x,
mouse_y,
mouse_dx,
mouse_dy,
} => {
if mouse_moved && window_focused {
*mouse_dx = *mouse_x - mouse_pos_x;
*mouse_x = mouse_pos_x;
*mouse_dy = *mouse_y - mouse_pos_y;
*mouse_y = mouse_pos_y;
call = true;
}
},
InputHookData::MouseScroll {
scroll_amt,
mouse_x,
mouse_y,
} => {
if scrolled && mouse_inside {
*scroll_amt = m_scroll_amt;
call = true;
*mouse_x = mouse_pos_x;
*mouse_y = mouse_pos_y;
}
},
_ => ()
}
if call {
hook_func(hook_data);
}
}
for (_hook_id, (ref mut hook_data, hook_func)) in &mut hook_map {
match hook_data.ty() {
InputHookTy::Press => {
let mut cond_change = false;
if let InputHookData::Press {
global,
mouse_x,
mouse_y,
key_active,
mouse_active,
} = hook_data {
for (key, val) in key_active.iter_mut() {
let v = if *global {
global_key_state.entry(key.clone()).or_insert(false)
} else {
key_state.entry(key.clone()).or_insert(false)
};
if *v != *val {
*val = *v;
cond_change = true;
}
}
for (button, val) in mouse_active.iter_mut(){
let b = if *global {
global_mouse_state.entry(button.clone()).or_insert(false)
} else {
mouse_state.entry(button.clone()).or_insert(false)
};
if *b != *val {
*val = *b;
cond_change = true;
}
}
if cond_change {
*mouse_x = mouse_pos_x;
*mouse_y = mouse_pos_y;
}
}
if cond_change && hook_data.cond_met() {
hook_func(&hook_data);
}
},
InputHookTy::Release => {
let mut cond_change = false;
if let InputHookData::Release {
global,
key_active,
mouse_active,
..
} = hook_data {
for (key, val) in key_active.iter_mut() {
let v = if *global {
global_key_state.entry(key.clone()).or_insert(false)
} else {
key_state.entry(key.clone()).or_insert(false)
};
if *v != *val {
*val = *v;
cond_change = true;
}
}
for (button, val) in mouse_active.iter_mut() {
let b = if *global {
global_mouse_state.entry(button.clone()).or_insert(false)
} else {
mouse_state.entry(button.clone()).or_insert(false)
};
if *b != *val {
*val = *b;
cond_change = true;
}
}
}
if cond_change {
let cond_met = hook_data.cond_met();
let mut call = false;
if let InputHookData::Release {
pressed,
..
} = hook_data {
if cond_met {
if !*pressed {
*pressed = true;
}
} else {
if *pressed {
*pressed = false;
call = true;
}
}
}
if call {
hook_func(&hook_data);
}
}
},
InputHookTy::Hold => {
let mut hook_act = false;
let mut cond_change = false;
if let InputHookData::Hold {
global,
active,
key_active,
mouse_active,
..
} = hook_data {
hook_act = *active;
for (key, val) in key_active.iter_mut() {
let v = if *global {
global_key_state.entry(key.clone()).or_insert(false)
} else {
key_state.entry(key.clone()).or_insert(false)
};
if *v != *val {
*val = *v;
cond_change = true;
}
}
for (button, val) in mouse_active.iter_mut() {
let b = if *global {
global_mouse_state.entry(button.clone()).or_insert(false)
} else {
mouse_state.entry(button.clone()).or_insert(false)
};
if *b != *val {
*val = *b;
cond_change = true;
}
}
}
if cond_change {
let cond_met = hook_data.cond_met();
if !hook_act && cond_met {
if let InputHookData::Hold {
active,
is_first_call,
first_call,
..
} = hook_data {
hook_act = true;
*active = true;
*is_first_call = true;
*first_call = Instant::now();
}
}
if hook_act && !cond_met {
if let InputHookData::Hold {
active,
..
} = hook_data {
*active = false;
hook_act = false;
}
}
}
if hook_act {
let mut call = false;
if let InputHookData::Hold {
is_first_call,
first_call,
last_call,
initial_delay,
mouse_x,
mouse_y,
interval,
..
} = hook_data {
if *is_first_call {
if first_call.elapsed() >= *initial_delay {
*first_call = Instant::now();
*last_call = Instant::now();
*mouse_x = mouse_pos_x;
*mouse_y = mouse_pos_y;
call = true;
}
} else {
if last_call.elapsed() >= *interval {
*mouse_x = mouse_pos_x;
*mouse_y = mouse_pos_y;
call = true;
}
}
}
if call {
hook_func(&hook_data);
if let InputHookData::Hold {
is_first_call,
last_call,
..
} = hook_data {
*is_first_call = false;
*last_call = Instant::now();
}
}
}
}
_ => ()
}
}
if start.elapsed() > Duration::from_millis(10) {
continue;
}
thread::sleep(Duration::from_millis(10) - start.elapsed());
}
});
input_ret
}
}