diff --git a/src/painter.rs b/src/painter.rs index 13994d9..5af3381 100644 --- a/src/painter.rs +++ b/src/painter.rs @@ -1,4 +1,7 @@ use crate::app::SwitchAppsState; +use crate::utils::RegKey; +use anyhow::Result; +use windows::core::w; use windows::Win32::Foundation::{COLORREF, RECT}; use windows::Win32::Graphics::Gdi::{ BeginPaint, BitBlt, CreateCompatibleBitmap, CreateCompatibleDC, CreateSolidBrush, DeleteDC, @@ -8,10 +11,14 @@ use windows::Win32::Graphics::Gdi::{ use windows::Win32::UI::WindowsAndMessaging::{DrawIconEx, DI_NORMAL}; use windows::Win32::{Foundation::HWND, Graphics::Gdi::GetDC}; -// window background color -pub const BG_COLOR: COLORREF = COLORREF(0x3b3b3b); -// selected icon box color -pub const FG_COLOR: COLORREF = COLORREF(0x4c4c4c); +// window background color in dark theme +pub const BG_DARK_COLOR: COLORREF = COLORREF(0x3b3b3b); +// selected icon box color in dark theme +pub const FG_DARK_COLOR: COLORREF = COLORREF(0x4c4c4c); +// window background color in light theme +pub const BG_LIGHT_COLOR: COLORREF = COLORREF(0xf2f2f2); +// selected icon box color in light theme +pub const FG_LIGHT_COLOR: COLORREF = COLORREF(0xe0e0e0); // minimum icon size pub const ICON_SIZE: i32 = 64; // window padding @@ -35,6 +42,9 @@ pub struct GdiAAPainter { size: i32, // scale scale: i32, + // color + fg_color: COLORREF, + bg_color: COLORREF, } impl GdiAAPainter { @@ -42,6 +52,17 @@ impl GdiAAPainter { /// /// The `scale` must be a multiple of 2, for example 2, 4, 6, 8, 12 ... pub fn new(hwnd: HWND, scale: i32) -> Self { + let light_theme = match is_light_theme() { + Ok(v) => v, + Err(_) => { + warn!("Fail to get system theme"); + false + } + }; + let (fg_color, bg_color) = match light_theme { + true => (FG_LIGHT_COLOR, BG_LIGHT_COLOR), + false => (FG_DARK_COLOR, BG_DARK_COLOR), + }; GdiAAPainter { mem_hdc: Default::default(), mem_map: Default::default(), @@ -52,6 +73,8 @@ impl GdiAAPainter { height: 0, size: 0, scale, + fg_color, + bg_color, } } @@ -86,7 +109,7 @@ impl GdiAAPainter { let mem_map = CreateCompatibleBitmap(hdc, width, height); SelectObject(mem_dc, mem_map); - let brush = CreateSolidBrush(BG_COLOR); + let brush = CreateSolidBrush(self.fg_color); let rect = RECT { left: 0, top: 0, @@ -164,7 +187,7 @@ impl GdiAAPainter { right: self.width * self.scale, bottom: self.width * self.scale, }; - FillRect(self.scaled_hdc, &rect as _, CreateSolidBrush(FG_COLOR)); + FillRect(self.scaled_hdc, &rect as _, CreateSolidBrush(self.fg_color)); let cy = (WINDOW_BORDER_SIZE + ICON_BORDER_SIZE) * self.scale; let brush_icon = HBRUSH::default(); @@ -183,7 +206,7 @@ impl GdiAAPainter { right, bottom, }; - FillRect(self.scaled_hdc, &rect as _, CreateSolidBrush(BG_COLOR)); + FillRect(self.scaled_hdc, &rect as _, CreateSolidBrush(self.bg_color)); } let cx = cy + item_size * (i as i32); @@ -202,3 +225,12 @@ impl GdiAAPainter { } } } + +fn is_light_theme() -> Result { + let reg_key = RegKey::new_hkcu( + w!("Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize"), + w!("SystemUsesLightTheme"), + )?; + let value = reg_key.get_int()?; + Ok(value == 1) +} diff --git a/src/utils/regedit.rs b/src/utils/regedit.rs index d3b1cab..c1d571c 100644 --- a/src/utils/regedit.rs +++ b/src/utils/regedit.rs @@ -3,7 +3,8 @@ use windows::core::PCWSTR; use windows::Win32::Foundation::ERROR_FILE_NOT_FOUND; use windows::Win32::System::Registry::{ RegCloseKey, RegDeleteValueW, RegGetValueW, RegOpenKeyExW, RegSetValueExW, HKEY, - HKEY_CURRENT_USER, KEY_ALL_ACCESS, REG_SZ, REG_VALUE_TYPE, RRF_RT_REG_SZ, + HKEY_CURRENT_USER, KEY_ALL_ACCESS, REG_DWORD_BIG_ENDIAN, REG_SZ, REG_VALUE_TYPE, + RRF_RT_REG_DWORD, RRF_RT_REG_SZ, }; #[derive(Debug)] @@ -57,6 +58,35 @@ impl RegKey { Ok(Some(buffer[..len].to_vec())) } + pub fn get_int(&self) -> Result { + let mut value: [u8; 4] = Default::default(); + let mut size: u32 = std::mem::size_of_val(&value) as u32; + let mut kind: REG_VALUE_TYPE = Default::default(); + let ret = unsafe { + RegGetValueW( + self.hkey, + None, + self.name, + RRF_RT_REG_DWORD, + Some(&mut kind), + Some(value.as_mut_ptr() as *mut _), + Some(&mut size), + ) + }; + if ret.is_err() { + bail!( + "Fail to get reg value, {:?}", + windows::core::Error::from(ret) + ); + } + let value = if kind == REG_DWORD_BIG_ENDIAN { + u32::from_be_bytes(value) + } else { + u32::from_le_bytes(value) + }; + Ok(value) + } + pub fn set_value(&self, value: &[u8]) -> Result<()> { unsafe { RegSetValueExW(self.hkey, self.name, 0, REG_SZ, Some(value)) } .ok()