From a5de77f321fae0cdd928d3b806e6291c3036f6bc Mon Sep 17 00:00:00 2001 From: siikamiika Date: Wed, 14 Nov 2018 01:55:09 +0200 Subject: [PATCH] optimize mouse events, refactoring --- src/input_thread.rs | 98 +++++++++++++++++++++++++++++++-------------- src/main.rs | 1 + 2 files changed, 70 insertions(+), 29 deletions(-) diff --git a/src/input_thread.rs b/src/input_thread.rs index ccc6430..eb02099 100644 --- a/src/input_thread.rs +++ b/src/input_thread.rs @@ -2,6 +2,7 @@ use std::thread; use std::time::Duration; use evdev_rs::util::event_code_to_int; +use evdev_rs::enums::EventType::EV_REL; use crossbeam::crossbeam_channel::{unbounded, Select, Receiver, Sender}; @@ -27,42 +28,81 @@ pub fn create_evdev_thread(device_path: &str) -> (String, Receiver (), - // stop request received, break out of the loop - Ok(oper) => match oper.index() { - i if i == oper1 => { - assert_eq!(oper.recv(&recv_stop_channel), Ok(true)); - break; - }, - // shouldn't happen - _ => (), - }, + if stop_requested(&recv_stop_channel) { + continue; } - // read next input event - let event = dev.device.next_event(evdev_rs::NORMAL | evdev_rs::BLOCKING); - match event { - // send input event to event channel - Ok(e) => send_event_channel.send( - ThreadInputEvent { - typ: e.1.event_type as u32, - code: event_code_to_int(&e.1.event_code).1, - value: e.1.value, + loop { + // block before starting while loop again + let mut first = true; + let mut event = dev.device.next_event(evdev_rs::NORMAL | evdev_rs::BLOCKING); + // pending events not required for first round + while first || dev.device.has_event_pending() { + first = false; + match event { + // send input event to event channel + Ok(e) => { + let e = ThreadInputEvent { + typ: e.1.event_type as u32, + code: event_code_to_int(&e.1.event_code).1, + value: e.1.value, + }; + if e.typ == 2 && e.code <= 1 { + mouse_move[e.code as usize] += e.value; + } else { + send_event_channel.send(e).unwrap(); + } + }, + Err(_) => (), } - ).unwrap(), - Err(_) => (), + // read next input event + event = dev.device.next_event(evdev_rs::NORMAL | evdev_rs::BLOCKING); + } + // combined mouse event + send_combined_mouse_move(&mut mouse_move, &send_event_channel); + // save cpu by sleeping after consuming all events + thread::sleep(Duration::from_millis(5)); } } }); (return_device_path, recv_event_channel, send_stop_channel) } + +fn stop_requested(chan: &Receiver) -> bool { + // check for stop requests + let mut sel = Select::new(); + // create stop channel receive operation + let oper1 = sel.recv(&chan); + // try to select from stop channel + let oper = sel.try_select(); + match oper { + // no stop requests + Err(_) => false, + // stop request received, break out of the loop + Ok(oper) => match oper.index() { + i if i == oper1 => { + oper.recv(&chan).unwrap() + }, + // shouldn't happen + _ => false, + }, + } +} + +fn send_combined_mouse_move(mouse_move: &mut Vec, chan: &Sender) { + // REL_X..=REL_Y + for code in 0..=1 { + if mouse_move[code] != 0 { + chan.send(ThreadInputEvent { + typ: EV_REL as u32, + code: code as u32, + value: mouse_move[code], + }).unwrap(); + mouse_move[code] = 0; + } + } +} diff --git a/src/main.rs b/src/main.rs index 151cb4d..ffd3667 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,6 +2,7 @@ extern crate uinput; extern crate evdev_rs; extern crate crossbeam; +use std::thread; use std::env::args; use std::time::Duration; use std::collections::HashMap;