当前位置: 首页 > 编程语言 > C++ > 正文

使用XCB编写X Window程序(二) 在窗口中绘图

时间:2015-05-13

在上一篇中,我展示了怎么连接X服务器以及怎么创建一个窗口。创建窗口是编写GUI程序的根本。在GUI编程中还有另外两个重点,其一是事件处理,其二是在窗口中绘图。这一篇中,将展示如何使用XCB在窗口中进行绘图。

先看一个示例代码及其运行效果,代码如下:

#include <stdlib.h>
    #include <stdio.h>
    
    #include <xcb/xcb.h>
    
    int
    main ()
    {
        /* geometric objects */
        xcb_point_t          points[] = {
            {40, 40},
            {40, 80},
            {80, 40},
            {80, 80}};
    
        xcb_point_t          polyline[] = {
            {200, 40},
            { 20, 80},     /* rest of points are relative */
            {100,-80},
            {40, 40}};
    
        xcb_segment_t        segments[] = {
            {400, 40, 560, 120},
            {440, 100, 520, 240}};
    
        xcb_rectangle_t      rectangles[] = {
            { 40, 200, 160, 80},
            { 320, 200, 40, 160}};
    
        xcb_arc_t            arcs[] = {
            {40, 400, 240, 160, 0, 90 << 6},
            {360, 400, 220, 160, 0, 270 << 6}};
    
    
        /* Open the connection to the X server */
        xcb_connection_t *connection = xcb_connect (NULL, NULL);
    
        /* Get the first screen */
        xcb_screen_t *screen = xcb_setup_roots_iterator (xcb_get_setup (connection)).data;
    
        /* Create black (foreground) graphic context */
        xcb_drawable_t  window     = screen->root;
        xcb_gcontext_t  gc = xcb_generate_id (connection);
        uint32_t        mask       = XCB_GC_FOREGROUND | XCB_GC_GRAPHICS_EXPOSURES;
        uint32_t        values[2]  = {screen->black_pixel, 0};
    
        xcb_create_gc (connection, gc, window, mask, values);
    
    
        /* Create a window */
        window = xcb_generate_id (connection);
    
        mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
        values[0] = screen->white_pixel;
        values[1] = XCB_EVENT_MASK_EXPOSURE;
    
        xcb_create_window (connection,                    /* connection          */
                           XCB_COPY_FROM_PARENT,          /* depth               */
                           window,                        /* window Id           */
                           screen->root,                  /* parent window       */
                           0, 0,                          /* x, y                */
                           800, 600,                      /* width, height       */
                           10,                            /* border_width        */
                           XCB_WINDOW_CLASS_INPUT_OUTPUT, /* class               */
                           screen->root_visual,           /* visual              */
                           mask, values );                /* masks */
    
    
        /* Map the window on the screen and flush*/
        xcb_map_window (connection, window);
        xcb_flush (connection);
    
    
        /* draw primitives */
        xcb_generic_event_t *event;
        while ((event = xcb_wait_for_event (connection))) {
            switch (event->response_type & ~0x80) {
            case XCB_EXPOSE:
                /* We draw the points */
                xcb_poly_point (connection, XCB_COORD_MODE_ORIGIN, window, gc, 4, points);
    
                /* We draw the polygonal line */
                xcb_poly_line (connection, XCB_COORD_MODE_PREVIOUS, window, gc, 4, polyline);
    
                /* We draw the segments */
                xcb_poly_segment (connection, window, gc, 2, segments);
    
                /* draw the rectangles */
                xcb_poly_rectangle (connection, window, gc, 2, rectangles);
    
                /* draw the arcs */
                xcb_poly_arc (connection, window, gc, 2, arcs);
    
                /* flush the request */
                xcb_flush (connection);
    
                break;
            default: 
                /* Unknown event type, ignore it */
                break;
            }

    
            free (event);
        }
    
        return 0;
    }