Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src-tauri/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src-tauri/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,8 @@ log = "0.4"
dirs = "5"
hyperdeck-core = { path = "../crates/hyperdeck-core" }
hyperdeck-os = { path = "../crates/hyperdeck-os" }

# AttachConsole for the CLI/headless modes (the tray app is a GUI-subsystem
# binary; see the windows_subsystem attribute in main.rs).
[target.'cfg(windows)'.dependencies]
windows = { version = "0.58", features = ["Win32_System_Console"] }
29 changes: 27 additions & 2 deletions src-tauri/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
// Tray-only application: no console window on Windows release builds.
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
// Tray-only application: never spawn a console window on Windows. This applies to
// every profile (the `cargo tauri build --debug` bundle and `cargo tauri dev`
// included), not just release — a debug-only guard let a console pop on test
// builds. The CLI/headless modes reattach to the parent terminal (see
// `attach_console`) so they still print when launched from a shell.
#![windows_subsystem = "windows"]

mod backend;

Expand All @@ -20,6 +24,7 @@ fn main() {

// Verify / prompt for input permission, then exit (parity with the Go flag).
if args.iter().any(|a| a == "--check-accessibility") {
attach_console();
if hyperdeck_os::injector::request_accessibility() {
println!("input permission granted");
std::process::exit(0);
Expand All @@ -30,13 +35,33 @@ fn main() {

// Headless mode: run the core with a logging presenter, no tray.
if args.iter().any(|a| a == "--no-tray" || a == "--headless") {
attach_console();
run_headless();
return;
}

run_tray();
}

/// Reattach this process to the parent terminal's console on Windows. The binary is
/// linked as a GUI-subsystem app (see the crate-level `windows_subsystem`
/// attribute) so the tray build never pops a console window; the CLI/headless modes
/// still want their stdout/stderr, so claim the parent console when one exists.
/// Launched from Explorer / a shortcut there is no parent console and this is a
/// harmless no-op. Non-Windows platforms inherit the terminal normally.
#[cfg(windows)]
fn attach_console() {
use windows::Win32::System::Console::{AttachConsole, ATTACH_PARENT_PROCESS};
// Safe: AttachConsole has no preconditions and we ignore the result — failure
// (no parent console) just means there is nothing to print to.
unsafe {
let _ = AttachConsole(ATTACH_PARENT_PROCESS);
}
}

#[cfg(not(windows))]
fn attach_console() {}

fn run_headless() {
let presenter: Arc<dyn StatusPresenter + Send + Sync> = Arc::new(LogPresenter);
match backend::start(presenter, BIND, POLL) {
Expand Down
Loading