//! TRACES: FR-PLAT-WIN-2 //! The Windows resource block: icon and version, compiled into the executable. //! //! Windows takes an application's icon and its "Details" tab from a resource //! inside the `.exe`, not from a `.desktop` file, so without this the installed //! program shows the generic executable icon in Explorer, the Start Menu and //! the taskbar, and reports no version. Nothing here runs for any other //! target: the whole body is behind the target-OS check, and the crate that //! does the work is a build-dependency only. //! //! The icon is the same PNG every other platform uses, wrapped into an `.ico` //! in `OUT_DIR` rather than committed: an ICO entry may *be* a PNG (Vista and //! later read them directly), so the wrapper is a 22-byte header and the //! file's bytes, and a generated binary stays out of the tree. use std::io::Write as _; use std::path::PathBuf; fn main() { println!("cargo:rerun-if-changed=build.rs"); if std::env::var("CARGO_CFG_TARGET_OS").as_deref() != Ok("windows") { return; } let png = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("../../ui/dr-ui/ui/app-icon.png"); println!("cargo:rerun-if-changed={}", png.display()); let bytes = std::fs::read(&png).expect("read app-icon.png"); let ico = PathBuf::from(std::env::var("OUT_DIR").unwrap()).join("darkroom.ico"); write_png_ico(&ico, &bytes, 256).expect("write darkroom.ico"); let mut res = winresource::WindowsResource::new(); res.set_icon(ico.to_str().unwrap()); res.set("ProductName", "DarkRoom"); res.set("FileDescription", "DarkRoom"); res.set("LegalCopyright", "GPL-3.0-or-later"); // Cross-compiling: `winresource` looks for a `windres` for the target and // the Windows image names it explicitly, for the same reason the Android // image names its linkers. if let Ok(windres) = std::env::var("WINDRES") { res.set_windres_path(&windres); } res.compile().expect("compile the Windows resource block"); } /// One PNG image as an `.ico`. `edge` is the PNG's width and height; 256 is /// written as 0 per the format. fn write_png_ico(path: &std::path::Path, png: &[u8], edge: u32) -> std::io::Result<()> { let mut f = std::fs::File::create(path)?; let dim = if edge >= 256 { 0u8 } else { edge as u8 }; // ICONDIR: reserved, type 1 (icon), one image. f.write_all(&[0, 0, 1, 0, 1, 0])?; // ICONDIRENTRY: width, height, palette 0, reserved, planes 1, bpp 32, // byte length, offset (6 + 16). f.write_all(&[dim, dim, 0, 0, 1, 0, 32, 0])?; f.write_all(&(png.len() as u32).to_le_bytes())?; f.write_all(&22u32.to_le_bytes())?; f.write_all(png) }