Replace deprecated Automake INCLUDES variable with AM_CPPFLAGS
[free-sw/xcb/demo] / tests / flames.c
index 89fd331..89e93cf 100644 (file)
 /* 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
@@ -49,12 +56,12 @@ typedef struct
 {
   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 */
@@ -69,6 +76,7 @@ typedef struct
   
 }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);
@@ -82,70 +90,70 @@ flame *
 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);
-  XCBSync (f->xcb.c, 0);
+  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 */
@@ -156,7 +164,7 @@ flame_init ()
   f->flame = (unsigned int *)malloc (size);
   if (! f->flame)
     {
-      XCBDisconnect (f->xcb.c);
+      xcb_disconnect (f->xcb.c);
       free (f);
       return NULL;
     }
@@ -164,7 +172,7 @@ flame_init ()
   if (! f->flame2)
     {
       free (f->flame);
-      XCBDisconnect (f->xcb.c);
+      xcb_disconnect (f->xcb.c);
       free (f);
       return NULL;
     }
@@ -186,7 +194,7 @@ flame_shutdown (flame *f)
 
   free (f->flame2);
   free (f->flame);
-  XCBDisconnect (f->xcb.c);
+  xcb_disconnect (f->xcb.c);
   free (f);
 }
 
@@ -194,8 +202,8 @@ int
 main ()
 {
   flame *f;
-  XCBGenericEvent *e;
-  XCBGCONTEXT gc = { 0 };
+  xcb_generic_event_t *e;
+  xcb_gcontext_t gc = { 0 };
 
   f = flame_init ();
   if (!f)
@@ -207,29 +215,42 @@ main ()
   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);
-             XCBSync (f->xcb.c, 0);
+             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;
@@ -237,14 +258,14 @@ main ()
 
 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),
@@ -257,14 +278,14 @@ static void title_set (flame *f, const char *title)
 
   /* 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);
 }
@@ -272,7 +293,7 @@ static void title_set (flame *f, const char *title)
 static void
 flame_draw_flame (flame *f)
 {
-  XCBImage     *image;
+  xcb_image_t     *image;
   unsigned int *ptr;
   int           x;
   int           y;
@@ -284,16 +305,33 @@ flame_draw_flame (flame *f)
   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++)
@@ -311,31 +349,31 @@ flame_draw_flame (flame *f)
          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;
@@ -354,13 +392,13 @@ flame_set_palette (flame *f)
       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);
     }