1use crate::cli::RuntimeOptions;
9use crate::config::Config;
10use anyhow::Result;
11use std::sync::Arc;
12use tokio::runtime::Runtime;
13use winit::event_loop::{ControlFlow, EventLoop};
14#[derive(Debug, Clone)]
17pub(crate) enum AppEvent {
18 #[cfg(target_os = "macos")]
20 DisplayConfigurationChanged,
21 UiTestStep(ui_test::UiTestStep),
23 UiTestFinish,
25}
26
27pub(crate) mod display_recovery;
28
29pub(crate) mod copy_mode;
30mod file_transfers;
31pub mod handler;
32pub mod input_events;
33pub mod mouse_events;
34pub(crate) mod pane_hint_select;
35pub(crate) mod render_pipeline;
36pub mod tab_ops;
37mod tmux_handler;
38mod triggers;
39pub(crate) mod ui_test;
40pub mod window_manager;
41pub mod window_state;
42
43pub(crate) use window_manager::WindowManager;
44
45pub struct App {
47 config: Config,
48 runtime: Arc<Runtime>,
49 runtime_options: RuntimeOptions,
50}
51
52impl App {
53 pub fn new(runtime: Arc<Runtime>, runtime_options: RuntimeOptions) -> Result<Self> {
55 let mut config = Config::load()?;
56
57 if let Some(ref shader) = runtime_options.shader {
59 config.shader.custom_shader = Some(shader.clone());
60 config.shader.custom_shader_enabled = true;
61 config.background.background_image_enabled = false;
63 log::info!("CLI override: using shader '{}'", shader);
64 }
65
66 if runtime_options.log_session {
68 config.session_log.auto_log_sessions = true;
69 log::info!("CLI override: session logging enabled");
70 }
71
72 if runtime_options.log_level.is_none() {
78 log::info!("Config log level: {}", config.log_level.display_name());
79 crate::debug::set_log_level(config.log_level.to_level_filter());
80 }
81
82 Ok(Self {
83 config,
84 runtime,
85 runtime_options,
86 })
87 }
88
89 pub fn run(self) -> Result<()> {
91 let event_loop = EventLoop::<AppEvent>::with_user_event().build()?;
92
93 event_loop.set_control_flow(ControlFlow::Wait);
96 #[cfg(target_os = "macos")]
97 let _display_observer =
98 display_recovery::register_display_change_observer(event_loop.create_proxy());
99
100 let ui_test_script = self
104 .runtime_options
105 .ui_test
106 .as_deref()
107 .map(ui_test::load_script)
108 .transpose()?;
109 if let Some(script) = ui_test_script {
110 let proxy = event_loop.create_proxy();
111 std::thread::spawn(move || {
112 for step in script.steps {
113 std::thread::sleep(std::time::Duration::from_millis(step.wait_ms));
114 if proxy.send_event(AppEvent::UiTestStep(step)).is_err() {
115 return; }
117 }
118 std::thread::sleep(std::time::Duration::from_millis(600));
121 let _ = proxy.send_event(AppEvent::UiTestFinish);
122 });
123 }
124
125 let mut window_manager =
126 WindowManager::new(self.config, self.runtime, self.runtime_options);
127
128 event_loop.run_app(&mut window_manager)?;
129
130 Ok(())
131 }
132}