libX11: XPutImage first call

2.1k views Asked by At

I've created XImage using XCreateImage and use XPutImage to display it on window, but XPutImage shows this picture only on second call of it. Why this happens?

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>

void draw(char *rgb_out, int w, int h)
{
        int i = 0;

        for (i = 0;i < w*h;i += 4) {
                rgb_out[i + 1] = 0;
                rgb_out[i + 2] = 0;
                rgb_out[i + 3] = 0;
        }

        return;
}

XImage *create_ximage(Display *display, Visual *visual, int width, int height)
{
        char *image32 = (char *)malloc(width * height * 4);
        draw(image32, width, height);
        return XCreateImage(display, visual, 24,
                            ZPixmap, 0, image32,
                            width, height, 32, 0);
}

int main(int argc, char **argv)
{
        int win_b_color;
        int win_w_color;
        XEvent xev;
        Window window;
        GC gc;
        Display *display = XOpenDisplay(NULL);
        Visual *visual;
        XImage *ximage;

        win_b_color = BlackPixel(display, DefaultScreen(display));
        win_w_color = BlackPixel(display, DefaultScreen(display));
        window = XCreateSimpleWindow(display,
                                DefaultRootWindow(display),
                                0, 0, 600, 400, 0,
                                win_b_color, win_w_color);

        gc = XCreateGC(display, window, 0, NULL);
        visual = DefaultVisual(display, 0);

        XMapWindow(display, window);
        XFlush(display);
        ximage = create_ximage(display, visual, 100, 100);
        while (1) {
                int r;

                r = XPutImage(display, window,
                        gc, ximage, 0, 0, 0, 0,
                        100, 100);
                printf("RES: %i\n", r);
                XSync(display, 1);
                XFlush(display);
                getchar();
        }

        return 0;
}
1

There are 1 answers

0
LPs On BEST ANSWER

The trick is to wait that the windows is mapped. You can do this by Expose event.

int main(int argc, char **argv)
{
        int win_b_color;
        int win_w_color;
        XEvent xev;
        Window window;
        GC gc;
        Display *display = XOpenDisplay(NULL);
        Visual *visual;
        XImage *ximage;

        win_b_color = BlackPixel(display, DefaultScreen(display));
        win_w_color = BlackPixel(display, DefaultScreen(display));
        window = XCreateSimpleWindow(display,
                                DefaultRootWindow(display),
                                0, 0, 600, 400, 0,
                                win_b_color, win_w_color);

        visual = DefaultVisual(display, 0);

        XSelectInput(display, window, ExposureMask | KeyPressMask);

        XMapWindow(display, window);
        XFlush(display);
        gc = XCreateGC(display, window, 0, NULL);
        ximage = create_ximage(display, visual, 100, 100);
        XEvent event;
        bool exit = false;

        while (!exit) {
                int r;

                XNextEvent(display, &event);

                if (event.type == Expose)
                {
                    r = XPutImage(display, window,
                            gc, ximage, 0, 0, 0, 0,
                            100, 100);
                    printf("RES: %i\n", r);
                }
                else if (event.type == KeyPress)
                    exit = true;
        }

        return 0;
}