Skip to content
Open
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
2 changes: 2 additions & 0 deletions apps/filmcraft/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ winit = { version = "0.30", default-features = false }
# Settings ▸ Appearance ▸ Sync with system: the XDG desktop portal's colour scheme. The zbus the
# portal file dialogs (rfd) and accesskit already use.
zbus = "5.19"
# Same winit as eframe: Linux event-loop options (enables --x11 backend for drag-and-drop).
winit = { version = "0.30", default-features = false, features = ["x11"] }

# Icon + VERSIONINFO for filmcraft.exe (build.rs); only needed when building on Windows.
[target.'cfg(windows)'.build-dependencies]
Expand Down
5 changes: 5 additions & 0 deletions apps/filmcraft/src/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ Options:
--graphics <mode> start with this graphics mode and keep it: default,
dx12 (Windows), software (Windows, Linux);
`--graphics default` undoes an automatic fallback
--x11 run via X11 / XWayland on Linux (enables file drag-and-drop)
--version print the version and exit
-h, --help print this help and exit
";
Expand All @@ -47,6 +48,8 @@ pub struct Launch {
pub data_dir: Option<std::path::PathBuf>,
/// `--graphics <mode>`: start with this graphics mode and keep it (see `graphics.rs`).
pub graphics: Option<crate::graphics::Mode>,
/// `--x11`: run via X11 / XWayland backend on Linux for drag-and-drop compatibility.
pub x11: bool,
}

/// Parse the arguments after the program name. `env_control_port` is the value of
Expand All @@ -70,6 +73,7 @@ pub fn parse(env_control_port: Option<String>, args: impl IntoIterator<Item = Os
recover: None,
data_dir: None,
graphics: None,
x11: false,
};
let (mut help, mut version) = (false, false);
let mut args = args.into_iter();
Expand All @@ -78,6 +82,7 @@ pub fn parse(env_control_port: Option<String>, args: impl IntoIterator<Item = Os
match a.as_ref() {
"-h" | "--help" => help = true,
"--version" => version = true,
"--x11" => l.x11 = true,
"--control" => {
let port = args.next().ok_or("--control needs a port number")?;
let port = port.to_string_lossy();
Expand Down
23 changes: 17 additions & 6 deletions apps/filmcraft/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,8 +130,9 @@ fn main() -> eframe::Result {
if graphics.mode() == graphics::Mode::Default {
register_gpu_frame_renderer();
}
let x11 = launch.x11 || std::env::var_os("FILMCRAFT_X11").is_some();
let started = loop {
let mut options = native_options(launch.control_port.is_some());
let mut options = native_options(launch.control_port.is_some(), x11);
// Before eframe creates the wgpu instance (e.g. no OpenGL on Windows, see graphics.rs).
graphics::apply(&mut options, graphics.mode(), backend_override);
let app_created = Arc::new(AtomicBool::new(false));
Expand Down Expand Up @@ -164,7 +165,7 @@ fn main() -> eframe::Result {
}

/// The main window's options; built for each start attempt (they hold a one-shot hook).
fn native_options(agent: bool) -> eframe::NativeOptions {
fn native_options(agent: bool, x11: bool) -> eframe::NativeOptions {
eframe::NativeOptions {
viewport: egui::ViewportBuilder::default()
.with_title("FilmCraft")
Expand All @@ -179,15 +180,15 @@ fn native_options(agent: bool) -> eframe::NativeOptions {
.with_icon(app_icon())
// Wayland matches the window to `packaging/linux/ai.storyteller.filmcraft.desktop`.
.with_app_id(APP_ID),
event_loop_builder: agent_event_loop(agent),
event_loop_builder: agent_event_loop(agent, x11),
..Default::default()
}
}

/// Creates the app once eframe has its window and graphics device; sets `created` when it runs,
/// and confirms the graphics mode once two frames have painted.
fn app_creator(launch: Launch, graphics: graphics::GraphicsStart, created: Arc<AtomicBool>) -> eframe::AppCreator<'static> {
let Launch { control_port, control_input_only, files, demo, startup_flag, recover, data_dir, graphics: _ } = launch;
let Launch { control_port, control_input_only, files, demo, startup_flag, recover, data_dir, graphics: _, x11: _ } = launch;
Box::new(move |cc| {
created.store(true, Ordering::Relaxed);
// A fallback graphics mode says so in the window, with a button back to the default.
Expand Down Expand Up @@ -426,15 +427,25 @@ fn local_offset(unix: i64) -> i32 {

/// Driven by an agent (`--control`): don't activate the app on launch, so the user's keyboard
/// focus stays where it is (macOS; winit activates ignoring other apps by default).
fn agent_event_loop(agent: bool) -> Option<eframe::EventLoopBuilderHook> {
/// On Linux, `--x11` configures winit to run via X11/XWayland so drag-and-drop works reliably.
fn agent_event_loop(agent: bool, x11: bool) -> Option<eframe::EventLoopBuilderHook> {
#[cfg(target_os = "macos")]
if agent {
let _ = x11;
return Some(Box::new(|b| {
use winit::platform::macos::EventLoopBuilderExtMacOS;
b.with_activate_ignoring_other_apps(false);
}));
}
let _ = agent;
#[cfg(target_os = "linux")]
if x11 {
let _ = agent;
return Some(Box::new(|b| {
use winit::platform::x11::EventLoopBuilderExtX11;
b.with_x11();
}));
}
let _ = (agent, x11);
None
}

Expand Down