我不仅是 Xlib 的新手,也是 Linux 接口编程的新手。
我正在尝试解决将一个窗口的内容绘制到另一个窗口的常见任务(这似乎并不常见,因为我找不到任何可靠的示例)。
但是,我遇到了严重的性能问题,我正在寻找可用于使程序更快、更可靠的解决方案。
现在我将提供一些有关程序流程的信息,因为我不确定选择的程序设计是否正确,也许我使用 Xlib 的方式存在一些错误。
程序以适当的方式获取活动窗口(从现在开始称为SrcWin)的 ID(Xlib“Window”类型)(不是某些程序的小部件的 ID,而是绘制所有内容的真实可见窗口),首先它XGetInputFocus
用于获得焦点窗口,然后XQueryTree
在找到根窗口的子窗口时使用迭代窗口,然后它使用XmuClientWindow
函数来获取命名窗口(如果它不是已经找到的窗口)。
然后使用它获取SrcWinXGetWindowAttributes
的宽度和高度,这两个函数都用于创建相同大小的新窗口(称为TrgWin)。XCreateSimpleWindow
使用函数为新窗口 TrgWin 注册了一些事件,例如KeyPress和ExposeXSelectInput
。
图形上下文以这种方式创建:
GC gc = DefaultGC (Display, ScreenCount (Display) - 1);
现在开始无限循环,在这个循环select
中调用函数来等待 X 连接上的某个事件或超时(struct timeval
)。
在该程序尝试使用以下方法从SrcWin获取图像后:
XImage *xi;
xi = XGetImage (Display, SrcWin, 0, 0, SrcWinWidth, SrcWinHeight, AllPlanes, ZPixmap);
如果成功获取图像,则将其放入TrgWin:
if (xi)
{
XPutImage (Display, TrgWin, gc, xi, 0, 0, 0, 0, SrcWinWidth, SrcWinHeight);
XFree (xi);
}
然后处理未决事件,如果它们是:
while (XPending (Display))
{
XNextEvent (Display, &XEvent);
/* some event processing using switch(XEvent.type){} */
}
如上所述,程序几乎按预期工作。但是当我试图让这个程序每 40 毫秒将 SrcWin 的内容绘制到TrgWin时,我遇到了严重的性能问题(这是时间值,它可能会更快),在核心 i5-3337U 上,它需要 21% 的 cpu 时间程序和近 20% 的 Xorg 进程将一个 683*752 窗口绘制到另一个相同大小的窗口中。
从我的角度来看,如果我能够将带有 SrcWin 像素的内存区域映射到 TrgWin 的相应内存区域,那就太好了,但是我在 Xlib 编程方面不太擅长,我怀疑这是否可能标准 Xlib 函数。
1)但是我已经启动了 KDE 环境来检查它的窗口切换器,并且所有窗口缩略图都实时绘制到窗口切换器的窗口,而没有任何严重的 CPU 负载。它是如何完成的?
2) 在某处提到了 XShmGetImage + XShmPutImage 机制 - 它对我的程序来说是否比 XGetImage+XPutImage 更好?
3) 我还看到 QT 和 GTK 中存在诸如“窗口损坏”事件之类的事情,它是特定于工具包的事件,还是具有 Xlib 等价物?
4) 我将 QT 和 GTK 中的“窗口损坏”事件理解为在窗口的图像缓冲区发生任何变化后发送的信号,所以导致窗口中至少一个像素发生变化的所有事情也会产生这样的事件?在 Xlib 中有这样的东西会很棒,因为即使 SrcWin 没有变化,我也可以摆脱每 40 毫秒不断变化的 TrgWin 内容。
5) 我应该使用 GTK+ 来让事情变得更简单吗?
在此先感谢您的回复,并为大量文字感到抱歉。