use anyhow::Result; #[cfg(not(coverage))] use { super::clipboard::send_clipboard_text_to_remote, super::device_test::{DeviceTestController, DeviceTestKind}, super::devices::{CameraMode, DeviceCatalog}, super::diagnostics::{PerformanceSample, quality_probe_command}, super::launcher_clipboard_control_path, super::launcher_focus_signal_path, super::power::{fetch_capture_power, reset_usb_gadget, set_capture_power_mode}, super::state::{ BreakoutSizePreset, CapturePowerStatus, CaptureSizePreset, DisplaySurface, FeedSourcePreset, InputRouting, LauncherState, MAX_AUDIO_GAIN_PERCENT, MAX_MIC_GAIN_PERCENT, }, super::ui_components::{ ConsoleLogLevel, build_launcher_view, sync_camera_quality_combo, sync_input_device_combo, sync_stage_device_combo, }, super::ui_runtime::{ RelayChild, append_session_log_for_level, apply_popout_window_size, attach_child_log_streams, audio_gain_control_path, capture_swap_key, copy_plain_text, copy_session_log, dock_all_displays_to_preview, dock_display_to_preview, input_control_path, input_state_path, input_toggle_control_path, mic_gain_control_path, next_input_routing, open_diagnostics_popout, open_popout_window, open_session_log_popout, path_marker, present_popout_windows, read_input_routing_state, reap_exited_child, refresh_launcher_ui, refresh_test_buttons, routing_name, selected_combo_value, selected_server_addr, shutdown_launcher_runtime, spawn_client_process, stop_child_process, toggle_key_label, update_test_action_result, uplink_camera_preview_path, uplink_mic_level_path, write_audio_gain_request, write_input_routing_request, write_input_toggle_key_request, write_mic_gain_request, }, crate::handshake::{HandshakeProbe, probe}, crate::output::display::enumerate_monitors, gtk::glib, gtk::prelude::*, lesavka_common::lesavka::CapturePowerCommand, lesavka_common::process_metrics::ProcessCpuSampler, std::cell::{Cell, RefCell}, std::collections::VecDeque, std::process::Command, std::rc::Rc, std::time::{Duration, Instant}, }; include!("ui/message_and_network_state.rs"); #[cfg(not(coverage))] include!("ui/control_requests.rs"); #[cfg(not(coverage))] include!("ui/diagnostic_sampling.rs"); #[cfg(not(coverage))] include!("ui/preview_profiles.rs"); #[cfg(not(coverage))] include!("ui/activation_context.rs"); #[cfg(not(coverage))] pub fn run_gui_launcher(server_addr: String) -> Result<()> { let app = gtk::Application::builder() .application_id("dev.lesavka.launcher") .build(); let catalog = Rc::new(RefCell::new(DeviceCatalog::discover())); let state = Rc::new(RefCell::new(LauncherState::new())); state.borrow_mut().apply_catalog_defaults(&catalog.borrow()); let child_proc = Rc::new(RefCell::new(None::)); let tests = Rc::new(RefCell::new(DeviceTestController::new())); let server_addr = Rc::new(server_addr); let focus_signal_path = Rc::new(launcher_focus_signal_path()); let clipboard_control_path = Rc::new(launcher_clipboard_control_path()); let input_control_path = Rc::new(input_control_path()); let input_state_path = Rc::new(input_state_path()); let input_toggle_control_path = Rc::new(input_toggle_control_path()); let _ = std::fs::remove_file(focus_signal_path.as_path()); let _ = std::fs::remove_file(clipboard_control_path.as_path()); let _ = std::fs::remove_file(input_control_path.as_path()); let _ = std::fs::remove_file(input_state_path.as_path()); let _ = std::fs::remove_file(input_toggle_control_path.as_path()); { let child_proc = Rc::clone(&child_proc); let focus_signal_path = Rc::clone(&focus_signal_path); let clipboard_control_path = Rc::clone(&clipboard_control_path); let input_control_path = Rc::clone(&input_control_path); let input_state_path = Rc::clone(&input_state_path); let input_toggle_control_path = Rc::clone(&input_toggle_control_path); let tests = Rc::clone(&tests); app.connect_shutdown(move |_| { stop_child_process(&child_proc); tests.borrow_mut().stop_all(); let _ = std::fs::remove_file(focus_signal_path.as_path()); let _ = std::fs::remove_file(clipboard_control_path.as_path()); let _ = std::fs::remove_file(input_control_path.as_path()); let _ = std::fs::remove_file(input_state_path.as_path()); let _ = std::fs::remove_file(input_toggle_control_path.as_path()); }); } { let catalog = Rc::clone(&catalog); let state = Rc::clone(&state); let child_proc = Rc::clone(&child_proc); let tests = Rc::clone(&tests); let server_addr = Rc::clone(&server_addr); let focus_signal_path = Rc::clone(&focus_signal_path); let input_control_path = Rc::clone(&input_control_path); let input_state_path = Rc::clone(&input_state_path); let input_toggle_control_path = Rc::clone(&input_toggle_control_path); app.connect_activate(move |app| { let ActivationContext { window, server_entry, camera_combo, camera_quality_combo, microphone_combo, speaker_combo, keyboard_combo, mouse_combo, widgets, preview, popouts, diagnostics_popout, log_popout, camera_quality_syncing, power_tx, power_rx, power_request_in_flight, relay_tx, relay_rx, relay_request_in_flight, caps_tx, caps_rx, caps_request_in_flight, diagnostics_network, diagnostics_process, next_power_probe, next_diagnostics_probe, next_diagnostics_sample, preview_session_active, clipboard_tx, clipboard_rx, log_tx, log_rx, } = include!("ui/activation_setup.rs"); include!("ui/stage_device_bindings.rs"); include!("ui/eye_display_bindings.rs"); include!("ui/media_device_bindings.rs"); let _: () = include!("ui/device_refresh_binding.rs"); include!("ui/relay_input_bindings.rs"); include!("ui/utility_button_bindings.rs"); include!("ui/local_test_bindings.rs"); include!("ui/power_display_key_bindings.rs"); let _: () = include!("ui/runtime_poll.rs"); window.present(); }); } let _ = app.run_with_args::<&str>(&[]); Ok(()) } #[cfg(coverage)] pub fn run_gui_launcher(_server_addr: String) -> Result<()> { Ok(()) } /// Keep the coverage stub aligned with the real preview activation rule. #[cfg(coverage)] fn session_preview_active( state: &crate::launcher::state::LauncherState, child_running: bool, ) -> bool { (child_running || state.remote_active) && state.capture_power.mode != "forced-off" } #[cfg(all(test, not(coverage)))] #[path = "tests/ui_preview_profiles.rs"] mod tests; #[cfg(all(test, coverage))] #[path = "tests/ui_coverage.rs"] mod tests;