如何退出X11程序而不会出现错误 [英] How do you exit X11 program without Error

查看:64
本文介绍了如何退出X11程序而不会出现错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

问题的结尾,我在X11中有一个相当简单的"Hello World".但是当它退出时,我得到下面的运行时错误消息:

I have a fairly simple "Hello World" in X11 at end of question. But when it exits I get the run time error messages below:

$ ./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()时,我得到了新的错误.

So I tried handling the wmDeleteMessage myself, and I was able to stop the window from closing, so i know I am getting the event correctly. Than I added a XDestroyWindow() to the event handling and I get new errors.

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

这听起来像是我要破坏一个已经毁坏的Window,但是如果我拿出 XDestroyWindow(),它在屏幕上仍然有效.

It sounds like i am trying to destroy a already destroyed Window, but if I take out the XDestroyWindow() it stays alive on my screen.

下面是我的代码,试图破坏窗口处理程序.如何退出而没有任何错误?

Below is my code with an attempt at a destroy window handler. How do I exit without any errors?

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

我不喜欢,因为我打算拥有更多的窗户,但是现在我回到我遇到的第一条错误消息:

Which I don't like because I plan on having more than window, but for now I am back to the first error message I had :

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 ,我遇到了同样的问题与他们的代码.我的设置一定有问题.

Tried changing many things around like having the loop run off of XPending(). Decided to run someone else's hello world and I get the same problem with their code. Must be something wrong with my setup.

更新显然很多人都有这个问题.Google ftk遇到了此问题,他们在

Update Apparently alot of people have this problem. Google ftk had this problem and they fixed it in their change log. They call FTK_QUIT() which i am guessing is like Exit(). So i put my return right there inside the loop and that solved the problem. Not sure why but it did. fixed code:

  case ClientMessage:
    if(e.xclient.data.l[0] == wmDeleteMessage) 
    {
      XDestroyWindow(display,e.xclient.window);
      XCloseDisplay(display);
      return 0;
    }

仍然会向能够解释为什么以及是否有可能将return语句(以及 XCloseDisplay )移出循环的人给出正确的答案.

Will still give correct answer to someone who can explain why and if is possible move the return statement (along with the XCloseDisplay) outside of the loop.

事件循环应如下所示正确退出:

The Event loop should look like this to exit properly:

  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 语句之前,可以解决该问题,而无需从循环内的程序返回.

When running in a switch statement the code does not work. Even if it exits the loop without calling another X function. The if statement above placed before your switch statement fixes the issue without returning from the program inside the loop.

推荐答案

此问题的解决方案很简单:

The solution to this problem is straightforward:

您必须在 XDestroyWindow ()函数中使用正确的结构成员.

You must use the right structure member with the XDestroyWindow() function.

由于X11事件结构的实现标准,它们彼此非常相似.每个结构都以'type'成员开头,而第一个成员实际上总是相同的.

Due to the implementation standard of the X11 event structures, they're very similar each other. Every structure begins with the 'type' member, and the first members are practically always the same.

现在假设:

int = 4 bytes
Bool = 4 bytes
unsigned long = 8 bytes
Display* = 8 bytes
Window = 4 bytes

如果使用 e.xdestroywindow.window 调用 XDestroyWindow (),则距离事件结构的开头要28个字节,而如果使用 e.xclient.window ,您将有24个字节.

If you call XDestroyWindow() with e.xdestroywindow.window, you are going to be 28 bytes away from the beginning of the event structure, while if you use e.xclient.window, you would be 24 bytes away.

由于您将使用错误的Window参数调用 XDestroyWindow (),因此它将失败.相反,如果您使用 e.xdestroywindow.event (距离事件结构的开头有24个字节)来调用它,则地址将是正确的,并且该函数将正常运行.

Since you're going to call XDestroyWindow() with a wrong Window argument, it will fail. Instead if you call it using e.xdestroywindow.event (which is 24 bytes away from the beginning of the event structure), the address would be right and the function would work gracefully.

如果您看一下 Xlib.h 文件,您会注意到这两个结构的 window 元素的位置不同.

If you take a look yourself at the Xlib.h file, you'll notice that the two structures have the window element positioned differently.

指出这一点,请记住Xlib已经开发了多年,并且每天都有许多程序员在使用它,因此,如果发生神秘错误,它可能不在Xlib中.作为最后的提示,我想告诉您:如果您想进一步了解Xlib编程,请始终将头文件作为主要参考,然后是系统手册,然后是所有其他内容.

Stated this, remember that Xlib has been developed for years and many programmers every day work with it, so if there is a mysterious error, it's probably not within Xlib. As a last hint I want to tell you: if you want to get farther with Xlib programming, always take the header files as the primary reference, followed by the system manual, then all the rest.

最后,您的代码唯一的错误是:

The only error with your code in the end is:

XDestroyWindow(display,e.xdestroywindow.window);

必须更改为此:

XDestroyWindow(display,e.xclient.window);

相反,使用 switch 很好,并且使用最方便,并且X11代码没有问题.

Instead the usage of switch is good, and is the most implemented, with no issues on the X11 code.

注意:我已经亲自测试了您的代码,只更改了该行,然后进行了各种测试,并打印了结果. XDestroyWindow ()行肯定是唯一的错误.

NOTE: I've tested your code myself, by changing that line only, and then doing various tests, printing the result. The XDestroyWindow() line is for sure the only error.

这篇关于如何退出X11程序而不会出现错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