handle configure notify events
[dana/dcompmgr.git] / window.c
1 #include "window.h"
2 #include "screen.h"
3 #include "display.h"
4 #include <stdlib.h>
5 #include <stdio.h>
6 #include <xcb/composite.h>
7
8 typedef struct {
9     /* public stuff */
10     xcb_window_t     id;
11     struct d_screen *sc;
12
13     /* private stuff */
14     int              ref;
15
16     /* queried things, don't read them directly from the struct */
17     int              x, y, w, h;
18     gboolean         mapped;
19     gboolean         input_only;
20
21     gboolean         zombie;
22
23     int              opacity;
24
25     xcb_pixmap_t     pixmap;
26
27     xcb_get_window_attributes_cookie_t ck_get_attr;
28     xcb_get_geometry_cookie_t          ck_get_geom;
29     xcb_void_cookie_t                  ck_get_pixmap;
30 } d_window_priv_t;
31
32 static void window_get_attributes_reply(d_window_priv_t *w);
33 static void window_get_geometry_reply(d_window_priv_t *w);
34
35 d_window_t*
36 window_new(xcb_window_t id, struct d_screen *sc)
37 {
38     d_window_priv_t *w;
39
40     w = malloc(sizeof(d_window_priv_t));
41     w->id = id;
42     w->ref = 1;
43     w->sc = sc;
44     w->zombie = FALSE;
45     w->opacity = WINDOW_OPACITY_MAX;
46     w->pixmap = XCB_NONE;
47
48     screen_stacking_add(sc, (d_window_t*)w);
49
50     w->ck_get_attr = xcb_get_window_attributes(sc->dpy->conn, id);
51     w->ck_get_geom = xcb_get_geometry(sc->dpy->conn, id);
52
53     w->ck_get_pixmap.sequence = 0;
54
55     //printf("new window 0x%x\n", w->id);
56
57     return (d_window_t*)w;
58 }
59
60 void
61 window_ref(d_window_t *pubw)
62 {
63     d_window_priv_t *w = (d_window_priv_t*)pubw;
64
65     ++w->ref;
66 }
67
68 void
69 window_unref(d_window_t *pubw)
70 {
71     d_window_priv_t *w = (d_window_priv_t*)pubw;
72
73     if (w && --w->ref == 0) {
74         xcb_pixmap_t p;
75
76         screen_stacking_remove(w->sc, (d_window_t*)w);
77
78         if ((p = window_get_pixmap(pubw))) {
79             xcb_free_pixmap(w->sc->dpy->conn, p);
80             w->pixmap = XCB_NONE;
81         }
82
83         free(w);
84     }
85 }
86
87 void
88 window_show(d_window_t *pubw)
89 {
90     d_window_priv_t *w = (d_window_priv_t*)pubw;
91     xcb_pixmap_t p;
92
93     if (window_is_mapped(pubw)) return;
94
95     printf("show window 0x%x\n", w->id);
96
97     /* XXX can we save it for until we get the new pixmap? */
98     if ((p = window_get_pixmap(pubw))) {
99         xcb_free_pixmap(w->sc->dpy->conn, p);
100         w->pixmap = XCB_NONE;
101     }
102
103     w->mapped = TRUE;
104     w->pixmap = xcb_generate_id(w->sc->dpy->conn);
105     w->ck_get_pixmap = 
106         xcb_composite_name_window_pixmap_checked(w->sc->dpy->conn,
107                                                  w->id, w->pixmap);
108     xcb_flush(w->sc->dpy->conn);
109 }
110
111 void
112 window_hide(d_window_t *pubw)
113 {
114     d_window_priv_t *w = (d_window_priv_t*)pubw;
115
116     if (!window_is_mapped(pubw)) return;
117
118     printf("hide window 0x%x\n", w->id);
119
120     w->mapped = FALSE;
121 }
122
123 void
124 window_become_zombie(d_window_t *pubw)
125 {
126     d_window_priv_t *w = (d_window_priv_t*)pubw;
127
128     if (w->zombie) return;
129
130     w->zombie = TRUE;
131 }
132
133 gboolean
134 window_is_zombie(d_window_t *pubw)
135 {
136     d_window_priv_t *w = (d_window_priv_t*)pubw;
137     return w->zombie;
138 }
139
140 gboolean
141 window_is_input_only(d_window_t *pubw)
142 {
143     d_window_priv_t *w = (d_window_priv_t*)pubw;
144     if (w->ck_get_attr.sequence)
145         window_get_attributes_reply(w);
146     return w->input_only;
147 }
148
149 void
150 window_get_area(d_window_t *pubw, int *x, int *y, int *width, int *height)
151 {
152     d_window_priv_t *w = (d_window_priv_t*)pubw;
153     if (w->ck_get_geom.sequence)
154         window_get_geometry_reply(w);
155     *x = w->x;
156     *y = w->y;
157     *width = w->w;
158     *height = w->h;
159 }
160
161 static void
162 window_get_attributes_reply(d_window_priv_t *w)
163 {
164     xcb_get_window_attributes_reply_t *rep;
165     xcb_generic_error_t *err = NULL;
166
167     rep = xcb_get_window_attributes_reply(w->sc->dpy->conn,
168                                           w->ck_get_attr,
169                                           &err);
170
171     if (rep) {
172         w->input_only = rep->_class == XCB_WINDOW_CLASS_INPUT_ONLY;
173         w->mapped = rep->map_state != XCB_MAP_STATE_UNMAPPED;
174         free(rep);
175     }
176     else {
177         w->input_only = TRUE;
178         w->mapped = FALSE;
179     }
180     if (err) {
181         printf("error getting attributes for window 0x%x\n", w->id);
182         free(err);
183     }
184     w->ck_get_attr.sequence = 0;
185 }
186
187 static void
188 window_get_geometry_reply(d_window_priv_t *w)
189 {
190     xcb_get_geometry_reply_t *rep;
191     xcb_generic_error_t *err = NULL;
192
193     rep = xcb_get_geometry_reply(w->sc->dpy->conn,
194                                  w->ck_get_geom,
195                                  &err);
196
197     if (rep) {
198         w->x = rep->x;
199         w->y = rep->y;
200         w->w = rep->width + rep->border_width * 2;
201         w->h = rep->height + rep->border_width * 2;
202         free(rep);
203     }
204     else {
205         w->x = w->y = -1;
206         w->w = w->h = 1;
207     }
208     if (err) {
209         printf("error getting geometry for window 0x%x\n", w->id);
210         free(err);
211     }
212     w->ck_get_geom.sequence = 0;
213 }
214
215 gboolean
216 window_is_mapped(d_window_t *pubw)
217 {
218     d_window_priv_t *w = (d_window_priv_t*)pubw;
219     if (w->ck_get_attr.sequence)
220         window_get_attributes_reply(w);
221     return w->mapped;
222 }
223
224 xcb_pixmap_t
225 window_get_pixmap(d_window_t *pubw)
226 {
227     d_window_priv_t *w = (d_window_priv_t*)pubw;
228
229     if (w->ck_get_pixmap.sequence) {
230         xcb_generic_error_t *err;
231         //printf("** checking get pixmap 0x%x\n", w->id);
232         err = xcb_request_check(w->sc->dpy->conn, w->ck_get_pixmap);
233         if (err) {
234             printf("error getting named pixmap for window 0x%x\n", w->id);
235             free(err);
236         }
237         w->pixmap = XCB_NONE;
238     }
239     //printf("returning pixmap 0x%x for window 0x%x\n", w->pixmap, w->id);
240     return w->pixmap;
241 }
242
243 void
244 window_configure(d_window_t *pubw, int x, int y, int width, int height,
245                  int border_width)
246 {
247     d_window_priv_t *w = (d_window_priv_t*)pubw;
248
249     /* this overrides any reply from our get_geometry call */
250     if (w->ck_get_geom.sequence)
251         w->ck_get_geom.sequence = 0;
252     w->x = x;
253     w->y = y;
254     w->w = width + border_width * 2;
255     w->h = height + border_width * 2;
256 }