0

在测试程序中:

/*
 * 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。

谢谢,

斯科特·佛朗哥加利福尼亚州圣何塞

4

0 回答 0