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;
}