control: keep channel responsive when window is covered (disable App Nap); fail fast on occluded screenshots

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
Brandon ThomasandClaude Opus 5.5 committed 2026-10-01 20:49:29 -04:00
1 parent 9f0cfb3373
commit 214345df13
4 files changed
+31

No files matched your search

+2
View File
@@ -21,3 +21,5 @@ rfd = { workspace = true }
[target.'cfg(target_os = "macos")'.dependencies]
# Same winit as eframe: macOS event-loop options (no app activation when driven by an agent).
winit = { version = "0.30", default-features = false }
# Keep the control channel responsive when the window is covered (App Nap / occlusion throttling).
objc2-foundation = { version = "0.3", default-features = false, features = ["std", "NSProcessInfo", "NSString", "NSObject"] }
+15
View File
@@ -70,6 +70,7 @@ fn main() -> eframe::Result {
app.hooks.pick_open_project =
Some(Box::new(|| rfd::FileDialog::new().add_filter("EffectCraft Project", &["ecproj"]).pick_file().map(|p| p.to_string_lossy().to_string())));
if let Some(port) = control_port {
disable_app_nap();
let rx = control_server::start(port, cc.egui_ctx.clone());
app = app.with_control(rx);
}
@@ -91,3 +92,17 @@ fn agent_event_loop(agent: bool) -> Option<eframe::EventLoopBuilderHook> {
let _ = agent;
None
}
/// Agents drive the app while its window is covered or on another Space. macOS App Nap would
/// throttle the event loop then, stalling the control channel; opt out for `--control` runs.
fn disable_app_nap() {
#[cfg(target_os = "macos")]
{
use objc2_foundation::{NSActivityOptions, NSProcessInfo, NSString};
let info = NSProcessInfo::processInfo();
let reason = NSString::from_str("EffectCraft control channel");
let opts = NSActivityOptions::UserInitiatedAllowingIdleSystemSleep | NSActivityOptions::LatencyCritical;
// Leaked on purpose: the activity lasts for the life of the process.
std::mem::forget(info.beginActivityWithOptions_reason(opts, &reason));
}
}