2014-06-10 7 views
5

X11 창이 매핑되고 표시 될 때까지 기다리는 적절한 방법은 무엇입니까?창이 매핑되고 볼 때까지 기다리는 방법

// X Error of failed request: BadMatch (invalid parameter attributes) 
// Major opcode of failed request: 42 (X_SetInputFocus)  

는 현재이 오류가 특히 느린 X 서버 또는 경우에 자주 발생합니다 정확하게, 나는 안전하게 다음 오류 역효과 X 서버의 위험에 실행하지 않고 XSetInputFocus()를 호출 할 수있을 때까지 대기 할 libXrandr을 사용하여 모니터 해상도를 변경 한 직후 새 창을 열려고합니다.

나는 이미이 문제에 대한 해결책을 가지고 있지만 깨끗한 버전이 있는지 여부를 알기 위해 창 속성을 폴링하기 때문에 꽤 해킹됩니다.

여기에 내 현재의 접근 방식 :

static Bool predicate(Display *display, XEvent *ev, XPointer arg) 
{ 
    return(ev->type == MapNotify); 
} 

static void waitmapnotify(struct osdisplayinfo *osd) 
{ 
    XEvent ev; 
    XWindowAttributes xwa; 

    XPeekIfEvent(osd->display, &ev, predicate, NULL); 

    do { 
     XGetWindowAttributes(osd->display, osd->window, &xwa); 
     usleep(1); 
    } while(xwa.map_state != IsViewable); 
} 

이 코드는 잘 작동하지만 내가 여기에 토론을 위해 그것을 참을 수있어 해키 - 단지의 경우이 작업을 수행하는 청소기 방법이있다.

답변

0

내가 아는 한 X11 lib는 X11 이벤트 처리에 대한 콜백 메 커닉을 노출하지 않습니다. (사용자가 이벤트 필터링 모델을 이해하면 자신 만의 빌드를 쉽게 만들 수 있습니다.)

X11 이벤트 큐에서 루프를 돌리고 싶을 수도 있습니다.이 게스트는이 목적을 위해보다 효율적으로 설계되어야합니다. 또한 특정 창에 관심있는 이벤트 만 가져올 수 있도록 이벤트 필터를 구성 할 수 있습니다.

유용한 (날짜가있는) 링크는 다음과 같을 수 있습니다. Linux Journal X11 Tutorial 필터 설치 및 X11 대기열에서 이벤트 가져 오는 예제는 두 페이지를 확인하십시오.

+0

문제는 AFAICS가 이제는 창을 볼 수 있다는 신호로 보내지는 이벤트가 없다는 것입니다. "MapNotify"가 있으며 이미이 작업을 기다리고 있지만 (위 참조) 충분하지 않습니다. "IsViewable"이 속성에 설정 될 때까지 기다릴 필요가 있지만 AFAICS에는이 속성이 설정/변경 될 때 신호를 보내는 이벤트가 없습니다. – Andreas

+0

Xlib에서 내 기억을 "새로 고침"할 때 다음 이벤트가 발견되었습니다. http://www.x.org/releases/X11R7.7/doc/libX11/libX11/libX11.html#VisibilityNotify_Events, AFAIA가 있어야합니다. 창 가시성 상태 변경에 의해 트리거됩니다. 그것은 당신의 시나리오에 대한 이해가 되니? – sergico

+0

VisibilityNotify를 시도했지만 불행히도 이전에 최소화 된 창을 다시 표시 할 때만 전송됩니다. 창을 만들고 처음 표시하면 VisibilityNotify가 전송되지 않습니다. – Andreas

2

루트 창에서 SubstructureNotifyMask을 선택하십시오. 최상위 창을 매핑, 매핑 해제, 이동, 제기, 크기 조정할 때마다 이벤트를 가져와야합니다. 이러한 이벤트는 잠재적으로 최상위 수준 윈도우의 가시성을 변경합니다. 이 프로그램은 이러한 이벤트가 발생할 때마다 메시지를 인쇄합니다.

#include <X11/Xlib.h> 
#include <stdio.h> 
int main() 
{ 
    Display* d = XOpenDisplay(0); 
    int cnt = 0; 
    XEvent ev;  
    XSelectInput (d, RootWindow(d, DefaultScreen(d)), SubstructureNotifyMask);  
    while (1) 
    { 
    XNextEvent(d, &ev); 
    printf ("Got an event %d!\n", cnt++); 
    // <----- do your XGetWindowAttributes(...) check here 
    } 
} 

매핑되는 자체 이벤트에 대한 이벤트가 표시되지 않을 수 있습니다. 이것은 WM이 최상위 창을 루트가 아닌 하위 창으로 재구성 할 가능성이 있기 때문입니다. 등 창문 부모, 부모의 부모가 ... 이벤트의 매핑 창 경우

  1. 확인 :

    상황에 대처하는 방법은 두 가지가 있습니다.

  2. XSelectInput (d, yourwindow, StructureNotifyMask);을 믹스에 추가하십시오.

첫 번째 선택은 SubstructureNotifyMask이고 다른 하나는 StructureNotifyMask입니다. 다른 마스크는 다른 마스크입니다.

+0

감사합니다. 그러나 이것은 나에게 적합하지 않습니다. 나는 그것을 시도하고 그것은 단지 무한 루프에 앉아있다. 게다가, 그것이 작동하더라도, XNextEvent()에 대한 호출 바로 전에 상태가 IsViewable로 바뀌면 어떻게 될지 궁금 할 것입니다. 그런 다음 XNextEvent()는 다른 윈도우가 매핑, 매핑 해제, 이동, 제기, 크기 조정 등을 할 때까지 앉아서 기다릴 것입니다. 그래서 아마 내 애플 리케이션을 막히게 될 줄 알았어. – Andreas

+0

가상 루트가있는 WM이있을 수 있습니다. 나는 그들과 많은 경험이 없다. 가상 루트가 무엇인지 찾아서 사용해야합니다. –

+0

IsViewable은 루트 하위 구조에서 * (* 따라서 * after *) 무언가가 변경되기 때문에 * 변경되지 않습니다. –