Xlib image grab fails in XGetImage

Viewed 432

Cookie cuttered (from supposedly working code) a trivial C program to perform a Xlib image grab using XGetImage(). At this point I'm not trying to process the image, this is just a proof-of-concept to see if the image grab works - and it doesn't. The XGetImage() call fails like:

X Error of failed request:  BadMatch (invalid parameter attributes)
  Major opcode of failed request:  73 (X_GetImage)
  Serial number of failed request:  21
  Current serial number in output stream:  21

I spent a fair amount of time researching this and apparently this problem has plagued other developers and no definitive answer was ever arrived at. Does someone know how I could go about resolving this? I can tell from the printf that the window of interest was correctly identified. The XMapRaised() is a suggestion from a prior thread on this problem, but doesn't seem to help. Here's the code:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "/usr/include/X11/Xlib.h"

Window findScidWindow(Display *display )
{
    Bool found = False;
    Window rootWindow = RootWindow(display, DefaultScreen(display));
    Atom atom = XInternAtom(display, "_NET_CLIENT_LIST", True);
    Atom actualType;
    int format;
    unsigned long numItems;
    unsigned long bytesAfter;

    unsigned char *data = '\0';
    Window *list;
    char *windowName;

    int status = XGetWindowProperty(display, rootWindow, atom, 0L, (~0L), False,
        AnyPropertyType, &actualType, &format, &numItems, &bytesAfter, &data);
    list = (Window *)data;

    if (status >= Success && numItems)
    {
        for (int i = 0; i < numItems; ++i)
        {
            status = XFetchName(display, list[i], &windowName);
            if (status >= Success)
            {
                if(strstr(windowName, "Scid vs. PC") != NULL)
                {
                    XFree(windowName);
                    XFree(data);
                    return list[i];
                }
            }
        }
    }
}
void
main( int argc, char*argv )
{
    Display* d = XOpenDisplay(":0.0");
    XImage *image;

    Window root = (Window)0x0560003b; /* obtained via 'wmctrl -l -G' */

    Window ScidWindow = findScidWindow(d);
    XWindowAttributes attrib;

    XGetWindowAttributes(d, ScidWindow, &attrib);

    int width = attrib.width;
    int height = attrib.height;
printf("width: %d    height: %d\n",width,height);

    XMapRaised(d, root);

    /* coordinates 438,110 obtained via 'wmctrl -l -G' */
    image = XGetImage( d, ScidWindow, 438, 110, width, height, AllPlanes, ZPixmap);
}
1 Answers

The issue is

    image = XGetImage( d, ScidWindow, 438, 110, width, height, AllPlanes, ZPixmap);

uses x = 438 and y = 110 that is particular a problem if x + width is actually bigger as the window width (same for the height)

So here I have to assume you're not attempting to crop the window image but rather want to take a plain raw screenshot, then you just need to pass 0 for x and y:

    image = XGetImage( d, ScidWindow, 0, 0, width, height, AllPlanes, ZPixmap);

The explanation is that the coordination system is not the full display or screen but the one of the window you are grabbing. Means the window starts at (0, 0).

This took me also some time to figure out.

Related