2 * Copyright (C) 2001-2002 Bart Massey and Jamey Sharp.
3 * All Rights Reserved. See the file COPYING in this directory
4 * for licensing information.
8 #include <xcb/xcb_aux.h>
9 #include "reply_formats.h"
11 #include <stdlib.h> /* for free(3) */
12 #include <unistd.h> /* for usleep(3) */
16 #define LAG 0.3 /* lag angle for the follow line */
18 /* If I've done my math right, Linux maxes out at 100 fps on Intel (1000 fps
19 * on Alpha) due to the granularity of the kernel timer. */
20 #define FRAME_RATE 10.0 /* frames per second */
24 static xcb_connection_t *c;
25 static xcb_screen_t *root;
26 static xcb_gcontext_t white, black;
38 void *run(void *param);
39 void *event_thread(void *param);
41 static void get_depth()
43 xcb_drawable_t drawable = { root->root };
44 xcb_get_geometry_reply_t *geom;
45 geom = xcb_get_geometry_reply(c, xcb_get_geometry(c, drawable), 0);
48 perror("GetGeometry(root) failed");
53 fprintf(stderr, "Root 0x%x: %dx%dx%d\n",
54 root->root, geom->width, geom->height, geom->depth);
63 uint32_t mask = XCB_GC_FOREGROUND | XCB_GC_GRAPHICS_EXPOSURES;
65 xcb_drawable_t rootwin;
68 c = xcb_connect(0, &screen_num);
69 root = xcb_aux_get_screen(c, screen_num);
73 white = xcb_generate_id(c);
74 black = xcb_generate_id(c);
76 pthread_create(&thr, 0, event_thread, 0);
78 values[1] = 0; /* no graphics exposures */
80 values[0] = root->white_pixel;
81 xcb_create_gc(c, white, rootwin, mask, values);
83 values[0] = root->black_pixel;
84 xcb_create_gc(c, black, rootwin, mask, values);
86 for(i = 1; i < WINS; ++i)
87 pthread_create(&thr, 0, run, (void*)i);
96 xcb_copy_area(c, windows[idx].p, windows[idx].w, white, 0, 0, 0, 0,
97 windows[idx].width, windows[idx].height);
98 /* FIXME: better error detection for broken pipe
101 perror("xcb_sync_t failed");
108 void *run(void *param)
110 int idx = (int)param;
117 windows[idx].w = xcb_generate_id(c);
118 windows[idx].p = xcb_generate_id(c);
119 windows[idx].width = 300;
120 line[0].x = xo = windows[idx].width / 2;
121 windows[idx].height = 300;
122 line[0].y = yo = windows[idx].height / 2;
123 windows[idx].angv = 0.05;
126 int ws = windows[idx].width * windows[idx].width;
127 int hs = windows[idx].height * windows[idx].height;
128 r = sqrt(ws + hs) + 1.0;
132 uint32_t mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK | XCB_CW_DONT_PROPAGATE;
134 xcb_rectangle_t rect = { 0, 0, windows[idx].width, windows[idx].height };
135 values[0] = root->white_pixel;
136 values[1] = XCB_EVENT_MASK_BUTTON_RELEASE | XCB_EVENT_MASK_EXPOSURE;
137 values[2] = XCB_EVENT_MASK_BUTTON_PRESS;
139 xcb_create_window(c, depth, windows[idx].w, root->root,
140 /* x */ 0, /* y */ 0,
141 windows[idx].width, windows[idx].height,
142 /* border */ 0, XCB_WINDOW_CLASS_INPUT_OUTPUT,
143 /* visual */ root->root_visual,
146 xcb_map_window(c, windows[idx].w);
148 xcb_create_pixmap(c, depth,
149 windows[idx].p, windows[idx].w,
150 windows[idx].width, windows[idx].height);
152 xcb_poly_fill_rectangle(c, windows[idx].p, white, 1, &rect);
159 line[1].x = xo + r * cos(theta);
160 line[1].y = yo + r * sin(theta);
161 xcb_poly_line(c, XCB_COORD_MODE_ORIGIN, windows[idx].p, black,
164 line[1].x = xo + r * cos(theta + LAG);
165 line[1].y = yo + r * sin(theta + LAG);
166 xcb_poly_line(c, XCB_COORD_MODE_ORIGIN, windows[idx].p, white,
170 theta += windows[idx].angv;
171 while(theta > 2 * PI)
176 usleep(1000000 / FRAME_RATE);
182 int lookup_window(xcb_window_t w)
185 for(i = 0; i < WINS; ++i)
186 if(windows[i].w == w)
191 void *event_thread(void *param)
193 xcb_generic_event_t *e;
198 e = xcb_wait_for_event(c);
201 if(e->response_type == XCB_EXPOSE)
203 xcb_expose_event_t *ee = (xcb_expose_event_t *) e;
204 idx = lookup_window(ee->window);
206 fprintf(stderr, "Expose on unknown window!\n");
209 xcb_copy_area(c, windows[idx].p, windows[idx].w,
210 white, ee->x, ee->y, ee->x, ee->y,
211 ee->width, ee->height);
216 else if(e->response_type == XCB_BUTTON_RELEASE)
218 xcb_button_release_event_t *bre = (xcb_button_release_event_t *) e;
219 idx = lookup_window(bre->event);
221 fprintf(stderr, "ButtonRelease on unknown window!\n");
224 if(bre->detail == XCB_BUTTON_INDEX_1)
225 windows[idx].angv = -windows[idx].angv;
226 else if(bre->detail == XCB_BUTTON_INDEX_4)
227 windows[idx].angv += 0.001;
228 else if(bre->detail == XCB_BUTTON_INDEX_5)
229 windows[idx].angv -= 0.001;