Thread: Impossible to draw in an XCB window using Cairo

  1. #1
    Registered User
    Join Date
    Oct 2015
    Posts
    11

    Impossible to draw in an XCB window using Cairo

    Hi everyone !

    I'm quite familiar with XCB, the X11 architecture and all that, and I recently started learning about Cairo since drawing with the native protocol's primitives got boring real quick (though it is still very satisfying).

    So I wrote a little program that's supposed to display one of the examples that can be found in Cairo's documentation, and problem is, it doesn't do so, which is kinda sad.
    Well, the real problem isn't quite that it doesn't draw, the real problem is I can't get to fix it. I guess I made a mistake somewhere but I can't manage to find it.

    Therefore, here is my code, maybe you will see :

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
    #include <stdint.h>
    #include <xcb/xcb.h>
    #include <cairo/cairo.h>
    #include <cairo/cairo-xcb.h>
    
    
    xcb_connection_t *main_connection = NULL;
    xcb_screen_t *main_screen = NULL;
    uint32_t main_screen_number = 0;
    xcb_setup_t *main_setup = NULL;
    xcb_depth_t *main_depth = NULL;
    xcb_visualtype_t *main_vitype = NULL;
    
    
    uint32_t mask = 0;
    uint32_t values [16];
    xcb_window_t main_window;
    
    
    cairo_surface_t *dsurface = NULL;
    cairo_t *dcontext = NULL;
    
    
    static int initialize (void);
    static int finalize (void);
    static int loop (void);
    static void draw (void);
    
    
    int initialize (void) {
        main_connection = xcb_connect (NULL, &main_screen_number);
        if (main_connection == NULL) return 1;
    
    
        unsigned int i = 0;
        main_setup = (xcb_setup_t *) xcb_get_setup (main_connection);
        xcb_screen_iterator_t screen_it = xcb_setup_roots_iterator (main_setup);
        for (i = 0; i < main_screen_number; ++i, xcb_screen_next (&screen_it));
        main_screen = screen_it.data;
        if (main_screen == NULL) return 2;
    
    
        xcb_depth_iterator_t depth_it = xcb_screen_allowed_depths_iterator (main_screen);
        for (i = 0; depth_it.data != NULL; ++i, xcb_depth_next (&depth_it))
            if (depth_it.data->depth == main_screen->root_depth)
                break;
        main_depth = depth_it.data;
        if (main_depth == NULL) return 3;
    
    
        xcb_visualtype_iterator_t vitype_it = xcb_depth_visuals_iterator (main_depth);
        for (i = 0; vitype_it.data != NULL; ++i, xcb_visualtype_next (&vitype_it))
            if (vitype_it.data->visual_id == main_screen->root_visual)
                break;
        main_vitype = vitype_it.data;
        if (main_vitype == NULL) return 4;
    
    
        if (main_vitype->bits_per_rgb_value != 8) return 5;
        if (main_vitype->_class != XCB_VISUAL_CLASS_TRUE_COLOR) return 6;
    
    
        mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
        values [0] = 0xffffff;
        values [1] = XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_POINTER_MOTION
            | XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_BUTTON_RELEASE
            | XCB_EVENT_MASK_ENTER_WINDOW | XCB_EVENT_MASK_LEAVE_WINDOW
            | XCB_EVENT_MASK_KEY_PRESS | XCB_EVENT_MASK_KEY_RELEASE;
        main_window = xcb_generate_id (main_connection);
        xcb_create_window (main_connection,
            XCB_COPY_FROM_PARENT,
            main_window,
            main_screen->root,
            0, 0, 120, 120, 2,
            XCB_WINDOW_CLASS_INPUT_OUTPUT,
            main_screen->root_visual,
            mask, values);
        xcb_map_window (main_connection, main_window);
    
    
        xcb_flush (main_connection);
    
    
        dsurface = cairo_xcb_surface_create (main_connection,
            main_window,
            main_vitype,
            120, 120);
        if (dsurface == NULL) return 7;
    
    
        dcontext = cairo_create (dsurface);
        if (dcontext == NULL) return 8;
    
    
        xcb_flush (main_connection);
    
    
        return 0;
    }
    
    
    int finalize (void) {
        cairo_surface_destroy (dsurface);
        cairo_destroy (dcontext);
        xcb_disconnect (main_connection);
        return 0;
    }
    
    
    int loop (void) {
        draw ();
    
    
        xcb_generic_event_t *event = NULL;
        int leave = 0;
        while ((event = xcb_wait_for_event (main_connection))) {
            switch (event->response_type & ~0x80) {
                case XCB_KEY_PRESS:
                    leave = 1;
                    break;
                case XCB_KEY_RELEASE:
                    leave++;
                    break;
                case XCB_EXPOSE:
                    draw ();
                    break;
                default:
                    printf ("Tant pis.\n");
                    break;
            }
    
    
            free (event);
            if (leave == 2)
                break;
        }
    
    
        return 0;
    }
    
    
    void draw (void) {
        cairo_set_source_rgb (dcontext, 0, 0, 0);
        cairo_move_to (dcontext, 0, 0);
        cairo_line_to (dcontext, 1, 1);
        cairo_move_to (dcontext, 1, 0);
        cairo_line_to (dcontext, 0, 1);
        cairo_set_line_width (dcontext, 0.2);
        cairo_stroke (dcontext);
    
    
        cairo_rectangle (dcontext, 0, 0, 0.5, 0.5);
        cairo_set_source_rgba (dcontext, 1, 0, 0, 0.8);
        cairo_fill (dcontext);
    
    
        cairo_rectangle (dcontext, 0, 0.5, 0.5, 0.5);
        cairo_set_source_rgba (dcontext, 0, 1, 0, 0.6);
        cairo_fill (dcontext);
    
    
        cairo_rectangle (dcontext, 0.5, 0, 0.5, 0.5);
        cairo_set_source_rgba (dcontext, 0, 0, 1, 0.4);
        cairo_fill (dcontext);
    
    
        cairo_surface_flush (dsurface);
        xcb_flush (main_connection);
    }
    
    
    int main (int argc, char *argv []) {
        int ret = 0;
        ret = initialize ();
        printf ("%d\n", ret);
        if (ret)
            return ret;
    
    
        ret = loop ();
        printf ("%d\n", ret);
    
    
        ret = finalize ();
        printf ("%d\n", ret);
        return ret;
    }

  2. #2
    Banned
    Join Date
    Oct 2014
    Location
    Home
    Posts
    135
    Wow, I really am stupid!

  3. #3
    Registered User
    Join Date
    Oct 2015
    Posts
    11
    Why are you saying that ?

  4. #4
    Banned
    Join Date
    Oct 2014
    Location
    Home
    Posts
    135
    Nevermind. You have header files that I don't have so I didn't know where some of the functions was...

  5. #5
    Registered User
    Join Date
    Oct 2015
    Posts
    11
    Happens to everyone In addition, the location of Cairo's include file seems to be not so well-defined, since I've seen examples in which the files weren't contained in a "cairo" folder, but I guess it depends on the distribution.

  6. #6
    Registered User
    Join Date
    Oct 2015
    Posts
    11
    UPDATE : It appears that drawing commands use user-space coordinates BY DEFAULT, where I thought it was exactly the opposite as in OpenGL ; also, the official Cairo tutorial doesn't use what appears to be user-space coordinates (0.5 and 1, quite small a drawing if the unit is the pixel) even though there is no word on a space transformation anywhere. Actually, it might be because the tutorial is quite old, maybe has there been changes in Cairo's design since then. The official manual actually only mentions user-space coordinates.

    BUT STILL. Though the program does draw for example on images (with little modifications), it still doesn't do so on the XCB window. Which is probably even weirder.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Move an object in cairo
    By tvaz in forum C Programming
    Replies: 1
    Last Post: 01-14-2016, 04:36 PM
  2. CAIRO - error when converting txt to pdf
    By leonardoadoado in forum C++ Programming
    Replies: 17
    Last Post: 12-05-2012, 01:38 PM
  3. cairo-dock issue
    By Annonymous in forum Linux Programming
    Replies: 2
    Last Post: 06-03-2012, 12:14 AM
  4. Cairo and GTK, still need a pixmap?
    By TriKri in forum Linux Programming
    Replies: 0
    Last Post: 03-18-2008, 04:18 PM
  5. Draw an hyperlink on the window
    By Niara in forum Windows Programming
    Replies: 4
    Last Post: 06-25-2007, 01:08 PM

Tags for this Thread