【发布时间】:2011-12-31 20:48:42
【问题描述】:
问题结束时,我在 X11 中有一个相当简单的“Hello World”。但是当它退出时,我会收到以下运行时错误消息:
$ ./xtest
XIO: fatal IO error 11 (Resource temporarily unavailable) on X server ":0"
after 9 requests (7 known processed) with 0 events remaining.
所以我尝试自己处理wmDeleteMessage,我能够阻止窗口关闭,所以我知道我正确地收到了事件。然后我在事件处理中添加了XDestroyWindow(),我得到了新的错误。
X Error of failed request: BadWindow (invalid Window parameter)
Major opcode of failed request: 4 (X_DestroyWindow)
Resource id in failed request: 0x130
Serial number of failed request: 12
Current serial number in output stream: 12
听起来我想摧毁一个已经被摧毁的窗口,但如果我取出XDestroyWindow(),它会在我的屏幕上保持活动状态。
下面是我尝试销毁窗口处理程序的代码。如何在没有任何错误的情况下退出?
#include<X11/Xlib.h>
#include <iostream>
int main()
{
Display *display;
if(!(display=XOpenDisplay(NULL)))
{
std::cerr << "ERROR: could not open display\n";
return 1;
}
int screen = DefaultScreen(display);
Window rootwind = RootWindow(display, screen);
Colormap cmap = DefaultColormap(display, screen);
Atom wmDeleteMessage = XInternAtom(display, "WM_DELETE_WINDOW", False);
int blackColor = BlackPixel(display, screen);
int whiteColor = WhitePixel(display, screen);
Window w = XCreateSimpleWindow(display, rootwind, 0, 0, 200, 100, 0, blackColor, blackColor);
XMapWindow(display, w);
XSetWMProtocols(display, w, &wmDeleteMessage, 1);
bool running = true;
while(running)
{
XEvent e;
XNextEvent(display, &e);
switch (e.type)
{
case ClientMessage:
if(e.xclient.data.l[0] == wmDeleteMessage)
{
std::cout << "Shutting down now!!!" << std::endl;
XDestroyWindow(display,e.xdestroywindow.window);
running=false;
break;
}
break;
}
}
XCloseDisplay(display);
return 0;
}
更新
将行改为:
std::cout << "Shutting down now!!!" << std::endl;
XDestroyWindow(display,w);
我不喜欢,因为我打算拥有更多的窗口,但现在我是 回到我收到的第一条错误消息:
XIO: fatal IO error 11 (Resource temporarily unavailable) on X server ":0"
after 9 requests (7 known processed) with 0 events remaining.
更新
尝试改变很多事情,比如让循环运行 XPending()。 决定运行别人的hello world,我的代码也遇到了同样的问题。我的设置一定有问题。
更新 显然很多人都有这个问题。 Google ftk 遇到了这个问题,他们在change log 中修复了它。他们调用 FTK_QUIT(),我猜这就像 Exit()。所以我把我的回报放在循环里面,这就解决了这个问题。不知道为什么,但确实如此。固定代码:
case ClientMessage:
if(e.xclient.data.l[0] == wmDeleteMessage)
{
XDestroyWindow(display,e.xclient.window);
XCloseDisplay(display);
return 0;
}
仍会向能够解释原因以及是否可以将 return 语句(连同 XCloseDisplay)移出循环的人给出正确答案。
事件循环应该看起来像这样才能正确退出:
XEvent e;
do
{
XNextEvent(display, &e);
if(e.type == ClientMessage && e.xclient.data.l[0] == wmDeleteMessage)
{
XDestroyWindow(display,e.xclient.window);
break;
}
//...
}while (XPending(display) > 0)
XCloseDisplay(display);
return 0;
在switch 语句中运行时,代码不起作用。即使它退出循环而不调用另一个 X 函数。上面的 if 语句放在您的 switch 语句之前可以解决问题,而无需从循环内的程序返回。
【问题讨论】:
-
添加了转义到循环,因为意识到它永远不会爆发。仍然是相同的错误消息。
-
为什么要直接做X11编程?我强烈建议使用图形工具包,例如 GTK 或 Qt(但也有其他工具包:FLTK、Fox...)
-
@Starynkevitch 更多了解它的工作原理。不适用于工作或学校。