diff --git a/README.md b/README.md index 00d7804b..0e0aafe8 100644 --- a/README.md +++ b/README.md @@ -120,6 +120,8 @@ information on what to include when reporting a bug. - Bugfix: Some extension loader headers did not prevent default OpenGL header inclusion (#1695) + - [Win32] Disabled framebuffer transparency on Windows 7 when DWM windows are + opaque (#1512) - [Win32] Bugfix: Non-BMP Unicode codepoint input was reported as UTF-16 - [Cocoa] Changed `EGLNativeWindowType` from `NSView` to `CALayer` (#1169) - [Cocoa] Bugfix: Non-BMP Unicode codepoint input was reported as UTF-16 diff --git a/docs/news.dox b/docs/news.dox index da97215c..c21a8b8a 100644 --- a/docs/news.dox +++ b/docs/news.dox @@ -299,6 +299,13 @@ a requirement of the GLFW CMake files. The GLFW source files do not depend on CMake. +@subsubsection caveat_fbtransparency_33 Framebuffer transparency requires DWM transparency + +GLFW no longer supports framebuffer transparency enabled via @ref +GLFW_TRANSPARENT_FRAMEBUFFER on Windows 7 if DWM transparency is off +(the Transparency setting under Personalization > Window Color). + + @subsection deprecations_33 Deprecations in version 3.3 @subsubsection charmods_callback_33 Character with modifiers callback diff --git a/docs/window.dox b/docs/window.dox index 8eb0df06..ce851737 100644 --- a/docs/window.dox +++ b/docs/window.dox @@ -234,13 +234,6 @@ alpha channel will be used to combine the framebuffer with the background. This does not affect window decorations. Possible values are `GLFW_TRUE` and `GLFW_FALSE`. -@par -@win32 GLFW sets a color key for the window to work around repainting issues -with a transparent framebuffer. The chosen color value is RGB 255,0,255 -(magenta). This will make pixels with that exact color fully transparent -regardless of their alpha values. If this is a problem, make these pixels any -other color before buffer swap. - @anchor GLFW_FOCUS_ON_SHOW_hint __GLFW_FOCUS_ON_SHOW__ specifies whether the window will be given input focus when @ref glfwShowWindow is called. Possible values are `GLFW_TRUE` and `GLFW_FALSE`. diff --git a/src/win32_init.c b/src/win32_init.c index b2aa0a3d..a7a6be6a 100644 --- a/src/win32_init.c +++ b/src/win32_init.c @@ -143,6 +143,8 @@ static GLFWbool loadLibraries(void) GetProcAddress(_glfw.win32.dwmapi.instance, "DwmFlush"); _glfw.win32.dwmapi.EnableBlurBehindWindow = (PFN_DwmEnableBlurBehindWindow) GetProcAddress(_glfw.win32.dwmapi.instance, "DwmEnableBlurBehindWindow"); + _glfw.win32.dwmapi.GetColorizationColor = (PFN_DwmGetColorizationColor) + GetProcAddress(_glfw.win32.dwmapi.instance, "DwmGetColorizationColor"); } _glfw.win32.shcore.instance = LoadLibraryA("shcore.dll"); diff --git a/src/win32_platform.h b/src/win32_platform.h index 426c0efc..a8db3070 100644 --- a/src/win32_platform.h +++ b/src/win32_platform.h @@ -77,6 +77,9 @@ #ifndef WM_DWMCOMPOSITIONCHANGED #define WM_DWMCOMPOSITIONCHANGED 0x031E #endif +#ifndef WM_DWMCOLORIZATIONCOLORCHANGED + #define WM_DWMCOLORIZATIONCOLORCHANGED 0x0320 +#endif #ifndef WM_COPYGLOBALDATA #define WM_COPYGLOBALDATA 0x0049 #endif @@ -247,9 +250,11 @@ typedef BOOL (WINAPI * PFN_AdjustWindowRectExForDpi)(LPRECT,DWORD,BOOL,DWORD,UIN typedef HRESULT (WINAPI * PFN_DwmIsCompositionEnabled)(BOOL*); typedef HRESULT (WINAPI * PFN_DwmFlush)(VOID); typedef HRESULT(WINAPI * PFN_DwmEnableBlurBehindWindow)(HWND,const DWM_BLURBEHIND*); +typedef HRESULT (WINAPI * PFN_DwmGetColorizationColor)(DWORD*,BOOL*); #define DwmIsCompositionEnabled _glfw.win32.dwmapi.IsCompositionEnabled #define DwmFlush _glfw.win32.dwmapi.Flush #define DwmEnableBlurBehindWindow _glfw.win32.dwmapi.EnableBlurBehindWindow +#define DwmGetColorizationColor _glfw.win32.dwmapi.GetColorizationColor // shcore.dll function pointer typedefs typedef HRESULT (WINAPI * PFN_SetProcessDpiAwareness)(PROCESS_DPI_AWARENESS); @@ -375,6 +380,7 @@ typedef struct _GLFWlibraryWin32 PFN_DwmIsCompositionEnabled IsCompositionEnabled; PFN_DwmFlush Flush; PFN_DwmEnableBlurBehindWindow EnableBlurBehindWindow; + PFN_DwmGetColorizationColor GetColorizationColor; } dwmapi; struct { diff --git a/src/win32_window.c b/src/win32_window.c index b19f6c61..f76f560f 100644 --- a/src/win32_window.c +++ b/src/win32_window.c @@ -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)