c++openglx11glx

X11/GLX window above desktop


I want create opengl application for desktop, but icons and wallpaper are break down.

Window should be under icons:

enter image description here

code for create window:

XSetWindowAttributes swa;
swa.background_pixmap = ParentRelative;
swa.background_pixel = 0;
swa.border_pixmap = 0;
swa.border_pixel = 0;
swa.bit_gravity = 0;
swa.win_gravity = 0;
swa.override_redirect = True;
swa.colormap = XCreateColormap(dis, root, vi->visual, AllocNone);
swa.event_mask = StructureNotifyMask | ExposureMask;

unsigned long mask = CWOverrideRedirect | CWBackingStore | CWBackPixel | CWBorderPixel | CWColormap;

window = XCreateWindow(display, desktop, 0, 0,
                              display_width, display_height, 0, vi->depth,
                             InputOutput, vi->visual, mask, &swa); // vi -XVisualInfo

XLowerWindow(display, window);


long value = XInternAtom(display, "_NET_WM_WINDOW_TYPE_DESKTOP", false);

XChangeProperty(display, window,
                    XInternAtom(display, "_NET_WM_WINDOW_TYPE", false),
                    XA_ATOM, 32, PropModeReplace, (unsigned char *) &value, 1);

Atom xa; 

 xa = ATOM(_WIN_LAYER); 

  if (xa != None) {
    long prop = 0;

    XChangeProperty(display, window, xa, XA_CARDINAL, 32,
                    PropModeAppend, (unsigned char *)&prop, 1);
  }

  xa = ATOM(_NET_WM_STATE);
  if (xa != None) {
    Atom xa_prop = ATOM(_NET_WM_STATE_BELOW);

    XChangeProperty(display, window, xa, XA_ATOM, 32, PropModeAppend,
                    (unsigned char *)&xa_prop, 1);
  }


  if (transparency < 1.0) {
    uint32_t cardinal_alpha = (uint32_t) (transparency * (uint32_t)-1) ;
    XChangeProperty(display, window,
                    XInternAtom(display, "_NET_WM_WINDOW_OPACITY", 0),
                    XA_CARDINAL, 32, PropModeReplace, (uint8_t*) &cardinal_alpha, 1);
}

XLowerWindow(display, window);
ctx = glXCreateContextAttribsARB(dis, fbc, NULL, True, gl3attr); //ctx =  GLXContext

next i create XMapWindow(dis, window), glXMakeCurrent(dis, window, ctx), glViewport and clearColor(red)\swapBuffers (in cycle)

note: ATOM = #define ATOM(a) XInternAtom(dis, #a, False)


Solution

  • Unfortunately there is no solution that works in 100% of all the cases. The most immediate solution would be to draw directly to the root window: open connection to X, get xid of root window, query what visual it's configured to, created compatible GLX context, draw to that. (this works somewhat reliably for X11; doing similar on Microsoft Windows or macOS is impossible though.)

    However you can't change the visual/pixelformat, and just drawing to the root window won't necessarily make it an "underlay" for icons on the desktop. You see, most "desktops" are implemented by creating their very own full screen window, on top of the root window (but beneath everything else), and will even be used to draw the wallpaper then.

    Drawing directly to the root window would give you the desired effect only, if the desktop environment of choice would cooperate and draw its desktop and the icons on it as a transparent, composited window; or if it'd mask out the icons using the X shape extension (I'm not aware of any DE that does either).