Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Option for transparent windows #197

Closed
nezumisama opened this issue Dec 28, 2013 · 119 comments
Closed

Option for transparent windows #197

nezumisama opened this issue Dec 28, 2013 · 119 comments
Assignees
Labels
enhancement Feature suggestions and PRs macOS Mir Wayland Windows Win32 specific (not Cygwin or WSL) X11
Milestone

Comments

@nezumisama
Copy link

On X11, when using a compositor/compositing WM, windows can have alpha-enabled visuals, allowing the application to specify opacity of each pixel. This is not however supported by GLFW now.

Here's some example code from Nvidia (note this works on Mesa as well): ftp://download.nvidia.com/XFree86/Linux-x86/177.70/README/chapter-23.html

I hacked together a version of glxgears with transparent background, for reference: https://gist.github.com/nezumisama/8161902

@retep998
Copy link

This feature is also supported on Windows, and is as simple as calling a few winapi calls to enable the alpha blending. However, as far as I've tested, it doesn't seem to work for fullscreen borderless windows.

@K-Zero
Copy link

K-Zero commented Dec 29, 2013

It would be great if GLFW support this. For Linux I only know GLX that can do that.
On X11/GLX it's just choosing the right FBConfig which nezumisama shows in his/her glxgears example on row 573.
I think in GLFW in glx_context.c you can change "chooseFBConfig" to select the right FBConfig, but I would rather use GLFW from the official repo instead of compiling it.

@elmindreda
Copy link
Member

This would be possible to add but is not something most people would use. Will review this again when 3.1 is out.

@nezumisama
Copy link
Author

I want this feature for my app. The alternative would be to use glx directly, but I'd rather not do that.
I managed to add this feature to GLFW (as a hard hint). Should I post a git diff somewhere?

@K-Zero
Copy link

K-Zero commented Dec 29, 2013

@nezumisama: I would love to see the git diff, please. I need this feature too.

@elmindreda: this is maybe true for games and so on, but I think not really for desktop apps like Widgets or others like cairo-docks which uses GLX to do that.

@retep998
Copy link

For windows vista and above

DWM_BLURBEHIND bb;
bb.dwFlags = DWM_BB_ENABLE;
bb.fEnable = true;
DwmEnableBlurBehindWindow(handle, &bb);

@nezumisama
Copy link
Author

@K-Zero: OK, here it is:

diff --git a/examples/gears.c b/examples/gears.c
index 2d44596..ef09df0 100644
--- a/examples/gears.c
+++ b/examples/gears.c
@@ -327,6 +327,9 @@ int main(int argc, char *argv[])
     }

     glfwWindowHint(GLFW_DEPTH_BITS, 16);
+    // Make the background transparent and hide decoration
+    glfwWindowHint(GLFW_ALPHA_MASK, GL_TRUE);
+    glfwWindowHint(GLFW_DECORATED, GL_FALSE);

     window = glfwCreateWindow( 300, 300, "Gears", NULL, NULL );
     if (!window)
