// Oak Video Editor - Non-Linear Video Editor
// Copyright (C) 2026 Oak Team
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
//! Offscreen screenshot capture for the app window.
//!
//! Renders the full [`OakApp`] shell at 1600×900 (2× = 3200×1866 px) in an
//! offscreen macOS window and writes the PNG to
//! `app/rust/docs/screenshot-window.png`, using the same
//! [`VisualTestAppContext`] machinery the gpui visual tests use. The window
//! is created at `(-10000, -10000)` so nothing flickers on screen.
//!
//! Run it on the macOS main thread (examples run on the main thread, unlike
//! `#[test]` harness threads):
//!
//! ```text
//! cargo run --example screenshot # 1600×900 → docs/screenshot-window.png
//! cargo run --example screenshot -- 1100 900 # any size (still overwrites the same file)
//! ```
use gpui::{px, size, AnyWindowHandle, AppContext, Result, VisualTestAppContext};
use gpui_platform::current_platform;
use oakapp::app::OakApp;
const DEFAULT_WIDTH: f32 = 1600.0;
const DEFAULT_HEIGHT: f32 = 900.0;
const OUT: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/docs/screenshot-window.png");
fn main() -> Result<()> {
let args: Vec = std::env::args().skip(1).collect();
let width = args
.first()
.and_then(|s| s.parse().ok())
.unwrap_or(DEFAULT_WIDTH);
let height = args
.get(1)
.and_then(|s| s.parse().ok())
.unwrap_or(DEFAULT_HEIGHT);
let mut cx = VisualTestAppContext::new(current_platform(false));
cx.update(|app| app.init_colors());
let window = cx.open_offscreen_window(size(px(width), px(height)), |window, cx| {
cx.new(|cx| OakApp::new(window, cx))
})?;
let handle: AnyWindowHandle = window.into();
// Draw a few frames so the layout settles: the node editor fits its graph
// once the canvas size is known and the viewers upload their first CPU
// frame, both of which happen on the frame after the initial render.
for _ in 0..4 {
cx.run_until_parked();
cx.update_window(handle, |_root, window, app| {
let _ = window.draw(app);
})?;
}
cx.run_until_parked();
let image = cx.capture_screenshot(handle)?;
std::fs::create_dir_all(std::path::Path::new(OUT).parent().unwrap())?;
image.save(OUT)?;
println!("wrote {OUT} ({}×{})", image.width(), image.height());
Ok(())
}