mirror of
https://github.com/gwm17/glfw.git
synced 2024-11-26 12:18:51 -05:00
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.
This commit is contained in:
parent
93e66661d3
commit
32e78aeb2e
|
@ -150,6 +150,8 @@ information on what to include when reporting a bug.
|
||||||
functions for accessing X11 primary selection (#894,#1056)
|
functions for accessing X11 primary selection (#894,#1056)
|
||||||
- Added headless [OSMesa](http://mesa3d.org/osmesa.html) backend (#850)
|
- Added headless [OSMesa](http://mesa3d.org/osmesa.html) backend (#850)
|
||||||
- Added definition of `GLAPIENTRY` to public header
|
- 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
|
- Added `GLFW_CENTER_CURSOR` window hint for controlling cursor centering
|
||||||
(#749,#842)
|
(#749,#842)
|
||||||
- Added `GLFW_JOYSTICK_HAT_BUTTONS` init hint (#889)
|
- Added `GLFW_JOYSTICK_HAT_BUTTONS` init hint (#889)
|
||||||
|
@ -289,6 +291,7 @@ skills.
|
||||||
- Yaron Cohen-Tal
|
- Yaron Cohen-Tal
|
||||||
- Omar Cornut
|
- Omar Cornut
|
||||||
- Andrew Corrigan
|
- Andrew Corrigan
|
||||||
|
- Bailey Cosier
|
||||||
- Noel Cower
|
- Noel Cower
|
||||||
- Jason Daly
|
- Jason Daly
|
||||||
- Jarrod Davis
|
- Jarrod Davis
|
||||||
|
@ -297,6 +300,7 @@ skills.
|
||||||
- Michael Dickens
|
- Michael Dickens
|
||||||
- Роман Донченко
|
- Роман Донченко
|
||||||
- Mario Dorn
|
- Mario Dorn
|
||||||
|
- Wolfgang Draxinger
|
||||||
- Jonathan Dummer
|
- Jonathan Dummer
|
||||||
- Ralph Eastwood
|
- Ralph Eastwood
|
||||||
- Fredrik Ehnbom
|
- Fredrik Ehnbom
|
||||||
|
@ -322,6 +326,7 @@ skills.
|
||||||
- Erik S. V. Jansson
|
- Erik S. V. Jansson
|
||||||
- Toni Jovanoski
|
- Toni Jovanoski
|
||||||
- Arseny Kapoulkine
|
- Arseny Kapoulkine
|
||||||
|
- Cem Karan
|
||||||
- Osman Keskin
|
- Osman Keskin
|
||||||
- Josh Kilmer
|
- Josh Kilmer
|
||||||
- Cameron King
|
- Cameron King
|
||||||
|
@ -363,6 +368,7 @@ skills.
|
||||||
- Andri Pálsson
|
- Andri Pálsson
|
||||||
- Peoro
|
- Peoro
|
||||||
- Braden Pellett
|
- Braden Pellett
|
||||||
|
- Christopher Pelloux
|
||||||
- Arturo J. Pérez
|
- Arturo J. Pérez
|
||||||
- Anthony Pesch
|
- Anthony Pesch
|
||||||
- Orson Peters
|
- 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
|
when the cursor is disabled. If the running X server does not support this
|
||||||
extension, regular accelerated mouse motion will be used.
|
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
|
@section compat_glx GLX extensions
|
||||||
|
|
||||||
|
|
|
@ -85,6 +85,13 @@ be disabled with the @ref GLFW_JOYSTICK_HAT_BUTTONS init hint.
|
||||||
@see @ref joystick_hat
|
@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
|
@subsection news_33_centercursor Cursor centering window hint
|
||||||
|
|
||||||
GLFW now supports controlling whether the cursor is centered over newly created
|
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
|
newly created full screen windows. Possible values are `GLFW_TRUE` and
|
||||||
`GLFW_FALSE`. This hint is ignored for windowed mode windows.
|
`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
|
@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
|
buffered. You nearly always want to use double buffering. This is a hard
|
||||||
constraint. Possible values are `GLFW_TRUE` and `GLFW_FALSE`.
|
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
|
@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_FLOATING | `GLFW_FALSE` | `GLFW_TRUE` or `GLFW_FALSE`
|
||||||
GLFW_MAXIMIZED | `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_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_RED_BITS | 8 | 0 to `INT_MAX` or `GLFW_DONT_CARE`
|
||||||
GLFW_GREEN_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`
|
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.
|
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
|
@subsection window_attribs Window attributes
|
||||||
|
|
||||||
Windows have a number of attributes that can be returned using @ref
|
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
|
[GLFW_FLOATING](@ref GLFW_FLOATING_hint) window hint or after with @ref
|
||||||
glfwSetWindowAttrib.
|
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
|
@subsubsection window_attribs_ctx Context related attributes
|
||||||
|
|
||||||
|
|
|
@ -172,7 +172,7 @@ static GLfloat angle = 0.f;
|
||||||
/* OpenGL draw function & timing */
|
/* OpenGL draw function & timing */
|
||||||
static void draw(void)
|
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);
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
|
|
||||||
glPushMatrix();
|
glPushMatrix();
|
||||||
|
@ -312,7 +312,6 @@ int main(int argc, char *argv[])
|
||||||
}
|
}
|
||||||
|
|
||||||
glfwWindowHint(GLFW_DEPTH_BITS, 16);
|
glfwWindowHint(GLFW_DEPTH_BITS, 16);
|
||||||
glfwWindowHint(GLFW_ALPHA_BITS, 8);
|
|
||||||
glfwWindowHint(GLFW_TRANSPARENT, GLFW_TRUE);
|
glfwWindowHint(GLFW_TRANSPARENT, GLFW_TRUE);
|
||||||
|
|
||||||
window = glfwCreateWindow( 300, 300, "Gears", NULL, NULL );
|
window = glfwCreateWindow( 300, 300, "Gears", NULL, NULL );
|
||||||
|
|
|
@ -787,6 +787,12 @@ extern "C" {
|
||||||
* Cursor centering [window hint](@ref GLFW_CENTER_CURSOR_hint).
|
* Cursor centering [window hint](@ref GLFW_CENTER_CURSOR_hint).
|
||||||
*/
|
*/
|
||||||
#define GLFW_CENTER_CURSOR 0x00020009
|
#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.
|
/*! @brief Framebuffer bit depth hint.
|
||||||
*
|
*
|
||||||
|
@ -868,11 +874,6 @@ extern "C" {
|
||||||
* Framebuffer double buffering [hint](@ref GLFW_DOUBLEBUFFER).
|
* Framebuffer double buffering [hint](@ref GLFW_DOUBLEBUFFER).
|
||||||
*/
|
*/
|
||||||
#define GLFW_DOUBLEBUFFER 0x00021010
|
#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.
|
/*! @brief Context client API hint and attribute.
|
||||||
*
|
*
|
||||||
|
|
|
@ -413,11 +413,7 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
|
||||||
|
|
||||||
- (BOOL)isOpaque
|
- (BOOL)isOpaque
|
||||||
{
|
{
|
||||||
// Set to NO even if alphaMask is not used;
|
return [window->ns.object isOpaque];
|
||||||
// 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL)canBecomeKeyView
|
- (BOOL)canBecomeKeyView
|
||||||
|
@ -1016,7 +1012,8 @@ static GLFWbool initializeAppKit(void)
|
||||||
// Create the Cocoa window
|
// Create the Cocoa window
|
||||||
//
|
//
|
||||||
static GLFWbool createNativeWindow(_GLFWwindow* window,
|
static GLFWbool createNativeWindow(_GLFWwindow* window,
|
||||||
const _GLFWwndconfig* wndconfig)
|
const _GLFWwndconfig* wndconfig,
|
||||||
|
const _GLFWfbconfig* fbconfig)
|
||||||
{
|
{
|
||||||
window->ns.delegate = [[GLFWWindowDelegate alloc] initWithGlfwWindow:window];
|
window->ns.delegate = [[GLFWWindowDelegate alloc] initWithGlfwWindow:window];
|
||||||
if (window->ns.delegate == nil)
|
if (window->ns.delegate == nil)
|
||||||
|
@ -1085,7 +1082,7 @@ static GLFWbool createNativeWindow(_GLFWwindow* window,
|
||||||
if (wndconfig->ns.retina)
|
if (wndconfig->ns.retina)
|
||||||
[window->ns.view setWantsBestResolutionOpenGLSurface:YES];
|
[window->ns.view setWantsBestResolutionOpenGLSurface:YES];
|
||||||
|
|
||||||
if (_glfw.hints.framebuffer.transparent)
|
if (fbconfig->transparent)
|
||||||
{
|
{
|
||||||
[window->ns.object setOpaque:NO];
|
[window->ns.object setOpaque:NO];
|
||||||
[window->ns.object setBackgroundColor:[NSColor clearColor]];
|
[window->ns.object setBackgroundColor:[NSColor clearColor]];
|
||||||
|
@ -1114,7 +1111,7 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
|
||||||
if (!initializeAppKit())
|
if (!initializeAppKit())
|
||||||
return GLFW_FALSE;
|
return GLFW_FALSE;
|
||||||
|
|
||||||
if (!createNativeWindow(window, wndconfig))
|
if (!createNativeWindow(window, wndconfig, fbconfig))
|
||||||
return GLFW_FALSE;
|
return GLFW_FALSE;
|
||||||
|
|
||||||
if (ctxconfig->client != GLFW_NO_API)
|
if (ctxconfig->client != GLFW_NO_API)
|
||||||
|
@ -1453,6 +1450,11 @@ int _glfwPlatformWindowMaximized(_GLFWwindow* window)
|
||||||
return [window->ns.object isZoomed];
|
return [window->ns.object isZoomed];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int _glfwPlatformFramebufferTransparent(_GLFWwindow* window)
|
||||||
|
{
|
||||||
|
return ![window->ns.object isOpaque] && ![window->ns.view isOpaque];
|
||||||
|
}
|
||||||
|
|
||||||
void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled)
|
void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled)
|
||||||
{
|
{
|
||||||
[window->ns.object setStyleMask:getStyleMask(window)];
|
[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
|
// not important to us here, so we count them as one
|
||||||
missing++;
|
missing++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (desired->transparent != current->transparent)
|
||||||
|
missing++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// These polynomials make many small channel size differences matter
|
// 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,
|
static GLFWbool chooseEGLConfig(const _GLFWctxconfig* ctxconfig,
|
||||||
const _GLFWfbconfig* desired,
|
const _GLFWfbconfig* desired,
|
||||||
EGLConfig* result,
|
EGLConfig* result)
|
||||||
GLFWbool findTransparent)
|
|
||||||
{
|
{
|
||||||
EGLConfig* nativeConfigs;
|
EGLConfig* nativeConfigs;
|
||||||
_GLFWfbconfig* usableConfigs;
|
_GLFWfbconfig* usableConfigs;
|
||||||
const _GLFWfbconfig* closest;
|
const _GLFWfbconfig* closest;
|
||||||
int i, nativeCount, usableCount;
|
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);
|
eglGetConfigs(_glfw.egl.display, NULL, 0, &nativeCount);
|
||||||
if (!nativeCount)
|
if (!nativeCount)
|
||||||
{
|
{
|
||||||
|
@ -115,7 +107,6 @@ static GLFWbool chooseEGLConfig(const _GLFWctxconfig* ctxconfig,
|
||||||
usableConfigs = calloc(nativeCount, sizeof(_GLFWfbconfig));
|
usableConfigs = calloc(nativeCount, sizeof(_GLFWfbconfig));
|
||||||
usableCount = 0;
|
usableCount = 0;
|
||||||
|
|
||||||
selectionloop:
|
|
||||||
for (i = 0; i < nativeCount; i++)
|
for (i = 0; i < nativeCount; i++)
|
||||||
{
|
{
|
||||||
const EGLConfig n = nativeConfigs[i];
|
const EGLConfig n = nativeConfigs[i];
|
||||||
|
@ -130,31 +121,24 @@ selectionloop:
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
#if defined(_GLFW_X11)
|
#if defined(_GLFW_X11)
|
||||||
|
XVisualInfo vi = {0};
|
||||||
|
|
||||||
// Only consider EGLConfigs with associated Visuals
|
// Only consider EGLConfigs with associated Visuals
|
||||||
visualTemplate.visualid = getEGLConfigAttrib(n, EGL_NATIVE_VISUAL_ID);
|
vi.visualid = getEGLConfigAttrib(n, EGL_NATIVE_VISUAL_ID);
|
||||||
if (!visualTemplate.visualid)
|
if (!vi.visualid)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if( findTransparent ) {
|
if (desired->transparent)
|
||||||
int n_vi;
|
{
|
||||||
XVisualInfo *visualinfo;
|
int count;
|
||||||
XRenderPictFormat *pictFormat;
|
XVisualInfo* vis = XGetVisualInfo(_glfw.x11.display,
|
||||||
|
VisualIDMask, &vi,
|
||||||
visualinfo = XGetVisualInfo(_glfw.x11.display, VisualIDMask, &visualTemplate, &n_vi);
|
&count);
|
||||||
if (!visualinfo)
|
if (vis)
|
||||||
continue;
|
{
|
||||||
|
u->transparent = _glfwIsVisualTransparentX11(vis[0].visual);
|
||||||
pictFormat = XRenderFindVisualFormat(_glfw.x11.display, visualinfo->visual);
|
XFree(vis);
|
||||||
if( !pictFormat ) {
|
}
|
||||||
XFree( visualinfo );
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( !pictFormat->direct.alphaMask ) {
|
|
||||||
XFree( visualinfo );
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
XFree( visualinfo );
|
|
||||||
}
|
}
|
||||||
#endif // _GLFW_X11
|
#endif // _GLFW_X11
|
||||||
|
|
||||||
|
@ -191,12 +175,6 @@ selectionloop:
|
||||||
u->handle = (uintptr_t) n;
|
u->handle = (uintptr_t) n;
|
||||||
usableCount++;
|
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);
|
closest = _glfwChooseFBConfig(desired, usableConfigs, usableCount);
|
||||||
if (closest)
|
if (closest)
|
||||||
|
@ -493,7 +471,7 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
|
||||||
if (ctxconfig->share)
|
if (ctxconfig->share)
|
||||||
share = ctxconfig->share->context.egl.handle;
|
share = ctxconfig->share->context.egl.handle;
|
||||||
|
|
||||||
if (!chooseEGLConfig(ctxconfig, fbconfig, &config, fbconfig->transparent))
|
if (!chooseEGLConfig(ctxconfig, fbconfig, &config))
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_FORMAT_UNAVAILABLE,
|
_glfwInputError(GLFW_FORMAT_UNAVAILABLE,
|
||||||
"EGL: Failed to find a suitable EGLConfig");
|
"EGL: Failed to find a suitable EGLConfig");
|
||||||
|
@ -738,7 +716,7 @@ GLFWbool _glfwChooseVisualEGL(const _GLFWwndconfig* wndconfig,
|
||||||
EGLint visualID = 0, count = 0;
|
EGLint visualID = 0, count = 0;
|
||||||
const long vimask = VisualScreenMask | VisualIDMask;
|
const long vimask = VisualScreenMask | VisualIDMask;
|
||||||
|
|
||||||
if (!chooseEGLConfig(ctxconfig, fbconfig, &native, fbconfig->transparent))
|
if (!chooseEGLConfig(ctxconfig, fbconfig, &native))
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_FORMAT_UNAVAILABLE,
|
_glfwInputError(GLFW_FORMAT_UNAVAILABLE,
|
||||||
"EGL: Failed to find a suitable EGLConfig");
|
"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
|
// Return the GLXFBConfig most closely matching the specified hints
|
||||||
//
|
//
|
||||||
static GLFWbool chooseGLXFBConfig(
|
static GLFWbool chooseGLXFBConfig(const _GLFWfbconfig* desired,
|
||||||
const _GLFWfbconfig* desired,
|
GLXFBConfig* result)
|
||||||
GLXFBConfig* result,
|
|
||||||
GLFWbool findTransparent)
|
|
||||||
{
|
{
|
||||||
GLXFBConfig* nativeConfigs;
|
GLXFBConfig* nativeConfigs;
|
||||||
_GLFWfbconfig* usableConfigs;
|
_GLFWfbconfig* usableConfigs;
|
||||||
|
@ -59,10 +57,6 @@ static GLFWbool chooseGLXFBConfig(
|
||||||
const char* vendor;
|
const char* vendor;
|
||||||
GLFWbool trustWindowBit = GLFW_TRUE;
|
GLFWbool trustWindowBit = GLFW_TRUE;
|
||||||
|
|
||||||
if ( !(_glfw.xrender.major || _glfw.xrender.minor) ) {
|
|
||||||
findTransparent = GLFW_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// HACK: This is a (hopefully temporary) workaround for Chromium
|
// HACK: This is a (hopefully temporary) workaround for Chromium
|
||||||
// (VirtualBox GL) not setting the window bit on any GLXFBConfigs
|
// (VirtualBox GL) not setting the window bit on any GLXFBConfigs
|
||||||
vendor = glXGetClientString(_glfw.x11.display, GLX_VENDOR);
|
vendor = glXGetClientString(_glfw.x11.display, GLX_VENDOR);
|
||||||
|
@ -80,7 +74,6 @@ static GLFWbool chooseGLXFBConfig(
|
||||||
usableConfigs = calloc(nativeCount, sizeof(_GLFWfbconfig));
|
usableConfigs = calloc(nativeCount, sizeof(_GLFWfbconfig));
|
||||||
usableCount = 0;
|
usableCount = 0;
|
||||||
|
|
||||||
selectionloop:
|
|
||||||
for (i = 0; i < nativeCount; i++)
|
for (i = 0; i < nativeCount; i++)
|
||||||
{
|
{
|
||||||
const GLXFBConfig n = nativeConfigs[i];
|
const GLXFBConfig n = nativeConfigs[i];
|
||||||
|
@ -97,25 +90,14 @@ selectionloop:
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( findTransparent ) {
|
if (desired->transparent)
|
||||||
XVisualInfo *visualinfo;
|
{
|
||||||
XRenderPictFormat *pictFormat;
|
XVisualInfo* vi = glXGetVisualFromFBConfig(_glfw.x11.display, n);
|
||||||
|
if (vi)
|
||||||
visualinfo = glXGetVisualFromFBConfig(_glfw.x11.display, n);
|
{
|
||||||
if (!visualinfo)
|
u->transparent = _glfwIsVisualTransparentX11(vi->visual);
|
||||||
continue;
|
XFree(vi);
|
||||||
|
}
|
||||||
pictFormat = XRenderFindVisualFormat(_glfw.x11.display, visualinfo->visual);
|
|
||||||
if( !pictFormat ) {
|
|
||||||
XFree( visualinfo );
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( !pictFormat->direct.alphaMask ) {
|
|
||||||
XFree( visualinfo );
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
XFree( visualinfo );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
u->redBits = getGLXFBConfigAttrib(n, GLX_RED_SIZE);
|
u->redBits = getGLXFBConfigAttrib(n, GLX_RED_SIZE);
|
||||||
|
@ -147,12 +129,6 @@ selectionloop:
|
||||||
u->handle = (uintptr_t) n;
|
u->handle = (uintptr_t) n;
|
||||||
usableCount++;
|
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);
|
closest = _glfwChooseFBConfig(desired, usableConfigs, usableCount);
|
||||||
if (closest)
|
if (closest)
|
||||||
|
@ -477,7 +453,7 @@ GLFWbool _glfwCreateContextGLX(_GLFWwindow* window,
|
||||||
if (ctxconfig->share)
|
if (ctxconfig->share)
|
||||||
share = ctxconfig->share->context.glx.handle;
|
share = ctxconfig->share->context.glx.handle;
|
||||||
|
|
||||||
if (!chooseGLXFBConfig(fbconfig, &native, fbconfig->transparent))
|
if (!chooseGLXFBConfig(fbconfig, &native))
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_FORMAT_UNAVAILABLE,
|
_glfwInputError(GLFW_FORMAT_UNAVAILABLE,
|
||||||
"GLX: Failed to find a suitable GLXFBConfig");
|
"GLX: Failed to find a suitable GLXFBConfig");
|
||||||
|
@ -665,7 +641,7 @@ GLFWbool _glfwChooseVisualGLX(const _GLFWwndconfig* wndconfig,
|
||||||
GLXFBConfig native;
|
GLXFBConfig native;
|
||||||
XVisualInfo* result;
|
XVisualInfo* result;
|
||||||
|
|
||||||
if (!chooseGLXFBConfig(fbconfig, &native, fbconfig->transparent))
|
if (!chooseGLXFBConfig(fbconfig, &native))
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_FORMAT_UNAVAILABLE,
|
_glfwInputError(GLFW_FORMAT_UNAVAILABLE,
|
||||||
"GLX: Failed to find a suitable GLXFBConfig");
|
"GLX: Failed to find a suitable GLXFBConfig");
|
||||||
|
|
|
@ -682,6 +682,7 @@ int _glfwPlatformWindowFocused(_GLFWwindow* window);
|
||||||
int _glfwPlatformWindowIconified(_GLFWwindow* window);
|
int _glfwPlatformWindowIconified(_GLFWwindow* window);
|
||||||
int _glfwPlatformWindowVisible(_GLFWwindow* window);
|
int _glfwPlatformWindowVisible(_GLFWwindow* window);
|
||||||
int _glfwPlatformWindowMaximized(_GLFWwindow* window);
|
int _glfwPlatformWindowMaximized(_GLFWwindow* window);
|
||||||
|
int _glfwPlatformFramebufferTransparent(_GLFWwindow* window);
|
||||||
void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled);
|
void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled);
|
||||||
void _glfwPlatformSetWindowDecorated(_GLFWwindow* window, GLFWbool enabled);
|
void _glfwPlatformSetWindowDecorated(_GLFWwindow* window, GLFWbool enabled);
|
||||||
void _glfwPlatformSetWindowFloating(_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;
|
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)
|
void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
|
|
|
@ -156,6 +156,11 @@ int _glfwPlatformWindowMaximized(_GLFWwindow* window)
|
||||||
return GLFW_FALSE;
|
return GLFW_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int _glfwPlatformFramebufferTransparent(_GLFWwindow* window)
|
||||||
|
{
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled)
|
void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
|
@ -83,20 +83,6 @@ static int choosePixelFormat(_GLFWwindow* window,
|
||||||
{
|
{
|
||||||
const int n = i + 1;
|
const int n = i + 1;
|
||||||
_GLFWfbconfig* u = usableConfigs + usableCount;
|
_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)
|
if (_glfw.wgl.ARB_pixel_format)
|
||||||
{
|
{
|
||||||
|
@ -168,7 +154,9 @@ static int choosePixelFormat(_GLFWwindow* window,
|
||||||
{
|
{
|
||||||
// Get pixel format attributes through legacy PFDs
|
// Get pixel format attributes through legacy PFDs
|
||||||
|
|
||||||
if (!fbconfig->transparent && DescribePixelFormat(window->context.wgl.dc,
|
PIXELFORMATDESCRIPTOR pfd;
|
||||||
|
|
||||||
|
if (!DescribePixelFormat(window->context.wgl.dc,
|
||||||
n,
|
n,
|
||||||
sizeof(PIXELFORMATDESCRIPTOR),
|
sizeof(PIXELFORMATDESCRIPTOR),
|
||||||
&pfd))
|
&pfd))
|
||||||
|
@ -215,14 +203,6 @@ static int choosePixelFormat(_GLFWwindow* window,
|
||||||
u->handle = n;
|
u->handle = n;
|
||||||
usableCount++;
|
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)
|
if (!usableCount)
|
||||||
{
|
{
|
||||||
|
@ -249,21 +229,6 @@ static int choosePixelFormat(_GLFWwindow* window,
|
||||||
return pixelFormat;
|
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)
|
static void makeContextCurrentWGL(_GLFWwindow* window)
|
||||||
{
|
{
|
||||||
if (window)
|
if (window)
|
||||||
|
@ -292,7 +257,7 @@ static void makeContextCurrentWGL(_GLFWwindow* window)
|
||||||
static void swapBuffersWGL(_GLFWwindow* window)
|
static void swapBuffersWGL(_GLFWwindow* window)
|
||||||
{
|
{
|
||||||
// HACK: Use DwmFlush when desktop composition is enabled
|
// HACK: Use DwmFlush when desktop composition is enabled
|
||||||
if (isCompositionEnabled() && !window->monitor)
|
if (_glfwIsCompositionEnabledWin32() && !window->monitor)
|
||||||
{
|
{
|
||||||
int count = abs(window->context.wgl.interval);
|
int count = abs(window->context.wgl.interval);
|
||||||
while (count--)
|
while (count--)
|
||||||
|
@ -310,7 +275,7 @@ static void swapIntervalWGL(int interval)
|
||||||
|
|
||||||
// HACK: Disable WGL swap interval when desktop composition is enabled to
|
// HACK: Disable WGL swap interval when desktop composition is enabled to
|
||||||
// avoid interfering with DWM vsync
|
// avoid interfering with DWM vsync
|
||||||
if (isCompositionEnabled() && !window->monitor)
|
if (_glfwIsCompositionEnabledWin32() && !window->monitor)
|
||||||
interval = 0;
|
interval = 0;
|
||||||
|
|
||||||
if (_glfw.wgl.EXT_swap_control)
|
if (_glfw.wgl.EXT_swap_control)
|
||||||
|
@ -504,75 +469,6 @@ void _glfwTerminateWGL(void)
|
||||||
attribs[index++] = v; \
|
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
|
// Create the OpenGL or OpenGL ES context
|
||||||
//
|
//
|
||||||
GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
|
GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
|
||||||
|
@ -802,14 +698,6 @@ GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fbconfig->transparent)
|
|
||||||
{
|
|
||||||
if (!setupTransparentWindow(window))
|
|
||||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
|
||||||
"WGL: Failed to setup window as transparent as requested");
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
window->context.makeCurrent = makeContextCurrentWGL;
|
window->context.makeCurrent = makeContextCurrentWGL;
|
||||||
window->context.swapBuffers = swapBuffersWGL;
|
window->context.swapBuffers = swapBuffersWGL;
|
||||||
window->context.swapInterval = swapIntervalWGL;
|
window->context.swapInterval = swapIntervalWGL;
|
||||||
|
|
|
@ -62,6 +62,17 @@ BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved)
|
||||||
|
|
||||||
#endif // _GLFW_BUILD_DLL
|
#endif // _GLFW_BUILD_DLL
|
||||||
|
|
||||||
|
// HACK: Define versionhelpers.h functions manually as MinGW lacks the header
|
||||||
|
BOOL IsWindowsVersionOrGreater(WORD major, WORD minor, WORD sp)
|
||||||
|
{
|
||||||
|
OSVERSIONINFOEXW osvi = { sizeof(osvi), major, minor, 0, 0, {0}, sp };
|
||||||
|
DWORD mask = VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR;
|
||||||
|
ULONGLONG cond = VerSetConditionMask(0, VER_MAJORVERSION, VER_GREATER_EQUAL);
|
||||||
|
cond = VerSetConditionMask(cond, VER_MINORVERSION, VER_GREATER_EQUAL);
|
||||||
|
cond = VerSetConditionMask(cond, VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL);
|
||||||
|
return VerifyVersionInfoW(&osvi, mask, cond);
|
||||||
|
}
|
||||||
|
|
||||||
// Load necessary libraries (DLLs)
|
// Load necessary libraries (DLLs)
|
||||||
//
|
//
|
||||||
static GLFWbool loadLibraries(void)
|
static GLFWbool loadLibraries(void)
|
||||||
|
@ -131,7 +142,7 @@ static GLFWbool loadLibraries(void)
|
||||||
GetProcAddress(_glfw.win32.dwmapi.instance, "DwmIsCompositionEnabled");
|
GetProcAddress(_glfw.win32.dwmapi.instance, "DwmIsCompositionEnabled");
|
||||||
_glfw.win32.dwmapi.Flush = (PFN_DwmFlush)
|
_glfw.win32.dwmapi.Flush = (PFN_DwmFlush)
|
||||||
GetProcAddress(_glfw.win32.dwmapi.instance, "DwmFlush");
|
GetProcAddress(_glfw.win32.dwmapi.instance, "DwmFlush");
|
||||||
_glfw.win32.dwmapi.DwmEnableBlurBehindWindow = (DWMENABLEBLURBEHINDWINDOW_T)
|
_glfw.win32.dwmapi.EnableBlurBehindWindow = (PFN_DwmEnableBlurBehindWindow)
|
||||||
GetProcAddress(_glfw.win32.dwmapi.instance, "DwmEnableBlurBehindWindow");
|
GetProcAddress(_glfw.win32.dwmapi.instance, "DwmEnableBlurBehindWindow");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -100,6 +100,9 @@
|
||||||
#ifndef DISPLAY_DEVICE_ACTIVE
|
#ifndef DISPLAY_DEVICE_ACTIVE
|
||||||
#define DISPLAY_DEVICE_ACTIVE 0x00000001
|
#define DISPLAY_DEVICE_ACTIVE 0x00000001
|
||||||
#endif
|
#endif
|
||||||
|
#ifndef _WIN32_WINNT_WINBLUE
|
||||||
|
#define _WIN32_WINNT_WINBLUE 0x0602
|
||||||
|
#endif
|
||||||
|
|
||||||
#if WINVER < 0x0601
|
#if WINVER < 0x0601
|
||||||
typedef struct tagCHANGEFILTERSTRUCT
|
typedef struct tagCHANGEFILTERSTRUCT
|
||||||
|
@ -113,6 +116,18 @@ typedef struct tagCHANGEFILTERSTRUCT
|
||||||
#endif
|
#endif
|
||||||
#endif /*Windows 7*/
|
#endif /*Windows 7*/
|
||||||
|
|
||||||
|
#if WINVER < 0x0600
|
||||||
|
#define DWM_BB_ENABLE 0x00000001
|
||||||
|
#define DWM_BB_BLURREGION 0x00000002
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
DWORD dwFlags;
|
||||||
|
BOOL fEnable;
|
||||||
|
HRGN hRgnBlur;
|
||||||
|
BOOL fTransitionOnMaximized;
|
||||||
|
} DWM_BLURBEHIND;
|
||||||
|
#endif /*Windows Vista*/
|
||||||
|
|
||||||
#ifndef DPI_ENUMS_DECLARED
|
#ifndef DPI_ENUMS_DECLARED
|
||||||
typedef enum PROCESS_DPI_AWARENESS
|
typedef enum PROCESS_DPI_AWARENESS
|
||||||
{
|
{
|
||||||
|
@ -122,30 +137,8 @@ typedef enum PROCESS_DPI_AWARENESS
|
||||||
} PROCESS_DPI_AWARENESS;
|
} PROCESS_DPI_AWARENESS;
|
||||||
#endif /*DPI_ENUMS_DECLARED*/
|
#endif /*DPI_ENUMS_DECLARED*/
|
||||||
|
|
||||||
#if !defined(_DWMAPI_H_)
|
|
||||||
#define DWM_BB_ENABLE 0x00000001
|
|
||||||
#define DWM_BB_BLURREGION 0x00000002
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
DWORD dwFlags;
|
|
||||||
BOOL fEnable;
|
|
||||||
HRGN hRgnBlur;
|
|
||||||
BOOL fTransitionOnMaximized;
|
|
||||||
} DWM_BLURBEHIND;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// HACK: Define versionhelpers.h functions manually as MinGW lacks the header
|
// HACK: Define versionhelpers.h functions manually as MinGW lacks the header
|
||||||
FORCEINLINE BOOL IsWindowsVersionOrGreater(WORD major, WORD minor, WORD sp)
|
BOOL IsWindowsVersionOrGreater(WORD major, WORD minor, WORD sp);
|
||||||
{
|
|
||||||
OSVERSIONINFOEXW osvi = { sizeof(osvi), major, minor, 0, 0, {0}, sp };
|
|
||||||
DWORD mask = VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR;
|
|
||||||
ULONGLONG cond = VerSetConditionMask(0, VER_MAJORVERSION, VER_GREATER_EQUAL);
|
|
||||||
cond = VerSetConditionMask(cond, VER_MINORVERSION, VER_GREATER_EQUAL);
|
|
||||||
cond = VerSetConditionMask(cond, VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL);
|
|
||||||
return VerifyVersionInfoW(&osvi, mask, cond);
|
|
||||||
}
|
|
||||||
|
|
||||||
#define IsWindowsVistaOrGreater() \
|
#define IsWindowsVistaOrGreater() \
|
||||||
IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_VISTA), \
|
IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_VISTA), \
|
||||||
LOBYTE(_WIN32_WINNT_VISTA), 0)
|
LOBYTE(_WIN32_WINNT_VISTA), 0)
|
||||||
|
@ -216,10 +209,10 @@ typedef BOOL (WINAPI * PFN_ChangeWindowMessageFilterEx)(HWND,UINT,DWORD,PCHANGEF
|
||||||
// dwmapi.dll function pointer typedefs
|
// dwmapi.dll function pointer typedefs
|
||||||
typedef HRESULT (WINAPI * PFN_DwmIsCompositionEnabled)(BOOL*);
|
typedef HRESULT (WINAPI * PFN_DwmIsCompositionEnabled)(BOOL*);
|
||||||
typedef HRESULT (WINAPI * PFN_DwmFlush)(VOID);
|
typedef HRESULT (WINAPI * PFN_DwmFlush)(VOID);
|
||||||
typedef HRESULT(WINAPI * DWMENABLEBLURBEHINDWINDOW_T)(HWND, const DWM_BLURBEHIND*);
|
typedef HRESULT(WINAPI * PFN_DwmEnableBlurBehindWindow)(HWND,const DWM_BLURBEHIND*);
|
||||||
#define DwmIsCompositionEnabled _glfw.win32.dwmapi.IsCompositionEnabled
|
#define DwmIsCompositionEnabled _glfw.win32.dwmapi.IsCompositionEnabled
|
||||||
#define DwmFlush _glfw.win32.dwmapi.Flush
|
#define DwmFlush _glfw.win32.dwmapi.Flush
|
||||||
#define _glfw_DwmEnableBlurBehindWindow _glfw.win32.dwmapi.DwmEnableBlurBehindWindow
|
#define DwmEnableBlurBehindWindow _glfw.win32.dwmapi.EnableBlurBehindWindow
|
||||||
|
|
||||||
// shcore.dll function pointer typedefs
|
// shcore.dll function pointer typedefs
|
||||||
typedef HRESULT (WINAPI * PFN_SetProcessDpiAwareness)(PROCESS_DPI_AWARENESS);
|
typedef HRESULT (WINAPI * PFN_SetProcessDpiAwareness)(PROCESS_DPI_AWARENESS);
|
||||||
|
@ -274,6 +267,8 @@ typedef struct _GLFWwindowWin32
|
||||||
GLFWbool frameAction;
|
GLFWbool frameAction;
|
||||||
GLFWbool iconified;
|
GLFWbool iconified;
|
||||||
GLFWbool maximized;
|
GLFWbool maximized;
|
||||||
|
// Whether to enable framebuffer transparency on DWM
|
||||||
|
GLFWbool transparent;
|
||||||
|
|
||||||
// The last received cursor position, regardless of source
|
// The last received cursor position, regardless of source
|
||||||
int lastCursorPosX, lastCursorPosY;
|
int lastCursorPosX, lastCursorPosY;
|
||||||
|
@ -325,7 +320,7 @@ typedef struct _GLFWlibraryWin32
|
||||||
HINSTANCE instance;
|
HINSTANCE instance;
|
||||||
PFN_DwmIsCompositionEnabled IsCompositionEnabled;
|
PFN_DwmIsCompositionEnabled IsCompositionEnabled;
|
||||||
PFN_DwmFlush Flush;
|
PFN_DwmFlush Flush;
|
||||||
DWMENABLEBLURBEHINDWINDOW_T DwmEnableBlurBehindWindow;
|
PFN_DwmEnableBlurBehindWindow EnableBlurBehindWindow;
|
||||||
} dwmapi;
|
} dwmapi;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
|
@ -388,6 +383,7 @@ typedef struct _GLFWmutexWin32
|
||||||
|
|
||||||
GLFWbool _glfwRegisterWindowClassWin32(void);
|
GLFWbool _glfwRegisterWindowClassWin32(void);
|
||||||
void _glfwUnregisterWindowClassWin32(void);
|
void _glfwUnregisterWindowClassWin32(void);
|
||||||
|
GLFWbool _glfwIsCompositionEnabledWin32(void);
|
||||||
|
|
||||||
WCHAR* _glfwCreateWideStringFromUTF8Win32(const char* source);
|
WCHAR* _glfwCreateWideStringFromUTF8Win32(const char* source);
|
||||||
char* _glfwCreateUTF8FromWideStringWin32(const WCHAR* source);
|
char* _glfwCreateUTF8FromWideStringWin32(const WCHAR* source);
|
||||||
|
|
|
@ -306,6 +306,55 @@ static void updateWindowStyles(const _GLFWwindow* window)
|
||||||
SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOZORDER);
|
SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOZORDER);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update window framebuffer transparency
|
||||||
|
//
|
||||||
|
static void updateFramebufferTransparency(const _GLFWwindow* window)
|
||||||
|
{
|
||||||
|
if (!IsWindowsVistaOrGreater())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (_glfwIsCompositionEnabledWin32())
|
||||||
|
{
|
||||||
|
HRGN region = CreateRectRgn(0, 0, -1, -1);
|
||||||
|
DWM_BLURBEHIND bb = {0};
|
||||||
|
bb.dwFlags = DWM_BB_ENABLE | DWM_BB_BLURREGION;
|
||||||
|
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 style = GetWindowLongW(window->win32.handle, GWL_EXSTYLE);
|
||||||
|
style |= WS_EX_LAYERED;
|
||||||
|
SetWindowLongW(window->win32.handle, GWL_EXSTYLE, style);
|
||||||
|
|
||||||
|
// 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(0, 193, 48), 255, LWA_COLORKEY);
|
||||||
|
}
|
||||||
|
|
||||||
|
DeleteObject(region);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LONG style = GetWindowLongW(window->win32.handle, GWL_EXSTYLE);
|
||||||
|
style &= ~WS_EX_LAYERED;
|
||||||
|
SetWindowLongW(window->win32.handle, GWL_EXSTYLE, style);
|
||||||
|
RedrawWindow(window->win32.handle, NULL, NULL,
|
||||||
|
RDW_ERASE | RDW_INVALIDATE | RDW_FRAME);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Translates a GLFW standard cursor to a resource ID
|
// Translates a GLFW standard cursor to a resource ID
|
||||||
//
|
//
|
||||||
static LPWSTR translateCursorShape(int shape)
|
static LPWSTR translateCursorShape(int shape)
|
||||||
|
@ -916,6 +965,13 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case WM_DWMCOMPOSITIONCHANGED:
|
||||||
|
{
|
||||||
|
if (window->win32.transparent)
|
||||||
|
updateFramebufferTransparency(window);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
case WM_SETCURSOR:
|
case WM_SETCURSOR:
|
||||||
{
|
{
|
||||||
if (LOWORD(lParam) == HTCLIENT)
|
if (LOWORD(lParam) == HTCLIENT)
|
||||||
|
@ -981,7 +1037,8 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
|
||||||
// Creates the GLFW window
|
// Creates the GLFW window
|
||||||
//
|
//
|
||||||
static int createNativeWindow(_GLFWwindow* window,
|
static int createNativeWindow(_GLFWwindow* window,
|
||||||
const _GLFWwndconfig* wndconfig)
|
const _GLFWwndconfig* wndconfig,
|
||||||
|
const _GLFWfbconfig* fbconfig)
|
||||||
{
|
{
|
||||||
int xpos, ypos, fullWidth, fullHeight;
|
int xpos, ypos, fullWidth, fullHeight;
|
||||||
WCHAR* wideTitle;
|
WCHAR* wideTitle;
|
||||||
|
@ -1051,6 +1108,12 @@ static int createNativeWindow(_GLFWwindow* window,
|
||||||
|
|
||||||
DragAcceptFiles(window->win32.handle, TRUE);
|
DragAcceptFiles(window->win32.handle, TRUE);
|
||||||
|
|
||||||
|
if (fbconfig->transparent)
|
||||||
|
{
|
||||||
|
updateFramebufferTransparency(window);
|
||||||
|
window->win32.transparent = GLFW_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
return GLFW_TRUE;
|
return GLFW_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1102,6 +1165,20 @@ void _glfwUnregisterWindowClassWin32(void)
|
||||||
UnregisterClassW(_GLFW_WNDCLASSNAME, GetModuleHandleW(NULL));
|
UnregisterClassW(_GLFW_WNDCLASSNAME, GetModuleHandleW(NULL));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns whether desktop compositing is enabled
|
||||||
|
//
|
||||||
|
GLFWbool _glfwIsCompositionEnabledWin32(void)
|
||||||
|
{
|
||||||
|
if (IsWindowsVistaOrGreater())
|
||||||
|
{
|
||||||
|
BOOL enabled;
|
||||||
|
if (SUCCEEDED(DwmIsCompositionEnabled(&enabled)))
|
||||||
|
return enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
////// GLFW platform API //////
|
////// GLFW platform API //////
|
||||||
|
@ -1112,7 +1189,7 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
|
||||||
const _GLFWctxconfig* ctxconfig,
|
const _GLFWctxconfig* ctxconfig,
|
||||||
const _GLFWfbconfig* fbconfig)
|
const _GLFWfbconfig* fbconfig)
|
||||||
{
|
{
|
||||||
if (!createNativeWindow(window, wndconfig))
|
if (!createNativeWindow(window, wndconfig, fbconfig))
|
||||||
return GLFW_FALSE;
|
return GLFW_FALSE;
|
||||||
|
|
||||||
if (ctxconfig->client != GLFW_NO_API)
|
if (ctxconfig->client != GLFW_NO_API)
|
||||||
|
@ -1481,6 +1558,11 @@ int _glfwPlatformWindowMaximized(_GLFWwindow* window)
|
||||||
return IsZoomed(window->win32.handle);
|
return IsZoomed(window->win32.handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int _glfwPlatformFramebufferTransparent(_GLFWwindow* window)
|
||||||
|
{
|
||||||
|
return window->win32.transparent && _glfwIsCompositionEnabledWin32();
|
||||||
|
}
|
||||||
|
|
||||||
void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled)
|
void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled)
|
||||||
{
|
{
|
||||||
updateWindowStyles(window);
|
updateWindowStyles(window);
|
||||||
|
|
|
@ -147,7 +147,6 @@ GLFWAPI GLFWwindow* glfwCreateWindow(int width, int height,
|
||||||
fbconfig = _glfw.hints.framebuffer;
|
fbconfig = _glfw.hints.framebuffer;
|
||||||
ctxconfig = _glfw.hints.context;
|
ctxconfig = _glfw.hints.context;
|
||||||
wndconfig = _glfw.hints.window;
|
wndconfig = _glfw.hints.window;
|
||||||
fbconfig.transparent = _glfw.hints.framebuffer.transparent ? GLFW_TRUE : GLFW_FALSE;
|
|
||||||
|
|
||||||
wndconfig.width = width;
|
wndconfig.width = width;
|
||||||
wndconfig.height = height;
|
wndconfig.height = height;
|
||||||
|
@ -728,6 +727,8 @@ GLFWAPI int glfwGetWindowAttrib(GLFWwindow* handle, int attrib)
|
||||||
return _glfwPlatformWindowVisible(window);
|
return _glfwPlatformWindowVisible(window);
|
||||||
case GLFW_MAXIMIZED:
|
case GLFW_MAXIMIZED:
|
||||||
return _glfwPlatformWindowMaximized(window);
|
return _glfwPlatformWindowMaximized(window);
|
||||||
|
case GLFW_TRANSPARENT:
|
||||||
|
return _glfwPlatformFramebufferTransparent(window);
|
||||||
case GLFW_RESIZABLE:
|
case GLFW_RESIZABLE:
|
||||||
return window->resizable;
|
return window->resizable;
|
||||||
case GLFW_DECORATED:
|
case GLFW_DECORATED:
|
||||||
|
|
|
@ -654,6 +654,13 @@ int _glfwPlatformWindowMaximized(_GLFWwindow* window)
|
||||||
return window->wl.maximized;
|
return window->wl.maximized;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int _glfwPlatformFramebufferTransparent(_GLFWwindow* window)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
|
"Wayland: Framebuffer transparency attribute not implemented yet");
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled)
|
void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled)
|
||||||
{
|
{
|
||||||
// TODO
|
// TODO
|
||||||
|
|
|
@ -651,6 +651,29 @@ static GLFWbool initExtensions(void)
|
||||||
dlsym(_glfw.x11.x11xcb.handle, "XGetXCBConnection");
|
dlsym(_glfw.x11.x11xcb.handle, "XGetXCBConnection");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_glfw.x11.xrender.handle = dlopen("libXrender.so.1", RTLD_LAZY | RTLD_GLOBAL);
|
||||||
|
if (_glfw.x11.xrender.handle)
|
||||||
|
{
|
||||||
|
_glfw.x11.xrender.QueryExtension = (PFN_XRenderQueryExtension)
|
||||||
|
dlsym(_glfw.x11.xrender.handle, "XRenderQueryExtension");
|
||||||
|
_glfw.x11.xrender.QueryVersion = (PFN_XRenderQueryVersion)
|
||||||
|
dlsym(_glfw.x11.xrender.handle, "XRenderQueryVersion");
|
||||||
|
_glfw.x11.xrender.FindVisualFormat = (PFN_XRenderFindVisualFormat)
|
||||||
|
dlsym(_glfw.x11.xrender.handle, "XRenderFindVisualFormat");
|
||||||
|
|
||||||
|
if (XRenderQueryExtension(_glfw.x11.display,
|
||||||
|
&_glfw.x11.xrender.errorBase,
|
||||||
|
&_glfw.x11.xrender.eventBase))
|
||||||
|
{
|
||||||
|
if (XRenderQueryVersion(_glfw.x11.display,
|
||||||
|
&_glfw.x11.xrender.major,
|
||||||
|
&_glfw.x11.xrender.minor))
|
||||||
|
{
|
||||||
|
_glfw.x11.xrender.available = GLFW_TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Update the key code LUT
|
// Update the key code LUT
|
||||||
// FIXME: We should listen to XkbMapNotify events to track changes to
|
// FIXME: We should listen to XkbMapNotify events to track changes to
|
||||||
// the keyboard mapping.
|
// the keyboard mapping.
|
||||||
|
@ -717,55 +740,6 @@ static GLFWbool initExtensions(void)
|
||||||
_glfw.x11.MOTIF_WM_HINTS =
|
_glfw.x11.MOTIF_WM_HINTS =
|
||||||
XInternAtom(_glfw.x11.display, "_MOTIF_WM_HINTS", False);
|
XInternAtom(_glfw.x11.display, "_MOTIF_WM_HINTS", False);
|
||||||
|
|
||||||
int i;
|
|
||||||
const char* sonames_xrender[] =
|
|
||||||
{
|
|
||||||
#if defined(__CYGWIN__)
|
|
||||||
"libXrender-1.so",
|
|
||||||
#else
|
|
||||||
"libXrender.so.1",
|
|
||||||
"libXrender.so",
|
|
||||||
#endif
|
|
||||||
NULL
|
|
||||||
};
|
|
||||||
|
|
||||||
// Xrender support is optional and not a requirement for GLX/EGL
|
|
||||||
// to work. Xrender is required for selecting a FB config that
|
|
||||||
// supports a picture format with an alpha mask, which in turn
|
|
||||||
// is required for transparent windows. I Xrender is not supported
|
|
||||||
// the GLFW_TRANSPARENT window hint is ignored.
|
|
||||||
for (i = 0; sonames_xrender[i]; i++)
|
|
||||||
{
|
|
||||||
_glfw.xrender.handle = dlopen(sonames_xrender[i], RTLD_LAZY | RTLD_GLOBAL);
|
|
||||||
if (_glfw.xrender.handle)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
_glfw.xrender.errorBase = 0;
|
|
||||||
_glfw.xrender.eventBase = 0;
|
|
||||||
_glfw.xrender.major = 0;
|
|
||||||
_glfw.xrender.minor = 0;
|
|
||||||
if (_glfw.xrender.handle) do {
|
|
||||||
int errorBase, eventBase, major, minor;
|
|
||||||
_glfw.xrender.QueryExtension =
|
|
||||||
dlsym(_glfw.xrender.handle, "XRenderQueryExtension");
|
|
||||||
_glfw.xrender.QueryVersion =
|
|
||||||
dlsym(_glfw.xrender.handle, "XRenderQueryVersion");
|
|
||||||
_glfw.xrender.FindVisualFormat =
|
|
||||||
dlsym(_glfw.xrender.handle, "XRenderFindVisualFormat");
|
|
||||||
|
|
||||||
if ( !XRenderQueryExtension(_glfw.x11.display, &errorBase, &eventBase)) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if ( !XRenderQueryVersion(_glfw.x11.display, &major, &minor)) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
_glfw.xrender.errorBase = errorBase;
|
|
||||||
_glfw.xrender.eventBase = eventBase;
|
|
||||||
_glfw.xrender.major = major;
|
|
||||||
_glfw.xrender.minor = minor;
|
|
||||||
} while(0);
|
|
||||||
|
|
||||||
return GLFW_TRUE;
|
return GLFW_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -116,6 +116,13 @@ typedef int (* PFN_XISelectEvents)(Display*,Window,XIEventMask*,int);
|
||||||
#define XIQueryVersion _glfw.x11.xi.QueryVersion
|
#define XIQueryVersion _glfw.x11.xi.QueryVersion
|
||||||
#define XISelectEvents _glfw.x11.xi.SelectEvents
|
#define XISelectEvents _glfw.x11.xi.SelectEvents
|
||||||
|
|
||||||
|
typedef Bool (* PFN_XRenderQueryExtension)(Display*,int*,int*);
|
||||||
|
typedef Status (* PFN_XRenderQueryVersion)(Display*dpy,int*,int*);
|
||||||
|
typedef XRenderPictFormat* (* PFN_XRenderFindVisualFormat)(Display*,Visual const*);
|
||||||
|
#define XRenderQueryExtension _glfw.x11.xrender.QueryExtension
|
||||||
|
#define XRenderQueryVersion _glfw.x11.xrender.QueryVersion
|
||||||
|
#define XRenderFindVisualFormat _glfw.x11.xrender.FindVisualFormat
|
||||||
|
|
||||||
typedef VkFlags VkXlibSurfaceCreateFlagsKHR;
|
typedef VkFlags VkXlibSurfaceCreateFlagsKHR;
|
||||||
typedef VkFlags VkXcbSurfaceCreateFlagsKHR;
|
typedef VkFlags VkXcbSurfaceCreateFlagsKHR;
|
||||||
|
|
||||||
|
@ -162,20 +169,10 @@ typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR)(Vk
|
||||||
#define _GLFW_EGL_NATIVE_DISPLAY ((EGLNativeDisplayType) _glfw.x11.display)
|
#define _GLFW_EGL_NATIVE_DISPLAY ((EGLNativeDisplayType) _glfw.x11.display)
|
||||||
|
|
||||||
#define _GLFW_PLATFORM_WINDOW_STATE _GLFWwindowX11 x11
|
#define _GLFW_PLATFORM_WINDOW_STATE _GLFWwindowX11 x11
|
||||||
#define _GLFW_PLATFORM_LIBRARY_WINDOW_STATE _GLFWlibraryX11 x11 ; _GLFWlibraryXrender xrender
|
#define _GLFW_PLATFORM_LIBRARY_WINDOW_STATE _GLFWlibraryX11 x11
|
||||||
#define _GLFW_PLATFORM_MONITOR_STATE _GLFWmonitorX11 x11
|
#define _GLFW_PLATFORM_MONITOR_STATE _GLFWmonitorX11 x11
|
||||||
#define _GLFW_PLATFORM_CURSOR_STATE _GLFWcursorX11 x11
|
#define _GLFW_PLATFORM_CURSOR_STATE _GLFWcursorX11 x11
|
||||||
|
|
||||||
// libXrender.so function pointer typedefs
|
|
||||||
typedef Bool (*PFNXRENDERQUERYEXTENSIONPROC)(Display*,int*,int*);
|
|
||||||
typedef Status (*PFNXRENDERQUERYVERSIONPROC)(Display*dpy,int*,int*);
|
|
||||||
typedef XRenderPictFormat* (*PFNXRENDERFINDVISUALFORMATPROC)(Display*,Visual const *);
|
|
||||||
|
|
||||||
// libXrender.so function identifier overlays
|
|
||||||
#define XRenderQueryExtension _glfw.xrender.QueryExtension
|
|
||||||
#define XRenderQueryVersion _glfw.xrender.QueryVersion
|
|
||||||
#define XRenderFindVisualFormat _glfw.xrender.FindVisualFormat
|
|
||||||
|
|
||||||
|
|
||||||
// X11-specific per-window data
|
// X11-specific per-window data
|
||||||
//
|
//
|
||||||
|
@ -189,6 +186,9 @@ typedef struct _GLFWwindowX11
|
||||||
GLFWbool iconified;
|
GLFWbool iconified;
|
||||||
GLFWbool maximized;
|
GLFWbool maximized;
|
||||||
|
|
||||||
|
// Whether the visual supports framebuffer transparency
|
||||||
|
GLFWbool transparent;
|
||||||
|
|
||||||
// Cached position and size used to filter out duplicate events
|
// Cached position and size used to filter out duplicate events
|
||||||
int width, height;
|
int width, height;
|
||||||
int xpos, ypos;
|
int xpos, ypos;
|
||||||
|
@ -383,24 +383,20 @@ typedef struct _GLFWlibraryX11
|
||||||
PFN_XISelectEvents SelectEvents;
|
PFN_XISelectEvents SelectEvents;
|
||||||
} xi;
|
} xi;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
GLFWbool available;
|
||||||
|
void* handle;
|
||||||
|
int major;
|
||||||
|
int minor;
|
||||||
|
int eventBase;
|
||||||
|
int errorBase;
|
||||||
|
PFN_XRenderQueryExtension QueryExtension;
|
||||||
|
PFN_XRenderQueryVersion QueryVersion;
|
||||||
|
PFN_XRenderFindVisualFormat FindVisualFormat;
|
||||||
|
} xrender;
|
||||||
|
|
||||||
} _GLFWlibraryX11;
|
} _GLFWlibraryX11;
|
||||||
|
|
||||||
// Xrender-specific global data
|
|
||||||
typedef struct _GLFWlibraryXrender
|
|
||||||
{
|
|
||||||
int major, minor;
|
|
||||||
int eventBase;
|
|
||||||
int errorBase;
|
|
||||||
|
|
||||||
// dlopen handle for libGL.so.1
|
|
||||||
void* handle;
|
|
||||||
|
|
||||||
// Xrender functions (subset required for transparent window)
|
|
||||||
PFNXRENDERQUERYEXTENSIONPROC QueryExtension;
|
|
||||||
PFNXRENDERQUERYVERSIONPROC QueryVersion;
|
|
||||||
PFNXRENDERFINDVISUALFORMATPROC FindVisualFormat;
|
|
||||||
} _GLFWlibraryXrender;
|
|
||||||
|
|
||||||
// X11-specific per-monitor data
|
// X11-specific per-monitor data
|
||||||
//
|
//
|
||||||
typedef struct _GLFWmonitorX11
|
typedef struct _GLFWmonitorX11
|
||||||
|
@ -434,6 +430,7 @@ unsigned long _glfwGetWindowPropertyX11(Window window,
|
||||||
Atom property,
|
Atom property,
|
||||||
Atom type,
|
Atom type,
|
||||||
unsigned char** value);
|
unsigned char** value);
|
||||||
|
GLFWbool _glfwIsVisualTransparentX11(Visual* visual);
|
||||||
|
|
||||||
void _glfwGrabErrorHandlerX11(void);
|
void _glfwGrabErrorHandlerX11(void);
|
||||||
void _glfwReleaseErrorHandlerX11(void);
|
void _glfwReleaseErrorHandlerX11(void);
|
||||||
|
|
|
@ -364,6 +364,7 @@ static void updateWindowMode(_GLFWwindow* window)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enable compositor bypass
|
// Enable compositor bypass
|
||||||
|
if (!window->x11.transparent)
|
||||||
{
|
{
|
||||||
const unsigned long value = 1;
|
const unsigned long value = 1;
|
||||||
|
|
||||||
|
@ -402,6 +403,7 @@ static void updateWindowMode(_GLFWwindow* window)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Disable compositor bypass
|
// Disable compositor bypass
|
||||||
|
if (!window->x11.transparent)
|
||||||
{
|
{
|
||||||
XDeleteProperty(_glfw.x11.display, window->x11.handle,
|
XDeleteProperty(_glfw.x11.display, window->x11.handle,
|
||||||
_glfw.x11.NET_WM_BYPASS_COMPOSITOR);
|
_glfw.x11.NET_WM_BYPASS_COMPOSITOR);
|
||||||
|
@ -577,6 +579,8 @@ static GLFWbool createNativeWindow(_GLFWwindow* window,
|
||||||
visual,
|
visual,
|
||||||
AllocNone);
|
AllocNone);
|
||||||
|
|
||||||
|
window->x11.transparent = _glfwIsVisualTransparentX11(visual);
|
||||||
|
|
||||||
// Create the actual window
|
// Create the actual window
|
||||||
{
|
{
|
||||||
XSetWindowAttributes wa;
|
XSetWindowAttributes wa;
|
||||||
|
@ -1838,6 +1842,15 @@ unsigned long _glfwGetWindowPropertyX11(Window window,
|
||||||
return itemCount;
|
return itemCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GLFWbool _glfwIsVisualTransparentX11(Visual* visual)
|
||||||
|
{
|
||||||
|
if (!_glfw.x11.xrender.available)
|
||||||
|
return GLFW_FALSE;
|
||||||
|
|
||||||
|
XRenderPictFormat* pf = XRenderFindVisualFormat(_glfw.x11.display, visual);
|
||||||
|
return pf && pf->direct.alphaMask;
|
||||||
|
}
|
||||||
|
|
||||||
// Push contents of our selection to clipboard manager
|
// Push contents of our selection to clipboard manager
|
||||||
//
|
//
|
||||||
void _glfwPushSelectionToManagerX11(void)
|
void _glfwPushSelectionToManagerX11(void)
|
||||||
|
@ -2422,6 +2435,18 @@ int _glfwPlatformWindowMaximized(_GLFWwindow* window)
|
||||||
return maximized;
|
return maximized;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int _glfwPlatformFramebufferTransparent(_GLFWwindow* window)
|
||||||
|
{
|
||||||
|
if (!window->x11.transparent)
|
||||||
|
return GLFW_FALSE;
|
||||||
|
|
||||||
|
// Check whether a compositing manager is running
|
||||||
|
char name[32];
|
||||||
|
snprintf(name, sizeof(name), "_NET_WM_CM_S%u", _glfw.x11.screen);
|
||||||
|
const Atom selection = XInternAtom(_glfw.x11.display, name, False);
|
||||||
|
return XGetSelectionOwner(_glfw.x11.display, selection) != None;
|
||||||
|
}
|
||||||
|
|
||||||
void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled)
|
void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled)
|
||||||
{
|
{
|
||||||
int width, height;
|
int width, height;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user