13 #include <sys/select.h>
18 #include <xcb/damage.h>
19 #include <xcb/shape.h>
25 static gboolean quit = FALSE;
28 read_options(int argc, char **argv, d_options_t *opts)
30 opts->foo = argc && argv;
34 signal_quit_handler(int sig)
36 printf("caught signal %d, quitting\n", sig);
41 event(d_display_t *dpy)
43 xcb_generic_event_t *ev;
45 while ((ev = xcb_poll_for_event(dpy->conn)) && !quit) {
46 //printf("event %d\n", ev->response_type);
48 if (!ev->response_type) {
49 display_error(dpy, (xcb_generic_error_t*)ev);
54 switch (ev->response_type) {
55 case XCB_CREATE_NOTIFY:
57 xcb_create_notify_event_t *cev;
61 cev = (xcb_create_notify_event_t*)ev;
62 sc = display_screen_from_root(dpy, cev->parent);
64 w = screen_add_window(sc, cev->window);
67 case XCB_DESTROY_NOTIFY:
69 xcb_destroy_notify_event_t *dev;
74 dev = (xcb_destroy_notify_event_t*)ev;
75 sc = display_screen_from_root(dpy, dev->event);
77 w = screen_find_window(sc, dev->window);
78 vis = window_is_mapped(w);
81 screen_remove_window(sc, w);
82 if (vis) screen_refresh(sc);
85 case XCB_REPARENT_NOTIFY:
87 xcb_reparent_notify_event_t *rev;
91 rev = (xcb_reparent_notify_event_t*)ev;
92 sc = display_screen_from_root(dpy, rev->event);
94 w = screen_find_window(sc, rev->window);
95 if (rev->parent == sc->super.root)
96 screen_add_window(sc, rev->window);
98 if (window_is_mapped(w))
100 screen_remove_window(sc, w);
107 xcb_map_notify_event_t *mev;
111 mev = (xcb_map_notify_event_t*)ev;
112 sc = display_screen_from_root(dpy, mev->event);
114 w = screen_find_window(sc, mev->window);
116 screen_refresh(w->sc);
119 case XCB_UNMAP_NOTIFY:
121 xcb_unmap_notify_event_t *mev;
125 mev = (xcb_unmap_notify_event_t*)ev;
126 sc = display_screen_from_root(dpy, mev->event);
128 w = screen_find_window(sc, mev->window);
130 screen_refresh(w->sc);
133 case XCB_CIRCULATE_NOTIFY:
135 xcb_circulate_notify_event_t *cev;
139 cev = (xcb_circulate_notify_event_t*)ev;
140 sc = display_screen_from_root(dpy, cev->event);
142 w = screen_find_window(sc, cev->window);
143 if (cev->place == XCB_PLACE_ON_TOP)
144 screen_stacking_move_to_top(sc, w);
146 screen_stacking_move_to_bottom(sc, w);
147 screen_refresh(w->sc);
149 case XCB_CONFIGURE_NOTIFY:
151 xcb_configure_notify_event_t *cev;
153 d_window_t *w, *above;
154 int x, y, width, height, bwidth;
156 cev = (xcb_configure_notify_event_t*)ev;
157 sc = display_screen_from_root(dpy, cev->event);
159 //printf("configure 0x%x", cev->window);
160 w = screen_find_window(sc, cev->window);
161 window_get_area(w, &x, &y, &width, &height, &bwidth);
162 if (x != cev->x || y != cev->y || width != cev->width ||
163 height != cev->height || bwidth != cev->border_width)
165 window_configure(w, cev->x, cev->y,
166 cev->width, cev->height,
168 if (window_is_mapped(w)) {
169 if (x != cev->x || y != cev->y)
171 if (width != cev->width ||
172 height != cev->height || bwidth != cev->border_width)
173 sc->window_resize(w);
176 above = screen_find_window(sc, cev->above_sibling);
177 screen_stacking_move_above(sc, w, above);
178 screen_refresh(w->sc);
181 case XCB_PROPERTY_NOTIFY:
183 xcb_property_notify_event_t *pev;
186 pev = (xcb_property_notify_event_t*)ev;
187 sc = display_screen_from_root(dpy, pev->window);
189 if (pev->atom == dpy->a.xrootpmap_id ||
190 pev->atom == dpy->a.esetroot_pmap_id ||
191 pev->atom == dpy->a.xsetroot_id)
193 sc->screen_root_pixmap_changed(sc);
198 if (ev->response_type - dpy->damage.event == XCB_DAMAGE_NOTIFY) {
199 xcb_damage_notify_event_t *dev;
202 dev = (xcb_damage_notify_event_t*)ev;
203 for (it = list_top(dpy->screens); it; it = it->next) {
204 d_screen_t *sc = it->data;
207 w = screen_find_window(sc, dev->drawable);
209 screen_refresh(w->sc);
213 xcb_damage_subtract(dpy->conn, dev->damage,
216 else if (dpy->shape.present &&
217 ev->response_type - dpy->shape.event == XCB_SHAPE_NOTIFY)
219 xcb_shape_notify_event_t *sev;
222 sev = (xcb_shape_notify_event_t*)ev;
223 for (it = list_top(dpy->screens); it; it = it->next) {
224 d_screen_t *sc = it->data;
227 w = screen_find_window(sc, sev->affected_window);
229 sc->window_reshape(w);
230 screen_refresh(w->sc);
238 xcb_flush(dpy->conn);
243 paint(d_display_t *dpy)
248 gettimeofday(&now, NULL);
250 for (it = list_top(dpy->screens); it; it = it->next) {
251 d_screen_t *sc = it->data;
253 if (time_compare(&sc->next_repaint, &now) <= 0)
254 sc->screen_paint(sc);
259 run(d_display_t *dpy)
262 struct timeval next, now, *wait;
270 for (it = list_top(dpy->screens); it; it = it->next) {
271 d_screen_t *sc = it->data;
272 if (sc->need_repaint &&
273 (!npaint || time_compare(&sc->next_repaint, &next) < 0))
275 next = sc->next_repaint;
280 gettimeofday(&now, 0);
283 /* wait forever, there is nothing that needs drawing */
285 else if (time_compare(&next, &now) > 0) {
286 /* wait until the next allowed redraw time */
287 time_difference(&next, &now, &next);
291 /* don't wait cuz a redraw is due now already */
298 FD_SET(dpy->fd, &fds);
300 //printf("select %d\n", npaint);
302 r = select(dpy->fd+1, &fds, NULL, NULL, wait);
304 //printf("select timeout\n");
306 xcb_flush(dpy->conn);
309 if (xcb_connection_has_error(dpy->conn))
315 setup_functions(d_display_t *dpy)
319 for (it = list_top(dpy->screens); it; it = it->next) {
320 d_screen_t *sc = it->data;
322 screen_setup_default_functions(sc);
324 /* these can be plugins.. */
326 render_init(sc, id++);
331 cleanup_functions(d_display_t *dpy)
335 for (it = list_top(dpy->screens); it; it = it->next) {
336 d_screen_t *sc = it->data;
338 /* these can be plugins.. */
344 main(int argc, char **argv)
349 read_options(argc, argv, &opts);
351 dpy = display_open(NULL);
353 printf(_("Unable to connect to display\n"));
357 if (!dpy->composite.present) {
358 printf(_("no composite extension present on the display\n"));
362 if (!dpy->xfixes.present) {
363 printf(_("no xfixes extension present on the display\n"));
367 if (!dpy->damage.present) {
368 printf(_("no damage extension present on the display\n"));
372 if (!dpy->render.present) {
373 printf(_("no render extension present on the display\n"));
377 if (dpy->composite.major_version <= 0 && dpy->composite.minor_version < 3)
379 printf(_("composite extension does not support the overlay window"));
384 if (!display_claim_screens(dpy)) {
385 printf(_("found no screens to run on\n"));
390 signal(SIGINT, signal_quit_handler);
391 signal(SIGHUP, signal_quit_handler);
392 signal(SIGTERM, signal_quit_handler);
393 signal(SIGQUIT, signal_quit_handler);
395 setup_functions(dpy);
398 /* some of the windows may already be visible */
401 for (sc_it = list_top(dpy->screens); sc_it; sc_it = sc_it->next) {
402 d_screen_t *sc = sc_it->data;
404 for (it = list_bottom(sc->stacking); it; it = it->prev)
405 if (window_is_attr_mapped(it->data))
406 sc->window_show(it->data);
413 /* make everything hidden */
416 for (sc_it = list_top(dpy->screens); sc_it; sc_it = sc_it->next) {
417 d_screen_t *sc = sc_it->data;
419 for (it = list_top(sc->stacking); it; it = it->next) {
420 if (window_is_mapped(it->data))
421 sc->window_hide(it->data);
426 cleanup_functions(dpy);