Skip to content

Comments

Improve Windows app logo quality#949

Merged
richiemcilroy merged 4 commits intomainfrom
improve-window-app-logo-quality-on-windows
Oct 1, 2025
Merged

Improve Windows app logo quality#949
richiemcilroy merged 4 commits intomainfrom
improve-window-app-logo-quality-on-windows

Conversation

@oscartbeaumont
Copy link
Contributor

@oscartbeaumont oscartbeaumont commented Aug 26, 2025

This needs more testing because I am concerned it's going to slow down the logo collection process again but I think it'll be alright.

Summary by CodeRabbit

  • New Features

    • Sharper, higher-resolution app icons on Windows (better selection up to 512 px) via multi-path high-res extraction.
    • Broader handling of icon sources (shell and executables) for clearer icons across the UI.
  • Bug Fixes

    • More reliable icon loading with ordered fallbacks, reducing missing or low-quality icons.
    • Improved size detection to avoid returning undersized icons.
  • Chores

    • Enabled additional Windows platform capabilities to support new extraction paths.

@oscartbeaumont oscartbeaumont changed the title Improve windows app logo quality Improve Windows app logo quality Aug 26, 2025
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Aug 26, 2025

Walkthrough

Added multi-path, high-resolution Windows icon extraction in win.rs: new private helpers for shell and executable icon enumeration, larger size threshold, expanded HICON→PNG sizing strategy, and reordered fallbacks. Also enabled additional WinRT graphics features in scap-targets/Cargo.toml. Public API unchanged.

Changes

Cohort / File(s) Summary
Windows icon extraction flow and helpers
crates/scap-targets/src/platform/win.rs
- Added imports for shell/icon APIs (SHGetFileInfoW, SHFILEINFOW, SHGFI_*, PrivateExtractIconsW, etc.)
- Increased GOOD_SIZE_THRESHOLD 64→256
- Reworked app_icon to try high-res shell and executable icon extraction before fallbacks; introduced multi-step Methods 1–6 with reordered fallback semantics
- Added private helpers: extract_shell_icon_high_res and extract_executable_icons_high_res (use SHGetFileInfoW, ExtractIconExW/PrivateExtractIconsW, convert HICON→PNG and select best)
- Expanded hicon_to_png_bytes_optimized target sizes and updated fallback ordering to prefer high-res outputs
Cargo feature flags (Windows target)
crates/scap-targets/Cargo.toml
- Added windows crate features: "Win32_System_WinRT", "Win32_System_WinRT_Graphics", and "Win32_System_WinRT_Graphics_Capture" under Windows target dependencies

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant W as WindowImpl::app_icon
  participant S as Shell (SHGetFileInfoW)
  participant E as Executable (ExtractIconExW / PrivateExtractIconsW)
  participant R as Renderer (hicon_to_png)
  participant F as Legacy Fallbacks

  rect rgba(200,230,255,0.25)
  note over W,S: Method 1 — Shell high-res attempt
  W->>S: SHGetFileInfoW (large/small)
  S-->>W: HICON (maybe)
  alt HICON returned
    W->>R: Convert HICON→PNG (high-res sizes)
    R-->>W: PNG (accept if >= threshold)
  end
  end

  rect rgba(200,255,200,0.25)
  note over W,E: Method 2 — Executable icon enumeration
  W->>E: ExtractIconExW / PrivateExtractIconsW (enumerate sizes)
  E-->>W: HICON list
  loop evaluate icons
    W->>R: Convert candidate HICON→PNG
    R-->>W: PNG (measure/choose best)
  end
  end

  rect rgba(255,245,200,0.25)
  note over W,F: Methods 3–6 — Prior fallback paths
  W->>F: Try legacy large/default icon extraction
  F-->>W: HICON/PNG if available
  end

  opt No satisfactory icon
    W-->>W: Return best available PNG or None
  end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Poem

I hopped through DLL and shell-lit trails,
Chased icons big enough to fill my pails.
I pulled high-res from EXE and shell,
Sized them up until one fit well.
A rabbit’s nibble made a PNG tale. 🐰✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title “Improve Windows app logo quality” succinctly and accurately reflects the primary change of enhancing high-resolution icon extraction on Windows without extraneous detail, clearly communicating the main purpose of the pull request.
✨ Finishing touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch improve-window-app-logo-quality-on-windows

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@vercel
Copy link
Contributor

vercel bot commented Sep 24, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Preview Comments Updated (UTC)
cap-web Ready Ready Preview Comment Sep 24, 2025 7:51am

@oscartbeaumont oscartbeaumont marked this pull request as ready for review September 24, 2025 07:56
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 7

