Adopt windows-sys (#2057)
This commit is contained in:
parent
78e5a395da
commit
b222dde835
17 changed files with 1424 additions and 1239 deletions
|
|
@ -1,29 +1,35 @@
|
|||
/// This is a simple implementation of support for Windows Dark Mode,
|
||||
/// which is inspired by the solution in https://github.com/ysc3839/win32-darkmode
|
||||
use std::ffi::OsStr;
|
||||
use std::os::windows::ffi::OsStrExt;
|
||||
use std::{ffi::c_void, ptr};
|
||||
|
||||
use winapi::{
|
||||
shared::{
|
||||
basetsd::SIZE_T,
|
||||
minwindef::{BOOL, DWORD, FALSE, WORD},
|
||||
ntdef::{NTSTATUS, NT_SUCCESS, PVOID},
|
||||
windef::HWND,
|
||||
winerror::S_OK,
|
||||
use windows_sys::{
|
||||
core::PCSTR,
|
||||
Win32::{
|
||||
Foundation::{BOOL, HWND, NTSTATUS, S_OK},
|
||||
System::{
|
||||
LibraryLoader::{GetProcAddress, LoadLibraryA},
|
||||
SystemInformation::OSVERSIONINFOW,
|
||||
},
|
||||
UI::{
|
||||
Accessibility::{HCF_HIGHCONTRASTON, HIGHCONTRASTA},
|
||||
Controls::SetWindowTheme,
|
||||
WindowsAndMessaging::{SystemParametersInfoA, SPI_GETHIGHCONTRAST},
|
||||
},
|
||||
},
|
||||
um::{libloaderapi, uxtheme, winnt, winuser},
|
||||
};
|
||||
|
||||
use crate::window::Theme;
|
||||
|
||||
use super::util;
|
||||
|
||||
lazy_static! {
|
||||
static ref WIN10_BUILD_VERSION: Option<DWORD> = {
|
||||
type RtlGetVersion = unsafe extern "system" fn (*mut winnt::OSVERSIONINFOW) -> NTSTATUS;
|
||||
static ref WIN10_BUILD_VERSION: Option<u32> = {
|
||||
type RtlGetVersion = unsafe extern "system" fn (*mut OSVERSIONINFOW) -> NTSTATUS;
|
||||
let handle = get_function!("ntdll.dll", RtlGetVersion);
|
||||
|
||||
if let Some(rtl_get_version) = handle {
|
||||
unsafe {
|
||||
let mut vi = winnt::OSVERSIONINFOW {
|
||||
let mut vi = OSVERSIONINFOW {
|
||||
dwOSVersionInfoSize: 0,
|
||||
dwMajorVersion: 0,
|
||||
dwMinorVersion: 0,
|
||||
|
|
@ -32,9 +38,9 @@ lazy_static! {
|
|||
szCSDVersion: [0; 128],
|
||||
};
|
||||
|
||||
let status = (rtl_get_version)(&mut vi as _);
|
||||
let status = (rtl_get_version)(&mut vi);
|
||||
|
||||
if NT_SUCCESS(status) && vi.dwMajorVersion == 10 && vi.dwMinorVersion == 0 {
|
||||
if status >= 0 && vi.dwMajorVersion == 10 && vi.dwMinorVersion == 0 {
|
||||
Some(vi.dwBuildNumber)
|
||||
} else {
|
||||
None
|
||||
|
|
@ -54,8 +60,8 @@ lazy_static! {
|
|||
}
|
||||
};
|
||||
|
||||
static ref DARK_THEME_NAME: Vec<u16> = widestring("DarkMode_Explorer");
|
||||
static ref LIGHT_THEME_NAME: Vec<u16> = widestring("");
|
||||
static ref DARK_THEME_NAME: Vec<u16> = util::encode_wide("DarkMode_Explorer");
|
||||
static ref LIGHT_THEME_NAME: Vec<u16> = util::encode_wide("");
|
||||
}
|
||||
|
||||
/// Attempt to set a theme on a window, if necessary.
|
||||
|
|
@ -77,7 +83,7 @@ pub fn try_theme(hwnd: HWND, preferred_theme: Option<Theme>) -> Theme {
|
|||
Theme::Light => LIGHT_THEME_NAME.as_ptr(),
|
||||
};
|
||||
|
||||
let status = unsafe { uxtheme::SetWindowTheme(hwnd, theme_name as _, std::ptr::null()) };
|
||||
let status = unsafe { SetWindowTheme(hwnd, theme_name, ptr::null()) };
|
||||
|
||||
if status == S_OK && set_dark_mode_for_window(hwnd, is_dark_mode) {
|
||||
return theme;
|
||||
|
|
@ -103,8 +109,8 @@ fn set_dark_mode_for_window(hwnd: HWND, is_dark_mode: bool) -> bool {
|
|||
#[repr(C)]
|
||||
struct WINDOWCOMPOSITIONATTRIBDATA {
|
||||
Attrib: WINDOWCOMPOSITIONATTRIB,
|
||||
pvData: PVOID,
|
||||
cbData: SIZE_T,
|
||||
pvData: *mut c_void,
|
||||
cbData: usize,
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
|
|
@ -115,7 +121,7 @@ fn set_dark_mode_for_window(hwnd: HWND, is_dark_mode: bool) -> bool {
|
|||
if let Some(set_window_composition_attribute) = *SET_WINDOW_COMPOSITION_ATTRIBUTE {
|
||||
unsafe {
|
||||
// SetWindowCompositionAttribute needs a bigbool (i32), not bool.
|
||||
let mut is_dark_mode_bigbool = is_dark_mode as BOOL;
|
||||
let mut is_dark_mode_bigbool = BOOL::from(is_dark_mode);
|
||||
|
||||
let mut data = WINDOWCOMPOSITIONATTRIBDATA {
|
||||
Attrib: WCA_USEDARKMODECOLORS,
|
||||
|
|
@ -123,9 +129,9 @@ fn set_dark_mode_for_window(hwnd: HWND, is_dark_mode: bool) -> bool {
|
|||
cbData: std::mem::size_of_val(&is_dark_mode_bigbool) as _,
|
||||
};
|
||||
|
||||
let status = set_window_composition_attribute(hwnd, &mut data as *mut _);
|
||||
let status = set_window_composition_attribute(hwnd, &mut data);
|
||||
|
||||
status != FALSE
|
||||
status != false.into()
|
||||
}
|
||||
} else {
|
||||
false
|
||||
|
|
@ -141,24 +147,17 @@ fn should_apps_use_dark_mode() -> bool {
|
|||
lazy_static! {
|
||||
static ref SHOULD_APPS_USE_DARK_MODE: Option<ShouldAppsUseDarkMode> = {
|
||||
unsafe {
|
||||
const UXTHEME_SHOULDAPPSUSEDARKMODE_ORDINAL: WORD = 132;
|
||||
const UXTHEME_SHOULDAPPSUSEDARKMODE_ORDINAL: PCSTR = 132 as PCSTR;
|
||||
|
||||
let module = libloaderapi::LoadLibraryA("uxtheme.dll\0".as_ptr() as _);
|
||||
let module = LoadLibraryA("uxtheme.dll\0".as_ptr());
|
||||
|
||||
if module.is_null() {
|
||||
if module == 0 {
|
||||
return None;
|
||||
}
|
||||
|
||||
let handle = libloaderapi::GetProcAddress(
|
||||
module,
|
||||
winuser::MAKEINTRESOURCEA(UXTHEME_SHOULDAPPSUSEDARKMODE_ORDINAL),
|
||||
);
|
||||
let handle = GetProcAddress(module, UXTHEME_SHOULDAPPSUSEDARKMODE_ORDINAL);
|
||||
|
||||
if handle.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(std::mem::transmute(handle))
|
||||
}
|
||||
handle.map(|handle| std::mem::transmute(handle))
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
@ -169,27 +168,20 @@ fn should_apps_use_dark_mode() -> bool {
|
|||
}
|
||||
|
||||
fn is_high_contrast() -> bool {
|
||||
let mut hc = winuser::HIGHCONTRASTA {
|
||||
let mut hc = HIGHCONTRASTA {
|
||||
cbSize: 0,
|
||||
dwFlags: 0,
|
||||
lpszDefaultScheme: std::ptr::null_mut(),
|
||||
lpszDefaultScheme: ptr::null_mut(),
|
||||
};
|
||||
|
||||
let ok = unsafe {
|
||||
winuser::SystemParametersInfoA(
|
||||
winuser::SPI_GETHIGHCONTRAST,
|
||||
SystemParametersInfoA(
|
||||
SPI_GETHIGHCONTRAST,
|
||||
std::mem::size_of_val(&hc) as _,
|
||||
&mut hc as *mut _ as _,
|
||||
0,
|
||||
)
|
||||
};
|
||||
|
||||
ok != FALSE && (winuser::HCF_HIGHCONTRASTON & hc.dwFlags) == 1
|
||||
}
|
||||
|
||||
fn widestring(src: &'static str) -> Vec<u16> {
|
||||
OsStr::new(src)
|
||||
.encode_wide()
|
||||
.chain(Some(0).into_iter())
|
||||
.collect()
|
||||
ok != false.into() && util::has_flag(hc.dwFlags, HCF_HIGHCONTRASTON)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue