#include "window.h"
#include "screen.h"
+#include "display.h"
#include <stdlib.h>
#include <stdio.h>
+#include <xcb/composite.h>
+
+typedef struct {
+ /* public stuff */
+ xcb_window_t id;
+ struct d_screen *sc;
+
+ /* private stuff */
+ int ref;
+
+ /* queried things, don't read them directly from the struct */
+ int x, y, w, h;
+ gboolean mapped;
+ gboolean input_only;
+
+ gboolean zombie;
+
+ int opacity;
+
+ xcb_pixmap_t pixmap;
+
+ xcb_get_window_attributes_cookie_t ck_get_attr;
+ xcb_get_geometry_cookie_t ck_get_geom;
+ 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);
d_window_t*
window_new(xcb_window_t id, struct d_screen *sc)
{
- d_window_t *w;
+ d_window_priv_t *w;
- w = malloc(sizeof(d_window_t));
+ w = malloc(sizeof(d_window_priv_t));
w->id = id;
w->ref = 1;
w->sc = sc;
- w->mapped = FALSE;
w->zombie = FALSE;
w->opacity = WINDOW_OPACITY_MAX;
+ w->pixmap = XCB_NONE;
+
+ screen_stacking_add(sc, (d_window_t*)w);
+
+ w->ck_get_attr = xcb_get_window_attributes(sc->dpy->conn, id);
+ w->ck_get_geom = xcb_get_geometry(sc->dpy->conn, id);
- screen_stacking_add(sc, w);
+ w->ck_get_pixmap.sequence = 0;
- printf("new window 0x%x\n", w->id);
+ //printf("new window 0x%x\n", w->id);
- return w;
+ return (d_window_t*)w;
}
void
-window_ref(d_window_t *w)
+window_ref(d_window_t *pubw)
{
+ d_window_priv_t *w = (d_window_priv_t*)pubw;
+
++w->ref;
}
void
-window_unref(d_window_t *w)
+window_unref(d_window_t *pubw)
{
+ d_window_priv_t *w = (d_window_priv_t*)pubw;
+
if (w && --w->ref == 0) {
- screen_stacking_remove(w->sc, w);
+ 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);
+ w->pixmap = XCB_NONE;
+ }
+
free(w);
}
}
void
-window_show(d_window_t *w)
+window_show(d_window_t *pubw)
{
- if (w->mapped) return;
+ d_window_priv_t *w = (d_window_priv_t*)pubw;
+ xcb_pixmap_t p;
+
+ if (window_is_mapped(pubw)) return;
printf("show window 0x%x\n", w->id);
+ /* XXX can we save it for until we get the new pixmap? */
+ if ((p = window_get_pixmap(pubw))) {
+ xcb_free_pixmap(w->sc->dpy->conn, p);
+ w->pixmap = XCB_NONE;
+ }
+
w->mapped = TRUE;
+ 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);
+ xcb_flush(w->sc->dpy->conn);
}
void
-window_hide(d_window_t *w)
+window_hide(d_window_t *pubw)
{
- if (!w->mapped) return;
+ d_window_priv_t *w = (d_window_priv_t*)pubw;
+
+ if (!window_is_mapped(pubw)) return;
printf("hide window 0x%x\n", w->id);
}
void
-window_become_zombie(d_window_t *w)
+window_become_zombie(d_window_t *pubw)
{
+ d_window_priv_t *w = (d_window_priv_t*)pubw;
+
if (w->zombie) return;
w->zombie = TRUE;
}
+
+gboolean
+window_is_zombie(d_window_t *pubw)
+{
+ d_window_priv_t *w = (d_window_priv_t*)pubw;
+ return w->zombie;
+}
+
+gboolean
+window_is_input_only(d_window_t *pubw)
+{
+ d_window_priv_t *w = (d_window_priv_t*)pubw;
+ if (w->ck_get_attr.sequence)
+ window_get_attributes_reply(w);
+ return w->input_only;
+}
+
+void
+window_get_area(d_window_t *pubw, int *x, int *y, int *width, int *height)
+{
+ d_window_priv_t *w = (d_window_priv_t*)pubw;
+ if (w->ck_get_geom.sequence)
+ window_get_geometry_reply(w);
+ *x = w->x;
+ *y = w->y;
+ *width = w->w;
+ *height = w->h;
+}
+
+static void
+window_get_attributes_reply(d_window_priv_t *w)
+{
+ xcb_get_window_attributes_reply_t *rep;
+ xcb_generic_error_t *err = NULL;
+
+ rep = xcb_get_window_attributes_reply(w->sc->dpy->conn,
+ w->ck_get_attr,
+ &err);
+
+ if (rep) {
+ w->input_only = rep->_class == XCB_WINDOW_CLASS_INPUT_ONLY;
+ w->mapped = rep->map_state != XCB_MAP_STATE_UNMAPPED;
+ free(rep);
+ }
+ else {
+ w->input_only = TRUE;
+ w->mapped = FALSE;
+ }
+ if (err) {
+ printf("error getting attributes for window 0x%x\n", w->id);
+ free(err);
+ }
+ w->ck_get_attr.sequence = 0;
+}
+
+static void
+window_get_geometry_reply(d_window_priv_t *w)
+{
+ xcb_get_geometry_reply_t *rep;
+ xcb_generic_error_t *err = NULL;
+
+ rep = xcb_get_geometry_reply(w->sc->dpy->conn,
+ w->ck_get_geom,
+ &err);
+
+ if (rep) {
+ w->x = rep->x;
+ w->y = rep->y;
+ w->w = rep->width + rep->border_width * 2;
+ w->h = rep->height + rep->border_width * 2;
+ free(rep);
+ }
+ else {
+ w->x = w->y = -1;
+ w->w = w->h = 1;
+ }
+ if (err) {
+ printf("error getting geometry for window 0x%x\n", w->id);
+ free(err);
+ }
+ w->ck_get_geom.sequence = 0;
+}
+
+gboolean
+window_is_mapped(d_window_t *pubw)
+{
+ d_window_priv_t *w = (d_window_priv_t*)pubw;
+ if (w->ck_get_attr.sequence)
+ window_get_attributes_reply(w);
+ return w->mapped;
+}
+
+xcb_pixmap_t
+window_get_pixmap(d_window_t *pubw)
+{
+ d_window_priv_t *w = (d_window_priv_t*)pubw;
+ if (w->ck_get_pixmap.sequence) {
+ 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) {
+ printf("error getting named pixmap for window 0x%x\n", w->id);
+ free(err);
+ }
+ w->pixmap = XCB_NONE;
+ }
+ //printf("returning pixmap 0x%x for window 0x%x\n", w->pixmap, w->id);
+ return w->pixmap;
+}