🧹 Nitpick comments (2)
crates/scap-targets/src/platform/win.rs (2)

566-607: Drop the redundant “Method 4” block.

This re-implements a subset of extract_executable_icons_high_res logic (index 0 only), duplicating work and increasing latency.

Apply this diff to remove the duplicate block:

-            // Method 4: Try executable file extraction (fallback to original method)
-            if let Some(exe_path) = self.get_executable_path() {
-                let wide_path: Vec<u16> =
-                    exe_path.encode_utf16().chain(std::iter::once(0)).collect();
-
-                let mut large_icon: HICON = HICON::default();
-                let mut small_icon: HICON = HICON::default();
-
-                let extracted = ExtractIconExW(
-                    PCWSTR(wide_path.as_ptr()),
-                    0, // Only try the first (main) icon
-                    Some(&mut large_icon),
-                    Some(&mut small_icon),
-                    1,
-                );
-
-                if extracted > 0 {
-                    // Try large icon first
-                    if !large_icon.is_invalid() {
-                        if let Some(result) = self.hicon_to_png_bytes_optimized(large_icon) {
-                            let _ = DestroyIcon(large_icon);
-                            if !small_icon.is_invalid() {
-                                let _ = DestroyIcon(small_icon);
-                            }
-                            // Return immediately if we got a good quality icon
-                            if result.1 >= GOOD_SIZE_THRESHOLD {
-                                return Some(result.0);
-                            }
-                        }
-                        let _ = DestroyIcon(large_icon);
-                    }
-
-                    // Try small icon as fallback
-                    if !small_icon.is_invalid() {
-                        if let Some(result) = self.hicon_to_png_bytes_optimized(small_icon) {
-                            let _ = DestroyIcon(small_icon);
-                            return Some(result.0);
-                        }
-                        let _ = DestroyIcon(small_icon);
-                    }
-                }
-            }

816-835: Don’t try upscaling first; attempt native size before larger targets.

This reduces work and avoids returning upscaled bitmaps when higher-res isn’t available.

Apply this diff:

-            let target_sizes = if let Some((width, height)) = native_size {
-                let native_dim = width.max(height);
-                if native_dim >= 512 {
-                    vec![native_dim, 512, 256, 128] // Ultra high-res icon
-                } else if native_dim >= 256 {
-                    vec![512, native_dim, 256, 128] // Try upscaling first, then native
-                } else if native_dim >= 128 {
-                    vec![512, 256, native_dim, 128] // Try higher res first
-                } else if native_dim >= 64 {
-                    vec![256, 128, native_dim, 64] // Medium-res icon
-                } else if native_dim >= 32 {
-                    vec![128, 64, native_dim, 32] // Standard icon
-                } else {
-                    vec![64, 32, 16] // Small icon, try reasonable sizes
-                }
-            } else {
-                // No native size info, try high-res defaults first
-                vec![512, 256, 128, 64, 32, 16]
-            };
+            let target_sizes = if let Some((width, height)) = native_size {
+                let native_dim = width.max(height);
+                if native_dim >= 512 {
+                    vec![native_dim, 256, 128, 64, 32, 16]
+                } else if native_dim >= 256 {
+                    vec![native_dim, 256, 128, 64, 32, 16]
+                } else if native_dim >= 128 {
+                    vec![native_dim, 128, 64, 32, 16]
+                } else if native_dim >= 64 {
+                    vec![native_dim, 64, 32, 16]
+                } else if native_dim >= 32 {
+                    vec![native_dim, 32, 16]
+                } else {
+                    vec![16]
+                }
+            } else {
+                vec![256, 128, 64, 32, 16]
+            };
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0720f67 and 92d464b.

📒 Files selected for processing (1)
  • crates/scap-targets/src/platform/win.rs (8 hunks)
🧰 Additional context used
📓 Path-based instructions (4)
crates/**/src/**/*.rs

📄 CodeRabbit inference engine (CLAUDE.md)

For desktop IPC, use tauri_specta derive/macros on Rust types/events; do not hand-roll bindings

Files:

  • crates/scap-targets/src/platform/win.rs
**/*.{ts,tsx,js,jsx,rs}

📄 CodeRabbit inference engine (CLAUDE.md)

Do not add inline, block, or docstring comments in any language; code must be self-explanatory

Files:

  • crates/scap-targets/src/platform/win.rs
**/*.rs

📄 CodeRabbit inference engine (AGENTS.md)

