| Crates.io | winshift |
| lib.rs | winshift |
| version | 0.0.5 |
| created_at | 2024-08-17 09:38:03.976166+00 |
| updated_at | 2025-09-04 03:57:00.232709+00 |
| description | A cross-platform window change hook library |
| homepage | |
| repository | https://github.com/efJerryYang/winshift-rs |
| max_upload_size | |
| id | 1341429 |
| size | 157,466 |
A cross-platform library for monitoring window focus changes.
Note: The app tracking functionality on macOS exists solely to work around platform limitations for reliable window focus detection.
cargo add winshift
See the Examples section for usage patterns.
This simplified example shows the basic structure. For complete, working examples see the examples/ directory.
use winshift::{FocusChangeHandler, WindowFocusHook};
use std::sync::Arc;
struct MyHandler;
impl FocusChangeHandler for MyHandler {
fn on_app_change(&self, pid: i32, app_name: String) {
println!("App changed: {} (PID: {})", app_name, pid);
}
fn on_window_change(&self, window_title: String) {
println!("Window changed: {}", window_title);
}
}
fn main() -> Result<(), winshift::WinshiftError> {
let handler = Arc::new(MyHandler);
let hook = WindowFocusHook::new(handler);
// Start monitoring (runs in current thread)
hook.run()?;
// On macOS, you can stop with:
// winshift::stop_hook();
Ok(())
}
When enabled, macOS event callbacks also include the full ActiveWindowInfo so apps don’t need to call get_active_window_info() after each event. This reduces overhead and simplifies consumers like chronicle.
How to enable:
use winshift::{FocusChangeHandler, WindowFocusHook, WindowHookConfig};
struct Handler;
impl FocusChangeHandler for Handler {
fn on_app_change(&self, pid: i32, app_name: String) {
println!("app: {app_name} ({pid})");
}
fn on_window_change(&self, title: String) {
println!("win: {title}");
}
// macOS-only rich payloads
#[cfg(target_os = "macos")]
fn on_app_change_info(&self, info: winshift::ActiveWindowInfo) {
println!("app+info: {} pid={} exe={} wid={} bounds=({},{} {}x{})",
info.app_name, info.process_id, info.proc_path, info.window_id,
info.bounds.x, info.bounds.y, info.bounds.width, info.bounds.height);
}
#[cfg(target_os = "macos")]
fn on_window_change_info(&self, info: winshift::ActiveWindowInfo) {
println!("win+info: '{}' exe={}", info.title, info.proc_path);
}
}
fn main() -> Result<(), winshift::WinshiftError> {
winshift::env_logger::init();
let mut cfg = WindowHookConfig::default();
cfg.embed_active_info = true; // opt-in to richer payloads
let hook = WindowFocusHook::with_config(Handler, cfg);
hook.run()
}
See examples/embed_info_monitor.rs for a complete example.
Important Notes:
stop_hook() to clean upFull API documentation is available via cargo doc --open.
Contributions are welcome! Please open issues or pull requests on GitHub.
MIT - See LICENSE for details.