use std::sync::{Arc, RwLock};
use winshift::{FocusChangeHandler, WindowFocusHook};
struct WindowOnlyHandler {
current_window: Arc<RwLock<String>>,
}
impl WindowOnlyHandler {
fn new() -> Self {
Self {
current_window: Arc::new(RwLock::new(String::new())),
}
}
}
impl FocusChangeHandler for WindowOnlyHandler {
fn on_app_change(&self, _pid: i32, _app_name: String) {
}
fn on_window_change(&self, window_title: String) {
let mut current_window = self.current_window.write().unwrap();
if window_title.is_empty() {
println!("Warning: Received empty window title");
return;
}
if *current_window != window_title {
if current_window.is_empty() {
println!("Initial window: '{window_title}'");
} else {
println!(
"Window changed: '{}' -> '{}'",
*current_window, window_title
);
}
*current_window = window_title;
}
}
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
winshift::env_logger::init();
println!("This monitor detects only window changes.");
println!("Application switches are ignored.");
println!();
println!("Try switching between:");
println!(" - Different windows within the same app (VSCode tabs, browser tabs, etc.)");
println!(" - Different windows across apps");
println!();
println!("Press Ctrl+C to exit");
println!();
let handler = WindowOnlyHandler::new();
let hook = Arc::new(WindowFocusHook::window_only(handler));
let stop_handle = hook.clone();
::ctrlc::set_handler(move || {
println!("\nShutting down window-only monitor...");
eprintln!("[SIGNAL] Ctrl+C signal received!");
if let Err(err) = stop_handle.stop() {
eprintln!("Failed to stop hook: {err}");
}
eprintln!("[SIGNAL] Stop signal sent, exiting signal handler");
})?;
if let Err(e) = hook.run() {
eprintln!("Error running hook: {e}");
}
println!("Window-only monitor stopped.");
Ok(())
}