我正在尝试打开一个 X11 窗口,打印出一个像素,然后添加代码以使 Terminate() 返回 true。但它不会形成一个窗口。这是我的代码:
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xos.h>
#include <iostream>
int x = 0;
int y = 0;
bool Termination() {
return true;
}
int main() {
Display *dspl = XOpenDisplay(NULL);
if (!dspl) return 1;
int screenNumber = DefaultScreen(dspl);
unsigned long white = WhitePixel(dspl, screenNumber);
unsigned long black = BlackPixel(dspl, screenNumber);
Window win = XCreateSimpleWindow(dspl, DefaultRootWindow(dspl), 50, 50, 1280, 720, 0, black, white);
XSetStandardProperties(dspl, win, "Lel", "Gaem", None, NULL, 0, NULL);
GC gc = XCreateGC(dspl, win, 0,0);
XSetBackground(dspl, gc, black);
XSetForeground(dspl, gc, white);
XClearWindow(dspl, win);
XMapRaised(dspl, win);
XDrawPoint(dspl, win, gc, x, y);
while (Termination())
{
}
XFreeGC(dspl, gc);
XDestroyWindow(dspl, win);
XCloseDisplay(dspl);
printf("Job's done!\n");
return 0;
}
是什么阻止 X11 显示我的窗口?
在此之前添加此
XMapWindow(dspl, win);
XInternAtom(dspl, "WM_DELETE_WINDOW", False);
我知道这是一个老问题,OP可能不再关心,但我很惊讶它没有更多答案,也许这可以帮助其他人。
虽然 Andrew Nic 的解决方案是偶然起作用的,但你的原始代码没有打开窗口的真正原因是因为 Xlib 两者:
在最低级别,Xlib 只是一个库,它将您的 Xlib 调用转换为网络数据包并将它们排入其内部 tx 队列。由于它没有单独的线程运行该队列,因此仅通过在 while 循环中自旋锁,Xlib 永远不会再次获得控制权,因此永远没有机会刷新其传出请求队列,并且服务器永远不会听到您的 CreateWindow 请求。
你期望要做的就是遵循这样的模式:
while (Termination())
{
XEvent evt;
XNextEvent(dspl, &evt);
}
XNextEvent 会让 Xlib 知道您现在已经完成并隐式刷新任何待处理的请求。或者,您可以通过明确地告诉 Xlib 首先传输它的队列,从技术上让它按原样工作:
XFlush(dspl);
while (Termination())
{
}
...尽管请注意,在任何程序中,像这样旋转而不至少添加一个短的 usleep() 或 poll() (例如,在循环内“usleep(10 * 1000);”)通常都是不明智的。内核最终会介入并抢占您的进程以保持其他任务继续运行,但其中一个核心的 CPU 使用率将达到 100%。不管怎样,当你的程序变得更加复杂时,你可能很快就会想要运行事件循环。 Xlib 假设您的程序将围绕这样的事件循环构建,这就是原始代码无法按预期工作的原因。
一个例外是从 X 服务器返回某种信息的调用(或者再次在网络级别,它们真正做的是发送数据包并阻塞,直到收到服务器的答复)——这些也迫使 Xlib进行隐式刷新/同步,因为服务器显然需要“赶上”最新的请求才能发送程序正在等待的答复。 InternAtom 就是一个这样的请求,这就是为什么 Andrew Nic 的解决方案顺便解决了这个问题(请注意,查找到的 WM_DELETE_WINDOW 原子从未实际使用过,因此它不执行任何其他操作,并且可能只是一个 XFlush() ,因为这一面 -效果是唯一的效果)。
还要注意,虽然在许多现代 DE 中,在循环之前绘制像素确实有效(由于合成器),但为了可靠,您实际上应该等到收到 Expose 事件后再绘制到窗口。至少,如果窗口被覆盖和未覆盖(或图标化/恢复),则通过不在 Expose 上进行重新绘制,您的像素可能会消失。
来源:我通过开发一个通过原始 TCP 套接字与 X 通信的库而熟悉 X11 协议,并且相当熟悉 Xlib 源代码。