6

I'm new not only to Xlib but to Linux interface programing as well.

I'm trying to solve common task(which is not so common as it seems to be, as I can't find any reliable example) of drawing content of one window into another.

However I've faced serious perfomance issues and I'm looking for solution which I can use to make program faster and reliable.

Now I'll provide some information about program flow, as I'm not sure if choosen program design was correct, maybe there are some errors with the way I use Xlib.

Program gets ID (Xlib "Window" type) of active window (called SrcWin from now on) in a proper way (not the IDs of widgets of some program, but real visible window where all content is drawn), at first it uses XGetInputFocus to get focused window, then iterates windows using XQueryTree while the child of root window is found, then it uses XmuClientWindow function to get named window(if it is not the already found one).

Then using XGetWindowAttributes it gets width and height of SrcWin which both used in XCreateSimpleWindow function to create new window (called TrgWin) of the same size.

Some events are registered for new window TrgWin such as KeyPress and Expose using XSelectInput function.

Graphics context is created in this way:

GC  gc = DefaultGC (Display, ScreenCount (Display) - 1);

Now infinite loop is started, in this loop select function is called to wait for some event on X connection or for timeout (struct timeval).

After that program tries to get image from SrcWin using:

XImage *xi;
xi = XGetImage (Display, SrcWin, 0, 0, SrcWinWidth, SrcWinHeight, AllPlanes, ZPixmap);

and if an image was successfully acquired it is put to TrgWin:

if (xi)
{
    XPutImage (Display, TrgWin, gc, xi, 0, 0, 0, 0, SrcWinWidth, SrcWinHeight);
    XFree (xi);
}

then pending events are processed if they are:

while (XPending (Display))
{
    XNextEvent (Display, &XEvent);
    /* some event processing using switch(XEvent.type){} */
}

As mentioned above program works nearly as expected. But I've faced serious perfomance issues when trying to make this program draw content of SrcWin to TrgWin every 40ms(this is timeval value, with events it might be faster), on core i5-3337U it takes 21% of cpu time for this program and nearly 20% for Xorg process to draw one 683*752 window into another of the same size.

From my point of view, it would have been great if only I was able to map memory region with pixels of SrcWin to the corresponding memory region of TrgWin, but I'm not so good in Xlib programming, and I doubt it is possible with standard Xlib functions.

1) However I've started KDE environment to check its window-switcher and all window thumbnails are drawn to window-switcher's window in realtime without any serious CPU load. How it is done?

2) Somewhere XShmGetImage + XShmPutImage mechanism is mentioned - is it better for my program than XGetImage+XPutImage?

3) Also I saw that there is such a thing as "window-damage" events in QT and GTK, is it toolkit-specific events, or does it have Xlib equivalent?

4) I understood "window-damage" events in QT and GTK as signals beign send after any changes in image buffer of window, so everything resulting in changing of at least one pixel in window is also generating such an event? It would be great to have something like this in Xlib as I could get rid of continuously changing TrgWin content every 40ms even if there were no changes in SrcWin.

5) Should I go with GTK+ to make things easier?

Thanks in advance for replies, and sorry for tons of text.

  • 1
    About question (2): yes, you should use XShmGetImage+XShmPutImage. With XGetImage, your program will allocate memory and receive the image data from the X server through the X server pipe. As you've seen you have to XFree() the allocated memory every time. With XShmGetImage+XShmPutImage you pre-allocate a shared memory region that will be used every time you call XShmGetImage, so you don't need to allocate+free every time. Plus since the memory is shared, the X server simply copies the image data to the memory you allocated, no need to send the data through the pipe. – Ricardo Massaro Sep 12 '17 at 06:47

0 Answers0