mirror of
https://github.com/hrydgard/ppsspp.git
synced 2024-11-30 08:50:33 +00:00
230 lines
7.1 KiB
C++
230 lines
7.1 KiB
C++
#include "IatHook.h"
|
|
#include "DarkMode.h"
|
|
|
|
fnSetWindowCompositionAttribute _SetWindowCompositionAttribute = nullptr;
|
|
fnShouldAppsUseDarkMode _ShouldAppsUseDarkMode = nullptr;
|
|
fnAllowDarkModeForWindow _AllowDarkModeForWindow = nullptr;
|
|
fnAllowDarkModeForApp _AllowDarkModeForApp = nullptr;
|
|
fnFlushMenuThemes _FlushMenuThemes = nullptr;
|
|
fnRefreshImmersiveColorPolicyState _RefreshImmersiveColorPolicyState = nullptr;
|
|
fnIsDarkModeAllowedForWindow _IsDarkModeAllowedForWindow = nullptr;
|
|
fnGetIsImmersiveColorUsingHighContrast _GetIsImmersiveColorUsingHighContrast = nullptr;
|
|
fnOpenNcThemeData _OpenNcThemeData = nullptr;
|
|
// 1903 18362
|
|
fnShouldSystemUseDarkMode _ShouldSystemUseDarkMode = nullptr;
|
|
fnSetPreferredAppMode _SetPreferredAppMode = nullptr;
|
|
fnSetWindowTheme _SetWindowTheme = nullptr;
|
|
|
|
bool g_darkModeSupported = false;
|
|
bool g_darkModeEnabled = false;
|
|
DWORD g_buildNumber = 0;
|
|
|
|
bool AllowDarkModeForWindow(HWND hWnd, bool allow)
|
|
{
|
|
if (g_darkModeSupported)
|
|
return _AllowDarkModeForWindow(hWnd, allow);
|
|
return false;
|
|
}
|
|
|
|
bool IsHighContrast()
|
|
{
|
|
HIGHCONTRASTW highContrast = { sizeof(highContrast) };
|
|
if (SystemParametersInfoW(SPI_GETHIGHCONTRAST, sizeof(highContrast), &highContrast, FALSE))
|
|
return highContrast.dwFlags & HCF_HIGHCONTRASTON;
|
|
return false;
|
|
}
|
|
|
|
void RefreshTitleBarThemeColor(HWND hWnd)
|
|
{
|
|
BOOL dark = FALSE;
|
|
if (_IsDarkModeAllowedForWindow(hWnd) &&
|
|
_ShouldAppsUseDarkMode() &&
|
|
!IsHighContrast())
|
|
{
|
|
dark = TRUE;
|
|
}
|
|
if (g_buildNumber < 18362)
|
|
SetPropW(hWnd, L"UseImmersiveDarkModeColors", reinterpret_cast<HANDLE>(static_cast<INT_PTR>(dark)));
|
|
else if (_SetWindowCompositionAttribute)
|
|
{
|
|
WINDOWCOMPOSITIONATTRIBDATA data = { WCA_USEDARKMODECOLORS, &dark, sizeof(dark) };
|
|
_SetWindowCompositionAttribute(hWnd, &data);
|
|
}
|
|
}
|
|
|
|
bool IsColorSchemeChangeMessage(LPARAM lParam)
|
|
{
|
|
bool is = false;
|
|
if (lParam && CompareStringOrdinal(reinterpret_cast<LPCWCH>(lParam), -1, L"ImmersiveColorSet", -1, TRUE) == CSTR_EQUAL)
|
|
{
|
|
_RefreshImmersiveColorPolicyState();
|
|
is = true;
|
|
}
|
|
_GetIsImmersiveColorUsingHighContrast(IHCM_REFRESH);
|
|
return is;
|
|
}
|
|
|
|
bool IsColorSchemeChangeMessage(UINT message, LPARAM lParam)
|
|
{
|
|
if (message == WM_SETTINGCHANGE)
|
|
return IsColorSchemeChangeMessage(lParam);
|
|
return false;
|
|
}
|
|
|
|
void AllowDarkModeForApp(bool allow)
|
|
{
|
|
if (_AllowDarkModeForApp)
|
|
_AllowDarkModeForApp(allow);
|
|
else if (_SetPreferredAppMode)
|
|
_SetPreferredAppMode(allow ? AllowDark : Default);
|
|
}
|
|
|
|
void FixDarkScrollBar()
|
|
{
|
|
// Disable this, doesn't look good.
|
|
return;
|
|
|
|
HMODULE hComctl = LoadLibraryExW(L"comctl32.dll", nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32);
|
|
if (hComctl)
|
|
{
|
|
auto addr = FindDelayLoadThunkInModule(hComctl, "uxtheme.dll", 49); // OpenNcThemeData
|
|
if (addr)
|
|
{
|
|
DWORD oldProtect;
|
|
if (VirtualProtect(addr, sizeof(IMAGE_THUNK_DATA), PAGE_READWRITE, &oldProtect))
|
|
{
|
|
auto MyOpenThemeData = [](HWND hWnd, LPCWSTR classList) -> HTHEME {
|
|
if (wcscmp(classList, L"ScrollBar") == 0)
|
|
{
|
|
hWnd = nullptr;
|
|
classList = L"Explorer::ScrollBar";
|
|
}
|
|
return _OpenNcThemeData(hWnd, classList);
|
|
};
|
|
|
|
addr->u1.Function = reinterpret_cast<ULONG_PTR>(static_cast<fnOpenNcThemeData>(MyOpenThemeData));
|
|
VirtualProtect(addr, sizeof(IMAGE_THUNK_DATA), oldProtect, &oldProtect);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void DarkModeInitDialog(HWND hDlg) {
|
|
if (g_darkModeSupported) {
|
|
_SetWindowTheme(GetDlgItem(hDlg, IDOK), L"Explorer", nullptr);
|
|
SendMessageW(hDlg, WM_THEMECHANGED, 0, 0);
|
|
}
|
|
}
|
|
|
|
LRESULT DarkModeDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) {
|
|
constexpr COLORREF darkBkColor = 0x383838;
|
|
constexpr COLORREF darkTextColor = 0xFFFFFF;
|
|
static HBRUSH hbrBkgnd = nullptr;
|
|
|
|
switch (message) {
|
|
case WM_CTLCOLORDLG:
|
|
case WM_CTLCOLORSTATIC:
|
|
{
|
|
if (g_darkModeSupported && g_darkModeEnabled)
|
|
{
|
|
HDC hdc = reinterpret_cast<HDC>(wParam);
|
|
SetTextColor(hdc, darkTextColor);
|
|
SetBkColor(hdc, darkBkColor);
|
|
if (!hbrBkgnd)
|
|
hbrBkgnd = CreateSolidBrush(darkBkColor);
|
|
return reinterpret_cast<INT_PTR>(hbrBkgnd);
|
|
}
|
|
break;
|
|
}
|
|
case WM_SETTINGCHANGE:
|
|
{
|
|
if (g_darkModeSupported && IsColorSchemeChangeMessage(lParam))
|
|
SendMessageW(hDlg, WM_THEMECHANGED, 0, 0);
|
|
break;
|
|
}
|
|
case WM_THEMECHANGED:
|
|
{
|
|
if (g_darkModeSupported)
|
|
{
|
|
_AllowDarkModeForWindow(hDlg, g_darkModeEnabled);
|
|
RefreshTitleBarThemeColor(hDlg);
|
|
|
|
HWND hButton = GetDlgItem(hDlg, IDOK);
|
|
_AllowDarkModeForWindow(hButton, g_darkModeEnabled);
|
|
SendMessageW(hButton, WM_THEMECHANGED, 0, 0);
|
|
|
|
UpdateWindow(hDlg);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
bool IsDarkModeEnabled() {
|
|
return g_darkModeEnabled;
|
|
}
|
|
|
|
constexpr bool CheckBuildNumber(DWORD buildNumber)
|
|
{
|
|
// TODO: This is BS.
|
|
|
|
return (buildNumber == 17763 || // 1809
|
|
buildNumber == 18362 || // 1903
|
|
buildNumber == 18363 || // 1909
|
|
buildNumber >= 19041); // Windows 11
|
|
}
|
|
|
|
void InitDarkMode()
|
|
{
|
|
auto RtlGetNtVersionNumbers = reinterpret_cast<fnRtlGetNtVersionNumbers>(GetProcAddress(GetModuleHandleW(L"ntdll.dll"), "RtlGetNtVersionNumbers"));
|
|
if (RtlGetNtVersionNumbers)
|
|
{
|
|
DWORD major, minor;
|
|
RtlGetNtVersionNumbers(&major, &minor, &g_buildNumber);
|
|
g_buildNumber &= ~0xF0000000;
|
|
if (major == 10 && minor == 0 && CheckBuildNumber(g_buildNumber))
|
|
{
|
|
HMODULE hUxtheme = LoadLibraryExW(L"uxtheme.dll", nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32);
|
|
if (hUxtheme)
|
|
{
|
|
_OpenNcThemeData = reinterpret_cast<fnOpenNcThemeData>(GetProcAddress(hUxtheme, MAKEINTRESOURCEA(49)));
|
|
_RefreshImmersiveColorPolicyState = reinterpret_cast<fnRefreshImmersiveColorPolicyState>(GetProcAddress(hUxtheme, MAKEINTRESOURCEA(104)));
|
|
_GetIsImmersiveColorUsingHighContrast = reinterpret_cast<fnGetIsImmersiveColorUsingHighContrast>(GetProcAddress(hUxtheme, MAKEINTRESOURCEA(106)));
|
|
_ShouldAppsUseDarkMode = reinterpret_cast<fnShouldAppsUseDarkMode>(GetProcAddress(hUxtheme, MAKEINTRESOURCEA(132)));
|
|
_AllowDarkModeForWindow = reinterpret_cast<fnAllowDarkModeForWindow>(GetProcAddress(hUxtheme, MAKEINTRESOURCEA(133)));
|
|
|
|
auto ord135 = GetProcAddress(hUxtheme, MAKEINTRESOURCEA(135));
|
|
if (g_buildNumber < 18362)
|
|
_AllowDarkModeForApp = reinterpret_cast<fnAllowDarkModeForApp>(ord135);
|
|
else
|
|
_SetPreferredAppMode = reinterpret_cast<fnSetPreferredAppMode>(ord135);
|
|
|
|
//_FlushMenuThemes = reinterpret_cast<fnFlushMenuThemes>(GetProcAddress(hUxtheme, MAKEINTRESOURCEA(136)));
|
|
_IsDarkModeAllowedForWindow = reinterpret_cast<fnIsDarkModeAllowedForWindow>(GetProcAddress(hUxtheme, MAKEINTRESOURCEA(137)));
|
|
|
|
_SetWindowCompositionAttribute = reinterpret_cast<fnSetWindowCompositionAttribute>(GetProcAddress(GetModuleHandleW(L"user32.dll"), "SetWindowCompositionAttribute"));
|
|
_SetWindowTheme = reinterpret_cast<fnSetWindowTheme>(GetProcAddress(hUxtheme, "SetWindowTheme"));
|
|
|
|
if (_OpenNcThemeData &&
|
|
_RefreshImmersiveColorPolicyState &&
|
|
_ShouldAppsUseDarkMode &&
|
|
_AllowDarkModeForWindow &&
|
|
(_AllowDarkModeForApp || _SetPreferredAppMode) &&
|
|
//_FlushMenuThemes &&
|
|
_IsDarkModeAllowedForWindow)
|
|
{
|
|
g_darkModeSupported = true;
|
|
|
|
AllowDarkModeForApp(true);
|
|
_RefreshImmersiveColorPolicyState();
|
|
|
|
g_darkModeEnabled = _ShouldAppsUseDarkMode() && !IsHighContrast();
|
|
|
|
FixDarkScrollBar();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|