xcb_visualid_t visual;
xcb_pixmap_t pixmap;
xcb_xfixes_region_t region;
+ d_window_type_t type;
+ /* the window id where we got the window type from. further property
+ queries should go to this window */
+ xcb_window_t client;
- double opacity;
+ double opacity;
- gboolean mapped;
- gboolean zombie;
+ gboolean mapped;
+ gboolean zombie;
- d_list_t *plugin_data;
+ d_list_t *plugin_data;
xcb_damage_damage_t damage;
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);
+static void window_update_type(d_window_priv_t *w);
d_window_t*
window_new(xcb_window_t id, struct d_screen *sc)
w->pixmap = XCB_NONE;
w->damage = XCB_NONE;
w->region = XCB_NONE;
+ w->type = DC_WINDOW_TYPE_INVALID;
screen_stacking_add(sc, (d_window_t*)w);
window_update_pixmap(w);
window_update_region(w);
+ window_update_type(w);
w->mapped = TRUE;
}
w->damage = XCB_NONE;
}
}
+
+static void
+type_request(d_display_t *dpy, d_window_priv_t *w, xcb_window_t *id, int nid)
+{
+ xcb_get_property_cookie_t *cks;
+ int i;
+
+ cks = malloc(sizeof(xcb_get_property_cookie_t) * nid * 2);
+ for (i = 0; i < nid; ++i) {
+ cks[i*2+0] =
+ xcb_get_property_unchecked(dpy->conn, FALSE, id[i],
+ dpy->a.net_wm_window_type,
+ dpy->a.atom, 0, 20);
+ cks[i*2+1] =
+ xcb_get_property_unchecked(dpy->conn, FALSE, id[i],
+ dpy->a.wm_transient_for,
+ dpy->a.window, 0, 1);
+ }
+
+ for (i = 0; i < nid; ++i) {
+ xcb_get_property_reply_t *rep;
+ d_window_type_t type = DC_WINDOW_TYPE_INVALID;
+
+ rep = xcb_get_property_reply(dpy->conn, cks[i*2+0], NULL);
+ if (rep) {
+ if (!w->type && rep->type == dpy->a.atom && rep->length >= 1) {
+ xcb_atom_t *a = (xcb_atom_t*)(xcb_get_property_value(rep));
+ uint32_t j;
+ for (j = 0; j < rep->length; ++j) {
+ if (a[j] == dpy->a.net_wm_window_type_normal) {
+ type = DC_WINDOW_TYPE_NORMAL; break;
+ }
+ if (a[j] == dpy->a.net_wm_window_type_desktop) {
+ type = DC_WINDOW_TYPE_DESKTOP; break;
+ }
+ if (a[j] == dpy->a.net_wm_window_type_dock) {
+ type = DC_WINDOW_TYPE_DOCK; break;
+ }
+ if (a[j] == dpy->a.net_wm_window_type_dialog) {
+ type = DC_WINDOW_TYPE_DIALOG; break;
+ }
+ if (a[j] == dpy->a.net_wm_window_type_toolbar) {
+ type = DC_WINDOW_TYPE_TOOLBAR; break;
+ }
+ if (a[j] == dpy->a.net_wm_window_type_menu) {
+ type = DC_WINDOW_TYPE_MENU; break;
+ }
+ if (a[j] == dpy->a.net_wm_window_type_utility) {
+ type = DC_WINDOW_TYPE_UTILITY; break;
+ }
+ if (a[j] == dpy->a.net_wm_window_type_splash) {
+ type = DC_WINDOW_TYPE_SPLASH; break;
+ }
+ if (a[j] == dpy->a.net_wm_window_type_dropdown_menu) {
+ type = DC_WINDOW_TYPE_DROPDOWN_MENU; break;
+ }
+ if (a[j] == dpy->a.net_wm_window_type_popup_menu) {
+ type = DC_WINDOW_TYPE_POPUP_MENU; break;
+ }
+ if (a[j] == dpy->a.net_wm_window_type_tooltip) {
+ type = DC_WINDOW_TYPE_TOOLTIP; break;
+ }
+ if (a[j] == dpy->a.net_wm_window_type_notification) {
+ type = DC_WINDOW_TYPE_NOTIFICATION; break;
+ }
+ if (a[j] == dpy->a.net_wm_window_type_combo) {
+ type = DC_WINDOW_TYPE_COMBO; break;
+ }
+ if (a[j] == dpy->a.net_wm_window_type_dnd) {
+ type = DC_WINDOW_TYPE_DND; break;
+ }
+ }
+ }
+ free(rep);
+ }
+ rep = xcb_get_property_reply(dpy->conn, cks[i*2+1], NULL);
+ if (rep) {
+ if (!w->type && rep->type == dpy->a.window && rep->length == 1)
+ type = DC_WINDOW_TYPE_DIALOG;
+ free(rep);
+ }
+
+ /* also save the window id that we got the type/transient hint from */
+ if (!w->type && type) {
+ w->type = type;
+ w->client = id[i];
+ }
+ }
+
+
+ for (i = 0; i < nid && !w->type; ++i) {
+ xcb_query_tree_cookie_t ck;
+ xcb_query_tree_reply_t *rep;
+
+ ck = xcb_query_tree(dpy->conn, id[i]);
+ rep = xcb_query_tree_reply(dpy->conn, ck, NULL);
+ if (rep) {
+ int num = xcb_query_tree_children_length(rep);
+ xcb_window_t *ch = xcb_query_tree_children(rep);
+
+ type_request(dpy, w, ch, num);
+ free(rep);
+ }
+ }
+}
+
+static void
+window_update_type(d_window_priv_t *w)
+{
+ w->type = DC_WINDOW_TYPE_INVALID;
+ type_request(w->sc->dpy, w, &w->id, 1);
+ if (!w->type) {
+ w->type = DC_WINDOW_TYPE_NORMAL;
+ w->client = w->id;
+ }
+
+ printf("window 0x%x type %d\n", w->id, w->type);
+}
+
+d_window_type_t
+window_get_type(d_window_t *pubw)
+{
+ d_window_priv_t *w = (d_window_priv_t*)pubw;
+
+ return w->type;
+}
+
struct d_screen *sc;
} d_window_t;
+typedef enum {
+ DC_WINDOW_TYPE_INVALID,
+ DC_WINDOW_TYPE_NORMAL,
+ DC_WINDOW_TYPE_DESKTOP,
+ DC_WINDOW_TYPE_DOCK,
+ DC_WINDOW_TYPE_DIALOG,
+ DC_WINDOW_TYPE_TOOLBAR,
+ DC_WINDOW_TYPE_MENU,
+ DC_WINDOW_TYPE_UTILITY,
+ DC_WINDOW_TYPE_SPLASH,
+ DC_WINDOW_TYPE_DROPDOWN_MENU,
+ DC_WINDOW_TYPE_POPUP_MENU,
+ DC_WINDOW_TYPE_TOOLTIP,
+ DC_WINDOW_TYPE_NOTIFICATION,
+ DC_WINDOW_TYPE_COMBO,
+ DC_WINDOW_TYPE_DND
+} d_window_type_t;
+
d_window_t* window_new(xcb_window_t id, struct d_screen *sc);
void window_ref(d_window_t *w);
void window_create_damage(d_window_t *w);
void window_destroy_damage(d_window_t *w);
+d_window_type_t window_get_type(d_window_t *w);
+
#endif