2013-10-10 3 views
6

Я не уверен, почему это происходит, но любое окно, которое я создаю с помощью Xlib в C++, выдает сообщение об ошибке, когда я пытаюсь закрыть, используя кнопку X. Я могу закрыть его программно без ошибок, это просто кнопка X, которая это делает.Xlib: Закрывающее окно всегда вызывает фатальную ошибку ввода-вывода?

Ошибка заключается в следующем:

XIO: fatal IO error 11 (Resource temporarily unavailable) on X server ":0" 
after 483 requests (483 known processed) with 0 events remaining. 

Количество запросов меняется каждый раз, но всегда есть 0 событий осталось. Почему это происходит? Причина не в том, что мой код, так как он делает это независимо от того, что и не отправляет в очередь никаких событий. Я пытался перехватить Atom WM_WINDOW_DELETE, и он не запускается над ожидаемым кодом при закрытии окна.

Редактировать: Добавлен код цикла событий.

while(XPending(display)) { 
    XNextEvent(display, &event); 

    pthread_mutex_unlock(&mutex); 

    if(event.type == Expose) { 
     XWindowAttributes getWindowAttributes; 

     pthread_mutex_lock(&mutex); 

     XGetWindowAttributes(display, window, &getWindowAttributes); 

     if(state.currentState == STATE_NORMAL) { 
      state.normX = getWindowAttributes.x; 
      state.normY = getWindowAttributes.y; 
      state.normWidth = getWindowAttributes.width; 
      state.normHeight = getWindowAttributes.height; 
     } 

     pthread_mutex_unlock(&mutex); 

     glViewport(0, 0, getWindowAttributes.width, getWindowAttributes.height); 
    } else if(event.type == KeyPress) { 
     return false; 
    } else if(event.type == ClientMessage) { 
     std::cout<<"X Button pressed"<<std::endl; //Never run when X-ing window 
     if(event.xclient.message_type == XInternAtom(display, "WM_DELETE_WINDOW", True)) { 
      return false; 
     } 
    } else if(event.type == ButtonPress) { 
     if(state.currentState != STATE_FULLSCREEN) { 
      fullscreen(); 
     } else { 
      normalize(); 
     } 
    } else if(!handleEvent(event)){ 
     return false; 
    } 

    pthread_mutex_lock(&mutex); 
} 
+0

_любой_ окна, даже всплывающих окон или переходных процессы? –

+0

В дополнение к 'WM_WINDOW_DELETE' вам необходимо прослушать и обработать событие' ClientMessage'. Покажите свой код по. 'WM_WINDOW_DELETE'. – mythagel

+0

Добавлен код цикла событий - я уже ищу ClientMessage. Это действие закрытия окна, которое закрывает ошибку, поэтому сообщение никогда не получено. – NmdMystery

ответ

4

В дополнение к WM_WINDOW_DELETE вы должны слушать и обработать ClientMessage событие.

Изменение примера из Rosetta Code для иллюстрации:

#include <X11/Xlib.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 

int main(void) { 
    Display *d; 
    Window w; 
    XEvent e; 
    const char *msg = "Hello, World!"; 
    int s; 

    d = XOpenDisplay(NULL); 
    if (d == NULL) { 
     fprintf(stderr, "Cannot open display\n"); 
     exit(1); 
    } 

    s = DefaultScreen(d); 
    w = XCreateSimpleWindow(d, RootWindow(d, s), 10, 10, 100, 100, 1, BlackPixel(d, s), WhitePixel(d, s)); 
    XSelectInput(d, w, ExposureMask | KeyPressMask); 
    XMapWindow(d, w); 

    // I support the WM_DELETE_WINDOW protocol 
    Atom WM_DELETE_WINDOW = XInternAtom(d, "WM_DELETE_WINDOW", False); 
    XSetWMProtocols(d, w, &WM_DELETE_WINDOW, 1); 

    while (1) { 
     XNextEvent(d, &e); 
     if (e.type == Expose) { 
      XFillRectangle(d, w, DefaultGC(d, s), 20, 20, 10, 10); 
      XDrawString(d, w, DefaultGC(d, s), 10, 50, msg, strlen(msg)); 
     } 
     else if (e.type == KeyPress) 
      break; 
     else if (e.type == ClientMessage) 
      // TODO Should check here for other client message types - 
      // however as the only protocol registered above is WM_DELETE_WINDOW 
      // it is safe for this small example. 
      break; 
    } 

    XCloseDisplay(d); 
    return 0; 
} 
+0

Я добавил SetWMProtocols к моему коду, похоже, этого не было. Почему вы должны сделать это по умолчанию? Weird ... – NmdMystery

+0

Также я заметил, что std :: cout не ведет себя так, как я ожидал. Иногда он работает правильно, в других случаях он просто ждет, пока программа не будет закрыта для вывода на терминал или ждет случайный период времени. Связано ли это с Xlib? – NmdMystery

+0

'SetWMProtocols' требуется, потому что без явного уведомления диспетчер окон не может делать предположений о возможностях любого конкретного клиента. Просто запрос «Atom» на самом деле ничего не делает. Один атом - это просто ручка ресурса. – mythagel

Смежные вопросы