diff --git a/mods/accent-color-sync.wh.cpp b/mods/accent-color-sync.wh.cpp index 29a7cae37..4f0c113be 100644 --- a/mods/accent-color-sync.wh.cpp +++ b/mods/accent-color-sync.wh.cpp @@ -1,10 +1,11 @@ // ==WindhawkMod== // @id accent-color-sync // @name Accent Color Sync -// @description Synchronises OpenGlass and Control Panel color settings -// @description:fr-FR Synchronisation des couleurs d'OpenGlass et du Panneau de configuration -// @description:es-ES Sincroniza los colores de OpenGlass y del Panel de control -// @version 1.41 +// @description Restores Control Panel color opacity functionality +// @description:fr-FR Retour de la fonctionnalité d'opacité des couleurs du Panneau de configuration +// @description:es-ES Recuperar la funcionalidad de opacidad de colores del Panel de control +// @description:ja-JP コントロールパネルの色の不透明度機能を復元する +// @version 1.5 // @author CatmanFan / Mr._Lechkar // @github https://github.com/CatmanFan // @include explorer.exe @@ -15,42 +16,91 @@ // ==WindhawkModReadme== /* -Brings back the functionality of the 'Color intensity' slider to Windows 10 using OpenGlass. The mod synchronises OpenGlass's Aero settings with the slider value. +Brings back the functionality of the Control Panel's "Color intensity" slider to Windows 10 1809 and above, using third-party DWM shader software (e.g. OpenGlass, Glass8). The mod synchronises the Aero colorization parameters used by the supported DWM customization software with the slider value. +## **⚠️ Requirements:** +**This mod requires that *one* of the following supported DWM shader applications is installed and running:** +* **[Legacy OpenGlass](https://github.com/ALTaleX531/OpenGlass/tree/legacy)**, supports Windows 10 1809 ― Windows 11 23H2; + * It is generally recommended to compile the source code from the official repo, but a list of OpenGlass-legacy downloads is also available *[here](https://github.com/ALTaleX531/OpenGlass/releases)*. +* **[Glass8](https://archive.org/details/full-glass8-archive)**, supports Windows 10 RTM to 1909 builds. + * Please note that the shader used by this software is not accurate to the original. -## **⚠️ To use this mod, you will need [kfh83](https://github.com/kfh83)'s OpenGlass-legacy fork.** -### It is generally recommended to compile the source code from *[the official repo](https://github.com/ALTaleX531/OpenGlass/tree/legacy)*, but a list of OpenGlass-legacy downloads is also available *[here](https://github.com/ALTaleX531/OpenGlass/releases)*. - -### *Additional tips:* -* If you are updating this mod from any prior versions, you must rename the three colorization values in the DWM registry starting with "***og_**(name)*" to "*(name)**Override***"; for example, ***og_**ColorizationColorBalance* to *ColorizationColorBalance**Override***. This is required so that the mod will be able to read the new values. - * Do **not** touch the "*og_Opacity*" value, as that is only used by this mod and is thus left unchanged. -* If you are updating this mod from version 1.0, it is required to disable or uninstall any other existing DWM shader software (such as regular OpenGlass or DWMBlurGlass). +### **Additional tips:** +* If you are updating this mod from version 1.0, it is required to disable or uninstall any unsupported DWM shader software (e.g. regular OpenGlass or DWMBlurGlass). * If you are updating this mod from version 1.3, it is recommended to also enable the *Sync with DWM* option from the mod's settings, although this can have some minor bugs (see below). * You may need to try changing the accent color manually if changes do not automatically take effect. +* If one of the OpenGlass options in the *'DWM customization software'* section of the mod settings (i.e. the options labelled "OpenGlass" or "OpenGlass (old registry name)") is not working, try setting it to the other one. This is because while official builds of OpenGlass now use the registry value name template "{xxx}Override" instead of the older "og_{xxx}", this is not the case for some separately-compiled builds, or ports such as [Tech Stuff](https://teknixstuff.com/)'s "OpenGlass Legacy - Windhawk edition". ---- ### Known bugs: * ***Sync with DWM* option enabled:** - * When changing the color intensity in the Control Panel without changing the color itself, the theme preview icon used for the color does not change unless after the theme preview is regenerated by changing the color RGB values or the desktop background. + * When changing the color intensity in the Control Panel without changing the color itself, the theme preview icon used for the color does not change unless after the theme preview is regenerated by changing the color RGB values or the desktop background. * Actually closing the Personalization window does not produce the same behaviour as clicking "Cancel" (i.e. the RGB color is changed but the OpenGlass opacity stays the same). * When using [Explorer7](https://github.com/Erizur/explorer7-releases/), the Start menu may not immediately change in opacity and requires a restart of explorer.exe. This may be fixed with schm1dt's glass POC mod downloadable [here](https://winclassic.net/post/24274). ### Special credits: * [OjasK](https://github.com/ojask) for his DirectUI reverse-engineering work, part of which was referenced in the making of this mod. -* [ALTaleX](https://github.com/ALTaleX531) for the incredible work on OpenGlass, and on porting the Windows 7 DWM colorization functionality to open-source code with [this formula](https://github.com/ALTaleX531/dwm_colorization_calculator). +* [ALTaleX](https://github.com/ALTaleX531) for the incredible work on OpenGlass, and on porting the Windows 7 DWM colorization functionality to open-source code with [this formula](https://github.com/ALTaleX531/dwm_colorization_calculator); as well as [kfh83](https://github.com/kfh83) on porting the Windows 7-esque shader to OpenGlass-legacy. + */ // ==/WindhawkModReadme== // ==WindhawkModSettings== /* +- fixedOpacity: + - enable: TRUE + $name: Enabled + $name:fr-FR: Activer l'option + $name:es-ES: Habilitada + $name:ja-JP: 有効化 + - value: 25 + $name: Value (0-100) + $name:fr-FR: Valeur (0-100) + $name:es-ES: Valor (0-100) + $name:ja-JP: 値(0~100) + $name: Fixed opacity + $name:fr-FR: Opacité fixe + $name:es-ES: Opacidad fijada + $name:ja-JP: 一定の不透明度 + $description: Permanently sets the OpenGlass opacity at a fixed value. This can be useful if the color is set to automatic based on desktop background. + $description:fr-FR: Définir l'opacité d'OpenGlass de façon permanente sur une valeur fixe. Cela peut être utile lorsque la couleur d'accentuation est automatiquement extraite d'un arrière-plan. + $description:es-ES: Establece de forma permanente la opacidad de OpenGlass en un valor fijo. Puede ser útil para cualquier color de énfasis del fondo de escritorio. + $description:ja-JP: オーペングラスの不透明度を一定の値に設定します。アクセントカラーが背景から自動的に設定されると有益かもしれません。 - syncDWM: TRUE $name: Sync with DWM $name:fr-FR: Synchroniser avec DWM $name:es-ES: Sincronizar con DWM + $name:ja-JP: DWMと同期する $description: Writes the opacity value to DWM's color and afterglow variables. This makes it so that the opacity is also written to the theme alongside the color's RGB. Otherwise, Windows automatically sets it to remain stationary at 0xc4 (196 of 255). $description:fr-FR: Sauvegarder la valeur d'opacité aux options de DWM. Cela permet de définir également l'opacité dans le thème simultanément avec les valeurs du RVB. Sinon, Windows le définit en permanence à 0xc4 (196 sur 255). - $description:es-ES: Guarda el valor de opacidad de OpenGlass en DWM. Esto le permite guardar la opacidad del tema, simultáneamente con los valores RGB. Windows normalmente establece la opacidad siempre en 0xc4 (196 de 255). + $description:es-ES: Guarda el valor de opacidad de OpenGlass en DWM. Esto lo permite guardar la opacidad del tema que Windows normalmente siempre establece en 0xc4, o 196 de 255, simultáneamente con los valores RGB. + $description:ja-JP: 不透明度の値をDWM設定に保存します。 +- glassSoftware: og2 + $options: + - og2: OpenGlass + - og1: OpenGlass (old registry name) + - glass8: Glass8 + $options:fr-FR: + - og2: OpenGlass + - og1: OpenGlass (anciennes valeurs de registre) + - glass8: Glass8 + $options:es-ES: + - og2: OpenGlass + - og1: OpenGlass (nombres antiguos de valores de registro) + - glass8: Glass8 + $options:ja-JP: + - og2: OpenGlass + - og1: OpenGlass(レジストリ値の古い名前) + - glass8: Glass8 + $name: DWM customization software + $name:fr-FR: Logiciel de modification du gestionnaire des fenêtres (DWM) + $name:es-ES: Software de modificación de interfaz gráfica DWM + $name:ja-JP: DWMカスタマイズソフトウェア + $description: The application currently being used to implement the Aero shader. + $description:fr-FR: L'application actuellement utilisée pour implémenter le shader Aero classique. + $description:es-ES: La aplicación que se utiliza actualmente para implementar la funcionalidad de Aero. + $description:ja-JP: Aeroシェーダー効果を反映するために現在使用されているアプリケーション */ // ==/WindhawkModSettings== @@ -73,21 +123,30 @@ Brings back the functionality of the 'Color intensity' slider to Windows 10 usin #include #include #include +#include #include #include #include +const std::wstring dwmKey = L"SOFTWARE\\Microsoft\\Windows\\DWM"; +const std::wstring opacityValue = L"og_Opacity"; + +enum class GlassSoftware { OpenGlass2, OpenGlass1, Glass8 }; +enum class WinVersion { None, Unsupported, Win10, Win11 }; +WinVersion winVer; + struct { + GlassSoftware glassApp; int opacity; + int fixedOpacity; + bool fixedOpacitySet; bool boolTransparency; bool boolSyncDWM; } settings; -enum class WinVersion { None, Unsupported, Win10, Win11 }; -WinVersion winVer; - -const std::wstring dwmKey = L"SOFTWARE\\Microsoft\\Windows\\DWM"; -const std::wstring opacityValue = L"og_Opacity"; +std::wstring balanceColor; +std::wstring balanceAfterglow; +std::wstring balanceBlur; #pragma region ----- Registry functions ----- /** @@ -201,7 +260,7 @@ BOOL exists_Key(std::wstring sk) * @param data The DWORD value to write. * @return `TRUE` if the operation succeeded, otherwise `FALSE`. */ -BOOL set_DWORD(std::wstring sk, std::wstring v, unsigned long data) +BOOL set_DWORD(std::wstring sk, std::wstring v, unsigned long data, bool del = FALSE) { const LPCTSTR subkey = sk.c_str(); const LPCTSTR value = v.c_str(); @@ -213,7 +272,7 @@ BOOL set_DWORD(std::wstring sk, std::wstring v, unsigned long data) return FALSE; } - LONG setRes = data < 0 ? RegDeleteValue(hKey, value) : RegSetValueEx(hKey, value, 0, REG_DWORD, (const BYTE*)&data, sizeof(data)); + LONG setRes = del ? RegDeleteValue(hKey, value) : RegSetValueEx(hKey, value, 0, REG_DWORD, (const BYTE*)&data, sizeof(data)); RegCloseKey(hKey); if (setRes == ERROR_SUCCESS) { @@ -226,10 +285,26 @@ BOOL set_DWORD(std::wstring sk, std::wstring v, unsigned long data) #pragma endregion #pragma region ----- DWM colorization calculator ----- -// ---------------------------------------------------------------------------- +/* ---------------------------------------------------------------------------- // Original code is by ALTaleX !! (converted from Python) // https://github.com/ALTaleX531/dwm_colorization_calculator/blob/main/main.py // ---------------------------------------------------------------------------- +// +// ************************************** +// IN ORDER: +// 1. HSB and ARGB +// 2. Colorization color, which generates ARGB from intensity and HSB and is convertable +// 3. DWM colorization parameters (the good stuff) +// ************************************** +// +// ---------------------------------------------------------------------------- +// ALL DOCUMENTATION FOLLOWING THIS COMMENT HAS BEEN COPIED FROM THEIR CODE FOR REFERENCE. +// ---------------------------------------------------------------------------- +*/ + +class dwm_colorization_parameters; + +class colorization_color; class hsb { public: @@ -237,94 +312,102 @@ class hsb { float saturation; // 0-1 float brightness; // 0-1 - hsb(float hue, float saturation, float brightness) - : hue(hue) - , saturation(saturation) - , brightness(brightness) - { + hsb(float hue, float saturation, float brightness) : hue(hue), saturation(saturation), brightness(brightness) { } void log() { Wh_Log(L"[H: %d, S: %d, B: %d]", hue, saturation, brightness); } }; -// Just the plain ARGB value -// ************************************** -class argb { -public: +class argb { public: int value; - argb(int value) - : value(value) - { - } + argb(int value) : value(value) {} - int get_a() const { return (value & 0xFF000000) >> 24; } - int get_r() const { return (value & 0x00FF0000) >> 16; } - int get_g() const { return (value & 0x0000FF00) >> 8; } - int get_b() const { return (value & 0x000000FF); } + int get_a() const { return (this->value & 0xFF000000) >> 24; } + int get_r() const { return (this->value & 0x00FF0000) >> 16; } + int get_g() const { return (this->value & 0x0000FF00) >> 8; } + int get_b() const { return (this->value & 0x000000FF); } - static int from_argb_channel(float a, float r, float g, float b) { return ((static_cast(a * 255.0 + 0.5) & 0xFF) << 24) | ((static_cast(r * 255.0 + 0.5) & 0xFF) << 16) | ((static_cast(g * 255.0 + 0.5) & 0xFF) << 8) | ((static_cast(b * 255.0 + 0.5) & 0xFF)); } + static argb from_argb_channel(float a, float r, float g, float b) { + return argb( + ((static_cast(round(a * 255.0 + 0.5)) & 0xFF) << 24) | + ((static_cast(round(r * 255.0 + 0.5)) & 0xFF) << 16) | + ((static_cast(round(g * 255.0 + 0.5)) & 0xFF) << 8) | + ((static_cast(round(b * 255.0 + 0.5)) & 0xFF)) + ); + } }; -// Colorization color, which permits ARGB color to be converted to DWM parameters -// ************************************** -class colorization_color : public argb { -public: - colorization_color(int value) - : argb(value) - { - } +class colorization_color : public argb { public: + colorization_color(int value) : argb(value) {} - static colorization_color from_hsb(const hsb& color, float intensity) - { + // themecpl.dll!CColorizationColor::CColorizationColor + static colorization_color from_hsb(const hsb& color, float intensity) { float r, g, b; - if (color.saturation == 0.0) { + if (color.saturation == 0.0) r = g = b = color.brightness; - } else { + else + { float value = color.hue / 60.0; - float difference = value - static_cast(value); + float difference = value - round(value); - if (color.hue > 0.0 && color.hue <= 60.0) { + if (0.0 < color.hue && color.hue <= 60.0) + { g = (1.0 - (1.0 - difference) * color.saturation) * color.brightness; b = (1.0 - color.saturation) * color.brightness; r = color.brightness; - } else if (color.hue > 60.0 && color.hue <= 120.0) { + } + if (60.0 < color.hue && color.hue <= 120.0) + { r = (1.0 - difference * color.saturation) * color.brightness; g = color.brightness; b = (1.0 - color.saturation) * color.brightness; - } else if (color.hue > 120.0 && color.hue <= 180.0) { + } + if (120.0 < color.hue && color.hue <= 180.0) + { r = (1.0 - color.saturation) * color.brightness; g = color.brightness; b = (1.0 - (1.0 - difference) * color.saturation) * color.brightness; - } else if (color.hue > 180.0 && color.hue <= 240.0) { + } + if (180.0 < color.hue && color.hue <= 240.0) + { r = (1.0 - color.saturation) * color.brightness; g = (1.0 - difference * color.saturation) * color.brightness; b = color.brightness; - } else if (color.hue > 240.0 && color.hue <= 300.0) { + } + if (240.0 < color.hue && color.hue <= 300.0) + { r = (1.0 - (1.0 - difference) * color.saturation) * color.brightness; g = (1.0 - color.saturation) * color.brightness; b = color.brightness; - } else /* if (color.hue > 300.0 && color.hue <= 360.0) */ { - r = color.brightness; + } + if (300.0 < color.hue && color.hue <= 360.0) + { g = (1.0 - color.saturation) * color.brightness; b = (1.0 - difference * color.saturation) * color.brightness; - } + r = color.brightness; + } } - return colorization_color(argb::from_argb_channel(intensity, r, g, b)); + return colorization_color + ( + argb::from_argb_channel(intensity, r, g, b).value + ); } - float get_intensity() const { return static_cast(get_a()) / 255.0; } + // themecpl.dll!CColorCplPage::UpdateSlidersToReflectColor + // The range for the slider is about [10%, 85%], normally you can't make it bigger or smaller + float get_intensity() const { return this->get_a() / 255.0f; } - hsb get_hsb_color() const - { - float r = static_cast(get_r()) / 255.0; - float g = static_cast(get_g()) / 255.0; - float b = static_cast(get_b()) / 255.0; + // themecpl.dll!CColorCplPage::UpdateSlidersToReflectColor + hsb get_hsb_color() const { + float r = this->get_r() / 255.0f; + float g = this->get_g() / 255.0f; + float b = this->get_b() / 255.0f; - float brightness = std::max({ r, g, b }); - float darkness = std::min({ r, g, b }); + float brightness = std::max({r, g, b}); + float darkness = std::min({r, g, b}); float range_value = brightness - darkness; float saturation, value; @@ -343,15 +426,12 @@ class colorization_color : public argb { } float hue = value * 60.0; - if (hue < 0.0) - hue += 360.0; + if (hue < 0.0) hue += 360.0; return hsb(hue, saturation, brightness); } }; -// Now we get to the good stuff -// ************************************** class dwm_colorization_parameters { public: argb color; @@ -362,30 +442,20 @@ class dwm_colorization_parameters { int glass_reflection_intensity; bool opaque_blend; - dwm_colorization_parameters(argb color = argb(0x6b74b8fc), argb afterglow = argb(0x6b74b8fc), int color_balance = 8, int afterglow_balance = 43, int blur_balance = 49, int glass_reflection_intensity = 50, bool opaque_blend = false) - : color(color) - , afterglow(afterglow) - , color_balance(color_balance) - , afterglow_balance(afterglow_balance) - , blur_balance(blur_balance) - , glass_reflection_intensity(glass_reflection_intensity) - , opaque_blend(opaque_blend) - { - } - - void log() - { - Wh_Log(L"[Color: %8x]", color); - Wh_Log(L"[Afterglow: %8x]", afterglow); - Wh_Log(L"[Balance (color): %d]", color_balance); - Wh_Log(L"[Balance (afterglow): %d]", afterglow_balance); - Wh_Log(L"[Balance (blur): %d]", blur_balance); - Wh_Log(L"{Glass reflection intensity: %d}", glass_reflection_intensity); - Wh_Log(L"{Opaque blend: %d}", opaque_blend); - } - - DWORD convert_colorization_parameters_to_argb() - { + dwm_colorization_parameters( + argb color = argb(0x6b74b8fc), //.0 a is actually ignored in the shader + argb afterglow = argb(0x6b74b8fc), //.1 a is actually ignored in the shader + int color_balance = 8, //.2 0..100 + int afterglow_balance = 43, //.3 0..100 + int blur_balance = 49, //.4 0..100 + int glass_reflection_intensity = 50, //.5 0..100 + bool opaque_blend = false //.6 + ) : color(color), afterglow(afterglow), color_balance(color_balance), + afterglow_balance(afterglow_balance), blur_balance(blur_balance), + glass_reflection_intensity(glass_reflection_intensity), opaque_blend(opaque_blend) {} + + // themecpl.dll!ConvertColorizationParametersToARGB + colorization_color convert_colorization_parameters_to_argb() { int balance = 0; if (opaque_blend) { @@ -400,45 +470,61 @@ class dwm_colorization_parameters { balance = 100 - blur_balance; } - return color.value & (0xFFFFFF | ((static_cast((static_cast(balance - 10) * 0.75 / 100.0 + 0.1) * 255.0 + 0.5) & 0xFF) << 24)); + return (color.value & 0xFFFFFF) | ((static_cast(round(((balance - 10.0f)) * 0.75 / 100.0 + 0.1) * 255.0 + 0.5) & 0xFF) << 24); } - colorization_color to_colorization_color() - { + // themecpl.dll!CColorCplPage::Setup + // used by theme control panel + colorization_color to_colorization_color() { int argb_color = 0; - if ((color.value & 0xFF000000) == 0xFF000000) { - argb_color = convert_colorization_parameters_to_argb(); - } else { + if ((color.value & 0xFF000000) == 0xFF000000) + argb_color = convert_colorization_parameters_to_argb().value; + else argb_color = color.value; - } return colorization_color(argb_color); } - colorization_color calculate_dwm_color() - { - float afterglow_balance = static_cast(this->afterglow_balance) / 100.0; - float color_balance = static_cast(this->color_balance) / 100.0; + // udwm.dll!DwmpCalculateColorizationColor + // used by WM_DWMCOLORIZATIONCOLORCHANGED and DwmGetColorizationColor + // + // https://stackoverflow.com/questions/3560890/vista-7-how-to-get-glass-color + // It's almost unusable, I keep it simply because its implementation exists inside udwm.dll from Windows 7. + colorization_color calculate_dwm_color() { + float afterglow_balance = this->afterglow_balance / 100.0f; + float color_balance = this->color_balance / 100.0f; - float color_r = static_cast(color.get_r()) / 255.0; - float color_g = static_cast(color.get_g()) / 255.0; - float color_b = static_cast(color.get_b()) / 255.0; + float color_r = color.get_r() / 255.0f; + float color_g = color.get_g() / 255.0f; + float color_b = color.get_b() / 255.0f; - float afterglow_r = static_cast(afterglow.get_r()) / 255.0; - float afterglow_g = static_cast(afterglow.get_g()) / 255.0; - float afterglow_b = static_cast(afterglow.get_b()) / 255.0; + float afterglow_r = afterglow.get_r() / 255.0f; + float afterglow_g = afterglow.get_g() / 255.0f; + float afterglow_b = afterglow.get_b() / 255.0f; - float result_a = std::max(0.0f, (1.0f - afterglow_balance) - (static_cast(blur_balance) / 100.0f)); + float result_a = std::max(0.0, (1.0 - afterglow_balance) - (blur_balance / 100.0f)); float brightness = (color_g * 0.7152 + color_r * 0.2126 + color_b * 0.0722) * afterglow_balance * color_balance; float result_r = afterglow_r * brightness + color_r * color_balance; float result_g = afterglow_g * brightness + color_g * color_balance; float result_b = afterglow_b * brightness + color_b * color_balance; - return colorization_color(argb::from_argb_channel(result_a, result_r, result_g, result_b)); + return colorization_color( + argb::from_argb_channel( + result_a, + result_r, + result_g, + result_b + ).value + ); } }; + +/* ---------------------------------------------------------------------------- +// CONVERSION OF ORIGINAL CODE AND COPIED DOCUMENTATION END HERE. +// ---------------------------------------------------------------------------- +*/ #pragma endregion #pragma region ----- DWM colorization calculation: Functions ----- @@ -467,41 +553,63 @@ DWORD readColor() void loadColorValues(DWORD input) { current = colorization_color(input); + dwmSettings = dwm_colorization_parameters(current.value, current.value, 0, 0, 0, 50, !settings.boolTransparency); HSB = current.get_hsb_color(); } +/** + * Writes color, afterglow and blur values to OpenGlass/Glass8 registry settings. + * @param c Color + * @param a Afterglow + * @param a Blur + */ +void writeColorizationBalance(int c, int a, int b) +{ + if (settings.glassApp == GlassSoftware::Glass8) { + set_DWORD(dwmKey, balanceColor, c); + set_DWORD(dwmKey, balanceBlur, b); + } else { + set_DWORD(dwmKey, balanceColor, c); + set_DWORD(dwmKey, balanceAfterglow, a); + set_DWORD(dwmKey, balanceBlur, b); + } +} + // ---------------------------------------------------------------------------- // Taken from "to_dwm_colorization_parameters" function (again, by ALTaleX): // https://github.com/ALTaleX531/dwm_colorization_calculator/blob/main/main.py#L110 // ---------------------------------------------------------------------------- -void calculateIntensity(DWORD self) +void calculateIntensity(DWORD self, bool opaque = FALSE) { - int balance = int((float((self >> 24) & 0xFF) / 255.0f - 0.1f) / 0.75f * 100.0f + 10.0f); - dwmSettings = dwm_colorization_parameters(self, self, 0, 0, 0, 50, !settings.boolTransparency); + int balance = round((static_cast((self >> 24) & 0xFF) / 255.0 - 0.1) / 0.75 * 100.0 + 10.0); + dwmSettings = dwm_colorization_parameters(self, self); + dwmSettings.glass_reflection_intensity = 50; + dwmSettings.opaque_blend = opaque; if (dwmSettings.opaque_blend) { dwmSettings.afterglow_balance = 10; dwmSettings.color_balance = balance - dwmSettings.afterglow_balance; dwmSettings.blur_balance = 100 - balance; + return; } - else if (balance < 50) { + if (balance < 50) { dwmSettings.color_balance = 5; dwmSettings.blur_balance = 100 - balance; dwmSettings.afterglow_balance = (100 - dwmSettings.color_balance) - dwmSettings.blur_balance; + return; } - else if (balance >= 95) { + if (balance >= 95) { dwmSettings.afterglow_balance = 0; dwmSettings.color_balance = balance - 25; dwmSettings.blur_balance = 100 - dwmSettings.color_balance; + return; } - else { - dwmSettings.afterglow_balance = 95 - balance; - dwmSettings.blur_balance = 50 - ((balance - 50) >> 1); - dwmSettings.color_balance = 100 - dwmSettings.afterglow_balance - dwmSettings.blur_balance; - } + dwmSettings.afterglow_balance = 95 - balance; + dwmSettings.blur_balance = 50 - ((balance - 50) >> 1); + dwmSettings.color_balance = 100 - dwmSettings.afterglow_balance - dwmSettings.blur_balance; } int opacity = -1; @@ -542,30 +650,39 @@ void bruteforceOpacity() * Calculates the color, afterglow and blur intensity values from an integer out of 100, then writes them to the registry for use with OpenGlass. * @param bruteforce Determines whether to also simultaneously bruteforce the opacity value to DWM. */ -void writeColorizationBalance(bool bruteforce = FALSE) +void setColorizationBalance(bool bruteforce = FALSE) { + // ********************************************* + // Set "og_Opacity" value. + if (settings.opacity < 0 || settings.opacity > 100) settings.opacity = 42; // 40.7853080838; if (opacity < 0 || opacity > 100) opacity = settings.opacity; set_DWORD(dwmKey, opacityValue, opacity); + + // Return if the function has already been run once under a fixed opacity. + // This is to prevent useless DWM refreshing afterward. + + if (settings.fixedOpacitySet) return; + bool isFixed = settings.fixedOpacity >= 0 && settings.fixedOpacity <= 100; + if (isFixed) settings.fixedOpacitySet = TRUE; + // ********************************************* - float alpha = opacity / 100.0f; + float alpha = (isFixed ? settings.fixedOpacity : opacity) / 100.0f; // ********************************************* // Min: 26, max: 217 // NOTE: Changing the ColorizationColor and Afterglow also affects the intensity slider // ********************************************* - loadColorValues((current.value & 0x00FFFFFF) | ((static_cast(alpha * 255.0 + 0.5) & 0xFF) << 24)); - calculateIntensity(current.value); + loadColorValues((current.value & 0x00FFFFFF) | ((int(alpha * 255.0 + 0.5) & 0xFF) << 24)); + calculateIntensity(current.value, !settings.boolTransparency); // ********************************************* // Actually do the registry editing // ********************************************* - set_DWORD(dwmKey, L"ColorizationColorBalanceOverride", dwmSettings.color_balance); - set_DWORD(dwmKey, L"ColorizationAfterglowBalanceOverride", dwmSettings.afterglow_balance); - set_DWORD(dwmKey, L"ColorizationBlurBalanceOverride", dwmSettings.blur_balance); - + writeColorizationBalance(dwmSettings.color_balance, dwmSettings.afterglow_balance, dwmSettings.blur_balance); + // Other registry values set_DWORD(dwmKey, L"GlassOpacity", 0); // settings.boolTransparency ? 0 : 100); set_DWORD(dwmKey, L"GlassType", 1); // settings.boolTransparency ? 1 : 0); @@ -592,7 +709,7 @@ void (*THISCALL Element_OnPropertyChanged)(class Element*, class PropertyInfo co void THISCALL Element_OnPropertyChanged_hook(class Element* This, class PropertyInfo const* prop, int integer, class Value* valueA, class Value* valueB) { Element_OnPropertyChanged(This, prop, integer, valueA, valueB); - intptr_t ptr = reinterpret_cast(This); + auto ptr = reinterpret_cast(This); if (ptr <= 0) return; ATOM id = Element_GetID(This, &This); @@ -616,12 +733,13 @@ void THISCALL Element_OnPropertyChanged_hook(class Element* This, class Property long (*THISCALL CCTrackBar_SetThumbPosition)(class CCTrackBar*, int); long THISCALL CCTrackBar_SetThumbPosition_hook(class CCTrackBar* This, int value) { - intptr_t ptr = reinterpret_cast(This); + auto ptr = reinterpret_cast(This); // Track bar value - if (ptr > 0 && ptr == intensitySlider) { + if (intensitySlider > 0 && intensitySlider == ptr) { opacity = value; - writeColorizationBalance(); + set_DWORD(dwmKey, opacityValue, opacity); + setColorizationBalance(); } return CCTrackBar_SetThumbPosition(This, value); @@ -636,7 +754,7 @@ typedef void (*THISCALL CCPushButton_OnSelectedPropertyChanged_T)(class CCPushBu CCPushButton_OnSelectedPropertyChanged_T CCPushButton_OnSelectedPropertyChanged; void THISCALL CCPushButton_OnSelectedPropertyChanged_hook(class CCPushButton* This, void* that) { - intptr_t ptr = reinterpret_cast(This); + auto ptr = reinterpret_cast(This); // OK button if (ptr > 0 && ptr == okButton) { @@ -648,7 +766,7 @@ void THISCALL CCPushButton_OnSelectedPropertyChanged_hook(class CCPushButton* Th else if (ptr > 0 && ptr == cancelButton) { opacity = settings.opacity; loadColorValues(old.value); - writeColorizationBalance(TRUE); + setColorizationBalance(TRUE); if (intensitySlider > 0) CCTrackBar_SetThumbPosition(reinterpret_cast(intensitySlider), opacity); @@ -669,7 +787,7 @@ enum DWMPGLASSATTRIBUTE : INT { /** * ------------------------- - * Function for setting OpenGlass opacity when the theme is changed from the Control Panel + * Function for setting DWM colorization when the theme is changed from the Control Panel * ------------------------- */ long (*STDCALL SetDwmColorizationColor)(unsigned long, enum DWMPGLASSATTRIBUTE, int); @@ -678,7 +796,7 @@ long STDCALL SetDwmColorizationColor_hook(unsigned long color, enum DWMPGLASSATT settings.opacity = opacity = round(argb(color).get_a() / 255.0 * 100.0); old = colorization_color(color); loadColorValues(old.value); - writeColorizationBalance(); + setColorizationBalance(); return SetDwmColorizationColor(color, attribute, integer); } @@ -757,24 +875,88 @@ WinVersion getWinVer() return WinVersion::None; } -BOOL isOpenGlassInstalled(bool strict = FALSE) +BOOL isInstalled(bool strict = FALSE) +{ + return settings.glassApp == GlassSoftware::Glass8 + ? (strict ? exists_DWORD(dwmKey, balanceColor) && exists_DWORD(dwmKey, balanceBlur) + : exists_DWORD(dwmKey, balanceColor) || exists_DWORD(dwmKey, balanceBlur)) + : (strict ? exists_DWORD(dwmKey, balanceColor) && exists_DWORD(dwmKey, balanceAfterglow) && exists_DWORD(dwmKey, balanceBlur) + : exists_DWORD(dwmKey, balanceColor) || exists_DWORD(dwmKey, balanceAfterglow) || exists_DWORD(dwmKey, balanceBlur)); +} + +void setValueNames() { - return strict ? exists_DWORD(dwmKey, L"ColorizationColorBalanceOverride") && exists_DWORD(dwmKey, L"ColorizationAfterglowBalanceOverride") && exists_DWORD(dwmKey, L"ColorizationBlurBalanceOverride") - : exists_DWORD(dwmKey, L"ColorizationColorBalanceOverride") || exists_DWORD(dwmKey, L"ColorizationAfterglowBalanceOverride") || exists_DWORD(dwmKey, L"ColorizationBlurBalanceOverride"); + if (settings.glassApp == GlassSoftware::Glass8) + { + balanceColor = L"ColorizationColorBalance"; + balanceBlur = L"ColorizationBlurBalance"; + return; + } + + DWORD value; + + std::wstring old1 = settings.glassApp == GlassSoftware::OpenGlass1 ? L"og_ColorizationColorBalance" : L"ColorizationColorBalanceOverride"; + std::wstring old2 = settings.glassApp == GlassSoftware::OpenGlass1 ? L"og_ColorizationAfterglowBalance" : L"ColorizationAfterglowBalanceOverride"; + std::wstring old3 = settings.glassApp == GlassSoftware::OpenGlass1 ? L"og_ColorizationBlurBalance" : L"ColorizationBlurBalanceOverride"; + std::wstring new1 = settings.glassApp == GlassSoftware::OpenGlass2 ? L"og_ColorizationColorBalance" : L"ColorizationColorBalanceOverride"; + std::wstring new2 = settings.glassApp == GlassSoftware::OpenGlass2 ? L"og_ColorizationAfterglowBalance" : L"ColorizationAfterglowBalanceOverride"; + std::wstring new3 = settings.glassApp == GlassSoftware::OpenGlass2 ? L"og_ColorizationBlurBalance" : L"ColorizationBlurBalanceOverride"; + + balanceColor = new1; + balanceAfterglow = new2; + balanceBlur = new3; + + if (exists_DWORD(dwmKey, old1)) { + value = read_DWORD(dwmKey, old1); + set_DWORD(dwmKey, new1, value); + set_DWORD(dwmKey, old1, value, TRUE); + } + + if (exists_DWORD(dwmKey, old2)) { + value = read_DWORD(dwmKey, old2); + set_DWORD(dwmKey, new2, value); + set_DWORD(dwmKey, old2, value, TRUE); + } + + if (exists_DWORD(dwmKey, old3)) { + value = read_DWORD(dwmKey, old3); + set_DWORD(dwmKey, new3, value); + set_DWORD(dwmKey, old3, value, TRUE); + } } BOOL LoadSettings() { + LPCWSTR glassAppName = Wh_GetStringSetting(L"glassSoftware"); + if (lstrcmpW(glassAppName, L"glass8") == 0) settings.glassApp = GlassSoftware::Glass8; + else if (lstrcmpW(glassAppName, L"og1") == 0) settings.glassApp = GlassSoftware::OpenGlass1; + else settings.glassApp = GlassSoftware::OpenGlass2; + Wh_FreeStringSetting(glassAppName); + + settings.fixedOpacity = -1; + if (Wh_GetIntSetting(L"fixedOpacity.enable") == 1) { + int opac = Wh_GetIntSetting(L"fixedOpacity.value"); + settings.fixedOpacity = opac < 0 || opac > 100 ? -1 : std::max(intensitySliderMin, std::min(opac, intensitySliderMax)); + } + settings.fixedOpacitySet = FALSE; + + settings.boolTransparency = TRUE; + settings.boolSyncDWM = Wh_GetIntSetting(L"syncDWM"); + bool regSetup = FALSE; + setValueNames(); // ********************************************* - // Check for OpenGlass installation + // Check for OpenGlass/Glass8 installation // ********************************************* - if (!isOpenGlassInstalled()) { - Wh_Log(L"HALT: OpenGlass Legacy was not detected"); + if (!isInstalled()) { + if (settings.glassApp == GlassSoftware::Glass8) + Wh_Log(L"Glass8 was not detected, stopping now"); + else + Wh_Log(L"OpenGlass Legacy was not detected, stopping now"); return FALSE; } else { - regSetup = !isOpenGlassInstalled(TRUE); + regSetup = !isInstalled(TRUE); } // ********************************************* @@ -791,23 +973,20 @@ BOOL LoadSettings() if (regSetup) { Wh_Log(L"Setting up registry"); - settings.opacity = 42; - set_DWORD(dwmKey, L"ColorizationColorBalanceOverride", 0x08); - set_DWORD(dwmKey, L"ColorizationAfterglowBalanceOverride", 0x2b); - set_DWORD(dwmKey, L"ColorizationBlurBalanceOverride", 0x31); + int def = 42; - if (!set_DWORD(dwmKey, opacityValue, settings.opacity)) + if (!set_DWORD(dwmKey, opacityValue, def)) return FALSE; if (!exists_DWORD(dwmKey, opacityValue)) return FALSE; + + opacity = settings.opacity = def; + writeColorizationBalance(0x08, 0x2b, 0x31); } loadColorValues(readColor()); old = current; - settings.boolTransparency = TRUE; - settings.boolSyncDWM = Wh_GetIntSetting(L"syncDWM"); - return TRUE; } @@ -823,18 +1002,18 @@ BOOL Wh_ModInit() { std::wstring username = read_SZ(L"Volatile Environment", L"USERNAME", L"???"); if (username == L"???") { - Wh_Log(L"HALT: Local username not detected"); + Wh_Log(L"Local username not detected, stopping now"); return FALSE; } winVer = getWinVer(); if (winVer == WinVersion::None) { - Wh_Log(L"HALT: Invalid OS version"); + Wh_Log(L"Invalid OS version"); return FALSE; } switch (winVer) { case WinVersion::Unsupported: - Wh_Log(L"HALT: Cannot run on Windows 8.1 or earlier"); + Wh_Log(L"Cannot run on Windows 8.1 or earlier"); return FALSE; default: @@ -842,32 +1021,32 @@ BOOL Wh_ModInit() } if (!LoadSettings()) { - Wh_Log(L"HALT: Failed to load settings"); + Wh_Log(L"Failed to load settings"); return FALSE; } HMODULE hDui = LoadLibraryW(L"dui70.dll"); if (hDui) { if (!WindhawkUtils::HookSymbols(hDui, dui70dll_hooks, ARRAYSIZE(dui70dll_hooks))) { - Wh_Log(L"HALT: Failed to hook symbols from dui70.dll"); + Wh_Log(L"Failed to hook symbols from dui70.dll"); return FALSE; } } else { - Wh_Log(L"HALT: Failed to load dui70.dll"); + Wh_Log(L"Failed to load dui70.dll"); return FALSE; } HMODULE hThemeUi = LoadLibraryW(L"themeui.dll"); if (hThemeUi) { if (!WindhawkUtils::HookSymbols(hThemeUi, themeuidll_hooks, ARRAYSIZE(themeuidll_hooks))) { - Wh_Log(L"HALT: Failed to hook symbols from themeui.dll"); + Wh_Log(L"Failed to hook symbols from themeui.dll"); return FALSE; } } else { - Wh_Log(L"HALT: Failed to load themeui.dll"); + Wh_Log(L"Failed to load themeui.dll"); return FALSE; } - writeColorizationBalance(); + setColorizationBalance(); return TRUE; -} \ No newline at end of file +}