Skip to content

Commit

Permalink
Adding sleep in event loops to improve CPU usage
Browse files Browse the repository at this point in the history
- The event loops were looping continuously causing CPU usage to be
  high. Now, the event loops sleep for 100 microseconds (to keep up
  with mice that can have upwards of an 8Khz refresh rate), this sleep
  time may be revisted in the future.
- Added a sleep to the empty loop in the example so the example no
  longer uses a ton of CPU time.
- Minor clippy fixes.
- Removing rustfmt.toml file and reformatting to default Rust style.
- Reverting to 1.1.3 since this is more a patch than a minor versio
  change.
  • Loading branch information
ostrosco committed Mar 31, 2023
1 parent 76d2406 commit 8f9ac45
Show file tree
Hide file tree
Showing 11 changed files with 47 additions and 59 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "device_query"
version = "1.2.0"
version = "1.1.3"
authors = ["ostrosco <ostrosco@fastmail.fm>"]
build = "build.rs"
description = "A basic library for querying keyboard and mouse state on-demand without a window."
Expand Down
5 changes: 2 additions & 3 deletions build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,10 @@ fn main() {
"x11", libdir
));

let config =
format!("pub mod config {{ pub mod libdir {{\n{}}}\n}}", config);
let config = format!("pub mod config {{ pub mod libdir {{\n{}}}\n}}", config);
let out_dir = env::var("OUT_DIR").unwrap();
let dest_path = Path::new(&out_dir).join("config.rs");
let mut f = File::create(&dest_path).unwrap();
let mut f = File::create(dest_path).unwrap();
f.write_all(&config.into_bytes()).unwrap();

let target = env::var("TARGET").unwrap();
Expand Down
6 changes: 5 additions & 1 deletion examples/event_based_print_keys.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
extern crate device_query;

use device_query::{DeviceEvents, DeviceState};
use std::thread;
use std::time::Duration;

fn main() {
let device_state = DeviceState::new();
Expand All @@ -11,5 +13,7 @@ fn main() {
println!("Up: {:#?}", key);
});

loop {}
loop {
thread::sleep(Duration::from_secs(1000));
}
}
6 changes: 5 additions & 1 deletion examples/event_based_print_mouse.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
extern crate device_query;

use device_query::{DeviceEvents, DeviceState};
use std::thread;
use std::time::Duration;

fn main() {
let device_state = DeviceState::new();
Expand All @@ -14,5 +16,7 @@ fn main() {
println!("Up: {:#?}", button);
});

loop {}
loop {
thread::sleep(Duration::from_secs(1000));
}
}
1 change: 0 additions & 1 deletion rustfmt.toml

This file was deleted.

