在X上等待一段时间的暴露事件的最佳方式是什么,然后唤醒并重新绘制,即使没有接收到暴露事件?目的是让opengl动画有时在其他地方运行,我只想在需要时重绘。这是我现在的代码,请查看下面我正在寻找的伪代码:
do {
XNextEvent(dpy, &event);
switch(event.type) {
...
case Expose:
need_redraw = True;
break;
}
} while(XPending(dpy)); /* loop to compress events */
if ( need_redraw )
{
// do redraw
}
这是我想要的一个伪示例:
bool animation_enabled = true;
XPostTimeoutEventEvery( 0.3 ); // <-- X will send a "Timeout"
// event each 0.3 seconds.
do {
XNextEvent(dpy, &event);
switch(event.type) {
...
case Expose:
// Redraw if it is required
need_redraw = True;
break;
// -- here --
case Timeout:
// Otherwise, after 0.3 seconds, redraw anyway if
// the animation is running
if ( animation_enabled )
{
need_redraw = True;
}
break;
}
} while(XPending(dpy)); /* loop to compress events */
if ( need_redraw )
{
// do redraw
// potentially change "animation_enabled" value
}
答案 0 :(得分:3)
答案 1 :(得分:1)
更简单的解决方案是使用XNextEvent的非阻塞Xlib等效项。这是我每次通过帧循环检查X事件时使用的内容:
mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask;
while (XCheckWindowEvent(xDisplay, xWin, mask, &evt) ||
XCheckTypedWindowEvent(xDisplay, xWin, ClientMessage, &evt)) {
/* Handle event */
}
希望这会有所帮助。完整的代码在我的演示OpenGL / GLX程序
中答案 2 :(得分:1)
XLib不提供XNextEvent的“超时”版本。 但是,可以轻松实现超时版本。
你需要一个功能
检查文件是否已更新
在给定的超时内,
您可以使用select
实现它:
#include <sys/select.h>
static int wait_fd(int fd, double seconds)
{
struct timeval tv;
fd_set in_fds;
FD_ZERO(&in_fds);
FD_SET(fd, &in_fds);
tv.tv_sec = trunc(seconds);
tv.tv_usec = (seconds - trunc(seconds))*1000000;
return select(fd+1, &in_fds, 0, 0, &tv);
}
然后,您可以使用wait_fd
在返回的文件描述符中
ConnectionNumber(display)
等待一个事件
在给定的时间限制内:
int XNextEventTimeout(Display *display, XEvent *event, double seconds)
{
if (XPending(display) || wait_fd(ConnectionNumber(display),seconds)) {
XNextEvent(display, event);
return 0;
} else {
return 1;
}
}
在你的主循环中,
您可以使用XNextEventTimeout
功能
等待给定超时内的事件。
如果超时到期,您可以模拟所需的事件,
在你的情况下Expose
事件:
for (;;) {
if (XNextEventTimeout(dpy, &event, 1.)) {
/* Handle timeout "event"
* one option is to simulate an Expose event */
e.type = Expose;
e.xexpose.count = 0;
}
switch (event.type) {
case Expose:
/* Handle expose event */
break;
/* ... */
/* Handle other events */
}
}