如何在linux上制作透明窗口
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/9363491/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to make transparent window on linux
提问by themean
I want to make application an application with a splash screen on Linux.
我想让应用程序成为 Linux 上带有启动画面的应用程序。
I want to use X11 and glx (OpenGL application).
我想使用 X11 和 glx(OpenGL 应用程序)。
I've found a way to remove the border around the window, but I can't find how to make it transparent. How can I accomplish this?
我找到了一种去除窗口周围边框的方法,但我找不到如何使其透明。我怎样才能做到这一点?
采纳答案by Jonathan Henson
This is definitely something that you will want to offload to the GPU. I would not recommend directly using the X11 lib for performance reasons. Let OpenGL do it. I did find the following link for glXChooseVisual.
这绝对是您想要卸载到 GPU 的东西。出于性能原因,我不建议直接使用 X11 库。让 OpenGL 来做。我确实找到了glXChooseVisual的以下链接。
Also, hereis another S.O. question that may be helpful.
此外,这是另一个可能有帮助的 SO 问题。
Furthermore, thisis for windows, but it should still apply.
此外,这适用于 Windows,但它仍应适用。
回答by themean
This is the real answer of my question
这是我问题的真正答案
/*------------------------------------------------------------------------
* A demonstration of OpenGL in a ARGB window
* => support for composited window transparency
*
* (c) 2011 by Wolfgang 'datenwolf' Draxinger
* See me at comp.graphics.api.opengl and StackOverflow.com
* License agreement: This source code is provided "as is". You
* can use this source code however you want for your own personal
* use. If you give this source code to anybody else then you must
* leave this message in it.
*
* This program is based on the simplest possible
* Linux OpenGL program by FTB (see info below)
The simplest possible Linux OpenGL program? Maybe...
(c) 2002 by FTB. See me in comp.graphics.api.opengl
--
<\___/>
/ O O \
\_____/ FTB.
------------------------------------------------------------------------*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <GL/gl.h>
#include <GL/glx.h>
#include <GL/glxext.h>
#include <X11/Xatom.h>
#include <X11/extensions/Xrender.h>
#include <X11/Xutil.h>
#define USE_CHOOSE_FBCONFIG
static void fatalError(const char *why)
{
fprintf(stderr, "%s", why);
exit(0x666);
}
static int Xscreen;
static Atom del_atom;
static Colormap cmap;
static Display *Xdisplay;
static XVisualInfo *visual;
static XRenderPictFormat *pict_format;
static GLXFBConfig *fbconfigs, fbconfig;
static int numfbconfigs;
static GLXContext render_context;
static Window Xroot, window_handle;
static GLXWindow glX_window_handle;
static int width, height;
static int VisData[] = {
GLX_RENDER_TYPE, GLX_RGBA_BIT,
GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,
GLX_DOUBLEBUFFER, True,
GLX_RED_SIZE, 8,
GLX_GREEN_SIZE, 8,
GLX_BLUE_SIZE, 8,
GLX_ALPHA_SIZE, 8,
GLX_DEPTH_SIZE, 16,
None
};
static int isExtensionSupported(const char *extList, const char *extension)
{
const char *start;
const char *where, *terminator;
/* Extension names should not have spaces. */
where = strchr(extension, ' ');
if ( where || *extension == '##代码##' )
return 0;
/* It takes a bit of care to be fool-proof about parsing the
OpenGL extensions string. Don't be fooled by sub-strings,
etc. */
for ( start = extList; ; ) {
where = strstr( start, extension );
if ( !where )
break;
terminator = where + strlen( extension );
if ( where == start || *(where - 1) == ' ' )
if ( *terminator == ' ' || *terminator == '##代码##' )
return 1;
start = terminator;
}
return 0;
}
static Bool WaitForMapNotify(Display *d, XEvent *e, char *arg)
{
return d && e && arg && (e->type == MapNotify) && (e->xmap.window == *(Window*)arg);
}
static void describe_fbconfig(GLXFBConfig fbconfig)
{
int doublebuffer;
int red_bits, green_bits, blue_bits, alpha_bits, depth_bits;
glXGetFBConfigAttrib(Xdisplay, fbconfig, GLX_DOUBLEBUFFER, &doublebuffer);
glXGetFBConfigAttrib(Xdisplay, fbconfig, GLX_RED_SIZE, &red_bits);
glXGetFBConfigAttrib(Xdisplay, fbconfig, GLX_GREEN_SIZE, &green_bits);
glXGetFBConfigAttrib(Xdisplay, fbconfig, GLX_BLUE_SIZE, &blue_bits);
glXGetFBConfigAttrib(Xdisplay, fbconfig, GLX_ALPHA_SIZE, &alpha_bits);
glXGetFBConfigAttrib(Xdisplay, fbconfig, GLX_DEPTH_SIZE, &depth_bits);
fprintf(stderr, "FBConfig selected:\n"
"Doublebuffer: %s\n"
"Red Bits: %d, Green Bits: %d, Blue Bits: %d, Alpha Bits: %d, Depth Bits: %d\n",
doublebuffer == True ? "Yes" : "No",
red_bits, green_bits, blue_bits, alpha_bits, depth_bits);
}
static void createTheWindow()
{
XEvent event;
int x,y, attr_mask;
XSizeHints hints;
XWMHints *startup_state;
XTextProperty textprop;
XSetWindowAttributes attr = {0,};
static char *title = "FTB's little OpenGL example - ARGB extension by WXD";
Xdisplay = XOpenDisplay(NULL);
if (!Xdisplay) {
fatalError("Couldn't connect to X server\n");
}
Xscreen = DefaultScreen(Xdisplay);
Xroot = RootWindow(Xdisplay, Xscreen);
fbconfigs = glXChooseFBConfig(Xdisplay, Xscreen, VisData, &numfbconfigs);
fbconfig = 0;
for(int i = 0; i<numfbconfigs; i++) {
visual = (XVisualInfo*) glXGetVisualFromFBConfig(Xdisplay, fbconfigs[i]);
if(!visual)
continue;
pict_format = XRenderFindVisualFormat(Xdisplay, visual->visual);
if(!pict_format)
continue;
fbconfig = fbconfigs[i];
if(pict_format->direct.alphaMask > 0) {
break;
}
}
if(!fbconfig) {
fatalError("No matching FB config found");
}
describe_fbconfig(fbconfig);
/* Create a colormap - only needed on some X clients, eg. IRIX */
cmap = XCreateColormap(Xdisplay, Xroot, visual->visual, AllocNone);
attr.colormap = cmap;
attr.background_pixmap = None;
attr.border_pixmap = None;
attr.border_pixel = 0;
attr.event_mask =
StructureNotifyMask |
EnterWindowMask |
LeaveWindowMask |
ExposureMask |
ButtonPressMask |
ButtonReleaseMask |
OwnerGrabButtonMask |
KeyPressMask |
KeyReleaseMask;
attr_mask =
CWBackPixmap|
CWColormap|
CWBorderPixel|
CWEventMask;
width = DisplayWidth(Xdisplay, DefaultScreen(Xdisplay))/2;
height = DisplayHeight(Xdisplay, DefaultScreen(Xdisplay))/2;
x=width/2, y=height/2;
window_handle = XCreateWindow( Xdisplay,
Xroot,
x, y, width, height,
0,
visual->depth,
InputOutput,
visual->visual,
attr_mask, &attr);
if( !window_handle ) {
fatalError("Couldn't create the window\n");
}
#if USE_GLX_CREATE_WINDOW
int glXattr[] = { None };
glX_window_handle = glXCreateWindow(Xdisplay, fbconfig, window_handle, glXattr);
if( !glX_window_handle ) {
fatalError("Couldn't create the GLX window\n");
}
#else
glX_window_handle = window_handle;
#endif
textprop.value = (unsigned char*)title;
textprop.encoding = XA_STRING;
textprop.format = 8;
textprop.nitems = strlen(title);
hints.x = x;
hints.y = y;
hints.width = width;
hints.height = height;
hints.flags = USPosition|USSize;
startup_state = XAllocWMHints();
startup_state->initial_state = NormalState;
startup_state->flags = StateHint;
XSetWMProperties(Xdisplay, window_handle,&textprop, &textprop,
NULL, 0,
&hints,
startup_state,
NULL);
XFree(startup_state);
XMapWindow(Xdisplay, window_handle);
XIfEvent(Xdisplay, &event, WaitForMapNotify, (char*)&window_handle);
if ((del_atom = XInternAtom(Xdisplay, "WM_DELETE_WINDOW", 0)) != None) {
XSetWMProtocols(Xdisplay, window_handle, &del_atom, 1);
}
}
static int ctxErrorHandler( Display *dpy, XErrorEvent *ev )
{
fputs("Error at context creation", stderr);
return 0;
}
static void createTheRenderContext()
{
int dummy;
if (!glXQueryExtension(Xdisplay, &dummy, &dummy)) {
fatalError("OpenGL not supported by X server\n");
}
#if USE_GLX_CREATE_CONTEXT_ATTRIB
#define GLX_CONTEXT_MAJOR_VERSION_ARB 0x2091
#define GLX_CONTEXT_MINOR_VERSION_ARB 0x2092
render_context = NULL;
if( isExtensionSupported( glXQueryExtensionsString(Xdisplay, DefaultScreen(Xdisplay)), "GLX_ARB_create_context" ) ) {
typedef GLXContext (*glXCreateContextAttribsARBProc)(Display*, GLXFBConfig, GLXContext, Bool, const int*);
glXCreateContextAttribsARBProc glXCreateContextAttribsARB = (glXCreateContextAttribsARBProc)glXGetProcAddressARB( (const GLubyte *) "glXCreateContextAttribsARB" );
if( glXCreateContextAttribsARB ) {
int context_attribs[] =
{
GLX_CONTEXT_MAJOR_VERSION_ARB, 3,
GLX_CONTEXT_MINOR_VERSION_ARB, 0,
//GLX_CONTEXT_FLAGS_ARB , GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB,
None
};
int (*oldHandler)(Display*, XErrorEvent*) = XSetErrorHandler(&ctxErrorHandler);
render_context = glXCreateContextAttribsARB( Xdisplay, fbconfig, 0, True, context_attribs );
XSync( Xdisplay, False );
XSetErrorHandler( oldHandler );
fputs("glXCreateContextAttribsARB failed", stderr);
} else {
fputs("glXCreateContextAttribsARB could not be retrieved", stderr);
}
} else {
fputs("glXCreateContextAttribsARB not supported", stderr);
}
if(!render_context)
{
#else
{
#endif
render_context = glXCreateNewContext(Xdisplay, fbconfig, GLX_RGBA_TYPE, 0, True);
if (!render_context) {
fatalError("Failed to create a GL context\n");
}
}
if (!glXMakeContextCurrent(Xdisplay, glX_window_handle, glX_window_handle, render_context)) {
fatalError("glXMakeCurrent failed for window\n");
}
}
static int updateTheMessageQueue()
{
XEvent event;
XConfigureEvent *xc;
while (XPending(Xdisplay))
{
XNextEvent(Xdisplay, &event);
switch (event.type)
{
case ClientMessage:
if (event.xclient.data.l[0] == del_atom)
{
return 0;
}
break;
case ConfigureNotify:
xc = &(event.xconfigure);
width = xc->width;
height = xc->height;
break;
}
}
return 1;
}
/* 6----7
/| /|
3----2 |
| 5--|-4
|/ |/
0----1
*/
GLfloat cube_vertices[][8] = {
/* X Y Z Nx Ny Nz S T */
{-1.0, -1.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0}, // 0
{ 1.0, -1.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0}, // 1
{ 1.0, 1.0, 1.0, 0.0, 0.0, 1.0, 1.0, 1.0}, // 2
{-1.0, 1.0, 1.0, 0.0, 0.0, 1.0, 0.0, 1.0}, // 3
{ 1.0, -1.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0}, // 4
{-1.0, -1.0, -1.0, 0.0, 0.0, -1.0, 1.0, 0.0}, // 5
{-1.0, 1.0, -1.0, 0.0, 0.0, -1.0, 1.0, 1.0}, // 6
{ 1.0, 1.0, -1.0, 0.0, 0.0, -1.0, 0.0, 1.0}, // 7
{-1.0, -1.0, -1.0, -1.0, 0.0, 0.0, 0.0, 0.0}, // 5
{-1.0, -1.0, 1.0, -1.0, 0.0, 0.0, 1.0, 0.0}, // 0
{-1.0, 1.0, 1.0, -1.0, 0.0, 0.0, 1.0, 1.0}, // 3
{-1.0, 1.0, -1.0, -1.0, 0.0, 0.0, 0.0, 1.0}, // 6
{ 1.0, -1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0}, // 1
{ 1.0, -1.0, -1.0, 1.0, 0.0, 0.0, 1.0, 0.0}, // 4
{ 1.0, 1.0, -1.0, 1.0, 0.0, 0.0, 1.0, 1.0}, // 7
{ 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 1.0}, // 2
{-1.0, -1.0, -1.0, 0.0, -1.0, 0.0, 0.0, 0.0}, // 5
{ 1.0, -1.0, -1.0, 0.0, -1.0, 0.0, 1.0, 0.0}, // 4
{ 1.0, -1.0, 1.0, 0.0, -1.0, 0.0, 1.0, 1.0}, // 1
{-1.0, -1.0, 1.0, 0.0, -1.0, 0.0, 0.0, 1.0}, // 0
{-1.0, 1.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0}, // 3
{ 1.0, 1.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0}, // 2
{ 1.0, 1.0, -1.0, 0.0, 1.0, 0.0, 1.0, 1.0}, // 7
{-1.0, 1.0, -1.0, 0.0, 1.0, 0.0, 0.0, 1.0}, // 6
};
static void draw_cube(void)
{
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glVertexPointer(3, GL_FLOAT, sizeof(GLfloat) * 8, &cube_vertices[0][0]);
glNormalPointer(GL_FLOAT, sizeof(GLfloat) * 8, &cube_vertices[0][3]);
glTexCoordPointer(2, GL_FLOAT, sizeof(GLfloat) * 8, &cube_vertices[0][6]);
glDrawArrays(GL_QUADS, 0, 24);
}
float const light0_dir[]={0,1,0,0};
float const light0_color[]={78./255., 80./255., 184./255.,1};
float const light1_dir[]={-1,1,1,0};
float const light1_color[]={255./255., 220./255., 97./255.,1};
float const light2_dir[]={0,-1,0,0};
float const light2_color[]={31./255., 75./255., 16./255.,1};
static void redrawTheWindow()
{
float const aspect = (float)width / (float)height;
static float a=0;
static float b=0;
static float c=0;
glDrawBuffer(GL_BACK);
glViewport(0, 0, width, height);
// Clear with alpha = 0.0, i.e. full transparency
glClearColor(0.0, 0.0, 0.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum(-aspect, aspect, -1, 1, 2.5, 10);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glLightfv(GL_LIGHT0, GL_POSITION, light0_dir);
glLightfv(GL_LIGHT0, GL_DIFFUSE, light0_color);
glLightfv(GL_LIGHT1, GL_POSITION, light1_dir);
glLightfv(GL_LIGHT1, GL_DIFFUSE, light1_color);
glLightfv(GL_LIGHT2, GL_POSITION, light2_dir);
glLightfv(GL_LIGHT2, GL_DIFFUSE, light2_color);
glTranslatef(0., 0., -5.);
glRotatef(a, 1, 0, 0);
glRotatef(b, 0, 1, 0);
glRotatef(c, 0, 0, 1);
glEnable(GL_LIGHT0);
glEnable(GL_LIGHT1);
glEnable(GL_LIGHTING);
glEnable(GL_COLOR_MATERIAL);
glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
glColor4f(1., 1., 1., 0.5);
glCullFace(GL_FRONT);
draw_cube();
glCullFace(GL_BACK);
draw_cube();
a = fmod(a+0.1, 360.);
b = fmod(b+0.5, 360.);
c = fmod(c+0.25, 360.);
glXSwapBuffers(Xdisplay, glX_window_handle);
}
int main(int argc, char *argv[])
{
createTheWindow();
createTheRenderContext();
while (updateTheMessageQueue()) {
redrawTheWindow();
}
return 0;
}
I take this from thislink I spend 10-15 min to find difference between this example and my code and 3-4 hours to get on my mind that i must change something on KDE Thank for solicitude
我从这个链接中得到这个我花了 10-15 分钟来找出这个例子和我的代码之间的区别,3-4 小时让我想起我必须在 KDE 上改变一些东西谢谢你的关心
回答by Yann Droneaud
In order to have a transparent window under X11, you need
为了在X11下有一个透明的窗口,你需要
- an X11 server with composite extension
- a composite manager
- an ARGB visual for your window
- 带有复合扩展的 X11 服务器
- 复合管理器
- 窗口的 ARGB 视觉效果
You don't need to use OpenGL directly: the composite manager could use it to render the screen.
您不需要直接使用 OpenGL:复合管理器可以使用它来渲染屏幕。
If you're going in the GTK path, have a look to
如果您要走 GTK 路径,请查看
- gdk_x11_display_composite
- gdk_screen_is_composited
- gdk_display_supports_composite
- gdk_screen_get_rgba_visual
- gdk_screen_get_rgba_colormap
- gdk_x11_display_composite
- gdk_screen_is_composited
- gdk_display_supports_composite
- gdk_screen_get_rgba_visual
- gdk_screen_get_rgba_colormap
But you could also use Qt or another toolkit.
但您也可以使用 Qt 或其他工具包。