0

在基于 XLib 的应用程序中,我需要使子窗口在父窗口之后调整大小。(比如为了让子窗口占据父窗口的整个客户区)

我正在处理父窗口的 ConfigureNotify 事件并在需要时调整子窗口的大小。

通常它可以正常工作。但是在调整父窗口大小(例如,当用户调整窗口大小拖动边缘时)和应用程序接收到的事件之间存在延迟。

由于这种延迟,子窗口仅在用户停止移动边缘后的一段时间才会采用其适当的大小。这样,屏幕上会出现一些不良闪烁,并且用户界面看起来非常缓慢。

我可以在许多 Linux 程序中看到类似的行为。

如何解决这个问题?或者至少,如何使延迟显着更小?

我试图通过只处理最后收到的事件来忽略一些 ConfigureNotify 事件,它有一点帮助,但还不够。

更新:

经过一些研究,我发现问题是由于 WM 应用程序交互的异步性质造成的。当应用程序调整大小并重新绘制子窗口时,窗口管理器会继续调整父窗口的大小。所以,当resize/realign/redraw的过程结束时,父窗口有另一个大小,另一个事件被发布到事件队列中,一切都必须从头开始。

4

1 回答 1

1

移除 ConfigureNotify 事件处理并在暴露处理中获取当前父大小。这将忽略排队的配置通知事件,它给出父大小的历史记录,而不是当前父窗口大小。

所以修改你在评论中发布的代码。

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);
    }
  }
}

更新:要解决缺少公开事件的问题,请添加以下内容:

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);
}

这将导致更多的暴露事件。XCheckTypedWindowEvent可能没有必要,它会从队列中删除任何所有 ConfigureNotify 事件,留下最后一个在e.

于 2013-07-14T14:46:44.663 回答