From c28bcc5c3bd655a7f1b051d70c067b564028b605 Mon Sep 17 00:00:00 2001 From: Dana Jansens Date: Thu, 6 Mar 2008 03:43:28 -0500 Subject: [PATCH] find out a window's type when it is shown --- display.c | 2 + display.h | 2 + window.c | 142 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- window.h | 20 ++++++++ 4 files changed, 162 insertions(+), 4 deletions(-) diff --git a/display.c b/display.c index 5482d6b..7f02cb6 100644 --- 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* diff --git a/display.h b/display.h index cd85ad4..6cfdc76 100644 --- 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; diff --git a/window.c b/window.c index 70c8861..cecae41 100644 --- 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; +} + diff --git a/window.h b/window.h index 5e79d4b..3a1cf09 100644 --- 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 -- 2.34.1