void map_client(client_t *c) { XWindowAttributes attr; strut_t s = { 0, 0, 0, 0 }; XWMHints *hints; int btn, want_raise = 1; XGrabServer(dpy); XGetWindowAttributes(dpy, c->win, &attr); collect_struts(c, &s); if (attr.map_state == IsViewable) { c->ignore_unmap++; reparent(c, &s); if (get_wm_state(c->win) == IconicState) { c->ignore_unmap++; XUnmapWindow(dpy, c->win); } else { set_wm_state(c, NormalState); do_map(c, want_raise); } } else { if ((hints = XGetWMHints(dpy, c->win))) { if (hints->flags & StateHint) set_wm_state(c, hints->initial_state); XFree(hints); } else { set_wm_state(c, NormalState); } if (!init_geom(c, &s) && opt_imap) { btn = sweep(c, map_curs, recalc_map, SWEEP_DOWN, &s); if (btn == Button2) btn = sweep(c, resize_curs, recalc_resize, SWEEP_UP, &s); if (btn == Button3) want_raise = 0; } #ifdef DEBUG dump_geom(c, "set to"); dump_info(c); #endif reparent(c, &s); if (get_wm_state(c->win) == NormalState) do_map(c, want_raise); } XSync(dpy, False); c->name = get_wm_name(c->win); // horrible kludge XUngrabServer(dpy); }
static void pager_propertynotify(pager *p, XEvent *ev) { Atom at = ev->xproperty.atom; Window win = ev->xproperty.window; task *t; ENTER; if ((win == GDK_ROOT_WINDOW()) || !(t = g_hash_table_lookup(p->htable, &win))) RET(); /* The property is deleted */ if( ((XPropertyEvent*)ev)->state == 1 ) return; DBG("window=0x%x\n", t->win); if (at == a_WM_STATE) { DBG("event=WM_STATE\n"); t->ws = get_wm_state (t->win); } else if (at == a_NET_WM_STATE) { DBG("event=NET_WM_STATE\n"); get_net_wm_state(t->win, &t->nws); } else if (at == a_NET_WM_DESKTOP) { DBG("event=NET_WM_DESKTOP\n"); desk_set_dirty_by_win(p, t); // to clean up desks where this task was t->desktop = get_net_wm_desktop(t->win); } else { RET(); } desk_set_dirty_by_win(p, t); RET(); }
void snprint_wm_name(char *buf, size_t len, Window w) { char *n; if ((n = get_wm_name(w))) { if (get_wm_state(w) == NormalState) { if (snprintf(buf, len, "%s", n) > len) strcpy(buf+len-4, "..."); } else { if (snprintf(buf, len, "[%s]", n) > len) strcpy(buf+len-5, "...]"); } XFree(n); } else { snprintf(buf, len, "%#lx", w); } }
/* Handle PropertyNotify event. * http://tronche.com/gui/x/icccm/ * http://standards.freedesktop.org/wm-spec/wm-spec-1.4.html */ static void pager_property_notify_event(PagerPlugin * pg, XEvent * ev) { /* State may be PropertyNewValue, PropertyDeleted. */ if (((XPropertyEvent*) ev)->state == PropertyNewValue) { Atom at = ev->xproperty.atom; Window win = ev->xproperty.window; if (win != GDK_ROOT_WINDOW()) { /* Look up task structure by X window handle. */ PagerTask * tk = task_lookup(pg, win); if (tk != NULL) { /* Install an error handler that ignores BadWindow. * We frequently get a PropertyNotify event on deleted windows. */ XErrorHandler previous_error_handler = XSetErrorHandler(panel_handle_x_error_swallow_BadWindow_BadDrawable); /* Dispatch on atom. */ if (at == a_WM_STATE) { /* Window changed state. */ tk->ws = get_wm_state(tk->win); desk_set_dirty_by_win(pg, tk); } else if (at == a_NET_WM_STATE) { /* Window changed EWMH state. */ get_net_wm_state(tk->win, &tk->nws); desk_set_dirty_by_win(pg, tk); } else if (at == a_NET_WM_DESKTOP) { /* Window changed desktop. * Mark both old and new desktops for redraw. */ desk_set_dirty_by_win(pg, tk); tk->desktop = get_net_wm_desktop(tk->win); desk_set_dirty_by_win(pg, tk); XSetErrorHandler(previous_error_handler); } } } } }
static void do_net_client_list_stacking(FbEv *ev, pager *p) { int i; task *t; ENTER; if (p->wins) XFree(p->wins); p->wins = get_xaproperty (GDK_ROOT_WINDOW(), a_NET_CLIENT_LIST_STACKING, XA_WINDOW, &p->winnum); if (!p->wins || !p->winnum) RET(); /* refresh existing tasks and add new */ for (i = 0; i < p->winnum; i++) { if ((t = g_hash_table_lookup(p->htable, &p->wins[i]))) { t->refcount++; if (t->stacking != i) { t->stacking = i; desk_set_dirty_by_win(p, t); } } else { t = g_new0(task, 1); t->refcount++; t->win = p->wins[i]; t->ws = get_wm_state (t->win); t->desktop = get_net_wm_desktop(t->win); get_net_wm_state(t->win, &t->nws); get_net_wm_window_type(t->win, &t->nwwt); task_get_sizepos(t); if (!FBPANEL_WIN(t->win)) XSelectInput (GDK_DISPLAY(), t->win, PropertyChangeMask | StructureNotifyMask); g_hash_table_insert(p->htable, &t->win, t); DBG("add %x\n", t->win); desk_set_dirty_by_win(p, t); } } /* pass throu hash table and delete stale windows */ g_hash_table_foreach_remove(p->htable, (GHRFunc) task_remove_stale, (gpointer)p); RET(); }
/* * List all hidden windows. * */ int findhidden(void) { xcb_query_tree_reply_t *reply; int i; int len; xcb_window_t *children; xcb_get_window_attributes_reply_t *attr; uint32_t state; xcb_get_property_cookie_t cookie; xcb_icccm_get_text_property_reply_t prop; xcb_generic_error_t *error; /* Get all children. */ reply = xcb_query_tree_reply(conn, xcb_query_tree(conn, screen->root), 0); if (NULL == reply) { return -1; } len = xcb_query_tree_children_length(reply); children = xcb_query_tree_children(reply); /* List all hidden windows on this root. */ for (i = 0; i < len; i ++) { attr = xcb_get_window_attributes_reply( conn, xcb_get_window_attributes(conn, children[i]), NULL); if (!attr) { fprintf(stderr, "Couldn't get attributes for window %d.", children[i]); continue; } /* * Don't bother windows in override redirect mode. * * This mode means they wouldn't have been reported to us * with a MapRequest if we had been running, so in the * normal case we wouldn't have seen them. */ if (!attr->override_redirect) { state = get_wm_state(children[i]); if (state == XCB_ICCCM_WM_STATE_ICONIC) { /* * Example names: * * _NET_WM_ICON_NAME(UTF8_STRING) = 0x75, 0x72, 0x78, * 0x76, 0x74 WM_ICON_NAME(STRING) = "urxvt" * _NET_WM_NAME(UTF8_STRING) = 0x75, 0x72, 0x78, 0x76, * 0x74 WM_NAME(STRING) = "urxvt" */ cookie = xcb_icccm_get_wm_icon_name(conn, children[i]); xcb_icccm_get_wm_icon_name_reply(conn, cookie, &prop, &error); prop.name[prop.name_len] = '\0'; if (printcommand) { /* FIXME: Need to escape : in prop.name. */ printf("'%s':'xdotool windowmap 0x%x windowraise 0x%x'\n", prop.name, children[i], children[i]); } else { puts(prop.name); } } } /* if not override redirect */ free(attr); } /* for */ free(reply); return 0; }