mirror of
https://github.com/glfw/glfw.git
synced 2026-09-21 16:44:11 +00:00
Win32: Disable fb transparency when it is broken
On Windows 7, when GLFW framebuffer transparency and the DWM are enabled
but DWM transparency is disabled (i.e. when the Transparency setting is
disabled under Personalization > Color), the contents of the framebuffer
is combined with the last frame using additive blending instead of
replacing the previous contents.
This commit limits GLFW framebuffer transparency on Windows 7 to when
DWM transparency is enabled, removing the previous workaround of setting
a layered window color key that led to rendering artifacts.
Fixes #1512.
(cherry picked from commit 05dd2fa298)
This commit is contained in:
+32
-31
@@ -377,12 +377,17 @@ static void updateWindowStyles(const _GLFWwindow* window)
|
||||
//
|
||||
static void updateFramebufferTransparency(const _GLFWwindow* window)
|
||||
{
|
||||
BOOL enabled;
|
||||
BOOL composition, opaque;
|
||||
DWORD color;
|
||||
|
||||
if (!IsWindowsVistaOrGreater())
|
||||
return;
|
||||
|
||||
if (SUCCEEDED(DwmIsCompositionEnabled(&enabled)) && enabled)
|
||||
if (FAILED(DwmIsCompositionEnabled(&composition)) || !composition)
|
||||
return;
|
||||
|
||||
if (IsWindows8OrGreater() ||
|
||||
(SUCCEEDED(DwmGetColorizationColor(&color, &opaque)) && !opaque))
|
||||
{
|
||||
HRGN region = CreateRectRgn(0, 0, -1, -1);
|
||||
DWM_BLURBEHIND bb = {0};
|
||||
@@ -390,37 +395,18 @@ static void updateFramebufferTransparency(const _GLFWwindow* window)
|
||||
bb.hRgnBlur = region;
|
||||
bb.fEnable = TRUE;
|
||||
|
||||
if (SUCCEEDED(DwmEnableBlurBehindWindow(window->win32.handle, &bb)))
|
||||
{
|
||||
// Decorated windows don't repaint the transparent background
|
||||
// leaving a trail behind animations
|
||||
// HACK: Making the window layered with a transparency color key
|
||||
// seems to fix this. Normally, when specifying
|
||||
// a transparency color key to be used when composing the
|
||||
// layered window, all pixels painted by the window in this
|
||||
// color will be transparent. That doesn't seem to be the
|
||||
// case anymore, at least when used with blur behind window
|
||||
// plus negative region.
|
||||
LONG exStyle = GetWindowLongW(window->win32.handle, GWL_EXSTYLE);
|
||||
exStyle |= WS_EX_LAYERED;
|
||||
SetWindowLongW(window->win32.handle, GWL_EXSTYLE, exStyle);
|
||||
|
||||
// Using a color key not equal to black to fix the trailing
|
||||
// issue. When set to black, something is making the hit test
|
||||
// not resize with the window frame.
|
||||
SetLayeredWindowAttributes(window->win32.handle,
|
||||
RGB(255, 0, 255), 255, LWA_COLORKEY);
|
||||
}
|
||||
|
||||
DwmEnableBlurBehindWindow(window->win32.handle, &bb);
|
||||
DeleteObject(region);
|
||||
}
|
||||
else
|
||||
{
|
||||
LONG exStyle = GetWindowLongW(window->win32.handle, GWL_EXSTYLE);
|
||||
exStyle &= ~WS_EX_LAYERED;
|
||||
SetWindowLongW(window->win32.handle, GWL_EXSTYLE, exStyle);
|
||||
RedrawWindow(window->win32.handle, NULL, NULL,
|
||||
RDW_ERASE | RDW_INVALIDATE | RDW_FRAME);
|
||||
// HACK: Disable framebuffer transparency on Windows 7 when the
|
||||
// colorization color is opaque, because otherwise the window
|
||||
// contents is blended additively with the previous frame instead
|
||||
// of replacing it
|
||||
DWM_BLURBEHIND bb = {0};
|
||||
bb.dwFlags = DWM_BB_ENABLE;
|
||||
DwmEnableBlurBehindWindow(window->win32.handle, &bb);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1097,6 +1083,7 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
|
||||
}
|
||||
|
||||
case WM_DWMCOMPOSITIONCHANGED:
|
||||
case WM_DWMCOLORIZATIONCOLORCHANGED:
|
||||
{
|
||||
if (window->win32.transparent)
|
||||
updateFramebufferTransparency(window);
|
||||
@@ -1821,7 +1808,8 @@ int _glfwPlatformWindowHovered(_GLFWwindow* window)
|
||||
|
||||
int _glfwPlatformFramebufferTransparent(_GLFWwindow* window)
|
||||
{
|
||||
BOOL enabled;
|
||||
BOOL composition, opaque;
|
||||
DWORD color;
|
||||
|
||||
if (!window->win32.transparent)
|
||||
return GLFW_FALSE;
|
||||
@@ -1829,7 +1817,20 @@ int _glfwPlatformFramebufferTransparent(_GLFWwindow* window)
|
||||
if (!IsWindowsVistaOrGreater())
|
||||
return GLFW_FALSE;
|
||||
|
||||
return SUCCEEDED(DwmIsCompositionEnabled(&enabled)) && enabled;
|
||||
if (FAILED(DwmIsCompositionEnabled(&composition)) || !composition)
|
||||
return GLFW_FALSE;
|
||||
|
||||
if (!IsWindows8OrGreater())
|
||||
{
|
||||
// HACK: Disable framebuffer transparency on Windows 7 when the
|
||||
// colorization color is opaque, because otherwise the window
|
||||
// contents is blended additively with the previous frame instead
|
||||
// of replacing it
|
||||
if (FAILED(DwmGetColorizationColor(&color, &opaque)) || opaque)
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
|
||||
void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled)
|
||||
|
||||
Reference in New Issue
Block a user