Commit 32e78aeb authored by Camilla Löwy's avatar Camilla Löwy
Browse files

Add GLFW_TRANSPARENT attribute and documentation

This completes support for window framebuffer transparency on Windows,
macOS and X11.  Note that the hint/attribute may be renamed before
release to clarify its relationship to GLFW_OPACITY.

Fixes #197.
Closes #1079.
Related to #663.
Related to #715.
Related to #723.
Related to #1078.
parent 93e66661
......@@ -150,6 +150,8 @@ information on what to include when reporting a bug.
functions for accessing X11 primary selection (#894,#1056)
- Added headless [OSMesa](http://mesa3d.org/osmesa.html) backend (#850)
- Added definition of `GLAPIENTRY` to public header
- Added `GLFW_TRANSPARENT` window hint for enabling window framebuffer
transparency (#197,#663,#715,#723,#1078)
- Added `GLFW_CENTER_CURSOR` window hint for controlling cursor centering
(#749,#842)
- Added `GLFW_JOYSTICK_HAT_BUTTONS` init hint (#889)
......@@ -289,6 +291,7 @@ skills.
- Yaron Cohen-Tal
- Omar Cornut
- Andrew Corrigan
- Bailey Cosier
- Noel Cower
- Jason Daly
- Jarrod Davis
......@@ -297,6 +300,7 @@ skills.
- Michael Dickens
- Роман Донченко
- Mario Dorn
- Wolfgang Draxinger
- Jonathan Dummer
- Ralph Eastwood
- Fredrik Ehnbom
......@@ -322,6 +326,7 @@ skills.
- Erik S. V. Jansson
- Toni Jovanoski
- Arseny Kapoulkine
- Cem Karan
- Osman Keskin
- Josh Kilmer
- Cameron King
......@@ -363,6 +368,7 @@ skills.
- Andri Pálsson
- Peoro
- Braden Pellett
- Christopher Pelloux
- Arturo J. Pérez
- Anthony Pesch
- Orson Peters
......
......@@ -80,6 +80,11 @@ GLFW uses the XInput2 extension to provide raw, non-accelerated mouse motion
when the cursor is disabled. If the running X server does not support this
extension, regular accelerated mouse motion will be used.
GLFW uses both the XRender extension and the compositing manager to support
transparent window framebuffers. If the running X server does not support this
extension or there is no running compositing manager, the `GLFW_TRANSPARENT`
framebuffer hint will have no effect.
@section compat_glx GLX extensions
......
......@@ -85,6 +85,13 @@ be disabled with the @ref GLFW_JOYSTICK_HAT_BUTTONS init hint.
@see @ref joystick_hat
@subsection news_33_transparent Support for transparent window framebuffer
GLFW now supports the creation of windows with transparent framebuffers on
systems with desktop compositing enabled with the @ref GLFW_TRANSPARENT window
hint and attribute. Any window decorations will still be opaque.
@subsection news_33_centercursor Cursor centering window hint
GLFW now supports controlling whether the cursor is centered over newly created
......
......@@ -225,6 +225,13 @@ __GLFW_CENTER_CURSOR__ specifies whether the cursor should be centered over
newly created full screen windows. Possible values are `GLFW_TRUE` and
`GLFW_FALSE`. This hint is ignored for windowed mode windows.
@anchor GLFW_TRANSPARENT_hint
__GLFW_TRANSPARENT__ specifies whether the window framebuffer will be
transparent. If enabled and supported by the system, the window framebuffer
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`.
@subsubsection window_hints_fb Framebuffer related hints
......@@ -287,10 +294,6 @@ __GLFW_DOUBLEBUFFER__ specifies whether the framebuffer should be double
buffered. You nearly always want to use double buffering. This is a hard
constraint. Possible values are `GLFW_TRUE` and `GLFW_FALSE`.
@anchor GLFW_TRANSPARENT_hint
__GLFW_TRANSPARENT__ specifies whether the framebuffer will support transparency
in the background. Possible values are `GLFW_TRUE` and `GLFW_FALSE`.
@subsubsection window_hints_mtr Monitor related hints
......@@ -474,6 +477,7 @@ GLFW_AUTO_ICONIFY | `GLFW_TRUE` | `GLFW_TRUE` or `GL
GLFW_FLOATING | `GLFW_FALSE` | `GLFW_TRUE` or `GLFW_FALSE`
GLFW_MAXIMIZED | `GLFW_FALSE` | `GLFW_TRUE` or `GLFW_FALSE`
GLFW_CENTER_CURSOR | `GLFW_TRUE` | `GLFW_TRUE` or `GLFW_FALSE`
GLFW_TRANSPARENT | `GLFW_FALSE` | `GLFW_TRUE` or `GLFW_FALSE`
GLFW_RED_BITS | 8 | 0 to `INT_MAX` or `GLFW_DONT_CARE`
GLFW_GREEN_BITS | 8 | 0 to `INT_MAX` or `GLFW_DONT_CARE`
GLFW_BLUE_BITS | 8 | 0 to `INT_MAX` or `GLFW_DONT_CARE`
......@@ -1065,6 +1069,30 @@ window contents are saved off-screen, this callback might only be called when
the window or framebuffer is resized.
@subsection window_transparency Window transparency
Window framebuffers can be made transparent on a per-pixel per-frame basis with
the [GLFW_TRANSPARENT](@ref GLFW_TRANSPARENT_hint) window hint.
@code
glfwWindowHint(GLFW_TRANSPARENT, GLFW_TRUE);
@endcode
If supported by the system, the window framebuffer will be composited with the
background using the framebuffer per-pixel alpha channel. This requires desktop
compositing to be enabled on the system. It does not affect window decorations.
You can check whether the window framebuffer was successfully made transparent
with the [GLFW_TRANSPARENT](@ref GLFW_TRANSPARENT_attrib) window attribute.
@code
if (glfwGetWindowAttrib(window, GLFW_TRANSPARENT))
{
// window framebuffer is currently transparent
}
@endcode
@subsection window_attribs Window attributes
Windows have a number of attributes that can be returned using @ref
......@@ -1134,6 +1162,11 @@ called topmost or always-on-top. This can be set before creation with the
[GLFW_FLOATING](@ref GLFW_FLOATING_hint) window hint or after with @ref
glfwSetWindowAttrib.
@anchor GLFW_TRANSPARENT_attrib
__GLFW_TRANSPARENT__ indicates whether the specified window has a transparent
framebuffer, i.e. the window contents is composited with the background using
the window framebuffer alpha channel. See @ref window_transparency for details.
@subsubsection window_attribs_ctx Context related attributes
......
......@@ -172,7 +172,7 @@ static GLfloat angle = 0.f;
/* OpenGL draw function & timing */
static void draw(void)
{
glClearColor(0., 0., 0., 0.);
glClearColor(0.0, 0.0, 0.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glPushMatrix();
......@@ -312,7 +312,6 @@ int main(int argc, char *argv[])
}
glfwWindowHint(GLFW_DEPTH_BITS, 16);
glfwWindowHint(GLFW_ALPHA_BITS, 8);
glfwWindowHint(GLFW_TRANSPARENT, GLFW_TRUE);
window = glfwCreateWindow( 300, 300, "Gears", NULL, NULL );
......
......@@ -787,6 +787,12 @@ extern "C" {
* Cursor centering [window hint](@ref GLFW_CENTER_CURSOR_hint).
*/
#define GLFW_CENTER_CURSOR 0x00020009
/*! @brief Window framebuffer transparency hint and attribute
*
* Window framebuffer transparency [window hint](@ref GLFW_TRANSPARENT_hint)
* and [window attribute](@ref GLFW_TRANSPARENT_attrib).
*/
#define GLFW_TRANSPARENT 0x0002000A
/*! @brief Framebuffer bit depth hint.
*
......@@ -868,11 +874,6 @@ extern "C" {
* Framebuffer double buffering [hint](@ref GLFW_DOUBLEBUFFER).
*/
#define GLFW_DOUBLEBUFFER 0x00021010
/*! @brief Framebuffer transparency hint.
*
* Framebuffer transparency [hint](@ref GLFW_TRANSPARENT_hint).
*/
#define GLFW_TRANSPARENT 0x00021011
/*! @brief Context client API hint and attribute.
*
......
......@@ -413,11 +413,7 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
- (BOOL)isOpaque
{
// Set to NO even if alphaMask is not used;
// The NSView/GLFWContentView does not need to be opaque anyway,
// and to avoid keeping track of alphaMask inside the NSView we
// just return NO here instead.
return NO;
return [window->ns.object isOpaque];
}
- (BOOL)canBecomeKeyView
......@@ -1016,7 +1012,8 @@ static GLFWbool initializeAppKit(void)
// Create the Cocoa window
//
static GLFWbool createNativeWindow(_GLFWwindow* window,
const _GLFWwndconfig* wndconfig)
const _GLFWwndconfig* wndconfig,
const _GLFWfbconfig* fbconfig)
{
window->ns.delegate = [[GLFWWindowDelegate alloc] initWithGlfwWindow:window];
if (window->ns.delegate == nil)
......@@ -1085,7 +1082,7 @@ static GLFWbool createNativeWindow(_GLFWwindow* window,
if (wndconfig->ns.retina)
[window->ns.view setWantsBestResolutionOpenGLSurface:YES];
if (_glfw.hints.framebuffer.transparent)
if (fbconfig->transparent)
{
[window->ns.object setOpaque:NO];
[window->ns.object setBackgroundColor:[NSColor clearColor]];
......@@ -1114,7 +1111,7 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
if (!initializeAppKit())
return GLFW_FALSE;
if (!createNativeWindow(window, wndconfig))
if (!createNativeWindow(window, wndconfig, fbconfig))
return GLFW_FALSE;
if (ctxconfig->client != GLFW_NO_API)
......@@ -1453,6 +1450,11 @@ int _glfwPlatformWindowMaximized(_GLFWwindow* window)
return [window->ns.object isZoomed];
}
int _glfwPlatformFramebufferTransparent(_GLFWwindow* window)
{
return ![window->ns.object isOpaque] && ![window->ns.view isOpaque];
}
void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled)
{
[window->ns.object setStyleMask:getStyleMask(window)];
......
......@@ -208,6 +208,9 @@ const _GLFWfbconfig* _glfwChooseFBConfig(const _GLFWfbconfig* desired,
// not important to us here, so we count them as one
missing++;
}
if (desired->transparent != current->transparent)
missing++;
}
// These polynomials make many small channel size differences matter
......
......@@ -87,21 +87,13 @@ static int getEGLConfigAttrib(EGLConfig config, int attrib)
//
static GLFWbool chooseEGLConfig(const _GLFWctxconfig* ctxconfig,
const _GLFWfbconfig* desired,
EGLConfig* result,
GLFWbool findTransparent)
EGLConfig* result)
{
EGLConfig* nativeConfigs;
_GLFWfbconfig* usableConfigs;
const _GLFWfbconfig* closest;
int i, nativeCount, usableCount;
#if defined(_GLFW_X11)
XVisualInfo visualTemplate = {0};
if ( !(_glfw.xrender.major || _glfw.xrender.minor) ) {
findTransparent = GLFW_FALSE;
}
#endif // _GLFW_X11
eglGetConfigs(_glfw.egl.display, NULL, 0, &nativeCount);
if (!nativeCount)
{
......@@ -115,7 +107,6 @@ static GLFWbool chooseEGLConfig(const _GLFWctxconfig* ctxconfig,
usableConfigs = calloc(nativeCount, sizeof(_GLFWfbconfig));
usableCount = 0;
selectionloop:
for (i = 0; i < nativeCount; i++)
{
const EGLConfig n = nativeConfigs[i];
......@@ -130,31 +121,24 @@ selectionloop:
continue;
#if defined(_GLFW_X11)
// Only consider EGLConfigs with associated Visuals
visualTemplate.visualid = getEGLConfigAttrib(n, EGL_NATIVE_VISUAL_ID);
if (!visualTemplate.visualid)
continue;
if( findTransparent ) {
int n_vi;
XVisualInfo *visualinfo;
XRenderPictFormat *pictFormat;
visualinfo = XGetVisualInfo(_glfw.x11.display, VisualIDMask, &visualTemplate, &n_vi);
if (!visualinfo)
continue;
XVisualInfo vi = {0};
pictFormat = XRenderFindVisualFormat(_glfw.x11.display, visualinfo->visual);
if( !pictFormat ) {
XFree( visualinfo );
// Only consider EGLConfigs with associated Visuals
vi.visualid = getEGLConfigAttrib(n, EGL_NATIVE_VISUAL_ID);
if (!vi.visualid)
continue;
}
if( !pictFormat->direct.alphaMask ) {
XFree( visualinfo );
continue;
}
XFree( visualinfo );
if (desired->transparent)
{
int count;
XVisualInfo* vis = XGetVisualInfo(_glfw.x11.display,
VisualIDMask, &vi,
&count);
if (vis)
{
u->transparent = _glfwIsVisualTransparentX11(vis[0].visual);
XFree(vis);
}
}
#endif // _GLFW_X11
......@@ -191,12 +175,6 @@ selectionloop:
u->handle = (uintptr_t) n;
usableCount++;
}
// reiterate the selection loop without looking for transparency supporting
// formats if no matchig FB configs for a transparent window were found.
if( findTransparent && !usableCount ) {
findTransparent = GLFW_FALSE;
goto selectionloop;
}
closest = _glfwChooseFBConfig(desired, usableConfigs, usableCount);
if (closest)
......@@ -493,7 +471,7 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
if (ctxconfig->share)
share = ctxconfig->share->context.egl.handle;
if (!chooseEGLConfig(ctxconfig, fbconfig, &config, fbconfig->transparent))
if (!chooseEGLConfig(ctxconfig, fbconfig, &config))
{
_glfwInputError(GLFW_FORMAT_UNAVAILABLE,
"EGL: Failed to find a suitable EGLConfig");
......@@ -738,7 +716,7 @@ GLFWbool _glfwChooseVisualEGL(const _GLFWwndconfig* wndconfig,
EGLint visualID = 0, count = 0;
const long vimask = VisualScreenMask | VisualIDMask;
if (!chooseEGLConfig(ctxconfig, fbconfig, &native, fbconfig->transparent))
if (!chooseEGLConfig(ctxconfig, fbconfig, &native))
{
_glfwInputError(GLFW_FORMAT_UNAVAILABLE,
"EGL: Failed to find a suitable EGLConfig");
......
......@@ -47,10 +47,8 @@ static int getGLXFBConfigAttrib(GLXFBConfig fbconfig, int attrib)
// Return the GLXFBConfig most closely matching the specified hints
//
static GLFWbool chooseGLXFBConfig(
const _GLFWfbconfig* desired,
GLXFBConfig* result,
GLFWbool findTransparent)
static GLFWbool chooseGLXFBConfig(const _GLFWfbconfig* desired,
GLXFBConfig* result)
{
GLXFBConfig* nativeConfigs;
_GLFWfbconfig* usableConfigs;
......@@ -59,10 +57,6 @@ static GLFWbool chooseGLXFBConfig(
const char* vendor;
GLFWbool trustWindowBit = GLFW_TRUE;
if ( !(_glfw.xrender.major || _glfw.xrender.minor) ) {
findTransparent = GLFW_FALSE;
}
// HACK: This is a (hopefully temporary) workaround for Chromium
// (VirtualBox GL) not setting the window bit on any GLXFBConfigs
vendor = glXGetClientString(_glfw.x11.display, GLX_VENDOR);
......@@ -80,7 +74,6 @@ static GLFWbool chooseGLXFBConfig(
usableConfigs = calloc(nativeCount, sizeof(_GLFWfbconfig));
usableCount = 0;
selectionloop:
for (i = 0; i < nativeCount; i++)
{
const GLXFBConfig n = nativeConfigs[i];
......@@ -97,25 +90,14 @@ selectionloop:
continue;
}
if( findTransparent ) {
XVisualInfo *visualinfo;
XRenderPictFormat *pictFormat;
visualinfo = glXGetVisualFromFBConfig(_glfw.x11.display, n);
if (!visualinfo)
continue;
pictFormat = XRenderFindVisualFormat(_glfw.x11.display, visualinfo->visual);
if( !pictFormat ) {
XFree( visualinfo );
continue;
}
if( !pictFormat->direct.alphaMask ) {
XFree( visualinfo );
continue;
}
XFree( visualinfo );
if (desired->transparent)
{
XVisualInfo* vi = glXGetVisualFromFBConfig(_glfw.x11.display, n);
if (vi)
{
u->transparent = _glfwIsVisualTransparentX11(vi->visual);
XFree(vi);
}
}
u->redBits = getGLXFBConfigAttrib(n, GLX_RED_SIZE);
......@@ -147,12 +129,6 @@ selectionloop:
u->handle = (uintptr_t) n;
usableCount++;
}
// reiterate the selection loop without looking for transparency supporting
// formats if no matchig FB configs for a transparent window were found.
if( findTransparent && !usableCount ) {
findTransparent = GLFW_FALSE;
goto selectionloop;
}
closest = _glfwChooseFBConfig(desired, usableConfigs, usableCount);
if (closest)
......@@ -477,7 +453,7 @@ GLFWbool _glfwCreateContextGLX(_GLFWwindow* window,
if (ctxconfig->share)
share = ctxconfig->share->context.glx.handle;
if (!chooseGLXFBConfig(fbconfig, &native, fbconfig->transparent))
if (!chooseGLXFBConfig(fbconfig, &native))
{
_glfwInputError(GLFW_FORMAT_UNAVAILABLE,
"GLX: Failed to find a suitable GLXFBConfig");
......@@ -665,7 +641,7 @@ GLFWbool _glfwChooseVisualGLX(const _GLFWwndconfig* wndconfig,
GLXFBConfig native;
XVisualInfo* result;
if (!chooseGLXFBConfig(fbconfig, &native, fbconfig->transparent))
if (!chooseGLXFBConfig(fbconfig, &native))
{
_glfwInputError(GLFW_FORMAT_UNAVAILABLE,
"GLX: Failed to find a suitable GLXFBConfig");
......
......@@ -682,6 +682,7 @@ int _glfwPlatformWindowFocused(_GLFWwindow* window);
int _glfwPlatformWindowIconified(_GLFWwindow* window);
int _glfwPlatformWindowVisible(_GLFWwindow* window);
int _glfwPlatformWindowMaximized(_GLFWwindow* window);
int _glfwPlatformFramebufferTransparent(_GLFWwindow* window);
void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled);
void _glfwPlatformSetWindowDecorated(_GLFWwindow* window, GLFWbool enabled);
void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled);
......
......@@ -614,6 +614,13 @@ int _glfwPlatformWindowMaximized(_GLFWwindow* window)
return mir_window_get_state(window->mir.window) == mir_window_state_maximized;
}
int _glfwPlatformFramebufferTransparent(_GLFWwindow* window)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
return GLFW_FALSE;
}
void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
......
......@@ -156,6 +156,11 @@ int _glfwPlatformWindowMaximized(_GLFWwindow* window)
return GLFW_FALSE;
}
int _glfwPlatformFramebufferTransparent(_GLFWwindow* window)
{
return GLFW_FALSE;
}
void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled)
{
}
......
......@@ -83,20 +83,6 @@ static int choosePixelFormat(_GLFWwindow* window,
{
const int n = i + 1;
_GLFWfbconfig* u = usableConfigs + usableCount;
PIXELFORMATDESCRIPTOR pfd;
if (fbconfig->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)
{
......@@ -168,7 +154,9 @@ static int choosePixelFormat(_GLFWwindow* window,
{
// Get pixel format attributes through legacy PFDs
if (!fbconfig->transparent && DescribePixelFormat(window->context.wgl.dc,
PIXELFORMATDESCRIPTOR pfd;
if (!DescribePixelFormat(window->context.wgl.dc,
n,
sizeof(PIXELFORMATDESCRIPTOR),
&pfd))
......@@ -215,14 +203,6 @@ 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 (fbconfig->transparent && !usableCount) {
free(usableConfigs);
_glfwInputError(GLFW_PLATFORM_ERROR,
"WGL: No pixel format found for transparent window. Ignoring transparency.");
return choosePixelFormat(window, ctxconfig, fbconfig);
}
if (!usableCount)
{
......@@ -249,21 +229,6 @@ static int choosePixelFormat(_GLFWwindow* window,
return pixelFormat;
}
// Returns whether desktop compositing is enabled
//
static GLFWbool isCompositionEnabled(void)
{
if (_glfw.win32.dwmapi.instance)
{
BOOL enabled;
if (DwmIsCompositionEnabled(&enabled) == S_OK)
return enabled;
}
return FALSE;
}
static void makeContextCurrentWGL(_GLFWwindow* window)
{
if (window)
......@@ -292,7 +257,7 @@ static void makeContextCurrentWGL(_GLFWwindow* window)
static void swapBuffersWGL(_GLFWwindow* window)
{
// HACK: Use DwmFlush when desktop composition is enabled
if (isCompositionEnabled() && !window->monitor)
if (_glfwIsCompositionEnabledWin32() && !window->monitor)
{
int count = abs(window->context.wgl.interval);
while (count--)
......@@ -310,7 +275,7 @@ static void swapIntervalWGL(int interval)
// HACK: Disable WGL swap interval when desktop composition is enabled to
// avoid interfering with DWM vsync
if (isCompositionEnabled() && !window->monitor)
if (_glfwIsCompositionEnabledWin32() && !window->monitor)
interval = 0;
if (_glfw.wgl.EXT_swap_control)
......@@ -504,75 +469,6 @@ 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;