简体   繁体   English

Xlib:关闭窗口总是会导致致命的IO错误?

[英]Xlib: Closing window always causes fatal IO error?

I'm not sure why this happens, but any window I create using Xlib in C++ gives outputs an error to the terminal when I try to close is using the X button. 我不确定为什么会发生这种情况,但是我在C ++中使用Xlib创建的任何窗口都会在我尝试关闭时使用X按钮向终端输出错误。 I can close it programmatically with no errors, it's just the X button that does it. 我可以通过编程方式关闭它而没有错误,它只是执行它的X按钮。

The error is the following: 错误如下:

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

The number of requests is different every time, but there's always 0 events remaining. 请求的数量每次都不同,但总有0个事件剩余。 Why does this happen? 为什么会这样? The cause doesn't seem to be my code, since it does this no matter what and sends no close events to the queue. 原因似乎不是我的代码,因为它无论如何都会执行此操作并且不向队列发送任何关闭事件。 I've tried intercepting the Atom WM_WINDOW_DELETE, and it doesn't run over the expected code when I close the window. 我试过拦截Atom WM_WINDOW_DELETE,当我关闭窗口时它不会运行预期的代码。

Edit: Added event loop code. 编辑:添加了事件循环代码。

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);
}

In addition to WM_WINDOW_DELETE you need to listen for and handle the ClientMessage event. WM_WINDOW_DELETE外,您还需要侦听并处理ClientMessage事件。

Modifying the example from Rosetta Code to illustrate: 修改Rosetta代码中的示例以说明:

#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;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM