avoid exit on startup for demo "julia" and handle EWMH delete window. See bug https...
[free-sw/xcb/demo] / tests / julia.c
1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <stdbool.h>
4 #include <string.h>
5
6 #include <xcb/xcb.h>
7 #include <xcb/shm.h>
8 #include <xcb/xcb_aux.h>
9 #include <xcb/xcb_image.h>
10 #define XCB_ALL_PLANES ~0
11
12 /* Needed for xcb_set_wm_protocols() */
13 #include <xcb/xcb_icccm.h>
14
15 #include "julia.h"
16
17 #define W_W 640
18 #define W_H 480
19
20 /* Parameters of the fractal */
21
22 /* double cr = -0.7927; */
23 /* double ci = 0.1609; */
24
25 /* double cr = 0.32; */
26 /* double ci = 0.043; */
27
28 /* double cr = -1.1380; */
29 /* double ci = -0.2403; */
30
31 /* double cr = -0.0986; */
32 /* double ci = -0.65186; */
33
34 /* double cr = -0.1225; */
35 /* double ci = 0.7449; */
36
37 double cr = -0.3380;
38 double ci = -0.6230;
39 double origin_x = -1.8;
40 double origin_y = -1.2;
41 double width = 3.6;
42 double height = 2.4;
43
44 /* Numbers of colors in the palette */
45 int cmax = 316;
46
47 static xcb_atom_t
48 get_atom (xcb_connection_t *connection, const char *atomName)
49 {
50   if (atomName == NULL)
51     return XCB_NONE;
52   xcb_atom_t atom = XCB_NONE;
53   xcb_intern_atom_reply_t *reply = xcb_intern_atom_reply(connection,
54         xcb_intern_atom(connection, 0, strlen(atomName), atomName), NULL);
55   if (reply)
56     {
57       atom = reply->atom;
58       free(reply);
59     }
60   return atom;
61 }
62
63 void
64 palette_julia (Data *datap)
65 {
66   xcb_alloc_color_reply_t *rep;
67   int               i;
68
69   datap->palette = (uint32_t *)malloc (sizeof (uint32_t) * cmax);
70   
71   for (i = 0 ; i < cmax ; i++)
72     {
73       if (i < 128)
74         rep = xcb_alloc_color_reply (datap->conn,
75                                   xcb_alloc_color (datap->conn,
76                                                  datap->cmap,
77                                                  i<<9, 0, 0),
78                                   0);
79       else if (i < 255)
80         rep = xcb_alloc_color_reply (datap->conn,
81                                   xcb_alloc_color (datap->conn,
82                                                  datap->cmap,
83                                                  65535, (i-127)<<9, 0),
84                                   0);
85       else
86         rep = xcb_alloc_color_reply (datap->conn,
87                                   xcb_alloc_color (datap->conn,
88                                                  datap->cmap,
89                                                  65535, 65535, (i-255)<<10),
90                                   0);
91       
92       if (!rep)
93         datap->palette[i] = 0;
94       else
95         datap->palette[i] = rep->pixel;
96       free (rep);
97     }
98   
99 }
100
101 void
102 draw_julia (Data *datap)
103 {
104   double    zr, zi, t;
105   int       c;
106   int       i, j;
107   
108   datap->image = xcb_image_get (datap->conn, datap->draw,
109                        0, 0, W_W, W_H,
110                        XCB_ALL_PLANES, datap->format);
111   
112   for (i = 0 ; i < datap->image->width ; i++)
113     for (j = 0 ; j < datap->image->height ; j++)
114       {
115         zr = origin_x + width * (double)i / (double)datap->image->width;
116         zi = origin_y + height * (double)j / (double)datap->image->height;
117         c = 0;
118         while ((zr*zr + zi*zi < 4.0) &&
119                (c < cmax-1))
120           {
121             t = zr;
122             zr = zr*zr - zi*zi + cr;
123             zi = 2.0*t*zi + ci;
124             c++;
125           }
126         xcb_image_put_pixel (datap->image,
127                           i,j,
128                           datap->palette[c]);
129       }
130
131   xcb_image_put (datap->conn, datap->draw, datap->gc, datap->image,
132                0, 0, 0);
133 }
134
135 int
136 main (int argc, char *argv[])
137 {
138   Data             data;
139   xcb_screen_t       *screen;
140   xcb_drawable_t      win;
141   xcb_drawable_t      rect;
142   xcb_gcontext_t      bgcolor;
143   uint32_t           mask;
144   uint32_t           valgc[2];
145   uint32_t           valwin[3];
146   xcb_rectangle_t     rect_coord = { 0, 0, W_W, W_H};
147   int              screen_num;
148   
149   data.conn = xcb_connect (0, &screen_num);
150   screen = xcb_aux_get_screen (data.conn, screen_num);
151   data.depth = xcb_aux_get_depth (data.conn, screen);
152
153   win = screen->root;
154
155   data.gc = xcb_generate_id (data.conn);
156   mask = XCB_GC_FOREGROUND | XCB_GC_GRAPHICS_EXPOSURES;
157   valgc[0] = screen->black_pixel;
158   valgc[1] = 0; /* no graphics exposures */
159   xcb_create_gc (data.conn, data.gc, win, mask, valgc);
160
161   bgcolor = xcb_generate_id (data.conn);
162   mask = XCB_GC_FOREGROUND | XCB_GC_GRAPHICS_EXPOSURES;
163   valgc[0] = screen->white_pixel;
164   valgc[1] = 0; /* no graphics exposures */
165   xcb_create_gc (data.conn, bgcolor, win, mask, valgc);
166
167   data.draw = xcb_generate_id (data.conn);
168   mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK | XCB_CW_DONT_PROPAGATE;
169   valwin[0] = screen->white_pixel;
170   valwin[1] = XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_EXPOSURE;
171   valwin[2] = XCB_EVENT_MASK_BUTTON_PRESS;
172   xcb_create_window (data.conn, 0,
173                    data.draw,
174                    screen->root,
175                    0, 0, W_W, W_H,
176                    10,
177                    XCB_WINDOW_CLASS_INPUT_OUTPUT,
178                    screen->root_visual,
179                    mask, valwin);
180   xcb_map_window (data.conn, data.draw);
181
182   rect = xcb_generate_id (data.conn);
183   xcb_create_pixmap (data.conn, data.depth,
184                    rect, data.draw,
185                    W_W, W_H);
186   xcb_poly_fill_rectangle(data.conn, rect, bgcolor, 1, &rect_coord);
187
188   xcb_map_window (data.conn, data.draw);
189
190   data.format = XCB_IMAGE_FORMAT_Z_PIXMAP;
191
192   data.cmap = xcb_generate_id (data.conn);
193   xcb_create_colormap (data.conn,
194                      XCB_COLORMAP_ALLOC_NONE,
195                      data.cmap,
196                      data.draw,
197                      screen->root_visual);
198
199   palette_julia (&data);
200
201   xcb_atom_t deleteWindowAtom = get_atom(data.conn, "WM_DELETE_WINDOW");
202   /* Listen to X client messages in order to be able to pickup
203      the "delete window" message that is generated for example
204      when someone clicks the top-right X button within the window
205      manager decoration (or when user hits ALT-F4). */
206   xcb_set_wm_protocols (data.conn, data.draw, 1, &deleteWindowAtom);
207
208   xcb_flush (data.conn); 
209
210   bool finished = false;
211   while (!finished)
212     {
213       xcb_generic_event_t *e;
214       if (e = xcb_wait_for_event(data.conn))
215         {
216           switch (e->response_type & 0x7f)
217             {
218             case XCB_EXPOSE:
219               {
220                 xcb_copy_area(data.conn, rect, data.draw, bgcolor,
221                                 0, 0, 0, 0, W_W, W_H);
222                 draw_julia (&data);
223                 xcb_flush (data.conn);
224                 break;
225               }
226             case XCB_CLIENT_MESSAGE:
227               {
228                 if (((xcb_client_message_event_t *)e)->data.data32[0] == deleteWindowAtom)
229                   {
230                     finished = true;
231                   }
232                 break;
233               }
234             case XCB_BUTTON_PRESS:
235               {
236                 finished = true;
237                 break;
238               }
239           }
240         free (e);
241       }
242     }
243
244   if (data.palette)
245     free (data.palette);
246   if (data.image)
247     xcb_image_destroy (data.image);
248   xcb_disconnect (data.conn);
249
250   return 0;
251 }