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;
29 static gboolean running = FALSE;
32 read_options(int argc, char **argv, d_options_t *opts)
34 opts->foo = argc && argv;
38 signal_quit_handler(int sig)
40 printf("caught signal %d, quitting\n", sig);
45 event(d_display_t *dpy)
47 xcb_generic_event_t *ev;
49 while ((ev = xcb_poll_for_event(dpy->conn)) && !quit) {
50 //printf("event %d\n", ev->response_type);
52 if (!ev->response_type) {
53 display_error(dpy, (xcb_generic_error_t*)ev);
58 switch (ev->response_type) {
59 case XCB_CREATE_NOTIFY:
61 xcb_create_notify_event_t *cev;
65 cev = (xcb_create_notify_event_t*)ev;
66 sc = display_screen_from_root(dpy, cev->parent);
68 w = screen_add_window(sc, cev->window);
71 case XCB_DESTROY_NOTIFY:
73 xcb_destroy_notify_event_t *dev;
78 dev = (xcb_destroy_notify_event_t*)ev;
79 sc = display_screen_from_root(dpy, dev->event);
81 w = screen_find_window(sc, dev->window);
82 vis = window_is_mapped(w);
84 sc->window_become_zombie(w);
87 screen_remove_window(sc, w);
88 if (vis) screen_refresh(sc);
91 case XCB_REPARENT_NOTIFY:
93 xcb_reparent_notify_event_t *rev;
97 rev = (xcb_reparent_notify_event_t*)ev;
98 sc = display_screen_from_root(dpy, rev->event);
100 w = screen_find_window(sc, rev->window);
101 if (rev->parent == sc->super.root)
102 screen_add_window(sc, rev->window);
104 if (window_is_mapped(w)) {
105 sc->window_become_zombie(w);
108 screen_remove_window(sc, w);
115 xcb_map_notify_event_t *mev;
119 mev = (xcb_map_notify_event_t*)ev;
120 sc = display_screen_from_root(dpy, mev->event);
122 w = screen_find_window(sc, mev->window);
124 screen_refresh(w->sc);
127 case XCB_UNMAP_NOTIFY:
129 xcb_unmap_notify_event_t *mev;
133 mev = (xcb_unmap_notify_event_t*)ev;
134 sc = display_screen_from_root(dpy, mev->event);
136 w = screen_find_window(sc, mev->window);
137 sc->window_become_zombie(w);
139 screen_refresh(w->sc);
142 case XCB_CIRCULATE_NOTIFY:
144 xcb_circulate_notify_event_t *cev;
148 cev = (xcb_circulate_notify_event_t*)ev;
149 sc = display_screen_from_root(dpy, cev->event);
151 w = screen_find_window(sc, cev->window);
152 if (cev->place == XCB_PLACE_ON_TOP)
153 screen_stacking_move_to_top(sc, w);
155 screen_stacking_move_to_bottom(sc, w);
156 screen_refresh(w->sc);
158 case XCB_CONFIGURE_NOTIFY:
160 xcb_configure_notify_event_t *cev;
162 d_window_t *w, *above;
163 int x, y, width, height, bwidth;
165 cev = (xcb_configure_notify_event_t*)ev;
166 sc = display_screen_from_root(dpy, cev->event);
168 //printf("configure 0x%x", cev->window);
169 w = screen_find_window(sc, cev->window);
170 window_get_area(w, &x, &y, &width, &height, &bwidth);
171 if (x != cev->x || y != cev->y || width != cev->width ||
172 height != cev->height || bwidth != cev->border_width)
174 window_configure(w, cev->x, cev->y,
175 cev->width, cev->height,
177 if (window_is_mapped(w)) {
178 if (x != cev->x || y != cev->y)
180 if (width != cev->width ||
181 height != cev->height || bwidth != cev->border_width)
182 sc->window_resize(w);
185 above = screen_find_window(sc, cev->above_sibling);
186 if (window_is_mapped(w))
187 sc->window_restack(w, above);
188 screen_refresh(w->sc);
191 case XCB_PROPERTY_NOTIFY:
193 xcb_property_notify_event_t *pev;
195 pev = (xcb_property_notify_event_t*)ev;
196 if (pev->atom == dpy->a.xrootpmap_id ||
197 pev->atom == dpy->a.esetroot_pmap_id ||
198 pev->atom == dpy->a.xsetroot_id)
202 sc = display_screen_from_root(dpy, pev->window);
203 if (sc) sc->screen_root_pixmap_change(sc);
205 else if (pev->atom == dpy->a.net_wm_window_opacity) {
208 for (it = list_top(dpy->screens); it; it = it->next) {
209 d_screen_t *sc = it->data;
212 w = screen_find_window(sc, pev->window);
214 window_update_user_opacity(w);
215 if (window_is_mapped(w)) {
216 sc->window_opacity_change(w);
217 screen_refresh(w->sc);
226 if (ev->response_type - dpy->damage.event == XCB_DAMAGE_NOTIFY) {
227 xcb_damage_notify_event_t *dev;
230 dev = (xcb_damage_notify_event_t*)ev;
231 for (it = list_top(dpy->screens); it; it = it->next) {
232 d_screen_t *sc = it->data;
235 w = screen_find_window(sc, dev->drawable);
237 sc->window_damage(w);
238 screen_refresh(w->sc);
242 xcb_damage_subtract(dpy->conn, dev->damage,
245 else if (dpy->shape.present &&
246 ev->response_type - dpy->shape.event == XCB_SHAPE_NOTIFY)
248 xcb_shape_notify_event_t *sev;
251 sev = (xcb_shape_notify_event_t*)ev;
252 for (it = list_top(dpy->screens); it; it = it->next) {
253 d_screen_t *sc = it->data;
256 w = screen_find_window(sc, sev->affected_window);
257 if (w && window_is_mapped(w)) {
258 sc->window_reshape(w);
259 screen_refresh(w->sc);
267 xcb_flush(dpy->conn);
272 timeouts(d_display_t *dpy, const struct timeval *now)
276 for (it = list_top(dpy->screens); it; it = it->next) {
277 d_screen_t *sc = it->data;
280 if (render_next_timeout(sc, &tv) && time_compare(&tv, now) <= 0)
281 render_timeout(sc, now);
282 if (fade_next_timeout(sc, &tv) && time_compare(&tv, now) <= 0)
283 fade_timeout(sc, now);
288 paint(d_display_t *dpy)
292 for (it = list_top(dpy->screens); it; it = it->next) {
293 d_screen_t *sc = it->data;
294 if (sc->need_repaint)
295 sc->screen_paint(sc);
300 run(d_display_t *dpy)
302 struct timeval now, next_repaint;
306 gettimeofday(&now, NULL);
310 struct timeval next, *wait;
311 int r, npaint, ntime;
320 for (it = list_top(dpy->screens); it; it = it->next) {
321 d_screen_t *sc = it->data;
322 struct timeval next_timeout;
324 if (render_next_timeout(sc, &next_timeout)) {
325 if (!ntime || time_compare(&next_timeout, &next) < 0) {
330 if (fade_next_timeout(sc, &next_timeout)) {
331 if (!ntime || time_compare(&next_timeout, &next) < 0) {
337 if (sc->need_repaint)
342 if (!ntime || time_compare(&next_repaint, &next) < 0) {
347 if (!npaint && !ntime) {
348 /* wait forever, there is nothing that needs drawing */
352 else if (time_compare(&next, &now) > 0) {
353 /* wait until the next allowed redraw time */
354 time_difference(&next, &now, &next);
359 /* don't wait cuz a timer is due now already */
363 //printf("select? %d %d\n", due, npaint);
367 FD_SET(dpy->fd, &fds);
368 r = select(dpy->fd+1, &fds, NULL, NULL, wait);
373 gettimeofday(&now, NULL);
375 //printf("select timeout\n");
377 if (time_compare(&next_repaint, &now) <= 0) {
380 time_add(&next_repaint, 1000000/90); /* 60hz */
382 xcb_flush(dpy->conn);
385 if (xcb_connection_has_error(dpy->conn))
393 setup_functions(d_display_t *dpy)
397 for (it = list_top(dpy->screens); it; it = it->next) {
398 d_screen_t *sc = it->data;
400 screen_setup_default_functions(sc);
402 /* these can be plugins.. */
404 render_init(sc, id++);
410 cleanup_functions(d_display_t *dpy)
414 for (it = list_top(dpy->screens); it; it = it->next) {
415 d_screen_t *sc = it->data;
417 /* these can be plugins.. */
424 main(int argc, char **argv)
429 read_options(argc, argv, &opts);
431 dpy = display_open(NULL);
433 printf(_("Unable to connect to display\n"));
437 if (!dpy->composite.present) {
438 printf(_("no composite extension present on the display\n"));
442 if (!dpy->xfixes.present) {
443 printf(_("no xfixes extension present on the display\n"));
447 if (!dpy->damage.present) {
448 printf(_("no damage extension present on the display\n"));
452 if (!dpy->render.present) {
453 printf(_("no render extension present on the display\n"));
457 if (dpy->composite.major_version <= 0 && dpy->composite.minor_version < 3)
459 printf(_("composite extension does not support the overlay window"));
464 if (!display_claim_screens(dpy)) {
465 printf(_("found no screens to run on\n"));
470 signal(SIGINT, signal_quit_handler);
471 signal(SIGHUP, signal_quit_handler);
472 signal(SIGTERM, signal_quit_handler);
473 signal(SIGQUIT, signal_quit_handler);
475 setup_functions(dpy);
478 /* some of the windows may already be visible */
481 for (sc_it = list_top(dpy->screens); sc_it; sc_it = sc_it->next) {
482 d_screen_t *sc = sc_it->data;
484 for (it = list_bottom(sc->stacking); it; it = it->prev)
485 if (window_is_attr_mapped(it->data))
486 sc->window_show(it->data);
494 /* make everything hidden */
497 for (sc_it = list_top(dpy->screens); sc_it; sc_it = sc_it->next) {
498 d_screen_t *sc = sc_it->data;
500 for (it = list_top(sc->stacking); it; it = it->next) {
501 if (window_is_mapped(it->data))
502 sc->window_hide(it->data);
507 cleanup_functions(dpy);
514 dcompmgr_running(void)