mirror of
https://github.com/spice2x/spice2x.github.io.git
synced 2026-08-01 14:20:42 -07:00
graphics: respect Windows dark mode (#765)
Only affects the caption bar. Should work for: - [x] standalone configurator - [x] dx9 games, including multi-window games like gitadora - [x] Unity games
This commit is contained in:
@@ -12,6 +12,7 @@
|
|||||||
#include "overlay/overlay.h"
|
#include "overlay/overlay.h"
|
||||||
#include "util/logging.h"
|
#include "util/logging.h"
|
||||||
#include "util/precise_timer.h"
|
#include "util/precise_timer.h"
|
||||||
|
#include "util/utils.h"
|
||||||
#include "cfg/configurator.h"
|
#include "cfg/configurator.h"
|
||||||
|
|
||||||
#include "icon.h"
|
#include "icon.h"
|
||||||
@@ -214,6 +215,8 @@ cfg::ConfiguratorWindow::ConfiguratorWindow() {
|
|||||||
|
|
||||||
if (this->hWnd) {
|
if (this->hWnd) {
|
||||||
overlay::USE_WM_CHAR_FOR_IMGUI_CHAR_INPUT = true;
|
overlay::USE_WM_CHAR_FOR_IMGUI_CHAR_INPUT = true;
|
||||||
|
// force dark title bar
|
||||||
|
set_window_dark_titlebar(this->hWnd, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,6 +27,7 @@
|
|||||||
#include "hooks/graphics/graphics.h"
|
#include "hooks/graphics/graphics.h"
|
||||||
#include "launcher/launcher.h"
|
#include "launcher/launcher.h"
|
||||||
#include "misc/eamuse.h"
|
#include "misc/eamuse.h"
|
||||||
|
#include "util/utils.h"
|
||||||
|
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
// overlay render bridge
|
// overlay render bridge
|
||||||
@@ -123,6 +124,10 @@ void try_create_overlay(IDXGISwapChain *swapchain) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// theme the native title bar; first present is the only reliable point for
|
||||||
|
// windows whose swapchain bypasses our factory hooks (e.g. UnityPlayer.dll)
|
||||||
|
set_window_dark_titlebar(desc.OutputWindow);
|
||||||
|
|
||||||
ID3D11Device *device = nullptr;
|
ID3D11Device *device = nullptr;
|
||||||
if (FAILED(swapchain->GetDevice(IID_PPV_ARGS(&device))) || !device) {
|
if (FAILED(swapchain->GetDevice(IID_PPV_ARGS(&device))) || !device) {
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -585,6 +585,9 @@ static HWND WINAPI CreateWindowExA_hook(DWORD dwExStyle, LPCSTR lpClassName, LPC
|
|||||||
hWndParent, hMenu, hInstance, lpParam);
|
hWndParent, hMenu, hInstance, lpParam);
|
||||||
GRAPHICS_WINDOWS.push_back(result);
|
GRAPHICS_WINDOWS.push_back(result);
|
||||||
|
|
||||||
|
// theme the native title bar (dark/light)
|
||||||
|
set_window_dark_titlebar(result);
|
||||||
|
|
||||||
if (is_tdj_sub_window) {
|
if (is_tdj_sub_window) {
|
||||||
// TDJ windowed mode: remember the subscreen window handle for later
|
// TDJ windowed mode: remember the subscreen window handle for later
|
||||||
TDJ_SUBSCREEN_WINDOW = result;
|
TDJ_SUBSCREEN_WINDOW = result;
|
||||||
@@ -706,6 +709,9 @@ static HWND WINAPI CreateWindowExW_hook(DWORD dwExStyle, LPCWSTR lpClassName, LP
|
|||||||
hWndParent, hMenu, hInstance, lpParam);
|
hWndParent, hMenu, hInstance, lpParam);
|
||||||
GRAPHICS_WINDOWS.push_back(result);
|
GRAPHICS_WINDOWS.push_back(result);
|
||||||
|
|
||||||
|
// theme the native title bar (dark/light)
|
||||||
|
set_window_dark_titlebar(result);
|
||||||
|
|
||||||
log_misc(
|
log_misc(
|
||||||
"graphics",
|
"graphics",
|
||||||
"CreateWindowExW returned {}, {}",
|
"CreateWindowExW returned {}, {}",
|
||||||
|
|||||||
@@ -4,6 +4,15 @@
|
|||||||
|
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
|
#if !SPICE_XP
|
||||||
|
#include <dwmapi.h>
|
||||||
|
#ifndef DWMWA_USE_IMMERSIVE_DARK_MODE
|
||||||
|
#define DWMWA_USE_IMMERSIVE_DARK_MODE 20
|
||||||
|
#endif
|
||||||
|
// older numbering used by Win10 1809..1909
|
||||||
|
#define DWMWA_USE_IMMERSIVE_DARK_MODE_OLD 19
|
||||||
|
#endif
|
||||||
|
|
||||||
const char *inet_ntop(short af, const void *src, char *dst, DWORD size) {
|
const char *inet_ntop(short af, const void *src, char *dst, DWORD size) {
|
||||||
|
|
||||||
// prepare storage
|
// prepare storage
|
||||||
@@ -124,3 +133,37 @@ void generate_ea_card(char card[17]) {
|
|||||||
// terminate and flush
|
// terminate and flush
|
||||||
card[16] = 0;
|
card[16] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void set_window_dark_titlebar(HWND hWnd, bool force_dark) {
|
||||||
|
#if !SPICE_XP
|
||||||
|
if (hWnd == nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// AppsUseLightTheme == 0 means the dark app theme is selected
|
||||||
|
DWORD light = 1;
|
||||||
|
if (!force_dark) {
|
||||||
|
DWORD size = sizeof(light);
|
||||||
|
HKEY key;
|
||||||
|
if (RegOpenKeyExW(HKEY_CURRENT_USER,
|
||||||
|
L"Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize",
|
||||||
|
0, KEY_QUERY_VALUE, &key) == ERROR_SUCCESS) {
|
||||||
|
RegQueryValueExW(key, L"AppsUseLightTheme", nullptr, nullptr,
|
||||||
|
reinterpret_cast<LPBYTE>(&light), &size);
|
||||||
|
RegCloseKey(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL dark = (force_dark || light == 0) ? TRUE : FALSE;
|
||||||
|
|
||||||
|
// fall back to the older attribute numbering on Win10 1809..1909
|
||||||
|
if (FAILED(DwmSetWindowAttribute(hWnd, DWMWA_USE_IMMERSIVE_DARK_MODE,
|
||||||
|
&dark, sizeof(dark)))) {
|
||||||
|
DwmSetWindowAttribute(hWnd, DWMWA_USE_IMMERSIVE_DARK_MODE_OLD,
|
||||||
|
&dark, sizeof(dark));
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
(void) hWnd;
|
||||||
|
(void) force_dark;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|||||||
@@ -28,6 +28,10 @@ static const char HEX_LOOKUP_UPPERCASE[16] = {
|
|||||||
|
|
||||||
const char *inet_ntop(short af, const void *src, char *dst, DWORD size);
|
const char *inet_ntop(short af, const void *src, char *dst, DWORD size);
|
||||||
|
|
||||||
|
// make a window's native title bar follow the Windows dark/light app theme.
|
||||||
|
// pass force_dark=true to always use the dark caption regardless of the system theme.
|
||||||
|
void set_window_dark_titlebar(HWND hWnd, bool force_dark = false);
|
||||||
|
|
||||||
static inline bool string_begins_with(const std::string &s, const std::string &prefix) {
|
static inline bool string_begins_with(const std::string &s, const std::string &prefix) {
|
||||||
return s.compare(0, prefix.size(), prefix) == 0;
|
return s.compare(0, prefix.size(), prefix) == 0;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user