**/*.rs: Format Rust code using rustfmt and ensure all Rust code passes workspace-level clippy lints.
Rust modules should be named with snake_case, and crate directories should be in kebab-case.

Files:

  • crates/scap-targets/src/platform/win.rs
crates/*/src/**/*

📄 CodeRabbit inference engine (AGENTS.md)

Rust crates should place tests within the src/ and/or a sibling tests/ directory for each crate inside crates/*.

Files:

  • crates/scap-targets/src/platform/win.rs
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Analyze (rust)
🔇 Additional comments (2)
crates/scap-targets/src/platform/win.rs (2)

19-21: Imports look correct and necessary.

These are used by get_file_description and the new shell icon path.


34-37: Shell imports LGTM.

Needed for SHGetFileInfoW and ExtractIconExW paths.

}

// Method 3: Try small window icon as fallback
// Method 5: Try small window icon as fallback
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Remove added inline comment (“Method 5”).

Per repo guidelines, don’t add inline comments in Rust files.

-            // Method 5: Try small window icon as fallback
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// Method 5: Try small window icon as fallback
🤖 Prompt for AI Agents
In crates/scap-targets/src/platform/win.rs around line 609, there is an inline
comment "// Method 5: Try small window icon as fallback" which violates the repo
guideline prohibiting inline comments in Rust files; remove that comment line
(or move any necessary context to the surrounding function-level documentation
or commit message) so the code contains no inline comment at that location.

}

// Method 4: Try class icon as last resort
// Method 6: Try class icon as last resort
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Remove added inline comment (“Method 6”).

Per repo guidelines, don’t add inline comments in Rust files.

-            // Method 6: Try class icon as last resort
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// Method 6: Try class icon as last resort
🤖 Prompt for AI Agents
In crates/scap-targets/src/platform/win.rs around line 623, remove the newly
added inline comment text "Method 6: Try class icon as last resort" so the Rust
file contains no inline comment per repo guidelines; simply delete that comment
line (or convert it into a non-inline doc or external note if context must be
preserved) and ensure formatting/lints remain clean.

Switches from ExtractIconExW to PrivateExtractIconsW for better icon quality and size selection. Refactors icon extraction and conversion routines to prioritize higher resolution icons and optimize PNG output, improving reliability and visual fidelity.
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (5)
crates/scap-targets/src/platform/win.rs (5)

559-564: Critical: Use native HICON dimensions, not rendered draw size, as quality threshold.

Lines 561 and 592 compare result.1 (the rendered/requested draw size) against GOOD_SIZE_THRESHOLD. This accepts upscaled icons as high-quality. A 32×32 native icon rendered at 256×256 will pass the check, defeating the PR's quality goal.

Call get_icon_size(hicon) before conversion and compare the native dimension against the threshold instead.

             if large_icon.0 != 0 {
-                if let Some(result) = self.hicon_to_png_bytes_optimized(HICON(large_icon.0 as _)) {
-                    // If we got a good quality icon, return it immediately
-                    if result.1 >= GOOD_SIZE_THRESHOLD {
-                        return Some(result.0);
+                let hicon = HICON(large_icon.0 as _);
+                let native_dim = self.get_icon_size(hicon)
+                    .map(|(w, h)| w.max(h))
+                    .unwrap_or(0);
+                if let Some((bytes, _)) = self.hicon_to_png_bytes_optimized(hicon) {
+                    if native_dim >= GOOD_SIZE_THRESHOLD {
+                        return Some(bytes);
                     }
                 }
             }

Apply similar fixes to line 592 and the new extraction methods at lines 659, 725.

Also applies to: 586-594


536-536: Remove all inline comments per repository guidelines.

The repository's coding guidelines explicitly prohibit inline, block, or docstring comments in Rust files. The code must be self-explanatory. Remove all newly added comment lines including "Method 1" through "Method 6" annotations and other inline comments throughout the new extraction methods.

Based on coding guidelines.

Also applies to: 543-543, 550-550, 567-567, 610-610, 624-624, 640-640, 660-660


536-548: Cache get_executable_path() result to avoid repeated calls.

The method get_executable_path() is called three times (lines 537, 544, 568). Cache the result once and reuse it across all three extraction attempts.

Apply this diff:

-            // Method 1: Try shell icon extraction for highest quality
-            if let Some(exe_path) = self.get_executable_path() {
-                if let Some(icon_data) = self.extract_shell_icon_high_res(&exe_path, 512) {
+            let exe_path = self.get_executable_path();
+            if let Some(ref exe_path) = exe_path {
+                if let Some(icon_data) = self.extract_shell_icon_high_res(exe_path, 512) {
                     return Some(icon_data);
                 }
             }

-            // Method 2: Try executable file extraction with multiple icon sizes
-            if let Some(exe_path) = self.get_executable_path() {
-                if let Some(icon_data) = self.extract_executable_icons_high_res(&exe_path) {
+            if let Some(ref exe_path) = exe_path {
+                if let Some(icon_data) = self.extract_executable_icons_high_res(exe_path) {
                     return Some(icon_data);
                 }
             }

-            // Method 3: Try to get the window's large icon
+
             let large_icon = SendMessageW(
                 self.0,
                 WM_GETICON,
@@ -564,8 +562,7 @@
                 }
             }

-            // Method 4: Try executable file extraction (fallback to original method)
-            if let Some(exe_path) = self.get_executable_path() {
+            if let Some(ref exe_path) = exe_path {
                 let wide_path: Vec<u16> =
                     exe_path.encode_utf16().chain(std::iter::once(0)).collect();

Also applies to: 567-608


636-670: Critical: Double-destroy of HICON and quality proxy issue.

Two critical bugs in this method:

  1. Double-destroy: When conversion succeeds but the size check fails (line 659), the HICON is destroyed at line 658, then destroyed again at line 664, causing undefined behavior.

  2. Quality proxy: Line 659 checks result.1 (rendered draw size) instead of native HICON dimensions, accepting upscaled icons.

Apply this fix:

     fn extract_shell_icon_high_res(&self, exe_path: &str, target_size: i32) -> Option<Vec<u8>> {
         unsafe {
             let wide_path: Vec<u16> = exe_path.encode_utf16().chain(std::iter::once(0)).collect();

-            // Try different shell icon sizes
             let icon_flags = [
-                SHGFI_ICON | SHGFI_LARGEICON, // Large system icon
-                SHGFI_ICON | SHGFI_SMALLICON, // Small system icon as fallback
+                SHGFI_ICON | SHGFI_LARGEICON,
+                SHGFI_ICON | SHGFI_SMALLICON,
             ];

             for flags in icon_flags {
                 let mut file_info = SHFILEINFOW::default();
                 let result = SHGetFileInfoW(
                     windows::core::PCWSTR(wide_path.as_ptr()),
                     FILE_FLAGS_AND_ATTRIBUTES(0),
                     Some(&mut file_info),
                     std::mem::size_of::<SHFILEINFOW>() as u32,
                     flags,
                 );

                 if result != 0 && !file_info.hIcon.is_invalid() {
-                    if let Some(result) = self.hicon_to_png_bytes_optimized(file_info.hIcon) {
-                        let _ = DestroyIcon(file_info.hIcon);
-                        if result.1 >= target_size / 2 {
-                            // Accept if at least half target size
-                            return Some(result.0);
-                        }
-                    }
-                    let _ = DestroyIcon(file_info.hIcon);
+                    let hicon = file_info.hIcon;
+                    let native_dim = self.get_icon_size(hicon)
+                        .map(|(w, h)| w.max(h))
+                        .unwrap_or(0);
+                    let converted = self.hicon_to_png_bytes_optimized(hicon);
+                    let _ = DestroyIcon(hicon);
+                    if let Some((bytes, _)) = converted {
+                        if native_dim >= target_size / 2 {
+                            return Some(bytes);
+                        }
+                    }
                 }
             }

             None
         }
     }

672-735: Critical: Best icon selection uses rendered size instead of native dimensions.

Lines 721-725 track best_size using realized_size from the tuple (the rendered draw size), not the native HICON bitmap dimensions. This causes the method to select upscaled icons over genuinely high-resolution ones.

Use get_icon_size(icon_handle) to determine native dimensions for comparison and early-exit logic.

     fn extract_executable_icons_high_res(&self, exe_path: &str) -> Option<Vec<u8>> {
         unsafe {
             let wide_path: Vec<u16> = exe_path.encode_utf16().chain(std::iter::once(0)).collect();

             let mut path_buffer = [0u16; 260];
             let copy_len = wide_path.len().min(path_buffer.len());
             path_buffer[..copy_len].copy_from_slice(&wide_path[..copy_len]);

             let icon_count = ExtractIconExW(PCWSTR(wide_path.as_ptr()), -1, None, None, 0);

             let total_icons = if icon_count > 0 {
                 icon_count as usize
             } else {
                 1
             };

             let max_icons_to_try = total_icons.min(8);
             let size_candidates: [i32; 12] = [512, 400, 256, 192, 128, 96, 72, 64, 48, 32, 24, 16];

             let mut best_icon: Option<Vec<u8>> = None;
-            let mut best_size: i32 = 0;
+            let mut best_native: i32 = 0;

             for &size in &size_candidates {
                 for index in 0..max_icons_to_try {
                     let mut icon_slot = [HICON::default(); 1];

                     let extracted = PrivateExtractIconsW(
                         &path_buffer,
                         index as i32,
                         size,
                         size,
                         Some(&mut icon_slot),
                         None,
                         0,
                     );

                     if extracted == 0 {
                         continue;
                     }

                     let icon_handle = icon_slot[0];
                     if icon_handle.is_invalid() {
                         continue;
                     }

+                    let native_dim = self.get_icon_size(icon_handle)
+                        .map(|(w, h)| w.max(h))
+                        .unwrap_or(0);
                     let icon_result = self.hicon_to_png_bytes_optimized(icon_handle);
                     let _ = DestroyIcon(icon_handle);

-                    if let Some((png_data, realized_size)) = icon_result {
-                        if realized_size > best_size {
-                            best_size = realized_size;
+                    if let Some((png_data, _)) = icon_result {
+                        if native_dim > best_native {
+                            best_native = native_dim;
                             best_icon = Some(png_data);

-                            if best_size >= 256 {
+                            if best_native >= 256 {
                                 return best_icon;
                             }
                         }
                     }
                 }
             }

             best_icon
         }
     }
🧹 Nitpick comments (1)
crates/scap-targets/src/platform/win.rs (1)

796-856: Return native dimensions in tuple to fix quality proxy issue throughout codebase.

The method returns (Vec<u8>, i32) where the i32 is the requested/rendered draw size (line 845), not the native HICON bitmap dimensions. This propagates the quality proxy bug to all callers.

Consider returning (Vec<u8>, i32, i32) where the third element is the native dimension, or restructure to return a struct with named fields for clarity.

Example signature change:

fn hicon_to_png_bytes_optimized(&self, icon: HICON) -> Option<(Vec<u8>, i32, i32)> {
    // ...
    // return Some((png_data, requested_size, native_dim))
}

Then update all call sites to use the third element for quality checks.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 92d464b and ef54fc1.

📒 Files selected for processing (2)
  • crates/scap-targets/Cargo.toml (1 hunks)
  • crates/scap-targets/src/platform/win.rs (12 hunks)
🧰 Additional context used
📓 Path-based instructions (4)
crates/**/src/**/*.rs

