use the list for holding all the managed screens in the display. limit the number...
[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     fd_set   fds;
140     int      max = -1;
141
142     FD_ZERO(&fds);
143     FD_SET(dpy->fd, &fds);
144     max = MAX(max, dpy->fd);
145
146     paint(dpy);
147
148     quit = FALSE;
149     while (!quit) {
150         struct timeval next, now, *wait;
151         int            r, npaint;
152         d_list_it_t   *it;
153
154         npaint = 0;
155         for (it = list_top(dpy->screens); it; it = it->next) {
156             d_screen_t *sc = it->data;
157             if (sc->need_repaint &&
158                 (!npaint || time_compare(&sc->next_repaint, &next) < 0))
159             {
160                 next = sc->next_repaint;
161                 ++npaint;
162             }
163         }
164
165         gettimeofday(&now, 0);
166
167         printf("* loop paint %d *\n", npaint);
168
169         if (!npaint)
170             /* wait forever, there is nothing that needs drawing */
171             wait = NULL;
172         else if (time_compare(&next, &now) > 0) {
173             /* wait until the next allowed redraw time */
174             time_difference(&next, &now, &next);
175             wait = &next;
176         }
177         else {
178             /* don't wait cuz a redraw is due now already */
179             next.tv_sec = 0;
180             next.tv_usec = 1;
181             wait = &next;
182         }
183
184         r = select(max+1, &fds, NULL, NULL, wait);
185         if (r < 0)
186             printf("select error\n");
187         else if (r == 0) {
188             printf("select timeout\n");
189             paint(dpy);
190         }
191         else {
192             printf("select data\n");
193             /*if (FD_ISSET(dpy->fd, &fds))*/ {
194                 event(dpy);
195             }
196         }
197
198         if (xcb_connection_has_error(dpy->conn))
199             quit = TRUE;
200     }
201 }
202
203 static void
204 setup_functions(d_display_t *dpy)
205 {
206     d_list_it_t *it;
207
208     for (it = list_top(dpy->screens); it; it = it->next) {
209         d_screen_t *sc = it->data;
210         screen_setup_default_functions(sc);
211
212         /* these can be plugins.. */
213         render_init(sc);
214     }
215 }
216
217 static void
218 cleanup_functions(d_display_t *dpy)
219 {
220     d_list_it_t *it;
221
222     for (it = list_top(dpy->screens); it; it = it->next) {
223         d_screen_t *sc = it->data;
224
225         /* these can be plugins.. */
226         render_free(sc);
227     }
228 }
229
230 int
231 main(int argc, char **argv)
232 {
233     d_display_t         *dpy;
234     d_options_t          opts;
235
236     read_options(argc, argv, &opts);
237
238     dpy = display_open(NULL);
239     if (!dpy) {
240         printf(_("Unable to connect to display\n"));
241         return 1;
242     }
243
244     if (!dpy->composite.present) {
245         printf(_("no composite extension present on the display\n"));
246         display_unref(dpy);
247         return 1;
248     }
249     if (!dpy->xfixes.present) {
250         printf(_("no xfixes extension present on the display\n"));
251         display_unref(dpy);
252         return 1;
253     }
254     if (!dpy->damage.present) {
255         printf(_("no damage extension present on the display\n"));
256         display_unref(dpy);
257         return 1;
258     }
259     if (!dpy->render.present) {
260         printf(_("no render extension present on the display\n"));
261         display_unref(dpy);
262         return 1;
263     }
264     if (dpy->composite.major_version <= 0 && dpy->composite.minor_version < 3)
265     {
266         printf(_("composite extension does not support the overlay window"));
267         display_unref(dpy);
268         return 1;
269     }
270
271     if (!display_claim_screens(dpy)) {
272         printf(_("found no screens to run on\n"));
273         display_unref(dpy);
274         return 0;
275     }
276
277     setup_functions(dpy);
278
279     run(dpy);
280
281     cleanup_functions(dpy);
282
283     display_unref(dpy);
284     return 0;
285 }