SDL transparent primary surface (main window)?

Hi,
is it possible to have a transparent background in the main window with SDL2?
So that if the SDL main window is running in foreground its still possible to see whats going on in the windows of the background programs.

Thx
Pat

no one knows?

I found this GL sample to manage transparent background which works but I have no idea how to adapt this with SDL2.

I tried the following in the render function:
Instead of SDL_RenderClear(mRenderer) I’ve added

// Create an OpenGL context associated with the window.
SDL_GLContext glcontext = SDL_GL_CreateContext(mWindow);
// now you can make GL calls.
glClearColor( 0.7, 0.7, 0.7, 0.7) ; // light gray bg
glClear(GL_COLOR_BUFFER_BIT);
// Once finished with OpenGL functions, the SDL_GLContext can be deleted.
SDL_GL_DeleteContext(glcontext);
… and finally
SDL_RenderPresent(mRenderer);

In principle it works, the bg will be shown light gray but unfortunatly solid instead of transparent.
What I missed (couldn’t archive it from the sample)?
Above GL stuff seems nothing other than SDL_SetRenderDrawColor(renderer, 0xC0, 0xC, 0xC, 127) which also didn’t helped to make it transparent.
I assume that there is maybe a OS dependent hack neecessary e.g. in SDL_X11window.c ?
I use to get it to work with Ubuntu 14.04 LTS.
Any help would be fine. :frowning:

I thought I would find here SDL specialists with a solution… [Wink]

Because I got no answer I solved it myself with help of regular SDL_CreateWindowFrom and share it with you.
Its not perfect but it works for me under Ubuntu.
It works only with GL. Another bad thing is that the window doesn’t post SDL events.
On the fly I couldn’t find a solution to manage this.
Maybe someone other can tell how this can be done.
Meanwhile below you will find too how to handle X events.

Add this variables to your App class or whereever

Code:
Window mXWindow;
Display* mXDisplay;

Here is the custom SDL create window function with transparent background.

Code:
SDL_Window* App::SDL_CreateTransparentWindow(const char* title, int x, int y, int w, int h)
{
/Window mXWindow;/
/Display/ mXDisplay = XOpenDisplay(0);
const char* xserver = getenv(“DISPLAY”);

if (mXDisplay == 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(mXDisplay, DefaultScreen(mXDisplay), 32, TrueColor, &visualinfo);

// create window
GC gc;
XSetWindowAttributes attr;
attr.colormap   = XCreateColormap(mXDisplay, DefaultRootWindow(mXDisplay), visualinfo.visual, AllocNone);
attr.event_mask = ExposureMask | KeyPressMask;
attr.background_pixmap = None;
attr.border_pixel = 0;

mXWindow = XCreateWindow(mXDisplay, DefaultRootWindow(mXDisplay),
                    x, y, w, h, // x,y,width,height : are possibly opverwriteen by window manager
                    0,
                    visualinfo.depth,
                    InputOutput,
                    visualinfo.visual,
                    CWColormap|CWEventMask|CWBackPixmap|CWBorderPixel,
                    &attr);
gc = XCreateGC(mXDisplay, mXWindow, 0, 0);

// set title bar name of window
XStoreName(mXDisplay, mXWindow, title);

// 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;
XSetWMNormalHints(mXDisplay, mXWindow, &sizehints);

// Switch On >> If user pressed close key let window manager only send notification >>
Atom wm_delete_window = XInternAtom(mXDisplay, "WM_DELETE_WINDOW", 0);
XSetWMProtocols(mXDisplay, mXWindow, &wm_delete_window, 1);

// create OpenGL context
GLXContext glcontext = glXCreateContext(mXDisplay, &visualinfo, 0, True) ;

if (!glcontext)
{
    printf("X11 server '%s' does not support OpenGL\n", xserver ) ;
    return false;
}

glXMakeCurrent(mXDisplay, mXWindow, glcontext);

// now let the window appear to the userSDL_WINDOWPOS_U
XMapWindow(mXDisplay, mXWindow);
glXSwapBuffers(mXDisplay, mXWindow);

SDL_Window* sdl_window = SDL_CreateWindowFrom((void*)mXWindow);

SDL_Delay(30);

return sdl_window;

}

SDL_CreateTransparentWindow can be used as usual

Code:

if (NULL == (mWindow=SDL_CreateTransparentWindow(“My SDL App with transparent background”, 100, 50, WindowWidth, WindowHeight)))
{
LogError(“Unable to create SDL Window: %s\n”, SDL_GetError());
return false;
}

if (NULL == (mRenderer=SDL_CreateRenderer(mWindow, -1, /*SDL_RENDERER_SOFTWARE*/SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC)))
{
	LogError("Unable to create renderer: %s\n", SDL_GetError());
	return false;
}

Add this to the beginning of your render procedure to clear the transparent background.
You can place your drawing objects as usual. Also blending your objects is still working.
Code:
void App:Render() {
SDL_SetRenderDrawColor(mRenderer, 0, 0, 0, 0);
SDL_RenderClear(mRenderer);

Event handler

Code:
void App::OnEvent()
{
if (XPending(mXDisplay) > 0)
{
// process event
XEvent event ;
XNextEvent(mXDisplay, &event) ;

    switch(event.type)
    {  // see 'man XAnyEvent' for a list of available events
    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(mXDisplay, "WM_PROTOCOLS", 1)
            && event.xclient.data.l[0]  == XInternAtom(mXDisplay, "WM_DELETE_WINDOW", 1))
        {
            printf("Event WM_PROTOCOLS\n");
        }
        break;
    case KeyPress:
        if (XLookupKeysym(&event.xkey, 0) == XK_Escape)
        {
            printf("Event KeyPress Escape\n");
        }
        break ;
    default:
        // do nothing
        break ;
    }
}

}

Add finally following to your cleanup procedure
Code:

if (mXDisplay && mXWindow)
{
XDestroyWindow(mXDisplay, mXWindow);
mXWindow = 0;
if (mXDisplay)
{
XCloseDisplay(mXDisplay);
mXDisplay = NULL;
}
}

I know that this comes a bit late, but maybe this can help you, meuchel.

I was making a ‘clone’ of Pong and I was asked to make it for a terminal
window, so I decided to use ncurses. As I wanted to manage the keyboard
events with SDL, I need an SDL window that received the events. In order to
receive them, the window needs to have the focus, but I wanted it to be
’transparent’, so this is what I used.

I have this window (which is the one I use for menus):

window = SDL_CreateWindow(“Poing!”, 100, 100, SCREEN_WIDTH,
SCREEN_HEIGHT, SDL_WINDOW_SHOWN);

and when I want it to be ‘transparent’, I use this:

SDL_DestroyWindow(window);
window = SDL_CreateWindow("", 0, 0, 100, 0, SDL_WINDOW_BORDERLESS);

I know this can looks horrible to someone with more experience in SDL than
me (that’s not too difficult :P), but it worked to me.

Greetings.