在X11中等效“Invalidate Rect”/“WM_PAINT”

时间:2013-06-10 15:55:13

标签: c++ linux x11 xlib

我正在将一些代码从Windows移植到XLib。在windows代码中,我可以通过调用InvalidateRect强制重绘,然后处理相应的WM_PAINT消息。但是,我无法在X11 / XLib中找到如何执行此操作。我看到有一条Expose消息,但不确定这是否是同一件事。

如果重要,我需要这样做以强制窗口以特定帧速率渲染基于OpenGL的程序。

2 个答案:

答案 0 :(得分:4)

您需要处理Expose事件。 This tutorial通过示例解释了如何处理Expose事件:

#include <stdio.h>
#include <stdlib.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xos.h>
#include <X11/Xatom.h>
#include <X11/keysym.h>
/*Linux users will need to add -ldl to the Makefile to compile 
 *this example.
 */
Display *dis;
Window win;
XEvent report;
GC green_gc;
XColor green_col;
Colormap colormap;
/*
Try changing the green[] = below to a different color.
The color can also be from /usr/X11R6/lib/X11/rgb.txt, such as RoyalBlue4.
A # (number sign) is only needed when using hexadecimal colors.
*/
char green[] = "#00FF00";

int main() {
    dis = XOpenDisplay(NULL);
    win = XCreateSimpleWindow(dis, RootWindow(dis, 0), 1, 1, 500, 500, 0, BlackPixel (dis, 0), BlackPixel(dis, 0));
    XMapWindow(dis, win);
    colormap = DefaultColormap(dis, 0);
    green_gc = XCreateGC(dis, win, 0, 0);
    XParseColor(dis, colormap, green, &green_col);
    XAllocColor(dis, colormap, &green_col);
    XSetForeground(dis, green_gc, green_col.pixel);

    XSelectInput(dis, win, ExposureMask | KeyPressMask | ButtonPressMask);

    XDrawRectangle(dis, win, green_gc, 1, 1, 497, 497);
    XDrawRectangle(dis, win, green_gc, 50, 50, 398, 398);
    XFlush(dis);

    while (1)  {
    XNextEvent(dis, &report);
        switch  (report.type) {
        case Expose:   
            fprintf(stdout, "I have been exposed.\n");
                XDrawRectangle(dis, win, green_gc, 1, 1, 497, 497);
                XDrawRectangle(dis, win, green_gc, 50, 50, 398, 398);
                XFlush(dis);
            break;
            case KeyPress:
        /*Close the program if q is pressed.*/
                if (XLookupKeysym(&report.xkey, 0) == XK_q) {
                exit(0);
                }
            break;
        }
    }

return 0;
}

我可能误解了这个问题。如果要在应用程序中创建Expose事件,可以创建并设置expose event,并使用XSendEvent发送。

答案 1 :(得分:4)

稍微扩展BЈовић,

给出的有用答案

使用原始Xlib,您可以随时在单个线程中绘制,因为每个Xlib函数都指定完整的显示,窗口和上下文。 AFAIK,多线程所有投注都已关闭。

如果您在桌面环境中,还必须拥有Expose事件处理程序,并选择这些事件。即使你正在编写全屏程序,也不会有任何伤害。

大多数工具包不够灵活,只能在指定的事件处理程序中绘制(但在许多其他方面使用得更好),并且有一些等同于Windows InvalidateRect。在原始Xlib中,通过发送自己的Expose事件可以获得相同的效果。这样做不会导致任何真正的性能问题,并且会使其他程序员更容易理解代码,并且更容易移植,所以你也可以这样做。

还有XClearArea和XClearWindow函数会为您生成Expose事件,但它们首先使用背景颜色擦除部分/全部,这可能会导致闪烁。

使用OpenGL它会变得更复杂,因为你也必须使用GLX。我在网上有一个非常简单的OpenGL / Xlib程序 http://cs.anu.edu.au/~hugh.fisher/3dteach/ 这可能是一个有用的例子。