mirror of
https://github.com/storytold/pdfcraft.git
synced 2026-11-10 13:01:29 +00:00
This commit is contained in:
1 parent
e24780c7bd
commit
d4828fe541
3 files changed
+82
No files matched your search
@@ -64,6 +64,10 @@ windows = { version = "0.62", default-features = false, features = ["std", "UI_V
|
||||
# socket. `std` has no Unix sockets on Windows, and calling Winsock directly needs unsafe, which
|
||||
# our workspace forbids. Already in the lockfile through zbus; pinned exactly, review before bumping.
|
||||
uds_windows = "=1.2.1"
|
||||
# Full-resolution taskbar and Alt+Tab icon (`ICON_BIG`, issue #3818). Set both window icons
|
||||
# directly so eframe cannot replace ICON_BIG with a system-sized copy. Already in the tree
|
||||
# through eframe and covered by the workspace's winit patch.
|
||||
winit = { version = "0.30", default-features = false }
|
||||
|
||||
[build-dependencies]
|
||||
# Icon + VERSIONINFO for pdfcraft.exe; build.rs only uses it when targeting Windows.
|
||||
|
||||
@@ -340,7 +340,15 @@ fn native_options(integrated: bool, app_frame: bool, renderer: eframe::Renderer)
|
||||
.with_drag_and_drop(true)
|
||||
// Wayland app id: matches packaging/linux/ai.storyteller.pdfcraft.desktop.
|
||||
.with_app_id(APP_ID);
|
||||
// eframe replaces ICON_BIG with a system-sized icon on its first active frame.
|
||||
// An explicitly empty icon disables that setter (None selects eframe's default).
|
||||
// Windows installs both sizes directly through winit in app_creator instead.
|
||||
#[cfg(target_os = "windows")]
|
||||
{
|
||||
viewport = viewport.with_icon(egui::IconData::default());
|
||||
}
|
||||
// Dock, taskbar, Alt-Tab and launcher icon when running unbundled.
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
match eframe::icon_data::from_png_bytes(APP_ICON_PNG) {
|
||||
Ok(icon) => viewport = viewport.with_icon(icon),
|
||||
Err(e) => log::warn!("app icon: {e}"),
|
||||
@@ -391,6 +399,48 @@ fn native_wayland(_: &eframe::CreationContext<'_>) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
/// Decode `png` as a [`winit::window::Icon`] for the Windows taskbar and Alt+Tab (`ICON_BIG`).
|
||||
#[cfg(target_os = "windows")]
|
||||
fn taskbar_icon(png: &[u8]) -> Option<winit::window::Icon> {
|
||||
let icon = match eframe::icon_data::from_png_bytes(png) {
|
||||
Ok(icon) => icon,
|
||||
Err(e) => {
|
||||
log::warn!("taskbar icon: {e}");
|
||||
return None;
|
||||
}
|
||||
};
|
||||
match winit::window::Icon::from_rgba(icon.rgba, icon.width, icon.height) {
|
||||
Ok(icon) => Some(icon),
|
||||
Err(e) => {
|
||||
log::warn!("taskbar icon: {e}");
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Install the decoded [`winit::window::Icon`] from `png` via `set` when decoding succeeds.
|
||||
#[cfg(target_os = "windows")]
|
||||
fn install_taskbar_icon(png: &[u8], set: impl FnOnce(winit::window::Icon)) {
|
||||
if let Some(icon) = taskbar_icon(png) {
|
||||
set(icon);
|
||||
}
|
||||
}
|
||||
|
||||
/// Install both window icons before the first frame. eframe's icon setter is disabled in
|
||||
/// `native_options`, so it cannot replace the full-resolution taskbar/Alt+Tab icon (#3818).
|
||||
#[cfg(target_os = "windows")]
|
||||
fn set_taskbar_icon(window: &winit::window::Window) {
|
||||
use winit::platform::windows::{IconExtWindows as _, WindowExtWindows as _};
|
||||
install_taskbar_icon(APP_ICON_PNG, |icon| window.set_taskbar_icon(Some(icon)));
|
||||
// The title bar's icon: the small image drawn for this scale in the exe's own icon (build.rs).
|
||||
let side = (16.0 * window.scale_factor()).round().clamp(16.0, 256.0) as u32;
|
||||
match winit::window::Icon::from_resource(1, Some(winit::dpi::PhysicalSize::new(side, side))) {
|
||||
Ok(icon) => window.set_window_icon(Some(icon)),
|
||||
Err(e) => log::warn!("window icon: {e}"),
|
||||
}
|
||||
}
|
||||
|
||||
/// Build the [`eframe::AppCreator`] closure that initializes [`PdfCraftApp`] once the window and renderer are ready.
|
||||
fn app_creator<'a>(
|
||||
launch: Launch,
|
||||
started: Rc<Cell<bool>>,
|
||||
@@ -418,6 +468,9 @@ fn app_creator<'a>(
|
||||
// it is set to On or Off.
|
||||
#[cfg(target_os = "windows")]
|
||||
{
|
||||
if let Some(window) = cc.winit_window() {
|
||||
set_taskbar_icon(window);
|
||||
}
|
||||
app.motion.source = Some(motion::source());
|
||||
}
|
||||
app.set_startup_update_check(true);
|
||||
|
||||
@@ -137,6 +137,31 @@ fn the_desktop_frame_is_turned_off_only_when_the_app_draws_one() {
|
||||
assert_eq!(native_options(false, true, eframe::Renderer::Glow).viewport.decorations, Some(false));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn the_window_and_windows_taskbar_icons_load_from_the_bundled_png() {
|
||||
let icon = eframe::icon_data::from_png_bytes(super::APP_ICON_PNG).expect("the bundled PNG decodes as the window icon");
|
||||
assert!(icon.width > 0 && icon.height > 0);
|
||||
assert_eq!(icon.rgba.len(), (icon.width as usize) * (icon.height as usize) * 4);
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
assert_eq!(super::native_options(false, false, eframe::Renderer::Glow).viewport.icon.as_deref(), Some(&icon));
|
||||
#[cfg(target_os = "windows")]
|
||||
{
|
||||
// None would load eframe's default icon; only the explicit empty sentinel prevents
|
||||
// its first-frame setter from overwriting our full-resolution ICON_BIG.
|
||||
for renderer in [eframe::Renderer::Glow, eframe::Renderer::Wgpu] {
|
||||
let viewport = super::native_options(false, false, renderer).viewport;
|
||||
assert_eq!(viewport.icon.as_deref(), Some(&egui::IconData::default()));
|
||||
}
|
||||
assert_eq!((icon.width, icon.height), (256, 256));
|
||||
let mut installed = None;
|
||||
super::install_taskbar_icon(super::APP_ICON_PNG, |icon| installed = Some(icon));
|
||||
assert!(installed.is_some(), "issue #3818: ICON_BIG loads and installs from APP_ICON_PNG");
|
||||
let mut bad = None;
|
||||
super::install_taskbar_icon(b"not a png", |icon| bad = Some(icon));
|
||||
assert!(bad.is_none());
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_software_renderer_is_shown_to_the_user() {
|
||||
use eframe::wgpu::DeviceType;
|
||||
|
||||
Reference in new issue
Block a user