refactor(bar): app widget and icon caching

PR #1439 authored and submitted by @JustForFun88

I understand this PR combines two areas of work — refactoring the
Applications widget and introducing a new icon caching system —
which would ideally be submitted separately.

Originally, I only intended to reduce allocations and simplify icon
loading in `applications.rs`, but as I worked through it, it became
clear that a more general-purpose caching system was needed. One
improvement led to another ... 😄

Apologies for bundling these changes together. If needed, I’m happy to
split this PR into smaller, focused ones.

Key Changes

- Introduced `IconsCache` with unified in-memory image & texture
  management.
- Added `ImageIcon` and `ImageIconId` (based on path or HWND) for
  caching and reuse.
- `Icon::Image` now wraps `ImageIcon`, decoupled from direct `RgbaImage`
  usage.
- Extracted app launch logic into `UserCommand` with built-in cooldown.
- Simplified config parsing and UI hover rendering in `App`.
- Replaced legacy `ICON_CACHE` in
  `KomorebiNotificationStateContainerInformation`
  → Now uses the shared `ImageIcon::try_load(hwnd, ..)` with caching and fallback.

Motivation

- Reduce redundant image copies and avoid repeated pixel-to-texture
  conversions.
- Cleanly separate concerns for launching and icon handling.
- Reuse icons across `Applications`, Komorebi windows, and potentially
  more in the future.

Tested

- Works on Windows 11.
- Verified path/exe/HWND icon loading and fallback.
This commit is contained in:
JustForFun88
2025-05-15 18:17:27 -07:00
committed by LGUG2Z
parent ce59bd9ae4
commit 3019eaf89c
4 changed files with 317 additions and 165 deletions
-7
View File
@@ -15,12 +15,10 @@ use eframe::egui::ViewportBuilder;
use font_loader::system_fonts;
use hotwatch::EventKind;
use hotwatch::Hotwatch;
use image::RgbaImage;
use komorebi_client::replace_env_in_path;
use komorebi_client::PathExt;
use komorebi_client::SocketMessage;
use komorebi_client::SubscribeOptions;
use std::collections::HashMap;
use std::io::BufReader;
use std::io::Read;
use std::path::PathBuf;
@@ -28,8 +26,6 @@ use std::sync::atomic::AtomicI32;
use std::sync::atomic::AtomicU32;
use std::sync::atomic::AtomicUsize;
use std::sync::atomic::Ordering;
use std::sync::LazyLock;
use std::sync::Mutex;
use std::time::Duration;
use tracing_subscriber::EnvFilter;
use windows::Win32::Foundation::HWND;
@@ -53,9 +49,6 @@ pub static DEFAULT_PADDING: f32 = 10.0;
pub static AUTO_SELECT_FILL_COLOUR: AtomicU32 = AtomicU32::new(0);
pub static AUTO_SELECT_TEXT_COLOUR: AtomicU32 = AtomicU32::new(0);
pub static ICON_CACHE: LazyLock<Mutex<HashMap<isize, RgbaImage>>> =
LazyLock::new(|| Mutex::new(HashMap::new()));
#[derive(Parser)]
#[clap(author, about, version)]
struct Opts {