### Run display information example Source: https://github.com/huakunshen/monio/blob/main/README.md Execute the 'display' example to retrieve and display information about connected displays. ```bash cargo run --example display ``` -------------------------------- ### Run event simulation example Source: https://github.com/huakunshen/monio/blob/main/README.md Execute the 'simulate' example to demonstrate how to simulate input events. ```bash cargo run --example simulate ``` -------------------------------- ### Run channel-based sync example Source: https://github.com/huakunshen/monio/blob/main/README.md Run the 'channel_sync' example to demonstrate synchronous channel-based event handling. ```bash cargo run --example channel_sync ``` -------------------------------- ### Run event grabbing example Source: https://github.com/huakunshen/monio/blob/main/README.md Run the 'grab' example to demonstrate how to grab and block specific key events. ```bash cargo run --example grab ``` -------------------------------- ### Run basic event logging example Source: https://github.com/huakunshen/monio/blob/main/README.md Execute the 'basic' example to demonstrate fundamental event logging capabilities. ```bash cargo run --example basic ``` -------------------------------- ### Run input statistics example Source: https://github.com/huakunshen/monio/blob/main/README.md Execute the 'statistics' example to gather and display input statistics. Requires the 'statistics' feature. ```bash cargo run --example statistics --features statistics ``` -------------------------------- ### Run drag detection demo Source: https://github.com/huakunshen/monio/blob/main/README.md Run the 'drag_detection' example to showcase the library's ability to detect drag gestures. ```bash cargo run --example drag_detection ``` -------------------------------- ### Run channel-based async example with Tokio Source: https://github.com/huakunshen/monio/blob/main/README.md Execute the 'channel_async' example, which uses Tokio for asynchronous channel-based event handling. Requires the 'tokio' feature. ```bash cargo run --example channel_async --features tokio ``` -------------------------------- ### Run Specific Cargo Example Source: https://github.com/huakunshen/monio/blob/main/AGENTS.md Command to run a specific example binary. Note that macOS requires Accessibility permissions for this to function correctly. ```bash cargo run --example basic ``` ```bash cargo run --example drag_detection ``` ```bash cargo run --example simulate ``` -------------------------------- ### Record and playback macros Source: https://github.com/huakunshen/monio/blob/main/README.md Use the 'recorder' example to record input macros to a JSON file and play them back. Requires the 'recorder' feature. ```bash cargo run --example recorder --features recorder -- record macro.json ``` ```bash cargo run --example recorder --features recorder -- playback macro.json ``` -------------------------------- ### Listen for Keyboard and Mouse Events Source: https://github.com/huakunshen/monio/blob/main/README.md Use the `listen` function to register a callback that processes incoming keyboard and mouse events. This example shows how to print key presses and mouse drag/move coordinates. ```rust use monio::{listen, Event, EventType}; fn main() { listen(|event: &Event| { match event.event_type { EventType::KeyPressed => { if let Some(kb) = &event.keyboard { println!("Key pressed: {:?}", kb.key); } } EventType::MouseDragged => { if let Some(mouse) = &event.mouse { println!("Dragging at ({}, {})", mouse.x, mouse.y); } } EventType::MouseMoved => { if let Some(mouse) = &event.mouse { println!("Moved to ({}, {})", mouse.x, mouse.y); } } _ => {} } }).expect("Failed to start hook"); } ``` -------------------------------- ### Listen for Events with Async Channels (Tokio) Source: https://github.com/huakunshen/monio/blob/main/README.md Integrate Monio event listening with Tokio's asynchronous runtime. This example uses `listen_async_channel` and processes events asynchronously using `rx.recv().await`. ```Rust use monio::channel::listen_async_channel; #[tokio::main] async fn main() { let (handle, mut rx) = listen_async_channel(100).unwrap(); while let Some(event) = rx.recv().await { println!("{:?}", event.event_type); } } ``` -------------------------------- ### Cargo Build and Test Commands Source: https://github.com/huakunshen/monio/blob/main/AGENTS.md Standard Cargo commands for checking compilation, running tests, and building the release version of the project. Includes commands to check all examples. ```bash cargo check ``` ```bash cargo check --examples ``` ```bash cargo test ``` ```bash cargo build --release ``` -------------------------------- ### Listen for Events with Channels (Rust) Source: https://github.com/huakunshen/monio/blob/main/README.md Use channels for background event processing. The `listen_channel` function starts a hook and returns a handle and a receiver. Events are processed in a loop, with a timeout to allow for other work. ```Rust use monio::channel::listen_channel; use monio::EventType; use std::time::Duration; fn main() { // Start hook with bounded channel (capacity 100) let (handle, rx) = listen_channel(100).expect("Failed to start hook"); // Process events without blocking loop { match rx.recv_timeout(Duration::from_millis(100)) { Ok(event) => { if event.event_type == EventType::KeyPressed { println!("Key pressed!"); } } Err(_) => { // Timeout - do other work } } } } ``` -------------------------------- ### Collect and Analyze Input Statistics (Rust) Source: https://github.com/huakunshen/monio/blob/main/README.md Gather statistics on user input over a period, such as typing speed and mouse movement. Requires the `statistics` feature. Provides methods to get summaries and check for break recommendations. ```Rust use monio::statistics::StatisticsCollector; use std::time::Duration; fn main() -> monio::Result<()> { println!("Collecting statistics for 60 seconds..."); let stats = StatisticsCollector::collect_for(Duration::from_secs(60))?; println!("{}", stats.summary()); println!("Typing speed: {:.1} keys/min", stats.keys_per_minute()); println!("Mouse distance: {:.0} pixels", stats.total_mouse_distance); if let Some((key, count)) = stats.most_frequent_key() { println!("Most pressed key: {:?} ({} times)", key, count); } if stats.needs_break(Duration::from_secs(30)) { println!("You've been typing for 30+ seconds. Consider taking a break!"); } Ok(()) } ``` -------------------------------- ### Blocking Global Input Listener with Callback Source: https://context7.com/huakunshen/monio/llms.txt Use the `listen` function to start a blocking global input hook. This function takes a callback that is invoked for every keyboard and mouse event. Events are passed through to other applications. The function blocks the calling thread until an error or an external stop signal. ```rust use monio::{listen, Event, EventType, Key, Button}; fn main() { listen(|event: &Event| { match event.event_type { EventType::KeyPressed => { if let Some(kb) = &event.keyboard { if kb.key.is_modifier() { println!("[modifier] {:?} held, mask=0x{:08x}", kb.key, event.mask); } else { println!("[key] {:?} (raw={})", kb.key, kb.raw_code); } } } EventType::KeyTyped => { if let Some(kb) = &event.keyboard { if let Some(ch) = kb.char { print!("{}", ch); // echo typed characters } } } EventType::MouseDragged => { if let Some(m) = &event.mouse { println!("[drag] ({:.0}, {:.0})", m.x, m.y); } } EventType::MouseMoved => { // Only fires when NO button is held if let Some(m) = &event.mouse { println!("[move] ({:.0}, {:.0})", m.x, m.y); } } EventType::MouseWheel => { if let Some(w) = &event.wheel { println!("[scroll] {:?} delta={}", w.direction, w.delta); } } EventType::MouseClicked => { if let Some(m) = &event.mouse { println!("[click] {:?} x{} at ({:.0},{:.0})", m.button, m.clicks, m.x, m.y); } } EventType::HookEnabled => println!("[hook] started"), EventType::HookDisabled => println!("[hook] stopped"), _ => {} } }).expect("Failed to start hook"); // Expected output when user presses 'H', 'i' and moves mouse: // [hook] started // [key] KeyH (raw=35) // Hi // [move] (412, 300) // [drag] (413, 301) ← when left button held } ``` -------------------------------- ### Blocking Event Interception with `grab` Source: https://context7.com/huakunshen/monio/llms.txt Use `grab` to start a blocking global hook that intercepts events before they reach other applications. Return `None` to consume the event or `Some(event)` to pass it through. This is fully supported on macOS and Windows, with listen-only fallback on Linux/X11. ```rust use monio::{grab, Event, EventType, Key}; fn main() { grab(|event: &Event| { match event.event_type { EventType::KeyPressed => { if let Some(kb) = &event.keyboard { match kb.key { // Block F1 completely Key::F1 => { println!("F1 blocked!"); return None; } // Remap: swallow CapsLock press (could inject Escape instead) Key::CapsLock => { println!("CapsLock suppressed"); return None; } _ => {} } } } EventType::MousePressed => { if let Some(m) = &event.mouse { // Block right-clicks in top-left corner if matches!(m.button, Some(monio::Button::Right)) && m.x < 100.0 && m.y < 100.0 { println!("Right-click in corner blocked"); return None; } } } _ => {} } Some(event.clone()) // pass through everything else }).expect("Failed to start grab"); // Expected: pressing F1 prints "F1 blocked!" and the key never reaches other apps } ``` -------------------------------- ### Grab and Consume Keyboard Events Source: https://github.com/huakunshen/monio/blob/main/README.md Utilize the `grab` function to intercept events and optionally prevent them from being processed by other applications. Returning `None` consumes the event; returning `Some(event)` passes it through. This example demonstrates blocking the F1 key. ```rust use monio::{grab, Event, EventType, Key}; fn main() { grab(|event: &Event| { // Block the F1 key if event.event_type == EventType::KeyPressed { if let Some(kb) = &event.keyboard { if kb.key == Key::F1 { println!("Blocked F1!"); return None; // Consume - don't pass to other apps } } } Some(event.clone()) // Pass through }).expect("Failed to start grab"); } ``` -------------------------------- ### Non-blocking Event Hook with `Hook` struct Source: https://context7.com/huakunshen/monio/llms.txt Utilize the `Hook` struct for non-blocking event interception with fine-grained lifecycle control. Start the hook in a background thread using `run_async`, monitor its status with `is_running`, and stop it with `stop`. The hook automatically stops when dropped. ```rust use monio::{Hook, Event, EventType}; use std::sync::{Arc, Mutex}; use std::time::Duration; fn main() -> monio::Result<()> { let hook = Hook::new(); let key_log: Arc>> = Arc::new(Mutex::new(Vec::new())); let log_clone = key_log.clone(); // Start in background thread — returns immediately hook.run_async(move |event: &Event| { if event.event_type == EventType::KeyPressed { if let Some(kb) = &event.keyboard { if let Ok(mut log) = log_clone.lock() { log.push(format!("{:?}", kb.key)); } } } })?; println!("Hook running: {}", hook.is_running()); // true // Do other work while hook runs in background std::thread::sleep(Duration::from_secs(5)); // Stop and inspect results hook.stop()?; println!("Hook running: {}", hook.is_running()); // false let log = key_log.lock().unwrap(); println!("Captured {} key events: {:?}", log.len(), &log[..log.len().min(5)]); // Expected output: // Hook running: true // Hook running: false // Captured 7 key events: ["KeyH", "KeyE", "KeyL", "KeyL", "KeyO"] Ok(()) } ``` -------------------------------- ### Monio Module Structure Source: https://github.com/huakunshen/monio/blob/main/AGENTS.md Overview of the monio library's directory and file structure, highlighting key modules for event handling, state management, and platform-specific implementations. ```text src/ ├── lib.rs # Public API re-exports ├── event.rs # Event, EventType, Button, ScrollDirection types ├── error.rs # Error enum with thiserror ├── state.rs # Global atomic button/modifier mask (THE KEY FIX) ├── keycode.rs # Key enum for all keyboard keys ├── hook.rs # Hook struct, EventHandler trait, listen() function └── platform/ ├── mod.rs # Conditional compilation for OS-specific modules ├── macos/ # CGEventTap (objc2 bindings) ├── windows/ # SetWindowsHookEx (windows crate) └── linux/ ├── x11/ # XRecord + XTest └── wayland/ # Stub (libei not yet implemented) ``` -------------------------------- ### Simulate User Input Events (Rust) Source: https://github.com/huakunshen/monio/blob/main/README.md Simulate keyboard and mouse actions using Monio's input simulation functions. Requires `key_tap`, `mouse_move`, and `mouse_click`. ```Rust use monio::{key_tap, mouse_move, mouse_click, Key, Button}; fn main() -> monio::Result<()> { // Move mouse to position mouse_move(100.0, 200.0)?; // Click mouse_click(Button::Left)?; // Type a key key_tap(Key::KeyA)?; Ok(()) } ``` -------------------------------- ### Query Display and System Properties (Rust) Source: https://github.com/huakunshen/monio/blob/main/README.md Retrieve information about connected displays and system settings. Functions like `displays`, `primary_display`, and `system_settings` are available. ```Rust use monio::{displays, primary_display, system_settings}; fn main() -> monio::Result<()> { // Get all displays let all_displays = displays()?; for display in all_displays { println!("Display {}: {}x{} @ {:?}Hz", display.id, display.bounds.width, display.bounds.height, display.refresh_rate ); } // Get primary display let primary = primary_display()?; println!("Primary scale factor: {}", primary.scale_factor); // Get system settings let settings = system_settings()?; println!("Double-click time: {:?}ms", settings.double_click_time); Ok(()) } ``` -------------------------------- ### Build with evdev backend Source: https://github.com/huakunshen/monio/blob/main/README.md Build the project with the evdev backend enabled, which is necessary for Wayland support. This command disables default features. ```bash cargo build --features evdev --no-default-features ``` -------------------------------- ### Add monio to Cargo.toml Source: https://github.com/huakunshen/monio/blob/main/README.md Include monio as a dependency in your project's Cargo.toml file. ```toml [dependencies] monio = "0.1" ``` -------------------------------- ### Classify Virtual Key Codes with Monio Key Enum Source: https://context7.com/huakunshen/monio/llms.txt Demonstrates how to use the `Key` enum and its helper predicates to classify different types of virtual key codes. This is useful for handling user input and detecting specific key categories. ```rust use monio::Key; fn classify_key(key: Key) { if key.is_modifier() { println!("{:?} is a modifier", key); } else if key.is_letter() { println!("{:?} is a letter", key); } else if key.is_number() { println!("{:?} is a digit", key); } else if key.is_function_key() { println!("{:?} is a function key", key); } else if key.is_numpad() { println!("{:?} is a numpad key", key); } else if key.is_navigation() { println!("{:?} is a navigation key", key); } else if key.is_media() { println!("{:?} is a media key", key); } else { println!("{:?} is a special/unknown key", key); } } fn main() { use monio::{listen, Event, EventType}; classify_key(Key::ShiftLeft); // modifier classify_key(Key::KeyA); // letter classify_key(Key::Num5); // digit classify_key(Key::F12); // function key classify_key(Key::Numpad0); // numpad classify_key(Key::ArrowUp); // navigation classify_key(Key::MediaPlayPause); // media classify_key(Key::Unknown(999)); // special/unknown // Use in a hook to filter by category listen(|event: &Event| { if event.event_type == EventType::KeyPressed { if let Some(kb) = &event.keyboard { // Only react to letter and digit keys if kb.key.is_letter() || kb.key.is_number() { println!("Printable key: {:?}", kb.key); } // Detect hotkey combos from event mask let ctrl = (event.mask & monio::state::MASK_CTRL) != 0; if ctrl && kb.key == Key::KeyC { println!("Ctrl+C detected"); } } } }).expect("Failed to start hook"); } ``` -------------------------------- ### Linux Feature Flags for Build Source: https://github.com/huakunshen/monio/blob/main/AGENTS.md Build commands for Linux specifying X11 or Wayland support. Use --no-default-features when explicitly selecting Wayland. ```bash # Build with X11 support (default) cargo build --features x11 ``` ```bash # Build with Wayland support (stub implementation) cargo build --features wayland --no-default-features ``` -------------------------------- ### Async Channel Listening with Tokio Source: https://context7.com/huakunshen/monio/llms.txt Demonstrates `listen_async_channel` which bridges OS events to a Tokio `mpsc` channel for asynchronous consumption. Requires the `tokio` feature enabled in `Cargo.toml`. ```rust // Cargo.toml: monio = { version = "0.1", features = ["tokio"] } use monio::channel::{listen_async_channel, grab_async_channel}; use monio::{EventType, Key}; #[tokio::main] async fn main() -> monio::Result<()> { // --- Async listen example --- let (handle, mut rx) = listen_async_channel(256)?; tokio::spawn(async move { while let Some(event) = rx.recv().await { if event.event_type == EventType::KeyPressed { if let Some(kb) = &event.keyboard { println!("[async] Key: {:?}", kb.key); if kb.key == Key::Escape { break; } } } } }); // --- Async grab example (blocks F-keys) --- let (grab_handle, mut grab_rx) = grab_async_channel(256, |event| { if event.event_type == EventType::KeyPressed { if let Some(kb) = &event.keyboard { if kb.key.is_function_key() { return false; // consume all F1-F24 } } } true // pass through })?; tokio::time::sleep(tokio::time::Duration::from_secs(5)).await; // Drain remaining events while let Ok(event) = grab_rx.try_recv() { println!("[grab] received: {:?}", event.event_type); } handle.stop()?; grab_handle.stop()?; // Expected: function keys are blocked system-wide; all events logged async Ok(()) } ``` -------------------------------- ### Simulate Keyboard and Mouse Events Source: https://context7.com/huakunshen/monio/llms.txt Programmatically inject keyboard and mouse events using high-level helpers like `key_tap`, `mouse_move`, `mouse_click`, or the versatile `simulate` function for full `Event` control. ```rust use monio::{ key_tap, key_press, key_release, mouse_move, mouse_click, mouse_press, mouse_release, mouse_position, simulate, Key, Button, Event, }; use std::time::Duration; fn main() -> monio::Result<()> { // Query current position let (x, y) = mouse_position()?; println!("Current mouse position: ({}, {})", x, y); // Move mouse mouse_move(500.0, 300.0)?; // Single key tap (press + release) key_tap(Key::KeyA)?; // Type "Hi" with shift key_press(Key::ShiftLeft)?; key_tap(Key::KeyH)?; key_release(Key::ShiftLeft)?; key_tap(Key::KeyI)?; // Click left button at current position mouse_click(Button::Left)?; // Simulate a drag: press, move, release mouse_press(Button::Left)?; std::thread::sleep(Duration::from_millis(50)); for i in 0..10 { mouse_move(500.0 + i as f64 * 10.0, 300.0)?; std::thread::sleep(Duration::from_millis(16)); } mouse_release(Button::Left)?; // Simulate a full event directly let drag_event = Event::mouse_dragged(600.0, 300.0); simulate(&drag_event)?; println!("Simulation complete"); // Expected: mouse moves to (500,300), "Hi" is typed, a drag is performed Ok(()) } ``` -------------------------------- ### Record and Replay User Input Macros (Rust) Source: https://github.com/huakunshen/monio/blob/main/README.md Record user input events for a specified duration and save them to a file. The recorded macro can then be replayed with original or modified timing. Requires the `recorder` feature. ```Rust use monio::recorder::{EventRecorder, Recording}; use std::time::Duration; fn main() -> monio::Result<()> { // Record for 5 seconds println!("Recording for 5 seconds..."); let recording = EventRecorder::record_for(Duration::from_secs(5))?; recording.save("macro.json")?; // Playback with original timing println!("Replaying..."); let recording = Recording::load("macro.json")?; recording.playback()?; // Or playback at 2x speed recording.playback_with_speed(2.0)?; Ok(()) } ``` -------------------------------- ### Sync Channel Listening with Bounded Channel Source: https://context7.com/huakunshen/monio/llms.txt Uses `listen_channel` to create a bounded synchronous channel. Events are dropped if the consumer is too slow. Suitable for scenarios where occasional event loss is acceptable. ```rust use monio::channel::{listen_channel, listen_unbounded_channel}; use monio::EventType; use std::time::Duration; fn main() -> monio::Result<()> { // Bounded: drops events if consumer is slow (capacity=100) let (handle, rx) = listen_channel(100)?; let mut key_count = 0u32; let deadline = std::time::Instant::now() + Duration::from_secs(10); loop { if std::time::Instant::now() >= deadline { break; } match rx.recv_timeout(Duration::from_millis(100)) { Ok(event) => { match event.event_type { EventType::KeyPressed => { key_count += 1; if let Some(kb) = &event.keyboard { println!("Key #{}: {:?}", key_count, kb.key); } } EventType::MouseDragged => { if let Some(m) = &event.mouse { println!("Dragging at ({:.0}, {:.0})", m.x, m.y); } } _ => {} } } Err(std::sync::mpsc::RecvTimeoutError::Timeout) => { // No events — do other work here } Err(std::sync::mpsc::RecvTimeoutError::Disconnected) => break, } } handle.stop()?; println!("Total key presses: {}", key_count); // Expected: prints each key pressed during 10 seconds, then total count Ok(()) } ``` -------------------------------- ### Add monio-rs to Cargo.toml Source: https://context7.com/huakunshen/monio/llms.txt Specify the monio crate version and enable features like tokio, recorder, or statistics as needed. For Linux, the 'evdev' backend can be used with 'default-features = false'. ```toml [dependencies] # Default (X11 on Linux) monio = "0.1" # With Tokio async channel support monio = { version = "0.1", features = ["tokio"] } # With macro recording/playback monio = { version = "0.1", features = ["recorder"] } # With input statistics collection monio = { version = "0.1", features = ["statistics"] } # All features monio = { version = "0.1", features = ["tokio", "recorder", "statistics"] } # Linux: evdev backend (works on X11 AND Wayland) monio = { version = "0.1", features = ["evdev"], default-features = false } ``` -------------------------------- ### Handle Monio Errors with the Error Enum Source: https://context7.com/huakunshen/monio/llms.txt Illustrates how to handle various errors returned by Monio functions using the `Error` enum. This includes matching on specific error variants like `NotRunning` and `AlreadyRunning`, and handling general errors. ```rust use monio::{Hook, Error}; fn main() { let hook = Hook::new(); // Attempting to stop a hook that isn't running match hook.stop() { Err(Error::NotRunning) => println!("Expected: hook was not running"), Err(e) => println!("Unexpected error: {}", e), Ok(_) => {} } // Start and try to start again hook.run_async(|_| {}).unwrap(); match hook.run_async(|_| {}) { Err(Error::AlreadyRunning) => println!("Expected: already running"), Err(e) => println!("Unexpected: {}", e), Ok(_) => {} } // Pattern match on all variants let err = Error::PermissionDenied("Accessibility not granted".into()); match err { Error::AlreadyRunning => println!("already running"), Error::NotRunning => println!("not running"), Error::HookStartFailed(msg) => println!("start failed: {}", msg), Error::HookStopFailed(msg) => println!("stop failed: {}", msg), Error::SimulateFailed(msg) => println!("simulate failed: {}", msg), Error::Platform(msg) => println!("platform: {}", msg), Error::PermissionDenied(msg) => println!("permission denied: {}", msg), Error::ThreadError(msg) => println!("thread error: {}", msg), Error::NotSupported(msg) => println!("not supported: {}", msg), Error::Other(msg) => println!("other: {}", msg), } // Expected: // Expected: hook was not running // Expected: already running // permission denied: Accessibility not granted hook.stop().unwrap(); } ``` -------------------------------- ### Synchronously Grab and Filter Events with grab_channel Source: https://context7.com/huakunshen/monio/llms.txt Use `grab_channel` to capture events and deliver them to a channel. The provided filter closure is executed inline and can consume events by returning `false`. All events are forwarded to the receiver channel. ```rust use monio::channel::grab_channel; use monio::{EventType, Key}; use std::time::Duration; fn main() -> monio::Result<()> { // Block specific hotkeys, log everything let blocked_keys = vec![Key::F1, Key::F2, Key::PrintScreen]; let (handle, rx) = grab_channel(200, move |event| { if event.event_type == EventType::KeyPressed { if let Some(kb) = &event.keyboard { if blocked_keys.contains(&kb.key) { println!("Blocked: {:?}", kb.key); return false; // consume } } } true // pass through })?; for event in rx.iter() { match event.event_type { EventType::KeyPressed => { if let Some(kb) = &event.keyboard { println!("Allowed key: {:?}", kb.key); } } _ => {} } if !handle.is_running() { break; } } // Expected: F1/F2/PrintScreen are blocked; all events appear in channel Ok(()) } ``` -------------------------------- ### Add user to input group Source: https://github.com/huakunshen/monio/blob/main/README.md Grant necessary permissions for the evdev backend by adding the current user to the 'input' group. Remember to log out and back in for the changes to take effect. ```bash sudo usermod -aG input $USER # Log out and back in for changes to take effect ``` -------------------------------- ### StatisticsCollector / EventStatistics Source: https://context7.com/huakunshen/monio/llms.txt Collects real-time input statistics including typing speed, mouse distance, key frequency, scroll totals, and active typing duration. Supports live snapshots, merging multiple sessions, and health-break detection. ```APIDOC ## `StatisticsCollector` / `EventStatistics` — Input analytics Requires the `statistics` feature. Collects real-time input statistics including typing speed, mouse distance, key frequency, scroll totals, and active typing duration. Supports live snapshots, merging multiple sessions, and health-break detection. ### Methods - **`collect_for(duration: Duration)`**: Collects statistics for a specified duration. - **`new()`**: Creates a new `StatisticsCollector` instance. - **`start()`**: Starts the statistics collection. - **`snapshot()`**: Returns a non-destructive snapshot of the current statistics. - **`stop()`**: Stops the statistics collection and returns the final statistics. ### Statistics Methods - **`summary()`**: Returns a formatted string summary of the collected statistics. - **`keys_per_minute()`**: Returns the typing speed in keys per minute. - **`total_mouse_distance`**: Returns the total distance the mouse has moved. - **`mouse_activity_ratio()`**: Returns the ratio of mouse activity. - **`total_vertical_scroll`**: Returns the total vertical scroll amount. - **`most_frequent_key()`**: Returns the most frequently pressed key and its count. - **`most_frequent_button()`**: Returns the most frequently clicked button and its count. - **`needs_break(threshold: Duration)`**: Checks if a break is needed based on the specified threshold. ### Example Usage ```rust use monio::statistics::StatisticsCollector; use std::time::Duration; // Collect for a duration let stats = StatisticsCollector::collect_for(Duration::from_secs(30))?; println!("{}", stats.summary()); // Live snapshot let mut collector = StatisticsCollector::new(); collector.start()?; std::thread::sleep(Duration::from_secs(5)); let snap = collector.snapshot(); println!("Snapshot key presses: {}", snap.key_press_count); let final_stats = collector.stop()?; println!("Final events: {}", final_stats.total_events()); ``` ``` -------------------------------- ### Configure monio Feature Flags Source: https://github.com/huakunshen/monio/blob/main/README.md Specify feature flags in Cargo.toml to enable specific functionalities like Tokio support, event recording, or input statistics. ```toml # Default (X11 on Linux) monio = "0.1" ``` ```toml # Async channel support with Tokio monio = { version = "0.1", features = ["tokio"] } ``` ```toml # Event recording and playback (macro scripts) monio = { version = "0.1", features = ["recorder"] } ``` ```toml # Input statistics collection monio = { version = "0.1", features = ["statistics"] } ``` ```toml # All features monio = { version = "0.1", features = ["tokio", "recorder", "statistics"] } ``` ```toml # Linux: evdev support (works on X11 AND Wayland) monio = { version = "0.1", features = ["evdev"], default-features = false } ``` -------------------------------- ### state module Source: https://context7.com/huakunshen/monio/llms.txt Provides atomic read/write access to the global modifier/button state. Every `Event` carries a `mask` field snapshot; these functions let you query the live state at any time or integrate with custom event pipelines. ```APIDOC ## `state` module — Global modifier and button mask Provides atomic read/write access to the global modifier/button state. Every `Event` carries a `mask` field snapshot; these functions let you query the live state at any time or integrate with custom event pipelines. ### Functions - **`get_mask()`**: Returns the current raw mask value. - **`set_mask(mask: u32)`**: Sets the global mask to the specified value. - **`unset_mask(mask: u32)`**: Unsets the bits in the mask corresponding to the specified value. - **`reset_mask()`**: Resets the global mask to 0. - **`is_button_held()`**: Checks if any mouse button is held. - **`is_shift_held()`**: Checks if the Shift key is held. - **`is_ctrl_held()`**: Checks if the Ctrl key is held. - **`is_alt_held()`**: Checks if the Alt key is held. - **`is_meta_held()`**: Checks if the Meta key is held. ### Constants - **`MASK_BUTTON1`**: Mask for the left mouse button. - **`MASK_SHIFT`**: Mask for the Shift key. - **`MASK_CTRL`**: Mask for the Ctrl key. ### Example Usage ```rust use monio::state::{ get_mask, set_mask, unset_mask, reset_mask, is_button_held, is_shift_held, is_ctrl_held, MASK_BUTTON1, MASK_SHIFT, MASK_CTRL, }; reset_mask(); assert!(!is_shift_held()); set_mask(MASK_SHIFT | MASK_CTRL); assert!(is_shift_held()); assert!(is_ctrl_held()); set_mask(MASK_BUTTON1); assert!(is_button_held()); let mask = get_mask(); println!("Current mask: 0x{:08x}", mask); unset_mask(MASK_SHIFT); assert!(!is_shift_held()); reset_mask(); assert_eq!(get_mask(), 0); ``` ``` -------------------------------- ### Manage Global Modifier and Button State Source: https://context7.com/huakunshen/monio/llms.txt The `state` module provides functions to atomically read, write, and modify the global modifier and button state. Use these functions to query the live state or integrate with custom event pipelines. ```rust use monio::state::{ get_mask, set_mask, unset_mask, reset_mask, is_button_held, is_shift_held, is_ctrl_held, is_alt_held, is_meta_held, MASK_BUTTON1, MASK_SHIFT, MASK_CTRL, }; fn main() { // Inspect live modifier state at any time reset_mask(); assert!(!is_button_held()); assert!(!is_shift_held()); // Manually set state (useful for testing or custom event sources) set_mask(MASK_SHIFT | MASK_CTRL); assert!(is_shift_held()); // true assert!(is_ctrl_held()); // true assert!(!is_alt_held()); // false // Simulate left-button press set_mask(MASK_BUTTON1); assert!(is_button_held()); // true // Read raw mask value let mask = get_mask(); println!("Current mask: 0x{:08x}", mask); // Expected: 0x00000103 (SHIFT=1, CTRL=2, BUTTON1=256) // Release shift unset_mask(MASK_SHIFT); assert!(!is_shift_held()); // false assert!(is_ctrl_held()); // still true // Full reset reset_mask(); assert_eq!(get_mask(), 0); println!("Mask constants: SHIFT={:#x} CTRL={:#x} BUTTON1={:#x}", MASK_SHIFT, MASK_CTRL, MASK_BUTTON1); // Expected: SHIFT=0x1 CTRL=0x2 BUTTON1=0x100 } ``` -------------------------------- ### Collect Input Statistics for a Duration Source: https://context7.com/huakunshen/monio/llms.txt Use `StatisticsCollector::collect_for` to gather input statistics over a specified duration. The collected data can be summarized or queried for specific metrics like typing speed and mouse distance. It also includes a check for break reminders. ```rust // Cargo.toml: monio = { version = "0.1", features = ["statistics"] } use monio::statistics::StatisticsCollector; use std::time::Duration; fn main() -> monio::Result<()> { // --- Timed collection --- println!("Collecting for 30 seconds..."); let stats = StatisticsCollector::collect_for(Duration::from_secs(30))?; println!("{}", stats.summary()); // Output: // === Input Statistics === // Duration: 00:30 // Total Events: 187 // Events/min: 374.0 // // Keyboard: // - Presses: 95 // - Keys/min: 190.0 // - Most pressed: Space (12 times) // // Mouse: // - Clicks: 8 // - Moves: 74 // - Distance: 3421 pixels // Specific metrics println!("Typing speed: {:.1} keys/min", stats.keys_per_minute()); println!("Mouse distance: {:.0}px", stats.total_mouse_distance); println!("Mouse activity ratio: {:.1}%", stats.mouse_activity_ratio() * 100.0); println!("Vertical scroll total: {:.1}", stats.total_vertical_scroll); if let Some((key, count)) = stats.most_frequent_key() { println!("Most pressed: {:?} ({} times)", key, count); } if let Some((btn, count)) = stats.most_frequent_button() { println!("Most clicked button: {:?} ({} times)", btn, count); } // Break reminder if stats.needs_break(Duration::from_secs(1800)) { println!("You've been typing for 30+ minutes. Take a break!"); } // --- Live snapshot example --- let mut collector = StatisticsCollector::new(); collector.start()?; std::thread::sleep(Duration::from_secs(5)); let snap = collector.snapshot(); // non-destructive peek println!("Snapshot after 5s: {} key presses so far", snap.key_press_count); let final_stats = collector.stop()?; println!("Final: {} total events", final_stats.total_events()); Ok(()) } ``` -------------------------------- ### Use Hook Struct for Non-blocking Event Handling (Rust) Source: https://github.com/huakunshen/monio/blob/main/README.md Utilize the `Hook` struct for non-blocking event handling in a separate thread. The `run_async` method takes a closure to process events, and `stop` can be called to terminate the hook. ```Rust use monio::{Hook, Event}; use std::thread; use std::time::Duration; fn main() -> monio::Result<()> { let hook = Hook::new(); // Start in background thread hook.run_async(|event: &Event| { println!("{:?}", event.event_type); })?; // Do other work... thread::sleep(Duration::from_secs(10)); // Stop the hook hook.stop()?; Ok(()) } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.