Maplespe / DWMBlurGlass

Add custom effect to global system title bar, support win10 and win11.
GNU Lesser General Public License v3.0
2.06k stars 92 forks source link

Borders only use active color (and the inactive aero effects don't work anymore) #130

Closed kfh83 closed 9 months ago

kfh83 commented 9 months ago

image As the title says. I've already tried deleting my old config, restarting my machine and DWM itself and no change, except that it worked once after installing.

Maplespe commented 9 months ago

Are you using a custom bulr method? We can't reproduce it.

angelbruni commented 9 months ago

Using CustomBlur method. image image

kfh83 commented 9 months ago

Are you using a custom bulr method? We can't reproduce it.

Yes

image

CallyHam commented 9 months ago

this is happening to me too, inactive blend color just doesn't do anything, it's always the active color, doesn't matter what kind of blur i choose

Maplespe commented 9 months ago

What software do you guys use besides StartIsBack? We've tested fresh installs of Windows 10 21H2 and 22H2 and neither of them can reproduce the problem. No issues with StartIsBack + 3rd party themes either.

kfh83 commented 9 months ago

What software do you guys use besides StartIsBack? We've tested fresh installs of Windows 10 21H2 and 22H2 and neither of them can reproduce the problem. No issues with StartIsBack + 3rd party themes either.

I'm on 21H2 and at the time i took the screenshot i hadn't installed StartIsBack yet, although still happens with it.

Maplespe commented 9 months ago

Release_x64.zip Please try this version, as I'm not sure then what other software is being used, I can only undo some of the changes first to confirm what's causing it.

angelbruni commented 9 months ago

I can confirm this seems to fix the issue. image

kfh83 commented 9 months ago

Issue is fixed. image

ALTaleX531 commented 9 months ago

However this is not good news because it means that some software you have installed broke DwmBlurGlass and we need to know exactly which one. 🤔

kfh83 commented 9 months ago

However this is not good news because it means that some software you have installed broke DwmBlurGlass and we need to know exactly which one. 🤔

I didn't install anything from trying the original 2.0.1 binaries and the ones uploaded just now.

ALTaleX531 commented 9 months ago

This is not possible, you may have installed some windhawk mods, or perhaps a udwm patch, or something else, because DwmBlurGlass works normally on a fresh install of Windows.

kfh83 commented 9 months ago

I just reverted it and tested it without any windhawk mods or patches (i don't patch uDWM anyways) and the issue still happens.

This is not possible, you may have installed some windhawk mods, or perhaps a udwm patch, or something else, because DwmBlurGlass works normally on a fresh install of Windows.

kfh83 commented 9 months ago

Oh nevermind, it seems like it's the caption button restorer mod on windhawk. I restarted DWM and the issue wouldn't happen, then i opened windhawk with the mod enabled and it did break the inactive colors @angelbruni

But why did it work before?

ALTaleX531 commented 9 months ago

DwmBlurGlass used to read memory directly from a specific address, however this is a dangerous behavior and leads to poor compatibility.

angelbruni commented 9 months ago

After inspecting the Windhawk mod, I've concluded that the problem is caused by the TreatAsActiveWindow hook. The Windhawk mod does bool CTopLevelWindow_TreatAsActiveWindow_Hook(void) { return TRUE; }; in order to keep the inactive buttons not faded, like Windows 7. With the hook: image Without the hook: image If a similar thing could be implemented in DWMBlurGlass it would be nice.

Maplespe commented 9 months ago

Where is this module released?

Maplespe commented 9 months ago

Previously, we accessed the active state of a window by hard-coding its memory address; in the recent update we switched to using the TreatAsActiveWindow function directly so this caused this issue. Before 224320 After 224355

But this reduces maintainability and compatibility, that's why we made the adjustment.

ALTaleX531 commented 9 months ago

Looks like we'll have to emulate TreatAsActiveWindow's behavior in every Windows version from now on, sadly!

angelbruni commented 9 months ago

I am sorry, I've copied the wrong code. Edited my comment (15 minutes ago). Unfortunately it has not been released and it's not ours either. I can give you only part of the mod that does the TreatAsActiveWindow behaviour.

bool (*CTopLevelWindow_TreatAsActiveWindow_Original)(void);

bool CTopLevelWindow_TreatAsActiveWindow_Hook(void) {
    return TRUE;
}

BOOL Wh_ModInit(void) {
    HMODULE uDWM = GetModuleHandle(L"uDWM.dll");
    if (!uDWM)
        return FALSE;

    WH_FIND_SYMBOL findSymbol;
    HANDLE findSymbolHandle = Wh_FindFirstSymbol(uDWM, nullptr, &findSymbol);
    if (!findSymbolHandle) {
        Wh_Log(L"Wh_FindFirstSymbol failed");
        return FALSE;
    }

    void* TreatAsActiveWindowAddr = nullptr;

    do {
        if (_wcsicmp(findSymbol.symbol,
                     L"private: bool __cdecl "
                     L"CTopLevelWindow::TreatAsActiveWindow(void)") == 0) {
            TreatAsActiveWindowAddr = findSymbol.address;
            Wh_Log(L"symbol: %s, Addr: %i", findSymbol.symbol,
                   findSymbol.address);
        }
    } while (Wh_FindNextSymbol(findSymbolHandle, &findSymbol));

    Wh_SetFunctionHook(TreatAsActiveWindowAddr,
                       (void*)CTopLevelWindow_TreatAsActiveWindow_Hook,
                       (void**)&CTopLevelWindow_TreatAsActiveWindow_Original);
    return TRUE;
}

TreatAsActiveWindow is a behaviour in every Windows version from now on, but is there an alternative to disable the fading? Maybe finding the value that sets the opacity/alpha?

Maplespe commented 9 months ago

Did @dulappy write this?

angelbruni commented 9 months ago

Yes. This a small portion of the pre-pre-pre-pre-pre-alpha of the final code (which is probably very different and that we don't have access to), so it could be doomed to break soon (like it is with the usage of DWMBlurGlass in this specific occasion).

Olivia6841 commented 9 months ago

Did @Dulappy write this?

Yes

Edit : I would like to retract my statement and return to just observing the conversation :)

ALTaleX531 commented 9 months ago

I think it's possible to patch the CTopLevelWindow::UpdateButtonVisuals call to CTopLevelWindow::TreatAsActiveWindow, and modifying the offset corresponding to 0xE8 should work. image Here's a sample code.

class TrampolinePool
{
public:
    UCHAR* Allocate(PVOID detourFunction)
    {
        if (!m_buffer)
        {
            return nullptr;
        }
#ifdef _WIN64
        UCHAR jmpCode[14]{ 0xFF, 0x25 };
        memcpy_s(&jmpCode[6], sizeof(PVOID), &detourFunction, sizeof(detourFunction));
#else
        UCHAR jmpCode[]{ 0xB8, 0, 0, 0, 0, 0xFF, 0xE0, 0 };
        memcpy_s(&jmpCode[1], sizeof(PVOID), &detourFunction, sizeof(detourFunction));
#endif
        if (m_current + sizeof(jmpCode) > m_end)
        {
            return nullptr;
        }

        auto startPos{ m_current };
        memcpy(startPos, jmpCode, sizeof(jmpCode));
        m_current += sizeof(jmpCode);

        return startPos;
    }
    TrampolinePool(PVOID startAddress)
    {
        m_buffer.reset(
            static_cast<UCHAR*>(DetourAllocateRegionWithinJumpBounds(startAddress, &m_bufferSize))
        );

        m_current = m_buffer.get();
        m_end = m_current + m_bufferSize;
    }
    ~TrampolinePool() = default;
private:
    DWORD m_bufferSize{0};
    wil::unique_virtualalloc_ptr<UCHAR> m_buffer{ nullptr };
    UCHAR* m_current{ nullptr }, * m_end{ nullptr };
};
LONG ReplaceE8Call(LONG* callOffset, PVOID trampolineAddress)
{
    auto callBaseAddress{ reinterpret_cast<UCHAR*>(reinterpret_cast<DWORD64>(callOffset) + sizeof(LONG)) };
    auto originalOffset{ *callOffset };
    HookHelper::WriteMemory(callOffset, [&]
    {
        *callOffset = static_cast<LONG>(reinterpret_cast<UCHAR*>(trampolineAddress) - callBaseAddress);
    });
    return originalOffset;
}

Please relay this to Dulappy if you can, we don't want to simulate the behavior of TreatAsActiveWindow.

angelbruni commented 9 months ago

Good luck with getting it to work! I was simply inspecting the code. Unfortunately, I have no coding expertise but thought I should help in any way I can.

Xdmg01 commented 9 months ago

There is also CButton::UpdateCurrentGlyphOpacity Screenshot_20240208_224213

This simple Windhawk mod always sets the glyph opacity to 1, tested on windows 21H2 LTSC

// ==WindhawkMod==
// @id              inactive-button-opacity
// @name            Inactive Button Opacity
// @version         0.1
// @include         dwm.exe
// ==/WindhawkMod==

#include <windhawk_utils.h>

bool (__thiscall *CButton__UpdateCurrentGlyphOpacity_orig)(void *, bool);
bool __thiscall CButton__UpdateCurrentGlyphOpacity_hook(void *pThis, bool param_1) {
    *((float *)pThis + 101) = 1.0;
    return CButton__UpdateCurrentGlyphOpacity_orig(pThis, param_1);
}

BOOL Wh_ModInit() {
    Wh_Log(L"Init");

    HMODULE uDWM = LoadLibraryW(L"uDWM.dll");

    if (!uDWM) {
        Wh_Log(L"Failed to load uDWM.dll");
        return FALSE;
    }

    WindhawkUtils::SYMBOL_HOOK symbolHook[] = {
        {
            {L"private: void __cdecl CButton::UpdateCurrentGlyphOpacity(bool)"},
            (void**)&CButton__UpdateCurrentGlyphOpacity_orig,
            (void*)CButton__UpdateCurrentGlyphOpacity_hook,
        },
    };

    if (!WindhawkUtils::HookSymbols(uDWM, symbolHook, 1)) {
        Wh_Log(L"Error hooking");
        return FALSE;
    }
    return TRUE;
}
Maplespe commented 9 months ago

Now that you have a solution, I will close it.