mirror of
https://github.com/ankitects/anki.git
synced 2025-09-18 14:02:21 -04:00
Fix icon/menu entries on macOS after update
We need to exec() Python from a GUI context so that the app name and icon are inherited from our launcher bundle. And we need to munge sys.argv[0] prior to main window instantiation so that we don't get app menu entries like "Hide -c". We do that in the launcher instead of __init__.py so that older versions display correctly too.
This commit is contained in:
parent
f5073b402a
commit
aa8dfe1cf4
2 changed files with 32 additions and 11 deletions
|
@ -6,7 +6,6 @@
|
|||
use std::io::stdin;
|
||||
use std::io::stdout;
|
||||
use std::io::Write;
|
||||
use std::os::unix::process::CommandExt;
|
||||
use std::process::Command;
|
||||
use std::time::SystemTime;
|
||||
use std::time::UNIX_EPOCH;
|
||||
|
@ -25,8 +24,8 @@ use anyhow::Result;
|
|||
use crate::platform::ensure_terminal_shown;
|
||||
use crate::platform::get_exe_and_resources_dirs;
|
||||
use crate::platform::get_uv_binary_name;
|
||||
use crate::platform::launch_anki_after_update;
|
||||
use crate::platform::launch_anki_normally;
|
||||
use crate::platform::respawn_launcher;
|
||||
|
||||
mod platform;
|
||||
|
||||
|
@ -148,8 +147,8 @@ fn run() -> Result<()> {
|
|||
println!("\x1B[1mYou can close this window.\x1B[0m\n");
|
||||
}
|
||||
|
||||
let cmd = build_python_command(&state.uv_install_root, &[])?;
|
||||
launch_anki_after_update(cmd)?;
|
||||
// respawn the launcher as a disconnected subprocess for normal startup
|
||||
respawn_launcher()?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -493,7 +492,7 @@ fn build_python_command(uv_install_root: &std::path::Path, args: &[String]) -> R
|
|||
};
|
||||
|
||||
let mut cmd = Command::new(python_exe);
|
||||
cmd.args(["-c", "import aqt; aqt.run()"]);
|
||||
cmd.args(["-c", "import aqt, sys; sys.argv[0] = 'Anki'; aqt.run()"]);
|
||||
cmd.args(args);
|
||||
// tell the Python code it was invoked by the launcher, and updating is
|
||||
// available
|
||||
|
|
|
@ -49,10 +49,32 @@ pub fn get_uv_binary_name() -> &'static str {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn launch_anki_after_update(mut cmd: std::process::Command) -> Result<()> {
|
||||
pub fn respawn_launcher() -> Result<()> {
|
||||
use std::process::Stdio;
|
||||
|
||||
cmd.stdin(Stdio::null())
|
||||
let mut launcher_cmd = if cfg!(target_os = "macos") {
|
||||
// On macOS, we need to launch the .app bundle, not the executable directly
|
||||
let current_exe =
|
||||
std::env::current_exe().context("Failed to get current executable path")?;
|
||||
|
||||
// Navigate from Contents/MacOS/launcher to the .app bundle
|
||||
let app_bundle = current_exe
|
||||
.parent() // MacOS
|
||||
.and_then(|p| p.parent()) // Contents
|
||||
.and_then(|p| p.parent()) // .app
|
||||
.context("Failed to find .app bundle")?;
|
||||
|
||||
let mut cmd = std::process::Command::new("open");
|
||||
cmd.arg(app_bundle);
|
||||
cmd
|
||||
} else {
|
||||
let current_exe =
|
||||
std::env::current_exe().context("Failed to get current executable path")?;
|
||||
std::process::Command::new(current_exe)
|
||||
};
|
||||
|
||||
launcher_cmd
|
||||
.stdin(Stdio::null())
|
||||
.stdout(Stdio::null())
|
||||
.stderr(Stdio::null());
|
||||
|
||||
|
@ -61,16 +83,16 @@ pub fn launch_anki_after_update(mut cmd: std::process::Command) -> Result<()> {
|
|||
use std::os::windows::process::CommandExt;
|
||||
const CREATE_NEW_PROCESS_GROUP: u32 = 0x00000200;
|
||||
const DETACHED_PROCESS: u32 = 0x00000008;
|
||||
cmd.creation_flags(CREATE_NEW_PROCESS_GROUP | DETACHED_PROCESS);
|
||||
launcher_cmd.creation_flags(CREATE_NEW_PROCESS_GROUP | DETACHED_PROCESS);
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
#[cfg(all(unix, not(target_os = "macos")))]
|
||||
{
|
||||
use std::os::unix::process::CommandExt;
|
||||
cmd.process_group(0);
|
||||
launcher_cmd.process_group(0);
|
||||
}
|
||||
|
||||
let child = cmd.ensure_spawn()?;
|
||||
let child = launcher_cmd.ensure_spawn()?;
|
||||
std::mem::forget(child);
|
||||
|
||||
Ok(())
|
||||
|
|
Loading…
Reference in a new issue