Workaround for getting dark title bar in Windows
Uses undocumented APIs to change the use dark title bar in Windows
This commit is contained in:
parent
bd8b525faa
commit
03ae320417
418
src/main.c
418
src/main.c
|
@ -1,209 +1,209 @@
|
|||
#include <stdio.h>
|
||||
#include <SDL2/SDL.h>
|
||||
#include "api/api.h"
|
||||
#include "renderer.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#include <dwmapi.h>
|
||||
#include <SDL2/SDL_syswm.h>
|
||||
|
||||
enum WINDOWCOMPOSITIONATTRIB {
|
||||
WCA_USEDARKMODECOLORS = 26
|
||||
};
|
||||
|
||||
struct WINDOWCOMPOSITIONATTRIBDATA {
|
||||
enum WINDOWCOMPOSITIONATTRIB Attrib;
|
||||
PVOID pvData;
|
||||
SIZE_T cbData;
|
||||
};
|
||||
|
||||
enum PreferredAppMode { Default, AllowDark, ForceDark, ForceLight, Max };
|
||||
|
||||
typedef BOOL(WINAPI *fnSetWindowCompositionAttribute)(
|
||||
HWND hWnd, struct WINDOWCOMPOSITIONATTRIBDATA *);
|
||||
typedef VOID(WINAPI *fnRefreshImmersiveColorPolicyState)(); // ordinal 104
|
||||
typedef BOOL(WINAPI *fnShouldAppsUseDarkMode)(); // ordinal 132
|
||||
typedef enum PreferredAppMode(WINAPI *fnSetPreferredAppMode)(
|
||||
enum PreferredAppMode appMode); // ordinal 135
|
||||
|
||||
fnRefreshImmersiveColorPolicyState _RefreshImmersiveColorPolicyState = NULL;
|
||||
fnSetWindowCompositionAttribute _SetWindowCompositionAttribute = NULL;
|
||||
fnShouldAppsUseDarkMode _ShouldAppsUseDarkMode = NULL;
|
||||
fnSetPreferredAppMode _SetPreferredAppMode = NULL;
|
||||
|
||||
HWND getWinHandle(SDL_Window *win) {
|
||||
SDL_SysWMinfo infoWindow;
|
||||
SDL_VERSION(&infoWindow.version);
|
||||
SDL_GetWindowWMInfo(win, &infoWindow);
|
||||
return (infoWindow.info.win.window);
|
||||
}
|
||||
|
||||
void get_dark_titlebar(SDL_Window *window, int dark) {
|
||||
HWND hwnd;
|
||||
hwnd = getWinHandle(window);
|
||||
HMODULE hUxtheme =
|
||||
LoadLibraryExW(L"uxtheme.dll", NULL, LOAD_LIBRARY_SEARCH_SYSTEM32);
|
||||
if (hUxtheme) {
|
||||
_SetWindowCompositionAttribute =
|
||||
(fnSetWindowCompositionAttribute)(GetProcAddress(
|
||||
GetModuleHandleW(L"user32.dll"), "SetWindowCompositionAttribute"));
|
||||
_RefreshImmersiveColorPolicyState = (fnRefreshImmersiveColorPolicyState)(
|
||||
GetProcAddress(hUxtheme, MAKEINTRESOURCEA(104)));
|
||||
_ShouldAppsUseDarkMode = (fnShouldAppsUseDarkMode)(
|
||||
GetProcAddress(hUxtheme, MAKEINTRESOURCEA(132)));
|
||||
_SetPreferredAppMode = (fnSetPreferredAppMode)(
|
||||
GetProcAddress(hUxtheme, MAKEINTRESOURCEA(135)));
|
||||
|
||||
if (_RefreshImmersiveColorPolicyState && _ShouldAppsUseDarkMode &&
|
||||
_SetPreferredAppMode) {
|
||||
_SetPreferredAppMode(AllowDark);
|
||||
_RefreshImmersiveColorPolicyState();
|
||||
LONG ldark = dark;
|
||||
struct WINDOWCOMPOSITIONATTRIBDATA data = {WCA_USEDARKMODECOLORS, &ldark,
|
||||
sizeof ldark};
|
||||
_SetWindowCompositionAttribute(hwnd, &data);
|
||||
}
|
||||
}
|
||||
}
|
||||
#elif __linux__
|
||||
#include <unistd.h>
|
||||
#elif __APPLE__
|
||||
#include <mach-o/dyld.h>
|
||||
#endif
|
||||
|
||||
|
||||
SDL_Window *window;
|
||||
|
||||
|
||||
static double get_scale(void) {
|
||||
float dpi;
|
||||
SDL_GetDisplayDPI(0, NULL, &dpi, NULL);
|
||||
#if _WIN32
|
||||
return dpi / 96.0;
|
||||
#else
|
||||
return 1.0;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static void get_exe_filename(char *buf, int sz) {
|
||||
#if _WIN32
|
||||
int len = GetModuleFileName(NULL, buf, sz - 1);
|
||||
buf[len] = '\0';
|
||||
#elif __linux__
|
||||
char path[512];
|
||||
sprintf(path, "/proc/%d/exe", getpid());
|
||||
int len = readlink(path, buf, sz - 1);
|
||||
buf[len] = '\0';
|
||||
#elif __APPLE__
|
||||
unsigned size = sz;
|
||||
_NSGetExecutablePath(buf, &size);
|
||||
#else
|
||||
strcpy(buf, "./lite");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static void init_window_icon(void) {
|
||||
#ifndef _WIN32
|
||||
#include "../icon.inl"
|
||||
(void) icon_rgba_len; /* unused */
|
||||
SDL_Surface *surf = SDL_CreateRGBSurfaceFrom(
|
||||
icon_rgba, 64, 64,
|
||||
32, 64 * 4,
|
||||
0x000000ff,
|
||||
0x0000ff00,
|
||||
0x00ff0000,
|
||||
0xff000000);
|
||||
SDL_SetWindowIcon(window, surf);
|
||||
SDL_FreeSurface(surf);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
#ifdef _WIN32
|
||||
HINSTANCE lib = LoadLibrary("user32.dll");
|
||||
int (*SetProcessDPIAware)() = (void*) GetProcAddress(lib, "SetProcessDPIAware");
|
||||
SetProcessDPIAware();
|
||||
#endif
|
||||
|
||||
SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS);
|
||||
SDL_EnableScreenSaver();
|
||||
SDL_EventState(SDL_DROPFILE, SDL_ENABLE);
|
||||
atexit(SDL_Quit);
|
||||
|
||||
#ifdef SDL_HINT_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR /* Available since 2.0.8 */
|
||||
SDL_SetHint(SDL_HINT_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR, "0");
|
||||
#endif
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 5)
|
||||
SDL_SetHint(SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH, "1");
|
||||
#endif
|
||||
|
||||
SDL_DisplayMode dm;
|
||||
SDL_GetCurrentDisplayMode(0, &dm);
|
||||
|
||||
window = SDL_CreateWindow(
|
||||
"", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, dm.w * 0.8, dm.h * 0.8,
|
||||
SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI | SDL_WINDOW_HIDDEN);
|
||||
#if _WIN32
|
||||
get_dark_titlebar(window, 1);
|
||||
#endif
|
||||
init_window_icon();
|
||||
ren_init(window);
|
||||
|
||||
|
||||
lua_State *L = luaL_newstate();
|
||||
luaL_openlibs(L);
|
||||
api_load_libs(L);
|
||||
|
||||
|
||||
lua_newtable(L);
|
||||
for (int i = 0; i < argc; i++) {
|
||||
lua_pushstring(L, argv[i]);
|
||||
lua_rawseti(L, -2, i + 1);
|
||||
}
|
||||
lua_setglobal(L, "ARGS");
|
||||
|
||||
lua_pushstring(L, "1.11");
|
||||
lua_setglobal(L, "VERSION");
|
||||
|
||||
lua_pushstring(L, SDL_GetPlatform());
|
||||
lua_setglobal(L, "PLATFORM");
|
||||
|
||||
lua_pushnumber(L, get_scale());
|
||||
lua_setglobal(L, "SCALE");
|
||||
|
||||
char exename[2048];
|
||||
get_exe_filename(exename, sizeof(exename));
|
||||
lua_pushstring(L, exename);
|
||||
lua_setglobal(L, "EXEFILE");
|
||||
|
||||
|
||||
(void) luaL_dostring(L,
|
||||
"local core\n"
|
||||
"xpcall(function()\n"
|
||||
" SCALE = tonumber(os.getenv(\"LITE_SCALE\")) or SCALE\n"
|
||||
" PATHSEP = package.config:sub(1, 1)\n"
|
||||
" EXEDIR = EXEFILE:match(\"^(.+)[/\\\\].*$\")\n"
|
||||
" package.path = EXEDIR .. '/data/?.lua;' .. package.path\n"
|
||||
" package.path = EXEDIR .. '/data/?/init.lua;' .. package.path\n"
|
||||
" core = require('core')\n"
|
||||
" core.init()\n"
|
||||
" core.run()\n"
|
||||
"end, function(err)\n"
|
||||
" print('Error: ' .. tostring(err))\n"
|
||||
" print(debug.traceback(nil, 2))\n"
|
||||
" if core and core.on_error then\n"
|
||||
" pcall(core.on_error, err)\n"
|
||||
" end\n"
|
||||
" os.exit(1)\n"
|
||||
"end)");
|
||||
|
||||
|
||||
lua_close(L);
|
||||
SDL_DestroyWindow(window);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
#include <stdio.h>
|
||||
#include <SDL2/SDL.h>
|
||||
#include "api/api.h"
|
||||
#include "renderer.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#include <dwmapi.h>
|
||||
#include <SDL2/SDL_syswm.h>
|
||||
|
||||
enum WINDOWCOMPOSITIONATTRIB {
|
||||
WCA_USEDARKMODECOLORS = 26
|
||||
};
|
||||
|
||||
struct WINDOWCOMPOSITIONATTRIBDATA {
|
||||
enum WINDOWCOMPOSITIONATTRIB Attrib;
|
||||
PVOID pvData;
|
||||
SIZE_T cbData;
|
||||
};
|
||||
|
||||
enum PreferredAppMode { Default, AllowDark, ForceDark, ForceLight, Max };
|
||||
|
||||
typedef BOOL(WINAPI *fnSetWindowCompositionAttribute)(
|
||||
HWND hWnd, struct WINDOWCOMPOSITIONATTRIBDATA *);
|
||||
typedef VOID(WINAPI *fnRefreshImmersiveColorPolicyState)(); // ordinal 104
|
||||
typedef BOOL(WINAPI *fnShouldAppsUseDarkMode)(); // ordinal 132
|
||||
typedef enum PreferredAppMode(WINAPI *fnSetPreferredAppMode)(
|
||||
enum PreferredAppMode appMode); // ordinal 135
|
||||
|
||||
fnRefreshImmersiveColorPolicyState _RefreshImmersiveColorPolicyState = NULL;
|
||||
fnSetWindowCompositionAttribute _SetWindowCompositionAttribute = NULL;
|
||||
fnShouldAppsUseDarkMode _ShouldAppsUseDarkMode = NULL;
|
||||
fnSetPreferredAppMode _SetPreferredAppMode = NULL;
|
||||
|
||||
HWND getWinHandle(SDL_Window *win) {
|
||||
SDL_SysWMinfo infoWindow;
|
||||
SDL_VERSION(&infoWindow.version);
|
||||
SDL_GetWindowWMInfo(win, &infoWindow);
|
||||
return (infoWindow.info.win.window);
|
||||
}
|
||||
|
||||
void get_dark_titlebar(SDL_Window *window, int dark) {
|
||||
HWND hwnd;
|
||||
hwnd = getWinHandle(window);
|
||||
HMODULE hUxtheme =
|
||||
LoadLibraryExW(L"uxtheme.dll", NULL, LOAD_LIBRARY_SEARCH_SYSTEM32);
|
||||
if (hUxtheme) {
|
||||
_SetWindowCompositionAttribute =
|
||||
(fnSetWindowCompositionAttribute)(GetProcAddress(
|
||||
GetModuleHandleW(L"user32.dll"), "SetWindowCompositionAttribute"));
|
||||
_RefreshImmersiveColorPolicyState = (fnRefreshImmersiveColorPolicyState)(
|
||||
GetProcAddress(hUxtheme, MAKEINTRESOURCEA(104)));
|
||||
_ShouldAppsUseDarkMode = (fnShouldAppsUseDarkMode)(
|
||||
GetProcAddress(hUxtheme, MAKEINTRESOURCEA(132)));
|
||||
_SetPreferredAppMode = (fnSetPreferredAppMode)(
|
||||
GetProcAddress(hUxtheme, MAKEINTRESOURCEA(135)));
|
||||
|
||||
if (_RefreshImmersiveColorPolicyState && _ShouldAppsUseDarkMode &&
|
||||
_SetPreferredAppMode) {
|
||||
_SetPreferredAppMode(AllowDark);
|
||||
_RefreshImmersiveColorPolicyState();
|
||||
LONG ldark = dark;
|
||||
struct WINDOWCOMPOSITIONATTRIBDATA data = {WCA_USEDARKMODECOLORS, &ldark,
|
||||
sizeof ldark};
|
||||
_SetWindowCompositionAttribute(hwnd, &data);
|
||||
}
|
||||
}
|
||||
}
|
||||
#elif __linux__
|
||||
#include <unistd.h>
|
||||
#elif __APPLE__
|
||||
#include <mach-o/dyld.h>
|
||||
#endif
|
||||
|
||||
|
||||
SDL_Window *window;
|
||||
|
||||
|
||||
static double get_scale(void) {
|
||||
float dpi;
|
||||
SDL_GetDisplayDPI(0, NULL, &dpi, NULL);
|
||||
#if _WIN32
|
||||
return dpi / 96.0;
|
||||
#else
|
||||
return 1.0;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static void get_exe_filename(char *buf, int sz) {
|
||||
#if _WIN32
|
||||
int len = GetModuleFileName(NULL, buf, sz - 1);
|
||||
buf[len] = '\0';
|
||||
#elif __linux__
|
||||
char path[512];
|
||||
sprintf(path, "/proc/%d/exe", getpid());
|
||||
int len = readlink(path, buf, sz - 1);
|
||||
buf[len] = '\0';
|
||||
#elif __APPLE__
|
||||
unsigned size = sz;
|
||||
_NSGetExecutablePath(buf, &size);
|
||||
#else
|
||||
strcpy(buf, "./lite");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static void init_window_icon(void) {
|
||||
#ifndef _WIN32
|
||||
#include "../icon.inl"
|
||||
(void) icon_rgba_len; /* unused */
|
||||
SDL_Surface *surf = SDL_CreateRGBSurfaceFrom(
|
||||
icon_rgba, 64, 64,
|
||||
32, 64 * 4,
|
||||
0x000000ff,
|
||||
0x0000ff00,
|
||||
0x00ff0000,
|
||||
0xff000000);
|
||||
SDL_SetWindowIcon(window, surf);
|
||||
SDL_FreeSurface(surf);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
#ifdef _WIN32
|
||||
HINSTANCE lib = LoadLibrary("user32.dll");
|
||||
int (*SetProcessDPIAware)() = (void*) GetProcAddress(lib, "SetProcessDPIAware");
|
||||
SetProcessDPIAware();
|
||||
#endif
|
||||
|
||||
SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS);
|
||||
SDL_EnableScreenSaver();
|
||||
SDL_EventState(SDL_DROPFILE, SDL_ENABLE);
|
||||
atexit(SDL_Quit);
|
||||
|
||||
#ifdef SDL_HINT_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR /* Available since 2.0.8 */
|
||||
SDL_SetHint(SDL_HINT_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR, "0");
|
||||
#endif
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 5)
|
||||
SDL_SetHint(SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH, "1");
|
||||
#endif
|
||||
|
||||
SDL_DisplayMode dm;
|
||||
SDL_GetCurrentDisplayMode(0, &dm);
|
||||
|
||||
window = SDL_CreateWindow(
|
||||
"", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, dm.w * 0.8, dm.h * 0.8,
|
||||
SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI | SDL_WINDOW_HIDDEN);
|
||||
#if _WIN32
|
||||
get_dark_titlebar(window, 1);
|
||||
#endif
|
||||
init_window_icon();
|
||||
ren_init(window);
|
||||
|
||||
|
||||
lua_State *L = luaL_newstate();
|
||||
luaL_openlibs(L);
|
||||
api_load_libs(L);
|
||||
|
||||
|
||||
lua_newtable(L);
|
||||
for (int i = 0; i < argc; i++) {
|
||||
lua_pushstring(L, argv[i]);
|
||||
lua_rawseti(L, -2, i + 1);
|
||||
}
|
||||
lua_setglobal(L, "ARGS");
|
||||
|
||||
lua_pushstring(L, "1.11");
|
||||
lua_setglobal(L, "VERSION");
|
||||
|
||||
lua_pushstring(L, SDL_GetPlatform());
|
||||
lua_setglobal(L, "PLATFORM");
|
||||
|
||||
lua_pushnumber(L, get_scale());
|
||||
lua_setglobal(L, "SCALE");
|
||||
|
||||
char exename[2048];
|
||||
get_exe_filename(exename, sizeof(exename));
|
||||
lua_pushstring(L, exename);
|
||||
lua_setglobal(L, "EXEFILE");
|
||||
|
||||
|
||||
(void) luaL_dostring(L,
|
||||
"local core\n"
|
||||
"xpcall(function()\n"
|
||||
" SCALE = tonumber(os.getenv(\"LITE_SCALE\")) or SCALE\n"
|
||||
" PATHSEP = package.config:sub(1, 1)\n"
|
||||
" EXEDIR = EXEFILE:match(\"^(.+)[/\\\\].*$\")\n"
|
||||
" package.path = EXEDIR .. '/data/?.lua;' .. package.path\n"
|
||||
" package.path = EXEDIR .. '/data/?/init.lua;' .. package.path\n"
|
||||
" core = require('core')\n"
|
||||
" core.init()\n"
|
||||
" core.run()\n"
|
||||
"end, function(err)\n"
|
||||
" print('Error: ' .. tostring(err))\n"
|
||||
" print(debug.traceback(nil, 2))\n"
|
||||
" if core and core.on_error then\n"
|
||||
" pcall(core.on_error, err)\n"
|
||||
" end\n"
|
||||
" os.exit(1)\n"
|
||||
"end)");
|
||||
|
||||
|
||||
lua_close(L);
|
||||
SDL_DestroyWindow(window);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue