[PATCH 0/2] MR11219: Improve theming (Ability to set .theme globally, env var for boolean ones)
Allows .theme files to be set globally with an override environment variable named `WINE_IGNORE_GLOBAL_THEME` . Also allows `GTK_THEME` to be used for apps that make use of dark/light theme setting on windows (Example: https://github.com/keepassxreboot/keepassxc/releases/tag/2.6.6) . I thought of using `GTK_THEME` as users tend to already have that set. I haven't seen any breakage caused by the dark/light theme switch, but in case there is or it's preferred not to be that way for any other reason (e.g. user's windows app becoming dark theme after this commit if they have it set) I can switch it to `WINETHEME` . Examples: Upstream: {width=312 height=357} With commits from my repo combined with a .theme file made off winlator's dark theme values: {width=311 height=360} Keepassxc: {width=900 height=565} {width=900 height=583} Please see; https://list.winehq.org/hyperkitty/list/wine-devel@list.winehq.org/thread/7B... https://bugs.winehq.org/show_bug.cgi?id=59739 -- https://gitlab.winehq.org/wine/wine/-/merge_requests/11219
From: Fatih Bakal <fatihbakal7@protonmail.com> --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 1e3c748c510..dd59bdb9517 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ be used for porting Windows code into native Unix executables. Wine is free software, released under the GNU LGPL; see the file LICENSE for the details. - +placeholder ## QUICK START From the top-level directory of the Wine source (which contains this file), -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11219
From: Fatih Bakal <fatihbakal7@protonmail.com> --- README.md | 1 - dlls/uxtheme/system.c | 347 +++++++++++++++++++++++++++++++------- dlls/uxtheme/uxthemedll.h | 2 +- 3 files changed, 291 insertions(+), 59 deletions(-) diff --git a/README.md b/README.md index dd59bdb9517..4ccb4c7ffeb 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,6 @@ be used for porting Windows code into native Unix executables. Wine is free software, released under the GNU LGPL; see the file LICENSE for the details. -placeholder ## QUICK START From the top-level directory of the Wine source (which contains this file), diff --git a/dlls/uxtheme/system.c b/dlls/uxtheme/system.c index 8f963115cde..9d1cd222b99 100644 --- a/dlls/uxtheme/system.c +++ b/dlls/uxtheme/system.c @@ -135,6 +135,78 @@ static DWORD query_reg_path (HKEY hKey, LPCWSTR lpszValue, * * Set the current active theme from the registry */ + +static const WCHAR * const SysColorsNames[] = +{ + L"Scrollbar", /* COLOR_SCROLLBAR */ + L"Background", /* COLOR_BACKGROUND */ + L"ActiveTitle", /* COLOR_ACTIVECAPTION */ + L"InactiveTitle", /* COLOR_INACTIVECAPTION */ + L"Menu", /* COLOR_MENU */ + L"Window", /* COLOR_WINDOW */ + L"WindowFrame", /* COLOR_WINDOWFRAME */ + L"MenuText", /* COLOR_MENUTEXT */ + L"WindowText", /* COLOR_WINDOWTEXT */ + L"TitleText", /* COLOR_CAPTIONTEXT */ + L"ActiveBorder", /* COLOR_ACTIVEBORDER */ + L"InactiveBorder", /* COLOR_INACTIVEBORDER */ + L"AppWorkSpace", /* COLOR_APPWORKSPACE */ + L"Hilight", /* COLOR_HIGHLIGHT */ + L"HilightText", /* COLOR_HIGHLIGHTTEXT */ + L"ButtonFace", /* COLOR_BTNFACE */ + L"ButtonShadow", /* COLOR_BTNSHADOW */ + L"GrayText", /* COLOR_GRAYTEXT */ + L"ButtonText", /* COLOR_BTNTEXT */ + L"InactiveTitleText", /* COLOR_INACTIVECAPTIONTEXT */ + L"ButtonHilight", /* COLOR_BTNHIGHLIGHT */ + L"ButtonDkShadow", /* COLOR_3DDKSHADOW */ + L"ButtonLight", /* COLOR_3DLIGHT */ + L"InfoText", /* COLOR_INFOTEXT */ + L"InfoWindow", /* COLOR_INFOBK */ + L"ButtonAlternateFace", /* COLOR_ALTERNATEBTNFACE */ + L"HotTrackingColor", /* COLOR_HOTLIGHT */ + L"GradientActiveTitle", /* COLOR_GRADIENTACTIVECAPTION */ + L"GradientInactiveTitle", /* COLOR_GRADIENTINACTIVECAPTION */ + L"MenuHilight", /* COLOR_MENUHILIGHT */ + L"MenuBar", /* COLOR_MENUBAR */ +}; + +static const WCHAR strColorKey[] = L"Control Panel\\Colors"; + +#define NUM_SYS_COLORS (COLOR_MENUBAR+1) + +static void update_personalize_from_env(void) +{ + WCHAR gtk_theme[128]; + DWORD dark_mode = 0; + HKEY hKey; + + if (GetEnvironmentVariableW(L"GTK_THEME", gtk_theme, ARRAY_SIZE(gtk_theme)) && + (wcsstr(gtk_theme, L"dark") || wcsstr(gtk_theme, L"Dark"))) + { + TRACE("GTK_THEME=%s is dark\n", debugstr_w(gtk_theme)); + dark_mode = 1; + } + else + { + TRACE("GTK_THEME not set or not dark\n"); + } + + if (!RegCreateKeyW(HKEY_CURRENT_USER, + L"Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize", &hKey)) + { + DWORD val = dark_mode ? 0 : 1; + TRACE("Writing AppsUseLightTheme=%lu, SystemUsesLightTheme=%lu\n", val, val); + RegSetValueExW(hKey, L"AppsUseLightTheme", 0, REG_DWORD, (BYTE*)&val, sizeof(val)); + RegSetValueExW(hKey, L"SystemUsesLightTheme", 0, REG_DWORD, (BYTE*)&val, sizeof(val)); + RegCloseKey(hKey); + } + else + { + TRACE("Failed to create/open Personalize registry key\n"); + } +} + static void UXTHEME_LoadTheme(void) { HKEY hKey; @@ -142,6 +214,159 @@ static void UXTHEME_LoadTheme(void) HRESULT hr; WCHAR tmp[10]; PTHEME_FILE pt; + BOOL path_resolved = FALSE; + BOOL theme_ignored = FALSE; + BOOL theme_file_override = FALSE; + BOOL prev_override = FALSE; + COLORREF tfc[NUM_SYS_COLORS]; + int tfi[NUM_SYS_COLORS], tfn = 0; + + update_personalize_from_env(); + + /* Read previous .theme file override state */ + { + WCHAR buf[2]; + DWORD size = sizeof(buf); + if (!RegOpenKeyExW(HKEY_CURRENT_USER, szThemeManager, 0, KEY_QUERY_VALUE, &hKey)) + { + if (RegQueryValueExW(hKey, L"ThemeFileOverride", NULL, NULL, (BYTE*)buf, &size)) + buf[0] = L'0'; + RegCloseKey(hKey); + } + else + { + buf[0] = L'0'; + } + prev_override = (buf[0] == L'1'); + } + + /* Check for .theme file first (unconditional, takes priority over registry) */ + { + WCHAR buf[2]; + if (!GetEnvironmentVariableW(L"WINE_IGNORE_GLOBAL_THEME", buf, 2) || buf[0] != L'1') + { + WCHAR path[MAX_PATH]; + DWORD len = GetEnvironmentVariableW(L"XDG_CONFIG_HOME", path, MAX_PATH); + TRACE("XDG_CONFIG_HOME len=%lu\n", len); + if (!len || len >= MAX_PATH) + { + len = GetEnvironmentVariableW(L"WINE_HOST_HOME", path, MAX_PATH); + TRACE("WINE_HOST_HOME len=%lu path=%s\n", len, debugstr_w(path)); + if (len && len < MAX_PATH) lstrcatW(path, L"/.config"); + } + if (len && len < MAX_PATH) + { + path_resolved = TRUE; + lstrcatW(path, L"/wine/theme.theme"); + TRACE("Checking for theme file: %s\n", debugstr_w(path)); + if (GetFileAttributesW(path) != INVALID_FILE_ATTRIBUTES) + { + int i, r, g, b; + WCHAR keys[4096]; + TRACE("Theme file exists\n"); + if (GetPrivateProfileStringW(L"Control Panel\\Colors", NULL, NULL, keys, ARRAY_SIZE(keys), path)) + { + WCHAR *key = keys; + TRACE("Found keys in theme file\n"); + while (*key) + { + WCHAR value[256]; + GetPrivateProfileStringW(L"Control Panel\\Colors", key, L"", value, ARRAY_SIZE(value), path); + TRACE("Reading color %s = %s\n", debugstr_w(key), debugstr_w(value)); + if (swscanf(value, L"%d %d %d", &r, &g, &b) == 3) + { + for (i = 0; i < NUM_SYS_COLORS; i++) + { + if (!lstrcmpW(key, SysColorsNames[i])) + { + tfi[tfn] = i; + tfc[tfn++] = RGB(r, g, b); + break; + } + } + } + key += lstrlenW(key) + 1; + } + theme_file_override = (tfn > 0); + if (tfn) + TRACE("Stored %d colors from .theme file for override\n", tfn); + else + TRACE("No known SysColors matched in .theme file\n"); + } + else + { + TRACE("No keys found in theme file\n"); + } + TRACE("XDG theme file processed: %s\n", debugstr_w(path)); + } + else + { + TRACE("Theme file not found at %s\n", debugstr_w(path)); + } + } + else + { + TRACE("Could not determine config path\n"); + } + } + else + { + TRACE("WINE_IGNORE_GLOBAL_THEME is set to 1, skipping\n"); + theme_ignored = TRUE; + } + } + + /* Persist current override state for next boot */ + { + WCHAR val[2] = { theme_file_override ? L'1' : L'0', 0 }; + if (!RegCreateKeyW(HKEY_CURRENT_USER, szThemeManager, &hKey)) + { + RegSetValueExW(hKey, L"ThemeFileOverride", 0, REG_SZ, (BYTE*)val, sizeof(val)); + RegCloseKey(hKey); + } + } + + if (theme_file_override) + { + int i, length; + WCHAR string[13]; + HKEY hkey; + + bThemeActive = FALSE; + TRACE(".theme file override active, deactivating theme engine\n"); + + MSSTYLES_SetActiveTheme(NULL, FALSE); + + if (!RegCreateKeyW(HKEY_CURRENT_USER, szThemeManager, &hKey)) + { + tmp[0] = L'0'; + tmp[1] = L'\0'; + RegSetValueExW(hKey, L"ThemeActive", 0, REG_SZ, (const BYTE *)tmp, 2 * sizeof(WCHAR)); + RegDeleteValueW(hKey, L"ColorName"); + RegDeleteValueW(hKey, L"SizeName"); + RegDeleteValueW(hKey, L"DllName"); + RegDeleteValueW(hKey, L"LoadedBefore"); + RegCloseKey(hKey); + } + + TRACE("Applying %d colors from .theme file\n", tfn); + SetSysColors(tfn, tfi, tfc); + + if (!RegCreateKeyExW(HKEY_CURRENT_USER, strColorKey, 0, 0, 0, KEY_ALL_ACCESS, 0, &hkey, 0)) + { + for (i = 0; i < NUM_SYS_COLORS; i++) + { + COLORREF color = GetSysColor(i); + length = swprintf(string, ARRAY_SIZE(string), L"%d %d %d", + GetRValue(color), GetGValue(color), GetBValue(color)); + RegSetValueExW(hkey, SysColorsNames[i], 0, REG_SZ, (BYTE *)string, + (length + 1) * sizeof(WCHAR)); + } + RegCloseKey(hkey); + } + + return; + } /* Get current theme configuration */ if(!RegOpenKeyW(HKEY_CURRENT_USER, szThemeManager, &hKey)) { @@ -184,58 +409,47 @@ static void UXTHEME_LoadTheme(void) lstrcpynW(szCurrentColor, pt->pszSelectedColor, ARRAY_SIZE(szCurrentColor)); lstrcpynW(szCurrentSize, pt->pszSelectedSize, ARRAY_SIZE(szCurrentSize)); - UXTHEME_SetActiveTheme(pt); + UXTHEME_SetActiveTheme(pt, prev_override, theme_file_override); TRACE("Theme active: %s %s %s\n", debugstr_w(szCurrentTheme), debugstr_w(szCurrentColor), debugstr_w(szCurrentSize)); MSSTYLES_CloseThemeFile(pt); } } if(!bThemeActive) { - MSSTYLES_SetActiveTheme(NULL, FALSE); - TRACE("Theming not active\n"); + if (theme_ignored || path_resolved) + { + WCHAR default_path[MAX_PATH]; + DWORD len = GetWindowsDirectoryW(default_path, MAX_PATH); + if (len && len < MAX_PATH - 50) + { + lstrcatW(default_path, L"\\resources\\themes\\aero\\aero.msstyles"); + if (GetFileAttributesW(default_path) != INVALID_FILE_ATTRIBUTES) + { + PTHEME_FILE pt; + HRESULT hr = MSSTYLES_OpenThemeFile(default_path, NULL, NULL, &pt); + if (SUCCEEDED(hr)) + { + lstrcpynW(szCurrentTheme, default_path, ARRAY_SIZE(szCurrentTheme)); + lstrcpynW(szCurrentColor, pt->pszSelectedColor, ARRAY_SIZE(szCurrentColor)); + lstrcpynW(szCurrentSize, pt->pszSelectedSize, ARRAY_SIZE(szCurrentSize)); + UXTHEME_SetActiveTheme(pt, prev_override, theme_file_override); + TRACE("Default theme activated: %s\n", debugstr_w(szCurrentTheme)); + MSSTYLES_CloseThemeFile(pt); + } + } + } + } + if (!bThemeActive) + { + MSSTYLES_SetActiveTheme(NULL, FALSE); + TRACE("Theming not active\n"); + } } -} -/***********************************************************************/ -static const WCHAR * const SysColorsNames[] = -{ - L"Scrollbar", /* COLOR_SCROLLBAR */ - L"Background", /* COLOR_BACKGROUND */ - L"ActiveTitle", /* COLOR_ACTIVECAPTION */ - L"InactiveTitle", /* COLOR_INACTIVECAPTION */ - L"Menu", /* COLOR_MENU */ - L"Window", /* COLOR_WINDOW */ - L"WindowFrame", /* COLOR_WINDOWFRAME */ - L"MenuText", /* COLOR_MENUTEXT */ - L"WindowText", /* COLOR_WINDOWTEXT */ - L"TitleText", /* COLOR_CAPTIONTEXT */ - L"ActiveBorder", /* COLOR_ACTIVEBORDER */ - L"InactiveBorder", /* COLOR_INACTIVEBORDER */ - L"AppWorkSpace", /* COLOR_APPWORKSPACE */ - L"Hilight", /* COLOR_HIGHLIGHT */ - L"HilightText", /* COLOR_HIGHLIGHTTEXT */ - L"ButtonFace", /* COLOR_BTNFACE */ - L"ButtonShadow", /* COLOR_BTNSHADOW */ - L"GrayText", /* COLOR_GRAYTEXT */ - L"ButtonText", /* COLOR_BTNTEXT */ - L"InactiveTitleText", /* COLOR_INACTIVECAPTIONTEXT */ - L"ButtonHilight", /* COLOR_BTNHIGHLIGHT */ - L"ButtonDkShadow", /* COLOR_3DDKSHADOW */ - L"ButtonLight", /* COLOR_3DLIGHT */ - L"InfoText", /* COLOR_INFOTEXT */ - L"InfoWindow", /* COLOR_INFOBK */ - L"ButtonAlternateFace", /* COLOR_ALTERNATEBTNFACE */ - L"HotTrackingColor", /* COLOR_HOTLIGHT */ - L"GradientActiveTitle", /* COLOR_GRADIENTACTIVECAPTION */ - L"GradientInactiveTitle", /* COLOR_GRADIENTINACTIVECAPTION */ - L"MenuHilight", /* COLOR_MENUHILIGHT */ - L"MenuBar", /* COLOR_MENUBAR */ -}; - -static const WCHAR strColorKey[] = L"Control Panel\\Colors"; +} -#define NUM_SYS_COLORS (COLOR_MENUBAR+1) +/***********************************************************************/ struct system_metrics { @@ -366,7 +580,7 @@ static void UXTHEME_SaveUnthemedSystemMetrics(struct system_metrics *metrics) } } -/* Make system settings persistent, so they're in effect even w/o uxtheme +/* Make system settings persistent, so they're in effect even w/o uxtheme * loaded. * For efficiency reasons, only the last SystemParametersInfoW sets * SPIF_SENDWININICHANGE */ @@ -418,7 +632,7 @@ static void UXTHEME_SaveSystemMetrics(struct system_metrics *metrics, BOOL send_ * * Change the current active theme */ -HRESULT UXTHEME_SetActiveTheme(PTHEME_FILE tf) +HRESULT UXTHEME_SetActiveTheme(PTHEME_FILE tf, BOOL prev_override, BOOL override_pending) { BOOL ret, loaded_before = FALSE, same_theme = FALSE; struct system_metrics metrics; @@ -448,7 +662,7 @@ HRESULT UXTHEME_SetActiveTheme(PTHEME_FILE tf) WARN("Failed to get LoadedBefore: %ld\n", GetLastError()); RegCloseKey(hKey); } - if (loaded_before && same_theme) + if (loaded_before && same_theme && (prev_override == override_pending)) return MSSTYLES_SetActiveTheme(tf, FALSE); if (!loaded_before && ret) @@ -960,7 +1174,7 @@ HRESULT WINAPI ApplyTheme(HTHEMEFILE hThemeFile, char *unknown, HWND hWnd) { HRESULT hr; TRACE("(%p,%s,%p)\n", hThemeFile, unknown, hWnd); - hr = UXTHEME_SetActiveTheme(hThemeFile); + hr = UXTHEME_SetActiveTheme(hThemeFile, FALSE, FALSE); UXTHEME_broadcast_msg (NULL, WM_THEMECHANGED); return hr; } @@ -1268,15 +1482,34 @@ void WINAPI RefreshImmersiveColorPolicyState(void) * RETURNS * Whether or not the system should use dark mode. */ -BOOLEAN WINAPI ShouldSystemUseDarkMode(void) +static BOOL check_gtk_theme_dark(void) { - DWORD light_theme = TRUE, light_theme_size = sizeof(light_theme); + WCHAR gtk_theme[128]; + BOOL found = GetEnvironmentVariableW(L"GTK_THEME", gtk_theme, ARRAY_SIZE(gtk_theme)); + BOOL dark = found && (wcsstr(gtk_theme, L"dark") || wcsstr(gtk_theme, L"Dark")); + TRACE("GTK_THEME=%s found=%d dark=%d\n", debugstr_w(gtk_theme), found, dark); + return dark; +} +static BOOL check_light_theme_registry(LPCWSTR value) +{ + DWORD light_theme = TRUE, light_theme_size = sizeof(light_theme); RegGetValueW(HKEY_CURRENT_USER, L"Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize", - L"SystemUsesLightTheme", RRF_RT_REG_DWORD, NULL, &light_theme, &light_theme_size); + value, RRF_RT_REG_DWORD, NULL, &light_theme, &light_theme_size); + TRACE("%s=%lu\n", debugstr_w(value), light_theme); + return light_theme; +} - return !light_theme; +BOOLEAN WINAPI ShouldSystemUseDarkMode(void) +{ + BOOL dark; + if (check_gtk_theme_dark()) + dark = TRUE; + else + dark = !check_light_theme_registry(L"SystemUsesLightTheme"); + TRACE("returning %d\n", dark); + return dark; } /********************************************************************** @@ -1287,13 +1520,13 @@ BOOLEAN WINAPI ShouldSystemUseDarkMode(void) */ BOOLEAN WINAPI ShouldAppsUseDarkMode(void) { - DWORD light_theme = TRUE, light_theme_size = sizeof(light_theme); - - RegGetValueW(HKEY_CURRENT_USER, - L"Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize", - L"AppsUseLightTheme", RRF_RT_REG_DWORD, NULL, &light_theme, &light_theme_size); - - return !light_theme; + BOOL dark; + if (check_gtk_theme_dark()) + dark = TRUE; + else + dark = !check_light_theme_registry(L"AppsUseLightTheme"); + TRACE("returning %d\n", dark); + return dark; } /********************************************************************** diff --git a/dlls/uxtheme/uxthemedll.h b/dlls/uxtheme/uxthemedll.h index aa073cbbb3c..3ef56f20ac1 100644 --- a/dlls/uxtheme/uxthemedll.h +++ b/dlls/uxtheme/uxthemedll.h @@ -102,7 +102,7 @@ BOOL WINAPI ThemeHooksInstall(void); BOOL WINAPI ThemeHooksRemove(void); extern void UXTHEME_InitSystem(HINSTANCE hInst); -extern HRESULT UXTHEME_SetActiveTheme(PTHEME_FILE tf); +extern HRESULT UXTHEME_SetActiveTheme(PTHEME_FILE tf, BOOL prev_override, BOOL override_pending); extern void UXTHEME_UninitSystem(void); extern struct user_api_hook user_api; -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11219
The MR is poorly written. Each commit should be small and serve a purpose. That aside, I don't think this is suitable for upstream. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/11219#note_143955
The MR is poorly written. Each commit should be small and serve a purpose.
Valid, I should probably squash all of them with a better commit message.
That aside, I don't think this is suitable for upstream.
Issues related to this were left open so I thought the feature would be welcome. Is there something I can chamge to make it suitable for upstream? -- https://gitlab.winehq.org/wine/wine/-/merge_requests/11219#note_143957
On Tue Jun 23 07:20:06 2026 +0000, Fatih Bakal wrote:
The MR is poorly written. Each commit should be small and serve a purpose. Valid, I should probably squash all of them with a better commit message. That aside, I don't think this is suitable for upstream. Issues related to this were left open so I thought the feature would be welcome. Is there something I can chamge to make it suitable for upstream? In this case, I am afraid the answer is no. I don't think it's worth it to add an environment variable to upstream Wine for such use cases.
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/11219#note_143962
I don't think it's worth it to add an environment variable to upstream Wine for such use cases.
Would it be okay if I did it without making use of env vars at all? Or is it not welcome at all (I know you said no at first but then mentioned env vars) If the answer is still no I'll close this and probbaly link the reply on the open issues (would be cool if those were closed in that case) -- https://gitlab.winehq.org/wine/wine/-/merge_requests/11219#note_143963
On Tue Jun 23 07:39:09 2026 +0000, Fatih Bakal wrote:
I don't think it's worth it to add an environment variable to upstream Wine for such use cases. Would it be okay if I did it without making use of env vars at all? Or is it not welcome at all (I know you said no at first but then mentioned env vars) If the answer is still no I'll close this and probbaly link the reply on the open issues (would be cool if those were closed in that case) It's not a problem with using environment variables. It's a problem because such a feature is not present in Windows, so it's a Wine-only feature. Then it's not that useful for the broad users because you can achieve the same thing with scripting. Then it becomes that we have to maintain a feature that people rarely use.
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/11219#note_143965
It's a problem because such a feature is not present in Windows
Valid but on windows one doesn't have to prefixes to worry about (.theme files exist on windows so I believe what you mean is setting it through something like .comfig? ) . I'm not sure if gui developers would be willing to implement this. Also is there a script that you know of for this? Idk how itd be done unless theres something running always checking for mew prefixes. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/11219#note_143966
On Tue Jun 23 08:06:56 2026 +0000, Fatih Bakal wrote:
It's a problem because such a feature is not present in Windows Valid but on windows one doesn't have to prefixes to worry about (.theme files exist on windows so I believe what you mean is setting it through something like .comfig? ) . I'm not sure if gui developers would be willing to implement this. Also is there a script that you know of for this? Idk how itd be done unless theres something running always checking for mew prefixes. The theme file paths are stored in the registry. Please see UXTHEME_LoadTheme(). Certainly, you can use the reg command to write a script to set the default theme to a different one.
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/11219#note_143967
Please see UXTHEME_LoadTheme(). Certainly, you can use the reg command to write a script to set the default theme to a different one.
`wine reg import ~.config/wine/theme.reg` would just do it for the default prefix once (if ~/.wine was deleted would need to be run again) There's also all the games in `~/Games/Heroic/Prefixes/` `.var/app/com.valvesoftware.Steam/.steam/steam/steamapps/compatdata/` and so on.. Not to repeat what's been said already but I really don't know how I can do it in a way that doesn't require me running something whenever I setup a new prefix unless there's something running 7/24 that's keeping track of everything (prefixes and which have the theme applied) -- https://gitlab.winehq.org/wine/wine/-/merge_requests/11219#note_143977
Not to repeat what's been said already but I really don't know how I can do it in a way that doesn't require me running something whenever I setup a new prefix
Maybe you can add it to the prefix setup script. For example, the proton script for Proton. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/11219#note_143978
Maybe you can add it to the prefix setup script. For example, the proton script for Proton.
I'd have to re-edit it each time it got updated just like the approach where the .msstyles file is replaced. Edit: I'd also have to do it for every proton build (regular, ge,dawn winery) -- https://gitlab.winehq.org/wine/wine/-/merge_requests/11219#note_143979
On Tue Jun 23 09:52:08 2026 +0000, Fatih Bakal wrote:
Maybe you can add it to the prefix setup script. For example, the proton script for Proton. I'd have to re-edit it each time it got updated just like the approach where the .msstyles file is replaced. Edit: I'd also have to do it for every proton build (regular, ge,dawn winery, and idk how id do it for wine) It might be worth trying to write some generic mechanism to apply a given registry script on prefix setup. This isn't the first time that would end up being useful.
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/11219#note_144001
It might be worth trying to write some generic mechanism to apply a given registry script on prefix setup.
Like getting it upstream for proton or wine? e.g. `~/.config/wine/reg1` (gets auto imported upon pfx creation) or `WINEREGAPPLY=~/.config/wine` (just an example ik env vars arent that welcome) Again would there be interest in merging something like that? If so I'll see what I can do -- https://gitlab.winehq.org/wine/wine/-/merge_requests/11219#note_144004
Like getting it upstream for proton or wine?
I'd be surprised if it's wanted for proton at all; I was thinking about upstream Wine.
e.g. `~/.config/wine/*.reg` (gets auto imported upon pfx creation) or `WINEREGAPPLY=~/.config/wine` (just an example ik env vars arent that welcome)
Both approaches seem reasonable enough to me.
Again would there be interest in merging something like that? If so I'll see what I can do
I can't answer that; that'd have to be a question for Alexandre. My gut on what Alexandre would like, which is not particularly reliable, says "maybe". -- https://gitlab.winehq.org/wine/wine/-/merge_requests/11219#note_144008
I'd be surprised if it's wanted for proton at all; I was thinking about upstream Wine.
Just the top of my head a lot of game mod managers and what not have a file explorer button/import/export dialogs.. which all use the default theme so seems fit to me (not even mentioning other stuff you can do with .regs)
I can't answer that; that'd have to be a question for Alexandre.
@julliard sorry for the ping but what do you say? -- https://gitlab.winehq.org/wine/wine/-/merge_requests/11219#note_144011
On Tue Jun 23 18:57:26 2026 +0000, Fatih Bakal wrote:
I'd be surprised if it's wanted for proton at all; I was thinking about upstream Wine. Just the top of my head a lot of game mod managers and what not have a file explorer button/import/export dialogs.. which all use the default theme so seems fit to me (not even mentioning other stuff you can do with .regs) I can't answer that; that'd have to be a question for Alexandre. @julliard sorry for the ping but what do you say? Like @zf said, "maybe". Basically it would need a convincing argument, taking into account the various possible use cases, as well as possible issues it would create.
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/11219#note_144017
On Tue Jun 23 19:51:32 2026 +0000, Alexandre Julliard wrote:
Like @zf said, "maybe". Basically it would need a convincing argument, taking into account the various possible use cases, as well as possible issues it would create. It's definitely not the first time I've heard people request something that would be addressed by it, and I don't think it's always been about theming. I can't well recall what the other cases were, though. I believe virtual desktop and Windows version were two such. I'd find it pretty useful myself for setting the virtual desktop keys.
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/11219#note_144044
On Tue Jun 23 21:31:42 2026 +0000, Elizabeth Figura wrote:
It's definitely not the first time I've heard people request something that would be addressed by it, and I don't think it's always been about theming. I can't well recall what the other cases were, though. I believe virtual desktop and Windows version were two such. I'd find it pretty useful myself for setting the virtual desktop keys. A list of stuff that can be done with this; (I'll edit this post when I find new stuff)
Use cases: - setting the windows version (also per-application e.g. `Software\\Wine\\AppDefaults\\placeholder` - setting dlloverrides per .exe name. (though im not sure if dll overrides will be as relevant in general once [this commit](https://gitlab.winehq.org/wine/wine/-/commit/a31ec8da9572672e04ae46792a398da...) makes its way into stable wine/proton, I don't think it's in yet.) ``` [HKEY_CURRENT_USER\Software\Wine\AppDefaults\PVZ.Main_Win64_Retail.exe\DllOverrides] "dinput8"="native,builtin" "winmm"="native,builtin" ``` - set file explorer to native one (https://gist.github.com/maotovisk/1bf3a7c9054890f91b9234c3663c03a2) - allow theming - allow setting `ShowDotFiles` - allow setting dpi ([Software\\Wine\\Fonts] & Control Panel\\Desktop) Cons: Not much I can think of as of right now -- https://gitlab.winehq.org/wine/wine/-/merge_requests/11219#note_144054
On Wed Jun 24 14:07:10 2026 +0000, Fatih Bakal wrote:
A list of stuff that can be done with this; (I'll edit this post when I find new stuff) Use cases: - setting the windows version globally & per .exe name ``` [Software\\Wine\\AppDefaults\\placeholder] "Version"="win81" ``` - setting dlloverrides per .exe name, not mentioning global as `WINEDLLOVERRIDES` already exists. (though im not sure if dll overrides will be as relevant in general once [this commit](https://gitlab.winehq.org/wine/wine/-/commit/a31ec8da9572672e04ae46792a398da...) makes its way into stable wine/proton, I don't think it's in yet.) ``` [HKEY_CURRENT_USER\Software\Wine\AppDefaults\PVZ.Main_Win64_Retail.exe\DllOverrides] "dinput8"="native,builtin" "winmm"="native,builtin" ``` - set owner & organization name - set file explorer to native one (https://gist.github.com/maotovisk/1bf3a7c9054890f91b9234c3663c03a2) - allow theming - allow setting `ShowDotFiles` - allow setting `Manage file and protocol associations` ``` [Software\\Wine\\FileOpenAssociations] "Enable"="Y" ``` - allow setting dpi (Software\\Wine\\Fonts & Control Panel\\Desktop) - configure driver related stuff (winepulse.drv & maybe forcing winewayland.drv in `HKEY_CURRENT_USER\Software\Wine\Drivers` without unsetting `DISPLAY`) - allow setting csd & window manager/virtual desktop related stuff ``` [Software\\Wine\\X11 Driver] "Decorated"="N" "Managed"="N" "GrabFullscreen"="Y" [Software\\Wine\\Explorer\\Desktops] "Default"="1920x1080" ``` - allow disabling controllers ``` [Software\\Wine\\DirectInput\\Joysticks] "Controller (XBOX 360 For Windows)"="disabled" ``` - Allow setting wine only environment variables ( `HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment` ) - Mapping folders (This allows for global symlinks instead of it making it prefix only like `~/.wine/drive_c/users/twig/Favorites` (really useful in my opinion): ``` Windows Registry Editor Version 5.00 [HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders] "Favorites"="Z:\\home\\twig\\.local\\share\\wine" [HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders] "Favorites"="Z:\\home\\twig\\.local\\share\\wine" ``` {width=866 height=600} Cons: - Not much I can think of as of right now
Basically it would need a convincing argument All these settings are kinda tiring to set on all prefixes (most users want them to be the same across prefixes) @julliard sorry for the ping again. I've compiled a list of things that can be done through .reg files above. What do you say (as in if it's worth merging an implementation of it or not) ?
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/11219#note_144107
On Wed Jun 24 14:09:33 2026 +0000, Fatih Bakal wrote:
@julliard sorry for the ping again. I've compiled a list of things that can be done through .reg files above. What do you say (as in if it's worth merging an implementation of it or not) ? @julliard bump. sorry for the ping. I've waited for 2 weeks for a response and didn't get one (totally fine I get it just stating what happened)
(I'll wait for 2 months for the next ping, I hope this isn't disturbing I'm just trying to get started on this as soon as I can depending on the response) -- https://gitlab.winehq.org/wine/wine/-/merge_requests/11219#note_145196
On Wed Jul 8 15:15:46 2026 +0000, Fatih Bakal wrote:
@julliard bump. sorry for the ping. I've waited for 2 weeks for a response and didn't get one (totally fine I get it just stating what happened) (I'll wait for 2 months for the next ping, I hope this isn't disturbing I'm just trying to get started on this as soon as I can depending on the response) @julliard bump. What do you say about this? (It's been 2 months and I don't think it's realistic to wait for 2 years for the next bump)
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/11219#note_149803
On Tue Aug 25 08:13:19 2026 +0000, Fatih Bakal wrote:
@julliard bump. What do you say about this? (It's been 2 months and I don't think it's realistic to wait for 2 years for the next bump) It would be more convincing with an actual prototype, and also by trying harder to find counter-arguments.
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/11219#note_149804
participants (5)
-
Alexandre Julliard (@julliard) -
Elizabeth Figura (@zfigura) -
Fatih Bakal -
Fatih Bakal (@Twig) -
Zhiyi Zhang (@zhiyi)