diff options
author | Eddy Pedroni <epedroni@pm.me> | 2023-12-16 17:32:10 +0100 |
---|---|---|
committer | Eddy Pedroni <epedroni@pm.me> | 2023-12-16 17:40:49 +0100 |
commit | 8d054f66e8ce3835b552936b34c4bd3baf2ecc09 (patch) | |
tree | 7a8b69cd682d6f67fe30d43a6a1e70735cc66a17 | |
parent | 5cf50e5fcb40ef48a8a92c4a00714a1174e17fc9 (diff) |
Apply pertag-tab v2b 6.1 patch, fix conflicts
-rw-r--r-- | config.def.h | 14 | ||||
-rw-r--r-- | dwm.1 | 33 | ||||
-rw-r--r-- | dwm.c | 347 |
3 files changed, 354 insertions, 40 deletions
diff --git a/config.def.h b/config.def.h index 9efa774..e458a03 100644 --- a/config.def.h +++ b/config.def.h @@ -18,9 +18,21 @@ static const char *colors[][3] = { [SchemeSel] = { col_gray4, col_cyan, col_cyan }, }; +/* Display modes of the tab bar: never shown, always shown, shown only in */ +/* monocle mode in presence of several windows. */ +/* Modes after showtab_nmodes are disabled */ +enum showtab_modes { showtab_never, showtab_auto, showtab_nmodes, showtab_always}; +static const int showtab = showtab_auto; /* Default tab bar show mode */ +static const Bool toptab = False; /* False means bottom tab bar */ + /* tagging */ static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" }; +/* default layout per tags */ +/* The first element is for all-tag view, following i-th element corresponds to */ +/* tags[i]. Layout is referred using the layouts array index.*/ +static int def_layouts[1 + LENGTH(tags)] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + static const Rule rules[] = { /* xprop(1): * WM_CLASS(STRING) = instance, class @@ -65,6 +77,7 @@ static const Key keys[] = { { MODKEY, XK_p, spawn, {.v = dmenucmd } }, { MODKEY|ShiftMask, XK_Return, spawn, {.v = termcmd } }, { MODKEY, XK_b, togglebar, {0} }, + { MODKEY, XK_w, tabmode, {-1} }, { MODKEY, XK_j, focusstack, {.i = +1 } }, { MODKEY, XK_k, focusstack, {.i = -1 } }, { MODKEY, XK_i, incnmaster, {.i = +1 } }, @@ -112,5 +125,6 @@ static const Button buttons[] = { { ClkTagBar, 0, Button3, toggleview, {0} }, { ClkTagBar, MODKEY, Button1, tag, {0} }, { ClkTagBar, MODKEY, Button3, toggletag, {0} }, + { ClkTabBar, 0, Button1, focuswin, {0} }, }; @@ -20,14 +20,22 @@ layout applied. 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 small status bars. +.P +One 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 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 +Another bar contains a tab for each window of the current view and allows +navigation between windows, especially in the monocle mode. The different +display modes of this bar are described under the Mod1\-w Keybord command +section. When a single tag is selected, that tag is indicated in the left corner +of the tab bar. .P dwm draws a small border around windows to indicate the focus state. .SH OPTIONS @@ -44,7 +52,8 @@ command. .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. @@ -110,6 +119,12 @@ Increase master area size. .B Mod1\-h Decrease master area size. .TP +.B Mod1\-w +Cycle over the tab bar display modes: never displayed, always displayed, +displayed only in monocle mode when the view contains than one window (auto +mode). Some display modes can be disabled in the configuration, config.h. In +the default configuration only "never" and "auto" display modes are enabled. +.TP .B Mod1\-Return Zooms/cycles focused window to/from master area (tiled layouts only). .TP @@ -64,7 +64,7 @@ enum { NetSupported, NetWMName, NetWMState, NetWMCheck, NetWMFullscreen, NetActiveWindow, NetWMWindowType, NetWMWindowTypeDialog, NetClientList, 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 { @@ -111,25 +111,35 @@ typedef struct { void (*arrange)(Monitor *); } Layout; +#define MAXTABS 50 + +typedef struct Pertag Pertag; 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]; int showbar; + int showtab; int topbar; + int 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 { @@ -163,6 +173,8 @@ static void detachstack(Client *c); 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 enternotify(XEvent *e); static void expose(XEvent *e); static void focus(Client *c); @@ -170,6 +182,7 @@ static void focusin(XEvent *e); static void focusmon(const Arg *arg); static void focusstack(const Arg *arg); static Atom getatomprop(Client *c, Atom prop); +static void focuswin(const Arg* arg); static int getrootptr(int *x, int *y); static long getstate(Window w); static int gettextprop(Window w, Atom atom, char *text, unsigned int size); @@ -206,6 +219,7 @@ static void setup(void); static void seturgent(Client *c, int urg); static void showhide(Client *c); static void spawn(const Arg *arg); +static void tabmode(const Arg *arg); static void tag(const Arg *arg); static void tagmon(const Arg *arg); static void tile(Monitor *m); @@ -240,6 +254,7 @@ static char stext[256]; static int screen; static int sw, sh; /* X display screen geometry width, height */ static int bh; /* bar height */ +static int th; /* tab bar geometry */ static int lrpad; /* sum of left and right padding for text */ static int (*xerrorxlib)(Display *, XErrorEvent *); static unsigned int numlockmask = 0; @@ -271,6 +286,16 @@ static Window root, wmcheckwin; /* 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 */ + Client *prevzooms[LENGTH(tags) + 1]; /* store zoom information */ +}; + /* compile-time check if all tags fit into an unsigned int bit array. */ struct NumTags { char limitexceeded[LENGTH(tags) > 31 ? -1 : 1]; }; @@ -396,6 +421,8 @@ arrange(Monitor *m) void arrangemon(Monitor *m) { + updatebarpos(m); + XMoveResizeWindow(dpy, m->tabwin, m->wx, m->ty, m->ww, th); strncpy(m->ltsymbol, m->lt[m->sellt]->symbol, sizeof m->ltsymbol); if (m->lt[m->sellt]->arrange) m->lt[m->sellt]->arrange(m); @@ -445,16 +472,35 @@ buttonpress(XEvent *e) click = ClkStatusText; else click = ClkWinTitle; - } else if ((c = wintoclient(ev->window))) { + } + 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); restack(selmon); XAllowEvents(dpy, ReplayPointer, CurrentTime); 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); + 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 || click == ClkTabBar) + && buttons[i].arg.i == 0) ? &arg : &buttons[i].arg); + } } void @@ -474,13 +520,13 @@ cleanup(void) Arg a = {.ui = ~0}; Layout foo = { "", NULL }; Monitor *m; - size_t i; + size_t i; view(&a); selmon->lt[selmon->sellt] = &foo; for (m = mons; m; m = m->next) - while (m->stack) - unmanage(m->stack, 0); + while(m->stack) + unmanage(m->stack, False); XUngrabKey(dpy, AnyKey, AnyModifier, root); while (mons) cleanupmon(mons); @@ -509,6 +555,8 @@ cleanupmon(Monitor *mon) } XUnmapWindow(dpy, mon->barwin); XDestroyWindow(dpy, mon->barwin); + XUnmapWindow(dpy, mon->tabwin); + XDestroyWindow(dpy, mon->tabwin); free(mon); } @@ -517,6 +565,7 @@ clientmessage(XEvent *e) { XClientMessageEvent *cme = &e->xclient; Client *c = wintoclient(cme->window); + int i; if (!c) return; @@ -528,6 +577,13 @@ clientmessage(XEvent *e) } else if (cme->message_type == netatom[NetActiveWindow]) { if (c != selmon->sel && !c->isurgent) seturgent(c, 1); + if (!ISVISIBLE(c)) { + c->mon->seltags ^= 1; + c->mon->tagset[c->mon->seltags] = c->tags; + for(i=0; !(c->tags & 1 << i); i++); + view(&(Arg){.ui = 1 << i}); + } + pop(c); } } @@ -566,6 +622,8 @@ configurenotify(XEvent *e) if (updategeom() || dirty) { drw_resize(drw, sw, bh); updatebars(); + //refreshing display of status bar. The tab bar is handled by the arrange() + //method, which is called below for (m = mons; m; m = m->next) { for (c = m->clients; c; c = c->next) if (c->isfullscreen) @@ -634,16 +692,41 @@ Monitor * createmon(void) { Monitor *m; + int i; m = ecalloc(1, sizeof(Monitor)); m->tagset[0] = m->tagset[1] = 1; m->mfact = mfact; m->nmaster = nmaster; m->showbar = showbar; + m->showtab = showtab; m->topbar = topbar; - m->lt[0] = &layouts[0]; + m->toptab = toptab; + m->ntabs = 0; + m->lt[0] = &layouts[def_layouts[1] % LENGTH(layouts)]; 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] = &layouts[def_layouts[i % LENGTH(def_layouts)] % LENGTH(layouts)]; + m->pertag->ltidxs[i][1] = m->lt[1]; + m->pertag->sellts[i] = m->sellt; + + /* init showbar */ + m->pertag->showbars[i] = m->showbar; + + /* swap focus and zoomswap*/ + m->pertag->prevzooms[i] = NULL; + } return m; } @@ -758,6 +841,104 @@ drawbars(void) } 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) { + 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; + int x = 0; + int w = 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; + w = m->tab_widths[i]; + drw_setscheme(drw, (c == m->sel) ? scheme[SchemeSel] : scheme[SchemeNorm]); + drw_text(drw, x, 0, w, th, lrpad / 2, c->name, 0); + x += w; + ++i; + } + + drw_setscheme(drw, scheme[SchemeNorm]); + + /* cleans interspace between window names and current viewed tag label */ + w = m->ww - view_info_w - x; + drw_text(drw, x, 0, w, th, lrpad / 2, "", 0); + + /* view info */ + x += w; + w = view_info_w; + drw_text(drw, x, 0, w, th, lrpad / 2, view_info, 0); + + drw_map(drw, m->tabwin, 0, 0, m->ww, th); +} + +void enternotify(XEvent *e) { Client *c; @@ -782,8 +963,10 @@ expose(XEvent *e) 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 @@ -809,6 +992,7 @@ focus(Client *c) } selmon->sel = c; drawbars(); + drawtabs(); } /* there are some broken focus acquiring clients needing extra handling */ @@ -861,6 +1045,19 @@ focusstack(const Arg *arg) } } +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) { @@ -980,7 +1177,7 @@ grabkeys(void) 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); } @@ -1135,7 +1332,7 @@ motionnotify(XEvent *e) if (ev->window != root) return; if ((m = recttomon(ev->x_root, ev->y_root, 1, 1)) != mon && mon) { - unfocus(selmon->sel, 1); + unfocus(selmon->sel, True); selmon = m; focus(NULL); } @@ -1155,6 +1352,8 @@ movemouse(const Arg *arg) return; if (c->isfullscreen) /* no support moving fullscreen windows by mouse */ return; + if(c->isfullscreen) /* no support moving fullscreen windows by mouse */ + return; restack(selmon); ocx = c->x; ocy = c->y; @@ -1243,12 +1442,14 @@ propertynotify(XEvent *e) 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); @@ -1310,6 +1511,8 @@ resizemouse(const Arg *arg) return; if (c->isfullscreen) /* no support resizing fullscreen windows by mouse */ return; + if(c->isfullscreen) /* no support resizing fullscreen windows by mouse */ + return; restack(selmon); ocx = c->x; ocy = c->y; @@ -1362,6 +1565,7 @@ restack(Monitor *m) XWindowChanges wc; drawbar(m); + drawtab(m); if (!m->sel) return; if (m->sel->isfloating || !m->lt[m->sellt]->arrange) @@ -1470,7 +1674,7 @@ sendevent(Client *c, Atom proto) void setfocus(Client *c) { - if (!c->neverfocus) { + if(!c->neverfocus) { XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime); XChangeProperty(dpy, root, netatom[NetActiveWindow], XA_WINDOW, 32, PropModeReplace, @@ -1510,10 +1714,13 @@ setfullscreen(Client *c, int fullscreen) void setlayout(const Arg *arg) { - if (!arg || !arg->v || arg->v != selmon->lt[selmon->sellt]) - selmon->sellt ^= 1; - if (arg && arg->v) - selmon->lt[selmon->sellt] = (Layout *)arg->v; + 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->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); @@ -1532,7 +1739,7 @@ setmfact(const Arg *arg) f = arg->f < 1.0 ? arg->f + selmon->mfact : arg->f - 1.0; if (f < 0.05 || f > 0.95) return; - selmon->mfact = f; + selmon->mfact = selmon->pertag->mfacts[selmon->pertag->curtag] = f; arrange(selmon); } @@ -1563,6 +1770,7 @@ setup(void) die("no fonts could be loaded."); lrpad = drw->fonts->h; bh = drw->fonts->h + 2; + th = bh; updategeom(); /* init atoms */ utf8string = XInternAtom(dpy, "UTF8_STRING", False); @@ -1651,8 +1859,8 @@ spawn(const Arg *arg) if (arg->v == dmenucmd) dmenumon[0] = '0' + selmon->num; - if (fork() == 0) { - if (dpy) + if(fork() == 0) { + if(dpy) close(ConnectionNumber(dpy)); setsid(); @@ -1715,18 +1923,29 @@ tile(Monitor *m) 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 +tabmode(const Arg *arg) +{ + if(arg && arg->i >= 0) + selmon->showtab = arg->ui % showtab_nmodes; + else + selmon->showtab = (selmon->showtab + 1 ) % showtab_nmodes; + arrange(selmon); +} + + +void togglefloating(const Arg *arg) { - if (!selmon->sel) + if(!selmon->sel) return; - if (selmon->sel->isfullscreen) /* no support for fullscreen windows */ + if(selmon->sel->isfullscreen) /* no support for fullscreen windows */ return; selmon->sel->isfloating = !selmon->sel->isfloating || selmon->sel->isfixed; if (selmon->sel->isfloating) @@ -1754,9 +1973,29 @@ 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); focus(NULL); arrange(selmon); } @@ -1834,20 +2073,44 @@ updatebars(void) XDefineCursor(dpy, m->barwin, cursor[CurNormal]->cursor); XMapRaised(dpy, m->barwin); XSetClassHint(dpy, m->barwin, &ch); + 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]->cursor); + XMapRaised(dpy, m->tabwin); } } void updatebarpos(Monitor *m) { + Client *c; + int nvis = 0; + m->wy = m->my; m->wh = m->mh; 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; - } else + if ( m->topbar ) + m->wy += bh; + } else { m->by = -bh; + } + + for(c = m->clients; c; c = c->next){ + if(ISVISIBLE(c)) ++nvis; + } + + if(m->showtab == showtab_always + || ((m->showtab == showtab_auto) && (nvis > 1) && (m->lt[m->sellt]->arrange == monocle))){ + m->wh -= th; + m->ty = m->toptab ? m->wy : m->wy + m->wh; + if ( m->toptab ) + m->wy += th; + } else { + m->ty = -th; + } } void @@ -2026,9 +2289,9 @@ updatewindowtype(Client *c) Atom wtype = getatomprop(c, netatom[NetWMWindowType]); if (state == netatom[NetWMFullscreen]) - setfullscreen(c, 1); + setfullscreen(c, True); if (wtype == netatom[NetWMWindowTypeDialog]) - c->isfloating = 1; + c->isfloating = True; } void @@ -2053,11 +2316,33 @@ updatewmhints(Client *c) void view(const Arg *arg) { - if ((arg->ui & TAGMASK) == selmon->tagset[selmon->seltags]) + 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); focus(NULL); arrange(selmon); } @@ -2085,7 +2370,7 @@ wintomon(Window w) 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; |