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;
185 pev = (xcb_property_notify_event_t*)ev;
186 if (pev->atom == dpy->a.xrootpmap_id ||
187 pev->atom == dpy->a.esetroot_pmap_id ||
188 pev->atom == dpy->a.xsetroot_id)
192 sc = display_screen_from_root(dpy, pev->window);
193 if (sc) sc->screen_root_pixmap_change(sc);
195 else if (pev->atom == dpy->a.net_wm_window_opacity) {
198 for (it = list_top(dpy->screens); it; it = it->next) {
199 d_screen_t *sc = it->data;
202 w = screen_find_window(sc, pev->window);
204 window_update_user_opacity(w);
205 if (window_is_mapped(w)) {
206 sc->window_opacity_change(w);
207 screen_refresh(w->sc);
216 if (ev->response_type - dpy->damage.event == XCB_DAMAGE_NOTIFY) {
217 xcb_damage_notify_event_t *dev;
220 dev = (xcb_damage_notify_event_t*)ev;
221 for (it = list_top(dpy->screens); it; it = it->next) {
222 d_screen_t *sc = it->data;
225 w = screen_find_window(sc, dev->drawable);
227 screen_refresh(w->sc);
231 xcb_damage_subtract(dpy->conn, dev->damage,
234 else if (dpy->shape.present &&
235 ev->response_type - dpy->shape.event == XCB_SHAPE_NOTIFY)
237 xcb_shape_notify_event_t *sev;
240 sev = (xcb_shape_notify_event_t*)ev;
241 for (it = list_top(dpy->screens); it; it = it->next) {
242 d_screen_t *sc = it->data;
245 w = screen_find_window(sc, sev->affected_window);
247 sc->window_reshape(w);
248 screen_refresh(w->sc);
256 xcb_flush(dpy->conn);
261 paint(d_display_t *dpy)
266 gettimeofday(&now, NULL);
268 for (it = list_top(dpy->screens); it; it = it->next) {
269 d_screen_t *sc = it->data;
271 if (time_compare(&sc->next_repaint, &now) <= 0)
272 sc->screen_paint(sc);
277 run(d_display_t *dpy)
280 struct timeval next, now, *wait;
288 for (it = list_top(dpy->screens); it; it = it->next) {
289 d_screen_t *sc = it->data;
290 if (sc->need_repaint &&
291 (!npaint || time_compare(&sc->next_repaint, &next) < 0))
293 next = sc->next_repaint;
298 gettimeofday(&now, 0);
301 /* wait forever, there is nothing that needs drawing */
303 else if (time_compare(&next, &now) > 0) {
304 /* wait until the next allowed redraw time */
305 time_difference(&next, &now, &next);
309 /* don't wait cuz a redraw is due now already */
316 FD_SET(dpy->fd, &fds);
318 //printf("select %d\n", npaint);
320 r = select(dpy->fd+1, &fds, NULL, NULL, wait);
322 //printf("select timeout\n");
324 xcb_flush(dpy->conn);
327 if (xcb_connection_has_error(dpy->conn))
333 setup_functions(d_display_t *dpy)
337 for (it = list_top(dpy->screens); it; it = it->next) {
338 d_screen_t *sc = it->data;
340 screen_setup_default_functions(sc);
342 /* these can be plugins.. */
344 render_init(sc, id++);
349 cleanup_functions(d_display_t *dpy)
353 for (it = list_top(dpy->screens); it; it = it->next) {
354 d_screen_t *sc = it->data;
356 /* these can be plugins.. */
362 main(int argc, char **argv)
367 read_options(argc, argv, &opts);
369 dpy = display_open(NULL);
371 printf(_("Unable to connect to display\n"));
375 if (!dpy->composite.present) {
376 printf(_("no composite extension present on the display\n"));
380 if (!dpy->xfixes.present) {
381 printf(_("no xfixes extension present on the display\n"));
385 if (!dpy->damage.present) {
386 printf(_("no damage extension present on the display\n"));
390 if (!dpy->render.present) {
391 printf(_("no render extension present on the display\n"));
395 if (dpy->composite.major_version <= 0 && dpy->composite.minor_version < 3)
397 printf(_("composite extension does not support the overlay window"));
402 if (!display_claim_screens(dpy)) {
403 printf(_("found no screens to run on\n"));
408 signal(SIGINT, signal_quit_handler);
409 signal(SIGHUP, signal_quit_handler);
410 signal(SIGTERM, signal_quit_handler);
411 signal(SIGQUIT, signal_quit_handler);
413 setup_functions(dpy);
416 /* some of the windows may already be visible */
419 for (sc_it = list_top(dpy->screens); sc_it; sc_it = sc_it->next) {
420 d_screen_t *sc = sc_it->data;
422 for (it = list_bottom(sc->stacking); it; it = it->prev)
423 if (window_is_attr_mapped(it->data))
424 sc->window_show(it->data);
431 /* make everything hidden */
434 for (sc_it = list_top(dpy->screens); sc_it; sc_it = sc_it->next) {
435 d_screen_t *sc = sc_it->data;
437 for (it = list_top(sc->stacking); it; it = it->next) {
438 if (window_is_mapped(it->data))
439 sc->window_hide(it->data);
444 cleanup_functions(dpy);