|
|
|
@ -83,6 +83,20 @@ static int choosePixelFormat(_GLFWwindow* window, |
|
|
|
|
{ |
|
|
|
|
const int n = i + 1; |
|
|
|
|
_GLFWfbconfig* u = usableConfigs + usableCount; |
|
|
|
|
PIXELFORMATDESCRIPTOR pfd; |
|
|
|
|
|
|
|
|
|
if (window->transparent) { |
|
|
|
|
if (!DescribePixelFormat(window->context.wgl.dc, |
|
|
|
|
n, |
|
|
|
|
sizeof(PIXELFORMATDESCRIPTOR), |
|
|
|
|
&pfd)) |
|
|
|
|
{ |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (!(pfd.dwFlags & PFD_SUPPORT_COMPOSITION)) |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (_glfw.wgl.ARB_pixel_format) |
|
|
|
|
{ |
|
|
|
@ -152,11 +166,9 @@ static int choosePixelFormat(_GLFWwindow* window, |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
{ |
|
|
|
|
PIXELFORMATDESCRIPTOR pfd; |
|
|
|
|
|
|
|
|
|
// Get pixel format attributes through legacy PFDs
|
|
|
|
|
|
|
|
|
|
if (!DescribePixelFormat(window->context.wgl.dc, |
|
|
|
|
if (!window->transparent && DescribePixelFormat(window->context.wgl.dc, |
|
|
|
|
n, |
|
|
|
|
sizeof(PIXELFORMATDESCRIPTOR), |
|
|
|
|
&pfd)) |
|
|
|
@ -203,6 +215,15 @@ static int choosePixelFormat(_GLFWwindow* window, |
|
|
|
|
u->handle = n; |
|
|
|
|
usableCount++; |
|
|
|
|
} |
|
|
|
|
// Reiterate the selection loop without looking for transparency supporting
|
|
|
|
|
// formats if no matching pixelformat for a transparent window were found.
|
|
|
|
|
if (window->transparent && !usableCount) { |
|
|
|
|
window->transparent = GLFW_FALSE; |
|
|
|
|
free(usableConfigs); |
|
|
|
|
_glfwInputError(GLFW_PLATFORM_ERROR, |
|
|
|
|
"WGL: No pixel format found for transparent window. Ignoring transparency."); |
|
|
|
|
return choosePixelFormat(window, ctxconfig, fbconfig); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (!usableCount) |
|
|
|
|
{ |
|
|
|
@ -484,6 +505,75 @@ void _glfwTerminateWGL(void) |
|
|
|
|
attribs[index++] = v; \
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static GLFWbool setupTransparentWindow(_GLFWwindow* window) |
|
|
|
|
{ |
|
|
|
|
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; |
|
|
|
|
HWND handle = window->win32.handle; |
|
|
|
|
|
|
|
|
|
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 (window->decorated && 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
|
|
|
|
|
//
|
|
|
|
|
GLFWbool _glfwCreateContextWGL(_GLFWwindow* window, |
|
|
|
@ -713,6 +803,12 @@ GLFWbool _glfwCreateContextWGL(_GLFWwindow* window, |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (window->transparent) |
|
|
|
|
{ |
|
|
|
|
if (!setupTransparentWindow(window)) |
|
|
|
|
window->transparent = GLFW_FALSE; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
window->context.makeCurrent = makeContextCurrentWGL; |
|
|
|
|
window->context.swapBuffers = swapBuffersWGL; |
|
|
|
|
window->context.swapInterval = swapIntervalWGL; |
|
|
|
|