-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Expand file tree
/
Copy pathlib.rs
More file actions
142 lines (120 loc) · 4.43 KB
/
lib.rs
File metadata and controls
142 lines (120 loc) · 4.43 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
use crate::app::App;
use crate::cef::CefHandler;
use crate::cli::Cli;
use crate::consts::APP_LOCK_FILE_NAME;
use crate::event::CreateAppEventSchedulerEventLoopExt;
use clap::Parser;
use std::io::Write;
use tracing_subscriber::EnvFilter;
use winit::event_loop::EventLoop;
pub(crate) use graphite_desktop_wrapper as wrapper;
mod app;
mod cef;
mod cli;
mod dirs;
mod event;
mod gpu_context;
mod persist;
mod preferences;
mod render;
mod window;
pub(crate) mod consts;
pub fn start() {
tracing_subscriber::fmt().with_env_filter(EnvFilter::from_default_env()).init();
let cef_context_builder = cef::CefContextBuilder::<CefHandler>::new();
if cef_context_builder.is_sub_process() {
// We are in a CEF subprocess
// This will block until the CEF subprocess quits
let error = cef_context_builder.execute_sub_process();
tracing::warn!("Cef subprocess failed with error: {error}");
return;
}
let cli = Cli::parse();
let Ok(lock_file) = std::fs::OpenOptions::new()
.read(true)
.write(true)
.create(true)
.truncate(true)
.open(dirs::app_data_dir().join(APP_LOCK_FILE_NAME))
else {
panic!("Failed to open lock file.")
};
let mut lock = fd_lock::RwLock::new(lock_file);
let lock = match lock.try_write() {
Ok(mut guard) => {
tracing::info!("Acquired application lock");
let _ = guard.set_len(0);
let _ = write!(guard, "{}", std::process::id());
let _ = guard.sync_all();
guard
}
Err(_) => {
tracing::error!("Another instance is already running, Exiting.");
std::process::exit(1);
}
};
let prefs = preferences::read();
// Must be called before event loop initialization or native window integrations will break
App::init();
let wgpu_context = futures::executor::block_on(gpu_context::create_wgpu_context());
let event_loop = EventLoop::new().unwrap();
let (app_event_sender, app_event_receiver) = std::sync::mpsc::channel();
let app_event_scheduler = event_loop.create_app_event_scheduler(app_event_sender);
let (cef_view_info_sender, cef_view_info_receiver) = std::sync::mpsc::channel();
let disable_ui_acceleration = prefs.disable_ui_acceleration || cli.disable_ui_acceleration;
if disable_ui_acceleration {
println!("UI acceleration is disabled");
}
let cef_handler = cef::CefHandler::new(wgpu_context.clone(), app_event_scheduler.clone(), cef_view_info_receiver);
let cef_context = match cef_context_builder.initialize(cef_handler, disable_ui_acceleration) {
Ok(context) => {
tracing::info!("CEF initialized successfully");
context
}
Err(cef::InitError::InitializationFailureCode(code)) => {
panic!("CEF initialization failed with code: {code}");
}
Err(cef::InitError::BrowserCreationFailed) => {
panic!("Failed to create CEF browser");
}
Err(cef::InitError::RequestContextCreationFailed) => {
panic!("Failed to create CEF request context");
}
};
let app = App::new(Box::new(cef_context), cef_view_info_sender, wgpu_context, app_event_receiver, app_event_scheduler, prefs, cli);
let exit_reason = app.run(event_loop);
// If exiting due to a UI acceleration failure, update preferences to disable it for next launch
if matches!(exit_reason, app::ExitReason::UiAccelerationFailure) {
tracing::error!("Disabling UI acceleration");
preferences::modify(|prefs| {
prefs.disable_ui_acceleration = true;
});
}
// Explicitly drop the instance lock
drop(lock);
match exit_reason {
app::ExitReason::Restart | app::ExitReason::UiAccelerationFailure => {
tracing::error!("Restarting application");
let mut command = std::process::Command::new(std::env::current_exe().unwrap());
#[cfg(target_family = "unix")]
let _ = std::os::unix::process::CommandExt::exec(&mut command);
#[cfg(target_family = "unix")]
tracing::error!("Failed to restart application");
#[cfg(not(target_family = "unix"))]
let _ = command.spawn();
}
_ => {}
}
// Workaround for a Windows-specific exception that occurs when `app` is dropped.
// The issue causes the window to hang for a few seconds before closing.
// Appears to be related to CEF object destruction order.
// Calling `exit` bypasses rust teardown and lets Windows perform process cleanup.
// TODO: Identify and fix the underlying CEF shutdown issue so this workaround can be removed.
#[cfg(target_os = "windows")]
std::process::exit(0);
}
pub fn start_helper() {
let cef_context_builder = cef::CefContextBuilder::<CefHandler>::new_helper();
assert!(cef_context_builder.is_sub_process());
cef_context_builder.execute_sub_process();
}