Full Code of ostrosco/device_query for AI

master 4f025c59e7bc cached
26 files
60.0 KB
17.0k tokens
192 symbols
1 requests
Download .txt
Repository: ostrosco/device_query
Branch: master
Commit: 4f025c59e7bc
Files: 26
Total size: 60.0 KB

Directory structure:
gitextract_sn8317i5/

├── .gitignore
├── .travis.yml
├── Cargo.toml
├── LICENSE
├── README.md
├── build.rs
├── examples/
│   ├── event_based_print_keys.rs
│   ├── event_based_print_mouse.rs
│   ├── print_keys.rs
│   └── print_mouse.rs
└── src/
    ├── device_events/
    │   ├── callback/
    │   │   ├── callback_guard.rs
    │   │   ├── keyboard_callback.rs
    │   │   ├── mod.rs
    │   │   └── mouse_callback.rs
    │   ├── event_loop.rs
    │   ├── mod.rs
    │   └── utils.rs
    ├── device_query.rs
    ├── device_state/
    │   ├── linux/
    │   │   ├── kernel_key.rs
    │   │   └── mod.rs
    │   ├── macos/
    │   │   └── mod.rs
    │   ├── mod.rs
    │   └── windows/
    │       └── mod.rs
    ├── keymap.rs
    ├── lib.rs
    └── mouse_state.rs

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitignore
================================================
# IDEs auto-generated files
.idea

