Last active
March 7, 2021 22:26
-
-
Save jackun/8909fd7fa6606f1855cda1231f0a228d to your computer and use it in GitHub Desktop.
Transparent X11 window with OpenGL
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
____ _____ | |
/\__ \ /\ ___\ | |
\/__/\ \ \ \ \__/_ | |
\ \ \ \ \____ \ | |
_\_\ \ \/__/_\ \ | |
/\ _____\ /\ _____\ | |
\/______/ \/______/ | |
Copyright (C) 2011 Joerg Seebohn | |
This program is free software; you can redistribute it and/or modify | |
it under the terms of the GNU General Public License as published by | |
the Free Software Foundation; either version 2 of the License, or | |
(at your option) any later version. | |
This program demonstrates how an X11 window with OpenGL support | |
can be drawn transparent. | |
The title bar and window border drawn by the window manager are | |
drawn opaque. | |
Compile it with: | |
gcc -std=gnu99 -o test x11_gl.c -lX11 -lGL | |
*/ | |
#include <X11/Xlib.h> | |
#include <X11/Xatom.h> | |
#include <X11/keysym.h> | |
#include <GL/gl.h> | |
#include <GL/glx.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <getopt.h> | |
int main(int argc, char* argv[]) | |
{ | |
int x = 200, y = 200, w = 300, h = 400, tmp, c; | |
const char* getopt_args = "x:y:w:h:"; | |
while ((c = getopt(argc, argv, getopt_args)) != -1) | |
{ | |
switch (c) | |
{ | |
case 'x': | |
if (sscanf(optarg, "%d", &tmp) == 1) | |
x = tmp; | |
break; | |
case 'y': | |
if (sscanf(optarg, "%d", &tmp) == 1) | |
y = tmp; | |
break; | |
case 'w': | |
if (sscanf(optarg, "%d", &tmp) == 1) | |
w = tmp; | |
break; | |
case 'h': | |
if (sscanf(optarg, "%d", &tmp) == 1) | |
h = tmp; | |
break; | |
case '?': | |
fprintf(stderr, "\nUsage:\n%s [-x xpos] [-y ypos] [-w width] [-h height]\n", argv[0]); | |
return 1; | |
} | |
} | |
const char* xserver = getenv("DISPLAY"); | |
Display* display = XOpenDisplay(xserver); | |
if (display == 0) | |
{ | |
printf("Could not establish a connection to X-server '%s'\n", xserver); | |
exit(1); | |
} | |
// query Visual for "TrueColor" and 32 bits depth (RGBA) | |
XVisualInfo visualinfo; | |
XMatchVisualInfo(display, DefaultScreen(display), 32, TrueColor, &visualinfo); | |
// create window | |
Window win; | |
GC gc; | |
XSetWindowAttributes attr; | |
attr.colormap = XCreateColormap(display, DefaultRootWindow(display), visualinfo.visual, AllocNone); | |
attr.event_mask = ExposureMask | KeyPressMask; | |
attr.background_pixmap = None; | |
attr.border_pixel = 0; | |
win = XCreateWindow(display, DefaultRootWindow(display), | |
x, y, w, h, | |
0, | |
visualinfo.depth, | |
InputOutput, | |
visualinfo.visual, | |
CWColormap | CWEventMask | CWBackPixmap | CWBorderPixel, | |
&attr); | |
gc = XCreateGC(display, win, 0, 0); | |
// set title bar name of window | |
XStoreName(display, win, "x11_gl"); | |
// say window manager which position we would prefer | |
XSizeHints sizehints; | |
sizehints.flags = PPosition | PSize; | |
sizehints.x = x; | |
sizehints.y = y; | |
sizehints.width = w; | |
sizehints.height = h; | |
//sizehints.win_gravity = CenterGravity; | |
XSetWMNormalHints(display, win, &sizehints); | |
// Switch On >> If user pressed close key let window manager only send notification >> | |
Atom wm_delete_window = XInternAtom(display, "WM_DELETE_WINDOW", 0); | |
XSetWMProtocols(display, win, &wm_delete_window, 1); | |
//Atom window_type = XInternAtom(display, "_NET_WM_WINDOW_TYPE", False); | |
//long value = XInternAtom(display, "_NET_WM_WINDOW_TYPE_DOCK", False); | |
//XChangeProperty(display, win, window_type, | |
// XA_ATOM, 32, PropModeReplace, (unsigned char*)&value, 1); | |
// create OpenGL context | |
GLXContext glcontext = glXCreateContext(display, &visualinfo, 0, True); | |
if (!glcontext) | |
{ | |
fprintf(stderr, "X11 server '%s' does not support OpenGL\n", xserver); | |
exit(1); | |
} | |
glXMakeCurrent(display, win, glcontext); | |
// now let the window appear to the user | |
XMapWindow(display, win); | |
int quit = 0; | |
while (!quit) | |
{ | |
while (XPending(display) > 0) | |
{ | |
// process event | |
XEvent event; | |
XNextEvent(display, &event); | |
switch (event.type) | |
{ | |
case ClientMessage: | |
// check if the client message was send by window manager to indicate user wants to close the window | |
if (event.xclient.message_type == XInternAtom(display, "WM_PROTOCOLS", 1) && event.xclient.data.l[0] == XInternAtom(display, "WM_DELETE_WINDOW", 1)) | |
{ | |
quit = 1; | |
} | |
case KeyPress: | |
if (XLookupKeysym(&event.xkey, 0) == XK_Escape) | |
{ | |
quit = 1; | |
} | |
break; | |
default: | |
// do no thing | |
break; | |
} | |
} | |
glClearColor(0, 0, 0, 0); | |
glClear(GL_COLOR_BUFFER_BIT); | |
glXSwapBuffers(display, win); | |
glXWaitGL(); | |
} | |
XDestroyWindow(display, win); | |
win = 0; | |
XCloseDisplay(display); | |
display = 0; | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment