我第一次在 C 中使用 xlib,而不是 C++。我想在屏幕上绘制一个测试框,但我必须等待 xorg 创建窗口。我有一个 MapNotify 回调,它被提前调用。我添加了 3 秒的延迟,3 秒后盒子就画好了。这个解决方案显然只是为了测试,但是我无法让回调正常工作。
代码(注意我的延迟被注释了,注释时函数停止工作)
#include <time.h>
#include <string.h>
#include <unistd.h>
#include <assert.h>
#include <X11/X.h>
#include <X11/Xlib.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#define white 0xFFFFFF
#define black 0
#define red 0xFF0000
#define green 0xFF00
#define blue 0xFF
void delay(unsigned int millis) {
clock_t start = clock();
while(clock() < start + millis);
}
int main(int argc, char** argv) {
Display* dpy = XOpenDisplay(NULL); // Get default display
if(dpy == NULL) {
fprintf(stderr, "Cannot open display\n");
return 1;
}
Window win = XCreateSimpleWindow(dpy, XDefaultRootWindow(dpy), 0, 0, 800, 800, 0, 0, black); // Make a """simple""" window
XMapWindow(dpy, win);
XSelectInput(dpy, win, StructureNotifyMask); // Get MapNotify events
GC gc = XCreateGC(dpy, win, 0, 0);
if(gc == NULL) {
fprintf(stderr, "Failed to make a GC\n");
return 1;
}
XSetBackground(dpy, gc, white);
XSetForeground(dpy, gc, white);
XSync(dpy, true);
while(true) { // Await for screen, TODO this is called too early for some reason
XEvent e;
XNextEvent(dpy, &e);
printf("Got event: %d\n", e.type);
if(e.type == MapNotify)
break;
}
//delay(3000);
XFillRectangle(dpy, win, gc, 5, 5, 100, 100);
XFlush(dpy);
while(true) { // Await for window close, this doesn't actually work but I don't care for now
XEvent e;
XNextEvent(dpy, &e);
if(e.type == UnmapNotify)
return 0;
}
}
根据您上面的后续评论,我认为以下声明(来自XMapWindow)确实最好地回答了这个问题:
如果窗口是一个InputOutput窗口,XMapWindow()会在它导致显示的每个InputOutput窗口上生成Expose事件。
如果客户端映射并绘制窗口并且客户端开始处理事件,则窗口将被绘制两次。为了避免这种情况,首先请求 Expose 事件,然后映射窗口,以便客户端照常处理输入事件。
事件列表将包括屏幕上出现的每个窗口的“Expose”。 客户端对 Expose 事件的正常响应应该是重新绘制窗口。这种方法通常会导致程序更简单并与窗口管理器进行正确的交互。