# Cargo files
/target/
**/*.rs.bk
Cargo.lock


================================================
FILE: .travis.yml
================================================
language: rust
cache: cargo
matrix:
  include:
    - os: linux
      rust: stable
      env: TARGET=x86_64_unknown_linux_gnu
    - os: linux
      rust: nightly
      env: TARGET=x86_64_unknown_linux_gnu



================================================
FILE: Cargo.toml
================================================
[package]
name = "device_query"
version = "4.0.1"
authors = ["ostrosco <ostrosco@fastmail.fm>"]
build = "build.rs"
description = "A basic library for querying keyboard and mouse state on-demand without a window."
homepage = "https://github.com/ostrosco/device_query"
repository = "https://github.com/ostrosco/device_query"
readme = "README.md"
keywords = ["input", "mouse", "keyboard"]
license = "MIT"

[badges]
travis-ci = { repository = "ostrosco/device_query" }

[build-dependencies]
pkg-config = "0.3.26"

[dependencies]

[target.'cfg(target_os = "linux")'.dependencies]
x11 = {version = "2.21.0", features = ["xlib"] }

[target.'cfg(target_os = "windows")'.dependencies]
windows = {version = "0.48.0", features = ["Win32_UI_Input_KeyboardAndMouse", "Win32_UI_WindowsAndMessaging", "Win32_Foundation", "Win32_Foundation"]}

[target.'cfg(target_os = "macos")'.dependencies]
readkey = "0.2.2"
readmouse = "0.2.1"
macos-accessibility-client = "0.0.1"


================================================
FILE: LICENSE
================================================
MIT License

Copyright (c) 2018 ostrosco

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.


================================================
FILE: README.md
================================================
# device_query

# NOTE: This repository has been relocated to https://codeberg.org/ostrosco/device_query. Future work will continue there.

[![Build Status](https://travis-ci.org/ostrosco/device_query.svg?branch=master)](https://travis-ci.org/ostrosco/device_query)

A simple library to query mouse and keyboard inputs on demand without a window.
Will work in Windows, Linux on X11, and macOS.

```Rust
use device_query::{DeviceQuery, DeviceState, MouseState, Keycode};

let device_state = DeviceState::new();
let mouse: MouseState = device_state.get_mouse();
println!("Current Mouse Coordinates: {:?}", mouse.coords);
let keys: Vec<Keycode> = device_state.get_keys();
println!("Is A pressed? {}", keys.contains(Keycode::A));
```

# Dependencies

Windows shouldn't require any special software to be installed for `device_query` to work properly.
On Linux, the X11 development libraries are required for `device_query` to query state from the OS.

On Ubuntu/Debian:
```
sudo apt install libx11-dev
```

On Fedora/RHEL/CentOS:
```
sudo dnf install xorg-x11-server-devel
```

On newer versions of MacOS, you may run into issues where you only see meta keys such as shift,
backspace, et cetera. This is due to a permission issue. To work around this:

* open the MacOS system preferences
* go to Security -> Privacy
* scroll down to Accessibility and unlock it
* add the app that is using `device_query` (such as your terminal) to the list

# Device Callbacks

`device_query` allows you to register callbacks for various device events such as key presses and mouse movements.

## Example

Here's a simple example demonstrating how to use the callback system:

```rust
extern crate device_query;
use device_query::{DeviceEvents, DeviceEventsHandler, Keycode, MouseButton, MousePosition};
use std::thread;
use std::time::Duration;

fn main() {
    // Initialize the event handler with a sleep duration of 10 milliseconds
    let event_handler = DeviceEventsHandler::new(Duration::from_millis(10))
        .expect("Could not initialize event loop");

    // Register callbacks for various events
    // The callbacks will be automatically deregistered when they go out of scope
    let _mouse_move_guard = event_handler.on_mouse_move(|position: &MousePosition| {
        println!("Mouse moved to position: {:?}", position);
    });

    // Keep the main thread alive to continue receiving events
    loop {
        thread::sleep(Duration::from_secs(1000));
    }
}
```


================================================
FILE: build.rs
================================================
extern crate pkg_config;

#[cfg(target_os = "windows")]
fn main() {}

#[cfg(target_os = "macos")]
fn main() {}

#[cfg(target_os = "linux")]
use std::env;
#[cfg(target_os = "linux")]
use std::fs::File;
#[cfg(target_os = "linux")]
use std::io::Write;
#[cfg(target_os = "linux")]
use std::path::Path;

#[cfg(target_os = "linux")]
fn main() {
    let mut config = String::new();
    let libdir = match pkg_config::get_variable("x11", "libdir") {
        Ok(libdir) => format!("Some(\"{}\")", libdir),
        Err(_) => "None".to_string(),
    };
    config.push_str(&format!(
        "pub const {}: Option<&'static str> = {};\n",
        "x11", libdir
    ));

    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();
    f.write_all(&config.into_bytes()).unwrap();

    let target = env::var("TARGET").unwrap();
    if target.contains("linux") {
        println!("cargo:rustc-link-lib=dl");
    } else if target.contains("freebsd") || target.contains("dragonfly") {
        println!("cargo:rustc-link-lib=c");
    }
}


================================================
FILE: examples/event_based_print_keys.rs
================================================
extern crate device_query;

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

fn main() {
    let event_handler = DeviceEventsHandler::new(Duration::from_millis(10))
        .expect("Could not initialize event loop");
    let _guard = event_handler.on_key_down(|key| {
        println!("Down: {:#?}", key);
    });
    let _guard = event_handler.on_key_up(|key| {
        println!("Up: {:#?}", key);
    });

    loop {
        thread::sleep(Duration::from_secs(1000));
    }
}


================================================
FILE: examples/event_based_print_mouse.rs
================================================
extern crate device_query;

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

fn main() {
    let event_handler = DeviceEventsHandler::new(std::time::Duration::from_millis(10))
        .expect("Could not initialize event loop");
    let _guard = event_handler.on_mouse_move(|position| {
        println!("Position: {:#?}", position);
    });
    let _guard = event_handler.on_mouse_down(|button| {
        println!("Down: {:#?}", button);
    });
    let _guard = event_handler.on_mouse_up(|button| {
        println!("Up: {:#?}", button);
    });

    loop {
        thread::sleep(Duration::from_secs(1000));
    }
}


================================================
FILE: examples/print_keys.rs
================================================
extern crate device_query;

use device_query::{DeviceQuery, DeviceState};

fn main() {
    let device_state = DeviceState::new();
    let mut prev_keys = vec![];
    loop {
        let keys = device_state.get_keys();
        if keys != prev_keys {
            println!("{:?}", keys);
        }
        prev_keys = keys;
    }
}


================================================
FILE: examples/print_mouse.rs
================================================
extern crate device_query;

use device_query::{DeviceQuery, DeviceState, MouseState};

fn main() {
    let device_state = DeviceState::new();
    let mut prev_mouse = MouseState::default();
    loop {
        let mouse = device_state.get_mouse();
        if mouse != prev_mouse {
            println!("{:?}", mouse);
        }
        prev_mouse = mouse;
    }
}


================================================
FILE: src/device_events/callback/callback_guard.rs
================================================
//! Callback guard.

use std::sync::Arc;

/// Callback guard returned when adding a callback as an event listener. If the guard is dropped,
/// the event listener is removed.
#[derive(Debug)]
pub struct CallbackGuard<Callback> {
    pub(crate) _callback: Arc<Callback>,
}


================================================
FILE: src/device_events/callback/keyboard_callback.rs
================================================
use crate::device_events::utils;
use std::ops::DerefMut;
use std::sync::{Arc, Mutex, Weak};
use Keycode;

/// Keyboard callback.
pub type KeyboardCallback = dyn Fn(&Keycode) + Sync + Send + 'static;

/// Keyboard callbacks.
#[derive(Default)]
pub(crate) struct KeyboardCallbacks {
    key_down: Mutex<Vec<Weak<KeyboardCallback>>>,
    key_up: Mutex<Vec<Weak<KeyboardCallback>>>,
}

impl KeyboardCallbacks {
    pub fn push_key_up(&self, callback: Arc<KeyboardCallback>) {
        if let Ok(mut key_down) = self.key_up.lock() {
            let callback = Arc::downgrade(&callback);
            key_down.push(callback)
        }
    }

    pub fn push_key_down(&self, callback: Arc<KeyboardCallback>) {
        if let Ok(mut key_down) = self.key_down.lock() {
            let callback = Arc::downgrade(&callback);
            key_down.push(callback)
        }
    }

    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()
            });
            for callback in callbacks.iter() {
                if let Some(callback) = callback.upgrade() {
                    callback(key);
                }
            }
        }
    }

    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()
            });
            for callback in callbacks.iter() {
                if let Some(callback) = callback.upgrade() {
                    callback(key);
                }
            }
        }
    }
}


================================================
FILE: src/device_events/callback/mod.rs
================================================
mod callback_guard;
mod keyboard_callback;
mod mouse_callback;

pub use self::callback_guard::*;
pub use self::keyboard_callback::*;
pub use self::mouse_callback::*;


================================================
FILE: src/device_events/callback/mouse_callback.rs
================================================
//! Mouse callback.

use crate::device_events::utils;
use std::ops::DerefMut;
use std::sync::{Arc, Mutex, Weak};
use MouseButton;
use MousePosition;

/// Mouse move callback.
pub type MouseMoveCallback = dyn Fn(&MousePosition) + Sync + Send + 'static;

/// Mouse button callback.
pub type MouseButtonCallback = dyn Fn(&MouseButton) + Sync + Send + 'static;

/// Mouse callbacks.
#[derive(Default)]
pub(crate) struct MouseCallbacks {
    pub mouse_move: Mutex<Vec<Weak<MouseMoveCallback>>>,
    pub mouse_up: Mutex<Vec<Weak<MouseButtonCallback>>>,
    pub mouse_down: Mutex<Vec<Weak<MouseButtonCallback>>>,
}

impl MouseCallbacks {
    pub fn push_mouse_move(&self, callback: Arc<MouseMoveCallback>) {
        if let Ok(mut callbacks) = self.mouse_move.lock() {
            let callback = Arc::downgrade(&callback);
            callbacks.push(callback)
        }
    }

    pub fn push_mouse_down(&self, callback: Arc<MouseButtonCallback>) {
        if let Ok(mut callbacks) = self.mouse_down.lock() {
            let callback = Arc::downgrade(&callback);
            callbacks.push(callback)
        }
    }

    pub fn push_mouse_up(&self, callback: Arc<MouseButtonCallback>) {
        if let Ok(mut callbacks) = self.mouse_up.lock() {
            let callback = Arc::downgrade(&callback);
            callbacks.push(callback)
        }
    }

    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()
            });
            for callback in callbacks.iter() {
                if let Some(callback) = callback.upgrade() {
                    callback(position);
                }
            }
        }
    }

    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()
            });
            for callback in callbacks.iter() {
                if let Some(callback) = callback.upgrade() {
                    callback(button);
                }
            }
        }
    }

    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()
            });
            for callback in callbacks.iter() {
                if let Some(callback) = callback.upgrade() {
                    callback(button);
                }
            }
        }
    }
}


================================================
FILE: src/device_events/event_loop.rs
================================================
use super::{CallbackGuard, KeyboardCallbacks};
use std::sync::{Arc, LazyLock, Mutex, Weak};
use std::thread::{sleep, spawn, JoinHandle};
use std::time::Duration;
use MouseState;
use {DeviceQuery, MouseCallbacks};
use {DeviceState, Keycode};
use {MouseButton, MousePosition};

pub(crate) struct EventLoop {
    keyboard_callbacks: Arc<KeyboardCallbacks>,
    mouse_callbacks: Arc<MouseCallbacks>,
    _keyboard_thread: JoinHandle<()>,
    _mouse_thread: JoinHandle<()>,
}

fn keyboard_thread(callbacks: Weak<KeyboardCallbacks>, sleep_dur: Duration) -> JoinHandle<()> {
    spawn(move || {
        let device_state = DeviceState::new();
        let mut prev_keys = vec![];
        while let Some(callbacks) = callbacks.upgrade() {
            let keys = device_state.get_keys();
            for key_state in &keys {
                if !prev_keys.contains(key_state) {
                    callbacks.run_key_down(key_state);
                }
            }
            for key_state in &prev_keys {
                if !keys.contains(key_state) {
                    callbacks.run_key_up(key_state);
                }
            }
            prev_keys = keys;
            sleep(sleep_dur);
        }
    })
}

fn mouse_thread(callbacks: Weak<MouseCallbacks>, sleep_dur: Duration) -> JoinHandle<()> {
    spawn(move || {
        let device_state = DeviceState::new();
        let mut previous_mouse_state = MouseState::default();
        while let Some(callbacks) = callbacks.upgrade() {
            let mouse_state = device_state.get_mouse();
            for (index, (previous_state, current_state)) in previous_mouse_state
                .button_pressed
                .iter()
                .zip(mouse_state.button_pressed.iter())
                .enumerate()
            {
                if !(*previous_state) && *current_state {
                    callbacks.run_mouse_down(&index);
                } else if *previous_state && !(*current_state) {
                    callbacks.run_mouse_up(&index);
                }
            }
            if mouse_state.coords != previous_mouse_state.coords {
                callbacks.run_mouse_move(&mouse_state.coords);
            }
            previous_mouse_state = mouse_state;
            sleep(sleep_dur);
        }
    })
}

impl Default for EventLoop {
    fn default() -> Self {
        Self::new(Duration::from_micros(100))
    }
}

impl EventLoop {
    fn new(sleep_dur: Duration) -> Self {
        let keyboard_callbacks = Arc::new(KeyboardCallbacks::default());
        let mouse_callbacks = Arc::new(MouseCallbacks::default());
        let _keyboard_thread = keyboard_thread(Arc::downgrade(&keyboard_callbacks), sleep_dur);
        let _mouse_thread = mouse_thread(Arc::downgrade(&mouse_callbacks), sleep_dur);
        Self {
            keyboard_callbacks,
            mouse_callbacks,
            _keyboard_thread,
            _mouse_thread,
        }
    }

    pub fn on_key_down<Callback: Fn(&Keycode) + Send + Sync + 'static>(
        &mut self,
        callback: Callback,
    ) -> CallbackGuard<Callback> {
        let _callback = Arc::new(callback);
        self.keyboard_callbacks.push_key_down(_callback.clone());
        CallbackGuard { _callback }
    }

    pub fn on_key_up<Callback: Fn(&Keycode) + Send + Sync + 'static>(
        &mut self,
        callback: Callback,
    ) -> CallbackGuard<Callback> {
        let _callback = Arc::new(callback);
        self.keyboard_callbacks.push_key_up(_callback.clone());
        CallbackGuard { _callback }
    }

    pub fn on_mouse_move<Callback: Fn(&MousePosition) + Send + Sync + 'static>(
        &mut self,
        callback: Callback,
    ) -> CallbackGuard<Callback> {
        let _callback = Arc::new(callback);
        self.mouse_callbacks.push_mouse_move(_callback.clone());
        CallbackGuard { _callback }
    }

    pub fn on_mouse_up<Callback: Fn(&MouseButton) + Send + Sync + 'static>(
        &mut self,
        callback: Callback,
    ) -> CallbackGuard<Callback> {
        let _callback = Arc::new(callback);
        self.mouse_callbacks.push_mouse_up(_callback.clone());
        CallbackGuard { _callback }
    }

    pub fn on_mouse_down<Callback: Fn(&MouseButton) + Send + Sync + 'static>(
        &mut self,
        callback: Callback,
    ) -> CallbackGuard<Callback> {
        let _callback = Arc::new(callback);
        self.mouse_callbacks.push_mouse_down(_callback.clone());
        CallbackGuard { _callback }
    }
}

pub(crate) static EVENT_LOOP: LazyLock<Mutex<Option<EventLoop>>> = LazyLock::new(|| Default::default());

pub(crate) fn init_event_loop(sleep_dur: Duration) -> bool {
    let Ok(mut lock) = EVENT_LOOP.lock() else {
        return false;
    };
    if lock.is_some() {
        return false;
    }
    *lock = Some(EventLoop::new(sleep_dur));
    true
}

================================================
FILE: src/device_events/mod.rs
================================================
//! Devices events listeners.
//! 
//! This module contains the implementation of the DeviceEventsHandler struct.
//! This allows to register callbacks for device events.
//! for the current state of the device, see the [`DeviceState`](crate::device_state::DeviceState) struct.
//! 
//! # Example
//! 
//! ```no_run
//! use device_query::{DeviceEvents, DeviceEventsHandler, Keycode, MouseButton};
//! use std::time::Duration;
//! 
//! fn main() {
//!   let device_events = DeviceEventsHandler::new(Duration::from_millis(10)).unwrap();
//!   // Register a key down event callback
//!   // The guard is used to keep the callback alive
//!   let _guard = device_events.on_key_down(|key| {
//!     println!("Key down: {:?}", key);
//!   });
//!   // Keep the main thread alive
//!   loop {}
//! }
//! 
//! ```
//! 

mod callback;
mod event_loop;
mod utils;

use std::time::Duration;

use crate::MousePosition;

pub use self::callback::*;
use self::event_loop::*;

use Keycode;
use MouseButton;

/// All the supported devices events.
pub trait DeviceEvents {
    /// Register an on key down event callback.
    fn on_key_down<Callback: Fn(&Keycode) + Sync + Send + 'static>(
        &self,
        callback: Callback,
    ) -> CallbackGuard<Callback>;
    /// Register an on key up event callback.
    fn on_key_up<Callback: Fn(&Keycode) + Sync + Send + 'static>(
        &self,
        callback: Callback,
    ) -> CallbackGuard<Callback>;

    /// Register an on mouse move event callback.
    fn on_mouse_move<Callback: Fn(&MousePosition) + Sync + Send + 'static>(
        &self,
        callback: Callback,
    ) -> CallbackGuard<Callback>;
    /// Register an on mouse button down event callback.
    fn on_mouse_down<Callback: Fn(&MouseButton) + Sync + Send + 'static>(
        &self,
        callback: Callback,
    ) -> CallbackGuard<Callback>;
    /// Register an on mouse button up event callback.
    fn on_mouse_up<Callback: Fn(&MouseButton) + Sync + Send + 'static>(
        &self,
        callback: Callback,
    ) -> CallbackGuard<Callback>;
}

pub struct DeviceEventsHandler;

impl DeviceEventsHandler {
    /// Attempts to start event loop with the given sleep duration.
    /// Returns None if the event loop is already running.
    pub fn new(sleep_dur: Duration) -> Option<Self> {
        event_loop::init_event_loop(sleep_dur).then_some(DeviceEventsHandler)
    }
}

/// Returns the event loop.
///
/// This is a workaround to avoid using unsafe code,
/// the existence of a [`DeviceEventsHandler`] means that the event loop is already initialized.
macro_rules! get_event_loop {
    () => {
        EVENT_LOOP
            .lock()
            .expect("Couldn't lock EVENT_LOOP")
            .as_mut()
            .unwrap()
    };
}

impl DeviceEvents for DeviceEventsHandler {
    fn on_key_down<Callback: Fn(&Keycode) + Sync + Send + 'static>(
        &self,
        callback: Callback,
    ) -> CallbackGuard<Callback> {
        get_event_loop!().on_key_down(callback)
    }

    fn on_key_up<Callback: Fn(&Keycode) + Sync + Send + 'static>(
        &self,
        callback: Callback,
    ) -> CallbackGuard<Callback> {
        get_event_loop!().on_key_up(callback)
    }

    fn on_mouse_move<Callback: Fn(&MousePosition) + Sync + Send + 'static>(
        &self,
        callback: Callback,
    ) -> CallbackGuard<Callback> {
        get_event_loop!().on_mouse_move(callback)
    }

    fn on_mouse_down<Callback: Fn(&MouseButton) + Sync + Send + 'static>(
        &self,
        callback: Callback,
    ) -> CallbackGuard<Callback> {
        get_event_loop!().on_mouse_down(callback)
    }

    fn on_mouse_up<Callback: Fn(&MouseButton) + Sync + Send + 'static>(
        &self,
        callback: Callback,
    ) -> CallbackGuard<Callback> {
        get_event_loop!().on_mouse_up(callback)
    }
}


================================================
FILE: src/device_events/utils.rs
================================================
//! Utils.

/// This is a placeholder for the unstable feature.
pub trait DrainFilter<T> {
    fn drain_filter<F>(&mut self, filter: F)
    where
        F: FnMut(&mut T) -> bool;
}

impl<T> DrainFilter<T> for Vec<T> {
    fn drain_filter<F>(&mut self, filter: F)
    where
        F: FnMut(&mut T) -> bool,
    {
        let mut filter = filter;
        if self.is_empty() {
            return;
        }

        let mut i = self.len();
        while i > 0 {
            i -= 1;
            if filter(&mut self[i]) {
                self.remove(i);
            }
        }
    }
}


================================================
FILE: src/device_query.rs
================================================
//! Query functions.

use DeviceState;
use {Keycode, MouseState};

/// Trait to get the state of the supported devices.
pub trait DeviceQuery {
    /// Get MouseState.
    fn get_mouse(&self) -> MouseState;

    /// Get Keyboard state.
    fn get_keys(&self) -> Vec<Keycode>;
}

impl DeviceQuery for DeviceState {
    /// Query for the current mouse position and mouse button device_state.
    fn get_mouse(&self) -> MouseState {
        self.query_pointer()
    }

    /// Query for all keys that are currently pressed down.
    fn get_keys(&self) -> Vec<Keycode> {
        self.query_keymap()
    }
}


================================================
FILE: src/device_state/linux/kernel_key.rs
================================================
/// A non-exhaustive list of keycodes from Linux. Only the ones that this library currently supports
/// is currently listed in this file; other keycodes will need to be added later as needed.
/// Reference: https://github.com/torvalds/linux/blob/master/include/uapi/linux/input-event-codes.h

pub const KEY_ESC: u16 = 1;
pub const KEY_1: u16 = 2;
pub const KEY_2: u16 = 3;
pub const KEY_3: u16 = 4;
pub const KEY_4: u16 = 5;
pub const KEY_5: u16 = 6;
pub const KEY_6: u16 = 7;
pub const KEY_7: u16 = 8;
pub const KEY_8: u16 = 9;
pub const KEY_9: u16 = 10;
pub const KEY_0: u16 = 11;
pub const KEY_MINUS: u16 = 12;
pub const KEY_EQUAL: u16 = 13;
pub const KEY_BACKSPACE: u16 = 14;
pub const KEY_TAB: u16 = 15;
pub const KEY_Q: u16 = 16;
pub const KEY_W: u16 = 17;
pub const KEY_E: u16 = 18;
pub const KEY_R: u16 = 19;
pub const KEY_T: u16 = 20;
pub const KEY_Y: u16 = 21;
pub const KEY_U: u16 = 22;
pub const KEY_I: u16 = 23;
pub const KEY_O: u16 = 24;
pub const KEY_P: u16 = 25;
pub const KEY_LEFTBRACE: u16 = 26;
pub const KEY_RIGHTBRACE: u16 = 27;
pub const KEY_ENTER: u16 = 28;
pub const KEY_LEFTCTRL: u16 = 29;
pub const KEY_A: u16 = 30;
pub const KEY_S: u16 = 31;
pub const KEY_D: u16 = 32;
pub const KEY_F: u16 = 33;
pub const KEY_G: u16 = 34;
pub const KEY_H: u16 = 35;
pub const KEY_J: u16 = 36;
pub const KEY_K: u16 = 37;
pub const KEY_L: u16 = 38;
pub const KEY_SEMICOLON: u16 = 39;
pub const KEY_APOSTROPHE: u16 = 40;
pub const KEY_GRAVE: u16 = 41;
pub const KEY_LEFTSHIFT: u16 = 42;
pub const KEY_BACKSLASH: u16 = 43;
pub const KEY_Z: u16 = 44;
pub const KEY_X: u16 = 45;
pub const KEY_C: u16 = 46;
pub const KEY_V: u16 = 47;
pub const KEY_B: u16 = 48;
pub const KEY_N: u16 = 49;
pub const KEY_M: u16 = 50;
pub const KEY_COMMA: u16 = 51;
pub const KEY_DOT: u16 = 52;
pub const KEY_SLASH: u16 = 53;
pub const KEY_RIGHTSHIFT: u16 = 54;
pub const KEY_KPASTERISK: u16 = 55;
pub const KEY_LEFTALT: u16 = 56;
pub const KEY_SPACE: u16 = 57;
pub const KEY_CAPSLOCK: u16 = 58;
pub const KEY_F1: u16 = 59;
pub const KEY_F2: u16 = 60;
pub const KEY_F3: u16 = 61;
pub const KEY_F4: u16 = 62;
pub const KEY_F5: u16 = 63;
pub const KEY_F6: u16 = 64;
pub const KEY_F7: u16 = 65;
pub const KEY_F8: u16 = 66;
pub const KEY_F9: u16 = 67;
pub const KEY_F10: u16 = 68;
pub const KEY_KP7: u16 = 71;
pub const KEY_KP8: u16 = 72;
pub const KEY_KP9: u16 = 73;
pub const KEY_KPMINUS: u16 = 74;
pub const KEY_KP4: u16 = 75;
pub const KEY_KP5: u16 = 76;
pub const KEY_KP6: u16 = 77;
pub const KEY_KPPLUS: u16 = 78;
pub const KEY_KP1: u16 = 79;
pub const KEY_KP2: u16 = 80;
pub const KEY_KP3: u16 = 81;
pub const KEY_KP0: u16 = 82;
pub const KEY_KPDOT: u16 = 83;
pub const KEY_F11: u16 = 87;
pub const KEY_F12: u16 = 88;
pub const KEY_F13: u16 = 183;
pub const KEY_F14: u16 = 184;
pub const KEY_F15: u16 = 185;
pub const KEY_F16: u16 = 186;
pub const KEY_F17: u16 = 187;
pub const KEY_F18: u16 = 188;
pub const KEY_F19: u16 = 189;
pub const KEY_F20: u16 = 190;
pub const KEY_KPENTER: u16 = 96;
pub const KEY_RIGHTCTRL: u16 = 97;
pub const KEY_KPSLASH: u16 = 98;
pub const KEY_RIGHTALT: u16 = 100;
pub const KEY_HOME: u16 = 102;
pub const KEY_UP: u16 = 103;
pub const KEY_PAGEUP: u16 = 104;
pub const KEY_LEFT: u16 = 105;
pub const KEY_RIGHT: u16 = 106;
pub const KEY_END: u16 = 107;
pub const KEY_DOWN: u16 = 108;
pub const KEY_PAGEDOWN: u16 = 109;
pub const KEY_INSERT: u16 = 110;
pub const KEY_DELETE: u16 = 111;
pub const KEY_KPEQUAL: u16 = 117;
pub const KEY_LEFTMETA: u16 = 125;
pub const KEY_RIGHTMETA: u16 = 126;


================================================
FILE: src/device_state/linux/mod.rs
================================================
extern crate x11;

use self::x11::xlib;
use keymap::Keycode;
use mouse_state::MouseState;
use std::os::raw::c_char;
use std::ptr;
use std::rc::Rc;
use std::slice;

mod kernel_key;

#[derive(Debug, Clone)]
/// Device state descriptor.
pub struct DeviceState {
    xc: Rc<X11Connection>,
}

#[derive(Debug)]
struct X11Connection {
    display: *mut xlib::Display,
}

impl Drop for X11Connection {
    fn drop(&mut self) {
        unsafe {
            xlib::XCloseDisplay(self.display);
        }
    }
}

impl DeviceState {
    /// Creates a new DeviceState.
    pub fn new() -> DeviceState {
        unsafe {
            let display = xlib::XOpenDisplay(ptr::null());
            if display.as_ref().is_none() {
                panic!("Could not connect to a X display");
            }
            DeviceState {
                xc: Rc::new(X11Connection { display }),
            }
        }
    }

    /// Create a new DeviceState. In case of failure, doesn't panic.
    pub fn checked_new() -> Option<DeviceState> {
        unsafe {
            let display = xlib::XOpenDisplay(ptr::null());
            if display.as_ref().is_none() {
                eprintln!("Could not connect to a X display");
                return None;
            }
            Some(DeviceState {
                xc: Rc::new(X11Connection { display }),
            })
        }
    }

    /// Query the `MouseState`.
    pub fn query_pointer(&self) -> MouseState {
        let root;
        let mut root_x = 0;
        let mut root_y = 0;
        let mut win_x = 0;
        let mut win_y = 0;
        let mut root_return = 0;
        let mut child_return = 0;
        let mut mask_return = 0;
        unsafe {
            root = xlib::XDefaultRootWindow(self.xc.display);
            xlib::XQueryPointer(
                self.xc.display,
                root,
                &mut root_return,
                &mut child_return,
                &mut root_x,
                &mut root_y,
                &mut win_x,
                &mut win_y,
                &mut mask_return,
            );
        }
        let button1pressed = mask_return & xlib::Button1Mask > 0;
        let button2pressed = mask_return & xlib::Button2Mask > 0;
        let button3pressed = mask_return & xlib::Button3Mask > 0;
        let button4pressed = mask_return & xlib::Button4Mask > 0;
        let button5pressed = mask_return & xlib::Button5Mask > 0;

        // Use 1-based indexing here so people can just query the button
        // number they're interested in directly.
        let button_pressed = vec![
            false,
            button1pressed,
            button2pressed,
            button3pressed,
            button4pressed,
            button5pressed,
        ];
        MouseState {
            coords: (win_x, win_y),
            button_pressed,
        }
    }

    /// Query the Keyboard state.
    pub fn query_keymap(&self) -> Vec<Keycode> {
        let mut keycodes = vec![];
        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 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) {
                            keycodes.push(k)
                        }
                    }
                }
            }
        }
        keycodes
    }

    fn kernel_key_to_keycode(&self, kernel_code: u8) -> Option<Keycode> {
        match kernel_code as u16 {
            kernel_key::KEY_0 => Some(Keycode::Key0),
            kernel_key::KEY_1 => Some(Keycode::Key1),
            kernel_key::KEY_2 => Some(Keycode::Key2),
            kernel_key::KEY_3 => Some(Keycode::Key3),
            kernel_key::KEY_4 => Some(Keycode::Key4),
            kernel_key::KEY_5 => Some(Keycode::Key5),
            kernel_key::KEY_6 => Some(Keycode::Key6),
            kernel_key::KEY_7 => Some(Keycode::Key7),
            kernel_key::KEY_8 => Some(Keycode::Key8),
            kernel_key::KEY_9 => Some(Keycode::Key9),
            kernel_key::KEY_A => Some(Keycode::A),
            kernel_key::KEY_B => Some(Keycode::B),
            kernel_key::KEY_C => Some(Keycode::C),
            kernel_key::KEY_D => Some(Keycode::D),
            kernel_key::KEY_E => Some(Keycode::E),
            kernel_key::KEY_F => Some(Keycode::F),
            kernel_key::KEY_G => Some(Keycode::G),
            kernel_key::KEY_H => Some(Keycode::H),
            kernel_key::KEY_I => Some(Keycode::I),
            kernel_key::KEY_J => Some(Keycode::J),
            kernel_key::KEY_K => Some(Keycode::K),
            kernel_key::KEY_L => Some(Keycode::L),
            kernel_key::KEY_M => Some(Keycode::M),
            kernel_key::KEY_N => Some(Keycode::N),
            kernel_key::KEY_O => Some(Keycode::O),
            kernel_key::KEY_P => Some(Keycode::P),
            kernel_key::KEY_Q => Some(Keycode::Q),
            kernel_key::KEY_R => Some(Keycode::R),
            kernel_key::KEY_S => Some(Keycode::S),
            kernel_key::KEY_T => Some(Keycode::T),
            kernel_key::KEY_U => Some(Keycode::U),
            kernel_key::KEY_V => Some(Keycode::V),
            kernel_key::KEY_W => Some(Keycode::W),
            kernel_key::KEY_X => Some(Keycode::X),
            kernel_key::KEY_Y => Some(Keycode::Y),
            kernel_key::KEY_Z => Some(Keycode::Z),
            kernel_key::KEY_F1 => Some(Keycode::F1),
            kernel_key::KEY_F2 => Some(Keycode::F2),
            kernel_key::KEY_F3 => Some(Keycode::F3),
            kernel_key::KEY_F4 => Some(Keycode::F4),
            kernel_key::KEY_F5 => Some(Keycode::F5),
            kernel_key::KEY_F6 => Some(Keycode::F6),
            kernel_key::KEY_F7 => Some(Keycode::F7),
            kernel_key::KEY_F8 => Some(Keycode::F8),
            kernel_key::KEY_F9 => Some(Keycode::F9),
            kernel_key::KEY_F10 => Some(Keycode::F10),
            kernel_key::KEY_F11 => Some(Keycode::F11),
            kernel_key::KEY_F12 => Some(Keycode::F12),
            kernel_key::KEY_F13 => Some(Keycode::F13),
            kernel_key::KEY_F14 => Some(Keycode::F14),
            kernel_key::KEY_F15 => Some(Keycode::F15),
            kernel_key::KEY_F16 => Some(Keycode::F16),
            kernel_key::KEY_F17 => Some(Keycode::F17),
            kernel_key::KEY_F18 => Some(Keycode::F18),
            kernel_key::KEY_F19 => Some(Keycode::F19),
            kernel_key::KEY_F20 => Some(Keycode::F20),
            kernel_key::KEY_KP0 => Some(Keycode::Numpad0),
            kernel_key::KEY_KP1 => Some(Keycode::Numpad1),
            kernel_key::KEY_KP2 => Some(Keycode::Numpad2),
            kernel_key::KEY_KP3 => Some(Keycode::Numpad3),
            kernel_key::KEY_KP4 => Some(Keycode::Numpad4),
            kernel_key::KEY_KP5 => Some(Keycode::Numpad5),
            kernel_key::KEY_KP6 => Some(Keycode::Numpad6),
            kernel_key::KEY_KP7 => Some(Keycode::Numpad7),
            kernel_key::KEY_KP8 => Some(Keycode::Numpad8),
            kernel_key::KEY_KP9 => Some(Keycode::Numpad9),
            kernel_key::KEY_KPENTER => Some(Keycode::NumpadEnter),
            kernel_key::KEY_KPMINUS => Some(Keycode::NumpadSubtract),
            kernel_key::KEY_KPPLUS => Some(Keycode::NumpadAdd),
            kernel_key::KEY_KPSLASH => Some(Keycode::NumpadDivide),
            kernel_key::KEY_KPASTERISK => Some(Keycode::NumpadMultiply),
            kernel_key::KEY_KPEQUAL => Some(Keycode::NumpadEquals),
            kernel_key::KEY_KPDOT => Some(Keycode::NumpadDecimal),
            kernel_key::KEY_ESC => Some(Keycode::Escape),
            kernel_key::KEY_SPACE => Some(Keycode::Space),
            kernel_key::KEY_LEFTCTRL => Some(Keycode::LControl),
            kernel_key::KEY_RIGHTCTRL => Some(Keycode::RControl),
            kernel_key::KEY_LEFTSHIFT => Some(Keycode::LShift),
            kernel_key::KEY_RIGHTSHIFT => Some(Keycode::RShift),
            kernel_key::KEY_LEFTALT => Some(Keycode::LAlt),
            kernel_key::KEY_RIGHTALT => Some(Keycode::RAlt),
            kernel_key::KEY_LEFTMETA => Some(Keycode::LMeta),
            kernel_key::KEY_RIGHTMETA => Some(Keycode::RMeta),
            kernel_key::KEY_ENTER => Some(Keycode::Enter),
            kernel_key::KEY_UP => Some(Keycode::Up),
            kernel_key::KEY_DOWN => Some(Keycode::Down),
            kernel_key::KEY_LEFT => Some(Keycode::Left),
            kernel_key::KEY_RIGHT => Some(Keycode::Right),
            kernel_key::KEY_BACKSPACE => Some(Keycode::Backspace),
            kernel_key::KEY_CAPSLOCK => Some(Keycode::CapsLock),
            kernel_key::KEY_TAB => Some(Keycode::Tab),
            kernel_key::KEY_HOME => Some(Keycode::Home),
            kernel_key::KEY_END => Some(Keycode::End),
            kernel_key::KEY_PAGEUP => Some(Keycode::PageUp),
            kernel_key::KEY_PAGEDOWN => Some(Keycode::PageDown),
            kernel_key::KEY_INSERT => Some(Keycode::Insert),
            kernel_key::KEY_DELETE => Some(Keycode::Delete),
            kernel_key::KEY_GRAVE => Some(Keycode::Grave),
            kernel_key::KEY_MINUS => Some(Keycode::Minus),
            kernel_key::KEY_EQUAL => Some(Keycode::Equal),
            kernel_key::KEY_LEFTBRACE => Some(Keycode::LeftBracket),
            kernel_key::KEY_RIGHTBRACE => Some(Keycode::RightBracket),
            kernel_key::KEY_BACKSLASH => Some(Keycode::BackSlash),
            kernel_key::KEY_SEMICOLON => Some(Keycode::Semicolon),
            kernel_key::KEY_APOSTROPHE => Some(Keycode::Apostrophe),
            kernel_key::KEY_COMMA => Some(Keycode::Comma),
            kernel_key::KEY_DOT => Some(Keycode::Dot),
            kernel_key::KEY_SLASH => Some(Keycode::Slash),
            _ => None,
        }
    }
}


================================================
FILE: src/device_state/macos/mod.rs
================================================
extern crate macos_accessibility_client;

use keymap::Keycode;
use mouse_state::MouseState;

#[derive(Debug, Clone)]
pub struct DeviceState;
const MAPPING: &[(readkey::Keycode, Keycode)] = &[
    (readkey::Keycode::_0, Keycode::Key0),
    (readkey::Keycode::_1, Keycode::Key1),
    (readkey::Keycode::_2, Keycode::Key2),
    (readkey::Keycode::_3, Keycode::Key3),
    (readkey::Keycode::_4, Keycode::Key4),
    (readkey::Keycode::_5, Keycode::Key5),
    (readkey::Keycode::_6, Keycode::Key6),
    (readkey::Keycode::_7, Keycode::Key7),
    (readkey::Keycode::_8, Keycode::Key8),
    (readkey::Keycode::_9, Keycode::Key9),
    (readkey::Keycode::A, Keycode::A),
    (readkey::Keycode::B, Keycode::B),
    (readkey::Keycode::C, Keycode::C),
    (readkey::Keycode::D, Keycode::D),
    (readkey::Keycode::E, Keycode::E),
    (readkey::Keycode::F, Keycode::F),
    (readkey::Keycode::G, Keycode::G),
    (readkey::Keycode::H, Keycode::H),
    (readkey::Keycode::I, Keycode::I),
    (readkey::Keycode::J, Keycode::J),
    (readkey::Keycode::K, Keycode::K),
    (readkey::Keycode::L, Keycode::L),
    (readkey::Keycode::M, Keycode::M),
    (readkey::Keycode::N, Keycode::N),
    (readkey::Keycode::O, Keycode::O),
    (readkey::Keycode::P, Keycode::P),
    (readkey::Keycode::Q, Keycode::Q),
    (readkey::Keycode::R, Keycode::R),
    (readkey::Keycode::S, Keycode::S),
    (readkey::Keycode::T, Keycode::T),
    (readkey::Keycode::U, Keycode::U),
    (readkey::Keycode::V, Keycode::V),
    (readkey::Keycode::W, Keycode::W),
    (readkey::Keycode::X, Keycode::X),
    (readkey::Keycode::Y, Keycode::Y),
    (readkey::Keycode::Z, Keycode::Z),
    (readkey::Keycode::F1, Keycode::F1),
    (readkey::Keycode::F2, Keycode::F2),
    (readkey::Keycode::F3, Keycode::F3),
    (readkey::Keycode::F4, Keycode::F4),
    (readkey::Keycode::F5, Keycode::F5),
    (readkey::Keycode::F6, Keycode::F6),
    (readkey::Keycode::F7, Keycode::F7),
    (readkey::Keycode::F8, Keycode::F8),
    (readkey::Keycode::F9, Keycode::F9),
    (readkey::Keycode::F10, Keycode::F10),
    (readkey::Keycode::F11, Keycode::F11),
    (readkey::Keycode::F12, Keycode::F12),
    (readkey::Keycode::F13, Keycode::F13),
    (readkey::Keycode::F14, Keycode::F14),
    (readkey::Keycode::F15, Keycode::F15),
    (readkey::Keycode::F16, Keycode::F16),
    (readkey::Keycode::F17, Keycode::F17),
    (readkey::Keycode::F18, Keycode::F18),
    (readkey::Keycode::F19, Keycode::F19),
    (readkey::Keycode::F20, Keycode::F20),
    (readkey::Keycode::Keypad0, Keycode::Numpad0),
    (readkey::Keycode::Keypad1, Keycode::Numpad1),
    (readkey::Keycode::Keypad2, Keycode::Numpad2),
    (readkey::Keycode::Keypad3, Keycode::Numpad3),
    (readkey::Keycode::Keypad4, Keycode::Numpad4),
    (readkey::Keycode::Keypad5, Keycode::Numpad5),
    (readkey::Keycode::Keypad6, Keycode::Numpad6),
    (readkey::Keycode::Keypad7, Keycode::Numpad7),
    (readkey::Keycode::Keypad8, Keycode::Numpad8),
    (readkey::Keycode::Keypad9, Keycode::Numpad9),
    (readkey::Keycode::KeypadPlus, Keycode::NumpadAdd),
    (readkey::Keycode::KeypadMinus, Keycode::NumpadSubtract),
    (readkey::Keycode::KeypadDivide, Keycode::NumpadDivide),
    (readkey::Keycode::KeypadMultiply, Keycode::NumpadMultiply),
    (readkey::Keycode::KeypadEquals, Keycode::NumpadEquals),
    (readkey::Keycode::KeypadEnter, Keycode::NumpadEnter),
    (readkey::Keycode::KeypadDecimal, Keycode::NumpadDecimal),
    (readkey::Keycode::Escape, Keycode::Escape),
    (readkey::Keycode::Space, Keycode::Space),
    (readkey::Keycode::Control, Keycode::LControl),
    (readkey::Keycode::RightControl, Keycode::RControl),
    (readkey::Keycode::Shift, Keycode::LShift),
    (readkey::Keycode::RightShift, Keycode::RShift),
    (readkey::Keycode::Option, Keycode::LOption),
    (readkey::Keycode::RightOption, Keycode::ROption),
    (readkey::Keycode::Command, Keycode::Command),
    (readkey::Keycode::RightCommand, Keycode::RCommand),
    (readkey::Keycode::Return, Keycode::Enter),
    (readkey::Keycode::Up, Keycode::Up),
    (readkey::Keycode::Down, Keycode::Down),
    (readkey::Keycode::Left, Keycode::Left),
    (readkey::Keycode::Right, Keycode::Right),
    (readkey::Keycode::Delete, Keycode::Backspace),
    (readkey::Keycode::CapsLock, Keycode::CapsLock),
    (readkey::Keycode::Tab, Keycode::Tab),
    (readkey::Keycode::Home, Keycode::Home),
    (readkey::Keycode::End, Keycode::End),
    (readkey::Keycode::PageUp, Keycode::PageUp),
    (readkey::Keycode::PageDown, Keycode::PageDown),
    (readkey::Keycode::Help, Keycode::Insert),
    (readkey::Keycode::ForwardDelete, Keycode::Delete),
    (readkey::Keycode::Grave, Keycode::Grave),
    (readkey::Keycode::Minus, Keycode::Minus),
    (readkey::Keycode::Equal, Keycode::Equal),
    (readkey::Keycode::LeftBracket, Keycode::LeftBracket),
    (readkey::Keycode::RightBracket, Keycode::RightBracket),
    (readkey::Keycode::Backslash, Keycode::BackSlash),
    (readkey::Keycode::Semicolon, Keycode::Semicolon),
    (readkey::Keycode::Quote, Keycode::Apostrophe),
    (readkey::Keycode::Comma, Keycode::Comma),
    (readkey::Keycode::Period, Keycode::Dot),
    (readkey::Keycode::Slash, Keycode::Slash),
];

impl DeviceState {
    pub fn new() -> DeviceState {
        // TODO: remove this
        assert!(
            has_accessibility(),
            "This app does not have Accessibility Permissions enabled and will not work"
        );

        DeviceState {}
    }

    /// returns `None` if app doesn't accessibility permissions.
    pub fn checked_new() -> Option<DeviceState> {
        if has_accessibility() {
            Some(DeviceState {})
        } else {
            None
        }
    }

    pub fn query_pointer(&self) -> MouseState {
        let (x, y) = readmouse::Mouse::location();
        let button_pressed = vec![
            false,
            readmouse::Mouse::Left.is_pressed(),
            readmouse::Mouse::Right.is_pressed(),
            readmouse::Mouse::Center.is_pressed(),
            false,
        ];

        MouseState {
            coords: (x as i32, y as i32),
            button_pressed,
        }
    }

    pub fn query_keymap(&self) -> Vec<Keycode> {
        MAPPING
            .iter()
            .filter(|(from, _)| from.is_pressed())
            .map(|(_, to)| *to)
            .collect()
    }
}

/// Returns true if the Accessibility permissions necessary for this library to work are granted
/// to this process
///
/// If this returns false, the app can request them through the OS APIs, or the user can:
///   1. open the MacOS system preferences
///   2. go to Security -> Privacy
///   3. scroll down to Accessibility and unlock it
///   4. Add the app that is using device_query (such as your terminal) to the list
///
fn has_accessibility() -> bool {
    use self::macos_accessibility_client::accessibility::*;
    // Without prompting:
    // application_is_trusted()

    // With prompting:
    application_is_trusted_with_prompt()
}


================================================
FILE: src/device_state/mod.rs
================================================
//! DeviceState implementation.
//! 
//! This module contains the implementation of the DeviceState struct.
//! This only allows to get the current state of the device.
//! for callbacks, see the [`DeviceEventsHandler`](crate::device_events::DeviceEventsHandler) struct.
//! 
//! # Example
//! 
//! ```no_run
//! use device_query::{DeviceState, DeviceQuery};
//! 
//! fn main() {
//!   let device_state = DeviceState::new(); 
//!   println!("Mouse position: {:?}", device_state.get_mouse());
//!   println!("Key down: {:?}", device_state.get_keys());
//! }
//! 
//! ```

#[cfg(target_os = "linux")]
mod linux;
#[cfg(target_os = "linux")]
pub use self::linux::DeviceState;

#[cfg(target_os = "windows")]
mod windows;
#[cfg(target_os = "windows")]
pub use self::windows::DeviceState;

#[cfg(target_os = "macos")]
mod macos;
#[cfg(target_os = "macos")]
pub use self::macos::DeviceState;

impl Default for DeviceState {
    fn default() -> Self {
        Self::new()
    }
}


================================================
FILE: src/device_state/windows/mod.rs
================================================
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::WindowsAndMessaging::GetCursorPos;

#[derive(Debug, Clone)]
pub struct DeviceState;

impl DeviceState {
    pub fn new() -> Self {
        Self {}
    }

    // Adding because Linux and OSX supports this where `new` can panic.
    pub fn checked_new() -> Option<Self> {
        Some(Self::new())
    }

    pub fn query_pointer(&self) -> MouseState {
        let point = &mut POINT { x: 0, y: 0 };
        let button1pressed;
        let button2pressed;
        let button3pressed;
        let button4pressed;
        let button5pressed;
        let coords;
        unsafe {
            coords = if GetCursorPos(point).into() {
                (point.x, point.y)
            } else {
                (0, 0)
            };
            button1pressed =
                GetAsyncKeyState(KeyboardAndMouse::VK_LBUTTON.0 as i32) as u32 & 0x8000 != 0;
            button2pressed =
                GetAsyncKeyState(KeyboardAndMouse::VK_RBUTTON.0 as i32) as u32 & 0x8000 != 0;
            button3pressed =
                GetAsyncKeyState(KeyboardAndMouse::VK_MBUTTON.0 as i32) as u32 & 0x8000 != 0;
            button4pressed =
                GetAsyncKeyState(KeyboardAndMouse::VK_XBUTTON1.0 as i32) as u32 & 0x8000 != 0;
            button5pressed =
                GetAsyncKeyState(KeyboardAndMouse::VK_XBUTTON2.0 as i32) as u32 & 0x8000 != 0;
        }
        MouseState {
            coords,
            button_pressed: vec![
                false,
                button1pressed,
                button2pressed,
                button3pressed,
                button4pressed,
                button5pressed,
            ],
        }
    }

    pub fn query_keymap(&self) -> Vec<Keycode> {
        let mut keycodes = vec![];
        let mut keymap = vec![];
        unsafe {
            for key in 0..256 {
                keymap.push(GetAsyncKeyState(key));
            }
        }
        for (ix, byte) in keymap.iter().enumerate() {
            if *byte as u32 & 0x8000 != 0 {
                if let Some(k) = self.win_key_to_keycode(ix as u16) {
                    keycodes.push(k)
                }
            }
        }
        keycodes
    }

    fn win_key_to_keycode(&self, win_key: u16) -> Option<Keycode> {
        let mut keycode = match VIRTUAL_KEY(win_key) {
            KeyboardAndMouse::VK_F1 => Some(Keycode::F1),
            KeyboardAndMouse::VK_F2 => Some(Keycode::F2),
            KeyboardAndMouse::VK_F3 => Some(Keycode::F3),
            KeyboardAndMouse::VK_F4 => Some(Keycode::F4),
            KeyboardAndMouse::VK_F5 => Some(Keycode::F5),
            KeyboardAndMouse::VK_F6 => Some(Keycode::F6),
            KeyboardAndMouse::VK_F7 => Some(Keycode::F7),
            KeyboardAndMouse::VK_F8 => Some(Keycode::F8),
            KeyboardAndMouse::VK_F9 => Some(Keycode::F9),
            KeyboardAndMouse::VK_F10 => Some(Keycode::F10),
            KeyboardAndMouse::VK_F11 => Some(Keycode::F11),
            KeyboardAndMouse::VK_F12 => Some(Keycode::F12),
            KeyboardAndMouse::VK_F13 => Some(Keycode::F13),
            KeyboardAndMouse::VK_F14 => Some(Keycode::F14),
            KeyboardAndMouse::VK_F15 => Some(Keycode::F15),
            KeyboardAndMouse::VK_F16 => Some(Keycode::F16),
            KeyboardAndMouse::VK_F17 => Some(Keycode::F17),
            KeyboardAndMouse::VK_F18 => Some(Keycode::F18),
            KeyboardAndMouse::VK_F19 => Some(Keycode::F19),
            KeyboardAndMouse::VK_F20 => Some(Keycode::F20),
            KeyboardAndMouse::VK_NUMPAD0 => Some(Keycode::Numpad0),
            KeyboardAndMouse::VK_NUMPAD1 => Some(Keycode::Numpad1),
            KeyboardAndMouse::VK_NUMPAD2 => Some(Keycode::Numpad2),
            KeyboardAndMouse::VK_NUMPAD3 => Some(Keycode::Numpad3),
            KeyboardAndMouse::VK_NUMPAD4 => Some(Keycode::Numpad4),
            KeyboardAndMouse::VK_NUMPAD5 => Some(Keycode::Numpad5),
            KeyboardAndMouse::VK_NUMPAD6 => Some(Keycode::Numpad6),
            KeyboardAndMouse::VK_NUMPAD7 => Some(Keycode::Numpad7),
            KeyboardAndMouse::VK_NUMPAD8 => Some(Keycode::Numpad8),
            KeyboardAndMouse::VK_NUMPAD9 => Some(Keycode::Numpad9),
            KeyboardAndMouse::VK_ADD => Some(Keycode::NumpadAdd),
            KeyboardAndMouse::VK_SUBTRACT => Some(Keycode::NumpadSubtract),
            KeyboardAndMouse::VK_DIVIDE => Some(Keycode::NumpadDivide),
            KeyboardAndMouse::VK_MULTIPLY => Some(Keycode::NumpadMultiply),
            KeyboardAndMouse::VK_OEM_NEC_EQUAL => Some(Keycode::NumpadEquals),
            KeyboardAndMouse::VK_DECIMAL => Some(Keycode::NumpadDecimal),
            KeyboardAndMouse::VK_SPACE => Some(Keycode::Space),
            KeyboardAndMouse::VK_LCONTROL => Some(Keycode::LControl),
            KeyboardAndMouse::VK_RCONTROL => Some(Keycode::RControl),
            KeyboardAndMouse::VK_LSHIFT => Some(Keycode::LShift),
            KeyboardAndMouse::VK_RSHIFT => Some(Keycode::RShift),
            KeyboardAndMouse::VK_LMENU => Some(Keycode::LAlt),
            KeyboardAndMouse::VK_RMENU => Some(Keycode::RAlt),
            KeyboardAndMouse::VK_LWIN => Some(Keycode::LMeta),
            KeyboardAndMouse::VK_RWIN => Some(Keycode::RMeta),
            KeyboardAndMouse::VK_RETURN => Some(Keycode::Enter),
            KeyboardAndMouse::VK_ESCAPE => Some(Keycode::Escape),
            KeyboardAndMouse::VK_UP => Some(Keycode::Up),
            KeyboardAndMouse::VK_DOWN => Some(Keycode::Down),
            KeyboardAndMouse::VK_LEFT => Some(Keycode::Left),
            KeyboardAndMouse::VK_RIGHT => Some(Keycode::Right),
            KeyboardAndMouse::VK_BACK => Some(Keycode::Backspace),
            KeyboardAndMouse::VK_CAPITAL => Some(Keycode::CapsLock),
            KeyboardAndMouse::VK_TAB => Some(Keycode::Tab),
            KeyboardAndMouse::VK_HOME => Some(Keycode::Home),
            KeyboardAndMouse::VK_END => Some(Keycode::End),
            KeyboardAndMouse::VK_PRIOR => Some(Keycode::PageUp),
            KeyboardAndMouse::VK_NEXT => Some(Keycode::PageDown),
            KeyboardAndMouse::VK_INSERT => Some(Keycode::Insert),
            KeyboardAndMouse::VK_DELETE => Some(Keycode::Delete),
            KeyboardAndMouse::VK_OEM_3 => Some(Keycode::Grave),
            KeyboardAndMouse::VK_OEM_MINUS => Some(Keycode::Minus),
            KeyboardAndMouse::VK_OEM_PLUS => Some(Keycode::Equal),
            KeyboardAndMouse::VK_OEM_4 => Some(Keycode::LeftBracket),
            KeyboardAndMouse::VK_OEM_6 => Some(Keycode::RightBracket),
            KeyboardAndMouse::VK_OEM_5 => Some(Keycode::BackSlash),
            KeyboardAndMouse::VK_OEM_1 => Some(Keycode::Semicolon),
            KeyboardAndMouse::VK_OEM_7 => Some(Keycode::Apostrophe),
            KeyboardAndMouse::VK_OEM_COMMA => Some(Keycode::Comma),
            KeyboardAndMouse::VK_OEM_PERIOD => Some(Keycode::Dot),
            KeyboardAndMouse::VK_OEM_2 => Some(Keycode::Slash),

            _ => None,
        };

        if keycode.is_none() {
            let win_key = win_key as u8;
            keycode = match win_key as char {
                '0' => Some(Keycode::Key0),
                '1' => Some(Keycode::Key1),
                '2' => Some(Keycode::Key2),
                '3' => Some(Keycode::Key3),
                '4' => Some(Keycode::Key4),
                '5' => Some(Keycode::Key5),
                '6' => Some(Keycode::Key6),
                '7' => Some(Keycode::Key7),
                '8' => Some(Keycode::Key8),
                '9' => Some(Keycode::Key9),
                'A' => Some(Keycode::A),
                'B' => Some(Keycode::B),
                'C' => Some(Keycode::C),
                'D' => Some(Keycode::D),
                'E' => Some(Keycode::E),
                'F' => Some(Keycode::F),
                'G' => Some(Keycode::G),
                'H' => Some(Keycode::H),
                'I' => Some(Keycode::I),
                'J' => Some(Keycode::J),
                'K' => Some(Keycode::K),
                'L' => Some(Keycode::L),
                'M' => Some(Keycode::M),
                'N' => Some(Keycode::N),
                'O' => Some(Keycode::O),
                'P' => Some(Keycode::P),
                'Q' => Some(Keycode::Q),
                'R' => Some(Keycode::R),
                'S' => Some(Keycode::S),
                'T' => Some(Keycode::T),
                'U' => Some(Keycode::U),
                'V' => Some(Keycode::V),
                'W' => Some(Keycode::W),
                'X' => Some(Keycode::X),
                'Y' => Some(Keycode::Y),
                'Z' => Some(Keycode::Z),
                _ => None,
            }
        }
        keycode
    }
}


================================================
FILE: src/keymap.rs
================================================
//! List of keycodes.

use std::fmt;
use std::str::FromStr;

/// A list of supported keys that we can query from the OS. Outside of mod.
#[derive(Debug, Eq, PartialEq, Hash, Clone, Copy)]
#[allow(missing_docs)]
pub enum Keycode {
    Key0,
    Key1,
    Key2,
    Key3,
    Key4,
    Key5,
    Key6,
    Key7,
    Key8,
    Key9,
    A,
    B,
    C,
    D,
    E,
    F,
    G,
    H,
    I,
    J,
    K,
    L,
    M,
    N,
    O,
    P,
    Q,
    R,
    S,
    T,
    U,
    V,
    W,
    X,
    Y,
    Z,
    F1,
    F2,
    F3,
    F4,
    F5,
    F6,
    F7,
    F8,
    F9,
    F10,
    F11,
    F12,
    F13,
    F14,
    F15,
    F16,
    F17,
    F18,
    F19,
    F20,
    Escape,
    Space,
    LControl,
    RControl,
    LShift,
    RShift,
    LAlt,
    RAlt,
    // TODO rename `Command` into `RCommand` at new major release
    Command,
    RCommand,
    LOption,
    ROption,
    LMeta,
    RMeta,
    Enter,
    Up,
    Down,
    Left,
    Right,
    Backspace,
    CapsLock,
    Tab,
    Home,
    End,
    PageUp,
    PageDown,
    Insert,
    Delete,

    // Numpad keys which have not been implemented: NumpadSeparator NumLock
    Numpad0,
    Numpad1,
    Numpad2,
    Numpad3,
    Numpad4,
    Numpad5,
    Numpad6,
    Numpad7,
    Numpad8,
    Numpad9,
    NumpadSubtract,
    NumpadAdd,
    NumpadDivide,
    NumpadMultiply,
    NumpadEquals,
    NumpadEnter,
    NumpadDecimal,

    // The following keys names represent the position of the key in a US keyboard,
    // not the sign value. In a different keyboards and OS, the position can vary.
    Grave,
    Minus,
    Equal,
    LeftBracket,
    RightBracket,
    BackSlash,
    Semicolon,
    Apostrophe,
    Comma,
    Dot,
    Slash,
}

impl FromStr for Keycode {
    type Err = String;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s {
            "Key0" => Ok(Self::Key0),
            "Key1" => Ok(Self::Key1),
            "Key2" => Ok(Self::Key2),
            "Key3" => Ok(Self::Key3),
            "Key4" => Ok(Self::Key4),
            "Key5" => Ok(Self::Key5),
            "Key6" => Ok(Self::Key6),
            "Key7" => Ok(Self::Key7),
            "Key8" => Ok(Self::Key8),
            "Key9" => Ok(Self::Key9),
            "A" => Ok(Self::A),
            "B" => Ok(Self::B),
            "C" => Ok(Self::C),
            "D" => Ok(Self::D),
            "E" => Ok(Self::E),
            "F" => Ok(Self::F),
            "G" => Ok(Self::G),
            "H" => Ok(Self::H),
            "I" => Ok(Self::I),
            "J" => Ok(Self::J),
            "K" => Ok(Self::K),
            "L" => Ok(Self::L),
            "M" => Ok(Self::M),
            "N" => Ok(Self::N),
            "O" => Ok(Self::O),
            "P" => Ok(Self::P),
            "Q" => Ok(Self::Q),
            "R" => Ok(Self::R),
            "S" => Ok(Self::S),
            "T" => Ok(Self::T),
            "U" => Ok(Self::U),
            "V" => Ok(Self::V),
            "W" => Ok(Self::W),
            "X" => Ok(Self::X),
            "Y" => Ok(Self::Y),
            "Z" => Ok(Self::Z),
            "F1" => Ok(Self::F1),
            "F2" => Ok(Self::F2),
            "F3" => Ok(Self::F3),
            "F4" => Ok(Self::F4),
            "F5" => Ok(Self::F5),
            "F6" => Ok(Self::F6),
            "F7" => Ok(Self::F7),
            "F8" => Ok(Self::F8),
            "F9" => Ok(Self::F9),
            "F10" => Ok(Self::F10),
            "F11" => Ok(Self::F11),
            "F12" => Ok(Self::F12),
            "F13" => Ok(Self::F13),
            "F14" => Ok(Self::F14),
            "F15" => Ok(Self::F15),
            "F16" => Ok(Self::F16),
            "F17" => Ok(Self::F17),
            "F18" => Ok(Self::F18),
            "F19" => Ok(Self::F19),
            "F20" => Ok(Self::F20),
            "Escape" => Ok(Self::Escape),
            "Space" => Ok(Self::Space),
            "LControl" => Ok(Self::LControl),
            "RControl" => Ok(Self::RControl),
            "LShift" => Ok(Self::LShift),
            "RShift" => Ok(Self::RShift),
            "LAlt" => Ok(Self::LAlt),
            "RAlt" => Ok(Self::RAlt),
            // TODO rename `Command` into `RCommand` at new major release
            "Command" => Ok(Self::Command),
            "RCommand" => Ok(Self::RCommand),
            "LOption" => Ok(Self::LOption),
            "ROption" => Ok(Self::ROption),
            "LMeta" => Ok(Self::LMeta),
            "RMeta" => Ok(Self::RMeta),
            "Enter" => Ok(Self::Enter),
            "Up" => Ok(Self::Up),
            "Down" => Ok(Self::Down),
            "Left" => Ok(Self::Left),
            "Right" => Ok(Self::Right),
            "Backspace" => Ok(Self::Backspace),
            "CapsLock" => Ok(Self::CapsLock),
            "Tab" => Ok(Self::Tab),
            "Home" => Ok(Self::Home),
            "End" => Ok(Self::End),
            "PageUp" => Ok(Self::PageUp),
            "PageDown" => Ok(Self::PageDown),
            "Insert" => Ok(Self::Insert),
            "Delete" => Ok(Self::Delete),
            "Numpad0" => Ok(Self::Numpad0),
            "Numpad1" => Ok(Self::Numpad1),
            "Numpad2" => Ok(Self::Numpad2),
            "Numpad3" => Ok(Self::Numpad3),
            "Numpad4" => Ok(Self::Numpad4),
            "Numpad5" => Ok(Self::Numpad5),
            "Numpad6" => Ok(Self::Numpad6),
            "Numpad7" => Ok(Self::Numpad7),
            "Numpad8" => Ok(Self::Numpad8),
            "Numpad9" => Ok(Self::Numpad9),
            "NumpadSubtract" => Ok(Self::NumpadSubtract),
            "NumpadAdd" => Ok(Self::NumpadAdd),
            "NumpadDivide" => Ok(Self::NumpadDivide),
            "NumpadMultiply" => Ok(Self::NumpadMultiply),
            "NumpadEquals" => Ok(Self::NumpadEquals),
            "NumpadEnter" => Ok(Self::NumpadEnter),
            "NumpadDecimal" => Ok(Self::NumpadDecimal),
            "Grave" => Ok(Self::Grave),
            "Minus" => Ok(Self::Minus),
            "Equal" => Ok(Self::Equal),
            "LeftBracket" => Ok(Self::LeftBracket),
            "RightBracket" => Ok(Self::RightBracket),
            "BackSlash" => Ok(Self::BackSlash),
            "Semicolon" => Ok(Self::Semicolon),
            "Apostrophe" => Ok(Self::Apostrophe),
            "Comma" => Ok(Self::Comma),
            "Dot" => Ok(Self::Dot),
            "Slash" => Ok(Self::Slash),
            _ => Err(String::from("failed to parse keycode")),
        }
    }
}

impl fmt::Display for Keycode {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{:?}", self)
    }
}


================================================
FILE: src/lib.rs
================================================
//! A simple library for querying mouse and keyboard state without requiring
//! an active window. Currently works in Windows, Linux, and macOS.
//!
//! ```no_run
//! use device_query::{DeviceQuery, DeviceState, MouseState, Keycode};
//!
//! let device_state = DeviceState::new();
//!
//! let mouse: MouseState = device_state.get_mouse();
//! println!("Current Mouse Coordinates: {:?}", mouse.coords);
//!
//! let keys: Vec<Keycode> = device_state.get_keys();
//! println!("Is A pressed? {}", keys.contains(&Keycode::A));
//! ```
//!
//! It's also possible to listen for events.
//! ```no_run
//!  use device_query::{DeviceEvents, DeviceEventsHandler};
//!  use std::time::Duration;
//!
//!  let device_state = DeviceEventsHandler::new(Duration::from_millis(10))
//!     .expect("Failed to start event loop");
//!
//!  // Register a key down event callback
//!  // The guard is used to keep the callback alive
//!  let _guard = device_state.on_mouse_move(|position| {
//!     println!("Mouse position: {:#?}", position);
//!  });
//!
//!  // Keep the main thread alive
//!  loop {}
//! ```

#[cfg(target_os = "windows")]
extern crate windows;

pub mod device_events;
pub mod device_query;
pub mod device_state;
pub mod keymap;
pub mod mouse_state;

pub use device_events::*;
pub use device_query::*;
pub use device_state::*;
pub use keymap::*;
pub use mouse_state::*;


================================================
FILE: src/mouse_state.rs
================================================
//! Description of mouse coordinates and state of buttons.

/// Mouse position.
pub type MousePosition = (i32, i32);

/// MouseButton.
pub type MouseButton = usize;

#[derive(Debug, PartialEq, Default, Clone)]
/// A simple structure containing the current mouse coordinates and the
/// state of each mouse button that we can query. Currently, Windows and
/// Linux provide nice ways to query five mouse buttons. Since button
/// numbers are 1-based, `button_pressed[0]` is assumed to be false and
/// have no meaning.
pub struct MouseState {
    /// Coordinates in pixel.
    pub coords: MousePosition,
    /// State of each mouse button.
    pub button_pressed: Vec<bool>,
}
Download .txt
gitextract_sn8317i5/

├── .gitignore
├── .travis.yml
├── Cargo.toml
├── LICENSE
├── README.md
├── build.rs
├── examples/
│   ├── event_based_print_keys.rs
│   ├── event_based_print_mouse.rs
│   ├── print_keys.rs
│   └── print_mouse.rs
└── src/
    ├── device_events/
    │   ├── callback/
    │   │   ├── callback_guard.rs
    │   │   ├── keyboard_callback.rs
    │   │   ├── mod.rs
    │   │   └── mouse_callback.rs
    │   ├── event_loop.rs
    │   ├── mod.rs
    │   └── utils.rs
    ├── device_query.rs
    ├── device_state/
    │   ├── linux/
    │   │   ├── kernel_key.rs
    │   │   └── mod.rs
    │   ├── macos/
    │   │   └── mod.rs
    │   ├── mod.rs
    │   └── windows/
    │       └── mod.rs
    ├── keymap.rs
    ├── lib.rs
    └── mouse_state.rs
Download .txt
SYMBOL INDEX (192 symbols across 19 files)

FILE: build.rs
  function main (line 4) | fn main() {}
  function main (line 7) | fn main() {}
  function main (line 19) | fn main() {

FILE: examples/event_based_print_keys.rs
  function main (line 7) | fn main() {

FILE: examples/event_based_print_mouse.rs
  function main (line 7) | fn main() {

FILE: examples/print_keys.rs
  function main (line 5) | fn main() {

FILE: examples/print_mouse.rs
  function main (line 5) | fn main() {

FILE: src/device_events/callback/callback_guard.rs
  type CallbackGuard (line 8) | pub struct CallbackGuard<Callback> {

FILE: src/device_events/callback/keyboard_callback.rs
  type KeyboardCallback (line 7) | pub type KeyboardCallback = dyn Fn(&Keycode) + Sync + Send + 'static;
  type KeyboardCallbacks (line 11) | pub(crate) struct KeyboardCallbacks {
    method push_key_up (line 17) | pub fn push_key_up(&self, callback: Arc<KeyboardCallback>) {
    method push_key_down (line 24) | pub fn push_key_down(&self, callback: Arc<KeyboardCallback>) {
    method run_key_up (line 31) | pub fn run_key_up(&self, key: &Keycode) {
    method run_key_down (line 44) | pub fn run_key_down(&self, key: &Keycode) {

FILE: src/device_events/callback/mouse_callback.rs
  type MouseMoveCallback (line 10) | pub type MouseMoveCallback = dyn Fn(&MousePosition) + Sync + Send + 'sta...
  type MouseButtonCallback (line 13) | pub type MouseButtonCallback = dyn Fn(&MouseButton) + Sync + Send + 'sta...
  type MouseCallbacks (line 17) | pub(crate) struct MouseCallbacks {
    method push_mouse_move (line 24) | pub fn push_mouse_move(&self, callback: Arc<MouseMoveCallback>) {
    method push_mouse_down (line 31) | pub fn push_mouse_down(&self, callback: Arc<MouseButtonCallback>) {
    method push_mouse_up (line 38) | pub fn push_mouse_up(&self, callback: Arc<MouseButtonCallback>) {
    method run_mouse_move (line 45) | pub fn run_mouse_move(&self, position: &MousePosition) {
    method run_mouse_down (line 58) | pub fn run_mouse_down(&self, button: &MouseButton) {
    method run_mouse_up (line 71) | pub fn run_mouse_up(&self, button: &MouseButton) {

FILE: src/device_events/event_loop.rs
  type EventLoop (line 10) | pub(crate) struct EventLoop {
    method new (line 73) | fn new(sleep_dur: Duration) -> Self {
    method on_key_down (line 86) | pub fn on_key_down<Callback: Fn(&Keycode) + Send + Sync + 'static>(
    method on_key_up (line 95) | pub fn on_key_up<Callback: Fn(&Keycode) + Send + Sync + 'static>(
    method on_mouse_move (line 104) | pub fn on_mouse_move<Callback: Fn(&MousePosition) + Send + Sync + 'sta...
    method on_mouse_up (line 113) | pub fn on_mouse_up<Callback: Fn(&MouseButton) + Send + Sync + 'static>(
    method on_mouse_down (line 122) | pub fn on_mouse_down<Callback: Fn(&MouseButton) + Send + Sync + 'static>(
  function keyboard_thread (line 17) | fn keyboard_thread(callbacks: Weak<KeyboardCallbacks>, sleep_dur: Durati...
  function mouse_thread (line 39) | fn mouse_thread(callbacks: Weak<MouseCallbacks>, sleep_dur: Duration) ->...
  method default (line 67) | fn default() -> Self {
  function init_event_loop (line 134) | pub(crate) fn init_event_loop(sleep_dur: Duration) -> bool {

FILE: src/device_events/mod.rs
  type DeviceEvents (line 42) | pub trait DeviceEvents {
    method on_key_down (line 44) | fn on_key_down<Callback: Fn(&Keycode) + Sync + Send + 'static>(
    method on_key_up (line 49) | fn on_key_up<Callback: Fn(&Keycode) + Sync + Send + 'static>(
    method on_mouse_move (line 55) | fn on_mouse_move<Callback: Fn(&MousePosition) + Sync + Send + 'static>(
    method on_mouse_down (line 60) | fn on_mouse_down<Callback: Fn(&MouseButton) + Sync + Send + 'static>(
    method on_mouse_up (line 65) | fn on_mouse_up<Callback: Fn(&MouseButton) + Sync + Send + 'static>(
    method on_key_down (line 96) | fn on_key_down<Callback: Fn(&Keycode) + Sync + Send + 'static>(
    method on_key_up (line 103) | fn on_key_up<Callback: Fn(&Keycode) + Sync + Send + 'static>(
    method on_mouse_move (line 110) | fn on_mouse_move<Callback: Fn(&MousePosition) + Sync + Send + 'static>(
    method on_mouse_down (line 117) | fn on_mouse_down<Callback: Fn(&MouseButton) + Sync + Send + 'static>(
    method on_mouse_up (line 124) | fn on_mouse_up<Callback: Fn(&MouseButton) + Sync + Send + 'static>(
  type DeviceEventsHandler (line 71) | pub struct DeviceEventsHandler;
    method new (line 76) | pub fn new(sleep_dur: Duration) -> Option<Self> {

FILE: src/device_events/utils.rs
  type DrainFilter (line 4) | pub trait DrainFilter<T> {
    method drain_filter (line 5) | fn drain_filter<F>(&mut self, filter: F)
  function drain_filter (line 11) | fn drain_filter<F>(&mut self, filter: F)

FILE: src/device_query.rs
  type DeviceQuery (line 7) | pub trait DeviceQuery {
    method get_mouse (line 9) | fn get_mouse(&self) -> MouseState;
    method get_keys (line 12) | fn get_keys(&self) -> Vec<Keycode>;
    method get_mouse (line 17) | fn get_mouse(&self) -> MouseState {
    method get_keys (line 22) | fn get_keys(&self) -> Vec<Keycode> {

FILE: src/device_state/linux/kernel_key.rs
  constant KEY_ESC (line 5) | pub const KEY_ESC: u16 = 1;
  constant KEY_1 (line 6) | pub const KEY_1: u16 = 2;
  constant KEY_2 (line 7) | pub const KEY_2: u16 = 3;
  constant KEY_3 (line 8) | pub const KEY_3: u16 = 4;
  constant KEY_4 (line 9) | pub const KEY_4: u16 = 5;
  constant KEY_5 (line 10) | pub const KEY_5: u16 = 6;
  constant KEY_6 (line 11) | pub const KEY_6: u16 = 7;
  constant KEY_7 (line 12) | pub const KEY_7: u16 = 8;
  constant KEY_8 (line 13) | pub const KEY_8: u16 = 9;
  constant KEY_9 (line 14) | pub const KEY_9: u16 = 10;
  constant KEY_0 (line 15) | pub const KEY_0: u16 = 11;
  constant KEY_MINUS (line 16) | pub const KEY_MINUS: u16 = 12;
  constant KEY_EQUAL (line 17) | pub const KEY_EQUAL: u16 = 13;
  constant KEY_BACKSPACE (line 18) | pub const KEY_BACKSPACE: u16 = 14;
  constant KEY_TAB (line 19) | pub const KEY_TAB: u16 = 15;
  constant KEY_Q (line 20) | pub const KEY_Q: u16 = 16;
  constant KEY_W (line 21) | pub const KEY_W: u16 = 17;
  constant KEY_E (line 22) | pub const KEY_E: u16 = 18;
  constant KEY_R (line 23) | pub const KEY_R: u16 = 19;
  constant KEY_T (line 24) | pub const KEY_T: u16 = 20;
  constant KEY_Y (line 25) | pub const KEY_Y: u16 = 21;
  constant KEY_U (line 26) | pub const KEY_U: u16 = 22;
  constant KEY_I (line 27) | pub const KEY_I: u16 = 23;
  constant KEY_O (line 28) | pub const KEY_O: u16 = 24;
  constant KEY_P (line 29) | pub const KEY_P: u16 = 25;
  constant KEY_LEFTBRACE (line 30) | pub const KEY_LEFTBRACE: u16 = 26;
  constant KEY_RIGHTBRACE (line 31) | pub const KEY_RIGHTBRACE: u16 = 27;
  constant KEY_ENTER (line 32) | pub const KEY_ENTER: u16 = 28;
  constant KEY_LEFTCTRL (line 33) | pub const KEY_LEFTCTRL: u16 = 29;
  constant KEY_A (line 34) | pub const KEY_A: u16 = 30;
  constant KEY_S (line 35) | pub const KEY_S: u16 = 31;
  constant KEY_D (line 36) | pub const KEY_D: u16 = 32;
  constant KEY_F (line 37) | pub const KEY_F: u16 = 33;
  constant KEY_G (line 38) | pub const KEY_G: u16 = 34;
  constant KEY_H (line 39) | pub const KEY_H: u16 = 35;
  constant KEY_J (line 40) | pub const KEY_J: u16 = 36;
  constant KEY_K (line 41) | pub const KEY_K: u16 = 37;
  constant KEY_L (line 42) | pub const KEY_L: u16 = 38;
  constant KEY_SEMICOLON (line 43) | pub const KEY_SEMICOLON: u16 = 39;
  constant KEY_APOSTROPHE (line 44) | pub const KEY_APOSTROPHE: u16 = 40;
  constant KEY_GRAVE (line 45) | pub const KEY_GRAVE: u16 = 41;
  constant KEY_LEFTSHIFT (line 46) | pub const KEY_LEFTSHIFT: u16 = 42;
  constant KEY_BACKSLASH (line 47) | pub const KEY_BACKSLASH: u16 = 43;
  constant KEY_Z (line 48) | pub const KEY_Z: u16 = 44;
  constant KEY_X (line 49) | pub const KEY_X: u16 = 45;
  constant KEY_C (line 50) | pub const KEY_C: u16 = 46;
  constant KEY_V (line 51) | pub const KEY_V: u16 = 47;
  constant KEY_B (line 52) | pub const KEY_B: u16 = 48;
  constant KEY_N (line 53) | pub const KEY_N: u16 = 49;
  constant KEY_M (line 54) | pub const KEY_M: u16 = 50;
  constant KEY_COMMA (line 55) | pub const KEY_COMMA: u16 = 51;
  constant KEY_DOT (line 56) | pub const KEY_DOT: u16 = 52;
  constant KEY_SLASH (line 57) | pub const KEY_SLASH: u16 = 53;
  constant KEY_RIGHTSHIFT (line 58) | pub const KEY_RIGHTSHIFT: u16 = 54;
  constant KEY_KPASTERISK (line 59) | pub const KEY_KPASTERISK: u16 = 55;
  constant KEY_LEFTALT (line 60) | pub const KEY_LEFTALT: u16 = 56;
  constant KEY_SPACE (line 61) | pub const KEY_SPACE: u16 = 57;
  constant KEY_CAPSLOCK (line 62) | pub const KEY_CAPSLOCK: u16 = 58;
  constant KEY_F1 (line 63) | pub const KEY_F1: u16 = 59;
  constant KEY_F2 (line 64) | pub const KEY_F2: u16 = 60;
  constant KEY_F3 (line 65) | pub const KEY_F3: u16 = 61;
  constant KEY_F4 (line 66) | pub const KEY_F4: u16 = 62;
  constant KEY_F5 (line 67) | pub const KEY_F5: u16 = 63;
  constant KEY_F6 (line 68) | pub const KEY_F6: u16 = 64;
  constant KEY_F7 (line 69) | pub const KEY_F7: u16 = 65;
  constant KEY_F8 (line 70) | pub const KEY_F8: u16 = 66;
  constant KEY_F9 (line 71) | pub const KEY_F9: u16 = 67;
  constant KEY_F10 (line 72) | pub const KEY_F10: u16 = 68;
  constant KEY_KP7 (line 73) | pub const KEY_KP7: u16 = 71;
  constant KEY_KP8 (line 74) | pub const KEY_KP8: u16 = 72;
  constant KEY_KP9 (line 75) | pub const KEY_KP9: u16 = 73;
  constant KEY_KPMINUS (line 76) | pub const KEY_KPMINUS: u16 = 74;
  constant KEY_KP4 (line 77) | pub const KEY_KP4: u16 = 75;
  constant KEY_KP5 (line 78) | pub const KEY_KP5: u16 = 76;
  constant KEY_KP6 (line 79) | pub const KEY_KP6: u16 = 77;
  constant KEY_KPPLUS (line 80) | pub const KEY_KPPLUS: u16 = 78;
  constant KEY_KP1 (line 81) | pub const KEY_KP1: u16 = 79;
  constant KEY_KP2 (line 82) | pub const KEY_KP2: u16 = 80;
  constant KEY_KP3 (line 83) | pub const KEY_KP3: u16 = 81;
  constant KEY_KP0 (line 84) | pub const KEY_KP0: u16 = 82;
  constant KEY_KPDOT (line 85) | pub const KEY_KPDOT: u16 = 83;
  constant KEY_F11 (line 86) | pub const KEY_F11: u16 = 87;
  constant KEY_F12 (line 87) | pub const KEY_F12: u16 = 88;
  constant KEY_F13 (line 88) | pub const KEY_F13: u16 = 183;
  constant KEY_F14 (line 89) | pub const KEY_F14: u16 = 184;
  constant KEY_F15 (line 90) | pub const KEY_F15: u16 = 185;
  constant KEY_F16 (line 91) | pub const KEY_F16: u16 = 186;
  constant KEY_F17 (line 92) | pub const KEY_F17: u16 = 187;
  constant KEY_F18 (line 93) | pub const KEY_F18: u16 = 188;
  constant KEY_F19 (line 94) | pub const KEY_F19: u16 = 189;
  constant KEY_F20 (line 95) | pub const KEY_F20: u16 = 190;
  constant KEY_KPENTER (line 96) | pub const KEY_KPENTER: u16 = 96;
  constant KEY_RIGHTCTRL (line 97) | pub const KEY_RIGHTCTRL: u16 = 97;
  constant KEY_KPSLASH (line 98) | pub const KEY_KPSLASH: u16 = 98;
  constant KEY_RIGHTALT (line 99) | pub const KEY_RIGHTALT: u16 = 100;
  constant KEY_HOME (line 100) | pub const KEY_HOME: u16 = 102;
  constant KEY_UP (line 101) | pub const KEY_UP: u16 = 103;
  constant KEY_PAGEUP (line 102) | pub const KEY_PAGEUP: u16 = 104;
  constant KEY_LEFT (line 103) | pub const KEY_LEFT: u16 = 105;
  constant KEY_RIGHT (line 104) | pub const KEY_RIGHT: u16 = 106;
  constant KEY_END (line 105) | pub const KEY_END: u16 = 107;
  constant KEY_DOWN (line 106) | pub const KEY_DOWN: u16 = 108;
  constant KEY_PAGEDOWN (line 107) | pub const KEY_PAGEDOWN: u16 = 109;
  constant KEY_INSERT (line 108) | pub const KEY_INSERT: u16 = 110;
  constant KEY_DELETE (line 109) | pub const KEY_DELETE: u16 = 111;
  constant KEY_KPEQUAL (line 110) | pub const KEY_KPEQUAL: u16 = 117;
  constant KEY_LEFTMETA (line 111) | pub const KEY_LEFTMETA: u16 = 125;
  constant KEY_RIGHTMETA (line 112) | pub const KEY_RIGHTMETA: u16 = 126;

FILE: src/device_state/linux/mod.rs
  type DeviceState (line 15) | pub struct DeviceState {
    method new (line 34) | pub fn new() -> DeviceState {
    method checked_new (line 47) | pub fn checked_new() -> Option<DeviceState> {
    method query_pointer (line 61) | pub fn query_pointer(&self) -> MouseState {
    method query_keymap (line 107) | pub fn query_keymap(&self) -> Vec<Keycode> {
    method kernel_key_to_keycode (line 129) | fn kernel_key_to_keycode(&self, kernel_code: u8) -> Option<Keycode> {
  type X11Connection (line 20) | struct X11Connection {
  method drop (line 25) | fn drop(&mut self) {

FILE: src/device_state/macos/mod.rs
  type DeviceState (line 7) | pub struct DeviceState;
    method new (line 120) | pub fn new() -> DeviceState {
    method checked_new (line 131) | pub fn checked_new() -> Option<DeviceState> {
    method query_pointer (line 139) | pub fn query_pointer(&self) -> MouseState {
    method query_keymap (line 155) | pub fn query_keymap(&self) -> Vec<Keycode> {
  constant MAPPING (line 8) | const MAPPING: &[(readkey::Keycode, Keycode)] = &[
  function has_accessibility (line 173) | fn has_accessibility() -> bool {

FILE: src/device_state/mod.rs
  method default (line 36) | fn default() -> Self {

FILE: src/device_state/windows/mod.rs
  type DeviceState (line 9) | pub struct DeviceState;
    method new (line 12) | pub fn new() -> Self {
    method checked_new (line 17) | pub fn checked_new() -> Option<Self> {
    method query_pointer (line 21) | pub fn query_pointer(&self) -> MouseState {
    method query_keymap (line 59) | pub fn query_keymap(&self) -> Vec<Keycode> {
    method win_key_to_keycode (line 77) | fn win_key_to_keycode(&self, win_key: u16) -> Option<Keycode> {

FILE: src/keymap.rs
  type Keycode (line 9) | pub enum Keycode {
    method fmt (line 253) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  type Err (line 131) | type Err = String;
  method from_str (line 132) | fn from_str(s: &str) -> Result<Self, Self::Err> {

FILE: src/mouse_state.rs
  type MousePosition (line 4) | pub type MousePosition = (i32, i32);
  type MouseButton (line 7) | pub type MouseButton = usize;
  type MouseState (line 15) | pub struct MouseState {
Condensed preview — 26 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (65K chars).
[
  {
    "path": ".gitignore",
    "chars": 80,
    "preview": "# IDEs auto-generated files\n.idea\n\n# Cargo files\n/target/\n**/*.rs.bk\nCargo.lock\n"
  },
  {
    "path": ".travis.yml",
    "chars": 205,
    "preview": "language: rust\ncache: cargo\nmatrix:\n  include:\n    - os: linux\n      rust: stable\n      env: TARGET=x86_64_unknown_linux"
  },
  {
    "path": "Cargo.toml",
    "chars": 952,
    "preview": "[package]\nname = \"device_query\"\nversion = \"4.0.1\"\nauthors = [\"ostrosco <ostrosco@fastmail.fm>\"]\nbuild = \"build.rs\"\ndescr"
  },
  {
    "path": "LICENSE",
    "chars": 1065,
    "preview": "MIT License\n\nCopyright (c) 2018 ostrosco\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\no"
  },
  {
    "path": "README.md",
    "chars": 2463,
    "preview": "# device_query\n\n# NOTE: This repository has been relocated to https://codeberg.org/ostrosco/device_query. Future work wi"
  },
  {
    "path": "build.rs",
    "chars": 1198,
    "preview": "extern crate pkg_config;\n\n#[cfg(target_os = \"windows\")]\nfn main() {}\n\n#[cfg(target_os = \"macos\")]\nfn main() {}\n\n#[cfg(ta"
  },
  {
    "path": "examples/event_based_print_keys.rs",
    "chars": 526,
    "preview": "extern crate device_query;\n\nuse device_query::{DeviceEvents, DeviceEventsHandler};\nuse std::thread;\nuse std::time::Durat"
  },
  {
    "path": "examples/event_based_print_mouse.rs",
    "chars": 666,
    "preview": "extern crate device_query;\n\nuse device_query::{DeviceEvents, DeviceEventsHandler};\nuse std::thread;\nuse std::time::Durat"
  },
  {
    "path": "examples/print_keys.rs",
    "chars": 328,
    "preview": "extern crate device_query;\n\nuse device_query::{DeviceQuery, DeviceState};\n\nfn main() {\n    let device_state = DeviceStat"
  },
  {
    "path": "examples/print_mouse.rs",
    "chars": 363,
    "preview": "extern crate device_query;\n\nuse device_query::{DeviceQuery, DeviceState, MouseState};\n\nfn main() {\n    let device_state "
  },
  {
    "path": "src/device_events/callback/callback_guard.rs",
    "chars": 272,
    "preview": "//! Callback guard.\n\nuse std::sync::Arc;\n\n/// Callback guard returned when adding a callback as an event listener. If th"
  },
  {
    "path": "src/device_events/callback/keyboard_callback.rs",
    "chars": 1742,
    "preview": "use crate::device_events::utils;\nuse std::ops::DerefMut;\nuse std::sync::{Arc, Mutex, Weak};\nuse Keycode;\n\n/// Keyboard c"
  },
  {
    "path": "src/device_events/callback/mod.rs",
    "chars": 166,
    "preview": "mod callback_guard;\nmod keyboard_callback;\nmod mouse_callback;\n\npub use self::callback_guard::*;\npub use self::keyboard_"
  },
  {
    "path": "src/device_events/callback/mouse_callback.rs",
    "chars": 2710,
    "preview": "//! Mouse callback.\n\nuse crate::device_events::utils;\nuse std::ops::DerefMut;\nuse std::sync::{Arc, Mutex, Weak};\nuse Mou"
  },
  {
    "path": "src/device_events/event_loop.rs",
    "chars": 4819,
    "preview": "use super::{CallbackGuard, KeyboardCallbacks};\nuse std::sync::{Arc, LazyLock, Mutex, Weak};\nuse std::thread::{sleep, spa"
  },
  {
    "path": "src/device_events/mod.rs",
    "chars": 3816,
    "preview": "//! Devices events listeners.\n//! \n//! This module contains the implementation of the DeviceEventsHandler struct.\n//! Th"
  },
  {
    "path": "src/device_events/utils.rs",
    "chars": 583,
    "preview": "//! Utils.\n\n/// This is a placeholder for the unstable feature.\npub trait DrainFilter<T> {\n    fn drain_filter<F>(&mut s"
  },
  {
    "path": "src/device_query.rs",
    "chars": 603,
    "preview": "//! Query functions.\n\nuse DeviceState;\nuse {Keycode, MouseState};\n\n/// Trait to get the state of the supported devices.\n"
  },
  {
    "path": "src/device_state/linux/kernel_key.rs",
    "chars": 3505,
    "preview": "/// A non-exhaustive list of keycodes from Linux. Only the ones that this library currently supports\n/// is currently li"
  },
  {
    "path": "src/device_state/linux/mod.rs",
    "chars": 10051,
    "preview": "extern crate x11;\n\nuse self::x11::xlib;\nuse keymap::Keycode;\nuse mouse_state::MouseState;\nuse std::os::raw::c_char;\nuse "
  },
  {
    "path": "src/device_state/macos/mod.rs",
    "chars": 6952,
    "preview": "extern crate macos_accessibility_client;\n\nuse keymap::Keycode;\nuse mouse_state::MouseState;\n\n#[derive(Debug, Clone)]\npub"
  },
  {
    "path": "src/device_state/mod.rs",
    "chars": 971,
    "preview": "//! DeviceState implementation.\n//! \n//! This module contains the implementation of the DeviceState struct.\n//! This onl"
  },
  {
    "path": "src/device_state/windows/mod.rs",
    "chars": 8849,
    "preview": "use keymap::Keycode;\nuse mouse_state::MouseState;\nuse windows::Win32::Foundation::POINT;\nuse windows::Win32::UI::Input::"
  },
  {
    "path": "src/keymap.rs",
    "chars": 6519,
    "preview": "//! List of keycodes.\n\nuse std::fmt;\nuse std::str::FromStr;\n\n/// A list of supported keys that we can query from the OS."
  },
  {
    "path": "src/lib.rs",
    "chars": 1368,
    "preview": "//! A simple library for querying mouse and keyboard state without requiring\n//! an active window. Currently works in Wi"
  },
  {
    "path": "src/mouse_state.rs",
    "chars": 676,
    "preview": "//! Description of mouse coordinates and state of buttons.\n\n/// Mouse position.\npub type MousePosition = (i32, i32);\n\n//"
  }
]

About this extraction

This page contains the full source code of the ostrosco/device_query GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 26 files (60.0 KB), approximately 17.0k tokens, and a symbol index with 192 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!