find out a window's type when it is shown
authorDana Jansens <danakj@orodu.net>
Thu, 6 Mar 2008 08:43:28 +0000 (03:43 -0500)
committerDana Jansens <danakj@orodu.net>
Thu, 6 Mar 2008 08:51:49 +0000 (03:51 -0500)
display.c
display.h
window.c
window.h

index 5482d6b..7f02cb6 100644 (file)
--- a/display.c
+++ b/display.c
@@ -195,6 +195,8 @@ query_statics(d_display_t *dpy)
     dpy->a.cardinal = 6;
     dpy->a.pixmap = 20;
     dpy->a.string = 31;
+    dpy->a.window = 33;
+    dpy->a.wm_transient_for = 68;
 }
 
 d_display_t*
index cd85ad4..6cfdc76 100644 (file)
--- a/display.h
+++ b/display.h
@@ -35,10 +35,12 @@ typedef struct d_display {
         xcb_atom_t utf8_string;
         xcb_atom_t string;
         xcb_atom_t pixmap;
+        xcb_atom_t window;
         /* properties */
         xcb_atom_t esetroot_pmap_id;
         xcb_atom_t xrootpmap_id;
         xcb_atom_t xsetroot_id;
+        xcb_atom_t wm_transient_for;
         xcb_atom_t net_wm_window_type;
         xcb_atom_t net_wm_window_type_desktop;
         xcb_atom_t net_wm_window_type_dock;
index 70c8861..cecae41 100644 (file)
--- a/window.c
+++ b/window.c
@@ -27,13 +27,17 @@ typedef struct {
     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;
 
@@ -47,6 +51,7 @@ 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);
+static void window_update_type(d_window_priv_t *w);
 
 d_window_t*
 window_new(xcb_window_t id, struct d_screen *sc)
@@ -62,6 +67,7 @@ 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);
 
@@ -178,6 +184,7 @@ window_show(d_window_t *pubw)
 
     window_update_pixmap(w);
     window_update_region(w);
+    window_update_type(w);
     w->mapped = TRUE;
 }
 
@@ -428,3 +435,130 @@ window_destroy_damage(d_window_t *pubw)
         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;
+}
+
index 5e79d4b..3a1cf09 100644 (file)
--- a/window.h
+++ b/window.h
@@ -12,6 +12,24 @@ typedef struct d_window {
     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);
@@ -49,4 +67,6 @@ void  window_remove_plugin_data(d_window_t *w, int it);
 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