11 #include <xcb/composite.h>
12 #include <xcb/damage.h>
22 /* queried things, don't read them directly from the struct */
27 xcb_visualid_t visual;
29 xcb_xfixes_region_t region;
36 d_list_t *plugin_data;
38 xcb_damage_damage_t damage;
40 gboolean waiting_attr;
41 xcb_get_window_attributes_cookie_t ck_get_attr;
42 gboolean waiting_geom;
43 xcb_get_geometry_cookie_t ck_get_geom;
46 static void window_get_attributes_reply(d_window_priv_t *w);
47 static void window_get_geometry_reply(d_window_priv_t *w);
48 static void window_update_pixmap(d_window_priv_t *w);
49 static void window_update_region(d_window_priv_t *w);
52 window_new(xcb_window_t id, struct d_screen *sc)
56 w = malloc(sizeof(d_window_priv_t));
66 screen_stacking_add(sc, (d_window_t*)w);
68 w->ck_get_attr = xcb_get_window_attributes(sc->dpy->conn, id);
69 w->waiting_attr = TRUE;
71 w->ck_get_geom = xcb_get_geometry(sc->dpy->conn, id);
72 w->waiting_geom = TRUE;
74 w->plugin_data = list_new();
76 //printf("new window 0x%x\n", w->id);
78 return (d_window_t*)w;
82 window_ref(d_window_t *pubw)
84 d_window_priv_t *w = (d_window_priv_t*)pubw;
90 window_unref(d_window_t *pubw)
92 d_window_priv_t *w = (d_window_priv_t*)pubw;
94 if (w && --w->ref == 0) {
95 screen_stacking_remove(w->sc, (d_window_t*)w);
98 xcb_xfixes_destroy_region(w->sc->dpy->conn, w->region);
103 /* this may cause an error if the pixmap was never valid, but
105 xcb_free_pixmap(w->sc->dpy->conn, w->pixmap);
106 w->pixmap = XCB_NONE;
109 list_unref(w->plugin_data);
115 window_get_pixmap(d_window_t *pubw)
117 d_window_priv_t *w = (d_window_priv_t*)pubw;
123 window_update_region(d_window_priv_t *w)
125 int x, y, wi, hei, bw;
127 if (window_is_zombie((d_window_t*)w)) return;
130 xcb_xfixes_destroy_region(w->sc->dpy->conn, w->region);
131 w->region = XCB_NONE;
134 w->region = xcb_generate_id(w->sc->dpy->conn);
135 xcb_xfixes_create_region_from_window(w->sc->dpy->conn, w->region,
136 w->id, XCB_SHAPE_SK_BOUNDING);
137 window_get_area((d_window_t*)w, &x, &y, &wi, &hei, &bw);
138 xcb_xfixes_translate_region(w->sc->dpy->conn, w->region, x+bw, y+bw);
142 window_update_pixmap(d_window_priv_t *w)
144 if (window_is_zombie((d_window_t*)w)) return;
146 /* the pixmap may not be valid even though it is non-zero, but
147 we can free it anyways and let it fail. we don't need to wait
148 for a response from the server */
150 xcb_free_pixmap(w->sc->dpy->conn, w->pixmap);
151 w->pixmap = XCB_NONE;
154 //printf("updating pixmap for 0x%x\n", w->id);
156 /* we don't check the result of this call, because it seems that sometimes
157 the X server just doesn't reply. if we check it, we end up hanging
158 sometimes waiting for the reply */
159 w->pixmap = xcb_generate_id(w->sc->dpy->conn);
160 xcb_composite_name_window_pixmap(w->sc->dpy->conn, w->id, w->pixmap);
161 //printf("requested pixmap sequence %u\n", w->ck_get_pixmap.sequence);
163 xcb_flush(w->sc->dpy->conn);
167 window_show(d_window_t *pubw)
169 d_window_priv_t *w = (d_window_priv_t*)pubw;
173 //printf("show window 0x%x\n", w->id);
175 /* make sure this is before we update the window's region */
176 if (w->sc->dpy->shape.present)
177 xcb_shape_select_input(w->sc->dpy->conn, w->id, TRUE);
179 window_update_pixmap(w);
180 window_update_region(w);
185 window_hide(d_window_t *pubw)
187 d_window_priv_t *w = (d_window_priv_t*)pubw;
191 //printf("hide window 0x%x\n", w->id);
192 if (w->sc->dpy->shape.present)
193 xcb_shape_select_input(w->sc->dpy->conn, w->id, FALSE);
199 window_fake_unmapped(d_window_t *pubw)
201 d_window_priv_t *w = (d_window_priv_t*)pubw;
207 window_become_zombie(d_window_t *pubw)
209 d_window_priv_t *w = (d_window_priv_t*)pubw;
211 if (w->zombie) return;
217 window_is_zombie(d_window_t *pubw)
219 d_window_priv_t *w = (d_window_priv_t*)pubw;
224 window_is_input_only(d_window_t *pubw)
226 d_window_priv_t *w = (d_window_priv_t*)pubw;
228 window_get_attributes_reply(w);
229 return w->input_only;
233 window_get_area(d_window_t *pubw, int *x, int *y, int *width, int *height,
236 d_window_priv_t *w = (d_window_priv_t*)pubw;
238 window_get_geometry_reply(w);
243 *border_width = w->bw;
247 window_get_attributes_reply(d_window_priv_t *w)
249 xcb_get_window_attributes_reply_t *rep;
250 xcb_generic_error_t *err = NULL;
252 rep = xcb_get_window_attributes_reply(w->sc->dpy->conn,
257 w->input_only = rep->_class == XCB_WINDOW_CLASS_INPUT_ONLY;
258 w->attr_mapped = rep->map_state != XCB_MAP_STATE_UNMAPPED;
259 w->visual = rep->visual;
260 //printf("0x%x attributes mapped %d\n", w->id, w->mapped);
264 w->input_only = TRUE;
265 w->attr_mapped = FALSE;
266 w->visual = XCB_NONE;
269 printf("error getting attributes for window 0x%x\n", w->id);
272 w->waiting_attr = FALSE;
276 window_get_geometry_reply(d_window_priv_t *w)
278 xcb_get_geometry_reply_t *rep;
279 xcb_generic_error_t *err = NULL;
281 rep = xcb_get_geometry_reply(w->sc->dpy->conn,
290 w->bw = rep->border_width;
291 w->argb = rep->depth == 32;
301 printf("error getting geometry for window 0x%x\n", w->id);
304 w->waiting_geom = FALSE;
308 window_is_mapped(d_window_t *pubw)
310 d_window_priv_t *w = (d_window_priv_t*)pubw;
315 window_is_attr_mapped(d_window_t *pubw)
317 d_window_priv_t *w = (d_window_priv_t*)pubw;
319 window_get_attributes_reply(w);
320 return w->attr_mapped;
324 window_is_argb(d_window_t *pubw)
326 d_window_priv_t *w = (d_window_priv_t*)pubw;
328 window_get_geometry_reply(w);
333 window_get_visual(d_window_t *pubw)
335 d_window_priv_t *w = (d_window_priv_t*)pubw;
337 window_get_attributes_reply(w);
342 window_get_region(d_window_t *pubw)
344 d_window_priv_t *w = (d_window_priv_t*)pubw;
350 window_configure(d_window_t *pubw, int x, int y, int width, int height,
353 d_window_priv_t *w = (d_window_priv_t*)pubw;
355 /* this overrides any reply from our get_geometry call */
357 w->waiting_geom = FALSE;
362 w->bw = border_width;
366 window_move(d_window_t *pubw)
368 //d_window_priv_t *w = (d_window_priv_t*)pubw;
369 window_update_region((d_window_priv_t*)pubw);
373 window_resize(d_window_t *w)
375 window_update_pixmap((d_window_priv_t*)w);
376 window_update_region((d_window_priv_t*)w);
380 window_reshape(d_window_t *w)
382 window_update_region((d_window_priv_t*)w);
386 window_add_plugin_data(d_window_t *pubw, int id, void *data)
388 d_window_priv_t *w = (d_window_priv_t*)pubw;
389 plugin_data_add(w->plugin_data, id, data);
393 window_find_plugin_data(d_window_t *pubw, int id)
395 d_window_priv_t *w = (d_window_priv_t*)pubw;
396 return plugin_data_find(w->plugin_data, id);
400 window_remove_plugin_data(d_window_t *pubw, int id)
402 d_window_priv_t *w = (d_window_priv_t*)pubw;
403 plugin_data_remove(w->plugin_data, id);
407 window_create_damage(d_window_t *pubw)
409 d_window_priv_t *w = (d_window_priv_t*)pubw;
411 if (!window_is_input_only(pubw)) {
412 assert(w->damage == XCB_NONE);
413 w->damage = xcb_generate_id(w->sc->dpy->conn);
414 //printf("creating damage 0x%x\n", w->damage);
415 xcb_damage_create(w->sc->dpy->conn, w->damage, w->id,
416 XCB_DAMAGE_REPORT_LEVEL_NON_EMPTY);
421 window_destroy_damage(d_window_t *pubw)
423 d_window_priv_t *w = (d_window_priv_t*)pubw;
426 //printf("destroying damage 0x%x\n", w->damage);
427 xcb_damage_destroy(w->sc->dpy->conn, w->damage);
428 w->damage = XCB_NONE;