我怎么知道 X server 何时完成绘制?
How do I know when X server has completed the drawing?
假设我想一个接一个地画矩形。我如何知道 X 服务器何时完成绘制一个矩形?有没有办法从 X 服务器获得任何确认?
在下面的代码中,我在 500,500 处绘制了第一个矩形,并在公开处理程序中重新绘制了相同的矩形。之后,我在 1000,1000 处绘制了一个新矩形。问题是第一个矩形从未被绘制。我必须通过 Expose 事件处理程序多少次? 多少次才够?
#include <X11/Xlib.h>
#include <X11/extensions/XTest.h>
#include <X11/Xutil.h>
#include <iostream>
using namespace std;
int main(){
Display *disp;
int screen;
Window win;
GC gc;
disp = XOpenDisplay(NULL);
screen = DefaultScreen(disp);
XColor color;
Colormap colormap;
char black[] = "#ffffff";
colormap = DefaultColormap(disp, 0);
XParseColor(disp, colormap, black, &color);
XAllocColor(disp, colormap, &color);
win = XCreateSimpleWindow(disp, RootWindow(disp, screen), 10,
10, 1500, 1500, 0, WhitePixel(disp, screen), color.pixel);
XSizeHints my_hints = {0};
my_hints.flags = PPosition | PSize;
my_hints.x = 10;
my_hints.y = 10;
my_hints.width = 1500;
my_hints.height = 1500;
XSetNormalHints(disp, win, &my_hints);
XMapWindow(disp, win);
gc = XCreateGC(disp, win, 0, 0);
XColor color1;
Colormap colormap1;
char red[] = "#000000";
colormap1 = DefaultColormap(disp, 0);
XParseColor(disp, colormap1, red, &color1);
XAllocColor(disp, colormap1, &color1);
XSetForeground(disp, gc, color1.pixel);
XSelectInput(disp, win, ExposureMask);
int x1 = 500;
int x2 = 500;
XEvent event;
int i = 0;
while(true){
XDrawRectangle(disp, win, gc, x1, x1, 500, 500);
XNextEvent(disp, &event);
if(event.xany.window == win){
if(event.type == Expose){
cout << i << endl;
XDrawRectangle(disp, win, gc, x1, x2, 500, 500);
}
}
i++;
x1 += 500;
x2 += 500;
}
XFreeGC(disp, gc);
XDestroyWindow(disp, win);
XCloseDisplay(disp);
return 0;
}
输出
0
1
2
3
您似乎希望 XDrawRectangle()
生成 Expose
事件,但它永远不会发生,因为它不是这样工作的。 Expose
事件在 window 被映射、调整大小、移动或模糊 window 未映射时生成,但绘制到 window 时不会生成。实际上,您唯一感兴趣的 Expose
事件是由 XMapWindow()
生成的事件。收到第一个 Expose
事件后,您知道 window 已映射并可以绘制到。您还应该在映射 window 之前调用 XClearWindow()
以确保它不包含任何垃圾。有时您可能还想检查 if (event.xexpose.count == 0)
以仅处理队列中的最新事件,但在您的示例中没有必要这样做。然后只需绘制到 window 并可能在每次绘制后用 XFlush()
或 XSync()
刷新缓冲区。这应该是你想要的(我稍微修改了坐标,但原理是一样的):
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/extensions/XTest.h>
#include <chrono>
#include <iostream>
#include <thread>
using namespace std;
int main()
{
Display* disp;
int screen;
Window win;
GC gc;
disp = XOpenDisplay(NULL);
screen = DefaultScreen(disp);
XColor color;
Colormap colormap;
char black[] = "#ffffff";
colormap = DefaultColormap(disp, 0);
XParseColor(disp, colormap, black, &color);
XAllocColor(disp, colormap, &color);
win = XCreateSimpleWindow(disp,
RootWindow(disp, screen),
10,
10,
1500,
1500,
0,
WhitePixel(disp, screen),
color.pixel);
XSizeHints my_hints = {0};
my_hints.flags = PPosition | PSize;
my_hints.x = 10;
my_hints.y = 10;
my_hints.width = 1500;
my_hints.height = 1500;
XSetNormalHints(disp, win, &my_hints);
gc = XCreateGC(disp, win, 0, 0);
XColor color1;
Colormap colormap1;
char red[] = "#000000";
colormap1 = DefaultColormap(disp, 0);
XParseColor(disp, colormap1, red, &color1);
XAllocColor(disp, colormap1, &color1);
XSetForeground(disp, gc, color1.pixel);
XSelectInput(disp, win, ExposureMask);
int x = 10;
int y = 10;
int i = 0;
XClearWindow(disp, win); // Clear window from possible garbage
XMapWindow(disp, win);
XEvent event;
while (true)
{
// Wait for window to be mapped
XNextEvent(disp, &event);
if (event.xany.window == win && event.type == Expose)
{
break;
}
}
for (int k = 0; k < 20; ++k)
{
std::cout << i << '\n';
XDrawRectangle(disp, win, gc, x, y, 500, 500);
XFlush(disp);
++i;
x += 10;
y += 10;
std::this_thread::sleep_for(std::chrono::milliseconds(500));
}
XFreeGC(disp, gc);
XDestroyWindow(disp, win);
XCloseDisplay(disp);
return 0;
}
假设我想一个接一个地画矩形。我如何知道 X 服务器何时完成绘制一个矩形?有没有办法从 X 服务器获得任何确认? 在下面的代码中,我在 500,500 处绘制了第一个矩形,并在公开处理程序中重新绘制了相同的矩形。之后,我在 1000,1000 处绘制了一个新矩形。问题是第一个矩形从未被绘制。我必须通过 Expose 事件处理程序多少次? 多少次才够?
#include <X11/Xlib.h>
#include <X11/extensions/XTest.h>
#include <X11/Xutil.h>
#include <iostream>
using namespace std;
int main(){
Display *disp;
int screen;
Window win;
GC gc;
disp = XOpenDisplay(NULL);
screen = DefaultScreen(disp);
XColor color;
Colormap colormap;
char black[] = "#ffffff";
colormap = DefaultColormap(disp, 0);
XParseColor(disp, colormap, black, &color);
XAllocColor(disp, colormap, &color);
win = XCreateSimpleWindow(disp, RootWindow(disp, screen), 10,
10, 1500, 1500, 0, WhitePixel(disp, screen), color.pixel);
XSizeHints my_hints = {0};
my_hints.flags = PPosition | PSize;
my_hints.x = 10;
my_hints.y = 10;
my_hints.width = 1500;
my_hints.height = 1500;
XSetNormalHints(disp, win, &my_hints);
XMapWindow(disp, win);
gc = XCreateGC(disp, win, 0, 0);
XColor color1;
Colormap colormap1;
char red[] = "#000000";
colormap1 = DefaultColormap(disp, 0);
XParseColor(disp, colormap1, red, &color1);
XAllocColor(disp, colormap1, &color1);
XSetForeground(disp, gc, color1.pixel);
XSelectInput(disp, win, ExposureMask);
int x1 = 500;
int x2 = 500;
XEvent event;
int i = 0;
while(true){
XDrawRectangle(disp, win, gc, x1, x1, 500, 500);
XNextEvent(disp, &event);
if(event.xany.window == win){
if(event.type == Expose){
cout << i << endl;
XDrawRectangle(disp, win, gc, x1, x2, 500, 500);
}
}
i++;
x1 += 500;
x2 += 500;
}
XFreeGC(disp, gc);
XDestroyWindow(disp, win);
XCloseDisplay(disp);
return 0;
}
输出
0
1
2
3
您似乎希望 XDrawRectangle()
生成 Expose
事件,但它永远不会发生,因为它不是这样工作的。 Expose
事件在 window 被映射、调整大小、移动或模糊 window 未映射时生成,但绘制到 window 时不会生成。实际上,您唯一感兴趣的 Expose
事件是由 XMapWindow()
生成的事件。收到第一个 Expose
事件后,您知道 window 已映射并可以绘制到。您还应该在映射 window 之前调用 XClearWindow()
以确保它不包含任何垃圾。有时您可能还想检查 if (event.xexpose.count == 0)
以仅处理队列中的最新事件,但在您的示例中没有必要这样做。然后只需绘制到 window 并可能在每次绘制后用 XFlush()
或 XSync()
刷新缓冲区。这应该是你想要的(我稍微修改了坐标,但原理是一样的):
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/extensions/XTest.h>
#include <chrono>
#include <iostream>
#include <thread>
using namespace std;
int main()
{
Display* disp;
int screen;
Window win;
GC gc;
disp = XOpenDisplay(NULL);
screen = DefaultScreen(disp);
XColor color;
Colormap colormap;
char black[] = "#ffffff";
colormap = DefaultColormap(disp, 0);
XParseColor(disp, colormap, black, &color);
XAllocColor(disp, colormap, &color);
win = XCreateSimpleWindow(disp,
RootWindow(disp, screen),
10,
10,
1500,
1500,
0,
WhitePixel(disp, screen),
color.pixel);
XSizeHints my_hints = {0};
my_hints.flags = PPosition | PSize;
my_hints.x = 10;
my_hints.y = 10;
my_hints.width = 1500;
my_hints.height = 1500;
XSetNormalHints(disp, win, &my_hints);
gc = XCreateGC(disp, win, 0, 0);
XColor color1;
Colormap colormap1;
char red[] = "#000000";
colormap1 = DefaultColormap(disp, 0);
XParseColor(disp, colormap1, red, &color1);
XAllocColor(disp, colormap1, &color1);
XSetForeground(disp, gc, color1.pixel);
XSelectInput(disp, win, ExposureMask);
int x = 10;
int y = 10;
int i = 0;
XClearWindow(disp, win); // Clear window from possible garbage
XMapWindow(disp, win);
XEvent event;
while (true)
{
// Wait for window to be mapped
XNextEvent(disp, &event);
if (event.xany.window == win && event.type == Expose)
{
break;
}
}
for (int k = 0; k < 20; ++k)
{
std::cout << i << '\n';
XDrawRectangle(disp, win, gc, x, y, 500, 500);
XFlush(disp);
++i;
x += 10;
y += 10;
std::this_thread::sleep_for(std::chrono::milliseconds(500));
}
XFreeGC(disp, gc);
XDestroyWindow(disp, win);
XCloseDisplay(disp);
return 0;
}