From 2a5d0da791801620f7d95ef0c75e1cc901265f46 Mon Sep 17 00:00:00 2001 From: Logan King Date: Wed, 18 Jun 2025 18:20:58 -0700 Subject: [PATCH 1/2] =?UTF-8?q?=E2=9C=A8=20focus=20terminal=20window=20on?= =?UTF-8?q?=20Windows?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Cargo.toml | 2 ++ src/main.rs | 24 ++++++++++++++++++++++++ src/windows_focus.rs | 37 +++++++++++++++++++++++++++++++++++++ 3 files changed, 63 insertions(+) create mode 100644 src/windows_focus.rs diff --git a/Cargo.toml b/Cargo.toml index 0a5cd01..984dd6a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -47,4 +47,6 @@ windows = { version = "0.52.0", features = [ "Win32_Foundation", "Win32_Media_Audio", "Win32_Media_Audio_Endpoints", + "Win32_System_Console", + "Win32_UI_WindowsAndMessaging", ] } diff --git a/src/main.rs b/src/main.rs index b670346..23ee175 100644 --- a/src/main.rs +++ b/src/main.rs @@ -54,6 +54,8 @@ use timers::AudibleTimers; mod options; #[cfg(target_os = "windows")] mod windows_volume; +#[cfg(target_os = "windows")] +mod windows_focus; use tracing::{debug, error, info, instrument, warn}; use tracing_appender::rolling::{RollingFileAppender, Rotation}; @@ -611,6 +613,18 @@ fn call_fn( Some(format!("Current voice is {}", name)) } + "focus_terminal" => { + #[cfg(target_os = "windows")] + { + windows_focus::bring_terminal_to_front(); + None + } + #[cfg(not(target_os = "windows"))] + { + Some("focus_terminal is only supported on Windows".to_string()) + } + } + "list_output_devices" => { let default = get_default_output_device().unwrap_or_else(|| "Unknown".to_string()); let mut devices = list_audio_output_devices(); @@ -1576,6 +1590,16 @@ async fn main() -> Result<(), Box> { })) .build().unwrap(), + ChatCompletionFunctionsArgs::default() + .name("focus_terminal") + .description("Brings the console window to the foreground on Windows.") + .parameters(json!({ + "type": "object", + "properties": {}, + "required": [], + })) + .build().unwrap(), + ChatCompletionFunctionsArgs::default() .name("get_location") .description("Returns an approximate location based on the machine's IP address.") diff --git a/src/windows_focus.rs b/src/windows_focus.rs new file mode 100644 index 0000000..43dd2b1 --- /dev/null +++ b/src/windows_focus.rs @@ -0,0 +1,37 @@ +#[cfg(target_os = "windows")] +use windows::Win32::Foundation::HWND; +#[cfg(target_os = "windows")] +use windows::Win32::System::Console::GetConsoleWindow; +#[cfg(target_os = "windows")] +use windows::Win32::UI::WindowsAndMessaging::{SetForegroundWindow, ShowWindow, SW_RESTORE}; + +#[cfg(target_os = "windows")] +/// Brings the console window to the foreground on Windows. +pub fn bring_terminal_to_front() { + unsafe { + let hwnd: HWND = GetConsoleWindow(); + if hwnd.0 != 0 { + // Restore the window in case it is minimized + ShowWindow(hwnd, SW_RESTORE); + // Attempt to bring the window to the foreground + let _ = SetForegroundWindow(hwnd); + } + } +} + +#[cfg(not(target_os = "windows"))] +/// Stub for non-Windows platforms. +pub fn bring_terminal_to_front() {} + +#[cfg(test)] +mod tests { + use super::*; + + #[cfg(target_os = "windows")] + #[test] + fn call_bring_terminal_to_front() { + // The function should simply run without panicking. + bring_terminal_to_front(); + } +} + From 012c365ae3facadf32423eec6b7f69bd1d8ea814 Mon Sep 17 00:00:00 2001 From: Logan King Date: Wed, 18 Jun 2025 18:34:17 -0700 Subject: [PATCH 2/2] =?UTF-8?q?=F0=9F=90=9B=20fix:=20avoid=20focusing=20VS?= =?UTF-8?q?=20Code=20terminal?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/windows_focus.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/windows_focus.rs b/src/windows_focus.rs index 43dd2b1..655a9ea 100644 --- a/src/windows_focus.rs +++ b/src/windows_focus.rs @@ -8,6 +8,13 @@ use windows::Win32::UI::WindowsAndMessaging::{SetForegroundWindow, ShowWindow, S #[cfg(target_os = "windows")] /// Brings the console window to the foreground on Windows. pub fn bring_terminal_to_front() { + // Skip if running inside VS Code's integrated terminal to avoid spawning a new window + if let Ok(term) = std::env::var("TERM_PROGRAM") { + if term.to_lowercase().contains("vscode") { + return; + } + } + unsafe { let hwnd: HWND = GetConsoleWindow(); if hwnd.0 != 0 { @@ -27,10 +34,9 @@ pub fn bring_terminal_to_front() {} mod tests { use super::*; - #[cfg(target_os = "windows")] #[test] fn call_bring_terminal_to_front() { - // The function should simply run without panicking. + // The function should simply run without panicking on all platforms. bring_terminal_to_front(); } }