mirror of
https://github.com/glfw/glfw.git
synced 2025-10-04 13:46:37 +00:00
Fix win8+ transparent area not repainting
This commit is contained in:
parent
fe81dd9899
commit
4ccda807aa
@ -298,10 +298,17 @@ static void init(void)
|
|||||||
glEnable(GL_NORMALIZE);
|
glEnable(GL_NORMALIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GLFWerrorfun ErrorFun(int i, const char* str) {
|
||||||
|
char buf[255];
|
||||||
|
sprintf(buf, "%d: %s", i, str);
|
||||||
|
MessageBoxA(0, buf, "Error", MB_ICONERROR | MB_OK);
|
||||||
|
}
|
||||||
|
|
||||||
/* program entry */
|
/* program entry */
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
|
glfwSetErrorCallback(ErrorFun);
|
||||||
|
|
||||||
GLFWwindow* window;
|
GLFWwindow* window;
|
||||||
int width, height;
|
int width, height;
|
||||||
|
|
||||||
@ -314,7 +321,7 @@ int main(int argc, char *argv[])
|
|||||||
glfwWindowHint(GLFW_DEPTH_BITS, 16);
|
glfwWindowHint(GLFW_DEPTH_BITS, 16);
|
||||||
glfwWindowHint(GLFW_ALPHA_BITS, 8);
|
glfwWindowHint(GLFW_ALPHA_BITS, 8);
|
||||||
glfwWindowHint(GLFW_TRANSPARENT, GLFW_TRUE);
|
glfwWindowHint(GLFW_TRANSPARENT, GLFW_TRUE);
|
||||||
glfwWindowHint(GLFW_DECORATED, GLFW_FALSE);
|
glfwWindowHint(GLFW_DECORATED, GLFW_TRUE);
|
||||||
|
|
||||||
window = glfwCreateWindow( 300, 300, "Gears", NULL, NULL );
|
window = glfwCreateWindow( 300, 300, "Gears", NULL, NULL );
|
||||||
if (!window)
|
if (!window)
|
||||||
|
@ -256,6 +256,8 @@ static GLFWbool choosePixelFormat(_GLFWwindow* window,
|
|||||||
if (window->transparent && !usableCount) {
|
if (window->transparent && !usableCount) {
|
||||||
window->transparent = GLFW_FALSE;
|
window->transparent = GLFW_FALSE;
|
||||||
free(usableConfigs);
|
free(usableConfigs);
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
|
"WGL: No pixel format found for transparent window. Ignoring transparency.");
|
||||||
return choosePixelFormat(window, desired, result);
|
return choosePixelFormat(window, desired, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -344,6 +346,96 @@ void _glfwTerminateWGL(void)
|
|||||||
assert((size_t) index < sizeof(attribs) / sizeof(attribs[0])); \
|
assert((size_t) index < sizeof(attribs) / sizeof(attribs[0])); \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Reliably check windows version as done in VersionHelpers.h
|
||||||
|
// needed for transparent window
|
||||||
|
static inline GLFWbool
|
||||||
|
isWindowsVersionOrGreater(WORD wMajorVersion, WORD wMinorVersion, WORD wServicePackMajor)
|
||||||
|
{
|
||||||
|
OSVERSIONINFOEXW osvi = { sizeof(osvi), 0, 0, 0, 0,{ 0 }, 0, 0 };
|
||||||
|
DWORDLONG const dwlConditionMask = VerSetConditionMask(
|
||||||
|
VerSetConditionMask(
|
||||||
|
VerSetConditionMask(
|
||||||
|
0, VER_MAJORVERSION, VER_GREATER_EQUAL),
|
||||||
|
VER_MINORVERSION, VER_GREATER_EQUAL),
|
||||||
|
VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL);
|
||||||
|
|
||||||
|
osvi.dwMajorVersion = wMajorVersion;
|
||||||
|
osvi.dwMinorVersion = wMinorVersion;
|
||||||
|
osvi.wServicePackMajor = wServicePackMajor;
|
||||||
|
|
||||||
|
return VerifyVersionInfoW(&osvi, VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR, dwlConditionMask) != FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GLFWbool isWindows8OrGreater() {
|
||||||
|
GLFWbool isWin8OrGreater = isWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WIN8), LOBYTE(_WIN32_WINNT_WIN8), 0) ? GLFW_TRUE: GLFW_FALSE;
|
||||||
|
return isWin8OrGreater;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GLFWbool setupTransparentWindow(HWND handle, GLFWbool isDecorated) {
|
||||||
|
if (!isCompositionEnabled) {
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
|
"WGL: Composition needed for transparent window is disabled");
|
||||||
|
}
|
||||||
|
if (!_glfw_DwmEnableBlurBehindWindow) {
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
|
"WGL: Unable to load DwmEnableBlurBehindWindow required for transparent window");
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT hr = S_OK;
|
||||||
|
|
||||||
|
DWM_BLURBEHIND bb = { 0 };
|
||||||
|
bb.dwFlags = DWM_BB_ENABLE | DWM_BB_BLURREGION;
|
||||||
|
bb.hRgnBlur = CreateRectRgn(0, 0, -1, -1); // makes the window transparent
|
||||||
|
bb.fEnable = TRUE;
|
||||||
|
hr = _glfw_DwmEnableBlurBehindWindow(handle, &bb);
|
||||||
|
|
||||||
|
if (!SUCCEEDED(hr)) {
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
|
"WGL: Failed to enable blur behind window required for transparent window");
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decorated windows on Windows 8+ 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 on Windows 8+, at least when used with
|
||||||
|
// DwmEnableBlurBehindWindow + negative region.
|
||||||
|
if (isDecorated && isWindows8OrGreater()) {
|
||||||
|
long style = GetWindowLong(handle, GWL_EXSTYLE);
|
||||||
|
if (!style) {
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
|
"WGL: Failed to retrieve extended styles. GetLastError: %d",
|
||||||
|
GetLastError());
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
style |= WS_EX_LAYERED;
|
||||||
|
if (!SetWindowLongPtr(handle, GWL_EXSTYLE, style))
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
|
"WGL: Failed to add layered style. GetLastError: %d",
|
||||||
|
GetLastError());
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
if (!SetLayeredWindowAttributes(handle,
|
||||||
|
// 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.
|
||||||
|
RGB(0, 193, 48),
|
||||||
|
255,
|
||||||
|
LWA_COLORKEY))
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
|
"WGL: Failed to set layered window. GetLastError: %d",
|
||||||
|
GetLastError());
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return GLFW_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
// Create the OpenGL or OpenGL ES context
|
// Create the OpenGL or OpenGL ES context
|
||||||
//
|
//
|
||||||
GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
|
GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
|
||||||
@ -494,25 +586,9 @@ GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (window->transparent) {
|
if (window->transparent) {
|
||||||
if (!isCompositionEnabled || !_glfw_DwmEnableBlurBehindWindow) {
|
if (!setupTransparentWindow(window->win32.handle, window->decorated)) {
|
||||||
window->transparent = GLFW_FALSE;
|
window->transparent = GLFW_FALSE;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
HRESULT hr = S_OK;
|
|
||||||
|
|
||||||
DWM_BLURBEHIND bb = { 0 };
|
|
||||||
bb.dwFlags = DWM_BB_ENABLE | DWM_BB_BLURREGION;
|
|
||||||
bb.hRgnBlur = CreateRectRgn(0, 0, -1, -1); // makes the window transparent
|
|
||||||
bb.fEnable = TRUE;
|
|
||||||
hr = _glfw_DwmEnableBlurBehindWindow(window->win32.handle, &bb);
|
|
||||||
|
|
||||||
if (!SUCCEEDED(hr)) {
|
|
||||||
window->transparent = GLFW_FALSE;
|
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
|
||||||
"WGL: Failed to enable blur behind window required for transparency");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return GLFW_TRUE;
|
return GLFW_TRUE;
|
||||||
|
Loading…
Reference in New Issue
Block a user