diff --git a/include/GLFW/glfw3.h b/include/GLFW/glfw3.h
index 0f97738..f357e6e 100644
--- a/include/GLFW/glfw3.h
+++ b/include/GLFW/glfw3.h
@@ -511,6 +511,7 @@ extern "C" {
 #define GLFW_SAMPLES                0x0002100D
 #define GLFW_SRGB_CAPABLE           0x0002100E
 #define GLFW_REFRESH_RATE           0x0002100F
+#define GLFW_ALPHA_MASK             0x00021010

 #define GLFW_CLIENT_API             0x00022001
 #define GLFW_CONTEXT_VERSION_MAJOR  0x00022002
diff --git a/src/context.c b/src/context.c
index 3bc86bc..a8d0dd5 100644
--- a/src/context.c
+++ b/src/context.c
@@ -221,6 +221,11 @@ const _GLFWfbconfig* _glfwChooseFBConfig(const _GLFWfbconfig* desired,
             // Stereo is a hard constraint
             continue;
         }
+        if (desired->alphaMask > 0 && current->alphaMask == 0)
+        {
+            // Alpha mask is a hard constraint
+            continue;
+        }

         // Count number of missing buffers
         {
diff --git a/src/glx_context.c b/src/glx_context.c
index 6b87000..0c23fff 100644
--- a/src/glx_context.c
+++ b/src/glx_context.c
@@ -69,6 +69,8 @@ static GLboolean chooseFBConfig(const _GLFWfbconfig* desired, GLXFBConfig* resul
     int i, nativeCount, usableCount;
     const char* vendor;
     GLboolean trustWindowBit = GL_TRUE;
+    XVisualInfo *vi;
+    XRenderPictFormat *pf;

     vendor = glXGetClientString(_glfw.x11.display, GLX_VENDOR);
     if (strcmp(vendor, "Chromium") == 0)
@@ -145,6 +147,14 @@ static GLboolean chooseFBConfig(const _GLFWfbconfig* desired, GLXFBConfig* resul
         u->auxBuffers = getFBConfigAttrib(n, GLX_AUX_BUFFERS);
         u->stereo = getFBConfigAttrib(n, GLX_STEREO);

+        vi = glXGetVisualFromFBConfig(_glfw.x11.display, n);
+        if (vi)
+        {
+            pf = XRenderFindVisualFormat(_glfw.x11.display, vi->visual);
+            if (pf)
+                u->alphaMask = pf->direct.alphaMask;
+        }
+
         if (_glfw.glx.ARB_multisample)
             u->samples = getFBConfigAttrib(n, GLX_SAMPLES);

@@ -161,6 +171,7 @@ static GLboolean chooseFBConfig(const _GLFWfbconfig* desired, GLXFBConfig* resul

     XFree(nativeConfigs);
     free(usableConfigs);
+    if (vi) XFree(vi);

     return closest ? GL_TRUE : GL_FALSE;
 }
diff --git a/src/internal.h b/src/internal.h
index 8a24959..014515b 100644
--- a/src/internal.h
+++ b/src/internal.h
@@ -185,6 +185,7 @@ struct _GLFWfbconfig
     GLboolean   stereo;
     int         samples;
     GLboolean   sRGB;
+    GLboolean   alphaMask;

     // This is defined in the context API's platform.h
     _GLFW_PLATFORM_FBCONFIG;
@@ -289,6 +290,7 @@ struct _GLFWlibrary
         GLboolean   resizable;
         GLboolean   visible;
         GLboolean   decorated;
+        GLboolean   alphaMask;
         int         samples;
         GLboolean   sRGB;
         int         refreshRate;
diff --git a/src/window.c b/src/window.c
index 4e2b277..db43c58 100644
--- a/src/window.c
+++ b/src/window.c
@@ -173,6 +173,7 @@ GLFWAPI GLFWwindow* glfwCreateWindow(int width, int height,
     fbconfig.stereo         = _glfw.hints.stereo ? GL_TRUE : GL_FALSE;
     fbconfig.samples        = Max(_glfw.hints.samples, 0);
     fbconfig.sRGB           = _glfw.hints.sRGB ? GL_TRUE : GL_FALSE;
+    fbconfig.alphaMask      = _glfw.hints.alphaMask ? GL_TRUE : GL_FALSE;

     // Set up desired window config
     wndconfig.width         = width;
@@ -284,6 +285,7 @@ void glfwDefaultWindowHints(void)
     _glfw.hints.alphaBits   = 8;
     _glfw.hints.depthBits   = 24;
     _glfw.hints.stencilBits = 8;
+    _glfw.hints.alphaMask   = GL_FALSE;
 }

 GLFWAPI void glfwWindowHint(int target, int hint)
@@ -367,6 +369,9 @@ GLFWAPI void glfwWindowHint(int target, int hint)
         case GLFW_OPENGL_PROFILE:
             _glfw.hints.glProfile = hint;
             break;
+        case GLFW_ALPHA_MASK:
+            _glfw.hints.alphaMask = hint;
+            break;
         default:
             _glfwInputError(GLFW_INVALID_ENUM, NULL);
             break;

Not sure if this exactly how it should be done, but it should work.

This requires the xrender extension. Xrender is required by xrandr, so this links and works without -lXrender flag for the linker, but maybe that flag should be added (I don't know how to use cmake, so I don't know where to add it).

@r-lyeh-archived
Copy link

i'd love to see this too :)

@elmindreda elmindreda added this to the 3.2 milestone Mar 6, 2014
@elmindreda elmindreda changed the title No option for transparent windows on X11 Option for transparent windows Jun 10, 2014
@1l0
Copy link

1l0 commented Jul 3, 2014

I'd like it too.

@andsve
Copy link

andsve commented Jul 16, 2014

I want this too... :)

I've started a branch trying to add support, implemented it for the OSX platform which seems to work: 7db465f. I'm using @nezumisama code as a starting point, i.e. GLFW_ALPHA_MASK window hint. Will try to add support for Windows soon, but I won't have access to a Linux box so if anyone wants to help out it would be appreciated. Or if @nezumisama code still works I might just borrow it?

@slimsag
Copy link
Contributor

slimsag commented Aug 31, 2014

@andsve have you had any luck with this on Windows or Linux ? I'm really interested.

@andsve
Copy link

andsve commented Sep 5, 2014

@slimsag Hey, I haven't had the time to look into it sadly... However, I have a windows machine again at my disposal so will try to do some testing soonish! Let me know if you have any luck on your end.

@slimsag
Copy link
Contributor

slimsag commented Sep 6, 2014

@andsve thank you for the response! Hopefully I get the chance to look into it sometime. If you need any testing done on Linux(X11), Windows, or OS X done please let me know.

@nezumisama
Copy link
Author

@andsve my patch should work on recent versions of Xorg (on GNU/Linux and FreeBSD, and other OSes).
@slimsag you could try that patch then.

@andrewrk
Copy link

I'm interested in this feature for the purpose of creating a GUI toolkit, for example a menu with a drop shadow.

@r-lyeh-archived
Copy link

same here, GUI purposes

@andsve
Copy link

andsve commented Mar 11, 2015

Funny thing, I'm also in need of it myself at the moment. I'll see if I have time to look into it this weekend, I think my branch is way out of sync with GLFW3 etc...

@andsve
Copy link

andsve commented Apr 14, 2015

Hey, if anyone is still interested in this, I just pushed a fix for Windows on this branch: https://github.com/andsve/glfw/tree/transparent-windows

Interested in hearing if it works or not for everyone else.

Haven't tested my OS X chnages since I last worked on this, so will do that next. Then maybe try integrating the Linux stuff from above in this thread.

Edit: OS X seems to be working. :)
screen shot 2015-03-09 at 1 49 24 pm
windows_glfw_transparent

@tombsar
Copy link
Contributor

tombsar commented Apr 14, 2015

Interested in hearing if it works or not for everyone else.

Works perfectly for me. Windows 8.1 64 bit (but building glfw as 32 bit) with Nvidia drivers.

@andsve
Copy link

andsve commented Apr 14, 2015

Tried to use the supplied X11 related changes that @nezumisama posted above, but I can't get it to work. I'm however running a debian install inside VirtualBox so I can't say for sure... Anyone with a Linux box that would like to apply this (using transparent-windows branch) and give it a try?

diff --git a/src/glx_context.c b/src/glx_context.c
index ec34e8f..28f0f7c 100644
--- a/src/glx_context.c
+++ b/src/glx_context.c
@@ -60,6 +60,8 @@ static GLboolean chooseFBConfig(const _GLFWfbconfig* desired, GLXFBConfig* resul
     int i, nativeCount, usableCount;
     const char* vendor;
     GLboolean trustWindowBit = GL_TRUE;
+    XVisualInfo *vi;
+    XRenderPictFormat *pf;

     vendor = glXGetClientString(_glfw.x11.display, GLX_VENDOR);
     if (strcmp(vendor, "Chromium") == 0)
@@ -126,6 +128,14 @@ static GLboolean chooseFBConfig(const _GLFWfbconfig* desired, GLXFBConfig* resul
         if (getFBConfigAttrib(n, GLX_DOUBLEBUFFER))
             u->doublebuffer = GL_TRUE;

+        vi = glXGetVisualFromFBConfig(_glfw.x11.display, n);
+        if (vi)
+        {
+            pf = XRenderFindVisualFormat(_glfw.x11.display, vi->visual);
+            if (pf)
+                u->alphaMask = pf->direct.alphaMask;
+        }
+
         if (_glfw.glx.ARB_multisample)
             u->samples = getFBConfigAttrib(n, GLX_SAMPLES);

@@ -142,6 +152,7 @@ static GLboolean chooseFBConfig(const _GLFWfbconfig* desired, GLXFBConfig* resul

     XFree(nativeConfigs);
     free(usableConfigs);
+    if (vi) XFree(vi);

     return closest ? GL_TRUE : GL_FALSE;
 }

@andrewrk
Copy link

@andsve

andy@andy-bx:~/Downloads/glfw/build$ make
[ 24%] Built target glfw
Linking C executable boing
/usr/bin/ld: ../src/libglfw3.a(glx_context.c.o): undefined reference to symbol 'XRenderFindVisualFormat'
/usr/lib/x86_64-linux-gnu/libXrender.so.1: error adding symbols: DSO missing from command line
collect2: error: ld returned 1 exit status
examples/CMakeFiles/boing.dir/build.make:96: recipe for target 'examples/boing' failed
make[2]: *** [examples/boing] Error 1
CMakeFiles/Makefile2:170: recipe for target 'examples/CMakeFiles/boing.dir/all' failed
make[1]: *** [examples/CMakeFiles/boing.dir/all] Error 2
Makefile:113: recipe for target 'all' failed
make: *** [all] Error 2

@andsve
Copy link

andsve commented Apr 14, 2015

Strange, what dist? I don't get any transparent window, but at least it compiles here.
Installed xorg-dev and libglu1-mesa-dev? Does it compile without the patch?

@andrewrk
Copy link

Ubuntu 14.10 Utopic Unicorn. I did not have xorg-dev installed, but after installing it, got the same error. Also, shouldn't cmake catch that?

Compiles fine without the patch. Running the transparent example yields: GLX: Failed to find a suitable GLXFBConfig

glxinfo:
OpenGL renderer string: GeForce GTX 780M/PCIe/SSE2
OpenGL version string: 4.5.0 NVIDIA 346.47

elmindreda added a commit that referenced this issue Sep 19, 2017
Fixes #197.
Related to #663.
Related to #715.
Related to #723.
Related to #1078.
elmindreda pushed a commit that referenced this issue Sep 19, 2017
This is a squashed extract of several commits, minimally edited to
ensure it compiles.

Related to #197.
Related to #715.
elmindreda pushed a commit that referenced this issue Sep 19, 2017
This is a squashed extract of several commits, minimally edited to
ensure it compiles.

Related to #197.
Related to #723.
elmindreda pushed a commit that referenced this issue Sep 19, 2017
This is an extract of a commit, minimally edited to ensure it compiles.

Closes #663.
Related to #197.
elmindreda pushed a commit that referenced this issue Sep 19, 2017
This is an extract of a commit, minimally edited to ensure it compiles.

Closes #1078.
Related to #197.
elmindreda added a commit that referenced this issue Sep 19, 2017
Fixes #197.
Related to #663.
Related to #715.
Related to #723.
Related to #1078.
@elmindreda
Copy link
Member

Please see if the transparent-window branch works for you. It should support Windows, macOS and X11.

If you have a corresponding local branch you may need to reset it.

@andsve
Copy link

andsve commented Sep 20, 2017

@elmindreda Tested transparent-window on macOS Sierra (10.12.6), worked fine! Super glad this old thread has been revived. ❤️

@elmindreda
Copy link
Member

@andsve Yay, thank you for testing!

I'll be away until Sunday. If no serious issues turn up, I will merge this next week. I believe the only thing left to do besides testing is a tiny bit of documentation.

The only issue I've found so far is that the content area alpha channel on OS X 10.10.5 doesn't seem to be updated after the first frame. I don't consider that to be blocking.

Things that (as far as I know) haven't been tested yet: WIndows Vista, 8 and 8.1, Radeon and Intel HD Windows OpenGL drivers as well as any X11 compositor other than Compton and Compiz. The code is based on the work you guys did but I've made changes on all platforms and may have broken something.

@tombsar
Copy link
Contributor

tombsar commented Sep 20, 2017

Seems to work fine with XFCE's built-in compositor (Debian 8, Nvidia graphics). I can also test on Windows 8.1 (Nvidia) and Windows 10 (Intel) over the next few days.

@thomthom
Copy link

Tried on my MacBook Pro running Windows 10, Visual Studio 2017, nVidia GeForce GT 650M.
32bit Release Build (default of CMake, forgot to add x64 flags).

Worked perfectly out of the box! :D

transparentgears

@thomthom
Copy link

Ditto for x64 Release and Debug builds. (Note, this was just me running the gears example. I didn't run tests.)

@tombsar
Copy link
Contributor

tombsar commented Sep 20, 2017

Is there any way to check if the transparency hint succeeded or failed? On XFCE with desktop compositing disabled the gears window is non-transparent, but there is no warning or error printed to the console. (This doesn't bother me at all, but might be a good feature to add and/or document)

@cosier
Copy link
Contributor

cosier commented Sep 21, 2017

If framebuffer selection fails due to lack of transparency, it simply trys again (silently) for a configuration without transparency.

Internally, the framebuffer hint will actually remain true, even upon failure. So that could be a possible issue in regards of checking in the future for success/failure.

There was an api for checking after the fact if the transparency hint was applied to the window.
But after some refactoring, that mechanism disapeared from the window configuration.

Maybe we can add a similar kind of checking to see if it was successful?
In my opinion, the fallback is quite graceful though.

@cosier
Copy link
Contributor

cosier commented Sep 21, 2017

I have created a pull request (#1079) which adds the ability to check for this outcome, along with updating the docs and the gears example with a print to stderr.

@tombsar On XFCE, you should see a printout in the console (after #1079 is merged.)

@thomthom
Copy link

Having a way to check the success would be good IMO. I have an application I want to create which rely on transparent background. If that fails I would want a way to handle/message that.

@ckaran
Copy link
Contributor

ckaran commented Sep 22, 2017

@cosier This is fantastic, thank you for making this happen! 👍

@elmindreda
Copy link
Member

elmindreda commented Sep 24, 2017

Here are things that remain to be done. More items may be added as we think of them, but not all of them are blocking for merge or release.

  • GLFW_TRANSPARENT window attribute
  • Disable _NET_WM_BYPASS_COMPOSITOR on X11 (blocking)
  • Wayland support
  • Mir support
  • Proper documentation (reference, window guide, compatibility guide, platform remarks) (blocking)
  • Delay-enable when DWM is enabled on Windows

elmindreda pushed a commit that referenced this issue Sep 27, 2017
This is a squashed extract of several commits, minimally edited to
ensure it compiles.

Related to #197.
Related to #715.
elmindreda pushed a commit that referenced this issue Sep 27, 2017
This is a squashed extract of several commits, minimally edited to
ensure it compiles.

Related to #197.
Related to #723.
elmindreda pushed a commit that referenced this issue Sep 27, 2017
This is an extract of a commit, minimally edited to ensure it compiles.

Closes #663.
Related to #197.
elmindreda pushed a commit that referenced this issue Sep 27, 2017
This is an extract of a commit, minimally edited to ensure it compiles.

Closes #1078.
Related to #197.
@elmindreda
Copy link
Member

Support for transparent window framebuffers has been merged. Thank you to everyone who contributed and apologies for the long wait.

@ivanstepanovftw
Copy link

How to destroy input shape and set CWOwerrideRedirect attribute?

@elmindreda
Copy link
Member

elmindreda commented Sep 28, 2017

@ashftw This addition doesn't include support for custom window shapes. There's currently no way to explicitly make a window override-redirect.

@elmindreda
Copy link
Member

If anyone here is interested in the other kind of window transparency, where you specify a single alpha value for the whole window including decorations, there is now an issue (#1089) for it. There is an initial implementation as well, but I won't have time to publish it until next week at the earliest.

This will very likely force a rename of the GLFW_TRANSPARENT constant but no changes in behavior. If you're using this feature it's just search-and-replace for this one thing. The renaming is to avoid the following:

glfwWindowHint(GLFW_TRANSPARENT, GLFW_FALSE);
glfwWindowHint(GLFW_OPACITY, 23);

...which will confusingly yield a transparent window.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement Feature suggestions and PRs macOS Mir Wayland Windows Win32 specific (not Cygwin or WSL) X11
Projects
None yet
Development

No branches or pull requests