Part of #92, for `benilla-ui`, `benilla-world` and `benilla-formats`. - 88 string literals drop private record and bug numbers, the dates of private incidents, and the workspace's name for the maintainer. They are assert and panic texts, log and printout lines, the `--` comments of the Lua prelude and of test fixtures, and one Lua assert. Each keeps its fact in its own words. - Two test names lose their numbers: `burning_steppes_lava_builds_a_magma_surface_at_the_reported_pin` and `join_channel_by_name_answers_the_row_custom_and_nil_legs`. - A test-only event, `B271_PROBE`, is now `ERROR_PROBE` in the two crates that register and fire it. A fixture's error text in `benilla-app`'s `ui_script` tests drops its bug number, together with the assertion that reads it. - Doc comments that named a client function by a disassembler's label (`FUN_0068a830`) now give its address, in `benilla-formats`, `benilla-assets` and one `benilla-app` file. - Every literal change keeps each literal's line count, proven with comments stripped and every literal masked. The two renamed tests differ only in their names. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
67 lines
2.6 KiB
Rust
67 lines
2.6 KiB
Rust
//! macOS `Cmd+Q`, re-pointed at the window close so quitting saves the session. winit's default
|
|
//! menu wires Quit to AppKit's `terminate:`, which tears the app down with no `app.update()`, so no
|
|
//! `AppExit` is read and the `Last` shutdown systems never run; bevy_winit 0.18 exposes no way to
|
|
//! turn that menu off. Re-pointed at `performClose:`, Quit becomes the window close, which Bevy
|
|
//! carries through `AppExit` to the shutdown systems. A no-op off macOS.
|
|
|
|
use bevy::prelude::*;
|
|
|
|
/// Re-points the Quit menu item at `Startup`, which runs inside the event loop, after winit built
|
|
/// its menu in `applicationDidFinishLaunching`.
|
|
pub struct MacQuitPlugin;
|
|
|
|
impl Plugin for MacQuitPlugin {
|
|
fn build(&self, app: &mut App) {
|
|
app.add_systems(Startup, route_quit_through_window_close);
|
|
}
|
|
}
|
|
|
|
#[cfg(not(target_os = "macos"))]
|
|
fn route_quit_through_window_close() {}
|
|
|
|
/// The `NonSendMarker` pins the system to the main thread, as AppKit requires.
|
|
#[cfg(target_os = "macos")]
|
|
fn route_quit_through_window_close(_main_thread: bevy::ecs::system::NonSendMarker) {
|
|
use objc2::sel;
|
|
use objc2_app_kit::NSApplication;
|
|
use objc2_foundation::MainThreadMarker;
|
|
|
|
let Some(mtm) = MainThreadMarker::new() else {
|
|
return;
|
|
};
|
|
let app = NSApplication::sharedApplication(mtm);
|
|
// SAFETY: main-thread AppKit reads of the app's own menu tree and property writes on the items
|
|
// found there, each call with its documented signature.
|
|
let rerouted = unsafe {
|
|
let Some(main_menu) = app.mainMenu() else {
|
|
// No default menu (a bundled build's own, or `default_menu` off): nothing to re-point.
|
|
return;
|
|
};
|
|
let mut rerouted = 0usize;
|
|
for item in main_menu.itemArray().iter() {
|
|
let Some(submenu) = item.submenu() else {
|
|
continue;
|
|
};
|
|
for entry in submenu.itemArray().iter() {
|
|
if entry.action() != Some(sel!(terminate:)) {
|
|
continue;
|
|
}
|
|
entry.setTarget(None); // nil: down the responder chain to the key window
|
|
entry.setAction(Some(sel!(performClose:)));
|
|
rerouted += 1;
|
|
}
|
|
}
|
|
rerouted
|
|
};
|
|
// Warn when nothing was found: a winit change that moves the item would otherwise silently
|
|
// bring back the quit that skips the shutdown systems.
|
|
if rerouted == 0 {
|
|
warn!(
|
|
"mac_quit: no Quit item bound to terminate: — Cmd+Q may bypass the shutdown tail \
|
|
and lose this session's settings"
|
|
);
|
|
} else {
|
|
info!("mac_quit: Cmd+Q routed through the window close ({rerouted} item(s))");
|
|
}
|
|
}
|