📄 CodeRabbit inference engine (CLAUDE.md)

For desktop IPC, use tauri_specta derive/macros on Rust types/events; do not hand-roll bindings

Files:

  • crates/scap-targets/src/platform/win.rs
**/*.{ts,tsx,js,jsx,rs}

📄 CodeRabbit inference engine (CLAUDE.md)

Do not add inline, block, or docstring comments in any language; code must be self-explanatory

Files:

  • crates/scap-targets/src/platform/win.rs
**/*.rs

📄 CodeRabbit inference engine (AGENTS.md)

**/*.rs: Format Rust code using rustfmt and ensure all Rust code passes workspace-level clippy lints.
Rust modules should be named with snake_case, and crate directories should be in kebab-case.

Files:

  • crates/scap-targets/src/platform/win.rs
crates/*/src/**/*

📄 CodeRabbit inference engine (AGENTS.md)

Rust crates should place tests within the src/ and/or a sibling tests/ directory for each crate inside crates/*.

Files:

  • crates/scap-targets/src/platform/win.rs
🧬 Code graph analysis (1)
crates/scap-targets/src/platform/win.rs (1)
crates/recording/src/cursor.rs (3)
  • std (236-236)
  • std (266-266)
  • std (295-295)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: Clippy
  • GitHub Check: Build Desktop (x86_64-pc-windows-msvc, windows-latest)
  • GitHub Check: Build Desktop (aarch64-apple-darwin, macos-latest)
  • GitHub Check: Analyze (rust)
🔇 Additional comments (2)
crates/scap-targets/Cargo.toml (1)

27-29: LGTM — WinRT features added to support enhanced icon extraction.

The three new Windows features enable the richer Shell/FileInfo handling and graphics capabilities used by the updated icon extraction logic in win.rs.

crates/scap-targets/src/platform/win.rs (1)

19-21: LGTM — imports added for high-resolution icon extraction.

The new Shell and FileSystem imports support the multi-path icon extraction logic introduced in this PR.

Also applies to: 34-37, 44-46

@richiemcilroy richiemcilroy merged commit 78ef173 into main Oct 1, 2025
14 of 15 checks passed
@oscartbeaumont oscartbeaumont deleted the improve-window-app-logo-quality-on-windows branch October 2, 2025 02:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants