10 /* these can be plugins */
12 #include "glxrender.h"
17 #include <sys/select.h>
22 #include <xcb/damage.h>
23 #include <xcb/shape.h>
29 static gboolean quit = FALSE;
30 static gboolean running = FALSE;
33 read_options(int argc, char **argv, d_options_t *opts)
35 opts->foo = argc && argv;
39 signal_quit_handler(int sig)
41 printf("caught signal %d, quitting\n", sig);
46 event(d_display_t *dpy)
48 xcb_generic_event_t *ev;
50 while ((ev = xcb_poll_for_event(dpy->conn)) && !quit) {
51 //printf("event %d\n", ev->response_type);
53 if (!ev->response_type) {
54 display_error(dpy, (xcb_generic_error_t*)ev);
59 switch (ev->response_type) {
60 case XCB_CREATE_NOTIFY:
62 xcb_create_notify_event_t *cev;
66 cev = (xcb_create_notify_event_t*)ev;
67 sc = display_screen_from_root(dpy, cev->parent);
69 w = screen_add_window(sc, cev->window);
72 case XCB_DESTROY_NOTIFY:
74 xcb_destroy_notify_event_t *dev;
79 dev = (xcb_destroy_notify_event_t*)ev;
80 sc = display_screen_from_root(dpy, dev->event);
82 w = screen_find_window(sc, dev->window);
83 vis = window_is_mapped(w);
85 sc->window_become_zombie(w);
88 screen_remove_window(sc, w);
89 if (vis) screen_refresh(sc);
92 case XCB_REPARENT_NOTIFY:
94 xcb_reparent_notify_event_t *rev;
98 rev = (xcb_reparent_notify_event_t*)ev;
99 sc = display_screen_from_root(dpy, rev->event);
101 w = screen_find_window(sc, rev->window);
102 if (rev->parent == sc->super.root)
103 screen_add_window(sc, rev->window);
105 if (window_is_mapped(w)) {
106 sc->window_become_zombie(w);
109 screen_remove_window(sc, w);
116 xcb_map_notify_event_t *mev;
120 mev = (xcb_map_notify_event_t*)ev;
121 sc = display_screen_from_root(dpy, mev->event);
123 w = screen_find_window(sc, mev->window);
125 screen_refresh(w->sc);
128 case XCB_UNMAP_NOTIFY:
130 xcb_unmap_notify_event_t *mev;
134 mev = (xcb_unmap_notify_event_t*)ev;
135 sc = display_screen_from_root(dpy, mev->event);
137 w = screen_find_window(sc, mev->window);
138 sc->window_become_zombie(w);
140 screen_refresh(w->sc);
143 case XCB_CIRCULATE_NOTIFY:
145 xcb_circulate_notify_event_t *cev;
149 cev = (xcb_circulate_notify_event_t*)ev;
150 sc = display_screen_from_root(dpy, cev->event);
152 w = screen_find_window(sc, cev->window);
153 if (cev->place == XCB_PLACE_ON_TOP)
154 screen_stacking_move_to_top(sc, w);
156 screen_stacking_move_to_bottom(sc, w);
157 screen_refresh(w->sc);
159 case XCB_CONFIGURE_NOTIFY:
161 xcb_configure_notify_event_t *cev;
163 d_window_t *w, *above;
164 int x, y, width, height, bwidth;
166 cev = (xcb_configure_notify_event_t*)ev;
167 sc = display_screen_from_root(dpy, cev->event);
169 //printf("configure 0x%x", cev->window);
170 w = screen_find_window(sc, cev->window);
171 window_get_area(w, &x, &y, &width, &height, &bwidth);
172 if (x != cev->x || y != cev->y || width != cev->width ||
173 height != cev->height || bwidth != cev->border_width)
175 window_configure(w, cev->x, cev->y,
176 cev->width, cev->height,
178 if (window_is_mapped(w)) {
179 if (x != cev->x || y != cev->y)
181 if (width != cev->width ||
182 height != cev->height || bwidth != cev->border_width)
183 sc->window_resize(w);
186 above = screen_find_window(sc, cev->above_sibling);
187 if (window_is_mapped(w))
188 sc->window_restack(w, above);
189 screen_refresh(w->sc);
192 case XCB_PROPERTY_NOTIFY:
194 xcb_property_notify_event_t *pev;
196 pev = (xcb_property_notify_event_t*)ev;
197 if (pev->atom == dpy->a.xrootpmap_id ||
198 pev->atom == dpy->a.esetroot_pmap_id ||
199 pev->atom == dpy->a.xsetroot_id)
203 sc = display_screen_from_root(dpy, pev->window);
204 if (sc) sc->screen_root_pixmap_change(sc);
206 else if (pev->atom == dpy->a.net_wm_window_opacity) {
209 for (it = list_top(dpy->screens); it; it = it->next) {
210 d_screen_t *sc = it->data;
213 w = screen_find_window(sc, pev->window);
215 window_update_user_opacity(w);
216 if (window_is_mapped(w)) {
217 sc->window_opacity_change(w);
218 screen_refresh(w->sc);
227 if (ev->response_type - dpy->damage.event == XCB_DAMAGE_NOTIFY) {
228 xcb_damage_notify_event_t *dev;
231 dev = (xcb_damage_notify_event_t*)ev;
232 for (it = list_top(dpy->screens); it; it = it->next) {
233 d_screen_t *sc = it->data;
236 w = screen_find_window(sc, dev->drawable);
238 sc->window_damage(w);
239 screen_refresh(w->sc);
243 xcb_damage_subtract(dpy->conn, dev->damage,
246 else if (dpy->shape.present &&
247 ev->response_type - dpy->shape.event == XCB_SHAPE_NOTIFY)
249 xcb_shape_notify_event_t *sev;
252 sev = (xcb_shape_notify_event_t*)ev;
253 for (it = list_top(dpy->screens); it; it = it->next) {
254 d_screen_t *sc = it->data;
257 w = screen_find_window(sc, sev->affected_window);
258 if (w && window_is_mapped(w)) {
259 sc->window_reshape(w);
260 screen_refresh(w->sc);
268 xcb_flush(dpy->conn);
273 timeouts(d_display_t *dpy, const struct timeval *now)
277 for (it = list_top(dpy->screens); it; it = it->next) {
278 d_screen_t *sc = it->data;
281 if (glxrender_next_timeout(sc, &tv) && time_compare(&tv, now) <= 0)
282 glxrender_timeout(sc, now);
283 if (render_next_timeout(sc, &tv) && time_compare(&tv, now) <= 0)
284 render_timeout(sc, now);
285 if (fade_next_timeout(sc, &tv) && time_compare(&tv, now) <= 0)
286 fade_timeout(sc, now);
291 paint(d_display_t *dpy)
295 for (it = list_top(dpy->screens); it; it = it->next) {
296 d_screen_t *sc = it->data;
297 if (sc->need_repaint)
298 sc->screen_paint(sc);
303 run(d_display_t *dpy)
305 struct timeval now, next_repaint;
309 gettimeofday(&now, NULL);
313 struct timeval next, *wait;
314 int r, npaint, ntime;
323 for (it = list_top(dpy->screens); it; it = it->next) {
324 d_screen_t *sc = it->data;
325 struct timeval next_timeout;
327 if (glxrender_next_timeout(sc, &next_timeout)) {
328 if (!ntime || time_compare(&next_timeout, &next) < 0) {
333 if (render_next_timeout(sc, &next_timeout)) {
334 if (!ntime || time_compare(&next_timeout, &next) < 0) {
339 if (fade_next_timeout(sc, &next_timeout)) {
340 if (!ntime || time_compare(&next_timeout, &next) < 0) {
346 if (sc->need_repaint)
351 if (!ntime || time_compare(&next_repaint, &next) < 0) {
356 if (!npaint && !ntime) {
357 /* wait forever, there is nothing that needs drawing */
361 else if (time_compare(&next, &now) > 0) {
362 /* wait until the next allowed redraw time */
363 time_difference(&next, &now, &next);
368 /* don't wait cuz a timer is due now already */
372 //printf("select? %d %d\n", due, npaint);
376 FD_SET(dpy->fd, &fds);
377 r = select(dpy->fd+1, &fds, NULL, NULL, wait);
382 gettimeofday(&now, NULL);
384 //printf("select timeout\n");
386 if (time_compare(&next_repaint, &now) <= 0) {
389 time_add(&next_repaint, 1000000/90); /* 60hz */
391 xcb_flush(dpy->conn);
394 if (xcb_connection_has_error(dpy->conn))
402 setup_functions(d_display_t *dpy)
406 for (it = list_top(dpy->screens); it; it = it->next) {
407 d_screen_t *sc = it->data;
409 screen_setup_default_functions(sc);
411 /* these can be plugins.. */
413 glxrender_init(sc, id++);
414 //render_init(sc, id++);
420 cleanup_functions(d_display_t *dpy)
424 for (it = list_top(dpy->screens); it; it = it->next) {
425 d_screen_t *sc = it->data;
427 /* these can be plugins.. */
435 main(int argc, char **argv)
440 read_options(argc, argv, &opts);
442 dpy = display_open(NULL);
444 printf(_("Unable to connect to display\n"));
448 if (!dpy->composite.present) {
449 printf(_("no composite extension present on the display\n"));
453 if (!dpy->xfixes.present) {
454 printf(_("no xfixes extension present on the display\n"));
458 if (!dpy->damage.present) {
459 printf(_("no damage extension present on the display\n"));
463 if (!dpy->render.present) {
464 printf(_("no render extension present on the display\n"));
468 if (dpy->composite.major_version <= 0 && dpy->composite.minor_version < 3)
470 printf(_("composite extension does not support the overlay window"));
475 if (!display_claim_screens(dpy)) {
476 printf(_("found no screens to run on\n"));
481 signal(SIGINT, signal_quit_handler);
482 signal(SIGHUP, signal_quit_handler);
483 signal(SIGTERM, signal_quit_handler);
484 signal(SIGQUIT, signal_quit_handler);
486 setup_functions(dpy);
489 /* some of the windows may already be visible */
492 for (sc_it = list_top(dpy->screens); sc_it; sc_it = sc_it->next) {
493 d_screen_t *sc = sc_it->data;
495 for (it = list_bottom(sc->stacking); it; it = it->prev)
496 if (window_is_attr_mapped(it->data))
497 sc->window_show(it->data);
505 /* make everything hidden */
508 for (sc_it = list_top(dpy->screens); sc_it; sc_it = sc_it->next) {
509 d_screen_t *sc = sc_it->data;
511 for (it = list_top(sc->stacking); it; it = it->next) {
512 if (window_is_mapped(it->data))
513 sc->window_hide(it->data);
518 cleanup_functions(dpy);
525 dcompmgr_running(void)