Skip to content

Instantly share code, notes, and snippets.

@jackun
Last active March 7, 2021 22:26
Show Gist options
  • Save jackun/8909fd7fa6606f1855cda1231f0a228d to your computer and use it in GitHub Desktop.
Save jackun/8909fd7fa6606f1855cda1231f0a228d to your computer and use it in GitHub Desktop.
Transparent X11 window with OpenGL
/*
____ _____
/\__ \ /\ ___\
\/__/\ \ \ \ \__/_
\ \ \ \ \____ \
_\_\ \ \/__/_\ \
/\ _____\ /\ _____\
\/______/ \/______/
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