mirror of
https://github.com/ankitects/anki.git
synced 2025-09-18 14:02:21 -04:00
parent
6eb1db0f5d
commit
469fd763c7
7 changed files with 61 additions and 17 deletions
7
Cargo.lock
generated
7
Cargo.lock
generated
|
@ -3548,6 +3548,7 @@ dependencies = [
|
||||||
"embed-resource",
|
"embed-resource",
|
||||||
"libc",
|
"libc",
|
||||||
"libc-stdhandle",
|
"libc-stdhandle",
|
||||||
|
"widestring",
|
||||||
"windows 0.61.3",
|
"windows 0.61.3",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -7375,6 +7376,12 @@ dependencies = [
|
||||||
"winsafe",
|
"winsafe",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "widestring"
|
||||||
|
version = "1.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "dd7cf3379ca1aac9eea11fba24fd7e315d621f8dfe35c8d7d2be8b793726e07d"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winapi"
|
name = "winapi"
|
||||||
version = "0.3.9"
|
version = "0.3.9"
|
||||||
|
|
|
@ -138,8 +138,9 @@ unic-ucd-category = "0.9.0"
|
||||||
unicode-normalization = "0.1.24"
|
unicode-normalization = "0.1.24"
|
||||||
walkdir = "2.5.0"
|
walkdir = "2.5.0"
|
||||||
which = "8.0.0"
|
which = "8.0.0"
|
||||||
|
widestring = "1.1.0"
|
||||||
winapi = { version = "0.3", features = ["wincon", "winreg"] }
|
winapi = { version = "0.3", features = ["wincon", "winreg"] }
|
||||||
windows = { version = "0.61.3", features = ["Media_SpeechSynthesis", "Media_Core", "Foundation_Collections", "Storage_Streams", "Win32_System_Console", "Win32_System_Registry", "Win32_Foundation"] }
|
windows = { version = "0.61.3", features = ["Media_SpeechSynthesis", "Media_Core", "Foundation_Collections", "Storage_Streams", "Win32_System_Console", "Win32_System_Registry", "Win32_Foundation", "Win32_UI_Shell"] }
|
||||||
wiremock = "0.6.3"
|
wiremock = "0.6.3"
|
||||||
xz2 = "0.1.7"
|
xz2 = "0.1.7"
|
||||||
zip = { version = "4.1.0", default-features = false, features = ["deflate", "time"] }
|
zip = { version = "4.1.0", default-features = false, features = ["deflate", "time"] }
|
||||||
|
|
|
@ -42,6 +42,11 @@ if "--syncserver" in sys.argv:
|
||||||
# does not return
|
# does not return
|
||||||
run_sync_server()
|
run_sync_server()
|
||||||
|
|
||||||
|
if sys.platform == "win32":
|
||||||
|
from win32com.shell import shell
|
||||||
|
|
||||||
|
shell.SetCurrentProcessExplicitAppUserModelID("Ankitects.Anki")
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
import builtins
|
import builtins
|
||||||
import cProfile
|
import cProfile
|
||||||
|
|
|
@ -1719,11 +1719,37 @@ title="{}" {}>{}</button>""".format(
|
||||||
self.maybeHideAccelerators()
|
self.maybeHideAccelerators()
|
||||||
self.hideStatusTips()
|
self.hideStatusTips()
|
||||||
elif is_win:
|
elif is_win:
|
||||||
# make sure ctypes is bundled
|
self._setupWin32()
|
||||||
from ctypes import windll, wintypes # type: ignore
|
|
||||||
|
|
||||||
_dummy1 = windll
|
def _setupWin32(self):
|
||||||
_dummy2 = wintypes
|
"""Fix taskbar display/pinning"""
|
||||||
|
if sys.platform != "win32":
|
||||||
|
return
|
||||||
|
|
||||||
|
launcher_path = os.environ.get("ANKI_LAUNCHER")
|
||||||
|
if not launcher_path:
|
||||||
|
return
|
||||||
|
|
||||||
|
from win32com.propsys import propsys, pscon
|
||||||
|
from win32com.propsys.propsys import PROPVARIANTType
|
||||||
|
|
||||||
|
hwnd = int(self.winId())
|
||||||
|
prop_store = propsys.SHGetPropertyStoreForWindow(hwnd) # type: ignore[call-arg]
|
||||||
|
prop_store.SetValue(
|
||||||
|
pscon.PKEY_AppUserModel_ID, PROPVARIANTType("Ankitects.Anki")
|
||||||
|
)
|
||||||
|
prop_store.SetValue(
|
||||||
|
pscon.PKEY_AppUserModel_RelaunchCommand,
|
||||||
|
PROPVARIANTType(f'"{launcher_path}"'),
|
||||||
|
)
|
||||||
|
prop_store.SetValue(
|
||||||
|
pscon.PKEY_AppUserModel_RelaunchDisplayNameResource, PROPVARIANTType("Anki")
|
||||||
|
)
|
||||||
|
prop_store.SetValue(
|
||||||
|
pscon.PKEY_AppUserModel_RelaunchIconResource,
|
||||||
|
PROPVARIANTType(f"{launcher_path},0"),
|
||||||
|
)
|
||||||
|
prop_store.Commit()
|
||||||
|
|
||||||
def maybeHideAccelerators(self, tgt: Any | None = None) -> None:
|
def maybeHideAccelerators(self, tgt: Any | None = None) -> None:
|
||||||
if not self.hideMenuAccels:
|
if not self.hideMenuAccels:
|
||||||
|
|
|
@ -16,6 +16,7 @@ dirs.workspace = true
|
||||||
|
|
||||||
[target.'cfg(windows)'.dependencies]
|
[target.'cfg(windows)'.dependencies]
|
||||||
windows.workspace = true
|
windows.workspace = true
|
||||||
|
widestring.workspace = true
|
||||||
libc.workspace = true
|
libc.workspace = true
|
||||||
libc-stdhandle.workspace = true
|
libc-stdhandle.workspace = true
|
||||||
|
|
||||||
|
|
|
@ -101,7 +101,7 @@ pub fn respawn_launcher() -> Result<()> {
|
||||||
pub fn launch_anki_normally(mut cmd: std::process::Command) -> Result<()> {
|
pub fn launch_anki_normally(mut cmd: std::process::Command) -> Result<()> {
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
{
|
{
|
||||||
crate::platform::windows::attach_to_parent_console();
|
crate::platform::windows::prepare_to_launch_normally();
|
||||||
cmd.ensure_success()?;
|
cmd.ensure_success()?;
|
||||||
}
|
}
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
|
|
|
@ -1,15 +1,13 @@
|
||||||
// Copyright: Ankitects Pty Ltd and contributors
|
// Copyright: Ankitects Pty Ltd and contributors
|
||||||
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
|
|
||||||
use std::ffi::OsStr;
|
|
||||||
use std::io::stdin;
|
use std::io::stdin;
|
||||||
use std::os::windows::ffi::OsStrExt;
|
|
||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
|
|
||||||
use anyhow::Context;
|
use anyhow::Context;
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
|
use widestring::u16cstr;
|
||||||
use windows::core::PCWSTR;
|
use windows::core::PCWSTR;
|
||||||
use windows::Win32::System::Registry::HKEY_CURRENT_USER;
|
|
||||||
use windows::Win32::System::Console::AttachConsole;
|
use windows::Win32::System::Console::AttachConsole;
|
||||||
use windows::Win32::System::Console::GetConsoleWindow;
|
use windows::Win32::System::Console::GetConsoleWindow;
|
||||||
use windows::Win32::System::Console::ATTACH_PARENT_PROCESS;
|
use windows::Win32::System::Console::ATTACH_PARENT_PROCESS;
|
||||||
|
@ -17,8 +15,10 @@ use windows::Win32::System::Registry::RegCloseKey;
|
||||||
use windows::Win32::System::Registry::RegOpenKeyExW;
|
use windows::Win32::System::Registry::RegOpenKeyExW;
|
||||||
use windows::Win32::System::Registry::RegQueryValueExW;
|
use windows::Win32::System::Registry::RegQueryValueExW;
|
||||||
use windows::Win32::System::Registry::HKEY;
|
use windows::Win32::System::Registry::HKEY;
|
||||||
|
use windows::Win32::System::Registry::HKEY_CURRENT_USER;
|
||||||
use windows::Win32::System::Registry::KEY_READ;
|
use windows::Win32::System::Registry::KEY_READ;
|
||||||
use windows::Win32::System::Registry::REG_SZ;
|
use windows::Win32::System::Registry::REG_SZ;
|
||||||
|
use windows::Win32::UI::Shell::SetCurrentProcessExplicitAppUserModelID;
|
||||||
|
|
||||||
pub fn ensure_terminal_shown() -> Result<()> {
|
pub fn ensure_terminal_shown() -> Result<()> {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -146,10 +146,7 @@ fn read_registry_install_dir() -> Option<std::path::PathBuf> {
|
||||||
let mut hkey = HKEY::default();
|
let mut hkey = HKEY::default();
|
||||||
|
|
||||||
// Convert the registry path to wide string
|
// Convert the registry path to wide string
|
||||||
let subkey: Vec<u16> = OsStr::new("SOFTWARE\\Anki")
|
let subkey = u16cstr!("SOFTWARE\\Anki");
|
||||||
.encode_wide()
|
|
||||||
.chain(std::iter::once(0))
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
// Open the registry key
|
// Open the registry key
|
||||||
let result = RegOpenKeyExW(
|
let result = RegOpenKeyExW(
|
||||||
|
@ -165,10 +162,7 @@ fn read_registry_install_dir() -> Option<std::path::PathBuf> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Query the Install_Dir64 value
|
// Query the Install_Dir64 value
|
||||||
let value_name: Vec<u16> = OsStr::new("Install_Dir64")
|
let value_name = u16cstr!("Install_Dir64");
|
||||||
.encode_wide()
|
|
||||||
.chain(std::iter::once(0))
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
let mut value_type = REG_SZ;
|
let mut value_type = REG_SZ;
|
||||||
let mut data_size = 0u32;
|
let mut data_size = 0u32;
|
||||||
|
@ -211,3 +205,13 @@ fn read_registry_install_dir() -> Option<std::path::PathBuf> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn prepare_to_launch_normally() {
|
||||||
|
// Set the App User Model ID for Windows taskbar grouping
|
||||||
|
unsafe {
|
||||||
|
let _ =
|
||||||
|
SetCurrentProcessExplicitAppUserModelID(PCWSTR(u16cstr!("Ankitects.Anki").as_ptr()));
|
||||||
|
}
|
||||||
|
|
||||||
|
attach_to_parent_console();
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue