static void pager_propertynotify(pager_priv *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(); DBG("window=0x%lx\n", t->win); 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(); }
/* Execute a window command. */ static void wincmd_execute(WinCmdPlugin * wc, WindowCommand command) { /* Get the list of all windows. */ int client_count; Window * client_list = get_xaproperty (GDK_ROOT_WINDOW(), a_NET_CLIENT_LIST, XA_WINDOW, &client_count); Display *xdisplay = GDK_DISPLAY_XDISPLAY(gdk_display_get_default()); if (client_list != NULL) { /* Loop over all windows. */ int current_desktop = get_net_current_desktop(); int i; for (i = 0; i < client_count; i++) { /* Get the desktop and window type properties. */ NetWMWindowType nwwt; int task_desktop = get_net_wm_desktop(client_list[i]); get_net_wm_window_type(client_list[i], &nwwt); /* If the task is visible on the current desktop and it is an ordinary window, * execute the requested Iconify or Shade change. */ if (((task_desktop == -1) || (task_desktop == current_desktop)) && (( ! nwwt.dock) && ( ! nwwt.desktop) && ( ! nwwt.splash))) { switch (command) { case WC_NONE: break; case WC_ICONIFY: if (( ! wc->toggle_preference) || ( ! wc->toggle_state)) XIconifyWindow(xdisplay, client_list[i], DefaultScreen(xdisplay)); else XMapWindow (xdisplay, client_list[i]); break; case WC_SHADE: Xclimsg(client_list[i], a_NET_WM_STATE, ((( ! wc->toggle_preference) || ( ! wc->toggle_state)) ? a_NET_WM_STATE_ADD : a_NET_WM_STATE_REMOVE), a_NET_WM_STATE_SHADED, 0, 0, 0); break; } } } XFree(client_list); /* Adjust toggle state. */ wincmd_adjust_toggle_state(wc); } }
/* 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 toggle_iconify(wincmd *wc, guint32 action) { Window *win = NULL; int num, i; guint32 tmp2, dno; net_wm_window_type nwwt; ENTER; win = get_xaproperty (GDK_ROOT_WINDOW(), a_NET_CLIENT_LIST, XA_WINDOW, &num); if (!win) RET(); if (!num) goto end; //tmp = get_xaproperty (GDK_ROOT_WINDOW(), a_NET_CURRENT_DESKTOP, XA_CARDINAL, 0); dno = get_net_current_desktop(); DBG("wincmd: #desk=%d\n", dno); //XFree(tmp); for (i = 0; i < num; i++) { int skip; tmp2 = get_net_wm_desktop(win[i]); DBG("wincmd: win=0x%x dno=%d...", win[i], tmp2); if ((tmp2 != -1) && (tmp2 != dno)) { DBG("skip - not cur desk\n"); continue; } get_net_wm_window_type(win[i], &nwwt); skip = (nwwt.dock || nwwt.desktop || nwwt.splash); if (skip) { DBG("skip - omnipresent window type\n"); continue; } if (action) XIconifyWindow(GDK_DISPLAY(), win[i], DefaultScreen(GDK_DISPLAY())); else XMapWindow (GDK_DISPLAY(), win[i]); DBG("ok\n"); } end: XFree(win); RET(); }
static void toggle_shaded(wincmd *wc, guint32 action) { Window *win = NULL; int num, i; guint32 tmp2, dno; net_wm_window_type nwwt; ENTER; win = get_xaproperty (GDK_ROOT_WINDOW(), a_NET_CLIENT_LIST, XA_WINDOW, &num); if (!win) RET(); if (!num) goto end; //tmp = get_xaproperty (GDK_ROOT_WINDOW(), a_NET_CURRENT_DESKTOP, XA_CARDINAL, 0); //dno = *tmp; dno = get_net_current_desktop(); DBG("wincmd: #desk=%d\n", dno); //XFree(tmp); for (i = 0; i < num; i++) { int skip; tmp2 = get_net_wm_desktop(win[i]); DBG("wincmd: win=0x%x dno=%d...", win[i], tmp2); if ((tmp2 != -1) && (tmp2 != dno)) { DBG("skip - not cur desk\n"); continue; } get_net_wm_window_type(win[i], &nwwt); skip = (nwwt.dock || nwwt.desktop || nwwt.splash); if (skip) { DBG("skip - omnipresent window type\n"); continue; } Xclimsg(win[i], a_NET_WM_STATE, action ? a_NET_WM_STATE_ADD : a_NET_WM_STATE_REMOVE, a_NET_WM_STATE_SHADED, 0, 0, 0); DBG("ok\n"); } end: XFree(win); RET(); }
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(); }