Question

In XLib based application, I need to make the child window to be resized after the parent window. (For example, in order to make the child window to take the whole client area of the parent window)

I am processing the ConfigureNotify event of the parent window and resizing the child window when needed.

In generally it works properly. But there is a delay between resizing the parent window (for example when the user resizes the window dragging the edge) and the event received by the application.

Because of this delay, the child window(s) takes its proper size only some time after the user stops to move the edges. This way, some bad flicker appears on the screen and the user interface looks really sluggish.

I can see the similar behavior in many Linux programs.

How this problem can be fixed? Or at least, how to make the delay significantly smaller?

I tried to ignore some of the ConfigureNotify events by processing only the last received event and it helps a little, but not enough.

Update:

After some research I found that the problem is due to the asynchronous nature of the WM-application interaction. While the application resizes and redraws the child window, the window manager continues to resize the parent window. So, when the process of the resize/realign/redraw finishes, the parent window has another size, another event is posted to the event queue and everything must be started from the beginning.

Était-ce utile?

La solution

Remove the ConfigureNotify event handling and get the current parent size in the expose processing. This ignores the queued Configure Notify events the give a history of the parent size rather that the current parent window size.

So modifying the code you posted in the comments.

if (e.type == Expose) {
  if (e.xexpose.count == 0) {
    Window r;
    int x,y;
    unsigned int wd,ht, bw, dep;
    XGetGeometry(d,w,&r,&x,&y,&wd,&ht,&bw,&dep);
    width = wd - 20;
    height = ht - 20;
    XMoveResizeWindow (d, ww, 10, 10, width, height);
    for (i=0;i<1000;i++) {
      XFillRectangle(d, ww, DefaultGC(d, s), 20, 20, 10, 10);
      XFillRectangle(d, ww, DefaultGC(d, s), width-30, height-30, 10, 10);
      XFillRectangle(d, ww, DefaultGC(d, s), 20, height-30, 10, 10);
      XFillRectangle(d, ww, DefaultGC(d, s), width-30, 20, 10, 10);
    }
  }
}

Update: To fix the lack of expose events, add the following:

if (e.type == ConfigureNotify) {
{
    while (XCheckTypedWindowEvent(d, w, ConfigureNotify, &e) == True);
    width = e.xconfigure.width - 20;
    height = e.xconfigure.height - 20;
    XMoveResizeWindow (d, ww, 10, 10, width, height);
}

This will cause some more expose events. The XCheckTypedWindowEvent may not be necessary, it removes any all the ConfigureNotify events from the queue leaving the last one found in e.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top