handle configure notify events
[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             gboolean vis;
58
59             dev = (xcb_destroy_notify_event_t*)ev;
60             sc = display_screen_from_root(dpy, dev->event);
61             if (!sc) break;
62             w = screen_find_window(sc, dev->window);
63             vis = window_is_mapped(w);
64             sc->window_hide(w);
65             screen_remove_window(sc, w);
66             if (vis) screen_refresh(sc);
67             break;
68         }
69         case XCB_REPARENT_NOTIFY:
70         {
71             xcb_reparent_notify_event_t *rev;
72             d_screen_t *sc;
73             d_window_t *w;
74
75             rev = (xcb_reparent_notify_event_t*)ev;
76             sc = display_screen_from_root(dpy, rev->event);
77             if (!sc) break;
78             w = screen_find_window(sc, rev->window);
79             if (rev->parent == sc->super.root)
80                 screen_add_window(sc, rev->window);
81             else {
82                 sc->window_hide(w);
83                 screen_remove_window(sc, w);
84             }
85             screen_refresh(w->sc);
86             break;
87         }
88         case XCB_MAP_NOTIFY:
89         {
90             xcb_map_notify_event_t *mev;
91             d_screen_t *sc;
92             d_window_t *w;
93
94             mev = (xcb_map_notify_event_t*)ev;
95             sc = display_screen_from_root(dpy, mev->event);
96             if (!sc) break;
97             w = screen_find_window(sc, mev->window);
98             sc->window_show(w);
99             screen_refresh(w->sc);
100             break;
101         }
102         case XCB_UNMAP_NOTIFY:
103         {
104             xcb_unmap_notify_event_t *mev;
105             d_screen_t *sc;
106             d_window_t *w;
107
108             mev = (xcb_unmap_notify_event_t*)ev;
109             sc = display_screen_from_root(dpy, mev->event);
110             if (!sc) break;
111             w = screen_find_window(sc, mev->window);
112             sc->window_hide(w);
113             screen_refresh(w->sc);
114             break;
115         }
116         case XCB_CONFIGURE_NOTIFY:
117         {
118             xcb_configure_notify_event_t *cev;
119             d_screen_t *sc;
120             d_window_t *w, *above;
121
122             cev = (xcb_configure_notify_event_t*)ev;
123             sc = display_screen_from_root(dpy, cev->event);
124             if (!sc) break;
125             w = screen_find_window(sc, cev->window);
126             sc->window_configure(w, cev->x, cev->y,
127                                  cev->width, cev->height, cev->border_width);
128             above = screen_find_window(sc, cev->above_sibling);
129             screen_stacking_move_above(sc, w, above);
130             screen_refresh(w->sc);
131             break;
132         }
133         default:
134             break;
135         }
136         free(ev);
137     }
138 }
139
140 static void
141 paint(d_display_t *dpy)
142 {
143     d_list_it_t *it;
144     struct timeval now;
145
146     gettimeofday(&now, NULL);
147     
148     for (it = list_top(dpy->screens); it; it = it->next) {
149         d_screen_t *sc = it->data;
150
151         if (time_compare(&sc->next_repaint, &now) <= 0)
152             sc->screen_paint(sc);
153     }
154 }
155
156 static void
157 run(d_display_t *dpy)
158 {
159     gboolean quit;
160
161     paint(dpy);
162
163     quit = FALSE;
164     while (!quit) {
165         struct timeval next, now, *wait;
166         int            r, npaint;
167         d_list_it_t   *it;
168         fd_set         fds;
169
170         npaint = 0;
171         for (it = list_top(dpy->screens); it; it = it->next) {
172             d_screen_t *sc = it->data;
173             if (sc->need_repaint &&
174                 (!npaint || time_compare(&sc->next_repaint, &next) < 0))
175             {
176                 next = sc->next_repaint;
177                 ++npaint;
178             }
179         }
180
181         gettimeofday(&now, 0);
182
183         if (!npaint)
184             /* wait forever, there is nothing that needs drawing */
185             wait = NULL;
186         else if (time_compare(&next, &now) > 0) {
187             /* wait until the next allowed redraw time */
188             time_difference(&next, &now, &next);
189             wait = &next;
190         }
191         else {
192             /* don't wait cuz a redraw is due now already */
193             next.tv_sec = 0;
194             next.tv_usec = 0;
195             wait = &next;
196         }
197
198         FD_ZERO(&fds);
199         FD_SET(dpy->fd, &fds);
200
201         r = select(dpy->fd+1, &fds, NULL, NULL, wait);
202         if (r < 0)
203             printf("select error\n");
204         else if (r == 0) {
205             //printf("select timeout\n");
206             paint(dpy);
207         }
208         else {
209             //printf("select data\n");
210             /*if (FD_ISSET(dpy->fd, &fds))*/ {
211                 event(dpy);
212             }
213         }
214
215         if (xcb_connection_has_error(dpy->conn))
216             quit = TRUE;
217         else
218             xcb_flush(dpy->conn);
219     }
220 }
221
222 static void
223 setup_functions(d_display_t *dpy)
224 {
225     d_list_it_t *it;
226
227     for (it = list_top(dpy->screens); it; it = it->next) {
228         d_screen_t *sc = it->data;
229         screen_setup_default_functions(sc);
230
231         /* these can be plugins.. */
232         render_init(sc);
233     }
234 }
235
236 static void
237 cleanup_functions(d_display_t *dpy)
238 {
239     d_list_it_t *it;
240
241     for (it = list_top(dpy->screens); it; it = it->next) {
242         d_screen_t *sc = it->data;
243
244         /* these can be plugins.. */
245         render_free(sc);
246     }
247 }
248
249 int
250 main(int argc, char **argv)
251 {
252     d_display_t         *dpy;
253     d_options_t          opts;
254
255     read_options(argc, argv, &opts);
256
257     dpy = display_open(NULL);
258     if (!dpy) {
259         printf(_("Unable to connect to display\n"));
260         return 1;
261     }
262
263     if (!dpy->composite.present) {
264         printf(_("no composite extension present on the display\n"));
265         display_unref(dpy);
266         return 1;
267     }
268     if (!dpy->xfixes.present) {
269         printf(_("no xfixes extension present on the display\n"));
270         display_unref(dpy);
271         return 1;
272     }
273     if (!dpy->damage.present) {
274         printf(_("no damage extension present on the display\n"));
275         display_unref(dpy);
276         return 1;
277     }
278     if (!dpy->render.present) {
279         printf(_("no render extension present on the display\n"));
280         display_unref(dpy);
281         return 1;
282     }
283     if (dpy->composite.major_version <= 0 && dpy->composite.minor_version < 3)
284     {
285         printf(_("composite extension does not support the overlay window"));
286         display_unref(dpy);
287         return 1;
288     }
289
290     if (!display_claim_screens(dpy)) {
291         printf(_("found no screens to run on\n"));
292         display_unref(dpy);
293         return 0;
294     }
295
296     setup_functions(dpy);
297
298     {
299         /* some of the windows may already be visible */
300         d_list_it_t *sc_it;
301
302         for (sc_it = list_top(dpy->screens); sc_it; sc_it = sc_it->next) {
303             d_screen_t *sc = sc_it->data;
304             d_list_it_t *it;
305             for (it = list_top(sc->stacking); it; it = it->next)
306                 if (window_is_mapped(it->data))
307                     sc->window_show(it->data);
308         }
309     }
310
311     run(dpy);
312
313     cleanup_functions(dpy);
314
315     display_unref(dpy);
316     return 0;
317 }