/* standard library */
#include <stdlib.h>
#include <stdio.h>
+#include <stdbool.h>
#include <time.h>
#include <assert.h>
#include <string.h>
+#include <unistd.h>
-#define X_H
-#include <X11/XCB/xcb.h>
-#include <X11/XCB/shm.h>
-#include <X11/XCB/xcb_aux.h>
-#include <X11/XCB/xcb_image.h>
-#include <X11/XCB/xcb_icccm.h>
+#include <xcb/xcb.h>
+#include <xcb/shm.h>
+#include <xcb/xcb_aux.h>
+#include <xcb/xcb_image.h>
+#include <xcb/xcb_atom.h>
+
+/* Needed for xcb_set_wm_protocols() */
+#include <xcb/xcb_icccm.h>
+
+#define XCB_ALL_PLANES ~0
+#include <xcb/xcb_icccm.h>
/* some defines for the flame */
#define HSPREAD 26
{
struct
{
- XCBConnection *c;
- XCBDRAWABLE draw;
- XCBDRAWABLE pixmap;
- XCBCOLORMAP cmap;
- CARD8 depth;
- XCBGCONTEXT gc;
+ xcb_connection_t *c;
+ xcb_drawable_t draw;
+ xcb_drawable_t pixmap;
+ xcb_colormap_t cmap;
+ uint8_t depth;
+ xcb_gcontext_t gc;
}xcb;
/* the palette */
}flame;
+static xcb_atom_t get_atom (xcb_connection_t *connection, const char *atomName);
static void title_set (flame *f, const char *title);
static int ilog2 (unsigned int n);
static void flame_set_palette (flame *f);
flame_init ()
{
flame *f;
- XCBSCREEN *screen;
- XCBGCONTEXT gc = { 0 };
+ xcb_screen_t *screen;
+ xcb_gcontext_t gc = { 0 };
int screen_nbr;
- CARD32 mask;
- CARD32 values[2];
+ uint32_t mask;
+ uint32_t values[2];
int size;
int flame_width;
int flame_height;
- XCBRECTANGLE rect_coord = { 0, 0, BG_W, BG_H};
+ xcb_rectangle_t rect_coord = { 0, 0, BG_W, BG_H};
f = (flame *)malloc (sizeof (flame));
if (!f)
return NULL;
- f->xcb.c = XCBConnect (NULL, &screen_nbr);
+ f->xcb.c = xcb_connect (NULL, &screen_nbr);
if (!f->xcb.c)
{
free (f);
return NULL;
}
- screen = XCBAuxGetScreen (f->xcb.c, screen_nbr);
+ screen = xcb_aux_get_screen (f->xcb.c, screen_nbr);
- f->xcb.draw.window = screen->root;
- f->xcb.gc = XCBGCONTEXTNew (f->xcb.c);
- mask = XCBGCForeground | XCBGCGraphicsExposures;
+ f->xcb.draw = screen->root;
+ f->xcb.gc = xcb_generate_id (f->xcb.c);
+ mask = XCB_GC_FOREGROUND | XCB_GC_GRAPHICS_EXPOSURES;
values[0] = screen->black_pixel;
values[1] = 0; /* no graphics exposures */
- XCBCreateGC (f->xcb.c, f->xcb.gc, f->xcb.draw, mask, values);
+ xcb_create_gc (f->xcb.c, f->xcb.gc, f->xcb.draw, mask, values);
- gc = XCBGCONTEXTNew (f->xcb.c);
- mask = XCBGCForeground | XCBGCGraphicsExposures;
+ gc = xcb_generate_id (f->xcb.c);
+ mask = XCB_GC_FOREGROUND | XCB_GC_GRAPHICS_EXPOSURES;
values[0] = screen->white_pixel;
values[1] = 0; /* no graphics exposures */
- XCBCreateGC (f->xcb.c, gc, f->xcb.draw, mask, values);
+ xcb_create_gc (f->xcb.c, gc, f->xcb.draw, mask, values);
- f->xcb.depth = XCBAuxGetDepth (f->xcb.c, screen);
- mask = XCBCWBackPixel | XCBCWEventMask;
+ f->xcb.depth = xcb_aux_get_depth (f->xcb.c, screen);
+ mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
values[0] = screen->white_pixel;
- values[1] = XCBEventMaskExposure | XCBEventMaskButtonPress;
- f->xcb.draw.window = XCBWINDOWNew (f->xcb.c);
- XCBCreateWindow (f->xcb.c, f->xcb.depth,
- f->xcb.draw.window,
+ values[1] = XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_BUTTON_PRESS;
+ f->xcb.draw = xcb_generate_id (f->xcb.c);
+ xcb_create_window (f->xcb.c, f->xcb.depth,
+ f->xcb.draw,
screen->root,
0, 0, BG_W, BG_H,
0,
- XCBWindowClassInputOutput,
+ XCB_WINDOW_CLASS_INPUT_OUTPUT,
screen->root_visual,
mask, values);
title_set (f, "XCB Flames");
- f->xcb.pixmap.pixmap = XCBPIXMAPNew (f->xcb.c);
- XCBCreatePixmap (f->xcb.c, f->xcb.depth,
- f->xcb.pixmap.pixmap, f->xcb.draw,
+ f->xcb.pixmap = xcb_generate_id (f->xcb.c);
+ xcb_create_pixmap (f->xcb.c, f->xcb.depth,
+ f->xcb.pixmap, f->xcb.draw,
BG_W, BG_H);
- XCBPolyFillRectangle(f->xcb.c, f->xcb.pixmap, gc, 1, &rect_coord);
+ xcb_poly_fill_rectangle(f->xcb.c, f->xcb.pixmap, gc, 1, &rect_coord);
- XCBMapWindow (f->xcb.c, f->xcb.draw.window);
- XCBFlush (f->xcb.c);
+ xcb_map_window (f->xcb.c, f->xcb.draw);
+ xcb_flush (f->xcb.c);
- f->xcb.cmap = XCBCOLORMAPNew (f->xcb.c);
- XCBCreateColormap (f->xcb.c,
- XCBColormapAllocNone,
+ f->xcb.cmap = xcb_generate_id (f->xcb.c);
+ xcb_create_colormap (f->xcb.c,
+ XCB_COLORMAP_ALLOC_NONE,
f->xcb.cmap,
- f->xcb.draw.window,
+ f->xcb.draw,
screen->root_visual);
/* Allocation of the flame arrays */
f->flame = (unsigned int *)malloc (size);
if (! f->flame)
{
- XCBDisconnect (f->xcb.c);
+ xcb_disconnect (f->xcb.c);
free (f);
return NULL;
}
if (! f->flame2)
{
free (f->flame);
- XCBDisconnect (f->xcb.c);
+ xcb_disconnect (f->xcb.c);
free (f);
return NULL;
}
free (f->flame2);
free (f->flame);
- XCBDisconnect (f->xcb.c);
+ xcb_disconnect (f->xcb.c);
free (f);
}
main ()
{
flame *f;
- XCBGenericEvent *e;
- XCBGCONTEXT gc = { 0 };
+ xcb_generic_event_t *e;
+ xcb_gcontext_t gc = { 0 };
f = flame_init ();
if (!f)
flame_set_flame_zero (f);
flame_set_random_flame_base (f);
- while (1)
+ xcb_atom_t deleteWindowAtom = xcb_atom_get(f->xcb.c, "WM_DELETE_WINDOW");
+ xcb_atom_t wmprotocolsAtom = xcb_atom_get(f->xcb.c, "WM_PROTOCOLS");
+ /* Listen to X client messages in order to be able to pickup
+ the "delete window" message that is generated for example
+ when someone clicks the top-right X button within the window
+ manager decoration (or when user hits ALT-F4). */
+ xcb_set_wm_protocols (f->xcb.c, wmprotocolsAtom, f->xcb.draw, 1, &deleteWindowAtom);
+
+ bool finished = false;
+ while (!finished)
{
- if ((e = XCBPollForEvent (f->xcb.c, NULL)))
+ if ((e = xcb_poll_for_event (f->xcb.c)))
{
- switch (e->response_type)
+ switch (XCB_EVENT_RESPONSE_TYPE(e))
{
- case XCBExpose:
- XCBCopyArea(f->xcb.c, f->xcb.pixmap, f->xcb.draw, gc,
+ case XCB_EXPOSE:
+ xcb_copy_area(f->xcb.c, f->xcb.pixmap, f->xcb.draw, gc,
0, 0, 0, 0, BG_W, BG_H);
- XCBFlush (f->xcb.c);
+ xcb_flush (f->xcb.c);
+ break;
+ case XCB_CLIENT_MESSAGE:
+ if (((xcb_client_message_event_t *)e)->data.data32[0] == deleteWindowAtom)
+ {
+ finished = true;
+ }
+ break;
+ case XCB_BUTTON_PRESS:
+ finished = true;
break;
- case XCBButtonPress:
- printf ("Exiting...\n");
- free (e);
- goto sortie;
}
free (e);
}
flame_draw_flame (f);
- XCBSync (f->xcb.c, 0);
+ xcb_flush (f->xcb.c);
}
- sortie:
flame_shutdown (f);
return 0;
static void title_set (flame *f, const char *title)
{
- XCBInternAtomRep *rep;
- XCBATOM encoding;
+ xcb_intern_atom_reply_t *rep;
+ xcb_atom_t encoding;
char *atom_name;
/* encoding */
atom_name = "UTF8_STRING";
- rep = XCBInternAtomReply (f->xcb.c,
- XCBInternAtom (f->xcb.c,
+ rep = xcb_intern_atom_reply (f->xcb.c,
+ xcb_intern_atom (f->xcb.c,
0,
strlen (atom_name),
atom_name),
/* NETWM */
atom_name = "_NET_WM_NAME";
- rep = XCBInternAtomReply (f->xcb.c,
- XCBInternAtom (f->xcb.c,
+ rep = xcb_intern_atom_reply (f->xcb.c,
+ xcb_intern_atom (f->xcb.c,
0,
strlen (atom_name),
atom_name),
NULL);
- XCBChangeProperty(f->xcb.c, XCBPropModeReplace,
- f->xcb.draw.window,
+ xcb_change_property(f->xcb.c, XCB_PROP_MODE_REPLACE,
+ f->xcb.draw,
rep->atom, encoding, 8, strlen (title), title);
free (rep);
}
static void
flame_draw_flame (flame *f)
{
- XCBImage *image;
+ xcb_image_t *image;
unsigned int *ptr;
int x;
int y;
int cl3;
int cl4;
+ image = xcb_image_get (f->xcb.c, f->xcb.draw,
+ 0, 0, BG_W, BG_H,
+ XCB_ALL_PLANES, XCB_IMAGE_FORMAT_Z_PIXMAP);
+ /* If the top-level window is minimized (iconic) then the xcb_image_get()
+ will return NULL. In this case, we'll skip both updating and drawing
+ the flame, and we will also do a small sleep so that the program doesn't
+ hog as much CPU while minimized.
+
+ Another (non-polling == cleaner) way to not hog the CPU while minimized
+ would be to pass the XCB_EVENT_MASK_STRUCTURE_NOTIFY flag to
+ xcb_create_window(). This will give you XCB_UNMAP_NOTIFY and
+ XCB_MAP_NOTIFY events whenever the window is "minimized" (made iconic)
+ and "unminimized" (made normal again). This information would then be
+ used to make the main loop use the xcb_wait_for_event() instead of
+ xcb_poll_for_event() while the window is minimized (iconic). */
+ if (image == NULL)
+ {
+ usleep (100000);
+ return;
+ }
+ f->im = (unsigned int *)image->data;
+
/* modify the base of the flame */
flame_modify_flame_base (f);
/* process the flame array, propagating the flames up the array */
flame_process_flame (f);
- image = XCBImageGet (f->xcb.c, f->xcb.draw,
- 0, 0, BG_W, BG_H,
- XCBAllPlanes, XCBImageFormatZPixmap);
- f->im = (unsigned int *)image->data;
-
for (y = 0 ; y < ((BG_H >> 1) - 1) ; y++)
{
for (x = 0 ; x < ((BG_W >> 1) - 1) ; x++)
cl4 = (int)*ptr;
- XCBImagePutPixel (image,
+ xcb_image_put_pixel (image,
xx, yy,
f->pal[cl]);
- XCBImagePutPixel (image,
+ xcb_image_put_pixel (image,
xx + 1, yy,
f->pal[((cl1+cl2) >> 1)]);
- XCBImagePutPixel (image,
+ xcb_image_put_pixel (image,
xx, yy + 1,
f->pal[((cl1 + cl3) >> 1)]);
- XCBImagePutPixel (image,
+ xcb_image_put_pixel (image,
xx + 1, yy + 1,
f->pal[((cl1 + cl4) >> 1)]);
}
}
- XCBImagePut (f->xcb.c, f->xcb.draw, f->xcb.gc, image,
- 0, 0, 0, 0, BG_W, BG_H);
- XCBImageDestroy (image);
+ xcb_image_put (f->xcb.c, f->xcb.draw, f->xcb.gc, image,
+ 0, 0, 0);
+ xcb_image_destroy (image);
}
/* set the flame palette */
static void
flame_set_palette (flame *f)
{
- XCBAllocColorCookie cookies[IMAX];
- XCBAllocColorRep *rep;
+ xcb_alloc_color_cookie_t cookies[IMAX];
+ xcb_alloc_color_reply_t *rep;
int i;
int r;
int g;
if (b < 0) b = 0;
if (b > 255) b = 255;
- cookies[i] = XCBAllocColor (f->xcb.c, f->xcb.cmap,
+ cookies[i] = xcb_alloc_color (f->xcb.c, f->xcb.cmap,
r << 8, g << 8, b << 8);
}
for (i = 0 ; i < IMAX ; i++)
{
- rep = XCBAllocColorReply (f->xcb.c, cookies[i], NULL);
+ rep = xcb_alloc_color_reply (f->xcb.c, cookies[i], NULL);
f->pal[i] = rep->pixel;
free (rep);
}