Reputation: 183
I'm doing some programming with cairo and xlib in C++, my code is listed below.
I had some flickering issues but by modifying my code, it seems works good now generally.
But when the window is resized at a small size (about 600x450 on my laptop), it is still flickering.
How can I fix it?
#include <cairo.h>
#include <cairo-xlib.h>
#include <string>
#include <cstdio>
using namespace std;
int main (int argc, char *argv[])
{
cairo_surface_t *surface;
cairo_t *cr;
surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 800, 600);
cr = cairo_create (surface);
/* Examples are in 1.0 x
* 1.0 coordinate space */
cairo_scale (cr, 800, 600);
cairo_set_source_rgb (cr, 1.0, 0, 0);
cairo_rectangle (cr, 0, 0, 1.0, 1.0);
cairo_fill(cr);
cairo_destroy(cr);
Display *display = XOpenDisplay(NULL);
int default_scr = DefaultScreen(display);
Visual *visual = DefaultVisual(display, default_scr);
Window root_win = RootWindow(display, default_scr);
Drawable drawable = XCreateSimpleWindow(display, root_win, 0, 0, 800, 600, 0,
BlackPixel(display, default_scr), WhitePixel(display, default_scr));
cairo_surface_t *x11_sf = cairo_xlib_surface_create(display, drawable, visual, 800, 600);
XSelectInput(display, drawable, ExposureMask | StructureNotifyMask);
XMapWindow(display, drawable);
XFlush(display);
XSync(display, default_scr);
Atom wmDeleteMessage = XInternAtom(display, "WM_DELETE_WINDOW", False);
XSetWMProtocols(display, drawable, &wmDeleteMessage, 1);
int height;
int width;
XEvent event;
bool running = true;
while (running)
{
XNextEvent(display, &event);
switch (event.type)
{
case Expose:
{
cairo_t *x11_cr = cairo_create(x11_sf);
cairo_scale(x11_cr, double(width) / 800, double(height) / 600);
cairo_set_source_surface(x11_cr, surface, 0, 0);
cairo_paint(x11_cr);
cairo_destroy (x11_cr);
}
break;
case ClientMessage:
if (event.xclient.data.l[0] == wmDeleteMessage)
{
running = false;
}
break;
case ConfigureNotify:
width = event.xconfigure.width;
height = event.xconfigure.height;
cairo_xlib_surface_set_size(x11_sf, width, height);
break;
}
}
cairo_surface_destroy (surface);
return 0;
}
I use cairo_xlib_surface
to draw a window, which has a whole red background color. I tried to catch XExpose
event and redraw it. But sometimes the redraw result gets strange.
#include <cairo.h>
#include <cairo-xlib.h>
#include <string>
#include <cstdio>
using namespace std;
int main (int argc, char *argv[])
{
cairo_surface_t *surface;
cairo_t *cr;
surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 800, 600);
cr = cairo_create (surface);
/* Examples are in 1.0 x 1.0 coordinate space */
cairo_scale (cr, 800, 600);
/* Drawing code goes here */
cairo_set_source_rgb (cr, 1.0, 0, 0);
cairo_rectangle (cr, 0, 0, 1.0, 1.0);
cairo_fill(cr);
Display *display = XOpenDisplay(NULL);
int default_scr = DefaultScreen(display);
Visual *visual = DefaultVisual(display, default_scr);
Window root_win = RootWindow(display, default_scr);
Drawable drawable = XCreateSimpleWindow(display, root_win, 0, 0, 800, 600, 0,
BlackPixel(display, default_scr), WhitePixel(display, default_scr));
XSelectInput(display, drawable, ExposureMask);
XMapWindow(display, drawable);
XFlush(display);
XSync(display, default_scr);
int height;
int width;
XEvent event;
while (1)
{
XNextEvent(display, &event);
switch (event.type)
{
case Expose:
{
width = event.xexpose.width;
height = event.xexpose.height;
cairo_surface_t *x11_sf = cairo_xlib_surface_create(display, drawable, visual, width, height);
cairo_t *x11_cr = cairo_create(x11_sf);
cairo_scale(x11_cr, double(width) / 800, double(height) / 600);
cairo_set_source_surface(x11_cr, surface, 0, 0);
cairo_paint(x11_cr);
cairo_destroy (x11_cr);
cairo_surface_destroy (x11_sf);
}
break;
}
}
/* Write output and clean up */
cairo_destroy (cr);
cairo_surface_destroy (surface);
return 0;
}
When I resize the window, sometimes I get the result like this:
It seems it hasn't finished to draw the red background.
Could someone tell me why this occurs and how to avoid it?
If someone want to compile it under Linux, could use: g++ \pkg-config --cflags --libs x11 cairo\
src.cpp
Thanks!
Upvotes: 5
Views: 1650
Reputation: 323
The issue is caused by the fact you're filling a red area on a white background to make a red background, that's not the most efficient way of doing it.
You should rather create the window with the background's color defined as red instead of white!
So, to do it, in XCreateSimpleWindow()
's background argument (the last one), you should put 0xFF0000
, it's the hexadecimal value for red in a 24-bit color space, but you may need to change it if you use different color spaces. The line would look like this:
XCreateSimpleWindow(display, root_win, 0, 0, 800, 600, 0,
BlackPixel(display, default_scr), WhitePixel(display, default_scr));
Upvotes: 2