fix(desktop): reject conflicting headless modes
This commit is contained in:
parent
87dbb21d8f
commit
0641cb3f3e
|
|
@ -98,6 +98,7 @@ mod window_resize;
|
|||
mod window_state;
|
||||
|
||||
use op_host_native::{NativeBackend, SharedSkiaContext, SharedSkiaError, WidgetHostNative};
|
||||
use std::ffi::OsStr;
|
||||
use std::path::PathBuf;
|
||||
use std::time::Instant;
|
||||
use winit::event_loop::{ControlFlow, EventLoop, EventLoopProxy};
|
||||
|
|
@ -538,6 +539,31 @@ fn init_tracing() {
|
|||
.try_init();
|
||||
}
|
||||
|
||||
fn conflicting_headless_modes<I, S>(args: I) -> Option<Vec<&'static str>>
|
||||
where
|
||||
I: IntoIterator<Item = S>,
|
||||
S: AsRef<OsStr>,
|
||||
{
|
||||
const MODE_FLAGS: [&str; 6] = [
|
||||
"--mcp",
|
||||
"--mcp-http",
|
||||
"--serve-web",
|
||||
"--tcc-selftest",
|
||||
"--render-shots",
|
||||
"--enrich-images",
|
||||
];
|
||||
let mut requested = Vec::new();
|
||||
for arg in args {
|
||||
let arg = arg.as_ref();
|
||||
for mode in MODE_FLAGS {
|
||||
if arg == OsStr::new(mode) && !requested.contains(&mode) {
|
||||
requested.push(mode);
|
||||
}
|
||||
}
|
||||
}
|
||||
(requested.len() > 1).then_some(requested)
|
||||
}
|
||||
|
||||
fn main() {
|
||||
// FIRST, before any thread exists: graft the login-shell PATH and proxy
|
||||
// exports onto this process. A Dock/Finder launch inherits launchd's
|
||||
|
|
@ -566,6 +592,13 @@ fn main() {
|
|||
Err(err) => eprintln!("[fonts] skipping imported-font rescan: {err}"),
|
||||
}
|
||||
init_tracing();
|
||||
if let Some(modes) = conflicting_headless_modes(std::env::args_os().skip(1)) {
|
||||
eprintln!(
|
||||
"openpencil-desktop: headless modes are mutually exclusive: {}",
|
||||
modes.join(", ")
|
||||
);
|
||||
std::process::exit(2);
|
||||
}
|
||||
// `--mcp` / `--mcp-http` swap the GUI for an MCP server mode;
|
||||
// when one of those ran, exit instead of opening a window.
|
||||
if mcp_serve::run_cli_if_requested() {
|
||||
|
|
|
|||
|
|
@ -4,6 +4,38 @@
|
|||
use super::*;
|
||||
use winit::keyboard::{Key, NamedKey};
|
||||
|
||||
#[test]
|
||||
fn distinct_headless_modes_are_rejected_before_dispatch() {
|
||||
assert_eq!(
|
||||
conflicting_headless_modes([
|
||||
"--render-shots",
|
||||
"input.op",
|
||||
"shots",
|
||||
"--enrich-images",
|
||||
"input.op",
|
||||
"output.op",
|
||||
]),
|
||||
Some(vec!["--render-shots", "--enrich-images"])
|
||||
);
|
||||
assert_eq!(
|
||||
conflicting_headless_modes(["--mcp-http", "3100", "input.op", "--tcc-selftest"]),
|
||||
Some(vec!["--mcp-http", "--tcc-selftest"])
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn one_headless_mode_or_repeated_same_flag_is_not_a_conflict() {
|
||||
assert_eq!(
|
||||
conflicting_headless_modes(["--render-shots", "input.op", "shots"]),
|
||||
None
|
||||
);
|
||||
assert_eq!(
|
||||
conflicting_headless_modes(["--enrich-images", "input.op", "--enrich-images"]),
|
||||
None
|
||||
);
|
||||
assert_eq!(conflicting_headless_modes(["document.op"]), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cursor_only_redraw_without_visible_state_change_skips_present() {
|
||||
let mut app = DesktopApp::new(None);
|
||||
|
|
|
|||
Loading…
Reference in a new issue