From ee2d341ca2e4166859e18845d962b6bf41f214fe Mon Sep 17 00:00:00 2001 From: ALTaleX <2368730049@qq.com> Date: Wed, 2 Oct 2024 01:14:25 +0800 Subject: [PATCH] v1.2 --- .gitignore | 6 +- OpenGlass/AeroEffect.cpp | 232 ++++++++++++++ OpenGlass/AeroEffect.hpp | 59 ++++ OpenGlass/BlurEffect.cpp | 98 ++++++ OpenGlass/BlurEffect.hpp | 46 +++ OpenGlass/CaptionTextHandler.cpp | 12 +- OpenGlass/CustomBlurEffect.cpp | 449 ++++------------------------ OpenGlass/CustomBlurEffect.hpp | 71 +---- OpenGlass/CustomMsstyleLoader.cpp | 16 +- OpenGlass/GeometryRecorder.cpp | 2 +- OpenGlass/GlassEffect.cpp | 376 +++++++++++++++++++++++ OpenGlass/GlassEffect.hpp | 38 +++ OpenGlass/GlassEffectManager.cpp | 304 ------------------- OpenGlass/GlassEffectManager.hpp | 39 --- OpenGlass/GlassFramework.cpp | 141 +++++---- OpenGlass/GlassRenderer.cpp | 255 ++++++++-------- OpenGlass/GlassSharedData.hpp | 31 -- OpenGlass/GlassSharedStructures.hpp | 10 - OpenGlass/HookHelper.cpp | 44 ++- OpenGlass/OpenGlass.cpp | 10 +- OpenGlass/OpenGlass.vcxproj | 13 +- OpenGlass/ReflectionEffect.hpp | 254 ++++++++++++++++ OpenGlass/ReflectionRenderer.hpp | 147 --------- OpenGlass/ServiceApi.cpp | 28 +- OpenGlass/Shared.hpp | 57 ++++ OpenGlass/SymbolParser.cpp | 12 +- OpenGlass/Utils.hpp | 29 +- OpenGlass/VisualManager.cpp | 248 ++++++++------- OpenGlass/VisualManager.hpp | 13 +- OpenGlass/dllmain.cpp | 16 +- OpenGlass/dwmcoreProjection.hpp | 43 ++- OpenGlass/framework.hpp | 4 +- OpenGlass/uDwmProjection.hpp | 41 ++- README.md | 12 +- 34 files changed, 1736 insertions(+), 1420 deletions(-) create mode 100644 OpenGlass/AeroEffect.cpp create mode 100644 OpenGlass/AeroEffect.hpp create mode 100644 OpenGlass/BlurEffect.cpp create mode 100644 OpenGlass/BlurEffect.hpp create mode 100644 OpenGlass/GlassEffect.cpp create mode 100644 OpenGlass/GlassEffect.hpp delete mode 100644 OpenGlass/GlassEffectManager.cpp delete mode 100644 OpenGlass/GlassEffectManager.hpp delete mode 100644 OpenGlass/GlassSharedData.hpp delete mode 100644 OpenGlass/GlassSharedStructures.hpp create mode 100644 OpenGlass/ReflectionEffect.hpp delete mode 100644 OpenGlass/ReflectionRenderer.hpp create mode 100644 OpenGlass/Shared.hpp diff --git a/.gitignore b/.gitignore index c2edcab..b73b77d 100644 --- a/.gitignore +++ b/.gitignore @@ -7,9 +7,10 @@ *.rsuser *.suo *.user +*.vcxproj.user *.userosscache *.sln.docstates -*.vcxproj.user +*.filters # User-specific files (MonoDevelop/Xamarin Studio) *.userprefs @@ -355,5 +356,4 @@ MigrationBackup/ *.zip /OpenGlass/Archieve /Theme -*.filters -/OpenGlass/OpenGlass.vcxproj.user +/OpenGlass/OpenGlass.vcxproj.user \ No newline at end of file diff --git a/OpenGlass/AeroEffect.cpp b/OpenGlass/AeroEffect.cpp new file mode 100644 index 0000000..cb22d9f --- /dev/null +++ b/OpenGlass/AeroEffect.cpp @@ -0,0 +1,232 @@ +#include "pch.h" +#include "AeroEffect.hpp" + +using namespace OpenGlass; + +HRESULT CAeroEffect::Initialize(ID2D1DeviceContext* context) +{ + m_customBlurEffect = winrt::make(); + + RETURN_IF_FAILED( + context->CreateEffect( + CLSID_D2D1Flood, + m_fallbackColorEffect.put() + ) + ); + RETURN_IF_FAILED( + context->CreateEffect( + CLSID_D2D1Flood, + m_colorEffect.put() + ) + ); + RETURN_IF_FAILED( + context->CreateEffect( + CLSID_D2D1Tint, + m_tintEffect.put() + ) + ); + RETURN_IF_FAILED( + context->CreateEffect( + CLSID_D2D1Saturation, + m_desaturationEffect.put() + ) + ); + RETURN_IF_FAILED( + context->CreateEffect( + CLSID_D2D1Composite, + m_innerCompositeEffect.put() + ) + ); + RETURN_IF_FAILED( + context->CreateEffect( + CLSID_D2D1ColorMatrix, + m_afterglowBalanceEffect.put() + ) + ); + RETURN_IF_FAILED( + context->CreateEffect( + CLSID_D2D1ColorMatrix, + m_blurBalanceEffect.put() + ) + ); + RETURN_IF_FAILED( + context->CreateEffect( + CLSID_D2D1Composite, + m_compositeEffect.put() + ) + ); + RETURN_IF_FAILED( + context->CreateEffect( + CLSID_D2D1Composite, + m_compositeEffect2.put() + ) + ); + + + + RETURN_IF_FAILED( + m_desaturationEffect->SetValue( + D2D1_SATURATION_PROP_SATURATION, + 0.f + ) + ); + + m_innerCompositeEffect->SetInputEffect(0, m_fallbackColorEffect.get()); + m_innerCompositeEffect->SetInputEffect(1, m_desaturationEffect.get()); + RETURN_IF_FAILED( + m_innerCompositeEffect->SetValue( + D2D1_COMPOSITE_PROP_MODE, + D2D1_COMPOSITE_MODE_SOURCE_OVER + ) + ); + + m_tintEffect->SetInputEffect(0, m_innerCompositeEffect.get()); + m_afterglowBalanceEffect->SetInputEffect(0, m_tintEffect.get()); + + m_compositeEffect->SetInputEffect(0, m_blurBalanceEffect.get()); + m_compositeEffect->SetInputEffect(1, m_afterglowBalanceEffect.get()); + RETURN_IF_FAILED( + m_compositeEffect->SetValue( + D2D1_COMPOSITE_PROP_MODE, + D2D1_COMPOSITE_MODE_PLUS + ) + ); + + m_compositeEffect2->SetInputEffect(0, m_compositeEffect.get()); + m_compositeEffect2->SetInputEffect(1, m_colorEffect.get()); + RETURN_IF_FAILED( + m_compositeEffect2->SetValue( + D2D1_COMPOSITE_PROP_MODE, + D2D1_COMPOSITE_MODE_PLUS + ) + ); + m_initialized = true; + + return S_OK; +} + +HRESULT STDMETHODCALLTYPE CAeroEffect::SetInput( + ID2D1DeviceContext* context, + ID2D1Image* inputImage, + const D2D1_RECT_F& imageRectangle, + const D2D1_RECT_F& imageBounds, + float blurAmount, + const D2D1_COLOR_F& color, + const D2D1_COLOR_F& afterglowColor, + float colorBalance, + float afterglowBalance, + float blurBalance +) +{ + if (!m_initialized) + { + RETURN_IF_FAILED(Initialize(context)); + } + RETURN_IF_FAILED( + m_customBlurEffect->SetInput( + context, + inputImage, + imageRectangle, + imageBounds, + blurAmount + ) + ); + + // CREDITS: @kfh83, @wiktorwiktor12, @TorutheRedFox and @WackyIdeas. special shoutouts to @aubymori and @kawapure for testing/help + // @ALTaleX modified it to adapt opening/restoring/closing animation + auto input = m_customBlurEffect->GetOutput(); + + RETURN_IF_FAILED( + m_fallbackColorEffect->SetValue( + D2D1_FLOOD_PROP_COLOR, + D2D1::Vector4F( + blurBalance / (1.f - afterglowBalance / 1.5f), + blurBalance / (1.f - afterglowBalance / 1.5f), + blurBalance / (1.f - afterglowBalance / 1.5f), + blurBalance * (1.f - afterglowBalance / 1.5f) + ) + ) + ); + m_blurBalanceEffect->SetInput(0, input); + RETURN_IF_FAILED( + m_blurBalanceEffect->SetValue( + D2D1_COLORMATRIX_PROP_COLOR_MATRIX, + D2D1::Matrix5x4F( + blurBalance, 0.f, 0.f, 0.f, + 0.f, blurBalance, 0.f, 0.f, + 0.f, 0.f, blurBalance, 0.f, + 0.f, 0.f, 0.f, 1.f, + 0.f, 0.f, 0.f, 0.f + ) + ) + ); + m_desaturationEffect->SetInput(0, input); + RETURN_IF_FAILED( + m_tintEffect->SetValue( + D2D1_TINT_PROP_COLOR, + D2D1::Vector4F( + afterglowColor.r, + afterglowColor.g, + afterglowColor.b, + 1.f + ) + ) + ); + RETURN_IF_FAILED( + m_colorEffect->SetValue( + D2D1_FLOOD_PROP_COLOR, + D2D1::Vector4F( + color.r, + color.g, + color.b, + 1.f + ) + ) + ); + RETURN_IF_FAILED( + m_afterglowBalanceEffect->SetValue( + D2D1_COLORMATRIX_PROP_COLOR_MATRIX, + D2D1::Matrix5x4F( + afterglowBalance, 0.f, 0.f, 0.f, + 0.f, afterglowBalance, 0.f, 0.f, + 0.f, 0.f, afterglowBalance, 0.f, + 0.f, 0.f, 0.f, 1.f, + 0.f, 0.f, 0.f, 0.f + ) + ) + ); + + m_desaturationEffect->SetInput(0, input); + RETURN_IF_FAILED( + m_colorEffect->SetValue( + D2D1_FLOOD_PROP_COLOR, + D2D1::Vector4F( + color.r * colorBalance, + color.g * colorBalance, + color.b * colorBalance, + colorBalance + ) + ) + ); + + m_compositeEffect2->GetOutput(m_effectOutput.put()); + + return S_OK; +} + +void STDMETHODCALLTYPE CAeroEffect::Reset() +{ + if (m_customBlurEffect) + { + m_customBlurEffect->Reset(); + } + if (m_blurBalanceEffect) + { + m_blurBalanceEffect->SetInput(0, nullptr); + } + if (m_desaturationEffect) + { + m_desaturationEffect->SetInput(0, nullptr); + } + m_effectOutput = nullptr; +} \ No newline at end of file diff --git a/OpenGlass/AeroEffect.hpp b/OpenGlass/AeroEffect.hpp new file mode 100644 index 0000000..d1189be --- /dev/null +++ b/OpenGlass/AeroEffect.hpp @@ -0,0 +1,59 @@ +#pragma once +#include "CustomBlurEffect.hpp" + +namespace OpenGlass +{ + // [Guid("60419F4A-0BAB-4EAA-A5A6-C7E05BB3FAC4")] + DECLARE_INTERFACE_IID_(IAeroEffect, IUnknown, "60419F4A-0BAB-4EAA-A5A6-C7E05BB3FAC4") + { + virtual HRESULT STDMETHODCALLTYPE SetInput( + ID2D1DeviceContext* context, + ID2D1Image* inputImage, + const D2D1_RECT_F& imageRectangle, + const D2D1_RECT_F& imageBounds, + float blurAmount, + const D2D1_COLOR_F& color, + const D2D1_COLOR_F& afterglowColor, + float colorBalance, + float afterglowBalance, + float blurBalance + ) = 0; + virtual ID2D1Image* STDMETHODCALLTYPE GetOutput() const = 0; + virtual void STDMETHODCALLTYPE Reset() = 0; + }; + + class CAeroEffect : public winrt::implements + { + bool m_initialized{ false }; + + winrt::com_ptr m_customBlurEffect{ nullptr }; + + winrt::com_ptr m_fallbackColorEffect{ nullptr }; + winrt::com_ptr m_colorEffect{ nullptr }; + winrt::com_ptr m_tintEffect{ nullptr }; + winrt::com_ptr m_desaturationEffect{ nullptr }; + winrt::com_ptr m_innerCompositeEffect{ nullptr }; + winrt::com_ptr m_afterglowBalanceEffect{ nullptr }; + winrt::com_ptr m_blurBalanceEffect{ nullptr }; + winrt::com_ptr m_compositeEffect{ nullptr }; + winrt::com_ptr m_compositeEffect2{ nullptr }; + winrt::com_ptr m_effectOutput{ nullptr }; + + HRESULT Initialize(ID2D1DeviceContext* context); + public: + HRESULT STDMETHODCALLTYPE SetInput( + ID2D1DeviceContext* context, + ID2D1Image* inputImage, + const D2D1_RECT_F& imageRectangle, + const D2D1_RECT_F& imageBounds, + float blurAmount, + const D2D1_COLOR_F& color, + const D2D1_COLOR_F& afterglowColor, + float colorBalance, + float afterglowBalance, + float blurBalance + ) override; + ID2D1Image* STDMETHODCALLTYPE GetOutput() const override { return m_effectOutput.get(); } + void STDMETHODCALLTYPE Reset() override; + }; +} \ No newline at end of file diff --git a/OpenGlass/BlurEffect.cpp b/OpenGlass/BlurEffect.cpp new file mode 100644 index 0000000..a56714f --- /dev/null +++ b/OpenGlass/BlurEffect.cpp @@ -0,0 +1,98 @@ +#include "pch.h" +#include "BlurEffect.hpp" + +using namespace OpenGlass; + +HRESULT CBlurEffect::Initialize(ID2D1DeviceContext* context) +{ + m_customBlurEffect = winrt::make(); + + RETURN_IF_FAILED( + context->CreateEffect( + CLSID_D2D1Flood, + m_colorEffect.put() + ) + ); + RETURN_IF_FAILED( + context->CreateEffect( + CLSID_D2D1Composite, + m_compositeEffect.put() + ) + ); + + RETURN_IF_FAILED( + m_compositeEffect->SetValue( + D2D1_COMPOSITE_PROP_MODE, + D2D1_COMPOSITE_MODE_SOURCE_OVER + ) + ); + + m_compositeEffect->SetInputEffect(1, m_colorEffect.get()); + m_initialized = true; + + return S_OK; +} + +HRESULT STDMETHODCALLTYPE CBlurEffect::SetInput( + ID2D1DeviceContext* context, + ID2D1Image* inputImage, + const D2D1_RECT_F& imageRectangle, + const D2D1_RECT_F& imageBounds, + float blurAmount, + const D2D1_COLOR_F& color, + float opacity +) +{ + if (!m_initialized) + { + RETURN_IF_FAILED(Initialize(context)); + } + RETURN_IF_FAILED( + m_colorEffect->SetValue( + D2D1_FLOOD_PROP_COLOR, + D2D1::Vector4F( + color.r * opacity, + color.g * opacity, + color.b * opacity, + opacity + ) + ) + ); + if (opacity == 1.f) + { + m_colorEffect->GetOutput(m_effectOutput.put()); + return S_OK; + } + + RETURN_IF_FAILED( + m_customBlurEffect->SetInput( + context, + inputImage, + imageRectangle, + imageBounds, + blurAmount + ) + ); + if (opacity == 0.f) + { + winrt::copy_from_abi(m_effectOutput, m_customBlurEffect->GetOutput()); + return S_OK; + } + m_compositeEffect->SetInput(0, m_customBlurEffect->GetOutput()); + m_compositeEffect->GetOutput(m_effectOutput.put()); + + return S_OK; +} + +void STDMETHODCALLTYPE CBlurEffect::Reset() +{ + if (m_customBlurEffect) + { + m_customBlurEffect->Reset(); + } + if (m_compositeEffect) + { + m_compositeEffect->SetInput(0, nullptr); + } + m_effectOutput = nullptr; +} \ No newline at end of file diff --git a/OpenGlass/BlurEffect.hpp b/OpenGlass/BlurEffect.hpp new file mode 100644 index 0000000..c0104a5 --- /dev/null +++ b/OpenGlass/BlurEffect.hpp @@ -0,0 +1,46 @@ +#pragma once +#include "CustomBlurEffect.hpp" + +namespace OpenGlass +{ + // [Guid("78E29503-85D2-4250-87BD-95572A988899")] + DECLARE_INTERFACE_IID_(IBlurEffect, IUnknown, "78E29503-85D2-4250-87BD-95572A988899") + { + virtual HRESULT STDMETHODCALLTYPE SetInput( + ID2D1DeviceContext* context, + ID2D1Image* inputImage, + const D2D1_RECT_F& imageRectangle, + const D2D1_RECT_F& imageBounds, + float blurAmount, + const D2D1_COLOR_F& color, + float opacity + ) = 0; + virtual ID2D1Image* STDMETHODCALLTYPE GetOutput() const = 0; + virtual void STDMETHODCALLTYPE Reset() = 0; + }; + + class CBlurEffect : public winrt::implements + { + bool m_initialized{ false }; + + winrt::com_ptr m_customBlurEffect{ nullptr }; + + winrt::com_ptr m_compositeEffect{ nullptr }; + winrt::com_ptr m_colorEffect{ nullptr }; + winrt::com_ptr m_effectOutput{ nullptr }; + + HRESULT Initialize(ID2D1DeviceContext* context); + public: + HRESULT STDMETHODCALLTYPE SetInput( + ID2D1DeviceContext* context, + ID2D1Image* inputImage, + const D2D1_RECT_F& imageRectangle, + const D2D1_RECT_F& imageBounds, + float blurAmount, + const D2D1_COLOR_F& color, + float opacity + ) override; + ID2D1Image* STDMETHODCALLTYPE GetOutput() const override { return m_effectOutput.get(); } + void STDMETHODCALLTYPE Reset() override; + }; +} \ No newline at end of file diff --git a/OpenGlass/CaptionTextHandler.cpp b/OpenGlass/CaptionTextHandler.cpp index b06e2ae..0d39f93 100644 --- a/OpenGlass/CaptionTextHandler.cpp +++ b/OpenGlass/CaptionTextHandler.cpp @@ -197,7 +197,7 @@ HRESULT STDMETHODCALLTYPE CaptionTextHandler::MyCText_SetSize(uDwm::CText* This, return g_CText_SetSize_Org(This, size); } - auto oldWidth{ This->GetWidth() }; + auto oldWidth = This->GetWidth(); HRESULT hr{ g_CText_SetSize_Org(This, size) }; if (oldWidth != size->cx) @@ -212,10 +212,10 @@ HRESULT STDMETHODCALLTYPE CaptionTextHandler::MyCMatrixTransformProxy_Update(str { if (g_textVisual) { - matrix->DX -= static_cast(g_textGlowSize); + matrix->DX -= static_cast(g_textGlowSize) * (g_textVisual->IsRTL() ? -1.f : 1.f); if (g_centerCaption) { - auto offset{ floor(static_cast(g_textVisual->GetWidth() - g_textWidth) / 2.) }; + auto offset = floor(static_cast(g_textVisual->GetWidth() - g_textWidth) / 2.); matrix->DX += g_textVisual->IsRTL() ? -offset : offset; } matrix->DY = static_cast(static_cast(static_cast(g_textVisual->GetHeight() - g_textHeight) / 2. - 0.5)); @@ -227,10 +227,10 @@ HRESULT STDMETHODCALLTYPE CaptionTextHandler::MyCChannel_MatrixTransformUpdate(d { if (g_textVisual) { - matrix->DX -= static_cast(g_textGlowSize); + matrix->DX -= static_cast(g_textGlowSize) * (g_textVisual->IsRTL() ? -1.f : 1.f); if (g_centerCaption) { - auto offset{ floor(static_cast(g_textVisual->GetWidth() - g_textWidth) / 2.) }; + auto offset = floor(static_cast(g_textVisual->GetWidth() - g_textWidth) / 2.); matrix->DX += g_textVisual->IsRTL() ? -offset : offset; } matrix->DY = static_cast(static_cast(static_cast(g_textVisual->GetHeight() - g_textHeight) / 2. - 0.5)); @@ -245,7 +245,7 @@ void CaptionTextHandler::UpdateConfiguration(ConfigurationFramework::UpdateType { g_centerCaption = static_cast(ConfigurationFramework::DwmGetDwordFromHKCUAndHKLM(L"CenterCaption", FALSE)); g_textGlowSize = standardGlowSize; - auto glowSize{ ConfigurationFramework::DwmTryDwordFromHKCUAndHKLM(L"TextGlowSize") }; + auto glowSize = ConfigurationFramework::DwmTryDwordFromHKCUAndHKLM(L"TextGlowSize"); if (!glowSize.has_value()) { glowSize = ConfigurationFramework::DwmTryDwordFromHKCUAndHKLM(L"TextGlowMode"); diff --git a/OpenGlass/CustomBlurEffect.cpp b/OpenGlass/CustomBlurEffect.cpp index 6d86e3b..655f311 100644 --- a/OpenGlass/CustomBlurEffect.cpp +++ b/OpenGlass/CustomBlurEffect.cpp @@ -4,255 +4,55 @@ using namespace OpenGlass; const float CCustomBlurEffect::k_optimizations[16] { - 8.f, 6.f, 1.5f, 2.5f, static_cast(-42.28171817154095), 8.f, 6.f, 1.5f, - 2.5f, static_cast(-34.12687268616382), 12.f, 6.f, 2.f, 3.f, static_cast(-34.12687268616382), 0.f + 8.f, 6.f, 1.5f, 2.5f, 0.f, 8.f, 6.f, 1.5f, + 2.5f, 0.f, 12.f, 6.f, 2.f, 3.f, 0.f, 0.f }; -CCustomBlurEffect::CCustomBlurEffect(ID2D1DeviceContext* deviceContext) -{ - winrt::copy_from_abi(m_deviceContext, deviceContext); -} - // CropInput -> ScaleDown (optional) -> Border -> DirectionalBlurX -> DirectionalBlurY -> ScaleUp (optional) -HRESULT CCustomBlurEffect::Initialize() +HRESULT CCustomBlurEffect::Initialize(ID2D1DeviceContext* context) { RETURN_IF_FAILED( - m_deviceContext->CreateEffect( + context->CreateEffect( CLSID_D2D1Crop, m_cropInputEffect.put() ) ); RETURN_IF_FAILED( - m_deviceContext->CreateEffect( + context->CreateEffect( CLSID_D2D1Scale, m_scaleDownEffect.put() ) ); RETURN_IF_FAILED( - m_deviceContext->CreateEffect( + context->CreateEffect( CLSID_D2D1Border, m_borderEffect.put() ) ); RETURN_IF_FAILED( - m_deviceContext->CreateEffect( + context->CreateEffect( CLSID_D2D1DirectionalBlurKernel, m_directionalBlurXEffect.put() ) ); RETURN_IF_FAILED( - m_deviceContext->CreateEffect( + context->CreateEffect( CLSID_D2D1DirectionalBlurKernel, m_directionalBlurYEffect.put() ) ); RETURN_IF_FAILED( - m_deviceContext->CreateEffect( + context->CreateEffect( CLSID_D2D1Scale, m_scaleUpEffect.put() ) ); - SetParams(); - - m_initialized = true; - - return S_OK; -} - -// CropInput -> ScaleDown (optional) -> Border -> DirectionalBlurX -> DirectionalBlurY -> ScaleUp (optional) -HRESULT CCustomBlurEffect::InitializeAero() -{ - RETURN_IF_FAILED( - m_deviceContext->CreateEffect( - CLSID_D2D1Crop, - m_cropInputEffect.put() - ) - ); - RETURN_IF_FAILED( - m_deviceContext->CreateEffect( - CLSID_D2D1Scale, - m_scaleDownEffect.put() - ) - ); - RETURN_IF_FAILED( - m_deviceContext->CreateEffect( - CLSID_D2D1Border, - m_borderEffect.put() - ) - ); - RETURN_IF_FAILED( - m_deviceContext->CreateEffect( - CLSID_D2D1DirectionalBlurKernel, - m_directionalBlurXEffect.put() - ) - ); - RETURN_IF_FAILED( - m_deviceContext->CreateEffect( - CLSID_D2D1DirectionalBlurKernel, - m_directionalBlurYEffect.put() - ) - ); - RETURN_IF_FAILED( - m_deviceContext->CreateEffect( - CLSID_D2D1Scale, - m_scaleUpEffect.put() - ) - ); - - // imma try n put whats relevant here - // ts is jus creating the effects - - RETURN_IF_FAILED( - m_deviceContext->CreateEffect( - CLSID_D2D1Composite, - m_compositeEffect.put() - ) - ); - RETURN_IF_FAILED( - m_deviceContext->CreateEffect( - CLSID_D2D1Composite, - m_compositeEffect_pass2.put() - ) - ); - - RETURN_IF_FAILED( - m_deviceContext->CreateEffect( - CLSID_D2D1Tint, - m_tintEffect.put() - ) - ); - - RETURN_IF_FAILED( - m_deviceContext->CreateEffect( - CLSID_D2D1Saturation, - m_saturationEffect.put() - ) - ); - - RETURN_IF_FAILED( - m_deviceContext->CreateEffect( - CLSID_D2D1ColorMatrix, - m_ColorizationAfterglowBalance.put() - ) - ); - RETURN_IF_FAILED( - m_deviceContext->CreateEffect( - CLSID_D2D1ColorMatrix, - m_ColorizationBlurBalance.put() - ) - ); - - RETURN_IF_FAILED( - m_deviceContext->CreateEffect( - CLSID_D2D1ColorMatrix, - m_ColorizationColorBalance.put() - ) - ); - - RETURN_IF_FAILED( - m_deviceContext->CreateEffect( - CLSID_D2D1Flood, - m_ColorizationColor.put() - ) - ); - - /* - RETURN_IF_FAILED( - m_cropInputEffect->SetValue(D2D1_PROPERTY_CACHED, TRUE) - );*/ - - SetParamsAero(); - - - m_initialized = true; - - return S_OK; -} - -HRESULT CCustomBlurEffect::SetParams() -{ - /* - RETURN_IF_FAILED( - m_cropInputEffect->SetValue(D2D1_PROPERTY_CACHED, TRUE) - );*/ - RETURN_IF_FAILED( - m_cropInputEffect->SetValue( - D2D1_CROP_PROP_BORDER_MODE, - D2D1_BORDER_MODE_SOFT - ) - ); - m_scaleDownEffect->SetInputEffect(0, m_cropInputEffect.get()); - RETURN_IF_FAILED(m_scaleDownEffect->SetValue(D2D1_SCALE_PROP_SHARPNESS, 1.f)); - RETURN_IF_FAILED( - m_scaleDownEffect->SetValue( - D2D1_SCALE_PROP_BORDER_MODE, - D2D1_BORDER_MODE_HARD - ) - ); - RETURN_IF_FAILED( - m_scaleDownEffect->SetValue( - D2D1_SCALE_PROP_INTERPOLATION_MODE, - D2D1_SCALE_INTERPOLATION_MODE_LINEAR - ) - ); - m_borderEffect->SetInputEffect(0, m_scaleDownEffect.get()); - RETURN_IF_FAILED( - m_borderEffect->SetValue( - D2D1_BORDER_PROP_EDGE_MODE_X, - D2D1_BORDER_EDGE_MODE_MIRROR - ) - ); - RETURN_IF_FAILED( - m_borderEffect->SetValue( - D2D1_BORDER_PROP_EDGE_MODE_Y, - D2D1_BORDER_EDGE_MODE_MIRROR - ) - ); - m_directionalBlurXEffect->SetInputEffect(0, m_borderEffect.get()); - RETURN_IF_FAILED( - m_directionalBlurXEffect->SetValue( - D2D1_DIRECTIONALBLURKERNEL_PROP_DIRECTION, - D2D1_DIRECTIONALBLURKERNEL_DIRECTION_X - ) - ); - m_directionalBlurYEffect->SetInputEffect(0, m_directionalBlurXEffect.get()); - RETURN_IF_FAILED( - m_directionalBlurYEffect->SetValue( - D2D1_DIRECTIONALBLURKERNEL_PROP_DIRECTION, - D2D1_DIRECTIONALBLURKERNEL_DIRECTION_Y - ) - ); - m_scaleUpEffect->SetInputEffect(0, m_directionalBlurYEffect.get()); - RETURN_IF_FAILED(m_scaleUpEffect->SetValue(D2D1_SCALE_PROP_SHARPNESS, 1.f)); - RETURN_IF_FAILED( - m_scaleUpEffect->SetValue( - D2D1_SCALE_PROP_BORDER_MODE, - D2D1_BORDER_MODE_HARD - ) - ); - RETURN_IF_FAILED( - m_scaleUpEffect->SetValue( - D2D1_SCALE_PROP_INTERPOLATION_MODE, - D2D1_SCALE_INTERPOLATION_MODE_LINEAR - ) - ); - - return S_OK; -} - -HRESULT CCustomBlurEffect::SetParamsAero() -{ - // now here we start setting values, or atleast the default values - // imma have to investigate later in the file whats being done but otherwise - - - RETURN_IF_FAILED( m_cropInputEffect->SetValue( D2D1_CROP_PROP_BORDER_MODE, D2D1_BORDER_MODE_SOFT - ) + ) ); m_scaleDownEffect->SetInputEffect(0, m_cropInputEffect.get()); RETURN_IF_FAILED(m_scaleDownEffect->SetValue(D2D1_SCALE_PROP_SHARPNESS, 1.f)); @@ -260,156 +60,50 @@ HRESULT CCustomBlurEffect::SetParamsAero() m_scaleDownEffect->SetValue( D2D1_SCALE_PROP_BORDER_MODE, D2D1_BORDER_MODE_HARD - ) - ); - RETURN_IF_FAILED( - m_scaleDownEffect->SetValue( - D2D1_SCALE_PROP_INTERPOLATION_MODE, - D2D1_SCALE_INTERPOLATION_MODE_ANISOTROPIC - ) + ) ); m_borderEffect->SetInputEffect(0, m_scaleDownEffect.get()); RETURN_IF_FAILED( m_borderEffect->SetValue( D2D1_BORDER_PROP_EDGE_MODE_X, D2D1_BORDER_EDGE_MODE_MIRROR - ) + ) ); RETURN_IF_FAILED( m_borderEffect->SetValue( D2D1_BORDER_PROP_EDGE_MODE_Y, D2D1_BORDER_EDGE_MODE_MIRROR - ) + ) ); m_directionalBlurXEffect->SetInputEffect(0, m_borderEffect.get()); RETURN_IF_FAILED( m_directionalBlurXEffect->SetValue( D2D1_DIRECTIONALBLURKERNEL_PROP_DIRECTION, D2D1_DIRECTIONALBLURKERNEL_DIRECTION_X - ) + ) ); m_directionalBlurYEffect->SetInputEffect(0, m_directionalBlurXEffect.get()); RETURN_IF_FAILED( m_directionalBlurYEffect->SetValue( D2D1_DIRECTIONALBLURKERNEL_PROP_DIRECTION, D2D1_DIRECTIONALBLURKERNEL_DIRECTION_Y - ) - ); - - - // CREDITS: @kfh83, @wiktorwiktor12, @TorutheRedFox and @WackyIdeas. special shoutouts to @aubymori and @kawapure for testing/help - - // okay my conclusion is that i shouldnt tamper with whatever was already set up (no point in removing the scales or adding gaussian blur) - // so since all of the blur work is done here, starting my part of it: - - // afterglow - m_saturationEffect->SetInputEffect(0, m_directionalBlurYEffect.get()); - RETURN_IF_FAILED( - m_saturationEffect->SetValue( - D2D1_SATURATION_PROP_SATURATION, - 0.0f - ) - ); - - m_tintEffect->SetInputEffect(0, m_saturationEffect.get()); - RETURN_IF_FAILED( - m_tintEffect->SetValue( - D2D1_TINT_PROP_COLOR, - D2D1::Vector4F(m_Color.r, m_Color.g, m_Color.b, 1.0f) - ) - ); - - - D2D1_MATRIX_5X4_F AfterglowBalanceM = D2D1::Matrix5x4F(m_colorizationAfterglowBalanceVal, 0.f, 0.f, 0.f, - 0.f, m_colorizationAfterglowBalanceVal, 0.f, 0.f, - 0.f, 0.f, m_colorizationAfterglowBalanceVal, 0.f, - 0.f, 0.f, 0.f, 1.f, - 0.f, 0.f, 0.f, 0.f); - - m_ColorizationAfterglowBalance->SetInputEffect(0, m_tintEffect.get()); - RETURN_IF_FAILED( - m_ColorizationAfterglowBalance->SetValue( - D2D1_COLORMATRIX_PROP_COLOR_MATRIX, - AfterglowBalanceM - ) - ); - - // afterglow done - - // heres blur balance - D2D1_MATRIX_5X4_F BlurBalanceM = D2D1::Matrix5x4F(m_colorizationBlurBalanceVal, 0.f, 0.f, 0.f, - 0.f, m_colorizationBlurBalanceVal, 0.f, 0.f, - 0.f, 0.f, m_colorizationBlurBalanceVal, 0.f, - 0.f, 0.f, 0.f, 1.f, - 0.f, 0.f, 0.f, 0.f); - - m_ColorizationBlurBalance->SetInputEffect(0, m_directionalBlurYEffect.get()); - RETURN_IF_FAILED( - m_ColorizationBlurBalance->SetValue( - D2D1_COLORMATRIX_PROP_COLOR_MATRIX, - BlurBalanceM - ) - ); - - // and finally ColorizationColor - - RETURN_IF_FAILED( - m_ColorizationColor->SetValue( - D2D1_FLOOD_PROP_COLOR, - D2D1::Vector4F(m_Color.r, m_Color.g, m_Color.b, 1.0f) - ) - ); - - D2D1_MATRIX_5X4_F ColorBalanceM = D2D1::Matrix5x4F(m_colorizationColorBalanceVal, 0.f, 0.f, 0.f, - 0.f, m_colorizationColorBalanceVal, 0.f, 0.f, - 0.f, 0.f, m_colorizationColorBalanceVal, 0.f, - 0.f, 0.f, 0.f, 1.f, - 0.f, 0.f, 0.f, 0.f); - - m_ColorizationColorBalance->SetInputEffect(0, m_ColorizationColor.get()); - RETURN_IF_FAILED( - m_ColorizationColorBalance->SetValue( - D2D1_COLORMATRIX_PROP_COLOR_MATRIX, - ColorBalanceM - ) - ); - - - // imma blend it together jus to see - m_compositeEffect->SetInputEffect(0, m_ColorizationBlurBalance.get()); - m_compositeEffect->SetInputEffect(1, m_ColorizationAfterglowBalance.get()); - RETURN_IF_FAILED( - m_compositeEffect->SetValue( - D2D1_COMPOSITE_PROP_MODE, - D2D1_COMPOSITE_MODE_PLUS - ) - ); - - m_compositeEffect_pass2->SetInputEffect(0, m_compositeEffect.get()); - m_compositeEffect_pass2->SetInputEffect(1, m_ColorizationColorBalance.get()); - RETURN_IF_FAILED( - m_compositeEffect_pass2->SetValue( - D2D1_COMPOSITE_PROP_MODE, - D2D1_COMPOSITE_MODE_PLUS - ) + ) ); - // okay - - m_scaleUpEffect->SetInputEffect(0, m_compositeEffect_pass2.get()); + m_scaleUpEffect->SetInputEffect(0, m_directionalBlurYEffect.get()); RETURN_IF_FAILED(m_scaleUpEffect->SetValue(D2D1_SCALE_PROP_SHARPNESS, 1.f)); RETURN_IF_FAILED( m_scaleUpEffect->SetValue( D2D1_SCALE_PROP_BORDER_MODE, D2D1_BORDER_MODE_HARD - ) + ) ); - RETURN_IF_FAILED( m_scaleUpEffect->SetValue( D2D1_SCALE_PROP_INTERPOLATION_MODE, - D2D1_SCALE_INTERPOLATION_MODE_ANISOTROPIC - ) + D2D1_SCALE_INTERPOLATION_MODE_LINEAR + ) ); + m_initialized = true; return S_OK; } @@ -435,44 +129,17 @@ float CCustomBlurEffect::DetermineOutputScale(float size, float blurAmount) return outputScale; } -HRESULT STDMETHODCALLTYPE CCustomBlurEffect::Invalidate( +HRESULT STDMETHODCALLTYPE CCustomBlurEffect::SetInput( + ID2D1DeviceContext* context, ID2D1Image* inputImage, const D2D1_RECT_F& imageRectangle, const D2D1_RECT_F& imageBounds, - float blurAmount, - float colorizationAfterglowBalanceVal, - float colorizationBlurBalanceVal, - float colorizationColorBalanceVal, - D2D1_COLOR_F color, - Type type + float blurAmount ) { - //colorizationAfterglowBalanceVal = 0.49f; - //colorizationBlurBalanceVal = 0.796f; - //colorizationColorBalanceVal = 0.08f; - if (!inputImage) return S_FALSE; - - bool recalculateParams{ false }; - if (m_blurAmount != blurAmount || m_colorizationAfterglowBalanceVal != colorizationAfterglowBalanceVal || - m_colorizationBlurBalanceVal != colorizationBlurBalanceVal || - m_colorizationColorBalanceVal != colorizationColorBalanceVal || (m_Color.r != color.r) || (m_Color.g != color.g) || (m_Color.b != color.b) || (m_Color.a != color.a) ) + if (!m_initialized) { - m_blurAmount = blurAmount; - m_colorizationAfterglowBalanceVal = colorizationAfterglowBalanceVal; - m_colorizationBlurBalanceVal = colorizationBlurBalanceVal; - m_colorizationColorBalanceVal = colorizationColorBalanceVal; - m_Color = color; - recalculateParams = true; - } - - //todo: fix handling type changes at runtime - if (!m_initialized || m_type != type) - { - m_type = type; - if (m_type == Type::Blur) - RETURN_IF_FAILED(Initialize()); - else if (m_type == Type::Aero) - RETURN_IF_FAILED(InitializeAero()); + RETURN_IF_FAILED(Initialize(context)); } if (m_effectInput != inputImage) { @@ -480,7 +147,12 @@ HRESULT STDMETHODCALLTYPE CCustomBlurEffect::Invalidate( m_cropInputEffect->SetInput(0, inputImage); } - + bool recalculateParams{ false }; + if (m_blurAmount != blurAmount) + { + m_blurAmount = blurAmount; + recalculateParams = true; + } if (memcmp(&m_imageRectangle, &imageRectangle, sizeof(D2D1_RECT_F)) != 0) { m_imageRectangle = imageRectangle; @@ -507,6 +179,15 @@ HRESULT STDMETHODCALLTYPE CCustomBlurEffect::Invalidate( ) ); + RETURN_IF_FAILED( + m_scaleDownEffect->SetValue( + D2D1_SCALE_PROP_INTERPOLATION_MODE, + blurAmount > 3.f ? + D2D1_SCALE_INTERPOLATION_MODE_ANISOTROPIC : + D2D1_SCALE_INTERPOLATION_MODE_LINEAR + ) + ); + D2D1_VECTOR_2F prescaleAmount { DetermineOutputScale(actualImageRect.right - actualImageRect.left, blurAmount), @@ -514,7 +195,7 @@ HRESULT STDMETHODCALLTYPE CCustomBlurEffect::Invalidate( }; D2D1_VECTOR_2F finalBlurAmount{ blurAmount, blurAmount }; D2D1_VECTOR_2F outputOffset{ 0.f, 0.f }; - auto finalPrescaleAmount{ prescaleAmount }; + auto finalPrescaleAmount = prescaleAmount; if (prescaleAmount.x != 1.f && finalBlurAmount.x > k_optimizations[2]) { @@ -608,12 +289,6 @@ HRESULT STDMETHODCALLTYPE CCustomBlurEffect::Invalidate( (prescaleAmount.y != finalPrescaleAmount.y) ? D2D1_DIRECTIONALBLURKERNEL_OPTIMIZATION_TRANSFORM_SCALE : D2D1_DIRECTIONALBLURKERNEL_OPTIMIZATION_TRANSFORM_IDENDITY ) ); - - if (m_type == Type::Blur) - RETURN_IF_FAILED(SetParams()); - else if (m_type == Type::Aero) - RETURN_IF_FAILED(SetParamsAero()); - #ifdef _DEBUG OutputDebugStringW( std::format( @@ -635,37 +310,13 @@ HRESULT STDMETHODCALLTYPE CCustomBlurEffect::Invalidate( return S_OK; } -HRESULT STDMETHODCALLTYPE CCustomBlurEffect::Draw( - CONST D2D1_RECT_F& bounds, - D2D1_INTERPOLATION_MODE interpolationMode, - D2D1_COMPOSITE_MODE compositeMode -) +void STDMETHODCALLTYPE CCustomBlurEffect::Reset() { - m_deviceContext->DrawImage( - m_effectOutput.get(), - D2D1::Point2F( - bounds.left + m_imageRectangle.left, - bounds.top + m_imageRectangle.top - ), - D2D1::RectF( - m_imageRectangle.left, - m_imageRectangle.top, - m_imageRectangle.left + min(m_imageRectangle.right - m_imageRectangle.left, bounds.right - bounds.left - m_imageRectangle.left), - m_imageRectangle.top + min(m_imageRectangle.bottom - m_imageRectangle.top, bounds.bottom - bounds.top - m_imageRectangle.top) - ), - interpolationMode, - compositeMode - ); - /*{ - winrt::com_ptr brush{}; - m_deviceContext->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::Red), brush.put()); - m_deviceContext->DrawRectangle(D2D1::RectF( - bounds.left + m_imageRectangle.left + 0.5f, - bounds.left + m_imageRectangle.top + 0.5f, - min(bounds.left + m_imageRectangle.right - 0.5f, bounds.right), - min(bounds.top + m_imageRectangle.bottom - 0.5f, bounds.bottom) - ), brush.get(), 1.f); - }*/ - - return S_OK; -} + if (m_cropInputEffect) + { + m_cropInputEffect->SetInput(0, nullptr); + } + m_imageRectangle = {}; + m_effectInput = nullptr; + m_effectOutput = nullptr; +} \ No newline at end of file diff --git a/OpenGlass/CustomBlurEffect.hpp b/OpenGlass/CustomBlurEffect.hpp index 9a72028..18621d8 100644 --- a/OpenGlass/CustomBlurEffect.hpp +++ b/OpenGlass/CustomBlurEffect.hpp @@ -2,8 +2,12 @@ #include "pch.h" #include "framework.hpp" #include "cpprt.hpp" -#include "GlassSharedStructures.hpp" +// this is actually a full mirror implementation of dwmcore!CCustomBlur, +// in order to produce a high performance blur effect than raw direct2d gaussian blur effect +// no reason for touching it + +// i have to apologize to all other contributors since i completely refactor this part of the code namespace OpenGlass { const GUID CLSID_D2D1DirectionalBlurKernel{ 0x58EB6E2A, 0x0D779, 0x4B7D, { 0x0AD, 0x39, 0x6F, 0x5A, 0x9F, 0x0C9, 0x0D2, 0x88} }; @@ -24,25 +28,16 @@ namespace OpenGlass D2D1_DIRECTIONALBLURKERNEL_OPTIMIZATION_TRANSFORM_IDENDITY, D2D1_DIRECTIONALBLURKERNEL_OPTIMIZATION_TRANSFORM_SCALE }; - + // [Guid("01AA613C-2376-4B95-8A74-B94CA840D4D1")] DECLARE_INTERFACE_IID_(ICustomBlurEffect, IUnknown, "01AA613C-2376-4B95-8A74-B94CA840D4D1") { - virtual HRESULT STDMETHODCALLTYPE Invalidate( + virtual HRESULT STDMETHODCALLTYPE SetInput( + ID2D1DeviceContext* context, ID2D1Image* inputImage, const D2D1_RECT_F& imageRectangle, const D2D1_RECT_F& imageBounds, - float blurAmount, - float colorizationAfterglowBalanceVal, - float colorizationBlurBalanceVal, - float colorizationColorBalanceVal, - D2D1_COLOR_F color, - Type type - ) = 0; - virtual HRESULT STDMETHODCALLTYPE Draw( - CONST D2D1_RECT_F & bounds, - D2D1_INTERPOLATION_MODE interpolationMode = D2D1_INTERPOLATION_MODE_NEAREST_NEIGHBOR, - D2D1_COMPOSITE_MODE compositeMode = D2D1_COMPOSITE_MODE_BOUNDED_SOURCE_COPY + float blurAmount ) = 0; virtual ID2D1Image* STDMETHODCALLTYPE GetOutput() const = 0; virtual void STDMETHODCALLTYPE Reset() = 0; @@ -51,65 +46,31 @@ namespace OpenGlass class CCustomBlurEffect : public winrt::implements { bool m_initialized{ false }; + float m_blurAmount{ 9.f }; - Type m_type{Type::Blur}; D2D1_RECT_F m_imageRectangle{}; ID2D1Image* m_effectInput{ nullptr }; winrt::com_ptr m_effectOutput{ nullptr }; - winrt::com_ptr m_deviceContext{ nullptr }; + winrt::com_ptr m_cropInputEffect{}; winrt::com_ptr m_scaleDownEffect{}; winrt::com_ptr m_borderEffect{}; winrt::com_ptr m_directionalBlurXEffect{}; winrt::com_ptr m_directionalBlurYEffect{}; winrt::com_ptr m_scaleUpEffect{}; - - // new stuff - winrt::com_ptr m_compositeEffect{}; - winrt::com_ptr m_compositeEffect_pass2{}; - winrt::com_ptr m_saturationEffect{}; - winrt::com_ptr m_tintEffect{}; - winrt::com_ptr m_ColorizationAfterglowBalance{}; - winrt::com_ptr m_ColorizationBlurBalance{}; - winrt::com_ptr m_ColorizationColorBalance{}; - winrt::com_ptr m_ColorizationColor{}; - - float m_colorizationAfterglowBalanceVal = 0.43f; - float m_colorizationBlurBalanceVal = 0.49f; - float m_colorizationColorBalanceVal = 0.08f; - D2D1_COLOR_F m_Color = { 116.0f / 255.0f, 184.0f / 255.0f, 252.0f / 255.0f,1.0f }; static const float k_optimizations[16]; static float DetermineOutputScale(float size, float blurAmount); - HRESULT Initialize(); - HRESULT InitializeAero(); - HRESULT SetParams(); - HRESULT SetParamsAero(); + HRESULT Initialize(ID2D1DeviceContext* context); public: - CCustomBlurEffect(ID2D1DeviceContext* deviceContext); - - HRESULT STDMETHODCALLTYPE Invalidate( + HRESULT STDMETHODCALLTYPE SetInput( + ID2D1DeviceContext* context, ID2D1Image* inputImage, const D2D1_RECT_F& imageRectangle, const D2D1_RECT_F& imageBounds, - float blurAmount, - float colorizationAfterglowBalanceVal, - float colorizationBlurBalanceVal, - float colorizationColorBalanceVal, - D2D1_COLOR_F color, - Type type - ) override; - HRESULT STDMETHODCALLTYPE Draw( - CONST D2D1_RECT_F& bounds, - D2D1_INTERPOLATION_MODE interpolationMode, - D2D1_COMPOSITE_MODE compositeMode + float blurAmount ) override; ID2D1Image* STDMETHODCALLTYPE GetOutput() const override { return m_effectOutput.get(); } - void STDMETHODCALLTYPE Reset() - { - if (m_cropInputEffect) { m_cropInputEffect->SetInput(0, nullptr); } - m_imageRectangle = {}; - m_effectInput = nullptr; - } + void STDMETHODCALLTYPE Reset() override; }; } \ No newline at end of file diff --git a/OpenGlass/CustomMsstyleLoader.cpp b/OpenGlass/CustomMsstyleLoader.cpp index f42762b..187641f 100644 --- a/OpenGlass/CustomMsstyleLoader.cpp +++ b/OpenGlass/CustomMsstyleLoader.cpp @@ -38,14 +38,18 @@ namespace OpenGlass::CustomMsstyleLoader DWORD unknwon2; CHAR themeFooter[4]{ "end" }; + bool IsValid() const + { + return sharableSectionView && unsharableSectionView; + } ~CUxThemeFile() { - auto unknown{ *unsharableSectionView.get() }; + auto unknown = *unsharableSectionView.get(); sharableSectionView.reset(); unsharableSectionView.reset(); if ((unknown & 4) != 0 && (unknown & 2) == 0) { - static const auto s_ClearTheme{ reinterpret_cast(GetProcAddress(GetModuleHandleW(L"uxtheme.dll"), MAKEINTRESOURCEA(84))) }; + static const auto s_ClearTheme = reinterpret_cast(GetProcAddress(GetModuleHandleW(L"uxtheme.dll"), MAKEINTRESOURCEA(84))); if (s_ClearTheme) [[likely]] { LOG_IF_FAILED(s_ClearTheme(sharableSection.release(), unsharableSection.release(), FALSE)); @@ -85,9 +89,9 @@ HTHEME WINAPI CustomMsstyleLoader::MyOpenThemeData( LPCWSTR pszClassList ) { - if (g_msstyleThemeFile) + if (g_msstyleThemeFile && g_msstyleThemeFile->IsValid()) { - static const auto s_OpenThemeDataFromFile{ reinterpret_cast(GetProcAddress(GetModuleHandleW(L"uxtheme.dll"), MAKEINTRESOURCEA(16))) }; + static const auto s_OpenThemeDataFromFile = reinterpret_cast(GetProcAddress(GetModuleHandleW(L"uxtheme.dll"), MAKEINTRESOURCEA(16))); if (s_OpenThemeDataFromFile) [[likely]] { return s_OpenThemeDataFromFile(g_msstyleThemeFile.get(), hwnd, pszClassList, 0); @@ -122,7 +126,7 @@ void CustomMsstyleLoader::UpdateConfiguration(ConfigurationFramework::UpdateType WCHAR colorSchemeName[MAX_PATH + 1]{}; WCHAR sizeName[MAX_PATH + 1]{}; - static const auto s_GetThemeDefaults{ reinterpret_cast(GetProcAddress(GetModuleHandleW(L"uxtheme.dll"), MAKEINTRESOURCEA(7)))}; + static const auto s_GetThemeDefaults = reinterpret_cast(GetProcAddress(GetModuleHandleW(L"uxtheme.dll"), MAKEINTRESOURCEA(7))); if (s_GetThemeDefaults && g_useMsstyleDefaultScheme) { THROW_IF_FAILED(s_GetThemeDefaults(g_msstyleThemePath.c_str(), colorSchemeName, MAX_PATH, sizeName, MAX_PATH)); @@ -133,7 +137,7 @@ void CustomMsstyleLoader::UpdateConfiguration(ConfigurationFramework::UpdateType } g_msstyleThemeFile = std::make_unique(); - static const auto s_LoaderLoadTheme{ GetProcAddress(GetModuleHandleW(L"uxtheme.dll"), MAKEINTRESOURCEA(92)) }; + static const auto s_LoaderLoadTheme = GetProcAddress(GetModuleHandleW(L"uxtheme.dll"), MAKEINTRESOURCEA(92)); if (s_LoaderLoadTheme) [[likely]] { HRESULT hr{ S_OK }; diff --git a/OpenGlass/GeometryRecorder.cpp b/OpenGlass/GeometryRecorder.cpp index db506dc..7547a26 100644 --- a/OpenGlass/GeometryRecorder.cpp +++ b/OpenGlass/GeometryRecorder.cpp @@ -129,7 +129,7 @@ void GeometryRecorder::BeginCapture() } HRGN GeometryRecorder::GetRegionFromGeometry(uDwm::CBaseGeometryProxy* geometry) { - auto it{ g_geometryMap.find(geometry) }; + auto it = g_geometryMap.find(geometry); if (it == g_geometryMap.end()) { return nullptr; diff --git a/OpenGlass/GlassEffect.cpp b/OpenGlass/GlassEffect.cpp new file mode 100644 index 0000000..e3f0dde --- /dev/null +++ b/OpenGlass/GlassEffect.cpp @@ -0,0 +1,376 @@ +#include "pch.h" +#include "Utils.hpp" +#include "uDwmProjection.hpp" +#include "GlassFramework.hpp" +#include "GlassEffect.hpp" +#include "AeroEffect.hpp" +#include "BlurEffect.hpp" +#include "Shared.hpp" + +using namespace OpenGlass; +namespace OpenGlass::GlassEffectFactory +{ + std::unordered_map> g_glassEffectMap{}; + + class CGlassEffect : public winrt::implements + { + D2D1_COLOR_F m_color{}; + D2D1_COLOR_F m_afterglow{}; + float m_glassOpacity{ 0.63f }; + float m_blurAmount{ 9.f }; + float m_colorBalance{ 0.f }; + float m_afterglowBalance{ 0.f }; + float m_blurBalance{ 0.f }; + Shared::Type m_type{ Shared::Type::Blur }; + PVOID m_originalVTable{ nullptr }; + + std::unordered_map> m_inputMap{}; + std::variant, winrt::com_ptr> m_customEffect{ nullptr }; + public: + void STDMETHODCALLTYPE SetGlassRenderingParameters( + const D2D1_COLOR_F& color, + const D2D1_COLOR_F& afterglow, + float glassOpacity, + float blurAmount, + float colorBalance, + float afterglowBalance, + float blurBalance, + Shared::Type type + ) override; + HRESULT STDMETHODCALLTYPE Render( + ID2D1DeviceContext* context, + ID2D1Geometry* geometry, + const D2D1_RECT_F& clipWorldBounds + ) override; + }; +} + +void STDMETHODCALLTYPE GlassEffectFactory::CGlassEffect::SetGlassRenderingParameters( + const D2D1_COLOR_F& color, + const D2D1_COLOR_F& afterglow, + float glassOpacity, + float blurAmount, + float colorBalance, + float afterglowBalance, + float blurBalance, + Shared::Type type +) +{ + m_color = color; + m_afterglow = afterglow; + m_glassOpacity = glassOpacity; + m_blurAmount = blurAmount; + m_colorBalance = colorBalance; + m_afterglowBalance = afterglowBalance; + m_blurBalance = blurBalance; + if (m_type != type) + { + m_type = type; + m_customEffect = nullptr; + } +} + +HRESULT STDMETHODCALLTYPE GlassEffectFactory::CGlassEffect::Render( + ID2D1DeviceContext* context, + ID2D1Geometry* geometry, + const D2D1_RECT_F& clipWorldBounds +) +{ + winrt::com_ptr targetBitmap{ nullptr }; + { + winrt::com_ptr image{ nullptr }; + context->GetTarget(image.put()); + if (!image) + { + return D2DERR_BITMAP_CANNOT_DRAW; + } + else + { + RETURN_IF_FAILED(image->QueryInterface(targetBitmap.put())); + } + } + if (!m_originalVTable) + { + m_originalVTable = *reinterpret_cast(targetBitmap.get()); + } + auto pixelFormat = targetBitmap->GetPixelFormat(); + + D2D1_MATRIX_3X2_F matrix{}; + context->GetTransform(&matrix); + D2D1_RECT_F geometryWorldBounds{}; + RETURN_IF_FAILED(geometry->GetBounds(&matrix, &geometryWorldBounds)); + + winrt::com_ptr inputBitmap{ nullptr }; + for (auto it = m_inputMap.begin(); it != m_inputMap.end(); ) + { + if (targetBitmap.get() == it->first) + { + inputBitmap = it->second; + } + if (IsBadReadPtr(it->first, sizeof(PVOID*)) || *reinterpret_cast(it->first) != m_originalVTable) + { +#ifdef _DEBUG + OutputDebugStringW(std::format(L"target bitmap: [{}] released, release corresponding input bitmap: [{}].\n", (void*)it->first, (void*)it->second.get()).c_str()); +#endif // _DEBUG + it = m_inputMap.erase(it); + } + else + { +#ifdef _DEBUG + auto ref = it->first->AddRef(); + OutputDebugStringW( + std::format( + L"target bitmap: [{}] current ref count: {}.\n", + (void*)it->first, + ref + ).c_str() + ); + it->first->Release(); +#endif // _DEBUG + it++; + } + } +#ifdef _DEBUG + OutputDebugStringW(std::format(L"inputMap count: {}\n", m_inputMap.size()).c_str()); +#endif // _DEBUG + + if (std::holds_alternative(m_customEffect)) + { + switch (m_type) + { + case Shared::Type::Blur: + { + m_customEffect = winrt::make(); + break; + } + case Shared::Type::Aero: + { + m_customEffect = winrt::make(); + break; + } + default: + break; + } + } + // size changed + if (inputBitmap) + { + if ( + D2D1_SIZE_F size{ inputBitmap->GetSize() }, actualSize{ geometryWorldBounds.right - geometryWorldBounds.left, geometryWorldBounds.bottom - geometryWorldBounds.top }; + size.width != actualSize.width || + size.height != actualSize.height + ) + { + inputBitmap = nullptr; + } + } + if (!inputBitmap) + { + RETURN_IF_FAILED( + context->CreateBitmap( + D2D1::SizeU( + dwmcore::PixelAlign(geometryWorldBounds.right - geometryWorldBounds.left), + dwmcore::PixelAlign(geometryWorldBounds.bottom - geometryWorldBounds.top) + ), + nullptr, + 0, + D2D1::BitmapProperties1( + D2D1_BITMAP_OPTIONS_NONE, + pixelFormat + ), + inputBitmap.put() + ) + ); + m_inputMap.insert_or_assign(targetBitmap.get(), inputBitmap); + +#ifdef _DEBUG + OutputDebugStringW(std::format(L"allocated input bitmap: [{}] for target bitmap: [{}].\n", (void*)inputBitmap.get(), (void*)targetBitmap.get()).c_str()); +#endif // _DEBUG + + switch (m_type) + { + case Shared::Type::Blur: + { + std::get>(m_customEffect)->Reset(); + break; + } + case Shared::Type::Aero: + { + std::get>(m_customEffect)->Reset(); + break; + } + default: + break; + } + } + + D2D1_RECT_F drawingWorldBounds + { + max(clipWorldBounds.left, geometryWorldBounds.left), + max(clipWorldBounds.top, geometryWorldBounds.top), + min(clipWorldBounds.right, geometryWorldBounds.right), + min(clipWorldBounds.bottom, geometryWorldBounds.bottom) + }; + D2D1_RECT_F dirtyRectangle + { + drawingWorldBounds.left - geometryWorldBounds.left, + drawingWorldBounds.top - geometryWorldBounds.top + }; + dirtyRectangle.right = dirtyRectangle.left + (drawingWorldBounds.right - drawingWorldBounds.left); + dirtyRectangle.bottom = dirtyRectangle.top + (drawingWorldBounds.bottom - drawingWorldBounds.top); + D2D1_POINT_2U dest + { + dwmcore::PixelAlign(dirtyRectangle.left), + dwmcore::PixelAlign(dirtyRectangle.top) + }; + D2D1_RECT_U src + { + dwmcore::PixelAlign(drawingWorldBounds.left), + dwmcore::PixelAlign(drawingWorldBounds.top), + dwmcore::PixelAlign(drawingWorldBounds.right), + dwmcore::PixelAlign(drawingWorldBounds.bottom) + }; + RETURN_IF_FAILED( + inputBitmap->CopyFromBitmap( + &dest, + targetBitmap.get(), + &src + ) + ); + + auto imageBounds = D2D1::RectF( + 0.f, + 0.f, + geometryWorldBounds.right - geometryWorldBounds.left, + geometryWorldBounds.bottom - geometryWorldBounds.top + ); + switch (m_type) + { + case Shared::Type::Blur: + { + RETURN_IF_FAILED( + std::get>(m_customEffect)->SetInput( + context, + inputBitmap.get(), + dirtyRectangle, + imageBounds, + m_blurAmount, + m_color, + m_glassOpacity + ) + ); + break; + } + case Shared::Type::Aero: + { + RETURN_IF_FAILED( + std::get>(m_customEffect)->SetInput( + context, + inputBitmap.get(), + dirtyRectangle, + imageBounds, + m_blurAmount, + m_color, + m_afterglow, + m_colorBalance, + m_afterglowBalance, + m_blurBalance + ) + ); + break; + } + default: + break; + } + + context->SetTransform(D2D1::IdentityMatrix()); + context->PushLayer( + D2D1::LayerParameters1( + drawingWorldBounds, + geometry, + D2D1_ANTIALIAS_MODE_ALIASED, + matrix, + 1.f, + nullptr, + D2D1_LAYER_OPTIONS1_INITIALIZE_FROM_BACKGROUND | + ( + pixelFormat.alphaMode == D2D1_ALPHA_MODE_IGNORE ? + D2D1_LAYER_OPTIONS1_IGNORE_ALPHA : + D2D1_LAYER_OPTIONS1_NONE + ) + ), + nullptr + ); + + ID2D1Image* outputImage{ nullptr }; + switch (m_type) + { + case Shared::Type::Blur: + { + outputImage = std::get>(m_customEffect)->GetOutput(); + break; + } + case Shared::Type::Aero: + { + outputImage = std::get>(m_customEffect)->GetOutput(); + break; + } + default: + break; + } + if (outputImage) + { + context->DrawImage( + outputImage, + D2D1::Point2F( + drawingWorldBounds.left, + drawingWorldBounds.top + ), + D2D1::RectF( + dirtyRectangle.left, + dirtyRectangle.top, + dirtyRectangle.right, + dirtyRectangle.bottom + ), + D2D1_INTERPOLATION_MODE_NEAREST_NEIGHBOR, + D2D1_COMPOSITE_MODE_BOUNDED_SOURCE_COPY + ); + } + + context->PopLayer(); + context->SetTransform(matrix); + + return S_OK; +} + +winrt::com_ptr GlassEffectFactory::GetOrCreate(dwmcore::CGeometry* geometry, bool createIfNecessary) +{ + auto it= g_glassEffectMap.find(geometry); + + if (createIfNecessary) + { + if (it == g_glassEffectMap.end()) + { + auto result = g_glassEffectMap.emplace(geometry, winrt::make()); + if (result.second == true) + { + it = result.first; + } + } + } + + return it == g_glassEffectMap.end() ? nullptr : it->second; +} +void GlassEffectFactory::Remove(dwmcore::CGeometry* geometry) +{ + auto it = g_glassEffectMap.find(geometry); + + if (it != g_glassEffectMap.end()) + { + g_glassEffectMap.erase(it); + } +} +void GlassEffectFactory::Shutdown() +{ + g_glassEffectMap.clear(); +} \ No newline at end of file diff --git a/OpenGlass/GlassEffect.hpp b/OpenGlass/GlassEffect.hpp new file mode 100644 index 0000000..2c85963 --- /dev/null +++ b/OpenGlass/GlassEffect.hpp @@ -0,0 +1,38 @@ +#pragma once +#include "framework.hpp" +#include "cpprt.hpp" +#include "uDwmProjection.hpp" +#include "Shared.hpp" + +namespace OpenGlass +{ + // [Guid("01AA613C-2376-4B95-8A74-B94CA840D4D1")] + DECLARE_INTERFACE_IID_(IGlassEffect, IUnknown, "01AA613C-2376-4B95-8A74-B94CA840D4D1") + { + virtual void STDMETHODCALLTYPE SetGlassRenderingParameters( + const D2D1_COLOR_F& color, + const D2D1_COLOR_F& afterglow, + float glassOpacity, + float blurAmount, + float colorBalance, + float afterglowBalance, + float blurBalance, + Shared::Type type + ) = 0; + virtual HRESULT STDMETHODCALLTYPE Render( + ID2D1DeviceContext* context, + ID2D1Geometry* geometry, + const D2D1_RECT_F& clipWorldBounds + ) = 0; + }; + + namespace GlassEffectFactory + { + winrt::com_ptr GetOrCreate( + dwmcore::CGeometry* geometry, + bool createIfNecessary = false + ); + void Remove(dwmcore::CGeometry* geometry); + void Shutdown(); + } +} \ No newline at end of file diff --git a/OpenGlass/GlassEffectManager.cpp b/OpenGlass/GlassEffectManager.cpp deleted file mode 100644 index 3194cac..0000000 --- a/OpenGlass/GlassEffectManager.cpp +++ /dev/null @@ -1,304 +0,0 @@ -#include "pch.h" -#include "Utils.hpp" -#include "uDwmProjection.hpp" -#include "GlassFramework.hpp" -#include "GlassEffectManager.hpp" -#include "ReflectionRenderer.hpp" -#include "CustomBlurEffect.hpp" -#include "GlassSharedStructures.hpp" - -using namespace OpenGlass; -namespace OpenGlass::GlassEffectManager -{ - std::unordered_map> g_glassEffectMap{}; - - class CGlassEffect : public winrt::implements - { - bool m_initialized{ false }; - Type m_type{ Type::Blur }; - float m_glassOpacity{ 0.63f }; - float m_blurAmount{ 9.f }; - D2D1_COLOR_F m_color{}; - - D2D1_SIZE_F m_glassSize{}; - D2D1_SIZE_F m_desktopSize{}; - D2D1_POINT_2F m_glassDesktopPosition{}; - D2D1_PIXEL_FORMAT m_backdropPixelFormat{}; - - winrt::com_ptr m_deviceContext{ nullptr }; - winrt::com_ptr m_blurBuffer{ nullptr }; - winrt::com_ptr m_customBlurEffect{ nullptr }; - - float m_colorizationAfterglowBalanceVal; - float m_colorizationBlurBalanceVal; - float m_colorizationColorBalanceVal; - - HRESULT Initialize(); - public: - CGlassEffect(ID2D1DeviceContext* deviceContext) { winrt::copy_from_abi(m_deviceContext, deviceContext); } - - void STDMETHODCALLTYPE SetGlassRenderingParameters( - const D2D1_COLOR_F& color, - float glassOpacity, - float blurAmount, - float colorizationAfterglowBalanceVal, - float colorizationBlurBalanceVal, - float colorizationColorBalanceVal, - Type type - ) override; - void STDMETHODCALLTYPE SetSize(const D2D1_SIZE_F& size) override; - HRESULT STDMETHODCALLTYPE Invalidate( - ID2D1Bitmap1* backdropBitmap, - const D2D1_POINT_2F& glassDesktopPosition, - const D2D1_RECT_F& desktopRedrawRect, - bool normalDesktopRender - ) override; - HRESULT STDMETHODCALLTYPE Render(ID2D1Geometry* geometry, ID2D1SolidColorBrush* brush) override; - }; -} - -HRESULT GlassEffectManager::CGlassEffect::Initialize() -{ - m_customBlurEffect = winrt::make(m_deviceContext.get()); - m_initialized = true; - return S_OK; -} -void STDMETHODCALLTYPE GlassEffectManager::CGlassEffect::SetGlassRenderingParameters( - const D2D1_COLOR_F& color, - float glassOpacity, - float blurAmount, - float colorizationAfterglowBalanceVal, - float colorizationBlurBalanceVal, - float colorizationColorBalanceVal, - Type type -) -{ - m_color = color; - m_glassOpacity = glassOpacity; - m_blurAmount = blurAmount; - m_colorizationAfterglowBalanceVal = colorizationAfterglowBalanceVal; - m_colorizationBlurBalanceVal = colorizationBlurBalanceVal; - m_colorizationColorBalanceVal = colorizationColorBalanceVal; - m_type = type; -} -void STDMETHODCALLTYPE GlassEffectManager::CGlassEffect::SetSize(const D2D1_SIZE_F& size) -{ - if (memcmp(&m_glassSize, &size, sizeof(D2D1_SIZE_F)) != 0) - { - if ( - auto actualGlassSize{ m_blurBuffer ? m_blurBuffer->GetSize() : m_glassSize }; - !( - m_blurBuffer && - actualGlassSize.width >= size.width && - actualGlassSize.height >= size.height && - ( - actualGlassSize.width / 4.f * 3.f < size.width && - actualGlassSize.height / 4.f * 3.f < size.height - ) - ) - ) - { - m_blurBuffer = nullptr; - } - m_glassSize = size; - } -} -HRESULT STDMETHODCALLTYPE GlassEffectManager::CGlassEffect::Invalidate( - ID2D1Bitmap1* backdropBitmap, - const D2D1_POINT_2F& glassDesktopPosition, - const D2D1_RECT_F& desktopRedrawRect, - bool normalDesktopRender -) -{ - m_backdropPixelFormat = backdropBitmap->GetPixelFormat(); - if (!m_initialized) - { - RETURN_IF_FAILED(Initialize()); - } - - if (normalDesktopRender) - { - if (m_blurBuffer) - { - auto blurBufferPixelFormat{ m_blurBuffer->GetPixelFormat() }; - m_blurBuffer = memcmp(&m_backdropPixelFormat, &blurBufferPixelFormat, sizeof(D2D1_PIXEL_FORMAT)) != 0 ? nullptr : m_blurBuffer; - } - - bool bufferRecreated{ false }; - if (!m_blurBuffer) - { - RETURN_IF_FAILED( - m_deviceContext->CreateBitmap( - D2D1::SizeU( - dwmcore::PixelAlign(m_glassSize.width), - dwmcore::PixelAlign(m_glassSize.height) - ), - nullptr, - 0, - D2D1::BitmapProperties1( - D2D1_BITMAP_OPTIONS_NONE, - m_backdropPixelFormat - ), - m_blurBuffer.put() - ) - ); - m_customBlurEffect->Reset(); - bufferRecreated = true; - - /*OutputDebugStringW( - std::format( - L"blur buffer recreated: [{} x {}]\n", - m_glassSize.width, - m_glassSize.height - ).c_str() - );*/ - } - - D2D1_POINT_2U dstPoint - { - dwmcore::PixelAlign(!bufferRecreated ? desktopRedrawRect.left - glassDesktopPosition.x : glassDesktopPosition.x > 0.f ? 0.f : -glassDesktopPosition.x), - dwmcore::PixelAlign(!bufferRecreated ? desktopRedrawRect.top - glassDesktopPosition.y : glassDesktopPosition.y > 0.f ? 0.f : -glassDesktopPosition.y) - }; - D2D1_RECT_U copyRect - { - dwmcore::PixelAlign(!bufferRecreated ? desktopRedrawRect.left : max(glassDesktopPosition.x, 0.f)), - dwmcore::PixelAlign(!bufferRecreated ? desktopRedrawRect.top : max(glassDesktopPosition.y, 0.f)), - dwmcore::PixelAlign(!bufferRecreated ? desktopRedrawRect.right : (glassDesktopPosition.x + m_glassSize.width)), - dwmcore::PixelAlign(!bufferRecreated ? desktopRedrawRect.bottom : (glassDesktopPosition.y + m_glassSize.height)) - }; - /*OutputDebugStringW( - std::format( - L"backdrop copied: dst:[{} x {}], copyRect:[{},{},{},{}]\n", - dstPoint.x, - dstPoint.y, - copyRect.left, - copyRect.top, - copyRect.right, - copyRect.bottom - ).c_str() - );*/ - RETURN_IF_FAILED( - m_blurBuffer->CopyFromBitmap( - &dstPoint, - backdropBitmap, - ©Rect - ) - ); - m_desktopSize = backdropBitmap->GetSize(); - m_glassDesktopPosition = glassDesktopPosition; - } - - // prepare drawing parameters - if (m_blurBuffer && m_blurAmount) - { - auto backdropSize{ backdropBitmap->GetSize() }; - auto truncatedWidth{ glassDesktopPosition.x + m_glassSize.width - backdropSize.width }; - auto truncatedHeight{ glassDesktopPosition.y + m_glassSize.height - backdropSize.height }; - D2D1_RECT_F imageBounds - { - normalDesktopRender ? max(0.f - glassDesktopPosition.x, 0.f) : 0.f, - normalDesktopRender ? max(0.f - glassDesktopPosition.y, 0.f) : 0.f, - (truncatedWidth > 0.f && normalDesktopRender) ? max(m_glassSize.width - truncatedWidth, 0.f) : m_glassSize.width, - (truncatedHeight > 0.f && normalDesktopRender) ? max(m_glassSize.height - truncatedHeight, 0.f) : m_glassSize.height - }; - D2D1_RECT_F invalidInputRect - { - normalDesktopRender ? (desktopRedrawRect.left - glassDesktopPosition.x) : 0.f, - normalDesktopRender ? (desktopRedrawRect.top - glassDesktopPosition.y) : 0.f, - normalDesktopRender ? (desktopRedrawRect.left - glassDesktopPosition.x + (desktopRedrawRect.right - desktopRedrawRect.left)) : m_glassSize.width, - normalDesktopRender ? (desktopRedrawRect.top - glassDesktopPosition.y + (desktopRedrawRect.bottom - desktopRedrawRect.top)) : m_glassSize.height - }; - RETURN_IF_FAILED( - m_customBlurEffect->Invalidate( - m_blurBuffer.get(), - invalidInputRect, - imageBounds, - m_blurAmount, - m_colorizationAfterglowBalanceVal, - m_colorizationBlurBalanceVal, - m_colorizationColorBalanceVal, - m_color, - m_type - ) - ); - } - - return S_OK; -} - -HRESULT STDMETHODCALLTYPE GlassEffectManager::CGlassEffect::Render(ID2D1Geometry* geometry, ID2D1SolidColorBrush* brush) -{ - D2D1_RECT_F bounds{}; - RETURN_IF_FAILED(geometry->GetBounds(nullptr, &bounds)); - - m_deviceContext->PushLayer( - D2D1::LayerParameters1( - bounds, - geometry, - D2D1_ANTIALIAS_MODE_ALIASED, - D2D1::IdentityMatrix(), - 1.f, - nullptr, - (m_backdropPixelFormat.alphaMode == D2D1_ALPHA_MODE_IGNORE && m_blurBuffer && m_blurAmount > 0.f ? D2D1_LAYER_OPTIONS1_IGNORE_ALPHA : D2D1_LAYER_OPTIONS1_NONE) | - (m_blurBuffer && m_blurAmount > 0.f ? D2D1_LAYER_OPTIONS1_INITIALIZE_FROM_BACKGROUND : D2D1_LAYER_OPTIONS1_NONE) - ), - nullptr - ); - if (m_blurBuffer && m_blurAmount > 0.f) - { - m_customBlurEffect->Draw(bounds); - } - if (m_glassOpacity) - { - auto opacity{ brush->GetOpacity() }; - brush->SetOpacity(m_glassOpacity); - m_deviceContext->FillGeometry( - geometry, - brush - ); - brush->SetOpacity(opacity); - } - RETURN_IF_FAILED( - ReflectionRenderer::Draw( - m_deviceContext.get(), - m_blurBuffer ? m_glassDesktopPosition : D2D1::Point2F(), - m_desktopSize, - bounds - ) - ); - m_deviceContext->PopLayer(); - - return S_OK; -} - -winrt::com_ptr GlassEffectManager::GetOrCreate(dwmcore::CGeometry* geometry, ID2D1DeviceContext* deviceContext, bool createIfNecessary) -{ - auto it{ g_glassEffectMap.find(geometry) }; - - if (createIfNecessary) - { - if (it == g_glassEffectMap.end()) - { - auto result{ g_glassEffectMap.emplace(geometry, winrt::make(deviceContext)) }; - if (result.second == true) - { - it = result.first; - } - } - } - - return it == g_glassEffectMap.end() ? nullptr : it->second; -} -void GlassEffectManager::Remove(dwmcore::CGeometry* geometry) -{ - auto it{ g_glassEffectMap.find(geometry) }; - - if (it != g_glassEffectMap.end()) - { - g_glassEffectMap.erase(it); - } -} -void GlassEffectManager::Shutdown() -{ - g_glassEffectMap.clear(); -} \ No newline at end of file diff --git a/OpenGlass/GlassEffectManager.hpp b/OpenGlass/GlassEffectManager.hpp deleted file mode 100644 index 8241a0e..0000000 --- a/OpenGlass/GlassEffectManager.hpp +++ /dev/null @@ -1,39 +0,0 @@ -#pragma once -#include "framework.hpp" -#include "cpprt.hpp" -#include "uDwmProjection.hpp" -#include "GlassSharedStructures.hpp" - -namespace OpenGlass::GlassEffectManager -{ - - // [Guid("01AA613C-2376-4B95-8A74-B94CA840D4D1")] - DECLARE_INTERFACE_IID_(IGlassEffect, IUnknown, "01AA613C-2376-4B95-8A74-B94CA840D4D1") - { - virtual void STDMETHODCALLTYPE SetGlassRenderingParameters( - const D2D1_COLOR_F& color, - float glassOpacity, - float blurAmount, - float colorizationAfterglowBalanceVal, - float colorizationBlurBalanceVal, - float colorizationColorBalanceVal, - Type type - ) = 0; - virtual void STDMETHODCALLTYPE SetSize(const D2D1_SIZE_F& size) = 0; - virtual HRESULT STDMETHODCALLTYPE Invalidate( - ID2D1Bitmap1* backdropBitmap, - const D2D1_POINT_2F& glassDesktopPosition, - const D2D1_RECT_F& desktopRedrawRect, - bool normalDesktopRender - ) = 0; - virtual HRESULT STDMETHODCALLTYPE Render(ID2D1Geometry* geometry, ID2D1SolidColorBrush* brush) = 0; - }; - - winrt::com_ptr GetOrCreate( - dwmcore::CGeometry* geometry, - ID2D1DeviceContext* deviceContext = nullptr, - bool createIfNecessary = false - ); - void Remove(dwmcore::CGeometry* geometry); - void Shutdown(); -} \ No newline at end of file diff --git a/OpenGlass/GlassFramework.cpp b/OpenGlass/GlassFramework.cpp index 77554a2..43581e5 100644 --- a/OpenGlass/GlassFramework.cpp +++ b/OpenGlass/GlassFramework.cpp @@ -4,7 +4,7 @@ #include "dwmcoreProjection.hpp" #include "GeometryRecorder.hpp" #include "VisualManager.hpp" -#include "GlassSharedData.hpp" +#include "Shared.hpp" using namespace OpenGlass; @@ -36,6 +36,8 @@ namespace OpenGlass::GlassFramework uDwm::CRenderDataVisual* g_accentRenderDataVisual{ nullptr }; DWORD g_accentState{}; int g_roundRectRadius{}; + + UINT g_dwOverlayTestMode{}; } HRGN WINAPI GlassFramework::MyCreateRoundRectRgn(int x1, int y1, int x2, int y2, int w, int h) @@ -59,18 +61,14 @@ HRESULT STDMETHODCALLTYPE GlassFramework::MyCDrawGeometryInstruction_Create(uDwm { winrt::com_ptr rgnGeometry{ nullptr }; uDwm::ResourceHelper::CreateGeometryFromHRGN(region, rgnGeometry.put()); - winrt::com_ptr solidBrush{ nullptr }; - RETURN_IF_FAILED( - uDwm::CDesktopManager::s_pDesktopManagerInstance->GetCompositor()->CreateSolidColorLegacyMilBrushProxy( - solidBrush.put() - ) - ); - auto color{ g_capturedWindow->GetTitlebarColorizationParameters()->getArgbcolor() }; - color.a *= 0.99f; - if (GlassSharedData::g_type == Type::Aero) - color.r = g_capturedWindow->TreatAsActiveWindow(); - RETURN_IF_FAILED(solidBrush->Update(1.0, color)); - return g_CDrawGeometryInstruction_Create_Org(solidBrush.get(), rgnGeometry.get(), instruction); + + auto color = + Shared::g_forceAccentColorization ? + dwmcore::Convert_D2D1_COLOR_F_sRGB_To_D2D1_COLOR_F_scRGB(g_capturedWindow->TreatAsActiveWindow() ? Shared::g_accentColor : Shared::g_accentColorInactive) : + g_capturedWindow->GetTitlebarColorizationParameters()->getArgbcolor(); + color.a = g_capturedWindow->TreatAsActiveWindow() ? 0.5f : 0.0f; + RETURN_IF_FAILED(reinterpret_cast(brush)->Update(1.0, color)); + return g_CDrawGeometryInstruction_Create_Org(brush, rgnGeometry.get(), instruction); } } @@ -81,11 +79,11 @@ HRESULT STDMETHODCALLTYPE GlassFramework::MyCDrawGeometryInstruction_Create(uDwm // and make sure the borders are splitted to improve performance HRESULT STDMETHODCALLTYPE GlassFramework::MyCTopLevelWindow_UpdateNCAreaBackground(uDwm::CTopLevelWindow* This) { - if (!GlassSharedData::IsBackdropAllowed()) + if (!Shared::IsBackdropAllowed()) { return g_CTopLevelWindow_UpdateNCAreaBackground_Org(This); } - auto data{ This->GetData() }; + auto data = This->GetData(); if (!data) { return g_CTopLevelWindow_UpdateNCAreaBackground_Org(This); @@ -93,6 +91,15 @@ HRESULT STDMETHODCALLTYPE GlassFramework::MyCTopLevelWindow_UpdateNCAreaBackgrou HRESULT hr{ S_OK }; + if (auto brush = This->GetClientBlurVisualBrush(); brush) + { + auto color = + Shared::g_forceAccentColorization ? + dwmcore::Convert_D2D1_COLOR_F_sRGB_To_D2D1_COLOR_F_scRGB(This->TreatAsActiveWindow() ? Shared::g_accentColor : Shared::g_accentColorInactive) : + This->GetTitlebarColorizationParameters()->getArgbcolor(); + color.a = This->TreatAsActiveWindow() ? 0.5f : 0.0f; + LOG_IF_FAILED(brush->Update(1.0, color)); + } if (This->HasNonClientBackground()) { GeometryRecorder::BeginCapture(); @@ -113,13 +120,13 @@ HRESULT STDMETHODCALLTYPE GlassFramework::MyCTopLevelWindow_UpdateNCAreaBackgrou if (SUCCEEDED(hr)) { - auto legacyVisualOverride{ VisualManager::GetOrCreateLegacyVisualOverrider(This, true) }; + auto legacyVisualOverride = VisualManager::GetOrCreateLegacyVisualOverrider(This, true); // the titlebar region has been updated // let's update our backdrop region if (GeometryRecorder::GetGeometryCount() && legacyVisualOverride) { - auto captionGeometry{ This->GetCaptionGeometry() }; - auto borderGeometry{ This->GetBorderGeometry() }; + auto captionGeometry = This->GetCaptionGeometry(); + auto borderGeometry = This->GetBorderGeometry(); HRGN captionRegion{ GeometryRecorder::GetRegionFromGeometry(captionGeometry) }; HRGN borderRegion{ GeometryRecorder::GetRegionFromGeometry(borderGeometry) }; @@ -142,11 +149,11 @@ HRESULT STDMETHODCALLTYPE GlassFramework::MyCTopLevelWindow_UpdateNCAreaBackgrou // make the visual of DwmEnableBlurBehind visible HRESULT STDMETHODCALLTYPE GlassFramework::MyCTopLevelWindow_UpdateClientBlur(uDwm::CTopLevelWindow* This) { - if (!GlassSharedData::IsBackdropAllowed()) + if (!Shared::IsBackdropAllowed()) { return g_CTopLevelWindow_UpdateClientBlur_Org(This); } - auto data{ This->GetData() }; + auto data = This->GetData(); if (!data) { return g_CTopLevelWindow_UpdateClientBlur_Org(This); @@ -164,17 +171,17 @@ HRESULT STDMETHODCALLTYPE GlassFramework::MyCTopLevelWindow_UpdateClientBlur(uDw // convert accent_state=3 or 4 into 2 and replace its solid rectangle instruction into draw glass instruction HRESULT STDMETHODCALLTYPE GlassFramework::MyCAccent_UpdateAccentPolicy(uDwm::CAccent* This, LPCRECT lprc, uDwm::ACCENT_POLICY* policy, uDwm::CBaseGeometryProxy* geometry) { - if (!GlassSharedData::IsBackdropAllowed()) + if (!Shared::IsBackdropAllowed()) { return g_CAccent_UpdateAccentPolicy_Org(This, lprc, policy, geometry); } - if (!GlassSharedData::g_overrideAccent) + if (!Shared::g_overrideAccent) { return g_CAccent_UpdateAccentPolicy_Org(This, lprc, policy, geometry); } HRESULT hr{ S_OK }; - auto accentPolicy{ *policy }; + auto accentPolicy = *policy; if (accentPolicy.AccentState == 3 || accentPolicy.AccentState == 4) { accentPolicy.AccentState = 2; @@ -190,11 +197,11 @@ HRESULT STDMETHODCALLTYPE GlassFramework::MyCAccent_UpdateAccentPolicy(uDwm::CAc HRESULT STDMETHODCALLTYPE GlassFramework::MyCAccent__UpdateSolidFill(uDwm::CAccent* This, uDwm::CRenderDataVisual* visual, DWORD color, const D2D1_RECT_F* lprc, float opacity) { - if (!GlassSharedData::IsBackdropAllowed()) + if (!Shared::IsBackdropAllowed()) { return g_CAccent__UpdateSolidFill_Org(This, visual, color, lprc, opacity); } - if (!GlassSharedData::g_overrideAccent) + if (!Shared::g_overrideAccent) { return g_CAccent__UpdateSolidFill_Org(This, visual, color, lprc, opacity); } @@ -204,7 +211,7 @@ HRESULT STDMETHODCALLTYPE GlassFramework::MyCAccent__UpdateSolidFill(uDwm::CAcce } uDwm::CWindowData* data{ nullptr }; { - auto lock{ wil::EnterCriticalSection(uDwm::CDesktopManager::s_csDwmInstance) }; + auto lock = wil::EnterCriticalSection(uDwm::CDesktopManager::s_csDwmInstance); if (FAILED(uDwm::CDesktopManager::s_pDesktopManagerInstance->GetWindowList()->GetSyncedWindowDataByHwnd(This->GetHwnd(), &data)) || !data) { return g_CAccent__UpdateSolidFill_Org(This, visual, color, lprc, opacity); @@ -226,11 +233,11 @@ HRESULT STDMETHODCALLTYPE GlassFramework::MyCAccent__UpdateSolidFill(uDwm::CAcce HRESULT STDMETHODCALLTYPE GlassFramework::MyCRenderDataVisual_AddInstruction(uDwm::CRenderDataVisual* This, uDwm::CRenderDataInstruction* instruction) { - if (!GlassSharedData::IsBackdropAllowed()) + if (!Shared::IsBackdropAllowed()) { return g_CRenderDataVisual_AddInstruction_Org(This, instruction); } - if (!GlassSharedData::g_overrideAccent) + if (!Shared::g_overrideAccent) { return g_CRenderDataVisual_AddInstruction_Org(This, instruction); } @@ -239,17 +246,16 @@ HRESULT STDMETHODCALLTYPE GlassFramework::MyCRenderDataVisual_AddInstruction(uDw return g_CRenderDataVisual_AddInstruction_Org(This, instruction); } - auto drawRectangleInstruction{ reinterpret_cast(instruction) }; - auto rectangle{ drawRectangleInstruction->GetRectangle() }; - auto color{ drawRectangleInstruction->GetColor() }; + auto drawRectangleInstruction = reinterpret_cast(instruction); + auto rectangle = drawRectangleInstruction->GetRectangle(); + auto color = drawRectangleInstruction->GetColor(); if (g_accentState == 4 && color.a == 0.f && color.r == 0.f && color.g == 0.f && color.b == 0.f) { return g_CRenderDataVisual_AddInstruction_Org(This, instruction); } - color.a = 0.99f; - if (GlassSharedData::g_type == Type::Aero) - color.r = 1.0f; + color.a = 0.5f; + winrt::com_ptr rgnGeometry{ nullptr }; uDwm::ResourceHelper::CreateGeometryFromHRGN(wil::unique_hrgn{ CreateRectRgn(static_cast(rectangle.left), static_cast(rectangle.top), static_cast(rectangle.right), static_cast(rectangle.bottom)) }.get(), rgnGeometry.put()); winrt::com_ptr solidBrush{ nullptr }; @@ -278,12 +284,12 @@ enum class BackgroundType */ DWORD STDMETHODCALLTYPE GlassFramework::MyCTopLevelWindow_CalculateBackgroundType(uDwm::CTopLevelWindow* This) { - if (!GlassSharedData::IsBackdropAllowed()) + if (!Shared::IsBackdropAllowed()) { return g_CTopLevelWindow_CalculateBackgroundType_Org(This); } - auto result{ g_CTopLevelWindow_CalculateBackgroundType_Org(This) }; + auto result = g_CTopLevelWindow_CalculateBackgroundType_Org(This); if (result == 4 || result == 3 || result == 2) { result = 0; @@ -295,18 +301,18 @@ DWORD STDMETHODCALLTYPE GlassFramework::MyCTopLevelWindow_CalculateBackgroundTyp // trick dwm into thinking the system backdrop is not exist HRESULT STDMETHODCALLTYPE GlassFramework::MyCTopLevelWindow_UpdateSystemBackdropVisual(uDwm::CTopLevelWindow* This) { - if (!GlassSharedData::IsBackdropAllowed()) + if (!Shared::IsBackdropAllowed()) { return g_CTopLevelWindow_UpdateSystemBackdropVisual_Org(This); } - auto data{ This->GetData() }; + auto data = This->GetData(); if (!data) { return g_CTopLevelWindow_UpdateSystemBackdropVisual_Org(This); } HRESULT hr{ S_OK }; - auto oldSystemBackdropType{ *reinterpret_cast(reinterpret_cast(data) + 204) }; + auto oldSystemBackdropType = *reinterpret_cast(reinterpret_cast(data) + 204); // trick dwm into thinking the window does not enable system backdrop *reinterpret_cast(reinterpret_cast(data) + 204) = 0; hr = g_CTopLevelWindow_UpdateSystemBackdropVisual_Org(This); @@ -326,28 +332,27 @@ void GlassFramework::UpdateConfiguration(ConfigurationFramework::UpdateType type { if (type & ConfigurationFramework::UpdateType::Framework) { - GlassSharedData::g_disableOnBattery = static_cast(ConfigurationFramework::DwmGetDwordFromHKCUAndHKLM(L"DisableGlassOnBattery", TRUE)); - GlassSharedData::g_batteryMode = Utils::IsBatterySaverEnabled(); + Shared::g_disableOnBattery = static_cast(ConfigurationFramework::DwmGetDwordFromHKCUAndHKLM(L"DisableGlassOnBattery", TRUE)); + Shared::g_batteryMode = Utils::IsBatterySaverEnabled(); } if (type & ConfigurationFramework::UpdateType::Backdrop) { - GlassSharedData::g_transparencyEnabled = Utils::IsTransparencyEnabled(ConfigurationFramework::GetPersonalizeKey()); - GlassSharedData::g_overrideAccent = static_cast(ConfigurationFramework::DwmGetDwordFromHKCUAndHKLM(L"GlassOverrideAccent")); + Shared::g_transparencyEnabled = Utils::IsTransparencyEnabled(ConfigurationFramework::GetPersonalizeKey()); + Shared::g_enableGeometryMerging = static_cast(ConfigurationFramework::DwmGetDwordFromHKCUAndHKLM(L"EnableGeometryMerging")); + Shared::g_overrideAccent = static_cast(ConfigurationFramework::DwmGetDwordFromHKCUAndHKLM(L"GlassOverrideAccent")); g_roundRectRadius = static_cast(ConfigurationFramework::DwmGetDwordFromHKCUAndHKLM(L"RoundRectRadius")); - } - - //Seperate keys for now until a way to readd the code that handles setting the actual values in registry is found - GlassSharedData::g_ColorizationAfterglowBalance = ((float)ConfigurationFramework::DwmGetDwordFromHKCUAndHKLM(L"OG_ColorizationAfterglowBalance",43) / 100); - GlassSharedData::g_ColorizationBlurBalance = ((float)ConfigurationFramework::DwmGetDwordFromHKCUAndHKLM(L"OG_ColorizationBlurBalance",49) / 100); - GlassSharedData::g_ColorizationColorBalance = ((float)ConfigurationFramework::DwmGetDwordFromHKCUAndHKLM(L"OG_ColorizationColorBalance",8) / 100); - //Get the colorizationColor from registry directly for aero glass type, a dwm function could be used, however mods or programs such as AWM hook into this and can - //cause issues, so the colour is taken directly from registry, which is fine for aero glass (actually better) since inactive and active have the same colour - DWORD hexColour = ConfigurationFramework::DwmGetDwordFromHKCUAndHKLM(L"ColorizationColor", 0xfffcb874); - GlassSharedData::g_ColorizationColor = Utils::FromArgb(hexColour); + if (Shared::g_forceAccentColorization = static_cast(ConfigurationFramework::DwmGetDwordFromHKCUAndHKLM(L"ForceAccentColorization")); Shared::g_forceAccentColorization) + { + auto accentColor = ConfigurationFramework::DwmGetDwordFromHKCUAndHKLM(L"AccentColor"); + auto accentColorInactive = ConfigurationFramework::DwmGetDwordFromHKCUAndHKLM(L"AccentColorInactive", accentColor); + Shared::g_accentColor = Utils::FromAbgr(accentColor); + Shared::g_accentColorInactive = Utils::FromAbgr(accentColorInactive); + } + } - auto lock{ wil::EnterCriticalSection(uDwm::CDesktopManager::s_csDwmInstance) }; - if (!GlassSharedData::IsBackdropAllowed()) + auto lock = wil::EnterCriticalSection(uDwm::CDesktopManager::s_csDwmInstance); + if (!Shared::IsBackdropAllowed()) { VisualManager::ShutdownLegacyVisualOverrider(); } @@ -355,13 +360,13 @@ void GlassFramework::UpdateConfiguration(ConfigurationFramework::UpdateType type { ULONG_PTR desktopID{ 0 }; Utils::GetDesktopID(1, &desktopID); - auto windowList{ uDwm::CDesktopManager::s_pDesktopManagerInstance->GetWindowList()->GetWindowListForDesktop(desktopID) }; - for (auto i{ windowList->Blink }; i != windowList; i = i->Blink) + auto windowList = uDwm::CDesktopManager::s_pDesktopManagerInstance->GetWindowList()->GetWindowListForDesktop(desktopID); + for (auto i = windowList->Blink; i != windowList; i = i->Blink) { - auto data{ reinterpret_cast(i) }; - auto hwnd{ data->GetHwnd() }; + auto data = reinterpret_cast(i); + auto hwnd = data->GetHwnd(); if (!hwnd || !IsWindow(hwnd)) { continue; } - auto window{ data->GetWindow() }; + auto window = data->GetWindow(); if (!window) { continue; } VisualManager::RedrawTopLevelWindow(window); @@ -372,6 +377,9 @@ void GlassFramework::UpdateConfiguration(ConfigurationFramework::UpdateType type HRESULT GlassFramework::Startup() { + g_dwOverlayTestMode = *dwmcore::CCommonRegistryData::m_dwOverlayTestMode; + *dwmcore::CCommonRegistryData::m_dwOverlayTestMode = 0x5; + uDwm::GetAddressFromSymbolMap("CDrawGeometryInstruction::Create", g_CDrawGeometryInstruction_Create_Org); uDwm::GetAddressFromSymbolMap("CTopLevelWindow::UpdateNCAreaBackground", g_CTopLevelWindow_UpdateNCAreaBackground_Org); uDwm::GetAddressFromSymbolMap("CTopLevelWindow::UpdateClientBlur", g_CTopLevelWindow_UpdateClientBlur_Org); @@ -384,7 +392,6 @@ HRESULT GlassFramework::Startup() g_CreateRoundRectRgn_Org = reinterpret_cast(HookHelper::WriteIAT(uDwm::g_moduleHandle, "gdi32.dll", "CreateRoundRectRgn", MyCreateRoundRectRgn)); - return HookHelper::Detours::Write([]() { HookHelper::Detours::Attach(&g_CDrawGeometryInstruction_Create_Org, MyCDrawGeometryInstruction_Create); @@ -407,6 +414,8 @@ HRESULT GlassFramework::Startup() void GlassFramework::Shutdown() { + *dwmcore::CCommonRegistryData::m_dwOverlayTestMode = g_dwOverlayTestMode; + HookHelper::Detours::Write([]() { HookHelper::Detours::Detach(&g_CDrawGeometryInstruction_Create_Org, MyCDrawGeometryInstruction_Create); @@ -435,13 +444,13 @@ void GlassFramework::Shutdown() VisualManager::ShutdownLegacyVisualOverrider(); ULONG_PTR desktopID{ 0 }; Utils::GetDesktopID(1, &desktopID); - auto windowList{ uDwm::CDesktopManager::s_pDesktopManagerInstance->GetWindowList()->GetWindowListForDesktop(desktopID) }; - for (auto i{ windowList->Blink }; i != windowList; i = i->Blink) + auto windowList = uDwm::CDesktopManager::s_pDesktopManagerInstance->GetWindowList()->GetWindowListForDesktop(desktopID); + for (auto i = windowList->Blink; i != windowList; i = i->Blink) { - auto data{ reinterpret_cast(i) }; - auto hwnd{ data->GetHwnd() }; + auto data = reinterpret_cast(i); + auto hwnd = data->GetHwnd(); if (!hwnd || !IsWindow(hwnd)) { continue; } - auto window{ data->GetWindow() }; + auto window = data->GetWindow(); if (!window) { continue; } VisualManager::RedrawTopLevelWindow(window); diff --git a/OpenGlass/GlassRenderer.cpp b/OpenGlass/GlassRenderer.cpp index f75f73f..850de54 100644 --- a/OpenGlass/GlassRenderer.cpp +++ b/OpenGlass/GlassRenderer.cpp @@ -2,11 +2,10 @@ #include "HookHelper.hpp" #include "uDwmProjection.hpp" #include "dwmcoreProjection.hpp" +#include "Shared.hpp" #include "GlassRenderer.hpp" -#include "GlassEffectManager.hpp" -#include "GlassSharedData.hpp" -#include "ReflectionRenderer.hpp" -#include "GlassSharedStructures.hpp" +#include "GlassEffect.hpp" +#include "ReflectionEffect.hpp" using namespace OpenGlass; @@ -46,13 +45,13 @@ namespace OpenGlass::GlassRenderer ID2D1Brush* brush, ID2D1Brush* opacityBrush ); - void STDMETHODCALLTYPE MyCGeometry_Destructor(dwmcore::CGeometry* This); HRESULT STDMETHODCALLTYPE MyCDirtyRegion__Add( dwmcore::CDirtyRegion* This, dwmcore::CVisual* visual, bool unknown, const D2D1_RECT_F& lprc ); + void STDMETHODCALLTYPE MyCGeometry_Destructor(dwmcore::CGeometry* This); decltype(&MyCRenderData_TryDrawCommandAsDrawList) g_CRenderData_TryDrawCommandAsDrawList_Org{ nullptr }; decltype(&MyCRenderData_DrawSolidColorRectangle) g_CRenderData_DrawSolidColorRectangle_Org{ nullptr }; @@ -62,20 +61,14 @@ namespace OpenGlass::GlassRenderer decltype(&MyCDrawingContext_DrawGeometry)* g_CDrawingContext_DrawGeometry_Org_Address{ nullptr }; decltype(&MyID2D1DeviceContext_FillGeometry) g_ID2D1DeviceContext_FillGeometry_Org{ nullptr }; decltype(&MyID2D1DeviceContext_FillGeometry)* g_ID2D1DeviceContext_FillGeometry_Org_Address{ nullptr }; - decltype(&MyCGeometry_Destructor) g_CGeometry_Destructor_Org{ nullptr }; decltype(&MyCDirtyRegion__Add) g_CDirtyRegion__Add_Org{ nullptr }; + decltype(&MyCGeometry_Destructor) g_CGeometry_Destructor_Org{ nullptr }; PVOID* g_CSolidColorLegacyMilBrush_vftable{ nullptr }; std::optional g_drawColor{}; - GlassEffectManager::IGlassEffect* g_glassEffectNoRef{ nullptr }; - dwmcore::IDrawingContext* g_drawingContextNoRef{ nullptr }; + IGlassEffect* g_glassEffectNoRef{ nullptr }; ID2D1Device* g_deviceNoRef{ nullptr }; - - float g_blurAmount{ 9.f }; - float g_glassOpacity{ 0.63f }; - // exclusively used by aero backdrop - float g_colorBalance{ 0.f }; - float g_afterglowBalance{ 0.43f }; + dwmcore::IDrawingContext* g_drawingContextNoRef{ nullptr }; } HRESULT STDMETHODCALLTYPE GlassRenderer::MyCRenderData_TryDrawCommandAsDrawList( @@ -108,7 +101,7 @@ HRESULT STDMETHODCALLTYPE GlassRenderer::MyCRenderData_DrawSolidColorRectangle( { if ( color.a != 1.f && - GlassSharedData::IsBackdropAllowed() + Shared::IsBackdropAllowed() ) { g_drawColor = color; @@ -160,7 +153,6 @@ HRESULT STDMETHODCALLTYPE GlassRenderer::MyCDrawingContext_DrawGeometry( dwmcore::CGeometry* geometry ) { - HRESULT hr{ g_CDrawingContext_DrawGeometry_Org(This, brush, geometry) }; if ( !brush || !geometry || @@ -168,25 +160,13 @@ HRESULT STDMETHODCALLTYPE GlassRenderer::MyCDrawingContext_DrawGeometry( !g_drawColor.has_value() ) { - return hr; + return g_CDrawingContext_DrawGeometry_Org(This, brush, geometry); } - //HWND hwnd = reinterpret_cast(This->GetDrawingContext()->GetD2DContextOwner())->GetCurrentVisual()->GetTopLevelWindow(); - //uDwm::CWindowData* data{ nullptr }; - //{ - // auto lock{ wil::EnterCriticalSection(uDwm::CDesktopManager::s_csDwmInstance) }; - // uDwm::CDesktopManager::s_pDesktopManagerInstance->GetWindowList()->GetSyncedWindowDataByHwnd(hwnd, &data); - //} - //if (!data) return hr; - bool bactive = g_drawColor.value().r == 1.0f; //HACK!!!: check if window is active using the data sent through the red channel - //bool bactive = data->GetWindow()->TreatAsActiveWindow(); - //OutputDebugStringW(std::format(L"r {}", g_drawColor.value().r).c_str()); - //g_drawColor.value() = D2D1_COLOR_F{ 116.0f / 255.0f, 184.0f / 255.0f, 252.0f / 255.0f, g_drawColor.value().a}; - //g_drawColor.value() = D2D1_COLOR_F{ GlassSharedData::g_ColorizationColor.r, GlassSharedData::g_ColorizationColor.g, GlassSharedData::g_ColorizationColor.b, g_drawColor.value().a}; - auto cleanUp{ wil::scope_exit([]{ g_drawColor = std::nullopt; })}; - - D2D1_COLOR_F color{ GlassSharedData::g_ColorizationColor.r, GlassSharedData::g_ColorizationColor.g, GlassSharedData::g_ColorizationColor.b, g_drawColor.value().a }; - if (GlassSharedData::g_type == Type::Blur) - color = dwmcore::Convert_D2D1_COLOR_F_scRGB_To_D2D1_COLOR_F_sRGB(g_drawColor.value()); + + auto cleanUp = wil::scope_exit([] { g_drawColor = std::nullopt; }); + auto color = dwmcore::Convert_D2D1_COLOR_F_scRGB_To_D2D1_COLOR_F_sRGB(g_drawColor.value()); + + // shape is nullptr or empty dwmcore::CShapePtr geometryShape{}; if ( FAILED(geometry->GetShapeData(nullptr, &geometryShape)) || @@ -194,50 +174,35 @@ HRESULT STDMETHODCALLTYPE GlassRenderer::MyCDrawingContext_DrawGeometry( geometryShape->IsEmpty() ) { - return hr; + return g_CDrawingContext_DrawGeometry_Org(This, brush, geometry); } - bool normalDesktopRender{ This->GetDrawingContext()->IsNormalDesktopRender() }; - D2D1_RECT_F boundRect{}; - RETURN_IF_FAILED(geometryShape->GetTightBounds(&boundRect, nullptr)); - D2D1_RECT_F worldSpaceClippedBounds{}; - This->GetDrawingContext()->CalcWorldSpaceClippedBounds(boundRect, &worldSpaceClippedBounds); - D2D1_RECT_F localSpaceClippedBounds{}; - This->GetDrawingContext()->CalcLocalSpaceClippedBounds(boundRect, &localSpaceClippedBounds); - - if ( - g_drawColor.value().a == 1.f || - ( - normalDesktopRender && - ( - worldSpaceClippedBounds.right <= worldSpaceClippedBounds.left || - worldSpaceClippedBounds.bottom <= worldSpaceClippedBounds.top || - localSpaceClippedBounds.right <= localSpaceClippedBounds.left || - localSpaceClippedBounds.bottom <= localSpaceClippedBounds.top - ) - ) - ) + // not our job + if (color.a == 1.f) { return This->GetDrawingContext()->FillShapeWithColor(geometryShape.ptr, &color); } - auto deviceContext{ This->GetDrawingContext()->GetD2DContext()->GetDeviceContext() }; winrt::com_ptr device{ nullptr }; - deviceContext->GetDevice(device.put()); + auto context = This->GetDrawingContext()->GetD2DContext()->GetDeviceContext(); + context->GetDevice(device.put()); // device lost if (g_deviceNoRef != device.get()) { g_deviceNoRef = device.get(); - ReflectionRenderer::g_reflectionBitmap = nullptr; - GlassEffectManager::Shutdown(); + ReflectionEffect::Reset(); + GlassEffectFactory::Shutdown(); } + // allocate glass effect - winrt::com_ptr glassEffect{ GlassEffectManager::GetOrCreate(geometry, deviceContext, true) }; + auto glassEffect = GlassEffectFactory::GetOrCreate(geometry, true); if (!glassEffect) { return This->GetDrawingContext()->FillShapeWithColor(geometryShape.ptr, &color); } - // prepare ID2D1DeviceContext::FillGeometry + + // prepare and hook ID2D1DeviceContext::FillGeometry + RETURN_IF_FAILED(This->GetDrawingContext()->FlushD2D()); g_glassEffectNoRef = glassEffect.get(); g_drawingContextNoRef = This; if (!g_ID2D1DeviceContext_FillGeometry_Org) @@ -246,45 +211,33 @@ HRESULT STDMETHODCALLTYPE GlassRenderer::MyCDrawingContext_DrawGeometry( g_ID2D1DeviceContext_FillGeometry_Org = HookHelper::WritePointer(g_ID2D1DeviceContext_FillGeometry_Org_Address, MyID2D1DeviceContext_FillGeometry); } - // hahaha, i can't belive i can actually convert ID2D1Image into ID2D1Bitmap1! - winrt::com_ptr backdropImage{}; - This->GetDrawingContext()->GetD2DContext()->GetDeviceContext()->GetTarget(backdropImage.put()); - winrt::com_ptr backdropBitmap{ backdropImage.as() }; - //TODO: ADD PROPER TYPE CHECKED CAST - //bool bactive = false; - //if (This->GetDrawingContext()->GetCurrentVisual()) - //bactive = true; - - RETURN_IF_FAILED(This->GetDrawingContext()->FlushD2D()); - - //bool bactive = true; + // hack! but a bit better + auto active = color.a == 0.5f; + // the reason why i keep it that is the hacky way is much faster and the normal way is less stable + // normally, you can get the HWND from CDrawingContext::PreSubgraph like this + /* + HRESULT STDMETHODCALLTYPE GlassRenderer::MyCDrawingContext_PreSubgraph( + dwmcore::CDrawingContext* This, + dwmcore::CVisualTree* visualTree, + bool* conditionalBreak + ) + { + HWND hwnd{ reinterpret_cast(This->GetD2DContextOwner())->GetCurrentVisual()->GetHwnd() }; + if (hwnd && g_current != hwnd) { g_current = hwnd; g_data = nullptr; } + HRESULT hr{ g_CDrawingContext_PreSubgraph_Org(This, visualTree, conditionalBreak) }; - dwmcore::CMILMatrix matrix{}; - D2D1_RECT_F shapeWorldBounds{}; - RETURN_IF_FAILED(This->GetDrawingContext()->GetWorldTransform(&matrix)); - RETURN_IF_FAILED(geometryShape->GetTightBounds(&shapeWorldBounds, &matrix)); + return hr; + } + */ glassEffect->SetGlassRenderingParameters( - color, - ((GlassSharedData::g_type == Type::Aero) ? 0.0f : g_glassOpacity), - g_blurAmount, - GlassSharedData::g_ColorizationAfterglowBalance, // stays the same - bactive ? GlassSharedData::g_ColorizationBlurBalance : 0.4f * GlassSharedData::g_ColorizationBlurBalance + 0.6f, // y = 0.4x + 60 - bactive ? GlassSharedData::g_ColorizationColorBalance : 0.4f * GlassSharedData::g_ColorizationColorBalance, //y = 0.4x - GlassSharedData::g_type - ); - glassEffect->SetSize( - D2D1::SizeF( - boundRect.right - boundRect.left, - boundRect.bottom - boundRect.top - ) - ); - RETURN_IF_FAILED( - glassEffect->Invalidate( - backdropBitmap.get(), - D2D1::Point2F(shapeWorldBounds.left, shapeWorldBounds.top), - worldSpaceClippedBounds, - normalDesktopRender - ) + (Shared::g_type == Shared::Type::Aero) ? color : Shared::g_color, + Shared::g_afterglow, + Shared::g_glassOpacity, + Shared::g_blurAmount, + active ? Shared::g_colorBalance : (0.4f * Shared::g_colorBalance), // y = 0.4x + Shared::g_afterglowBalance, // stays the same + active ? Shared::g_glassOpacity : (0.4f * Shared::g_glassOpacity + 0.6f), // y = 0.4x + 60 + Shared::g_type ); return This->GetDrawingContext()->FillShapeWithColor(geometryShape.ptr, &color); @@ -304,22 +257,37 @@ void STDMETHODCALLTYPE GlassRenderer::MyID2D1DeviceContext_FillGeometry( g_drawingContextNoRef ) { - auto glassEffect{ g_glassEffectNoRef }; + D2D1_RECT_F clipWorldBounds{}; + D2D1_ANTIALIAS_MODE mode{}; + g_drawingContextNoRef->GetDrawingContext()->GetD2DContext()->GetClip( + g_drawingContextNoRef->GetDrawingContext()->GetD2DContextOwner(), + &clipWorldBounds, + &mode + ); + + auto hr = g_glassEffectNoRef->Render(This, geometry, clipWorldBounds); + if (FAILED(hr)) + { + LOG_HR(hr); + g_ID2D1DeviceContext_FillGeometry_Org(This, geometry, brush, opacityBrush); + } + LOG_IF_FAILED( + ReflectionEffect::Render( + This, + geometry, + Shared::g_reflectionIntensity, + Shared::g_reflectionParallaxIntensity + ) + ); + g_drawingContextNoRef = nullptr; g_glassEffectNoRef = nullptr; - LOG_IF_FAILED(glassEffect->Render(geometry, solidColorBrush.get())); return; } return g_ID2D1DeviceContext_FillGeometry_Org(This, geometry, brush, opacityBrush); } -void STDMETHODCALLTYPE GlassRenderer::MyCGeometry_Destructor(dwmcore::CGeometry* This) -{ - GlassEffectManager::Remove(This); - return g_CGeometry_Destructor_Org(This); -} - // this is not the best way to mitigate artifacts, it needs to be reworked in the future! HRESULT STDMETHODCALLTYPE GlassRenderer::MyCDirtyRegion__Add( dwmcore::CDirtyRegion* This, @@ -328,7 +296,9 @@ HRESULT STDMETHODCALLTYPE GlassRenderer::MyCDirtyRegion__Add( const D2D1_RECT_F& lprc ) { - float extendAmount{ g_blurAmount * 3.f + 0.5f }; + // at high blur radius, there is no need to extend that much, + // it will only cause severe flickering + float extendAmount{ min(Shared::g_blurAmount * 3.f + 0.5f, 15.5f) }; D2D1_RECT_F extendedDirtyRectangle { lprc.left - extendAmount, @@ -345,33 +315,64 @@ HRESULT STDMETHODCALLTYPE GlassRenderer::MyCDirtyRegion__Add( ); } +void STDMETHODCALLTYPE GlassRenderer::MyCGeometry_Destructor(dwmcore::CGeometry* This) +{ + GlassEffectFactory::Remove(This); + return g_CGeometry_Destructor_Org(This); +} + void GlassRenderer::UpdateConfiguration(ConfigurationFramework::UpdateType type) { if (type & ConfigurationFramework::UpdateType::Backdrop) { - g_blurAmount = std::clamp(static_cast(ConfigurationFramework::DwmGetDwordFromHKCUAndHKLM(L"BlurDeviation", 30)) / 10.f * 3.f, 0.f, 250.f); - g_glassOpacity = std::clamp(static_cast(ConfigurationFramework::DwmGetDwordFromHKCUAndHKLM(L"GlassOpacity", 63)) / 100.f, 0.f, 1.f); + Shared::g_blurAmount = std::clamp(static_cast(ConfigurationFramework::DwmGetDwordFromHKCUAndHKLM(L"BlurDeviation", 30)) / 10.f * 3.f, 0.f, 250.f); + Shared::g_glassOpacity = std::clamp(static_cast(ConfigurationFramework::DwmGetDwordFromHKCUAndHKLM(L"GlassOpacity", 63)) / 100.f, 0.f, 1.f); + WCHAR reflectionTexturePath[MAX_PATH + 1]{}; ConfigurationFramework::DwmGetStringFromHKCUAndHKLM(L"CustomThemeReflection", reflectionTexturePath); - ReflectionRenderer::g_reflectionTexturePath = reflectionTexturePath; - ReflectionRenderer::g_reflectionIntensity = std::clamp(static_cast(ConfigurationFramework::DwmGetDwordFromHKCUAndHKLM(L"ColorizationGlassReflectionIntensity")) / 100.f, 0.f, 1.f); - ReflectionRenderer::g_reflectionParallaxIntensity = std::clamp(static_cast(ConfigurationFramework::DwmGetDwordFromHKCUAndHKLM(L"ColorizationGlassReflectionParallaxIntensity", 10)) / 100.f, 0.f, 1.f); - ReflectionRenderer::g_reflectionBitmap = nullptr; - auto colorBalance{ ConfigurationFramework::DwmTryDwordFromHKCUAndHKLM(L"ColorizationColorBalanceOverride") }; - if (!colorBalance.has_value()) + ReflectionEffect::UpdateTexture(reflectionTexturePath); + Shared::g_reflectionIntensity = std::clamp(static_cast(ConfigurationFramework::DwmGetDwordFromHKCUAndHKLM(L"ColorizationGlassReflectionIntensity")) / 100.f, 0.f, 1.f); + Shared::g_reflectionParallaxIntensity = std::clamp(static_cast(ConfigurationFramework::DwmGetDwordFromHKCUAndHKLM(L"ColorizationGlassReflectionParallaxIntensity", 10)) / 100.f, 0.f, 1.f); + + std::optional result{ std::nullopt }; + + result = ConfigurationFramework::DwmTryDwordFromHKCUAndHKLM(L"ColorizationColorOverride"); + if (!result.has_value()) { - colorBalance = ConfigurationFramework::DwmGetDwordFromHKCUAndHKLM(L"ColorizationColorBalance", 0); + result = ConfigurationFramework::DwmGetDwordFromHKCUAndHKLM(L"ColorizationColor", 0xff74b8fc); } - g_colorBalance = std::clamp(static_cast(colorBalance.value()) / 100.f, 0.f, 1.f); - auto afterglowBalance{ ConfigurationFramework::DwmTryDwordFromHKCUAndHKLM(L"ColorizationAfterglowBalanceOverride") }; - if (!afterglowBalance.has_value()) + Shared::g_color = Utils::FromArgb(result.value()); + + result = ConfigurationFramework::DwmTryDwordFromHKCUAndHKLM(L"ColorizationAfterglowOverride"); + if (!result.has_value()) { - afterglowBalance = ConfigurationFramework::DwmGetDwordFromHKCUAndHKLM(L"ColorizationAfterglowBalance", 43); + result = ConfigurationFramework::DwmGetDwordFromHKCUAndHKLM(L"ColorizationAfterglow", 0xff74b8fc); } - g_afterglowBalance = std::clamp(static_cast(afterglowBalance.value()) / 100.f, 0.f, 1.f); + Shared::g_afterglow = Utils::FromArgb(result.value()); - GlassSharedData::g_type = static_cast(std::clamp(ConfigurationFramework::DwmGetDwordFromHKCUAndHKLM(L"GlassType", 0), 0ul, 4ul)); + result = ConfigurationFramework::DwmTryDwordFromHKCUAndHKLM(L"ColorizationBlurBalanceOverride"); + if (!result.has_value()) + { + result = ConfigurationFramework::DwmGetDwordFromHKCUAndHKLM(L"ColorizationBlurBalance", 49); + } + Shared::g_blurBalance = std::clamp(static_cast(result.value()) / 100.f, 0.f, 1.f); + + result = ConfigurationFramework::DwmTryDwordFromHKCUAndHKLM(L"ColorizationColorBalanceOverride"); + if (!result.has_value()) + { + result = ConfigurationFramework::DwmGetDwordFromHKCUAndHKLM(L"ColorizationColorBalance", 8); + } + Shared::g_colorBalance = std::clamp(static_cast(result.value()) / 100.f, 0.f, 1.f); + + result = ConfigurationFramework::DwmTryDwordFromHKCUAndHKLM(L"ColorizationAfterglowBalanceOverride"); + if (!result.has_value()) + { + result = ConfigurationFramework::DwmGetDwordFromHKCUAndHKLM(L"ColorizationAfterglowBalance", 43); + } + Shared::g_afterglowBalance = std::clamp(static_cast(result.value()) / 100.f, 0.f, 1.f); + + Shared::g_type = static_cast(std::clamp(ConfigurationFramework::DwmGetDwordFromHKCUAndHKLM(L"GlassType", 0), 0ul, 1ul)); } } @@ -379,16 +380,16 @@ HRESULT GlassRenderer::Startup() { dwmcore::GetAddressFromSymbolMap("CRenderData::TryDrawCommandAsDrawList", g_CRenderData_TryDrawCommandAsDrawList_Org); dwmcore::GetAddressFromSymbolMap("CRenderData::DrawSolidColorRectangle", g_CRenderData_DrawSolidColorRectangle_Org); + dwmcore::GetAddressFromSymbolMap("CDirtyRegion::_Add", g_CDirtyRegion__Add_Org); dwmcore::GetAddressFromSymbolMap("CGeometry::~CGeometry", g_CGeometry_Destructor_Org); dwmcore::GetAddressFromSymbolMap("CSolidColorLegacyMilBrush::`vftable'", g_CSolidColorLegacyMilBrush_vftable); - dwmcore::GetAddressFromSymbolMap("CDirtyRegion::_Add", g_CDirtyRegion__Add_Org); return HookHelper::Detours::Write([]() { HookHelper::Detours::Attach(&g_CRenderData_TryDrawCommandAsDrawList_Org, MyCRenderData_TryDrawCommandAsDrawList); HookHelper::Detours::Attach(&g_CRenderData_DrawSolidColorRectangle_Org, MyCRenderData_DrawSolidColorRectangle); - HookHelper::Detours::Attach(&g_CGeometry_Destructor_Org, MyCGeometry_Destructor); HookHelper::Detours::Attach(&g_CDirtyRegion__Add_Org, MyCDirtyRegion__Add); + HookHelper::Detours::Attach(&g_CGeometry_Destructor_Org, MyCGeometry_Destructor); }); } @@ -398,8 +399,8 @@ void GlassRenderer::Shutdown() { HookHelper::Detours::Detach(&g_CRenderData_TryDrawCommandAsDrawList_Org, MyCRenderData_TryDrawCommandAsDrawList); HookHelper::Detours::Detach(&g_CRenderData_DrawSolidColorRectangle_Org, MyCRenderData_DrawSolidColorRectangle); - HookHelper::Detours::Detach(&g_CGeometry_Destructor_Org, MyCGeometry_Destructor); HookHelper::Detours::Detach(&g_CDirtyRegion__Add_Org, MyCDirtyRegion__Add); + HookHelper::Detours::Detach(&g_CGeometry_Destructor_Org, MyCGeometry_Destructor); }); if (g_ID2D1DeviceContext_FillGeometry_Org) @@ -421,6 +422,6 @@ void GlassRenderer::Shutdown() g_CDrawingContext_DrawSolidRectangle_Org = nullptr; } - GlassEffectManager::Shutdown(); - ReflectionRenderer::g_reflectionBitmap = nullptr; + GlassEffectFactory::Shutdown(); + ReflectionEffect::Reset(); } diff --git a/OpenGlass/GlassSharedData.hpp b/OpenGlass/GlassSharedData.hpp deleted file mode 100644 index e446ce0..0000000 --- a/OpenGlass/GlassSharedData.hpp +++ /dev/null @@ -1,31 +0,0 @@ -#pragma once -#include "framework.hpp" -#include "cpprt.hpp" -#include "GlassSharedStructures.hpp" - -namespace OpenGlass::GlassSharedData -{ - inline bool g_disableOnBattery{ true }; - inline bool g_overrideAccent{ false }; - inline bool g_batteryMode{ false }; - inline bool g_transparencyEnabled{ true }; - inline float g_ColorizationAfterglowBalance = 0.43f; - inline float g_ColorizationBlurBalance = 0.49f; - inline float g_ColorizationColorBalance = 0.08f; - inline D2D_COLOR_F g_ColorizationColor{ 116.0f / 255.0f, 184.0f / 255.0f, 252.0f / 255.0f,1.0f }; - inline Type g_type{ Type::Blur }; - - FORCEINLINE bool IsBackdropAllowed() - { - if (g_batteryMode && g_disableOnBattery) - { - return false; - } - if (!g_transparencyEnabled) - { - return false; - } - - return true; - } -} \ No newline at end of file diff --git a/OpenGlass/GlassSharedStructures.hpp b/OpenGlass/GlassSharedStructures.hpp deleted file mode 100644 index 5231162..0000000 --- a/OpenGlass/GlassSharedStructures.hpp +++ /dev/null @@ -1,10 +0,0 @@ -#pragma once - -namespace OpenGlass -{ - enum class Type : unsigned char - { - Blur = 0, - Aero = 1 - }; -} \ No newline at end of file diff --git a/OpenGlass/HookHelper.cpp b/OpenGlass/HookHelper.cpp index dcc85b7..c05ccb7 100644 --- a/OpenGlass/HookHelper.cpp +++ b/OpenGlass/HookHelper.cpp @@ -93,7 +93,7 @@ HMODULE HookHelper::GetProcessModule(HANDLE processHandle, std::wstring_view dll return targetModule; } DWORD moduleCount{ bytesNeeded / sizeof(HMODULE) }; - auto moduleList{ std::make_unique(moduleCount) }; + auto moduleList = std::make_unique(moduleCount); if (!EnumProcessModules(processHandle, moduleList.get(), bytesNeeded, &bytesNeeded)) { return targetModule; @@ -122,17 +122,14 @@ void HookHelper::WalkIAT(PVOID baseAddress, std::string_view dllName, std::funct THROW_HR_IF_NULL(E_INVALIDARG, callback); ULONG size{ 0ul }; - auto importDescriptor - { - static_cast( - ImageDirectoryEntryToData( - baseAddress, - TRUE, - IMAGE_DIRECTORY_ENTRY_IMPORT, - &size - ) + auto importDescriptor = static_cast( + ImageDirectoryEntryToData( + baseAddress, + TRUE, + IMAGE_DIRECTORY_ENTRY_IMPORT, + &size ) - }; + ); THROW_HR_IF_NULL(E_INVALIDARG, importDescriptor); @@ -152,7 +149,7 @@ void HookHelper::WalkIAT(PVOID baseAddress, std::string_view dllName, std::funct THROW_HR_IF(HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), !found); - auto thunk{ reinterpret_cast(reinterpret_cast(baseAddress) + importDescriptor->FirstThunk) }; + auto thunk = reinterpret_cast(reinterpret_cast(baseAddress) + importDescriptor->FirstThunk); auto nameThunk = reinterpret_cast(reinterpret_cast(baseAddress) + importDescriptor->OriginalFirstThunk); bool result{ true }; @@ -192,17 +189,14 @@ void HookHelper::WalkDelayloadIAT(PVOID baseAddress, std::string_view dllName, s THROW_HR_IF_NULL(E_INVALIDARG, callback); ULONG size{ 0ul }; - auto importDescriptor - { - static_cast( - ImageDirectoryEntryToData( - baseAddress, - TRUE, - IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT, - &size - ) + auto importDescriptor = static_cast( + ImageDirectoryEntryToData( + baseAddress, + TRUE, + IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT, + &size ) - }; + ); THROW_HR_IF_NULL(E_INVALIDARG, importDescriptor); @@ -224,7 +218,7 @@ void HookHelper::WalkDelayloadIAT(PVOID baseAddress, std::string_view dllName, s THROW_HR_IF(HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), !found); - auto attributes{ importDescriptor->Attributes.RvaBased }; + auto attributes = importDescriptor->Attributes.RvaBased; THROW_WIN32_IF_MSG(ERROR_FILE_NOT_FOUND, attributes != 1, "Unsupported delay loaded dll![%hs]", dllName.data()); auto moduleHandle = reinterpret_cast( @@ -317,7 +311,7 @@ PVOID HookHelper::WriteIAT(PVOID baseAddress, std::string_view dllName, LPCSTR t { PVOID originalFunction{ nullptr }; - auto functionAddress{ GetIAT(baseAddress, dllName, targetFunctionNameOrOrdinal) }; + auto functionAddress = GetIAT(baseAddress, dllName, targetFunctionNameOrOrdinal); if (functionAddress) { originalFunction = *functionAddress; @@ -332,7 +326,7 @@ std::pair HookHelper::WriteDelayloadIAT(PVOID baseAddress, std:: HMODULE originalModule{ nullptr }; PVOID originalFunction{ nullptr }; - auto [moduleHandle, functionAddress] {GetDelayloadIAT(baseAddress, dllName, targetFunctionNameOrOrdinal, true)}; + auto [moduleHandle, functionAddress] = GetDelayloadIAT(baseAddress, dllName, targetFunctionNameOrOrdinal, true); if (functionAddress) { originalModule = *moduleHandle; diff --git a/OpenGlass/OpenGlass.cpp b/OpenGlass/OpenGlass.cpp index a8433ca..963b3f1 100644 --- a/OpenGlass/OpenGlass.cpp +++ b/OpenGlass/OpenGlass.cpp @@ -257,7 +257,7 @@ void OpenGlass::OnSymbolDownloading(SymbolDownloaderStatus status, std::wstring_ } case SymbolDownloaderStatus::Downloading: { - auto percentIndex{ text.find(L" percent") }; + auto percentIndex = text.find(L" percent"); if (percentIndex != text.npos) { std::wstring_view progressView{ &text[percentIndex] - 3, 4 }; @@ -288,8 +288,8 @@ void OpenGlass::OnSymbolDownloading(SymbolDownloaderStatus status, std::wstring_ DWORD WINAPI OpenGlass::Initialize(PVOID) { - auto moduleReference{ wil::get_module_reference_for_thread() }; - auto coCleanUp{ wil::CoInitializeEx() }; + auto moduleReference = wil::get_module_reference_for_thread(); + auto coCleanUp = wil::CoInitializeEx(); SetThreadDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2); RETURN_IF_FAILED(SetThreadDescription(GetCurrentThread(), L"OpenGlass Initialization Thread")); @@ -302,7 +302,7 @@ DWORD WINAPI OpenGlass::Initialize(PVOID) if (os::IsOpenGlassUnsupported()) { - auto result{ 0 }; + auto result = 0; LOG_IF_FAILED( TaskDialog( nullptr, @@ -322,7 +322,7 @@ DWORD WINAPI OpenGlass::Initialize(PVOID) } { - auto indicator{ std::make_unique() }; + auto indicator = std::make_unique(); indicator->SetProgressTotalValue(200, false); g_indicator = indicator.get(); diff --git a/OpenGlass/OpenGlass.vcxproj b/OpenGlass/OpenGlass.vcxproj index e555557..e2c35a4 100644 --- a/OpenGlass/OpenGlass.vcxproj +++ b/OpenGlass/OpenGlass.vcxproj @@ -189,15 +189,16 @@ + + - - - + + - + @@ -217,9 +218,11 @@ + + - + diff --git a/OpenGlass/ReflectionEffect.hpp b/OpenGlass/ReflectionEffect.hpp new file mode 100644 index 0000000..977b889 --- /dev/null +++ b/OpenGlass/ReflectionEffect.hpp @@ -0,0 +1,254 @@ +#pragma once +#include "resource.h" +#include "framework.hpp" +#include "cpprt.hpp" +#include "uDwmProjection.hpp" + +namespace OpenGlass::ReflectionEffect +{ + namespace Details + { + bool g_reflectionTexturePathChanged{ false }; + inline winrt::com_ptr g_reflectionBitmapSourceEffect{ nullptr }; + inline winrt::com_ptr g_cropEffect{ nullptr }; + inline std::wstring g_reflectionTexturePath{}; + inline UINT g_reflectionTextureWidth{}, g_reflectionTextureHeight{}; + } + + inline void UpdateTexture( + std::wstring_view reflectionTexturePath + ) + { + Details::g_reflectionTexturePath = reflectionTexturePath; + Details::g_reflectionTextureWidth = Details::g_reflectionTextureHeight = 0; + Details::g_reflectionTexturePathChanged = true; + } + inline HRESULT Render( + ID2D1DeviceContext* context, + ID2D1Geometry* geometry, + float reflectionIntensity, + float parallaxIntensity, + // reserved for the next release + const D2D1_SIZE_F* canvasSize = nullptr, + const D2D1_POINT_2F* glassOffset = nullptr + ) + { + if (reflectionIntensity == 0.f) + { + return S_OK; + } + // setup effects + if (!Details::g_reflectionBitmapSourceEffect) + { + RETURN_IF_FAILED( + context->CreateEffect( + CLSID_D2D1BitmapSource, + Details::g_reflectionBitmapSourceEffect.put() + ) + ); + RETURN_IF_FAILED( + Details::g_reflectionBitmapSourceEffect->SetValue( + D2D1_BITMAPSOURCE_PROP_ALPHA_MODE, + D2D1_ALPHA_MODE_PREMULTIPLIED + ) + ); + RETURN_IF_FAILED( + Details::g_reflectionBitmapSourceEffect->SetValue( + D2D1_BITMAPSOURCE_PROP_INTERPOLATION_MODE, + D2D1_INTERPOLATION_MODE_LINEAR + ) + ); + RETURN_IF_FAILED( + Details::g_reflectionBitmapSourceEffect->SetValue( + D2D1_PROPERTY_CACHED, + TRUE + ) + ); + + Details::g_reflectionTexturePathChanged = true; + } + if (!Details::g_cropEffect) + { + RETURN_IF_FAILED( + context->CreateEffect( + CLSID_D2D1Crop, + Details::g_cropEffect.put() + ) + ); + RETURN_IF_FAILED( + Details::g_cropEffect->SetValue( + D2D1_CROP_PROP_BORDER_MODE, + D2D1_BORDER_MODE_SOFT + ) + ); + Details::g_cropEffect->SetInputEffect(0, Details::g_reflectionBitmapSourceEffect.get()); + } + + if (Details::g_reflectionTexturePathChanged) + { + winrt::com_ptr stream{ nullptr }; + if (Details::g_reflectionTexturePath.empty() || !PathFileExistsW(Details::g_reflectionTexturePath.data())) + { + HMODULE currentModule{ wil::GetModuleInstanceHandle() }; + auto resourceHandle = FindResourceW(currentModule, MAKEINTRESOURCE(IDB_REFLECTION), L"PNG"); + RETURN_LAST_ERROR_IF_NULL(resourceHandle); + auto globalHandle = LoadResource(currentModule, resourceHandle); + RETURN_LAST_ERROR_IF_NULL(globalHandle); + auto cleanUp = wil::scope_exit([&] + { + if (globalHandle) + { + UnlockResource(globalHandle); + FreeResource(globalHandle); + } + }); + DWORD resourceSize{ SizeofResource(currentModule, resourceHandle) }; + RETURN_LAST_ERROR_IF(resourceSize == 0); + auto resourceAddress = reinterpret_cast(LockResource(globalHandle)); + stream = { SHCreateMemStream(resourceAddress, resourceSize), winrt::take_ownership_from_abi }; + } + else + { + wil::unique_hfile file{ CreateFileW(Details::g_reflectionTexturePath.data(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0) }; + RETURN_LAST_ERROR_IF(!file.is_valid()); + + LARGE_INTEGER fileSize{}; + RETURN_IF_WIN32_BOOL_FALSE(GetFileSizeEx(file.get(), &fileSize)); + + auto buffer = std::make_unique(static_cast(fileSize.QuadPart)); + RETURN_IF_WIN32_BOOL_FALSE(ReadFile(file.get(), buffer.get(), static_cast(fileSize.QuadPart), nullptr, nullptr)); + stream = { SHCreateMemStream(buffer.get(), static_cast(fileSize.QuadPart)), winrt::take_ownership_from_abi }; + } + RETURN_LAST_ERROR_IF_NULL(stream); + + winrt::com_ptr wicFactory{ nullptr }; + wicFactory.copy_from(uDwm::CDesktopManager::s_pDesktopManagerInstance->GetWICFactory()); + winrt::com_ptr wicDecoder{ nullptr }; + RETURN_IF_FAILED(wicFactory->CreateDecoderFromStream(stream.get(), &GUID_VendorMicrosoft, WICDecodeMetadataCacheOnDemand, wicDecoder.put())); + winrt::com_ptr wicFrame{ nullptr }; + RETURN_IF_FAILED(wicDecoder->GetFrame(0, wicFrame.put())); + winrt::com_ptr wicConverter{ nullptr }; + RETURN_IF_FAILED(wicFactory->CreateFormatConverter(wicConverter.put())); + RETURN_IF_FAILED( + wicConverter->Initialize( + wicFrame.get(), + GUID_WICPixelFormat32bppPBGRA, + WICBitmapDitherTypeNone, + nullptr, + 0, + WICBitmapPaletteTypeCustom + ) + ); + + RETURN_IF_FAILED( + Details::g_reflectionBitmapSourceEffect->SetValue( + D2D1_BITMAPSOURCE_PROP_WIC_BITMAP_SOURCE, + wicConverter.get() + ) + ); + RETURN_IF_FAILED( + wicConverter->GetSize( + &Details::g_reflectionTextureWidth, + &Details::g_reflectionTextureHeight + ) + ); + Details::g_reflectionTexturePathChanged = false; + } + + // initialize effect params + if (!canvasSize) + { + auto size = context->GetSize(); + RETURN_IF_FAILED( + Details::g_reflectionBitmapSourceEffect->SetValue( + D2D1_BITMAPSOURCE_PROP_SCALE, + D2D1::Vector2F( + size.width / static_cast(Details::g_reflectionTextureWidth), + size.height / static_cast(Details::g_reflectionTextureHeight) + ) + ) + ); + } + else + { + RETURN_IF_FAILED( + Details::g_reflectionBitmapSourceEffect->SetValue( + D2D1_BITMAPSOURCE_PROP_SCALE, + D2D1::Vector2F( + canvasSize->width / static_cast(Details::g_reflectionTextureWidth), + canvasSize->height / static_cast(Details::g_reflectionTextureHeight) + ) + ) + ); + } + + D2D1_MATRIX_3X2_F matrix{}; + context->GetTransform(&matrix); + + D2D1_POINT_2F offset{}; + if (!glassOffset) + { + offset = D2D1::Point2F(matrix.dx, matrix.dy); + matrix.dx = matrix.dy = 0.f; + } + else + { + offset = *glassOffset; + } + + D2D1_RECT_F bounds{}; + RETURN_IF_FAILED(geometry->GetBounds(nullptr, &bounds)); + + //D2D1_POINT_2F point{ offset.x >= 0.f ? bounds.left : 0.f, offset.y >= 0.f ? bounds.top : 0.f }; + D2D1_POINT_2F point{ bounds.left, bounds.top }; + D2D1_RECT_F cropRect + { + offset.x * (1.f - parallaxIntensity), + offset.y + }; + cropRect.right = max(cropRect.left, 0.f) + (bounds.right - bounds.left); + cropRect.bottom = max(cropRect.top, 0.f) + (bounds.bottom - bounds.top); + + RETURN_IF_FAILED( + Details::g_cropEffect->SetValue( + D2D1_CROP_PROP_RECT, + cropRect + ) + ); + + if (memcmp(matrix.m, D2D1::IdentityMatrix().m, sizeof(matrix.m)) != 0) + { + // not identity matrix, stop rendering it + // currently not support + + return S_OK; + } + context->PushLayer( + D2D1::LayerParameters1( + bounds, + geometry, + D2D1_ANTIALIAS_MODE_ALIASED, + D2D1::IdentityMatrix(), + reflectionIntensity, + nullptr, + D2D1_LAYER_OPTIONS1_INITIALIZE_FROM_BACKGROUND + ), + nullptr + ); + // do some rendering job + context->DrawImage( + Details::g_cropEffect.get(), + point, + cropRect + ); + context->PopLayer(); + + return S_OK; + } + inline void Reset() + { + Details::g_reflectionBitmapSourceEffect = nullptr; + Details::g_cropEffect = nullptr; + Details::g_reflectionTextureWidth = Details::g_reflectionTextureHeight = 0; + } +} \ No newline at end of file diff --git a/OpenGlass/ReflectionRenderer.hpp b/OpenGlass/ReflectionRenderer.hpp deleted file mode 100644 index 29eeba3..0000000 --- a/OpenGlass/ReflectionRenderer.hpp +++ /dev/null @@ -1,147 +0,0 @@ -#pragma once -#include "pch.h" -#include "resource.h" -#include "framework.hpp" -#include "cpprt.hpp" -#include "uDwmProjection.hpp" - -namespace OpenGlass::ReflectionRenderer -{ - inline float g_reflectionIntensity{ 0.f }; - inline float g_reflectionParallaxIntensity{ 0.1f }; - inline std::wstring g_reflectionTexturePath{}; - inline winrt::com_ptr g_reflectionBitmap{ nullptr }; - - inline HRESULT LoadReflectionTexture(ID2D1DeviceContext* deviceContext) - { - winrt::com_ptr stream{ nullptr }; - if (g_reflectionTexturePath.empty() || !PathFileExistsW(g_reflectionTexturePath.data())) - { - HMODULE currentModule{ wil::GetModuleInstanceHandle() }; - auto resourceHandle{ FindResourceW(currentModule, MAKEINTRESOURCE(IDB_REFLECTION), L"PNG") }; - RETURN_LAST_ERROR_IF_NULL(resourceHandle); - auto globalHandle{ LoadResource(currentModule, resourceHandle) }; - RETURN_LAST_ERROR_IF_NULL(globalHandle); - auto cleanUp = wil::scope_exit([&] - { - if (globalHandle) - { - UnlockResource(globalHandle); - FreeResource(globalHandle); - } - }); - DWORD resourceSize{ SizeofResource(currentModule, resourceHandle) }; - RETURN_LAST_ERROR_IF(resourceSize == 0); - auto resourceAddress{ reinterpret_cast(LockResource(globalHandle)) }; - stream = { SHCreateMemStream(resourceAddress, resourceSize), winrt::take_ownership_from_abi }; - } - else - { - wil::unique_hfile file{ CreateFileW(g_reflectionTexturePath.data(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0) }; - RETURN_LAST_ERROR_IF(!file.is_valid()); - - LARGE_INTEGER fileSize{}; - RETURN_IF_WIN32_BOOL_FALSE(GetFileSizeEx(file.get(), &fileSize)); - - auto buffer{ std::make_unique(static_cast(fileSize.QuadPart)) }; - RETURN_IF_WIN32_BOOL_FALSE(ReadFile(file.get(), buffer.get(), static_cast(fileSize.QuadPart), nullptr, nullptr)); - stream = { SHCreateMemStream(buffer.get(), static_cast(fileSize.QuadPart)), winrt::take_ownership_from_abi }; - } - RETURN_LAST_ERROR_IF_NULL(stream); - - winrt::com_ptr wicFactory{ nullptr }; - wicFactory.copy_from(uDwm::CDesktopManager::s_pDesktopManagerInstance->GetWICFactory()); - winrt::com_ptr wicDecoder{ nullptr }; - RETURN_IF_FAILED(wicFactory->CreateDecoderFromStream(stream.get(), &GUID_VendorMicrosoft, WICDecodeMetadataCacheOnDemand, wicDecoder.put())); - winrt::com_ptr wicFrame{ nullptr }; - RETURN_IF_FAILED(wicDecoder->GetFrame(0, wicFrame.put())); - winrt::com_ptr wicConverter{ nullptr }; - RETURN_IF_FAILED(wicFactory->CreateFormatConverter(wicConverter.put())); - winrt::com_ptr wicPalette{ nullptr }; - RETURN_IF_FAILED( - wicConverter->Initialize( - wicFrame.get(), - GUID_WICPixelFormat32bppPBGRA, - WICBitmapDitherTypeNone, - wicPalette.get(), - 0, WICBitmapPaletteTypeCustom - ) - ); - winrt::com_ptr wicBitmap{ nullptr }; - RETURN_IF_FAILED(wicFactory->CreateBitmapFromSource(wicConverter.get(), WICBitmapCreateCacheOption::WICBitmapNoCache, wicBitmap.put())); - - RETURN_IF_FAILED( - deviceContext->CreateBitmapFromWicBitmap( - wicBitmap.get(), - D2D1::BitmapProperties1( - D2D1_BITMAP_OPTIONS_NONE, - D2D1::PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_PREMULTIPLIED) - ), - g_reflectionBitmap.put() - ) - ); - - return S_OK; - } - inline HRESULT Draw( - ID2D1DeviceContext* deviceContext, - const D2D1_POINT_2F& reflectionPosition, - const D2D1_SIZE_F& desktopSize, - const D2D1_RECT_F& reflectionBounds - ) - { - if (!g_reflectionBitmap) - { - RETURN_IF_FAILED(LoadReflectionTexture(deviceContext)); - } - if (g_reflectionIntensity != 0.f) - { - auto reflectionSize{ g_reflectionBitmap->GetSize() }; - auto bounds{ reflectionBounds }; - D2D1_POINT_2F offset - { - reflectionPosition.x * (1.f - g_reflectionParallaxIntensity) * (reflectionSize.width / desktopSize.width), - reflectionPosition.y * (reflectionSize.height / desktopSize.height) - }; - if (reflectionPosition.x < 0) - { - bounds.left += -reflectionPosition.x; - offset.x += -offset.x; - } - if (reflectionPosition.y < 0) - { - bounds.top += -reflectionPosition.y; - offset.y += -offset.y; - } - if (reflectionPosition.x + reflectionBounds.right - reflectionBounds.left > desktopSize.width) - { - bounds.right = bounds.right - (reflectionPosition.x + reflectionBounds.right - reflectionBounds.left - desktopSize.width); - } - if (reflectionPosition.y + reflectionBounds.bottom - reflectionBounds.top > desktopSize.height) - { - bounds.bottom = bounds.bottom - (reflectionPosition.y + reflectionBounds.bottom - reflectionBounds.top - desktopSize.height); - } - - D2D1_SIZE_F size - { - (bounds.right - bounds.left) * (reflectionSize.width / desktopSize.width), - (bounds.bottom - bounds.top) * (reflectionSize.height / desktopSize.height) - }; - - deviceContext->DrawBitmap( - g_reflectionBitmap.get(), - bounds, - g_reflectionIntensity, - D2D1_BITMAP_INTERPOLATION_MODE_LINEAR, - D2D1::RectF( - offset.x, - offset.y, - offset.x + size.width, - offset.y + size.height - ) - ); - } - - return S_OK; - } -} \ No newline at end of file diff --git a/OpenGlass/ServiceApi.cpp b/OpenGlass/ServiceApi.cpp index 84b6293..94ae2c2 100644 --- a/OpenGlass/ServiceApi.cpp +++ b/OpenGlass/ServiceApi.cpp @@ -10,7 +10,7 @@ namespace OpenGlass std::unordered_map> g_dwmInjectionMap{}; std::chrono::steady_clock::time_point g_dwmInjectionCheckPoint{}; bool g_serverClosed{ false }; - auto g_openGlassDllPath{ wil::GetModuleFileNameW(wil::GetModuleInstanceHandle()) }; + auto g_openGlassDllPath = wil::GetModuleFileNameW(wil::GetModuleInstanceHandle()); } using namespace OpenGlass; @@ -84,8 +84,8 @@ HRESULT Server::InjectDllToDwm(DWORD processId, bool inject) OutputDebugStringW(std::format(L"dwm {}. (PID: {})\n", inject ? L"injected" : L"uninjected", processId).c_str()); #endif // _DEBUG - auto bufferSize{ (g_openGlassDllPath.size() + 1) * sizeof(WCHAR) }; - auto remoteAddress{ inject ? VirtualAllocEx(processHandle.get(), nullptr, bufferSize, MEM_COMMIT, PAGE_READWRITE) : nullptr }; + auto bufferSize = (g_openGlassDllPath.size() + 1) * sizeof(WCHAR); + auto remoteAddress = inject ? VirtualAllocEx(processHandle.get(), nullptr, bufferSize, MEM_COMMIT, PAGE_READWRITE) : nullptr; if (inject) { RETURN_LAST_ERROR_IF_NULL(remoteAddress); @@ -99,18 +99,16 @@ HRESULT Server::InjectDllToDwm(DWORD processId, bool inject) } }); - auto startRoutine - { - inject ? + auto startRoutine = + inject ? reinterpret_cast(LoadLibraryW) : - reinterpret_cast(FreeLibrary) - }; + reinterpret_cast(FreeLibrary); if (inject) { RETURN_IF_WIN32_BOOL_FALSE(WriteProcessMemory(processHandle.get(), remoteAddress, static_cast(g_openGlassDllPath.c_str()), bufferSize, nullptr)); } wil::unique_handle threadHandle{ nullptr }; - static const auto s_pfnNtCreateThreadEx{ reinterpret_cast(GetProcAddress(GetModuleHandleW(L"ntdll.dll"), "NtCreateThreadEx")) }; + static const auto s_pfnNtCreateThreadEx = reinterpret_cast(GetProcAddress(GetModuleHandleW(L"ntdll.dll"), "NtCreateThreadEx")); NTSTATUS ntstatus{ s_pfnNtCreateThreadEx(&threadHandle, PROCESS_ALL_ACCESS, nullptr, processHandle.get(), startRoutine, inject ? remoteAddress : moduleHandle, 0x0, 0x0, 0x0, 0x0, nullptr)}; RETURN_IF_NTSTATUS_FAILED(ntstatus); RETURN_LAST_ERROR_IF(WaitForSingleObject(threadHandle.get(), 1000) != WAIT_OBJECT_0); @@ -121,8 +119,8 @@ HRESULT Server::InjectDllToDwm(DWORD processId, bool inject) DWORD Server::InjectionThreadProc(LPVOID) { RETURN_IF_FAILED(SetThreadDescription(GetCurrentThread(), L"OpenGlass Injection Thread")); - constexpr auto SE_DEBUG_PRIVILEGE{ 0x14 }; - static const auto s_pfnRtlAdjustPrivilege{ reinterpret_cast(GetProcAddress(GetModuleHandleW(L"ntdll.dll"), "RtlAdjustPrivilege")) }; + constexpr auto SE_DEBUG_PRIVILEGE = 0x14; + static const auto s_pfnRtlAdjustPrivilege = reinterpret_cast(GetProcAddress(GetModuleHandleW(L"ntdll.dll"), "RtlAdjustPrivilege")); BOOLEAN result = false; s_pfnRtlAdjustPrivilege(SE_DEBUG_PRIVILEGE, true, false, &result); @@ -161,12 +159,12 @@ DWORD Server::InjectionThreadProc(LPVOID) { return; } - auto currentTimeStamp{ std::chrono::steady_clock::now() }; + auto currentTimeStamp = std::chrono::steady_clock::now(); if (!IsDllAlreadyLoadedByDwm(processId)) { // DWM crashes constantly - auto it{ g_dwmInjectionMap.find(sessionId) }; + auto it = g_dwmInjectionMap.find(sessionId); if (it != g_dwmInjectionMap.end()) { auto IsProcessAlive = [](DWORD processId) @@ -181,8 +179,8 @@ DWORD Server::InjectionThreadProc(LPVOID) }; if (currentTimeStamp - it->second.second <= std::chrono::seconds{ 15 } && !IsProcessAlive(it->second.first)) { - auto title{ Utils::GetResWStringView() }; - auto content{ Utils::GetResWStringView() }; + auto title = Utils::GetResWStringView(); + auto content = Utils::GetResWStringView(); DWORD response{ IDTIMEOUT }; LOG_IF_WIN32_BOOL_FALSE( WTSSendMessageW( diff --git a/OpenGlass/Shared.hpp b/OpenGlass/Shared.hpp new file mode 100644 index 0000000..9ca1b51 --- /dev/null +++ b/OpenGlass/Shared.hpp @@ -0,0 +1,57 @@ +#pragma once +#include "framework.hpp" +#include "cpprt.hpp" + +namespace OpenGlass::Shared +{ + inline enum class Type : UCHAR + { + Blur, + Aero + } g_type{ 0 }; + inline bool g_enableGeometryMerging{ false }; + inline bool g_disableOnBattery{ true }; + inline bool g_overrideAccent{ false }; + inline bool g_batteryMode{ false }; + inline bool g_transparencyEnabled{ true }; + inline float g_blurAmount{ 9.f }; + inline float g_glassOpacity{ 0.63f }; + // exclusively used by aero backdrop + inline float g_colorBalance{ 0.f }; + inline float g_afterglowBalance{ 0.43f }; + inline float g_blurBalance{ 0.49f }; + inline D2D1_COLOR_F g_color + { + 116.f / 255.f, + 184.f / 255.f, + 252.f / 255.f, + 1.f + }; + inline D2D1_COLOR_F g_afterglow + { + 116.f / 255.f, + 184.f / 255.f, + 252.f / 255.f, + 1.f + }; + inline bool g_forceAccentColorization{ false }; + inline D2D1_COLOR_F g_accentColor{}; + inline D2D1_COLOR_F g_accentColorInactive{}; + + inline float g_reflectionIntensity{ 0.f }; + inline float g_reflectionParallaxIntensity{ 0.1f }; + + FORCEINLINE bool IsBackdropAllowed() + { + if (g_batteryMode && g_disableOnBattery) + { + return false; + } + if (!g_transparencyEnabled) + { + return false; + } + + return true; + } +} \ No newline at end of file diff --git a/OpenGlass/SymbolParser.cpp b/OpenGlass/SymbolParser.cpp index d5b72b0..84492d7 100644 --- a/OpenGlass/SymbolParser.cpp +++ b/OpenGlass/SymbolParser.cpp @@ -16,8 +16,8 @@ BOOL CALLBACK SymbolParser::SymCallback( { if (UserContext) { - auto& symbolResolver{ *reinterpret_cast(UserContext) }; - auto event{ reinterpret_cast(CallbackData) }; + auto& symbolResolver = *reinterpret_cast(UserContext); + auto event = reinterpret_cast(CallbackData); if (wcsstr(event->desc, L"from http://")) { @@ -46,8 +46,8 @@ HMODULE WINAPI SymbolParser::MyLoadLibraryExW( DWORD dwFlags ) { - static auto s_symsrvSysFullPath{ wil::GetSystemDirectoryW() + L"\\symsrv.dll" }; - static auto s_symsrvCurFullPath{ Utils::make_current_folder_file_wstring(L"symsrv.dll") }; + static const auto s_symsrvSysFullPath = wil::GetSystemDirectoryW() + L"\\symsrv.dll"; + static const auto s_symsrvCurFullPath = Utils::make_current_folder_file_wstring(L"symsrv.dll"); if ( !_wcsicmp(lpLibFileName, s_symsrvSysFullPath.c_str()) ) @@ -72,7 +72,7 @@ SymbolParser::SymbolParser() THROW_LAST_ERROR_IF(GetModuleFileName(wil::GetModuleInstanceHandle(), curDir, MAX_PATH) == 0); THROW_IF_FAILED(PathCchRemoveFileSpec(curDir, MAX_PATH)); - auto symPath{ std::wstring{L"SRV*"} + curDir + L"\\symbols" }; + const auto symPath = std::wstring{ L"SRV*" } + curDir + L"\\symbols"; THROW_IF_WIN32_BOOL_FALSE(SymSetSearchPathW(GetCurrentProcess(), symPath.c_str())); } catch (...) @@ -123,7 +123,7 @@ HRESULT SymbolParser::Walk( THROW_LAST_ERROR_IF(GetModuleFileName(wil::GetModuleInstanceHandle(), curDir, MAX_PATH) == 0); THROW_IF_FAILED(PathCchRemoveFileSpec(curDir, MAX_PATH)); - auto symPath{ std::wstring{L"SRV*"} + curDir + L"\\symbols*http://msdl.microsoft.com/download/symbols" }; + const auto symPath = std::wstring{ L"SRV*" } + curDir + L"\\symbols*http://msdl.microsoft.com/download/symbols"; DWORD options = SymSetOptions(SymGetOptions() | SYMOPT_DEBUG); diff --git a/OpenGlass/Utils.hpp b/OpenGlass/Utils.hpp index 2cf8340..ca503f2 100644 --- a/OpenGlass/Utils.hpp +++ b/OpenGlass/Utils.hpp @@ -24,28 +24,25 @@ namespace OpenGlass::Utils FORCEINLINE const std::wstring_view GetResWStringView() { LPCWSTR buffer{ nullptr }; - auto length{ LoadStringW(wil::GetModuleInstanceHandle(), id, reinterpret_cast(&buffer), 0) }; + auto length = LoadStringW(wil::GetModuleInstanceHandle(), id, reinterpret_cast(&buffer), 0); return { buffer, static_cast(length) }; } template FORCEINLINE std::wstring GetResWString() { LPCWSTR buffer{ nullptr }; - auto length{ LoadStringW(wil::GetModuleInstanceHandle(), id, reinterpret_cast(&buffer), 0) }; + auto length = LoadStringW(wil::GetModuleInstanceHandle(), id, reinterpret_cast(&buffer), 0); return { buffer, static_cast(length) }; } static std::wstring make_current_folder_file_wstring(std::wstring_view baseFileName) { - static const auto s_current_module_path + static const auto s_current_module_path = []() -> std::wstring { - []() -> std::wstring - { - WCHAR filePath[MAX_PATH + 1] {}; - GetModuleFileNameW(wil::GetModuleInstanceHandle(), filePath, _countof(filePath)); - return std::wstring{ filePath }; - } () - }; + WCHAR filePath[MAX_PATH + 1]{}; + GetModuleFileNameW(wil::GetModuleInstanceHandle(), filePath, _countof(filePath)); + return std::wstring{ filePath }; + }(); WCHAR filePath[MAX_PATH + 1]{ L"" }; [&]() @@ -67,7 +64,7 @@ namespace OpenGlass::Utils // type = ..., desktop created by CreateDesktop? FORCEINLINE bool WINAPI GetDesktopID(ULONG_PTR type, ULONG_PTR* desktopID) { - static const auto pfnGetDesktopID{ reinterpret_cast(GetProcAddress(GetModuleHandleW(L"user32.dll"), "GetDesktopID")) }; + static const auto pfnGetDesktopID = reinterpret_cast(GetProcAddress(GetModuleHandleW(L"user32.dll"), "GetDesktopID")); if (pfnGetDesktopID) [[likely]] { return pfnGetDesktopID(type, desktopID); @@ -109,7 +106,7 @@ namespace OpenGlass::Utils FORCEINLINE D2D1_COLOR_F FromAbgr(DWORD color) { - auto abgr{ reinterpret_cast(&color) }; + auto abgr = reinterpret_cast(&color); return { static_cast(abgr[0]) / 255.f, @@ -120,7 +117,7 @@ namespace OpenGlass::Utils } FORCEINLINE D2D1_COLOR_F FromArgb(DWORD color) { - auto argb{ reinterpret_cast(&color) }; + auto argb = reinterpret_cast(&color); return { static_cast(argb[2]) / 255.f, @@ -138,8 +135,8 @@ namespace OpenGlass::Utils } } -#define DEFINE_INVOKER(fn) static const auto s_fn_ptr{ Utils::cast_pointer(g_symbolMap.at(#fn)) } -#define DEFINE_USER_INVOKER(type, name) static const auto s_fn_ptr{ Utils::cast_pointer(g_symbolMap.at(name)) } -#define DEFINE_CUSTOM_INVOKER(type, name) static const auto s_fn_ptr{ Utils::cast_pointer(g_symbolMap.at(name)) } +#define DEFINE_INVOKER(fn) static const auto s_fn_ptr = Utils::cast_pointer(g_symbolMap.at(#fn)) +#define DEFINE_USER_INVOKER(type, name) static const auto s_fn_ptr = Utils::cast_pointer(g_symbolMap.at(name)) +#define DEFINE_CUSTOM_INVOKER(type, name) static const auto s_fn_ptr = Utils::cast_pointer(g_symbolMap.at(name)) #define INVOKE_MEMBERFUNCTION(...) std::invoke(s_fn_ptr, this, ##__VA_ARGS__) #define INVOKE_FUNCTION(...) std::invoke(s_fn_ptr, ##__VA_ARGS__) \ No newline at end of file diff --git a/OpenGlass/VisualManager.cpp b/OpenGlass/VisualManager.cpp index 48b491c..bc003ea 100644 --- a/OpenGlass/VisualManager.cpp +++ b/OpenGlass/VisualManager.cpp @@ -2,7 +2,7 @@ #include "GlassFramework.hpp" #include "uDwmProjection.hpp" #include "VisualManager.hpp" -#include "GlassSharedData.hpp" +#include "Shared.hpp" #include "Utils.hpp" using namespace OpenGlass; @@ -15,11 +15,13 @@ namespace OpenGlass::VisualManager bool m_initialized{ false }; uDwm::CTopLevelWindow* m_window{ nullptr }; winrt::com_ptr m_brush{ nullptr }; + winrt::com_ptr m_geometry{ nullptr }; winrt::com_ptr m_captionRgnGeometry{ nullptr }; winrt::com_ptr m_topBorderRgnGeometry{ nullptr }; winrt::com_ptr m_leftBorderRgnGeometry{ nullptr }; winrt::com_ptr m_bottomBorderRgnGeometry{ nullptr }; winrt::com_ptr m_rightBorderRgnGeometry{ nullptr }; + winrt::com_ptr m_instruction{ nullptr }; winrt::com_ptr m_captionDrawInstruction{ nullptr }; winrt::com_ptr m_topBorderDrawInstruction{ nullptr }; winrt::com_ptr m_leftBorderDrawInstruction{ nullptr }; @@ -40,7 +42,7 @@ namespace OpenGlass::VisualManager void VisualManager::RedrawTopLevelWindow(uDwm::CTopLevelWindow* window) { - if (auto clientBlurVisual{ window->GetClientBlurVisual() }; clientBlurVisual) + if (auto clientBlurVisual = window->GetClientBlurVisual(); clientBlurVisual) { LOG_IF_FAILED(clientBlurVisual->ClearInstructions()); } @@ -60,7 +62,7 @@ VisualManager::CLegacyVisualOverrider::CLegacyVisualOverrider(uDwm::CTopLevelWin VisualManager::CLegacyVisualOverrider::~CLegacyVisualOverrider() { - auto legacyVisual{ m_window->GetLegacyVisualAddress() }; + auto legacyVisual = m_window->GetLegacyVisualAddress(); if (*legacyVisual) { m_window->GetNonClientVisual()->GetVisualCollection()->Remove(*legacyVisual); @@ -79,6 +81,20 @@ HRESULT VisualManager::CLegacyVisualOverrider::Initialize() wil::unique_hrgn emptyRegion{ CreateRectRgn(0, 0, 0, 0) }; RETURN_LAST_ERROR_IF_NULL(emptyRegion); + RETURN_IF_FAILED( + uDwm::ResourceHelper::CreateGeometryFromHRGN( + emptyRegion.get(), + m_geometry.put() + ) + ); + RETURN_IF_FAILED( + uDwm::CDrawGeometryInstruction::Create( + m_brush.get(), + m_geometry.get(), + m_instruction.put() + ) + ); + // caption RETURN_IF_FAILED( uDwm::ResourceHelper::CreateGeometryFromHRGN( emptyRegion.get(), @@ -162,158 +178,180 @@ HRESULT STDMETHODCALLTYPE VisualManager::CLegacyVisualOverrider::UpdateNCBackgro { RETURN_IF_FAILED(Initialize()); } - auto legacyVisual{ m_window->GetLegacyVisual() }; + auto legacyVisual = m_window->GetLegacyVisual(); if (!m_window->GetData()->IsWindowVisibleAndUncloaked() || m_window->IsTrullyMinimized()) { return S_OK; } RETURN_IF_FAILED(legacyVisual->ClearInstructions()); - RETURN_IF_FAILED(legacyVisual->AddInstruction(m_captionDrawInstruction.get())); - RETURN_IF_FAILED(legacyVisual->AddInstruction(m_topBorderDrawInstruction.get())); - RETURN_IF_FAILED(legacyVisual->AddInstruction(m_leftBorderDrawInstruction.get())); - RETURN_IF_FAILED(legacyVisual->AddInstruction(m_bottomBorderDrawInstruction.get())); - RETURN_IF_FAILED(legacyVisual->AddInstruction(m_rightBorderDrawInstruction.get())); + if (!Shared::g_enableGeometryMerging) + { + RETURN_IF_FAILED(legacyVisual->AddInstruction(m_captionDrawInstruction.get())); + RETURN_IF_FAILED(legacyVisual->AddInstruction(m_topBorderDrawInstruction.get())); + RETURN_IF_FAILED(legacyVisual->AddInstruction(m_leftBorderDrawInstruction.get())); + RETURN_IF_FAILED(legacyVisual->AddInstruction(m_bottomBorderDrawInstruction.get())); + RETURN_IF_FAILED(legacyVisual->AddInstruction(m_rightBorderDrawInstruction.get())); + } + else + { + RETURN_IF_FAILED(legacyVisual->AddInstruction(m_instruction.get())); + } + + auto color = + Shared::g_forceAccentColorization ? + dwmcore::Convert_D2D1_COLOR_F_sRGB_To_D2D1_COLOR_F_scRGB(m_window->TreatAsActiveWindow() ? Shared::g_accentColor : Shared::g_accentColorInactive) : + m_window->GetTitlebarColorizationParameters()->getArgbcolor(); + color.a = m_window->TreatAsActiveWindow() ? 0.5f : 0.0f; - auto color{ m_window->GetTitlebarColorizationParameters()->getArgbcolor() }; - color.a *= 0.99f; - if (GlassSharedData::g_type == Type::Aero) - color.r = m_window->TreatAsActiveWindow(); //HACK!!: Send active or inactive window data through the red channel RETURN_IF_FAILED(m_brush->Update(1.0, color)); wil::unique_hrgn emptyRegion{ CreateRectRgn(0, 0, 0, 0) }; - if (m_window->GetData()->IsFullGlass()) + if (!Shared::g_enableGeometryMerging) { + if (m_window->GetData()->IsFullGlass()) + { + RETURN_IF_FAILED( + uDwm::ResourceHelper::CreateGeometryFromHRGN( + borderRgn, + reinterpret_cast(&m_captionRgnGeometry) + ) + ); + RETURN_IF_FAILED( + uDwm::ResourceHelper::CreateGeometryFromHRGN( + emptyRegion.get(), + reinterpret_cast(&m_topBorderRgnGeometry) + ) + ); + RETURN_IF_FAILED( + uDwm::ResourceHelper::CreateGeometryFromHRGN( + emptyRegion.get(), + reinterpret_cast(&m_leftBorderRgnGeometry) + ) + ); + RETURN_IF_FAILED( + uDwm::ResourceHelper::CreateGeometryFromHRGN( + emptyRegion.get(), + reinterpret_cast(&m_bottomBorderRgnGeometry) + ) + ); + RETURN_IF_FAILED( + uDwm::ResourceHelper::CreateGeometryFromHRGN( + emptyRegion.get(), + reinterpret_cast(&m_rightBorderRgnGeometry) + ) + ); + + return S_OK; + } + + RECT borderBox{}; + GetRgnBox(borderRgn, &borderBox); + RECT captionBox{}; + GetRgnBox(captionRgn, &captionBox); + RETURN_IF_FAILED( uDwm::ResourceHelper::CreateGeometryFromHRGN( - borderRgn, + captionRgn, reinterpret_cast(&m_captionRgnGeometry) ) ); + wil::unique_hrgn borderPartRgn // top border + { + CreateRectRgn( + borderBox.left, + borderBox.top, + borderBox.right, + captionBox.top + ) + }; + RETURN_LAST_ERROR_IF_NULL(borderPartRgn); + CombineRgn(borderPartRgn.get(), borderPartRgn.get(), borderRgn, RGN_AND); RETURN_IF_FAILED( uDwm::ResourceHelper::CreateGeometryFromHRGN( - emptyRegion.get(), + borderPartRgn.get(), reinterpret_cast(&m_topBorderRgnGeometry) ) ); + + borderPartRgn.reset( // left border + CreateRectRgn( + borderBox.left, + borderBox.top, + captionBox.left, + borderBox.bottom + ) + ); + RETURN_LAST_ERROR_IF_NULL(borderPartRgn); + CombineRgn(borderPartRgn.get(), borderPartRgn.get(), borderRgn, RGN_AND); RETURN_IF_FAILED( uDwm::ResourceHelper::CreateGeometryFromHRGN( - emptyRegion.get(), + borderPartRgn.get(), reinterpret_cast(&m_leftBorderRgnGeometry) ) ); + + borderPartRgn.reset( // bottom border + CreateRectRgn( + captionBox.left, + captionBox.bottom, + captionBox.right, + borderBox.bottom + ) + ); + RETURN_LAST_ERROR_IF_NULL(borderPartRgn); + CombineRgn(borderPartRgn.get(), borderPartRgn.get(), borderRgn, RGN_AND); RETURN_IF_FAILED( uDwm::ResourceHelper::CreateGeometryFromHRGN( - emptyRegion.get(), + borderPartRgn.get(), reinterpret_cast(&m_bottomBorderRgnGeometry) ) ); + + borderPartRgn.reset( // right border + CreateRectRgn( + captionBox.right, + borderBox.top, + borderBox.right, + borderBox.bottom + ) + ); + RETURN_LAST_ERROR_IF_NULL(borderPartRgn); + CombineRgn(borderPartRgn.get(), borderPartRgn.get(), borderRgn, RGN_AND); RETURN_IF_FAILED( uDwm::ResourceHelper::CreateGeometryFromHRGN( - emptyRegion.get(), + borderPartRgn.get(), reinterpret_cast(&m_rightBorderRgnGeometry) ) ); - - return S_OK; } - - RECT borderBox{}; - GetRgnBox(borderRgn, &borderBox); - RECT captionBox{}; - GetRgnBox(captionRgn, &captionBox); - - RETURN_IF_FAILED( - uDwm::ResourceHelper::CreateGeometryFromHRGN( - captionRgn, - reinterpret_cast(&m_captionRgnGeometry) - ) - ); - wil::unique_hrgn borderPartRgn // top border + else { - CreateRectRgn( - borderBox.left, - borderBox.top, - borderBox.right, - captionBox.top - ) - }; - RETURN_LAST_ERROR_IF_NULL(borderPartRgn); - CombineRgn(borderPartRgn.get(), borderPartRgn.get(), borderRgn, RGN_AND); - RETURN_IF_FAILED( - uDwm::ResourceHelper::CreateGeometryFromHRGN( - borderPartRgn.get(), - reinterpret_cast(&m_topBorderRgnGeometry) - ) - ); - - borderPartRgn.reset( // left border - CreateRectRgn( - borderBox.left, - borderBox.top, - captionBox.left, - borderBox.bottom - ) - ); - RETURN_LAST_ERROR_IF_NULL(borderPartRgn); - CombineRgn(borderPartRgn.get(), borderPartRgn.get(), borderRgn, RGN_AND); - RETURN_IF_FAILED( - uDwm::ResourceHelper::CreateGeometryFromHRGN( - borderPartRgn.get(), - reinterpret_cast(&m_leftBorderRgnGeometry) - ) - ); - - borderPartRgn.reset( // bottom border - CreateRectRgn( - captionBox.left, - captionBox.bottom, - captionBox.right, - borderBox.bottom - ) - ); - RETURN_LAST_ERROR_IF_NULL(borderPartRgn); - CombineRgn(borderPartRgn.get(), borderPartRgn.get(), borderRgn, RGN_AND); - RETURN_IF_FAILED( - uDwm::ResourceHelper::CreateGeometryFromHRGN( - borderPartRgn.get(), - reinterpret_cast(&m_bottomBorderRgnGeometry) - ) - ); - - borderPartRgn.reset( // right border - CreateRectRgn( - captionBox.right, - borderBox.top, - borderBox.right, - borderBox.bottom - ) - ); - RETURN_LAST_ERROR_IF_NULL(borderPartRgn); - CombineRgn(borderPartRgn.get(), borderPartRgn.get(), borderRgn, RGN_AND); - RETURN_IF_FAILED( - uDwm::ResourceHelper::CreateGeometryFromHRGN( - borderPartRgn.get(), - reinterpret_cast(&m_rightBorderRgnGeometry) - ) - ); + CombineRgn(emptyRegion.get(), captionRgn, borderRgn, RGN_OR); + RETURN_IF_FAILED( + uDwm::ResourceHelper::CreateGeometryFromHRGN( + emptyRegion.get(), + reinterpret_cast(&m_geometry) + ) + ); + } return S_OK; } -winrt::com_ptr VisualManager::GetOrCreateLegacyVisualOverrider(uDwm::CTopLevelWindow* window, bool createIfNecessary) +winrt::com_ptr VisualManager::GetOrCreateLegacyVisualOverrider(uDwm::CTopLevelWindow* window, bool createIfNecessary) { - auto it{ g_visualMap.find(window) }; + auto it = g_visualMap.find(window); if (createIfNecessary) { - auto data{ window->GetData() }; + auto data = window->GetData(); if ( data && it == g_visualMap.end() ) { - auto result{ g_visualMap.emplace(window, winrt::make(window)) }; + auto result = g_visualMap.emplace(window, winrt::make(window)); if (result.second == true) { it = result.first; @@ -326,7 +364,7 @@ winrt::com_ptr VisualManager::GetOrCreate void VisualManager::RemoveLegacyVisualOverrider(uDwm::CTopLevelWindow* window) { - auto it{ g_visualMap.find(window) }; + auto it = g_visualMap.find(window); if (it != g_visualMap.end()) { diff --git a/OpenGlass/VisualManager.hpp b/OpenGlass/VisualManager.hpp index 5e9ebb2..fa11a17 100644 --- a/OpenGlass/VisualManager.hpp +++ b/OpenGlass/VisualManager.hpp @@ -4,7 +4,7 @@ #include "uDwmProjection.hpp" #include "ConfigurationFramework.hpp" -namespace OpenGlass::VisualManager +namespace OpenGlass { // [Guid("B1FDFCD4-F35C-44FD-8BF0-C2E7E6571461")] DECLARE_INTERFACE_IID_(ILegacyVisualOverrider, IUnknown, "B1FDFCD4-F35C-44FD-8BF0-C2E7E6571461") @@ -15,9 +15,12 @@ namespace OpenGlass::VisualManager ) = 0; }; - winrt::com_ptr GetOrCreateLegacyVisualOverrider(uDwm::CTopLevelWindow* window, bool createIfNecessary = false); - void RemoveLegacyVisualOverrider(uDwm::CTopLevelWindow* window); - void ShutdownLegacyVisualOverrider(); + namespace VisualManager + { + winrt::com_ptr GetOrCreateLegacyVisualOverrider(uDwm::CTopLevelWindow* window, bool createIfNecessary = false); + void RemoveLegacyVisualOverrider(uDwm::CTopLevelWindow* window); + void ShutdownLegacyVisualOverrider(); - void RedrawTopLevelWindow(uDwm::CTopLevelWindow* window); + void RedrawTopLevelWindow(uDwm::CTopLevelWindow* window); + } } \ No newline at end of file diff --git a/OpenGlass/dllmain.cpp b/OpenGlass/dllmain.cpp index 549ce92..f5fc60a 100644 --- a/OpenGlass/dllmain.cpp +++ b/OpenGlass/dllmain.cpp @@ -17,7 +17,7 @@ _NODISCARD _Ret_notnull_ _Post_writable_byte_size_(size) _VCRT_ALLOCATOR void* operator new(size_t size) noexcept(false) { - auto memory{ HeapAlloc(OpenGlass::Utils::g_processHeap, 0, size) }; + auto memory = HeapAlloc(OpenGlass::Utils::g_processHeap, 0, size); THROW_LAST_ERROR_IF_NULL(memory); return memory; } @@ -34,7 +34,7 @@ void* operator new[]( size_t size ) { - auto memory{ HeapAlloc(OpenGlass::Utils::g_processHeap, 0, size) }; + auto memory = HeapAlloc(OpenGlass::Utils::g_processHeap, 0, size); THROW_LAST_ERROR_IF_NULL(memory); return memory; } @@ -128,7 +128,7 @@ EXTERN_C __declspec(dllexport) HRESULT StartupService() { if (!OpenGlass::Utils::IsRunAsLocalSystem()) { - auto cleanUp{ wil::CoInitializeEx() }; + auto cleanUp = wil::CoInitializeEx(); wil::com_ptr taskService{ wil::CoCreateInstance(CLSID_TaskScheduler) }; RETURN_IF_FAILED(taskService->Connect(_variant_t{}, _variant_t{}, _variant_t{}, _variant_t{})); @@ -164,7 +164,7 @@ EXTERN_C __declspec(dllexport) HRESULT ShutdownService() } EXTERN_C __declspec(dllexport) HRESULT InstallApp() try { - auto cleanUp{ wil::CoInitializeEx() }; + auto cleanUp = wil::CoInitializeEx(); wil::com_ptr taskService{ wil::CoCreateInstance(CLSID_TaskScheduler) }; THROW_IF_FAILED(taskService->Connect(_variant_t{}, _variant_t{}, _variant_t{}, _variant_t{})); @@ -257,7 +257,7 @@ EXTERN_C __declspec(dllexport) HRESULT InstallApp() try CATCH_RETURN() EXTERN_C __declspec(dllexport) HRESULT UninstallApp() try { - auto cleanUp{ wil::CoInitializeEx() }; + auto cleanUp = wil::CoInitializeEx(); wil::com_ptr taskService{ wil::CoCreateInstance(CLSID_TaskScheduler) }; THROW_IF_FAILED(taskService->Connect(_variant_t{}, _variant_t{}, _variant_t{}, _variant_t{})); @@ -292,7 +292,7 @@ struct ExecutionParameters ExecutionParameters AnalyseCommandLine(LPCWSTR lpCmdLine) { int args{ 0 }; - auto argv{ CommandLineToArgvW(lpCmdLine, &args) }; + auto argv = CommandLineToArgvW(lpCmdLine, &args); ExecutionParameters params{}; for (int i = 0; i < args; i++) @@ -331,13 +331,13 @@ EXTERN_C __declspec(dllexport) int WINAPI Main( // Convert the ansi string back to unicode string HRESULT hr{ S_OK }; - auto length{ MultiByteToWideChar(CP_ACP, 0, lpCmdLine, -1, nullptr, 0) }; + auto length = MultiByteToWideChar(CP_ACP, 0, lpCmdLine, -1, nullptr, 0); RETURN_LAST_ERROR_IF(length == 0); wil::unique_cotaskmem_string convertedCommandLine{ reinterpret_cast(CoTaskMemAlloc(sizeof(WCHAR) * length)) }; RETURN_LAST_ERROR_IF_NULL(convertedCommandLine); RETURN_LAST_ERROR_IF(MultiByteToWideChar(CP_ACP, 0, lpCmdLine, -1, convertedCommandLine.get(), length) == 0); - auto params{ AnalyseCommandLine(convertedCommandLine.get()) }; + auto params = AnalyseCommandLine(convertedCommandLine.get()); if (params.type == ExecutionParameters::CommandType::Startup) { hr = StartupService(); diff --git a/OpenGlass/dwmcoreProjection.hpp b/OpenGlass/dwmcoreProjection.hpp index f8ebd2a..a0d8b25 100644 --- a/OpenGlass/dwmcoreProjection.hpp +++ b/OpenGlass/dwmcoreProjection.hpp @@ -12,13 +12,13 @@ namespace OpenGlass::dwmcore template FORCEINLINE T GetAddressFromSymbolMap(std::string_view functionName) { - auto it{ g_symbolMap.find(std::string{ functionName }) }; + auto it = g_symbolMap.find(std::string{ functionName }); return it != g_symbolMap.end() ? Utils::cast_pointer(it->second) : nullptr; } template FORCEINLINE void GetAddressFromSymbolMap(std::string_view functionName, T& target) { - auto it{ g_symbolMap.find(std::string{ functionName }) }; + auto it = g_symbolMap.find(std::string{ functionName }); if (it != g_symbolMap.end()) [[likely]] { target = Utils::cast_pointer(it->second); @@ -82,7 +82,7 @@ namespace OpenGlass::dwmcore size_t size ) { - auto memory{ HeapAlloc(OpenGlass::Utils::g_processHeap, 0, size) }; + auto memory = HeapAlloc(OpenGlass::Utils::g_processHeap, 0, size); THROW_LAST_ERROR_IF_NULL(memory); return memory; } @@ -120,17 +120,17 @@ namespace OpenGlass::dwmcore } void Add(const T& object) { - auto newSize{ this->size + 1u }; + auto newSize = this->size + 1u; if (newSize < this->size) { FAIL_FAST_HR(static_cast(0x80070216ul)); } else { - auto bufferSize{ this->size * sizeof(T) }; + auto bufferSize = this->size * sizeof(T); if (newSize > this->capacity) { - auto tmp{ std::unique_ptr(this->data)}; + auto tmp = std::unique_ptr(this->data); this->capacity *= 2; this->data = new T[this->capacity]; @@ -328,6 +328,11 @@ namespace OpenGlass::dwmcore { return reinterpret_cast(this)[30]; } + void STDMETHODCALLTYPE GetClip(ID2DContextOwner* owner, D2D1_RECT_F* clipRect, D2D1_ANTIALIAS_MODE* mode) const + { + DEFINE_INVOKER(CD2DContext::GetClip); + return INVOKE_MEMBERFUNCTION(owner, clipRect, mode); + } }; struct IDeviceTarget; struct IDeviceSurface @@ -361,15 +366,12 @@ namespace OpenGlass::dwmcore } HRESULT GetD2DBitmap(ID2D1Bitmap1** bitmap) const { - auto deviceTarget{ GetDeviceTarget() }; - auto deviceSurface - { - reinterpret_cast( - reinterpret_cast(deviceTarget) + - *reinterpret_cast(reinterpret_cast(deviceTarget)[1] + 16) + - 8ull - ) - }; + auto deviceTarget = GetDeviceTarget(); + auto deviceSurface = reinterpret_cast( + reinterpret_cast(deviceTarget) + + *reinterpret_cast(reinterpret_cast(deviceTarget)[1] + 16) + + 8ull + ); return deviceSurface->GetD2DBitmap(bitmap, false); } @@ -476,7 +478,6 @@ namespace OpenGlass::dwmcore { DEFINE_INVOKER(CDrawingContext::GetCurrentVisual); return INVOKE_MEMBERFUNCTION(); - //return std::invoke(s_fn_ptr, (CDrawingContext*)(__int64(this) + 0x18) ); } bool STDMETHODCALLTYPE IsInLayer() const { @@ -553,8 +554,17 @@ namespace OpenGlass::dwmcore return INVOKE_FUNCTION(value, mode); } + namespace CCommonRegistryData + { + inline PULONG m_dwOverlayTestMode{ nullptr }; + } + inline bool OnSymbolParsing(std::string_view functionName, std::string_view fullyUnDecoratedFunctionName, const HookHelper::OffsetStorage& offset, const PSYMBOL_INFO /*originalSymInfo*/) { + if (fullyUnDecoratedFunctionName == "CCommonRegistryData::m_dwOverlayTestMode") + { + offset.To(g_moduleHandle, CCommonRegistryData::m_dwOverlayTestMode); + } if ( fullyUnDecoratedFunctionName.starts_with("CArrayBasedCoverageSet::") || fullyUnDecoratedFunctionName.starts_with("CZOrderedRect::") || @@ -573,6 +583,7 @@ namespace OpenGlass::dwmcore fullyUnDecoratedFunctionName == "CDirtyRegion::SetFullDirty" || fullyUnDecoratedFunctionName == "CDirtyRegion::_Add" || fullyUnDecoratedFunctionName == "CVisual::GetHwnd" || + fullyUnDecoratedFunctionName == "CD2DContext::GetClip" || ( fullyUnDecoratedFunctionName.starts_with("CDrawingContext::") && fullyUnDecoratedFunctionName != "CDrawingContext::IsOccluded" diff --git a/OpenGlass/framework.hpp b/OpenGlass/framework.hpp index 33b46fa..84c5a34 100644 --- a/OpenGlass/framework.hpp +++ b/OpenGlass/framework.hpp @@ -63,6 +63,4 @@ #pragma comment(lib, "dwrite.lib") #pragma comment(lib, "dxguid.lib") -#pragma comment(lib, "onecore.lib") - - +#pragma comment(lib, "onecore.lib") \ No newline at end of file diff --git a/OpenGlass/uDwmProjection.hpp b/OpenGlass/uDwmProjection.hpp index eb0c590..5ba31b5 100644 --- a/OpenGlass/uDwmProjection.hpp +++ b/OpenGlass/uDwmProjection.hpp @@ -13,7 +13,7 @@ namespace OpenGlass::uDwm template FORCEINLINE T GetAddressFromSymbolMap(std::string_view functionName) { - auto it{ g_symbolMap.find(std::string{ functionName }) }; + auto it = g_symbolMap.find(std::string{ functionName }); return it != g_symbolMap.end() ? Utils::cast_pointer(it->second) : nullptr; } template @@ -36,7 +36,7 @@ namespace OpenGlass::uDwm { [[nodiscard]] void* operator new(size_t size) noexcept(false) { - auto memory{ HeapAlloc(OpenGlass::Utils::g_processHeap, 0, size) }; + auto memory = HeapAlloc(OpenGlass::Utils::g_processHeap, 0, size); THROW_LAST_ERROR_IF_NULL(memory); return memory; } @@ -52,7 +52,7 @@ namespace OpenGlass::uDwm } size_t Release() { - auto result{ InterlockedDecrement(reinterpret_cast(this) + 2) }; + auto result = InterlockedDecrement(reinterpret_cast(this) + 2); if (!result) { delete this; @@ -305,7 +305,7 @@ namespace OpenGlass::uDwm STDMETHOD(DrawTileImage)(UINT imageHandleTableIndex, const D2D1_RECT_F& rect, float opacity, const D2D1_POINT_2F& point) PURE; STDMETHOD(DrawVisual)(UINT visualHandleTableIndex) PURE; STDMETHOD(Pop)() PURE; - STDMETHOD(PushTransform)(UINT transformHandleTableInfex) PURE; + STDMETHOD(PushTransform)(UINT transformHandleTableIndex) PURE; STDMETHOD(DrawSolidRectangle)(const D2D1_RECT_F& rect, const D2D1_COLOR_F& color) PURE; }; struct CRenderDataInstruction : CResource @@ -438,11 +438,16 @@ namespace OpenGlass::uDwm struct CTopLevelWindow; struct CWindowData : CBaseObject { - bool STDMETHODCALLTYPE IsWindowVisibleAndUncloaked() + bool STDMETHODCALLTYPE IsWindowVisibleAndUncloaked() const { DEFINE_INVOKER(CWindowData::IsWindowVisibleAndUncloaked); return INVOKE_MEMBERFUNCTION(); } + HRESULT STDMETHODCALLTYPE GetWindowRestoreRect(LPRECT lprc, bool unknown) + { + DEFINE_INVOKER(CWindowData::GetWindowRestoreRect); + return INVOKE_MEMBERFUNCTION(lprc, unknown); + } ULONG_PTR GetDesktopID() const { ULONG_PTR desktopID{ 0 }; @@ -623,7 +628,7 @@ namespace OpenGlass::uDwm } else { - auto legacyBackgroundVisual{ reinterpret_cast(this)[39] }; + auto legacyBackgroundVisual = reinterpret_cast(this)[39]; if (legacyBackgroundVisual) { geometry = reinterpret_cast(legacyBackgroundVisual)[40]; @@ -650,7 +655,7 @@ namespace OpenGlass::uDwm } else { - auto legacyBackgroundVisual{ reinterpret_cast(this)[39] }; + auto legacyBackgroundVisual = reinterpret_cast(this)[39]; if (legacyBackgroundVisual) { geometry = reinterpret_cast(legacyBackgroundVisual)[39]; @@ -659,6 +664,17 @@ namespace OpenGlass::uDwm return geometry; } + CSolidColorLegacyMilBrushProxy* GetClientBlurVisualBrush() const + { + CSolidColorLegacyMilBrushProxy* brush{ nullptr }; + + if (os::buildNumber < os::build_w11_21h2) + { + brush = reinterpret_cast(this)[96]; + } + + return brush; + } void GetBorderMargins(MARGINS* margins) const { DEFINE_INVOKER(CTopLevelWindow::GetBorderMargins); @@ -1068,6 +1084,11 @@ namespace OpenGlass::uDwm DEFINE_INVOKER(CWindowList::GetSyncedWindowDataByHwnd); return INVOKE_MEMBERFUNCTION(hwnd, windowData); } + CWindowData* STDMETHODCALLTYPE FindWindowDataByHwnd(HWND hwnd) + { + DEFINE_INVOKER(CWindowList::FindWindowDataByHwnd); + return INVOKE_MEMBERFUNCTION(hwnd); + } }; struct CCompositor @@ -1199,11 +1220,6 @@ namespace OpenGlass::uDwm return interopDevice; } - HTHEME __fastcall GetTheme(int a1) - { - DEFINE_INVOKER(CDesktopManager::GetTheme); - return INVOKE_MEMBERFUNCTION(a1); - } }; FORCEINLINE HWND GetShellWindowForCurrentDesktop() { @@ -1244,6 +1260,7 @@ namespace OpenGlass::uDwm fullyUnDecoratedFunctionName.starts_with("CAccent::") || fullyUnDecoratedFunctionName == "CWindowList::UpdateAccentBlurRect" || fullyUnDecoratedFunctionName == "CWindowList::GetSyncedWindowDataByHwnd" || + fullyUnDecoratedFunctionName == "CWindowList::FindWindowDataByHwnd" || fullyUnDecoratedFunctionName == "CWindowList::GetWindowListForDesktop" || fullyUnDecoratedFunctionName == "CWindowList::GetRootVisualForDesktop" || fullyUnDecoratedFunctionName == "CWindowList::GetShellWindowForDesktop" || diff --git a/README.md b/README.md index 29cae0e..507fb1c 100644 --- a/README.md +++ b/README.md @@ -29,6 +29,8 @@ This branch does not rely on `dcomp` and `Windows.UI.Composition` and instead us ## Documentation The legacy branch can use most of the features of the master branch. The following table lists the difference with master branch. The legacy branch uses the colors stored by `CTopLevelWindow`, so you can change the color settings using AWM without problems. +> [!NOTE] +> Starting from 1.2, if the GlassType is 0x1, then it will use the value of `ColorizationColor`, `ColorizationAfterglow`, `ColorizationBlurBalance`. - `Not implemented` means that this feature has not yet been implemented but is possible in the future. - `Not supported` means that this feature is impossible to be implemented in current structure. @@ -36,20 +38,20 @@ The legacy branch can use most of the features of the master branch. The followi | master branch | Type | Description | legacy branch | Description | Remarks | ---- | ---- | ---- | ---- | ---- | ---- | | RoundRectRadius | DWORD | The radius of glass geometry, Win8 = 0, Win7 = 12 | | Rounded corners are not anti-aliased. | **OK** | -| og_ColorizationColorBalance | DWORD | Controls the balance of the solid color layer. Behaves the same as Windows 7. | | **NOTE FOR og_ VARIANTS:** This is done so Windows doesn't override these values with bogus ones. | **OK** | -| og_ColorizationAfterglowBalance | DWORD | Controls the balance of the multiply+blur layer. Behaves the same as Windows 7. | | | **OK** | -| og_ColorizationrBlurBalance | DWORD | Controls the balance of the blur layer. Behaves the same as Windows 7. | | | **OK** | +| | DWORD | **Not supported** | ColorizationBlurBalanceOverride | Override the value of `ColorizationBlurBalance`. | **OK** | +| | DWORD | **Not supported** | ColorizationColorOverride | Override the value of `ColorizationColor`. | **OK** | +| | DWORD | **Not supported** | ColorizationAfterglowOverride | Override the value of `ColorizationAfterglow`. | **OK** | | CustomThemeMaterial | String | **Undocumented** | | | **Not implemented** | | MaterialOpacity | DWORD | **Undocumented** | | | **Not implemented** | | GlassLuminosity | DWORD | The luminosity of Acrylic/Mica effect | | | **Not implemented** | -| GlassOpacity | DWORD | Controls the opacity of the glass colorization | | ***TODO:** deprecate this registry key for GlassType 0x1 and introduce an inactive variant for GlassType 0x0 (Vista style) | **OK*** | +| GlassOpacity | DWORD | Controls the opacity of the glass colorization | | This registry item is only used when `GlassType` is 0x0, otherwise `Colorization***` will be used. | **OK*** | | GlassType | DWORD | The type of backdrop effect (0x0-0x4). 0x0=Blur. 0x01=Aero. 0x02=Acrylic. 0x03=Mica. 0x04=Solid. | | Only 0x0 and 0x1 are implemented. | **OK** | | GlassOverrideBorder | DWORD | Specifies that the effect should extend to the border. The default value is 0. | | The glass will override the border by default. | **Not implemented** | | GlassCrossFadeTime | DWORD | The cross fade time for backdrop switching. The default value is 87. | | | **Not supported** | | GlassOverrideAccent | DWORD | Overriding accent with the effect of OpenGlass. The default value is 0. | | Some windows are overwritten resulting in full transparency. And the behavior of the overrides makes a difference. | **OK** | | GlassAdditionalPreScaleAmount | DWORD | Additional prescaling factor for backdrop input image, the smaller the value the more significant the performance improvement, the lower the quality of the glass. The default value is 90% for Windows 10 but 95% for Windows 11. | | | **Not implemented** | -| ForceAccentColorization | DWORD | When this option is on, OpenGlass will always uses the colors from `AccentColor` and `AccentColorInactive`, which will ignore all the system settings related to color. You can turn it on when there exists third-party softwares that break the auto-coloring. | | | **Not implemented** | | GlassCrossFadeEasingFunction | DWORD | The easing function for cross fade animation. 0x0=Linear. 0x1=CubicBezier. The Default value is 0. | | | **Not supported** | +| | DWORD | **Not supported** | EnableGeometryMerging | Merge multiple blurred regions into one. The default value is 0.

**!!! THIS OPTION IS VERY DANGEROUS, IT HAS A SIGNIFICANT NEGATIVE IMPACT ON PERFORMANCE, USE IT AT YOUR OWN RISK !!!** | **OK** | > [!TIP] > Check out the code to discover more details!