X11 窗口在获取事件之前不会刷新

X11 window does not get refreshed until it gets an event

本文关键字:刷新 事件 窗口 获取 X11      更新时间:2023-10-16

在我的应用程序(cairoX11)中,用户可以发出一个命令,从而放大绘图。为了能够将整个绘图作为图案抓取,我放大了绘图表面以匹配当前比例(绘图只是一个图形,因此就内存而言可以提供)。但是,从一定的比例开始,X11 窗口拒绝刷新,直到它得到一个事件(例如失去焦点,这在我的应用程序中甚至没有处理)。

我尝试使用 XFlush()XSync() 刷新窗口。

这看起来像是窗口系统中的错误吗?如果没有,我该怎么办?一切都可以在较小的规模下完美运行。

编辑1:经过大量gdb工作,我发现问题不在于窗口不刷新。相反,在某个点上,对XNextEvent()的调用会导致窗口全黑。

编辑2:看起来调用XNextEvent()实际上会导致窗口刷新!以下是导致问题的代码:

struct PatternLock {
    PatternLock(Graphics &g)
        : g_(g) {
        p_ = cairo_get_source(g_.cr);
        cairo_pattern_reference(p_);
    }
    ~PatternLock() {
        // The commented lines caused the problem. How come?
        // cairo_set_source_rgb(g_.cr, 0, 0, 0);
        // cairo_paint(g_.cr);
        cairo_set_source(g_.cr, p_);
        cairo_paint(g_.cr);
        cairo_pattern_destroy(p_);
    }
private:
    Graphics &g_;
    cairo_pattern_t *p_;
};

假设我们有以下代码来移动绘图:

{
    PatternLock lock{g};
    ... // Change of transformation matrix
}

不知何故,PatternLock析构函数中注释行的效果变得可见(因此出现黑屏),但以下行的效果却不可见。我意识到注释的代码实际上是不需要的。但是,这是怎么发生的呢?

如果我没记错的话,可绘制对象(例如 Windows 和 Pixmap)的限制为 4096x4096 像素。您应该检查调用 XCreatePixmap() 等的返回值。

无论哪种方式,只是放大像素图来绘制你的绘图都是糟糕的设计(tm),并且不可避免地会导致一个非常缓慢的程序。了解如何处理缩放和平移(提示:从视口中心而不是角落开始工作)。假设您的绘图是基于矢量的(即直线和曲线),则可以在高缩放系数下优化大量绘画。

如果必须以大于 4096 像素的分辨率抓取完整的图形,则必须实现平铺,如果您已经具有缩放和平移功能,这并不难。