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)
274 gettimeofday(&now, NULL);
276 for (it = list_top(dpy->screens); it; it = it->next) {
277 d_screen_t *sc = it->data;
279 render_timeout(sc, &now);
280 fade_timeout(sc, &now);
285 paint(d_display_t *dpy)
290 gettimeofday(&now, NULL);
292 for (it = list_top(dpy->screens); it; it = it->next) {
293 d_screen_t *sc = it->data;
295 if (time_compare(&sc->next_repaint, &now) <= 0)
296 sc->screen_paint(sc);
301 run(d_display_t *dpy)
304 struct timeval next, now, *wait;
305 int r, npaint, ntime;
313 for (it = list_top(dpy->screens); it; it = it->next) {
314 d_screen_t *sc = it->data;
315 struct timeval next_timeout;
317 if (render_next_timeout(sc, &next_timeout)) {
318 if ((!npaint && !ntime) ||
319 time_compare(&next_timeout, &next) < 0)
325 if (fade_next_timeout(sc, &next_timeout)) {
326 if ((!npaint && !ntime) ||
327 time_compare(&next_timeout, &next) < 0)
334 if (sc->need_repaint &&
335 ((!npaint && !ntime) ||
336 time_compare(&sc->next_repaint, &next) < 0))
338 next = sc->next_repaint;
343 gettimeofday(&now, 0);
345 if (!npaint && !ntime)
346 /* wait forever, there is nothing that needs drawing */
348 else if (time_compare(&next, &now) > 0) {
349 /* wait until the next allowed redraw time */
350 time_difference(&next, &now, &next);
354 /* don't wait cuz a timer is due now already */
361 FD_SET(dpy->fd, &fds);
363 //printf("select %d\n", npaint);
365 r = select(dpy->fd+1, &fds, NULL, NULL, wait);
367 //printf("select timeout\n");
370 xcb_flush(dpy->conn);
373 if (xcb_connection_has_error(dpy->conn))
379 setup_functions(d_display_t *dpy)
383 for (it = list_top(dpy->screens); it; it = it->next) {
384 d_screen_t *sc = it->data;
386 screen_setup_default_functions(sc);
388 /* these can be plugins.. */
390 render_init(sc, id++);
396 cleanup_functions(d_display_t *dpy)
400 for (it = list_top(dpy->screens); it; it = it->next) {
401 d_screen_t *sc = it->data;
403 /* these can be plugins.. */
410 main(int argc, char **argv)
415 read_options(argc, argv, &opts);
417 dpy = display_open(NULL);
419 printf(_("Unable to connect to display\n"));
423 if (!dpy->composite.present) {
424 printf(_("no composite extension present on the display\n"));
428 if (!dpy->xfixes.present) {
429 printf(_("no xfixes extension present on the display\n"));
433 if (!dpy->damage.present) {
434 printf(_("no damage extension present on the display\n"));
438 if (!dpy->render.present) {
439 printf(_("no render extension present on the display\n"));
443 if (dpy->composite.major_version <= 0 && dpy->composite.minor_version < 3)
445 printf(_("composite extension does not support the overlay window"));
450 if (!display_claim_screens(dpy)) {
451 printf(_("found no screens to run on\n"));
456 signal(SIGINT, signal_quit_handler);
457 signal(SIGHUP, signal_quit_handler);
458 signal(SIGTERM, signal_quit_handler);
459 signal(SIGQUIT, signal_quit_handler);
461 setup_functions(dpy);
464 /* some of the windows may already be visible */
467 for (sc_it = list_top(dpy->screens); sc_it; sc_it = sc_it->next) {
468 d_screen_t *sc = sc_it->data;
470 for (it = list_bottom(sc->stacking); it; it = it->prev)
471 if (window_is_attr_mapped(it->data))
472 sc->window_show(it->data);
479 /* make everything hidden */
482 for (sc_it = list_top(dpy->screens); sc_it; sc_it = sc_it->next) {
483 d_screen_t *sc = sc_it->data;
485 for (it = list_top(sc->stacking); it; it = it->next) {
486 if (window_is_mapped(it->data))
487 sc->window_hide(it->data);
492 cleanup_functions(dpy);