remove a todo comment that is done
[dana/dcompmgr.git] / dcompmgr.c
1 #include "screen.h"
2 #include "window.h"
3 #include "list.h"
4 #include "display.h"
5 #include "gettext.h"
6 #include "time.h"
7 #include "render.h"
8
9 #include <glib.h>
10 #include <stdio.h>
11 #include <sys/select.h>
12 #include <stdlib.h>
13 #include <string.h>
14 #include <xcb/xcb.h>
15
16 typedef struct {
17     int foo;
18 } d_options_t;
19
20 static void
21 read_options(int argc, char **argv, d_options_t *opts)
22 {
23     opts->foo = argc && argv;
24 }
25
26 static void
27 event(d_display_t *dpy)
28 {
29     xcb_generic_event_t *ev;
30
31     while ((ev = xcb_poll_for_event(dpy->conn))) {
32         //printf("event %d\n", ev->response_type);
33
34         if (!ev->response_type) {
35             display_error(dpy, (xcb_generic_error_t*)ev);
36             free(ev);
37             continue;
38         }
39
40         switch (ev->response_type) {
41         case XCB_CREATE_NOTIFY:
42         {
43             xcb_create_notify_event_t *cev;
44             d_screen_t *sc;
45
46             cev = (xcb_create_notify_event_t*)ev;
47             sc = display_screen_from_root(dpy, cev->parent);
48             if (!sc) break;
49             screen_add_window(sc, cev->window);
50             break;
51         }
52         case XCB_DESTROY_NOTIFY:
53         {
54             xcb_destroy_notify_event_t *dev;
55             d_screen_t *sc;
56             d_window_t *w;
57
58             dev = (xcb_destroy_notify_event_t*)ev;
59             sc = display_screen_from_root(dpy, dev->event);
60             if (!sc) break;
61             w = screen_find_window(sc, dev->window);
62             sc->window_hide(w);
63             screen_remove_window(sc, w);
64             printf("** refresh needed **\n");
65             screen_refresh(sc);
66             break;
67         }
68         case XCB_REPARENT_NOTIFY:
69         {
70             xcb_reparent_notify_event_t *rev;
71             d_screen_t *sc;
72             d_window_t *w;
73
74             rev = (xcb_reparent_notify_event_t*)ev;
75             sc = display_screen_from_root(dpy, rev->event);
76             if (!sc) break;
77             w = screen_find_window(sc, rev->window);
78             if (rev->parent == sc->super.root)
79                 screen_add_window(sc, rev->window);
80             else {
81                 sc->window_hide(w);
82                 screen_remove_window(sc, w);
83             }
84             break;
85         }
86         case XCB_MAP_NOTIFY:
87         {
88             xcb_map_notify_event_t *mev;
89             d_screen_t *sc;
90             d_window_t *w;
91
92             mev = (xcb_map_notify_event_t*)ev;
93             sc = display_screen_from_root(dpy, mev->event);
94             if (!sc) break;
95             w = screen_find_window(sc, mev->window);
96             sc->window_show(w);
97             break;
98         }
99         case XCB_UNMAP_NOTIFY:
100         {
101             xcb_unmap_notify_event_t *mev;
102             d_screen_t *sc;
103             d_window_t *w;
104
105             mev = (xcb_unmap_notify_event_t*)ev;
106             sc = display_screen_from_root(dpy, mev->event);
107             if (!sc) break;
108             w = screen_find_window(sc, mev->window);
109             sc->window_hide(w);
110             break;
111         }
112         default:
113             break;
114         }
115         free(ev);
116     }
117 }
118
119 static void
120 paint(d_display_t *dpy)
121 {
122     d_list_it_t *it;
123     struct timeval now;
124
125     gettimeofday(&now, NULL);
126     
127     for (it = list_top(dpy->screens); it; it = it->next) {
128         d_screen_t *sc = it->data;
129
130         if (time_compare(&sc->next_repaint, &now) <= 0)
131             sc->screen_paint(sc);
132     }
133 }
134
135 static void
136 run(d_display_t *dpy)
137 {
138     gboolean quit;
139
140     paint(dpy);
141
142     quit = FALSE;
143     while (!quit) {
144         struct timeval next, now, *wait;
145         int            r, npaint;
146         d_list_it_t   *it;
147         fd_set         fds;
148
149         npaint = 0;
150         for (it = list_top(dpy->screens); it; it = it->next) {
151             d_screen_t *sc = it->data;
152             if (sc->need_repaint &&
153                 (!npaint || time_compare(&sc->next_repaint, &next) < 0))
154             {
155                 next = sc->next_repaint;
156                 ++npaint;
157             }
158         }
159
160         gettimeofday(&now, 0);
161
162         if (!npaint)
163             /* wait forever, there is nothing that needs drawing */
164             wait = NULL;
165         else if (time_compare(&next, &now) > 0) {
166             /* wait until the next allowed redraw time */
167             time_difference(&next, &now, &next);
168             wait = &next;
169         }
170         else {
171             /* don't wait cuz a redraw is due now already */
172             next.tv_sec = 0;
173             next.tv_usec = 0;
174             wait = &next;
175         }
176
177         FD_ZERO(&fds);
178         FD_SET(dpy->fd, &fds);
179
180         r = select(dpy->fd+1, &fds, NULL, NULL, wait);
181         if (r < 0)
182             printf("select error\n");
183         else if (r == 0) {
184             //printf("select timeout\n");
185             paint(dpy);
186         }
187         else {
188             //printf("select data\n");
189             /*if (FD_ISSET(dpy->fd, &fds))*/ {
190                 event(dpy);
191             }
192         }
193
194         if (xcb_connection_has_error(dpy->conn))
195             quit = TRUE;
196         else
197             xcb_flush(dpy->conn);
198     }
199 }
200
201 static void
202 setup_functions(d_display_t *dpy)
203 {
204     d_list_it_t *it;
205
206     for (it = list_top(dpy->screens); it; it = it->next) {
207         d_screen_t *sc = it->data;
208         screen_setup_default_functions(sc);
209
210         /* these can be plugins.. */
211         render_init(sc);
212     }
213 }
214
215 static void
216 cleanup_functions(d_display_t *dpy)
217 {
218     d_list_it_t *it;
219
220     for (it = list_top(dpy->screens); it; it = it->next) {
221         d_screen_t *sc = it->data;
222
223         /* these can be plugins.. */
224         render_free(sc);
225     }
226 }
227
228 int
229 main(int argc, char **argv)
230 {
231     d_display_t         *dpy;
232     d_options_t          opts;
233
234     read_options(argc, argv, &opts);
235
236     dpy = display_open(NULL);
237     if (!dpy) {
238         printf(_("Unable to connect to display\n"));
239         return 1;
240     }
241
242     if (!dpy->composite.present) {
243         printf(_("no composite extension present on the display\n"));
244         display_unref(dpy);
245         return 1;
246     }
247     if (!dpy->xfixes.present) {
248         printf(_("no xfixes extension present on the display\n"));
249         display_unref(dpy);
250         return 1;
251     }
252     if (!dpy->damage.present) {
253         printf(_("no damage extension present on the display\n"));
254         display_unref(dpy);
255         return 1;
256     }
257     if (!dpy->render.present) {
258         printf(_("no render extension present on the display\n"));
259         display_unref(dpy);
260         return 1;
261     }
262     if (dpy->composite.major_version <= 0 && dpy->composite.minor_version < 3)
263     {
264         printf(_("composite extension does not support the overlay window"));
265         display_unref(dpy);
266         return 1;
267     }
268
269     if (!display_claim_screens(dpy)) {
270         printf(_("found no screens to run on\n"));
271         display_unref(dpy);
272         return 0;
273     }
274
275     setup_functions(dpy);
276
277     {
278         /* some of the windows may already be visible */
279         d_list_it_t *sc_it;
280
281         for (sc_it = list_top(dpy->screens); sc_it; sc_it = sc_it->next) {
282             d_screen_t *sc = sc_it->data;
283             d_list_it_t *it;
284             for (it = list_top(sc->stacking); it; it = it->next)
285                 if (window_is_mapped(it->data))
286                     sc->window_show(it->data);
287         }
288     }
289
290     run(dpy);
291
292     cleanup_functions(dpy);
293
294     display_unref(dpy);
295     return 0;
296 }