Search code examples
cx11

Setting X11 root window pixmap


The code below is supposed to make root window white, but does nothing. Compiles and runs with no errors. I omitted only includes and variable definitions.

int
main(int argc, char **argv) {
    dpy = XOpenDisplay(NULL);
    if (!dpy) {
        fputs("cannot open display\n", stderr);
        return EXIT_FAILURE;
    }
    screen = DefaultScreen(dpy);
    root   = RootWindow(dpy, screen);
    vis    = DefaultVisual(dpy, screen);
    depth  = DefaultDepth(dpy, screen);
    height = DisplayHeight(dpy, screen);
    width  = DisplayWidth(dpy, screen);
    img = malloc(depth/8 * height * width);
    if (img == NULL) {
        perror("malloc() failed");
        return EXIT_FAILURE;
    }
    memset(img, 0xFF, depth/8 * height * width);
    ximg = XCreateImage(dpy, vis, depth, ZPixmap, 0, img, width, height, 32, 0);
    pm = XCreatePixmap(dpy, root, width, height, depth);
    gc = XCreateGC(dpy, pm, 0, NULL);
    XPutImage(dpy, pm, gc, ximg, 0, 0, 0, 0, width, height);
    XSetWindowBackgroundPixmap(dpy, root, pm);
    XClearWindow(dpy, root);
    XFlush(dpy);
    XDestroyImage(ximg);
    XFreePixmap(dpy, pm);
    XFreeGC(dpy, gc);
    XCloseDisplay(dpy);
    return EXIT_SUCCESS;
}

How do I even start troubleshooting this? removing XClearWindow(dpy, root); does not help.


Solution

  • Apparently XSetWindowBackgroundPixmap() needs some prior atom setup. This borrowed function fixed the issue.

    // Adapted from fluxbox' bsetroot
    int
    setRootAtoms(Pixmap pixmap)
    {
      Atom atom_root, atom_eroot, type;
      unsigned char *data_root, *data_eroot;
      int format;
      unsigned long length, after;
    
      atom_root = XInternAtom(display, "_XROOTMAP_ID", True);
      atom_eroot = XInternAtom(display, "ESETROOT_PMAP_ID", True);
    
      // doing this to clean up after old background
      if (atom_root != None && atom_eroot != None) {
        XGetWindowProperty(display, RootWindow(display, screen), atom_root, 0L, 1L, False, AnyPropertyType, &type, &format, &length, &after, &data_root);
    
        if (type == XA_PIXMAP) {
          XGetWindowProperty(display, RootWindow(display, screen), atom_eroot, 0L, 1L, False, AnyPropertyType, &type, &format, &length, &after, &data_eroot);
    
          if (data_root && data_eroot && type == XA_PIXMAP && *((Pixmap *) data_root) == *((Pixmap *) data_eroot))
            XKillClient(display, *((Pixmap *) data_root));
        }
      }
    
      atom_root = XInternAtom(display, "_XROOTPMAP_ID", False);
      atom_eroot = XInternAtom(display, "ESETROOT_PMAP_ID", False);
    
      if (atom_root == None || atom_eroot == None)
        return 0;
    
      // setting new background atoms
      XChangeProperty(display, RootWindow(display, screen), atom_root, XA_PIXMAP, 32, PropModeReplace, (unsigned char *) &pixmap, 1);
      XChangeProperty(display, RootWindow(display, screen), atom_eroot, XA_PIXMAP, 32, PropModeReplace, (unsigned char *) &pixmap, 1);
    
      return 1;
    }