diff -u dwm-6.0-orig/config.def.h dwm-6.0-pertag-tab/config.def.h --- dwm-6.0-orig/config.def.h 2011-12-19 16:02:46.000000000 +0100 +++ dwm-6.0-pertag-tab/config.def.h 2013-06-23 00:06:48.000000000 +0200 @@ -12,6 +12,9 @@ static const unsigned int snap = 32; /* snap pixel */ static const Bool showbar = True; /* False means no bar */ static const Bool topbar = True; /* False means bottom bar */ +static const Bool showtab = True; /* False means no tab bar */ +static const Bool toptab = False; /* False means bottom tab bar */ + /* tagging */ static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" }; @@ -25,7 +28,7 @@ /* layout(s) */ static const float mfact = 0.55; /* factor of master area size [0.05..0.95] */ static const int nmaster = 1; /* number of clients in master area */ -static const Bool resizehints = True; /* True means respect size hints in tiled resizals */ +static const Bool resizehints = False; /* True means respect size hints in tiled resizals */ static const Layout layouts[] = { /* symbol arrange function */ @@ -54,6 +57,7 @@ { MODKEY, XK_p, spawn, {.v = dmenucmd } }, { MODKEY|ShiftMask, XK_Return, spawn, {.v = termcmd } }, { MODKEY, XK_b, togglebar, {0} }, + { MODKEY, XK_w, toggletab, {0} }, { MODKEY, XK_j, focusstack, {.i = +1 } }, { MODKEY, XK_k, focusstack, {.i = -1 } }, { MODKEY, XK_i, incnmaster, {.i = +1 } }, @@ -101,5 +105,6 @@ { ClkTagBar, 0, Button3, toggleview, {0} }, { ClkTagBar, MODKEY, Button1, tag, {0} }, { ClkTagBar, MODKEY, Button3, toggletag, {0} }, + { ClkTabBar, 0, Button1, focuswin, {0} }, }; diff -u dwm-6.0-orig/dwm.1 dwm-6.0-pertag-tab/dwm.1 --- dwm-6.0-orig/dwm.1 2011-12-19 16:02:46.000000000 +0100 +++ dwm-6.0-pertag-tab/dwm.1 2013-06-23 00:21:16.000000000 +0200 @@ -19,14 +19,16 @@ Windows are grouped by tags. Each window can be tagged with one or multiple tags. Selecting certain tags displays all windows with these tags. .P -Each screen contains a small status bar which displays all available tags, the -layout, the title of the focused window, and the text read from the root window -name property, if the screen is focused. A floating window is indicated with an -empty square and a maximised floating window is indicated with a filled square -before the windows title. The selected tags are indicated with a different -color. The tags of the focused window are indicated with a filled square in the -top left corner. The tags which are applied to one or more windows are -indicated with an empty square in the top left corner. +Each screen contains two bars. A small status bar displays all available tags, +the layout, the title of the focused window, and the text read from the root +window name property, if the screen is focused. A small tab bar lists the +windows in the current view and allows navigation from window to window, +especially in the monocle mode. A floating window is indicated with an empty +square and a maximised floating window is indicated with a filled square before +the windows title. The selected tags are indicated with a different color. The +tags of the focused window are indicated with a filled square in the top left +corner. The tags which are applied to one or more windows are indicated with an +empty square in the top left corner. .P dwm draws a small border around windows to indicate the focus state. .SH OPTIONS @@ -43,7 +45,8 @@ .TP .B Button1 click on a tag label to display all windows with that tag, click on the layout -label toggles between tiled and floating layout. +label toggles between tiled and floating layout, click on a window name in the +tab bar brings focus to that window. .TP .B Button3 click on a tag label adds/removes all windows with that tag to/from the view. @@ -104,6 +107,9 @@ .B Mod1\-h Decrease master area size. .TP +.B Mod1\-w +Toggle the tab bar. +.TP .B Mod1\-Return Zooms/cycles focused window to/from master area (tiled layouts only). .TP diff -u dwm-6.0-orig/dwm.c dwm-6.0-pertag-tab/dwm.c --- dwm-6.0-orig/dwm.c 2011-12-19 16:02:46.000000000 +0100 +++ dwm-6.0-pertag-tab/dwm.c 2013-06-23 16:57:10.000000000 +0200 @@ -62,7 +62,7 @@ NetWMFullscreen, NetActiveWindow, NetWMWindowType, NetWMWindowTypeDialog, NetLast }; /* EWMH atoms */ enum { WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast }; /* default atoms */ -enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, +enum { ClkTagBar, ClkTabBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, ClkRootWin, ClkLast }; /* clicks */ typedef union { @@ -102,6 +102,7 @@ unsigned long norm[ColLast]; unsigned long sel[ColLast]; Drawable drawable; + Drawable tabdrawable; GC gc; struct { int ascent; @@ -124,25 +125,36 @@ void (*arrange)(Monitor *); } Layout; +typedef struct Pertag Pertag; + +#define MAXTABS 50 + struct Monitor { char ltsymbol[16]; float mfact; int nmaster; int num; int by; /* bar geometry */ + int ty; /* tab bar geometry */ int mx, my, mw, mh; /* screen size */ int wx, wy, ww, wh; /* window area */ unsigned int seltags; unsigned int sellt; unsigned int tagset[2]; Bool showbar; + Bool showtab; Bool topbar; + Bool toptab; Client *clients; Client *sel; Client *stack; Monitor *next; Window barwin; + Window tabwin; + int ntabs; + int tab_widths[MAXTABS]; const Layout *lt[2]; + Pertag *pertag; }; typedef struct { @@ -178,11 +190,15 @@ static Monitor *dirtomon(int dir); static void drawbar(Monitor *m); static void drawbars(void); +static void drawtab(Monitor *m); +static void drawtabs(void); static void drawsquare(Bool filled, Bool empty, Bool invert, unsigned long col[ColLast]); -static void drawtext(const char *text, unsigned long col[ColLast], Bool invert); +static void drawtext(Drawable drawable, const char *text, unsigned long col[ColLast], Bool invert); +//static void drawtabtext(const char *text, unsigned long col[ColLast], Bool invert); static void enternotify(XEvent *e); static void expose(XEvent *e); static void focus(Client *c); +static void focuswin(const Arg* arg); static void focusin(XEvent *e); static void focusmon(const Arg *arg); static void focusstack(const Arg *arg); @@ -229,6 +245,7 @@ static int textnw(const char *text, unsigned int len); static void tile(Monitor *); static void togglebar(const Arg *arg); +static void toggletab(const Arg *arg); static void togglefloating(const Arg *arg); static void toggletag(const Arg *arg); static void toggleview(const Arg *arg); @@ -258,6 +275,7 @@ static int screen; static int sw, sh; /* X display screen geometry width, height */ static int bh, blw = 0; /* bar geometry */ +static int th = 0; /* tab bar geometry */ static int (*xerrorxlib)(Display *, XErrorEvent *); static unsigned int numlockmask = 0; static void (*handler[LASTEvent]) (XEvent *) = { @@ -287,6 +305,16 @@ /* configuration, allows nested code to access above variables */ #include "config.h" +struct Pertag { + unsigned int curtag, prevtag; /* current and previous tag */ + int nmasters[LENGTH(tags) + 1]; /* number of windows in master area */ + float mfacts[LENGTH(tags) + 1]; /* mfacts per tag */ + unsigned int sellts[LENGTH(tags) + 1]; /* selected layouts */ + const Layout *ltidxs[LENGTH(tags) + 1][2]; /* matrix of tags and layouts indexes */ + Bool showbars[LENGTH(tags) + 1]; /* display bar for the current tag */ + Bool showtabs[LENGTH(tags) + 1]; /* display tab bar for the current tag */ +}; + /* compile-time check if all tags fit into an unsigned int bit array. */ struct NumTags { char limitexceeded[LENGTH(tags) > 31 ? -1 : 1]; }; @@ -454,14 +482,32 @@ else click = ClkWinTitle; } + if(ev->window == selmon->tabwin) { + i = 0; x = 0; + for(c = selmon->clients; c; c = c->next){ + if(!ISVISIBLE(c)) continue; + x += selmon->tab_widths[i]; + if (ev->x > x) + ++i; + else + break; + if(i >= m->ntabs) break; + } + if(c) { + click = ClkTabBar; + arg.ui = i; + } + } else if((c = wintoclient(ev->window))) { focus(c); click = ClkClientWin; } for(i = 0; i < LENGTH(buttons); i++) if(click == buttons[i].click && buttons[i].func && buttons[i].button == ev->button - && CLEANMASK(buttons[i].mask) == CLEANMASK(ev->state)) - buttons[i].func(click == ClkTagBar && buttons[i].arg.i == 0 ? &arg : &buttons[i].arg); + && CLEANMASK(buttons[i].mask) == CLEANMASK(ev->state)){ + buttons[i].func(((click == ClkTagBar || click == ClkTabBar) + && buttons[i].arg.i == 0) ? &arg : &buttons[i].arg); + } } void @@ -491,6 +537,7 @@ XFreeFont(dpy, dc.font.xfont); XUngrabKey(dpy, AnyKey, AnyModifier, root); XFreePixmap(dpy, dc.drawable); + XFreePixmap(dpy, dc.tabdrawable); XFreeGC(dpy, dc.gc); XFreeCursor(dpy, cursor[CurNormal]); XFreeCursor(dpy, cursor[CurResize]); @@ -513,6 +560,8 @@ } XUnmapWindow(dpy, mon->barwin); XDestroyWindow(dpy, mon->barwin); + XUnmapWindow(dpy, mon->tabwin); + XDestroyWindow(dpy, mon->tabwin); free(mon); } @@ -581,9 +630,14 @@ if(dc.drawable != 0) XFreePixmap(dpy, dc.drawable); dc.drawable = XCreatePixmap(dpy, root, sw, bh, DefaultDepth(dpy, screen)); + if(dc.tabdrawable != 0) + XFreePixmap(dpy, dc.tabdrawable); + dc.tabdrawable = XCreatePixmap(dpy, root, sw, th, DefaultDepth(dpy, screen)); updatebars(); - for(m = mons; m; m = m->next) + for(m = mons; m; m = m->next){ XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, bh); + XMoveResizeWindow(dpy, m->tabwin, m->wx, m->ty, m->ww, th); + } focus(NULL); arrange(NULL); } @@ -646,6 +700,7 @@ Monitor * createmon(void) { Monitor *m; + int i; if(!(m = (Monitor *)calloc(1, sizeof(Monitor)))) die("fatal: could not malloc() %u bytes\n", sizeof(Monitor)); @@ -653,10 +708,34 @@ m->mfact = mfact; m->nmaster = nmaster; m->showbar = showbar; + m->showtab = showtab; m->topbar = topbar; + m->toptab = toptab; + m->ntabs = 0; m->lt[0] = &layouts[0]; m->lt[1] = &layouts[1 % LENGTH(layouts)]; strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol); + if(!(m->pertag = (Pertag *)calloc(1, sizeof(Pertag)))) + die("fatal: could not malloc() %u bytes\n", sizeof(Pertag)); + m->pertag->curtag = m->pertag->prevtag = 1; + for(i=0; i <= LENGTH(tags); i++) { + /* init nmaster */ + m->pertag->nmasters[i] = m->nmaster; + + /* init mfacts */ + m->pertag->mfacts[i] = m->mfact; + + /* init layouts */ + m->pertag->ltidxs[i][0] = m->lt[0]; + m->pertag->ltidxs[i][1] = m->lt[1]; + m->pertag->sellts[i] = m->sellt; + + /* init showbar */ + m->pertag->showbars[i] = m->showbar; + + /* init showtab */ + m->pertag->showtabs[i] = m->showtab; + } return m; } @@ -731,13 +810,13 @@ for(i = 0; i < LENGTH(tags); i++) { dc.w = TEXTW(tags[i]); col = m->tagset[m->seltags] & 1 << i ? dc.sel : dc.norm; - drawtext(tags[i], col, urg & 1 << i); + drawtext(dc.drawable, tags[i], col, urg & 1 << i); drawsquare(m == selmon && selmon->sel && selmon->sel->tags & 1 << i, occ & 1 << i, urg & 1 << i, col); dc.x += dc.w; } dc.w = blw = TEXTW(m->ltsymbol); - drawtext(m->ltsymbol, dc.norm, False); + drawtext(dc.drawable, m->ltsymbol, dc.norm, False); dc.x += dc.w; x = dc.x; if(m == selmon) { /* status is only drawn on selected monitor */ @@ -747,19 +826,20 @@ dc.x = x; dc.w = m->ww - x; } - drawtext(stext, dc.norm, False); + drawtext(dc.drawable, stext, dc.norm, False); } else dc.x = m->ww; if((dc.w = dc.x - x) > bh) { dc.x = x; if(m->sel) { - col = m == selmon ? dc.sel : dc.norm; - drawtext(m->sel->name, col, False); + // col = m == selmon ? dc.sel : dc.norm; + // drawtext(dc.drawable, m->sel->name, col, False); + drawtext(dc.drawable, m->sel->name, dc.norm, False); drawsquare(m->sel->isfixed, m->sel->isfloating, False, col); } else - drawtext(NULL, dc.norm, False); + drawtext(dc.drawable, NULL, dc.norm, False); } XCopyArea(dpy, dc.drawable, m->barwin, dc.gc, 0, 0, m->ww, bh, 0, 0); XSync(dpy, False); @@ -774,6 +854,104 @@ } void +drawtabs(void) { + Monitor *m; + + for(m = mons; m; m = m->next) + drawtab(m); +} + +static int +cmpint(const void *p1, const void *p2) { + /* The actual arguments to this function are "pointers to + pointers to char", but strcmp(3) arguments are "pointers + to char", hence the following cast plus dereference */ + return *((int*) p1) > * (int*) p2; +} + + +void +drawtab(Monitor *m) { + unsigned long *col; + Client *c; + int i; + int itag = -1; + char view_info[50]; + int view_info_w = 0; + int sorted_label_widths[MAXTABS]; + int tot_width; + int maxsize = bh; + dc.x = 0; + + //view_info: indicate the tag which is displayed in the view + for(i = 0; i < LENGTH(tags); ++i){ + if((selmon->tagset[selmon->seltags] >> i) & 1) { + if(itag >=0){ //more than one tag selected + itag = -1; + break; + } + itag = i; + } + } + if(0 <= itag && itag < LENGTH(tags)){ + snprintf(view_info, sizeof view_info, "[%s]", tags[itag]); + } else { + strncpy(view_info, "[...]", sizeof view_info); + } + view_info[sizeof(view_info) - 1 ] = 0; + view_info_w = TEXTW(view_info); + tot_width = view_info_w; + + /* Calculates number of labels and their width */ + m->ntabs = 0; + for(c = m->clients; c; c = c->next){ + if(!ISVISIBLE(c)) continue; + m->tab_widths[m->ntabs] = TEXTW(c->name); + tot_width += m->tab_widths[m->ntabs]; + ++m->ntabs; + if(m->ntabs >= MAXTABS) break; + } + + if(tot_width > m->ww){ //not enough space to display the labels, they need to be truncated + memcpy(sorted_label_widths, m->tab_widths, sizeof(int) * m->ntabs); + qsort(sorted_label_widths, m->ntabs, sizeof(int), cmpint); + tot_width = view_info_w; + for(i = 0; i < m->ntabs; ++i){ + if(tot_width + (m->ntabs - i) * sorted_label_widths[i] > m->ww) + break; + tot_width += sorted_label_widths[i]; + } + maxsize = (m->ww - tot_width) / (m->ntabs - i); + } else{ + maxsize = m->ww; + } + i = 0; + for(c = m->clients; c; c = c->next){ + if(!ISVISIBLE(c)) continue; + if(i >= m->ntabs) break; + if(m->tab_widths[i] > maxsize) m->tab_widths[i] = maxsize; + dc.w = m->tab_widths[i]; + col = (c == m->sel) ? dc.sel : dc.norm; + drawtext(dc.tabdrawable, c->name, col, 0); + dc.x += dc.w; + ++i; + } + + /* cleans interspace between window names and current viewed tag label */ + dc.w = m->ww - view_info_w - dc.x; + drawtext(dc.tabdrawable, NULL, dc.norm, 0); + + /* view info */ + dc.x += dc.w; + dc.w = view_info_w; + drawtext(dc.tabdrawable, view_info, dc.norm, 0); + + XCopyArea(dpy, dc.tabdrawable, m->tabwin, dc.gc, 0, 0, m->ww, th, 0, 0); + XSync(dpy, False); +} + + +void drawsquare(Bool filled, Bool empty, Bool invert, unsigned long col[ColLast]) { int x; @@ -785,13 +963,14 @@ XDrawRectangle(dpy, dc.drawable, dc.gc, dc.x+1, dc.y+1, x, x); } + void -drawtext(const char *text, unsigned long col[ColLast], Bool invert) { +drawtext(Drawable drawable, const char *text, unsigned long col[ColLast], Bool invert) { char buf[256]; int i, x, y, h, len, olen; XSetForeground(dpy, dc.gc, col[invert ? ColFG : ColBG]); - XFillRectangle(dpy, dc.drawable, dc.gc, dc.x, dc.y, dc.w, dc.h); + XFillRectangle(dpy, drawable, dc.gc, dc.x, dc.y, dc.w, dc.h); if(!text) return; olen = strlen(text); @@ -807,11 +986,12 @@ for(i = len; i && i > len - 3; buf[--i] = '.'); XSetForeground(dpy, dc.gc, col[invert ? ColBG : ColFG]); if(dc.font.set) - XmbDrawString(dpy, dc.drawable, dc.font.set, dc.gc, x, y, buf, len); + XmbDrawString(dpy, drawable, dc.font.set, dc.gc, x, y, buf, len); else - XDrawString(dpy, dc.drawable, dc.gc, x, y, buf, len); + XDrawString(dpy, drawable, dc.gc, x, y, buf, len); } + void enternotify(XEvent *e) { Client *c; @@ -836,8 +1016,10 @@ Monitor *m; XExposeEvent *ev = &e->xexpose; - if(ev->count == 0 && (m = wintomon(ev->window))) + if(ev->count == 0 && (m = wintomon(ev->window))){ drawbar(m); + drawtab(m); + } } void @@ -862,6 +1044,7 @@ XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime); selmon->sel = c; drawbars(); + drawtabs(); } void @@ -911,6 +1094,19 @@ } } +void +focuswin(const Arg* arg){ + int iwin = arg->i; + Client* c = NULL; + for(c = selmon->clients; c && (iwin || !ISVISIBLE(c)) ; c = c->next){ + if(ISVISIBLE(c)) --iwin; + }; + if(c) { + focus(c); + restack(selmon); + } +} + Atom getatomprop(Client *c, Atom prop) { int di; @@ -1028,7 +1224,7 @@ void incnmaster(const Arg *arg) { - selmon->nmaster = MAX(selmon->nmaster + arg->i, 0); + selmon->nmaster = selmon->pertag->nmasters[selmon->pertag->curtag] = MAX(selmon->nmaster + arg->i, 0); arrange(selmon); } @@ -1311,12 +1507,14 @@ case XA_WM_HINTS: updatewmhints(c); drawbars(); + drawtabs(); break; } if(ev->atom == XA_WM_NAME || ev->atom == netatom[NetWMName]) { updatetitle(c); if(c == c->mon->sel) drawbar(c->mon); + drawtab(c->mon); } if(ev->atom == netatom[NetWMWindowType]) updatewindowtype(c); @@ -1418,6 +1616,7 @@ XWindowChanges wc; drawbar(m); + drawtab(m); if(!m->sel) return; if(m->sel->isfloating || !m->lt[m->sellt]->arrange) @@ -1555,10 +1754,13 @@ void setlayout(const Arg *arg) { - if(!arg || !arg->v || arg->v != selmon->lt[selmon->sellt]) - selmon->sellt ^= 1; + if(!arg || !arg->v || arg->v != selmon->lt[selmon->sellt]) { + selmon->pertag->sellts[selmon->pertag->curtag] ^= 1; + selmon->sellt = selmon->pertag->sellts[selmon->pertag->curtag]; + } if(arg && arg->v) - selmon->lt[selmon->sellt] = (Layout *)arg->v; + selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt] = (Layout *)arg->v; + selmon->lt[selmon->sellt] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt]; strncpy(selmon->ltsymbol, selmon->lt[selmon->sellt]->symbol, sizeof selmon->ltsymbol); if(selmon->sel) arrange(selmon); @@ -1576,7 +1778,7 @@ f = arg->f < 1.0 ? arg->f + selmon->mfact : arg->f - 1.0; if(f < 0.1 || f > 0.9) return; - selmon->mfact = f; + selmon->mfact = selmon->pertag->mfacts[selmon->pertag->curtag] = f; arrange(selmon); } @@ -1594,6 +1796,7 @@ sw = DisplayWidth(dpy, screen); sh = DisplayHeight(dpy, screen); bh = dc.h = dc.font.height + 2; + th = bh; updategeom(); /* init atoms */ wmatom[WMProtocols] = XInternAtom(dpy, "WM_PROTOCOLS", False); @@ -1619,6 +1822,7 @@ dc.sel[ColBG] = getcolor(selbgcolor); dc.sel[ColFG] = getcolor(selfgcolor); dc.drawable = XCreatePixmap(dpy, root, DisplayWidth(dpy, screen), bh, DefaultDepth(dpy, screen)); + dc.tabdrawable = XCreatePixmap(dpy, root, DisplayWidth(dpy, screen), th, DefaultDepth(dpy, screen)); dc.gc = XCreateGC(dpy, root, 0, NULL); XSetLineAttributes(dpy, dc.gc, 1, LineSolid, CapButt, JoinMiter); if(!dc.font.set) @@ -1729,13 +1933,22 @@ void togglebar(const Arg *arg) { - selmon->showbar = !selmon->showbar; + selmon->showbar = selmon->pertag->showbars[selmon->pertag->curtag] = !selmon->showbar; updatebarpos(selmon); XMoveResizeWindow(dpy, selmon->barwin, selmon->wx, selmon->by, selmon->ww, bh); arrange(selmon); } void +toggletab(const Arg *arg) { + selmon->showtab = selmon->pertag->showtabs[selmon->pertag->curtag] = !selmon->showtab; + updatebarpos(selmon); + XMoveResizeWindow(dpy, selmon->tabwin, selmon->wx, selmon->ty, selmon->ww, th); + arrange(selmon); +} + + +void togglefloating(const Arg *arg) { if(!selmon->sel) return; @@ -1763,9 +1976,31 @@ void toggleview(const Arg *arg) { unsigned int newtagset = selmon->tagset[selmon->seltags] ^ (arg->ui & TAGMASK); + int i; if(newtagset) { + if(newtagset == ~0) { + selmon->pertag->prevtag = selmon->pertag->curtag; + selmon->pertag->curtag = 0; + } + /* test if the user did not select the same tag */ + if(!(newtagset & 1 << (selmon->pertag->curtag - 1))) { + selmon->pertag->prevtag = selmon->pertag->curtag; + for (i=0; !(newtagset & 1 << i); i++) ; + selmon->pertag->curtag = i + 1; + } selmon->tagset[selmon->seltags] = newtagset; + + /* apply settings for this view */ + selmon->nmaster = selmon->pertag->nmasters[selmon->pertag->curtag]; + selmon->mfact = selmon->pertag->mfacts[selmon->pertag->curtag]; + selmon->sellt = selmon->pertag->sellts[selmon->pertag->curtag]; + selmon->lt[selmon->sellt] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt]; + selmon->lt[selmon->sellt^1] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt^1]; + if (selmon->showbar != selmon->pertag->showbars[selmon->pertag->curtag]) + togglebar(NULL); + if (selmon->showtab != selmon->pertag->showtabs[selmon->pertag->curtag]) + toggletab(NULL); focus(NULL); arrange(selmon); } @@ -1832,6 +2067,11 @@ CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa); XDefineCursor(dpy, m->barwin, cursor[CurNormal]); XMapRaised(dpy, m->barwin); + m->tabwin = XCreateWindow(dpy, root, m->wx, m->ty, m->ww, th, 0, DefaultDepth(dpy, screen), + CopyFromParent, DefaultVisual(dpy, screen), + CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa); + XDefineCursor(dpy, m->tabwin, cursor[CurNormal]); + XMapRaised(dpy, m->tabwin); } } @@ -1842,10 +2082,20 @@ if(m->showbar) { m->wh -= bh; m->by = m->topbar ? m->wy : m->wy + m->wh; - m->wy = m->topbar ? m->wy + bh : m->wy; + if ( m->topbar ) + m->wy += bh; + } else { + m->by = -bh; + } + + if(m->showtab) { + m->wh -= th; + m->ty = m->toptab ? m->wy : m->wy + m->wh; + if ( m->toptab ) + m->wy += th; + } else { + m->ty = -th; } - else - m->by = -bh; } Bool @@ -2043,11 +2293,35 @@ void view(const Arg *arg) { + int i; + unsigned int tmptag; + if((arg->ui & TAGMASK) == selmon->tagset[selmon->seltags]) return; selmon->seltags ^= 1; /* toggle sel tagset */ - if(arg->ui & TAGMASK) + if(arg->ui & TAGMASK) { + selmon->pertag->prevtag = selmon->pertag->curtag; selmon->tagset[selmon->seltags] = arg->ui & TAGMASK; + if(arg->ui == ~0) + selmon->pertag->curtag = 0; + else { + for (i=0; !(arg->ui & 1 << i); i++) ; + selmon->pertag->curtag = i + 1; + } + } else { + tmptag = selmon->pertag->prevtag; + selmon->pertag->prevtag = selmon->pertag->curtag; + selmon->pertag->curtag = tmptag; + } + selmon->nmaster = selmon->pertag->nmasters[selmon->pertag->curtag]; + selmon->mfact = selmon->pertag->mfacts[selmon->pertag->curtag]; + selmon->sellt = selmon->pertag->sellts[selmon->pertag->curtag]; + selmon->lt[selmon->sellt] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt]; + selmon->lt[selmon->sellt^1] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt^1]; + if (selmon->showbar != selmon->pertag->showbars[selmon->pertag->curtag]) + togglebar(NULL); + if (selmon->showtab != selmon->pertag->showtabs[selmon->pertag->curtag]) + toggletab(NULL); focus(NULL); arrange(selmon); } @@ -2073,7 +2347,7 @@ if(w == root && getrootptr(&x, &y)) return recttomon(x, y, 1, 1); for(m = mons; m; m = m->next) - if(w == m->barwin) + if(w == m->barwin || w == m->tabwin) return m; if((c = wintoclient(w))) return c->mon;