From 03ae320417d72df2a72d0f26185acd7628e1a553 Mon Sep 17 00:00:00 2001 From: Pratyush Nair Date: Mon, 17 May 2021 16:48:17 +0530 Subject: [PATCH] Workaround for getting dark title bar in Windows Uses undocumented APIs to change the use dark title bar in Windows --- src/main.c | 418 ++++++++++++++++++++++++++--------------------------- 1 file changed, 209 insertions(+), 209 deletions(-) diff --git a/src/main.c b/src/main.c index e48744d..6372071 100644 --- a/src/main.c +++ b/src/main.c @@ -1,209 +1,209 @@ -#include -#include -#include "api/api.h" -#include "renderer.h" - -#ifdef _WIN32 - #include - #include - #include - - 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 -#elif __APPLE__ - #include -#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 +#include +#include "api/api.h" +#include "renderer.h" + +#ifdef _WIN32 + #include + #include + #include + + 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 +#elif __APPLE__ + #include +#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; +}