在测试程序中:
/*
* Study for Xwindow events.
*/
#include <X11/Xlib.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//#define BACKGROUND_PAINT
void prtxevtt(int type)
{
switch (type) {
case 2: fprintf(stderr, "KeyPress"); break;
case 3: fprintf(stderr, "KeyRelease"); break;
case 4: fprintf(stderr, "ButtonPress"); break;
case 5: fprintf(stderr, "ButtonRelease"); break;
case 6: fprintf(stderr, "MotionNotify"); break;
case 7: fprintf(stderr, "EnterNotify"); break;
case 8: fprintf(stderr, "LeaveNotify"); break;
case 9: fprintf(stderr, "FocusIn"); break;
case 10: fprintf(stderr, "FocusOut"); break;
case 11: fprintf(stderr, "KeymapNotify"); break;
case 12: fprintf(stderr, "Expose"); break;
case 13: fprintf(stderr, "GraphicsExpose"); break;
case 14: fprintf(stderr, "NoExpose"); break;
case 15: fprintf(stderr, "VisibilityNotify"); break;
case 16: fprintf(stderr, "CreateNotify"); break;
case 17: fprintf(stderr, "DestroyNotify"); break;
case 18: fprintf(stderr, "UnmapNotify"); break;
case 19: fprintf(stderr, "MapNotify"); break;
case 20: fprintf(stderr, "MapRequest"); break;
case 21: fprintf(stderr, "ReparentNotify"); break;
case 22: fprintf(stderr, "ConfigureNotify"); break;
case 23: fprintf(stderr, "ConfigureRequest"); break;
case 24: fprintf(stderr, "GravityNotify"); break;
case 25: fprintf(stderr, "ResizeRequest"); break;
case 26: fprintf(stderr, "CirculateNotify"); break;
case 27: fprintf(stderr, "CirculateRequest"); break;
case 28: fprintf(stderr, "PropertyNotify"); break;
case 29: fprintf(stderr, "SelectionClear"); break;
case 30: fprintf(stderr, "SelectionRequest"); break;
case 31: fprintf(stderr, "SelectionNotify"); break;
case 32: fprintf(stderr, "ColormapNotify"); break;
case 33: fprintf(stderr, "ClientMessage"); break;
case 34: fprintf(stderr, "MappingNotify"); break;
case 35: fprintf(stderr, "GenericEvent"); break;
default: fprintf(stderr, "???"); break;
}
}
void prtxevt(Display* d, XEvent* e)
{
fprintf(stderr, "X Event: %5ld Window: %lx ", e->xany.serial,
e->xany.window);
prtxevtt(e->type);
switch (e->type) {
case Expose: fprintf(stderr, ": x: %d y: %d w: %d h: %d",
e->xexpose.x, e->xexpose.y,
e->xexpose.width, e->xexpose.height); break;
case ConfigureNotify: fprintf(stderr, ": x: %d y: %d w: %d h: %d",
e->xconfigure.x, e->xconfigure.y,
e->xconfigure.width, e->xconfigure.height); break;
case MotionNotify: fprintf(stderr, ": x: %d y: %d",
e->xmotion.x, e->xmotion.y); break;
case PropertyNotify: fprintf(stderr, ": atom: %s",
XGetAtomName(d, e->xproperty.atom));
}
fprintf(stderr, "\n"); fflush(stderr);
}
int main(void) {
Window w;
GC gracxt;
XEvent e;
const char* msg = "Hello, window";
int s;
Display* d;
XFontStruct* font;
d = XOpenDisplay(NULL);
if (d == NULL) {
fprintf(stderr, "Cannot open display\n");
exit(1);
}
s = DefaultScreen(d);
font = XLoadQueryFont(d,
"-bitstream-courier 10 pitch-bold-r-normal--0-0-200-200-m-0-iso8859-1");
if (!font) {
fprintf(stderr, "*** No font ***\n");
exit(1);
}
gracxt = XDefaultGC(d, s);
XSetFont(d, gracxt, font->fid);
#ifdef BACKGROUND_PAINT
w = XCreateSimpleWindow(d, RootWindow(d, s), 10, 10, 1000, 1000, 5,
BlackPixel(d, s), WhitePixel(d, s));
#else
// no background draw
w = XCreateWindow(d, RootWindow(d, s), 0, 0, 1000, 1000, 0, CopyFromParent,
InputOutput, CopyFromParent, 0, NULL);
#endif
XSelectInput(d, w, ExposureMask|KeyPressMask|/*PointerMotionMask|*/
StructureNotifyMask/*|PropertyChangeMask*/);
XMapWindow(d, w);
while (1) {
XNextEvent(d, &e);
prtxevt(d, &e);
if (e.type == Expose) {
XSetForeground(d, gracxt, WhitePixel(d, s));
XFillRectangle(d, e.xany.window, gracxt,
e.xexpose.x, e.xexpose.y,
e.xexpose.width, e.xexpose.height);
XSetForeground(d, gracxt, BlackPixel(d, s));
XDrawString(d, e.xany.window, gracxt, 10, 50, msg, strlen(msg));
}
}
XCloseDisplay(d);
return 0;
}
它是一个相当普通的窗口,上面画着“你好,窗口”(文本被放大,因为我有一个 4k 显示器)。背景油漆被关闭了,所以我们自己处理油漆。
如果我抓住窗口的右下角并在 x 和 y 中缓慢展开它,我会得到:
miam@samiam-h-pc-2:~/projects/petit_ami_tools/linux$ ./xmltwin
X Event: 13 Window: 4e00002 ReparentNotify
X Event: 13 Window: 4e00002 ConfigureNotify: x: 20 y: 90 w: 1000 h: 1000
X Event: 13 Window: 4e00002 MapNotify
X Event: 13 Window: 4e00002 Expose: x: 0 y: 0 w: 1000 h: 1000
X Event: 17 Window: 4e00002 ConfigureNotify: x: 20 y: 90 w: 1001 h: 1000
X Event: 17 Window: 4e00002 Expose: x: 0 y: 0 w: 1001 h: 1000
X Event: 21 Window: 4e00002 ConfigureNotify: x: 20 y: 90 w: 1005 h: 1002
X Event: 21 Window: 4e00002 Expose: x: 0 y: 0 w: 1005 h: 1002
X Event: 25 Window: 4e00002 ConfigureNotify: x: 20 y: 90 w: 1007 h: 1003
X Event: 25 Window: 4e00002 Expose: x: 0 y: 0 w: 1007 h: 1003
X Event: 29 Window: 4e00002 ConfigureNotify: x: 20 y: 90 w: 1008 h: 1004
X Event: 29 Window: 4e00002 Expose: x: 0 y: 0 w: 1008 h: 1004
X Event: 33 Window: 4e00002 ConfigureNotify: x: 20 y: 90 w: 1009 h: 1004
X Event: 33 Window: 4e00002 Expose: x: 0 y: 0 w: 1009 h: 1004
X Event: 37 Window: 4e00002 ConfigureNotify: x: 20 y: 90 w: 1010 h: 1005
X Event: 37 Window: 4e00002 Expose: x: 0 y: 0 w: 1010 h: 1005
X Event: 41 Window: 4e00002 ConfigureNotify: x: 20 y: 90 w: 1012 h: 1005
X Event: 41 Window: 4e00002 Expose: x: 0 y: 0 w: 1012 h: 1005
X Event: 45 Window: 4e00002 ConfigureNotify: x: 20 y: 90 w: 1013 h: 1006
X Event: 45 Window: 4e00002 Expose: x: 0 y: 0 w: 1013 h: 1006
X Event: 49 Window: 4e00002 ConfigureNotify: x: 20 y: 90 w: 1015 h: 1009
X Event: 49 Window: 4e00002 Expose: x: 0 y: 0 w: 1015 h: 1009
X Event: 53 Window: 4e00002 ConfigureNotify: x: 20 y: 90 w: 1016 h: 1010
X Event: 53 Window: 4e00002 Expose: x: 0 y: 0 w: 1016 h: 1010
X Event: 57 Window: 4e00002 ConfigureNotify: x: 20 y: 90 w: 1016 h: 1011
X Event: 57 Window: 4e00002 Expose: x: 0 y: 0 w: 1016 h: 1011
X Event: 61 Window: 4e00002 ConfigureNotify: x: 20 y: 90 w: 1017 h: 1011
X Event: 61 Window: 4e00002 Expose: x: 0 y: 0 w: 1017 h: 1011
X Event: 65 Window: 4e00002 ConfigureNotify: x: 20 y: 90 w: 1017 h: 1012
X Event: 65 Window: 4e00002 Expose: x: 0 y: 0 w: 1017 h: 1012
X Event: 69 Window: 4e00002 ConfigureNotify: x: 20 y: 90 w: 1018 h: 1013
X Event: 69 Window: 4e00002 Expose: x: 0 y: 0 w: 1018 h: 1013
X Event: 73 Window: 4e00002 ConfigureNotify: x: 20 y: 90 w: 1019 h: 1014
X Event: 73 Window: 4e00002 Expose: x: 0 y: 0 w: 1019 h: 1014
请注意,我得到了完整的公开事件,也就是说,公开矩形告诉我重新绘制整个窗口。这在技术上是正确的,但效率很低。我希望暴露矩形只要求绘制窗口的最右边和最底部部分,在上面的示例中,它们只是单个像素切片。
我知道如果我指定背景像素,Xwindow 必须给我完全曝光事件,因为它正在为我擦除背景。但这应该在后台关闭。我关闭了填充(XFillRectangle)并验证它不会绘制背景,将其保留为窗口下的先前内容。我是否指定没有正确绘制背景?
我注意到 Xwindows 的底层代码使用 XCB,并且它不会生成未覆盖的绘制(在前面放置另一个窗口,阻挡它的一部分,然后移动以再次显示该窗口)。这(对我来说)意味着它正在缓冲绘制的表面并从内存中恢复它。一种理论是 XLIB/XCB 不再需要优化暴露事件。
带有 GDM3 的 Ubuntu 20.04 LTS。
谢谢,
斯科特·佛朗哥加利福尼亚州圣何塞