2013-06-23 5 views
2

이벤트를 수신하지 않았더라도 X에서 이벤트를 노출하기 위해 일정 시간 대기 한 다음 깨어나 다시 그리기를 수행하는 가장 좋은 방법은 무엇입니까? 목적은 때로는 다른 사람들이 필요하다면 다시 그리기를 원할 때 OpenGL 애니메이션을 실행하는 것입니다. 여기에 내가 지금, 내가 무엇을 찾고의 의사 코드는 아래를 확인 가지고 내 코드입니다 :X : 일정한 간격으로 트리거 이벤트

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 
    } 

답변

3

그냥 정기적 인 시스템 타이머를 사용하십시오; 원하는 이벤트가 제 시간에 도착하지 않으면 원하는대로하십시오.

X는 응용 프로그램 프레임 워크가 아니며 디스플레이 프로토콜입니다. 타이머는 X11의 범위 밖에 있습니다.

해당 답변에서 제공된 herelink을 확인하십시오.

1

더 간단한 솔루션은 XNextEvent에 해당하는 비 차단 Xlib를 사용하는 것입니다. 다음은 프레임 루프를 통해 매번 X 이벤트를 확인하는 방법입니다.

mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask; 
while (XCheckWindowEvent(xDisplay, xWin, mask, &evt) || 
     XCheckTypedWindowEvent(xDisplay, xWin, ClientMessage, &evt)) { 
     /* Handle event */ 
} 

희망이 있습니다. 전체 코드는 GLX 프로그램 Xlib를가가 XNextEvent의 버전을 "시간 초과"제공하지 않습니다

http://cs.anu.edu.au/~Hugh.Fisher/3dteach/glxcube.tar

1

/내 데모는 OpenGL에 있습니다. 그러나 시간 초과 버전을 쉽게 구현할 수 있습니다.

당신은 파일이 주어진 제한 시간 내에 업데이트되었는지 확인하는 기능 이 필요합니다, 당신이 그것을 구현할 수 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 을 사용할 수 있습니다

int XNextEventTimeout(Display *display, XEvent *event, double seconds) 
{ 
    if (XPending(display) || wait_fd(ConnectionNumber(display),seconds)) { 
     XNextEvent(display, event); 
     return 0; 
    } else { 
     return 1; 
    } 
} 
: 주어진 제한 시간 내에 이벤트 기다릴 ConnectionNumber(display) 에 의해 반환

주 루프에서 함수 을 사용하여 지정된 시간 내에 이벤트를 대기 할 수 있습니다.

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 */ 
    } 
} 
: 제한 시간이 만료되면, 당신이 원하는 이벤트를 시뮬레이션 할 수 있습니다, 당신의 는 Expose 이벤트를 케이스