10 /* these can be plugins */
16 #include <sys/select.h>
21 #include <xcb/damage.h>
22 #include <xcb/shape.h>
28 static gboolean quit = FALSE;
31 read_options(int argc, char **argv, d_options_t *opts)
33 opts->foo = argc && argv;
37 signal_quit_handler(int sig)
39 printf("caught signal %d, quitting\n", sig);
44 event(d_display_t *dpy)
46 xcb_generic_event_t *ev;
48 while ((ev = xcb_poll_for_event(dpy->conn)) && !quit) {
49 //printf("event %d\n", ev->response_type);
51 if (!ev->response_type) {
52 display_error(dpy, (xcb_generic_error_t*)ev);
57 switch (ev->response_type) {
58 case XCB_CREATE_NOTIFY:
60 xcb_create_notify_event_t *cev;
64 cev = (xcb_create_notify_event_t*)ev;
65 sc = display_screen_from_root(dpy, cev->parent);
67 w = screen_add_window(sc, cev->window);
70 case XCB_DESTROY_NOTIFY:
72 xcb_destroy_notify_event_t *dev;
77 dev = (xcb_destroy_notify_event_t*)ev;
78 sc = display_screen_from_root(dpy, dev->event);
80 w = screen_find_window(sc, dev->window);
81 vis = window_is_mapped(w);
83 sc->window_become_zombie(w);
86 screen_remove_window(sc, w);
87 if (vis) screen_refresh(sc);
90 case XCB_REPARENT_NOTIFY:
92 xcb_reparent_notify_event_t *rev;
96 rev = (xcb_reparent_notify_event_t*)ev;
97 sc = display_screen_from_root(dpy, rev->event);
99 w = screen_find_window(sc, rev->window);
100 if (rev->parent == sc->super.root)
101 screen_add_window(sc, rev->window);
103 if (window_is_mapped(w)) {
104 sc->window_become_zombie(w);
107 screen_remove_window(sc, w);
114 xcb_map_notify_event_t *mev;
118 mev = (xcb_map_notify_event_t*)ev;
119 sc = display_screen_from_root(dpy, mev->event);
121 w = screen_find_window(sc, mev->window);
123 screen_refresh(w->sc);
126 case XCB_UNMAP_NOTIFY:
128 xcb_unmap_notify_event_t *mev;
132 mev = (xcb_unmap_notify_event_t*)ev;
133 sc = display_screen_from_root(dpy, mev->event);
135 w = screen_find_window(sc, mev->window);
136 sc->window_become_zombie(w);
138 screen_refresh(w->sc);
141 case XCB_CIRCULATE_NOTIFY:
143 xcb_circulate_notify_event_t *cev;
147 cev = (xcb_circulate_notify_event_t*)ev;
148 sc = display_screen_from_root(dpy, cev->event);
150 w = screen_find_window(sc, cev->window);
151 if (cev->place == XCB_PLACE_ON_TOP)
152 screen_stacking_move_to_top(sc, w);
154 screen_stacking_move_to_bottom(sc, w);
155 screen_refresh(w->sc);
157 case XCB_CONFIGURE_NOTIFY:
159 xcb_configure_notify_event_t *cev;
161 d_window_t *w, *above;
162 int x, y, width, height, bwidth;
164 cev = (xcb_configure_notify_event_t*)ev;
165 sc = display_screen_from_root(dpy, cev->event);
167 //printf("configure 0x%x", cev->window);
168 w = screen_find_window(sc, cev->window);
169 window_get_area(w, &x, &y, &width, &height, &bwidth);
170 if (x != cev->x || y != cev->y || width != cev->width ||
171 height != cev->height || bwidth != cev->border_width)
173 window_configure(w, cev->x, cev->y,
174 cev->width, cev->height,
176 if (window_is_mapped(w)) {
177 if (x != cev->x || y != cev->y)
179 if (width != cev->width ||
180 height != cev->height || bwidth != cev->border_width)
181 sc->window_resize(w);
184 above = screen_find_window(sc, cev->above_sibling);
185 screen_stacking_move_above(sc, w, above);
186 screen_refresh(w->sc);
189 case XCB_PROPERTY_NOTIFY:
191 xcb_property_notify_event_t *pev;
193 pev = (xcb_property_notify_event_t*)ev;
194 if (pev->atom == dpy->a.xrootpmap_id ||
195 pev->atom == dpy->a.esetroot_pmap_id ||
196 pev->atom == dpy->a.xsetroot_id)
200 sc = display_screen_from_root(dpy, pev->window);
201 if (sc) sc->screen_root_pixmap_change(sc);
203 else if (pev->atom == dpy->a.net_wm_window_opacity) {
206 for (it = list_top(dpy->screens); it; it = it->next) {
207 d_screen_t *sc = it->data;
210 w = screen_find_window(sc, pev->window);
212 window_update_user_opacity(w);
213 if (window_is_mapped(w)) {
214 sc->window_opacity_change(w);
215 screen_refresh(w->sc);
224 if (ev->response_type - dpy->damage.event == XCB_DAMAGE_NOTIFY) {
225 xcb_damage_notify_event_t *dev;
228 dev = (xcb_damage_notify_event_t*)ev;
229 for (it = list_top(dpy->screens); it; it = it->next) {
230 d_screen_t *sc = it->data;
233 w = screen_find_window(sc, dev->drawable);
235 screen_refresh(w->sc);
239 xcb_damage_subtract(dpy->conn, dev->damage,
242 else if (dpy->shape.present &&
243 ev->response_type - dpy->shape.event == XCB_SHAPE_NOTIFY)
245 xcb_shape_notify_event_t *sev;
248 sev = (xcb_shape_notify_event_t*)ev;
249 for (it = list_top(dpy->screens); it; it = it->next) {
250 d_screen_t *sc = it->data;
253 w = screen_find_window(sc, sev->affected_window);
255 sc->window_reshape(w);
256 screen_refresh(w->sc);
264 xcb_flush(dpy->conn);
269 timeouts(d_display_t *dpy, const struct timeval *now)
273 for (it = list_top(dpy->screens); it; it = it->next) {
274 d_screen_t *sc = it->data;
277 if (render_next_timeout(sc, &tv) && time_compare(&tv, now) <= 0)
278 render_timeout(sc, now);
279 if (fade_next_timeout(sc, &tv) && time_compare(&tv, now) <= 0)
280 fade_timeout(sc, now);
285 paint(d_display_t *dpy)
289 for (it = list_top(dpy->screens); it; it = it->next) {
290 d_screen_t *sc = it->data;
291 if (sc->need_repaint)
292 sc->screen_paint(sc);
297 run(d_display_t *dpy)
299 struct timeval now, next_repaint;
301 gettimeofday(&now, NULL);
305 struct timeval next, *wait;
306 int r, npaint, ntime;
314 for (it = list_top(dpy->screens); it; it = it->next) {
315 d_screen_t *sc = it->data;
316 struct timeval next_timeout;
318 if (render_next_timeout(sc, &next_timeout)) {
319 if (!ntime || time_compare(&next_timeout, &next) < 0) {
324 if (fade_next_timeout(sc, &next_timeout)) {
325 if (!ntime || time_compare(&next_timeout, &next) < 0) {
331 if (sc->need_repaint)
336 if (!ntime || time_compare(&next_repaint, &next) < 0) {
341 if (!npaint && !ntime)
342 /* wait forever, there is nothing that needs drawing */
344 else if (time_compare(&next, &now) > 0) {
345 /* wait until the next allowed redraw time */
346 time_difference(&next, &now, &next);
350 /* don't wait cuz a timer is due now already */
357 FD_SET(dpy->fd, &fds);
359 //printf("select %d\n", npaint);
361 r = select(dpy->fd+1, &fds, NULL, NULL, wait);
363 gettimeofday(&now, NULL);
365 //printf("select timeout\n");
367 if (time_compare(&next_repaint, &now) <= 0) {
370 time_add(&next_repaint, 1000000/90); /* 60hz */
372 xcb_flush(dpy->conn);
375 if (xcb_connection_has_error(dpy->conn))
381 setup_functions(d_display_t *dpy)
385 for (it = list_top(dpy->screens); it; it = it->next) {
386 d_screen_t *sc = it->data;
388 screen_setup_default_functions(sc);
390 /* these can be plugins.. */
392 render_init(sc, id++);
398 cleanup_functions(d_display_t *dpy)
402 for (it = list_top(dpy->screens); it; it = it->next) {
403 d_screen_t *sc = it->data;
405 /* these can be plugins.. */
412 main(int argc, char **argv)
417 read_options(argc, argv, &opts);
419 dpy = display_open(NULL);
421 printf(_("Unable to connect to display\n"));
425 if (!dpy->composite.present) {
426 printf(_("no composite extension present on the display\n"));
430 if (!dpy->xfixes.present) {
431 printf(_("no xfixes extension present on the display\n"));
435 if (!dpy->damage.present) {
436 printf(_("no damage extension present on the display\n"));
440 if (!dpy->render.present) {
441 printf(_("no render extension present on the display\n"));
445 if (dpy->composite.major_version <= 0 && dpy->composite.minor_version < 3)
447 printf(_("composite extension does not support the overlay window"));
452 if (!display_claim_screens(dpy)) {
453 printf(_("found no screens to run on\n"));
458 signal(SIGINT, signal_quit_handler);
459 signal(SIGHUP, signal_quit_handler);
460 signal(SIGTERM, signal_quit_handler);
461 signal(SIGQUIT, signal_quit_handler);
463 setup_functions(dpy);
466 /* some of the windows may already be visible */
469 for (sc_it = list_top(dpy->screens); sc_it; sc_it = sc_it->next) {
470 d_screen_t *sc = sc_it->data;
472 for (it = list_bottom(sc->stacking); it; it = it->prev)
473 if (window_is_attr_mapped(it->data))
474 sc->window_show(it->data);
481 /* make everything hidden */
484 for (sc_it = list_top(dpy->screens); sc_it; sc_it = sc_it->next) {
485 d_screen_t *sc = sc_it->data;
487 for (it = list_top(sc->stacking); it; it = it->next) {
488 if (window_is_mapped(it->data))
489 sc->window_hide(it->data);
494 cleanup_functions(dpy);