+#include "efence.h"
+
#include "window.h"
#include "screen.h"
#include "plugin.h"
int ref;
/* queried things, don't read them directly from the struct */
- int x, y, w, h, bw;
- gboolean mapped;
- gboolean input_only;
- xcb_visualid_t visual;
- xcb_pixmap_t pixmap;
+ int x, y, w, h, bw;
+ gboolean attr_mapped;
+ gboolean input_only;
+ gboolean argb;
+ xcb_visualid_t visual;
+ xcb_pixmap_t pixmap;
+ xcb_xfixes_region_t region;
double opacity;
+ gboolean mapped;
gboolean zombie;
d_list_t *plugin_data;
xcb_get_window_attributes_cookie_t ck_get_attr;
gboolean waiting_geom;
xcb_get_geometry_cookie_t ck_get_geom;
- gboolean waiting_pixmap;
- xcb_void_cookie_t ck_get_pixmap;
} d_window_priv_t;
static void window_get_attributes_reply(d_window_priv_t *w);
static void window_get_geometry_reply(d_window_priv_t *w);
+static void window_update_pixmap(d_window_priv_t *w);
+static void window_update_region(d_window_priv_t *w);
d_window_t*
window_new(xcb_window_t id, struct d_screen *sc)
w->ref = 1;
w->sc = sc;
w->zombie = FALSE;
+ w->mapped = FALSE;
w->pixmap = XCB_NONE;
w->damage = XCB_NONE;
+ w->region = XCB_NONE;
screen_stacking_add(sc, (d_window_t*)w);
w->ck_get_geom = xcb_get_geometry(sc->dpy->conn, id);
w->waiting_geom = TRUE;
- w->waiting_pixmap = FALSE;
-
w->plugin_data = list_new();
//printf("new window 0x%x\n", w->id);
d_window_priv_t *w = (d_window_priv_t*)pubw;
if (w && --w->ref == 0) {
- xcb_pixmap_t p;
-
screen_stacking_remove(w->sc, (d_window_t*)w);
- if ((p = window_get_pixmap(pubw))) {
- xcb_free_pixmap(w->sc->dpy->conn, p);
+ if (w->region) {
+ xcb_xfixes_destroy_region(w->sc->dpy->conn, w->region);
+ w->region = XCB_NONE;
+ }
+
+ if (w->pixmap) {
+ /* this may cause an error if the pixmap was never valid, but
+ that's fine */
+ xcb_free_pixmap(w->sc->dpy->conn, w->pixmap);
w->pixmap = XCB_NONE;
}
}
}
+xcb_pixmap_t
+window_get_pixmap(d_window_t *pubw)
+{
+ d_window_priv_t *w = (d_window_priv_t*)pubw;
+
+ return w->pixmap;
+}
+
static void
-window_update_pixmap(d_window_priv_t *w)
+window_update_region(d_window_priv_t *w)
{
- xcb_pixmap_t p;
+ int x, y, wi, hei, bw;
if (window_is_zombie((d_window_t*)w)) return;
- /* XXX can we save it for until we get the new pixmap? */
- if ((p = window_get_pixmap((d_window_t*)w))) {
- xcb_free_pixmap(w->sc->dpy->conn, p);
+ if (w->region) {
+ xcb_xfixes_destroy_region(w->sc->dpy->conn, w->region);
+ w->region = XCB_NONE;
+ }
+
+ w->region = xcb_generate_id(w->sc->dpy->conn);
+ xcb_xfixes_create_region_from_window(w->sc->dpy->conn, w->region,
+ w->id, XCB_SHAPE_SK_BOUNDING);
+ window_get_area((d_window_t*)w, &x, &y, &wi, &hei, &bw);
+ xcb_xfixes_translate_region(w->sc->dpy->conn, w->region, x+bw, y+bw);
+}
+
+static void
+window_update_pixmap(d_window_priv_t *w)
+{
+ if (window_is_zombie((d_window_t*)w)) return;
+
+ /* the pixmap may not be valid even though it is non-zero, but
+ we can free it anyways and let it fail. we don't need to wait
+ for a response from the server */
+ if (w->pixmap) {
+ xcb_free_pixmap(w->sc->dpy->conn, w->pixmap);
w->pixmap = XCB_NONE;
}
//printf("updating pixmap for 0x%x\n", w->id);
+ /* we don't check the result of this call, because it seems that sometimes
+ the X server just doesn't reply. if we check it, we end up hanging
+ sometimes waiting for the reply */
w->pixmap = xcb_generate_id(w->sc->dpy->conn);
- w->ck_get_pixmap =
- xcb_composite_name_window_pixmap_checked(w->sc->dpy->conn,
- w->id, w->pixmap);
- w->waiting_pixmap = TRUE;
+ xcb_composite_name_window_pixmap(w->sc->dpy->conn, w->id, w->pixmap);
+ //printf("requested pixmap sequence %u\n", w->ck_get_pixmap.sequence);
+ //fflush(stdout);
xcb_flush(w->sc->dpy->conn);
}
{
d_window_priv_t *w = (d_window_priv_t*)pubw;
- window_is_mapped(pubw); /* kill any ongoing request */
+ assert(!w->mapped);
//printf("show window 0x%x\n", w->id);
+ /* make sure this is before we update the window's region */
+ if (w->sc->dpy->shape.present)
+ xcb_shape_select_input(w->sc->dpy->conn, w->id, TRUE);
+
window_update_pixmap(w);
+ window_update_region(w);
w->mapped = TRUE;
}
{
d_window_priv_t *w = (d_window_priv_t*)pubw;
- window_is_mapped(pubw); /* kill any ongoing request */
+ assert(w->mapped);
//printf("hide window 0x%x\n", w->id);
+ if (w->sc->dpy->shape.present)
+ xcb_shape_select_input(w->sc->dpy->conn, w->id, FALSE);
+
+ w->mapped = FALSE;
+}
+
+void
+window_fake_unmapped(d_window_t *pubw)
+{
+ d_window_priv_t *w = (d_window_priv_t*)pubw;
w->mapped = FALSE;
}
if (rep) {
w->input_only = rep->_class == XCB_WINDOW_CLASS_INPUT_ONLY;
- w->mapped = rep->map_state != XCB_MAP_STATE_UNMAPPED;
+ w->attr_mapped = rep->map_state != XCB_MAP_STATE_UNMAPPED;
w->visual = rep->visual;
+ //printf("0x%x attributes mapped %d\n", w->id, w->mapped);
free(rep);
}
else {
w->input_only = TRUE;
- w->mapped = FALSE;
+ w->attr_mapped = FALSE;
w->visual = XCB_NONE;
}
if (err) {
printf("error getting attributes for window 0x%x\n", w->id);
free(err);
}
- w->waiting_attr = 0;
+ w->waiting_attr = FALSE;
}
static void
w->w = rep->width;
w->h = rep->height;
w->bw = rep->border_width;
+ w->argb = rep->depth == 32;
free(rep);
}
else {
w->x = w->y = -1;
w->w = w->h = 1;
w->bw = 0;
+ w->argb = FALSE;
}
if (err) {
printf("error getting geometry for window 0x%x\n", w->id);
free(err);
}
- w->waiting_geom = 0;
+ w->waiting_geom = FALSE;
}
gboolean
window_is_mapped(d_window_t *pubw)
{
d_window_priv_t *w = (d_window_priv_t*)pubw;
- if (w->waiting_attr)
- window_get_attributes_reply(w);
return w->mapped;
}
-xcb_pixmap_t
-window_get_pixmap(d_window_t *pubw)
+gboolean
+window_is_attr_mapped(d_window_t *pubw)
{
d_window_priv_t *w = (d_window_priv_t*)pubw;
+ if (w->waiting_attr)
+ window_get_attributes_reply(w);
+ return w->attr_mapped;
+}
- if (w->waiting_pixmap) {
- xcb_generic_error_t *err;
- //printf("** checking get pixmap 0x%x\n", w->id);
- err = xcb_request_check(w->sc->dpy->conn, w->ck_get_pixmap);
- if (err) {
- w->pixmap = XCB_NONE;
- printf("error getting named pixmap for window 0x%x\n", w->id);
- free(err);
- }
- w->waiting_pixmap = FALSE;
- }
- //printf("returning pixmap 0x%x for window 0x%x\n", w->pixmap, w->id);
- return w->pixmap;
+gboolean
+window_is_argb(d_window_t *pubw)
+{
+ d_window_priv_t *w = (d_window_priv_t*)pubw;
+ if (w->waiting_geom)
+ window_get_geometry_reply(w);
+ return w->argb;
}
xcb_visualid_t
return w->visual;
}
+xcb_xfixes_region_t
+window_get_region(d_window_t *pubw)
+{
+ d_window_priv_t *w = (d_window_priv_t*)pubw;
+
+ return w->region;
+}
+
void
window_configure(d_window_t *pubw, int x, int y, int width, int height,
int border_width)
}
void
-window_move(d_window_t *w)
+window_move(d_window_t *pubw)
{
- (void)w;
+ //d_window_priv_t *w = (d_window_priv_t*)pubw;
+ window_update_region((d_window_priv_t*)pubw);
}
void
window_resize(d_window_t *w)
{
window_update_pixmap((d_window_priv_t*)w);
+ window_update_region((d_window_priv_t*)w);
+}
+
+void
+window_reshape(d_window_t *w)
+{
+ window_update_region((d_window_priv_t*)w);
}
void
if (!window_is_input_only(pubw)) {
assert(w->damage == XCB_NONE);
w->damage = xcb_generate_id(w->sc->dpy->conn);
+ //printf("creating damage 0x%x\n", w->damage);
xcb_damage_create(w->sc->dpy->conn, w->damage, w->id,
XCB_DAMAGE_REPORT_LEVEL_NON_EMPTY);
}
}
-void window_destroy_damage(d_window_t *pubw)
+void
+window_destroy_damage(d_window_t *pubw)
{
d_window_priv_t *w = (d_window_priv_t*)pubw;
if (w->damage) {
+ //printf("destroying damage 0x%x\n", w->damage);
xcb_damage_destroy(w->sc->dpy->conn, w->damage);
w->damage = XCB_NONE;
}