Replace deprecated Automake INCLUDES variable with AM_CPPFLAGS
[free-sw/xcb/demo] / tests / julia.c
index 27d6823..75468ce 100644 (file)
@@ -1,10 +1,18 @@
 #include <stdlib.h>
 #include <stdio.h>
+#include <stdbool.h>
+#include <string.h>
+#include <assert.h>
 
 #include <xcb/xcb.h>
 #include <xcb/shm.h>
 #include <xcb/xcb_aux.h>
 #include <xcb/xcb_image.h>
+#include <xcb/xcb_atom.h>
+#define XCB_ALL_PLANES ~0
+
+/* Needed for xcb_set_wm_protocols() */
+#include <xcb/xcb_icccm.h>
 
 #include "julia.h"
 
@@ -87,6 +95,8 @@ draw_julia (Data *datap)
                       0, 0, W_W, W_H,
                       XCB_ALL_PLANES, datap->format);
   
+  assert(datap->image);
+
   for (i = 0 ; i < datap->image->width ; i++)
     for (j = 0 ; j < datap->image->height ; j++)
       {
@@ -107,7 +117,7 @@ draw_julia (Data *datap)
       }
 
   xcb_image_put (datap->conn, datap->draw, datap->gc, datap->image,
-              0, 0, 0, 0, W_W, W_H);
+              0, 0, 0);
 }
 
 int
@@ -122,90 +132,109 @@ main (int argc, char *argv[])
   uint32_t           valgc[2];
   uint32_t           valwin[3];
   xcb_rectangle_t     rect_coord = { 0, 0, W_W, W_H};
-  xcb_generic_event_t *e;
   int              screen_num;
   
   data.conn = xcb_connect (0, &screen_num);
   screen = xcb_aux_get_screen (data.conn, screen_num);
   data.depth = xcb_aux_get_depth (data.conn, screen);
 
-  win.window = screen->root;
+  win = screen->root;
 
-  data.gc = xcb_gcontext_new (data.conn);
+  data.gc = xcb_generate_id (data.conn);
   mask = XCB_GC_FOREGROUND | XCB_GC_GRAPHICS_EXPOSURES;
   valgc[0] = screen->black_pixel;
   valgc[1] = 0; /* no graphics exposures */
   xcb_create_gc (data.conn, data.gc, win, mask, valgc);
 
-  bgcolor = xcb_gcontext_new (data.conn);
+  bgcolor = xcb_generate_id (data.conn);
   mask = XCB_GC_FOREGROUND | XCB_GC_GRAPHICS_EXPOSURES;
   valgc[0] = screen->white_pixel;
   valgc[1] = 0; /* no graphics exposures */
   xcb_create_gc (data.conn, bgcolor, win, mask, valgc);
 
-  data.draw.window = xcb_window_new (data.conn);
+  data.draw = xcb_generate_id (data.conn);
   mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK | XCB_CW_DONT_PROPAGATE;
   valwin[0] = screen->white_pixel;
-  valwin[1] = XCB_EVENT_MASK_KEY_RELEASE | XCB_EVENT_MASK_BUTTON_RELEASE | XCB_EVENT_MASK_EXPOSURE;
+  valwin[1] = XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_EXPOSURE;
   valwin[2] = XCB_EVENT_MASK_BUTTON_PRESS;
   xcb_create_window (data.conn, 0,
-                  data.draw.window,
+                  data.draw,
                   screen->root,
                   0, 0, W_W, W_H,
                   10,
                   XCB_WINDOW_CLASS_INPUT_OUTPUT,
                   screen->root_visual,
                   mask, valwin);
-  xcb_map_window (data.conn, data.draw.window);
+  xcb_map_window (data.conn, data.draw);
 
-  rect.pixmap = xcb_pixmap_new (data.conn);
+  rect = xcb_generate_id (data.conn);
   xcb_create_pixmap (data.conn, data.depth,
-                  rect.pixmap, data.draw,
+                  rect, data.draw,
                   W_W, W_H);
   xcb_poly_fill_rectangle(data.conn, rect, bgcolor, 1, &rect_coord);
 
-  xcb_map_window (data.conn, data.draw.window);
+  xcb_map_window (data.conn, data.draw);
 
   data.format = XCB_IMAGE_FORMAT_Z_PIXMAP;
 
-  data.cmap = xcb_colormap_new (data.conn);
+  data.cmap = xcb_generate_id (data.conn);
   xcb_create_colormap (data.conn,
                     XCB_COLORMAP_ALLOC_NONE,
                     data.cmap,
-                    data.draw.window,
+                    data.draw,
                     screen->root_visual);
 
   palette_julia (&data);
 
+  xcb_atom_t deleteWindowAtom = xcb_atom_get(data.conn, "WM_DELETE_WINDOW");
+  xcb_atom_t wmprotocolsAtom = xcb_atom_get(data.conn, "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 (data.conn, wmprotocolsAtom, data.draw, 1, &deleteWindowAtom);
+
   xcb_flush (data.conn); 
 
-  while ((e = xcb_wait_for_event(data.conn)))
+  bool finished = false;
+  while (!finished)
     {
-      switch (e->response_type)
+      xcb_generic_event_t *e;
+      if (e = xcb_wait_for_event(data.conn))
        {
-       case XCB_EXPOSE:
-         {
-           xcb_copy_area(data.conn, rect, data.draw, bgcolor,
-                       0, 0, 0, 0, W_W, W_H);
-           draw_julia (&data);
-           xcb_flush (data.conn);
-           break;
+          switch (XCB_EVENT_RESPONSE_TYPE(e))
+           {
+           case XCB_EXPOSE:
+             {
+               xcb_copy_area(data.conn, rect, data.draw, bgcolor,
+                               0, 0, 0, 0, W_W, W_H);
+               draw_julia (&data);
+               xcb_flush (data.conn);
+               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 XCB_KEY_RELEASE:
-       case XCB_BUTTON_RELEASE:
-         {
-            if (data.palette)
-              free (data.palette);
-            if (data.image)
-              xcb_image_destroy (data.image);
-            free (e);
-            xcb_disconnect (data.conn);
-            exit (0);
-           break;
-         }
-       }
-      free (e);
+        free (e);
+      }
     }
 
-  return 1;
+  if (data.palette)
+    free (data.palette);
+  if (data.image)
+    xcb_image_destroy (data.image);
+  xcb_disconnect (data.conn);
+
+  return 0;
 }