#![windows_subsystem = "windows"]
mod audit;
mod cli;
mod clock;
mod config;
mod explain;
mod orchestrator;
mod os;
mod session;
mod timer;
mod ui;
use cli::Command;
use windows::core::PCWSTR;
use windows::Win32::Foundation::{ERROR_ALREADY_EXISTS, HANDLE, HWND, LPARAM, WPARAM};
use windows::Win32::System::DataExchange::COPYDATASTRUCT;
use windows::Win32::System::Threading::CreateMutexW;
use windows::Win32::UI::WindowsAndMessaging::{FindWindowW, SendMessageW, WM_COPYDATA};
fn main() {
let args: Vec<String> = std::env::args().skip(1).collect();
let command = match cli::parse(&args) {
Ok(c) => c,
Err(e) => {
report(&format!("taskbar-focus: {}\n\n{}", e.0, cli::HELP));
std::process::exit(2);
}
};
match command {
Command::Help => {
report(cli::HELP);
return;
}
Command::Version => {
report(&format!("taskbar-focus {}", env!("CARGO_PKG_VERSION")));
return;
}
Command::Explain => {
report(&explain::report());
return;
}
_ => {}
}
let (already_running, _mutex) = acquire_single_instance();
if already_running {
forward_to_running_instance(&command);
return;
}
let first_run = config::is_first_run();
let config = config::Config::load();
let timer = if config.behavior.restore_session_on_restart {
session::restore().unwrap_or_default()
} else {
session::clear();
timer::Timer::new()
};
audit::log_start(config.dnd.enabled);
if let Some(outcome) = os::dnd::recover_if_needed() {
audit::log(&format!(
"recovery: previous run exited uncleanly with DND on -> {outcome:?}"
));
}
if let Err(e) = ui::app::run(config, timer, command, first_run) {
report(&format!("taskbar-focus failed to start: {e}"));
std::process::exit(1);
}
}
struct MutexGuard(#[allow(dead_code)] HANDLE);
unsafe impl Send for MutexGuard {}
fn acquire_single_instance() -> (bool, Option<MutexGuard>) {
let name = ui::wide(ui::app::MUTEX_NAME);
unsafe {
match CreateMutexW(None, true, name.as_pcwstr()) {
Ok(h) => {
let existed = windows::Win32::Foundation::GetLastError() == ERROR_ALREADY_EXISTS;
(existed, Some(MutexGuard(h)))
}
Err(_) => (false, None),
}
}
}
fn forward_to_running_instance(command: &Command) {
let class = ui::wide(ui::app::CLASS_MAIN);
let hwnd = unsafe { FindWindowW(class.as_pcwstr(), PCWSTR::null()) };
let Ok(hwnd) = hwnd else {
report("taskbar-focus is already running, but its window could not be found.");
return;
};
if hwnd.is_invalid() {
return;
}
if !command.is_remote_control() {
return;
}
let payload = command.encode();
let cds = COPYDATASTRUCT {
dwData: 0,
cbData: payload.len() as u32,
lpData: payload.as_ptr() as *mut _,
};
unsafe {
SendMessageW(
hwnd,
WM_COPYDATA,
Some(WPARAM(0)),
Some(LPARAM(&cds as *const _ as isize)),
);
}
}
fn report(text: &str) {
if write_to_parent_console(text) {
return;
}
let body = ui::wide(text);
let title = ui::wide("taskbar-focus");
unsafe {
windows::Win32::UI::WindowsAndMessaging::MessageBoxW(
Some(HWND::default()),
body.as_pcwstr(),
title.as_pcwstr(),
windows::Win32::UI::WindowsAndMessaging::MB_OK,
);
}
}
fn write_to_parent_console(text: &str) -> bool {
use windows::Win32::Storage::FileSystem::{
CreateFileW, FILE_GENERIC_WRITE, FILE_SHARE_WRITE, OPEN_EXISTING,
};
use windows::Win32::System::Console::{
AttachConsole, FreeConsole, GetConsoleWindow, WriteConsoleW, ATTACH_PARENT_PROCESS,
};
unsafe {
if !GetConsoleWindow().is_invalid() {
println!("{text}");
return true;
}
if AttachConsole(ATTACH_PARENT_PROCESS).is_err() {
return false;
}
let name = ui::wide("CONOUT$");
let handle = CreateFileW(
name.as_pcwstr(),
FILE_GENERIC_WRITE.0,
FILE_SHARE_WRITE,
None,
OPEN_EXISTING,
Default::default(),
None,
);
let ok = match handle {
Ok(h) if !h.is_invalid() => {
let wide: Vec<u16> = format!("{text}\r\n").encode_utf16().collect();
let mut written = 0u32;
let r = WriteConsoleW(h, &wide, Some(&mut written), None).is_ok();
let _ = windows::Win32::Foundation::CloseHandle(h);
r
}
_ => false,
};
let _ = FreeConsole();
ok
}
}