14 changes: 6 additions & 8 deletions src/device_events/callback/keyboard_callback.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,9 @@ impl KeyboardCallbacks {

pub fn run_key_up(&self, key: &Keycode) {
if let Ok(mut callbacks) = self.key_up.lock() {
utils::DrainFilter::drain_filter(
callbacks.deref_mut(),
|callback| callback.upgrade().is_none(),
);
utils::DrainFilter::drain_filter(callbacks.deref_mut(), |callback| {
callback.upgrade().is_none()
});
for callback in callbacks.iter() {
if let Some(callback) = callback.upgrade() {
callback(key);
Expand All @@ -44,10 +43,9 @@ impl KeyboardCallbacks {

pub fn run_key_down(&self, key: &Keycode) {
if let Ok(mut callbacks) = self.key_down.lock() {
utils::DrainFilter::drain_filter(
callbacks.deref_mut(),
|callback| callback.upgrade().is_none(),
);
utils::DrainFilter::drain_filter(callbacks.deref_mut(), |callback| {
callback.upgrade().is_none()
});
for callback in callbacks.iter() {
if let Some(callback) = callback.upgrade() {
callback(key);
Expand Down
21 changes: 9 additions & 12 deletions src/device_events/callback/mouse_callback.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,9 @@ impl MouseCallbacks {

pub fn run_mouse_move(&self, position: &MousePosition) {
if let Ok(mut callbacks) = self.mouse_move.lock() {
utils::DrainFilter::drain_filter(
callbacks.deref_mut(),
|callback| callback.upgrade().is_none(),
);
utils::DrainFilter::drain_filter(callbacks.deref_mut(), |callback| {
callback.upgrade().is_none()
});
for callback in callbacks.iter() {
if let Some(callback) = callback.upgrade() {
callback(position);
Expand All @@ -58,10 +57,9 @@ impl MouseCallbacks {

pub fn run_mouse_down(&self, button: &MouseButton) {
if let Ok(mut callbacks) = self.mouse_down.lock() {
utils::DrainFilter::drain_filter(
callbacks.deref_mut(),
|callback| callback.upgrade().is_none(),
);
utils::DrainFilter::drain_filter(callbacks.deref_mut(), |callback| {
callback.upgrade().is_none()
});
for callback in callbacks.iter() {
if let Some(callback) = callback.upgrade() {
callback(button);
Expand All @@ -72,10 +70,9 @@ impl MouseCallbacks {

pub fn run_mouse_up(&self, button: &MouseButton) {
if let Ok(mut callbacks) = self.mouse_up.lock() {
utils::DrainFilter::drain_filter(
callbacks.deref_mut(),
|callback| callback.upgrade().is_none(),
);
utils::DrainFilter::drain_filter(callbacks.deref_mut(), |callback| {
callback.upgrade().is_none()
});
for callback in callbacks.iter() {
if let Some(callback) = callback.upgrade() {
callback(button);
Expand Down
15 changes: 7 additions & 8 deletions src/device_events/event_loop.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use super::{CallbackGuard, KeyboardCallbacks};
use std::sync::{Arc, Mutex, Weak};
use std::thread::{spawn, JoinHandle};
use std::thread::{sleep, spawn, JoinHandle};
use std::time::Duration;
use MouseState;
use {DeviceQuery, MouseCallbacks};
use {DeviceState, Keycode};
Expand Down Expand Up @@ -30,6 +31,7 @@ fn keyboard_thread(callbacks: Weak<KeyboardCallbacks>) -> JoinHandle<()> {
}
}
prev_keys = keys;
sleep(Duration::from_micros(100));
}
})
}
Expand All @@ -56,6 +58,7 @@ fn mouse_thread(callbacks: Weak<MouseCallbacks>) -> JoinHandle<()> {
callbacks.run_mouse_move(&mouse_state.coords);
}
previous_mouse_state = mouse_state;
sleep(Duration::from_micros(100));
}
})
}
Expand All @@ -64,8 +67,7 @@ impl Default for EventLoop {
fn default() -> Self {
let keyboard_callbacks = Arc::new(KeyboardCallbacks::default());
let mouse_callbacks = Arc::new(MouseCallbacks::default());
let _keyboard_thread =
keyboard_thread(Arc::downgrade(&keyboard_callbacks));
let _keyboard_thread = keyboard_thread(Arc::downgrade(&keyboard_callbacks));
let _mouse_thread = mouse_thread(Arc::downgrade(&mouse_callbacks));
Self {
keyboard_callbacks,
Expand Down Expand Up @@ -95,9 +97,7 @@ impl EventLoop {
CallbackGuard { _callback }
}

pub fn on_mouse_move<
Callback: Fn(&MousePosition) + Send + Sync + 'static,
>(
pub fn on_mouse_move<Callback: Fn(&MousePosition) + Send + Sync + 'static>(
&mut self,
callback: Callback,
) -> CallbackGuard<Callback> {
Expand Down Expand Up @@ -126,6 +126,5 @@ impl EventLoop {
}

lazy_static! {
pub(crate) static ref EVENT_LOOP: Arc<Mutex<EventLoop>> =
Default::default();
pub(crate) static ref EVENT_LOOP: Arc<Mutex<EventLoop>> = Default::default();
}
7 changes: 2 additions & 5 deletions src/device_state/linux/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,17 +95,14 @@ impl DeviceState {
unsafe {
let keymap: *mut c_char = [0; 32].as_mut_ptr();
xlib::XQueryKeymap(self.xc.display, keymap);
for (ix, byte) in
slice::from_raw_parts(keymap, 32).iter().enumerate()
{
for (ix, byte) in slice::from_raw_parts(keymap, 32).iter().enumerate() {
for bit in 0_u8..8_u8 {
let bitmask = 1 << bit;
if byte & bitmask != 0 {
//x11 keycode uses kernel keycode with an offset of 8.
let x11_key = ix as u8 * 8 + bit;
let kernel_key = x11_key - 8;
if let Some(k) = self.kernel_key_to_keycode(kernel_key)
{
if let Some(k) = self.kernel_key_to_keycode(kernel_key) {
keycodes.push(k)
}
}
Expand Down
5 changes: 4 additions & 1 deletion src/device_state/macos/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,10 @@ const MAPPING: &[(readkey::Keycode, Keycode)] = &[
impl DeviceState {
pub fn new() -> DeviceState {
// TODO: remove this
assert!(has_accessibility(), "This app does not have Accessibility Permissions enabled and will not work");
assert!(
has_accessibility(),
"This app does not have Accessibility Permissions enabled and will not work"
);

DeviceState {}
}
Expand Down
24 changes: 6 additions & 18 deletions src/device_state/windows/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@ use keymap::Keycode;
use mouse_state::MouseState;
use windows::Win32::Foundation::POINT;
use windows::Win32::UI::Input::KeyboardAndMouse;
use windows::Win32::UI::Input::KeyboardAndMouse::{
GetAsyncKeyState, VIRTUAL_KEY,
};
use windows::Win32::UI::Input::KeyboardAndMouse::{GetAsyncKeyState, VIRTUAL_KEY};
use windows::Win32::UI::WindowsAndMessaging::GetCursorPos;

#[derive(Debug, Clone)]
Expand All @@ -30,25 +28,15 @@ impl DeviceState {
(0, 0)
};
button1pressed =
GetAsyncKeyState(KeyboardAndMouse::VK_LBUTTON.0 as i32) as u32
& 0x8000
!= 0;
GetAsyncKeyState(KeyboardAndMouse::VK_LBUTTON.0 as i32) as u32 & 0x8000 != 0;
button2pressed =
GetAsyncKeyState(KeyboardAndMouse::VK_RBUTTON.0 as i32) as u32
& 0x8000
!= 0;
GetAsyncKeyState(KeyboardAndMouse::VK_RBUTTON.0 as i32) as u32 & 0x8000 != 0;
button3pressed =
GetAsyncKeyState(KeyboardAndMouse::VK_MBUTTON.0 as i32) as u32
& 0x8000
!= 0;
GetAsyncKeyState(KeyboardAndMouse::VK_MBUTTON.0 as i32) as u32 & 0x8000 != 0;
button4pressed =
GetAsyncKeyState(KeyboardAndMouse::VK_XBUTTON1.0 as i32) as u32
& 0x8000
!= 0;
GetAsyncKeyState(KeyboardAndMouse::VK_XBUTTON1.0 as i32) as u32 & 0x8000 != 0;
button5pressed =
GetAsyncKeyState(KeyboardAndMouse::VK_XBUTTON2.0 as i32) as u32
& 0x8000
!= 0;
GetAsyncKeyState(KeyboardAndMouse::VK_XBUTTON2.0 as i32) as u32 & 0x8000 != 0;
}
MouseState {
coords,
Expand Down

0 comments on commit 8f9ac45

Please sign in to comment.