dwm-6.0-pertag-tab.diff - sites - public wiki contents of suckless.org
HTML git clone git://git.suckless.org/sites
DIR Log
DIR Files
DIR Refs
---
dwm-6.0-pertag-tab.diff (23754B)
---
1 diff -u dwm-6.0-orig/config.def.h dwm-6.0-pertag-tab/config.def.h
2 --- dwm-6.0-orig/config.def.h 2011-12-19 16:02:46.000000000 +0100
3 +++ dwm-6.0-pertag-tab/config.def.h 2013-06-23 00:06:48.000000000 +0200
4 @@ -12,6 +12,9 @@
5 static const unsigned int snap = 32; /* snap pixel */
6 static const Bool showbar = True; /* False means no bar */
7 static const Bool topbar = True; /* False means bottom bar */
8 +static const Bool showtab = True; /* False means no tab bar */
9 +static const Bool toptab = False; /* False means bottom tab bar */
10 +
11
12 /* tagging */
13 static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" };
14 @@ -25,7 +28,7 @@
15 /* layout(s) */
16 static const float mfact = 0.55; /* factor of master area size [0.05..0.95] */
17 static const int nmaster = 1; /* number of clients in master area */
18 -static const Bool resizehints = True; /* True means respect size hints in tiled resizals */
19 +static const Bool resizehints = False; /* True means respect size hints in tiled resizals */
20
21 static const Layout layouts[] = {
22 /* symbol arrange function */
23 @@ -54,6 +57,7 @@
24 { MODKEY, XK_p, spawn, {.v = dmenucmd } },
25 { MODKEY|ShiftMask, XK_Return, spawn, {.v = termcmd } },
26 { MODKEY, XK_b, togglebar, {0} },
27 + { MODKEY, XK_w, toggletab, {0} },
28 { MODKEY, XK_j, focusstack, {.i = +1 } },
29 { MODKEY, XK_k, focusstack, {.i = -1 } },
30 { MODKEY, XK_i, incnmaster, {.i = +1 } },
31 @@ -101,5 +105,6 @@
32 { ClkTagBar, 0, Button3, toggleview, {0} },
33 { ClkTagBar, MODKEY, Button1, tag, {0} },
34 { ClkTagBar, MODKEY, Button3, toggletag, {0} },
35 + { ClkTabBar, 0, Button1, focuswin, {0} },
36 };
37
38 diff -u dwm-6.0-orig/dwm.1 dwm-6.0-pertag-tab/dwm.1
39 --- dwm-6.0-orig/dwm.1 2011-12-19 16:02:46.000000000 +0100
40 +++ dwm-6.0-pertag-tab/dwm.1 2013-06-23 00:21:16.000000000 +0200
41 @@ -19,14 +19,16 @@
42 Windows are grouped by tags. Each window can be tagged with one or multiple
43 tags. Selecting certain tags displays all windows with these tags.
44 .P
45 -Each screen contains a small status bar which displays all available tags, the
46 -layout, the title of the focused window, and the text read from the root window
47 -name property, if the screen is focused. A floating window is indicated with an
48 -empty square and a maximised floating window is indicated with a filled square
49 -before the windows title. The selected tags are indicated with a different
50 -color. The tags of the focused window are indicated with a filled square in the
51 -top left corner. The tags which are applied to one or more windows are
52 -indicated with an empty square in the top left corner.
53 +Each screen contains two bars. A small status bar displays all available tags,
54 +the layout, the title of the focused window, and the text read from the root
55 +window name property, if the screen is focused. A small tab bar lists the
56 +windows in the current view and allows navigation from window to window,
57 +especially in the monocle mode. A floating window is indicated with an empty
58 +square and a maximised floating window is indicated with a filled square before
59 +the windows title. The selected tags are indicated with a different color. The
60 +tags of the focused window are indicated with a filled square in the top left
61 +corner. The tags which are applied to one or more windows are indicated with an
62 +empty square in the top left corner.
63 .P
64 dwm draws a small border around windows to indicate the focus state.
65 .SH OPTIONS
66 @@ -43,7 +45,8 @@
67 .TP
68 .B Button1
69 click on a tag label to display all windows with that tag, click on the layout
70 -label toggles between tiled and floating layout.
71 +label toggles between tiled and floating layout, click on a window name in the
72 +tab bar brings focus to that window.
73 .TP
74 .B Button3
75 click on a tag label adds/removes all windows with that tag to/from the view.
76 @@ -104,6 +107,9 @@
77 .B Mod1\-h
78 Decrease master area size.
79 .TP
80 +.B Mod1\-w
81 +Toggle the tab bar.
82 +.TP
83 .B Mod1\-Return
84 Zooms/cycles focused window to/from master area (tiled layouts only).
85 .TP
86 diff -u dwm-6.0-orig/dwm.c dwm-6.0-pertag-tab/dwm.c
87 --- dwm-6.0-orig/dwm.c 2011-12-19 16:02:46.000000000 +0100
88 +++ dwm-6.0-pertag-tab/dwm.c 2013-06-23 16:57:10.000000000 +0200
89 @@ -62,7 +62,7 @@
90 NetWMFullscreen, NetActiveWindow, NetWMWindowType,
91 NetWMWindowTypeDialog, NetLast }; /* EWMH atoms */
92 enum { WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast }; /* default atoms */
93 -enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle,
94 +enum { ClkTagBar, ClkTabBar, ClkLtSymbol, ClkStatusText, ClkWinTitle,
95 ClkClientWin, ClkRootWin, ClkLast }; /* clicks */
96
97 typedef union {
98 @@ -102,6 +102,7 @@
99 unsigned long norm[ColLast];
100 unsigned long sel[ColLast];
101 Drawable drawable;
102 + Drawable tabdrawable;
103 GC gc;
104 struct {
105 int ascent;
106 @@ -124,25 +125,36 @@
107 void (*arrange)(Monitor *);
108 } Layout;
109
110 +typedef struct Pertag Pertag;
111 +
112 +#define MAXTABS 50
113 +
114 struct Monitor {
115 char ltsymbol[16];
116 float mfact;
117 int nmaster;
118 int num;
119 int by; /* bar geometry */
120 + int ty; /* tab bar geometry */
121 int mx, my, mw, mh; /* screen size */
122 int wx, wy, ww, wh; /* window area */
123 unsigned int seltags;
124 unsigned int sellt;
125 unsigned int tagset[2];
126 Bool showbar;
127 + Bool showtab;
128 Bool topbar;
129 + Bool toptab;
130 Client *clients;
131 Client *sel;
132 Client *stack;
133 Monitor *next;
134 Window barwin;
135 + Window tabwin;
136 + int ntabs;
137 + int tab_widths[MAXTABS];
138 const Layout *lt[2];
139 + Pertag *pertag;
140 };
141
142 typedef struct {
143 @@ -178,11 +190,15 @@
144 static Monitor *dirtomon(int dir);
145 static void drawbar(Monitor *m);
146 static void drawbars(void);
147 +static void drawtab(Monitor *m);
148 +static void drawtabs(void);
149 static void drawsquare(Bool filled, Bool empty, Bool invert, unsigned long col[ColLast]);
150 -static void drawtext(const char *text, unsigned long col[ColLast], Bool invert);
151 +static void drawtext(Drawable drawable, const char *text, unsigned long col[ColLast], Bool invert);
152 +//static void drawtabtext(const char *text, unsigned long col[ColLast], Bool invert);
153 static void enternotify(XEvent *e);
154 static void expose(XEvent *e);
155 static void focus(Client *c);
156 +static void focuswin(const Arg* arg);
157 static void focusin(XEvent *e);
158 static void focusmon(const Arg *arg);
159 static void focusstack(const Arg *arg);
160 @@ -229,6 +245,7 @@
161 static int textnw(const char *text, unsigned int len);
162 static void tile(Monitor *);
163 static void togglebar(const Arg *arg);
164 +static void toggletab(const Arg *arg);
165 static void togglefloating(const Arg *arg);
166 static void toggletag(const Arg *arg);
167 static void toggleview(const Arg *arg);
168 @@ -258,6 +275,7 @@
169 static int screen;
170 static int sw, sh; /* X display screen geometry width, height */
171 static int bh, blw = 0; /* bar geometry */
172 +static int th = 0; /* tab bar geometry */
173 static int (*xerrorxlib)(Display *, XErrorEvent *);
174 static unsigned int numlockmask = 0;
175 static void (*handler[LASTEvent]) (XEvent *) = {
176 @@ -287,6 +305,16 @@
177 /* configuration, allows nested code to access above variables */
178 #include "config.h"
179
180 +struct Pertag {
181 + unsigned int curtag, prevtag; /* current and previous tag */
182 + int nmasters[LENGTH(tags) + 1]; /* number of windows in master area */
183 + float mfacts[LENGTH(tags) + 1]; /* mfacts per tag */
184 + unsigned int sellts[LENGTH(tags) + 1]; /* selected layouts */
185 + const Layout *ltidxs[LENGTH(tags) + 1][2]; /* matrix of tags and layouts indexes */
186 + Bool showbars[LENGTH(tags) + 1]; /* display bar for the current tag */
187 + Bool showtabs[LENGTH(tags) + 1]; /* display tab bar for the current tag */
188 +};
189 +
190 /* compile-time check if all tags fit into an unsigned int bit array. */
191 struct NumTags { char limitexceeded[LENGTH(tags) > 31 ? -1 : 1]; };
192
193 @@ -454,14 +482,32 @@
194 else
195 click = ClkWinTitle;
196 }
197 + if(ev->window == selmon->tabwin) {
198 + i = 0; x = 0;
199 + for(c = selmon->clients; c; c = c->next){
200 + if(!ISVISIBLE(c)) continue;
201 + x += selmon->tab_widths[i];
202 + if (ev->x > x)
203 + ++i;
204 + else
205 + break;
206 + if(i >= m->ntabs) break;
207 + }
208 + if(c) {
209 + click = ClkTabBar;
210 + arg.ui = i;
211 + }
212 + }
213 else if((c = wintoclient(ev->window))) {
214 focus(c);
215 click = ClkClientWin;
216 }
217 for(i = 0; i < LENGTH(buttons); i++)
218 if(click == buttons[i].click && buttons[i].func && buttons[i].button == ev->button
219 - && CLEANMASK(buttons[i].mask) == CLEANMASK(ev->state))
220 - buttons[i].func(click == ClkTagBar && buttons[i].arg.i == 0 ? &arg : &buttons[i].arg);
221 + && CLEANMASK(buttons[i].mask) == CLEANMASK(ev->state)){
222 + buttons[i].func(((click == ClkTagBar || click == ClkTabBar)
223 + && buttons[i].arg.i == 0) ? &arg : &buttons[i].arg);
224 + }
225 }
226
227 void
228 @@ -491,6 +537,7 @@
229 XFreeFont(dpy, dc.font.xfont);
230 XUngrabKey(dpy, AnyKey, AnyModifier, root);
231 XFreePixmap(dpy, dc.drawable);
232 + XFreePixmap(dpy, dc.tabdrawable);
233 XFreeGC(dpy, dc.gc);
234 XFreeCursor(dpy, cursor[CurNormal]);
235 XFreeCursor(dpy, cursor[CurResize]);
236 @@ -513,6 +560,8 @@
237 }
238 XUnmapWindow(dpy, mon->barwin);
239 XDestroyWindow(dpy, mon->barwin);
240 + XUnmapWindow(dpy, mon->tabwin);
241 + XDestroyWindow(dpy, mon->tabwin);
242 free(mon);
243 }
244
245 @@ -581,9 +630,14 @@
246 if(dc.drawable != 0)
247 XFreePixmap(dpy, dc.drawable);
248 dc.drawable = XCreatePixmap(dpy, root, sw, bh, DefaultDepth(dpy, screen));
249 + if(dc.tabdrawable != 0)
250 + XFreePixmap(dpy, dc.tabdrawable);
251 + dc.tabdrawable = XCreatePixmap(dpy, root, sw, th, DefaultDepth(dpy, screen));
252 updatebars();
253 - for(m = mons; m; m = m->next)
254 + for(m = mons; m; m = m->next){
255 XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, bh);
256 + XMoveResizeWindow(dpy, m->tabwin, m->wx, m->ty, m->ww, th);
257 + }
258 focus(NULL);
259 arrange(NULL);
260 }
261 @@ -646,6 +700,7 @@
262 Monitor *
263 createmon(void) {
264 Monitor *m;
265 + int i;
266
267 if(!(m = (Monitor *)calloc(1, sizeof(Monitor))))
268 die("fatal: could not malloc() %u bytes\n", sizeof(Monitor));
269 @@ -653,10 +708,34 @@
270 m->mfact = mfact;
271 m->nmaster = nmaster;
272 m->showbar = showbar;
273 + m->showtab = showtab;
274 m->topbar = topbar;
275 + m->toptab = toptab;
276 + m->ntabs = 0;
277 m->lt[0] = &layouts[0];
278 m->lt[1] = &layouts[1 % LENGTH(layouts)];
279 strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol);
280 + if(!(m->pertag = (Pertag *)calloc(1, sizeof(Pertag))))
281 + die("fatal: could not malloc() %u bytes\n", sizeof(Pertag));
282 + m->pertag->curtag = m->pertag->prevtag = 1;
283 + for(i=0; i <= LENGTH(tags); i++) {
284 + /* init nmaster */
285 + m->pertag->nmasters[i] = m->nmaster;
286 +
287 + /* init mfacts */
288 + m->pertag->mfacts[i] = m->mfact;
289 +
290 + /* init layouts */
291 + m->pertag->ltidxs[i][0] = m->lt[0];
292 + m->pertag->ltidxs[i][1] = m->lt[1];
293 + m->pertag->sellts[i] = m->sellt;
294 +
295 + /* init showbar */
296 + m->pertag->showbars[i] = m->showbar;
297 +
298 + /* init showtab */
299 + m->pertag->showtabs[i] = m->showtab;
300 + }
301 return m;
302 }
303
304 @@ -731,13 +810,13 @@
305 for(i = 0; i < LENGTH(tags); i++) {
306 dc.w = TEXTW(tags[i]);
307 col = m->tagset[m->seltags] & 1 << i ? dc.sel : dc.norm;
308 - drawtext(tags[i], col, urg & 1 << i);
309 + drawtext(dc.drawable, tags[i], col, urg & 1 << i);
310 drawsquare(m == selmon && selmon->sel && selmon->sel->tags & 1 << i,
311 occ & 1 << i, urg & 1 << i, col);
312 dc.x += dc.w;
313 }
314 dc.w = blw = TEXTW(m->ltsymbol);
315 - drawtext(m->ltsymbol, dc.norm, False);
316 + drawtext(dc.drawable, m->ltsymbol, dc.norm, False);
317 dc.x += dc.w;
318 x = dc.x;
319 if(m == selmon) { /* status is only drawn on selected monitor */
320 @@ -747,19 +826,20 @@
321 dc.x = x;
322 dc.w = m->ww - x;
323 }
324 - drawtext(stext, dc.norm, False);
325 + drawtext(dc.drawable, stext, dc.norm, False);
326 }
327 else
328 dc.x = m->ww;
329 if((dc.w = dc.x - x) > bh) {
330 dc.x = x;
331 if(m->sel) {
332 - col = m == selmon ? dc.sel : dc.norm;
333 - drawtext(m->sel->name, col, False);
334 + // col = m == selmon ? dc.sel : dc.norm;
335 + // drawtext(dc.drawable, m->sel->name, col, False);
336 + drawtext(dc.drawable, m->sel->name, dc.norm, False);
337 drawsquare(m->sel->isfixed, m->sel->isfloating, False, col);
338 }
339 else
340 - drawtext(NULL, dc.norm, False);
341 + drawtext(dc.drawable, NULL, dc.norm, False);
342 }
343 XCopyArea(dpy, dc.drawable, m->barwin, dc.gc, 0, 0, m->ww, bh, 0, 0);
344 XSync(dpy, False);
345 @@ -774,6 +854,104 @@
346 }
347
348 void
349 +drawtabs(void) {
350 + Monitor *m;
351 +
352 + for(m = mons; m; m = m->next)
353 + drawtab(m);
354 +}
355 +
356 +static int
357 +cmpint(const void *p1, const void *p2) {
358 + /* The actual arguments to this function are "pointers to
359 + pointers to char", but strcmp(3) arguments are "pointers
360 + to char", hence the following cast plus dereference */
361 + return *((int*) p1) > * (int*) p2;
362 +}
363 +
364 +
365 +void
366 +drawtab(Monitor *m) {
367 + unsigned long *col;
368 + Client *c;
369 + int i;
370 + int itag = -1;
371 + char view_info[50];
372 + int view_info_w = 0;
373 + int sorted_label_widths[MAXTABS];
374 + int tot_width;
375 + int maxsize = bh;
376 + dc.x = 0;
377 +
378 + //view_info: indicate the tag which is displayed in the view
379 + for(i = 0; i < LENGTH(tags); ++i){
380 + if((selmon->tagset[selmon->seltags] >> i) & 1) {
381 + if(itag >=0){ //more than one tag selected
382 + itag = -1;
383 + break;
384 + }
385 + itag = i;
386 + }
387 + }
388 + if(0 <= itag && itag < LENGTH(tags)){
389 + snprintf(view_info, sizeof view_info, "[%s]", tags[itag]);
390 + } else {
391 + strncpy(view_info, "[...]", sizeof view_info);
392 + }
393 + view_info[sizeof(view_info) - 1 ] = 0;
394 + view_info_w = TEXTW(view_info);
395 + tot_width = view_info_w;
396 +
397 + /* Calculates number of labels and their width */
398 + m->ntabs = 0;
399 + for(c = m->clients; c; c = c->next){
400 + if(!ISVISIBLE(c)) continue;
401 + m->tab_widths[m->ntabs] = TEXTW(c->name);
402 + tot_width += m->tab_widths[m->ntabs];
403 + ++m->ntabs;
404 + if(m->ntabs >= MAXTABS) break;
405 + }
406 +
407 + if(tot_width > m->ww){ //not enough space to display the labels, they need to be truncated
408 + memcpy(sorted_label_widths, m->tab_widths, sizeof(int) * m->ntabs);
409 + qsort(sorted_label_widths, m->ntabs, sizeof(int), cmpint);
410 + tot_width = view_info_w;
411 + for(i = 0; i < m->ntabs; ++i){
412 + if(tot_width + (m->ntabs - i) * sorted_label_widths[i] > m->ww)
413 + break;
414 + tot_width += sorted_label_widths[i];
415 + }
416 + maxsize = (m->ww - tot_width) / (m->ntabs - i);
417 + } else{
418 + maxsize = m->ww;
419 + }
420 + i = 0;
421 + for(c = m->clients; c; c = c->next){
422 + if(!ISVISIBLE(c)) continue;
423 + if(i >= m->ntabs) break;
424 + if(m->tab_widths[i] > maxsize) m->tab_widths[i] = maxsize;
425 + dc.w = m->tab_widths[i];
426 + col = (c == m->sel) ? dc.sel : dc.norm;
427 + drawtext(dc.tabdrawable, c->name, col, 0);
428 + dc.x += dc.w;
429 + ++i;
430 + }
431 +
432 + /* cleans interspace between window names and current viewed tag label */
433 + dc.w = m->ww - view_info_w - dc.x;
434 + drawtext(dc.tabdrawable, NULL, dc.norm, 0);
435 +
436 + /* view info */
437 + dc.x += dc.w;
438 + dc.w = view_info_w;
439 + drawtext(dc.tabdrawable, view_info, dc.norm, 0);
440 +
441 + XCopyArea(dpy, dc.tabdrawable, m->tabwin, dc.gc, 0, 0, m->ww, th, 0, 0);
442 + XSync(dpy, False);
443 +}
444 +
445 +
446 +void
447 drawsquare(Bool filled, Bool empty, Bool invert, unsigned long col[ColLast]) {
448 int x;
449
450 @@ -785,13 +963,14 @@
451 XDrawRectangle(dpy, dc.drawable, dc.gc, dc.x+1, dc.y+1, x, x);
452 }
453
454 +
455 void
456 -drawtext(const char *text, unsigned long col[ColLast], Bool invert) {
457 +drawtext(Drawable drawable, const char *text, unsigned long col[ColLast], Bool invert) {
458 char buf[256];
459 int i, x, y, h, len, olen;
460
461 XSetForeground(dpy, dc.gc, col[invert ? ColFG : ColBG]);
462 - XFillRectangle(dpy, dc.drawable, dc.gc, dc.x, dc.y, dc.w, dc.h);
463 + XFillRectangle(dpy, drawable, dc.gc, dc.x, dc.y, dc.w, dc.h);
464 if(!text)
465 return;
466 olen = strlen(text);
467 @@ -807,11 +986,12 @@
468 for(i = len; i && i > len - 3; buf[--i] = '.');
469 XSetForeground(dpy, dc.gc, col[invert ? ColBG : ColFG]);
470 if(dc.font.set)
471 - XmbDrawString(dpy, dc.drawable, dc.font.set, dc.gc, x, y, buf, len);
472 + XmbDrawString(dpy, drawable, dc.font.set, dc.gc, x, y, buf, len);
473 else
474 - XDrawString(dpy, dc.drawable, dc.gc, x, y, buf, len);
475 + XDrawString(dpy, drawable, dc.gc, x, y, buf, len);
476 }
477
478 +
479 void
480 enternotify(XEvent *e) {
481 Client *c;
482 @@ -836,8 +1016,10 @@
483 Monitor *m;
484 XExposeEvent *ev = &e->xexpose;
485
486 - if(ev->count == 0 && (m = wintomon(ev->window)))
487 + if(ev->count == 0 && (m = wintomon(ev->window))){
488 drawbar(m);
489 + drawtab(m);
490 + }
491 }
492
493 void
494 @@ -862,6 +1044,7 @@
495 XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime);
496 selmon->sel = c;
497 drawbars();
498 + drawtabs();
499 }
500
501 void
502 @@ -911,6 +1094,19 @@
503 }
504 }
505
506 +void
507 +focuswin(const Arg* arg){
508 + int iwin = arg->i;
509 + Client* c = NULL;
510 + for(c = selmon->clients; c && (iwin || !ISVISIBLE(c)) ; c = c->next){
511 + if(ISVISIBLE(c)) --iwin;
512 + };
513 + if(c) {
514 + focus(c);
515 + restack(selmon);
516 + }
517 +}
518 +
519 Atom
520 getatomprop(Client *c, Atom prop) {
521 int di;
522 @@ -1028,7 +1224,7 @@
523
524 void
525 incnmaster(const Arg *arg) {
526 - selmon->nmaster = MAX(selmon->nmaster + arg->i, 0);
527 + selmon->nmaster = selmon->pertag->nmasters[selmon->pertag->curtag] = MAX(selmon->nmaster + arg->i, 0);
528 arrange(selmon);
529 }
530
531 @@ -1311,12 +1507,14 @@
532 case XA_WM_HINTS:
533 updatewmhints(c);
534 drawbars();
535 + drawtabs();
536 break;
537 }
538 if(ev->atom == XA_WM_NAME || ev->atom == netatom[NetWMName]) {
539 updatetitle(c);
540 if(c == c->mon->sel)
541 drawbar(c->mon);
542 + drawtab(c->mon);
543 }
544 if(ev->atom == netatom[NetWMWindowType])
545 updatewindowtype(c);
546 @@ -1418,6 +1616,7 @@
547 XWindowChanges wc;
548
549 drawbar(m);
550 + drawtab(m);
551 if(!m->sel)
552 return;
553 if(m->sel->isfloating || !m->lt[m->sellt]->arrange)
554 @@ -1555,10 +1754,13 @@
555
556 void
557 setlayout(const Arg *arg) {
558 - if(!arg || !arg->v || arg->v != selmon->lt[selmon->sellt])
559 - selmon->sellt ^= 1;
560 + if(!arg || !arg->v || arg->v != selmon->lt[selmon->sellt]) {
561 + selmon->pertag->sellts[selmon->pertag->curtag] ^= 1;
562 + selmon->sellt = selmon->pertag->sellts[selmon->pertag->curtag];
563 + }
564 if(arg && arg->v)
565 - selmon->lt[selmon->sellt] = (Layout *)arg->v;
566 + selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt] = (Layout *)arg->v;
567 + selmon->lt[selmon->sellt] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt];
568 strncpy(selmon->ltsymbol, selmon->lt[selmon->sellt]->symbol, sizeof selmon->ltsymbol);
569 if(selmon->sel)
570 arrange(selmon);
571 @@ -1576,7 +1778,7 @@
572 f = arg->f < 1.0 ? arg->f + selmon->mfact : arg->f - 1.0;
573 if(f < 0.1 || f > 0.9)
574 return;
575 - selmon->mfact = f;
576 + selmon->mfact = selmon->pertag->mfacts[selmon->pertag->curtag] = f;
577 arrange(selmon);
578 }
579
580 @@ -1594,6 +1796,7 @@
581 sw = DisplayWidth(dpy, screen);
582 sh = DisplayHeight(dpy, screen);
583 bh = dc.h = dc.font.height + 2;
584 + th = bh;
585 updategeom();
586 /* init atoms */
587 wmatom[WMProtocols] = XInternAtom(dpy, "WM_PROTOCOLS", False);
588 @@ -1619,6 +1822,7 @@
589 dc.sel[ColBG] = getcolor(selbgcolor);
590 dc.sel[ColFG] = getcolor(selfgcolor);
591 dc.drawable = XCreatePixmap(dpy, root, DisplayWidth(dpy, screen), bh, DefaultDepth(dpy, screen));
592 + dc.tabdrawable = XCreatePixmap(dpy, root, DisplayWidth(dpy, screen), th, DefaultDepth(dpy, screen));
593 dc.gc = XCreateGC(dpy, root, 0, NULL);
594 XSetLineAttributes(dpy, dc.gc, 1, LineSolid, CapButt, JoinMiter);
595 if(!dc.font.set)
596 @@ -1729,13 +1933,22 @@
597
598 void
599 togglebar(const Arg *arg) {
600 - selmon->showbar = !selmon->showbar;
601 + selmon->showbar = selmon->pertag->showbars[selmon->pertag->curtag] = !selmon->showbar;
602 updatebarpos(selmon);
603 XMoveResizeWindow(dpy, selmon->barwin, selmon->wx, selmon->by, selmon->ww, bh);
604 arrange(selmon);
605 }
606
607 void
608 +toggletab(const Arg *arg) {
609 + selmon->showtab = selmon->pertag->showtabs[selmon->pertag->curtag] = !selmon->showtab;
610 + updatebarpos(selmon);
611 + XMoveResizeWindow(dpy, selmon->tabwin, selmon->wx, selmon->ty, selmon->ww, th);
612 + arrange(selmon);
613 +}
614 +
615 +
616 +void
617 togglefloating(const Arg *arg) {
618 if(!selmon->sel)
619 return;
620 @@ -1763,9 +1976,31 @@
621 void
622 toggleview(const Arg *arg) {
623 unsigned int newtagset = selmon->tagset[selmon->seltags] ^ (arg->ui & TAGMASK);
624 + int i;
625
626 if(newtagset) {
627 + if(newtagset == ~0) {
628 + selmon->pertag->prevtag = selmon->pertag->curtag;
629 + selmon->pertag->curtag = 0;
630 + }
631 + /* test if the user did not select the same tag */
632 + if(!(newtagset & 1 << (selmon->pertag->curtag - 1))) {
633 + selmon->pertag->prevtag = selmon->pertag->curtag;
634 + for (i=0; !(newtagset & 1 << i); i++) ;
635 + selmon->pertag->curtag = i + 1;
636 + }
637 selmon->tagset[selmon->seltags] = newtagset;
638 +
639 + /* apply settings for this view */
640 + selmon->nmaster = selmon->pertag->nmasters[selmon->pertag->curtag];
641 + selmon->mfact = selmon->pertag->mfacts[selmon->pertag->curtag];
642 + selmon->sellt = selmon->pertag->sellts[selmon->pertag->curtag];
643 + selmon->lt[selmon->sellt] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt];
644 + selmon->lt[selmon->sellt^1] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt^1];
645 + if (selmon->showbar != selmon->pertag->showbars[selmon->pertag->curtag])
646 + togglebar(NULL);
647 + if (selmon->showtab != selmon->pertag->showtabs[selmon->pertag->curtag])
648 + toggletab(NULL);
649 focus(NULL);
650 arrange(selmon);
651 }
652 @@ -1832,6 +2067,11 @@
653 CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa);
654 XDefineCursor(dpy, m->barwin, cursor[CurNormal]);
655 XMapRaised(dpy, m->barwin);
656 + m->tabwin = XCreateWindow(dpy, root, m->wx, m->ty, m->ww, th, 0, DefaultDepth(dpy, screen),
657 + CopyFromParent, DefaultVisual(dpy, screen),
658 + CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa);
659 + XDefineCursor(dpy, m->tabwin, cursor[CurNormal]);
660 + XMapRaised(dpy, m->tabwin);
661 }
662 }
663
664 @@ -1842,10 +2082,20 @@
665 if(m->showbar) {
666 m->wh -= bh;
667 m->by = m->topbar ? m->wy : m->wy + m->wh;
668 - m->wy = m->topbar ? m->wy + bh : m->wy;
669 + if ( m->topbar )
670 + m->wy += bh;
671 + } else {
672 + m->by = -bh;
673 + }
674 +
675 + if(m->showtab) {
676 + m->wh -= th;
677 + m->ty = m->toptab ? m->wy : m->wy + m->wh;
678 + if ( m->toptab )
679 + m->wy += th;
680 + } else {
681 + m->ty = -th;
682 }
683 - else
684 - m->by = -bh;
685 }
686
687 Bool
688 @@ -2043,11 +2293,35 @@
689
690 void
691 view(const Arg *arg) {
692 + int i;
693 + unsigned int tmptag;
694 +
695 if((arg->ui & TAGMASK) == selmon->tagset[selmon->seltags])
696 return;
697 selmon->seltags ^= 1; /* toggle sel tagset */
698 - if(arg->ui & TAGMASK)
699 + if(arg->ui & TAGMASK) {
700 + selmon->pertag->prevtag = selmon->pertag->curtag;
701 selmon->tagset[selmon->seltags] = arg->ui & TAGMASK;
702 + if(arg->ui == ~0)
703 + selmon->pertag->curtag = 0;
704 + else {
705 + for (i=0; !(arg->ui & 1 << i); i++) ;
706 + selmon->pertag->curtag = i + 1;
707 + }
708 + } else {
709 + tmptag = selmon->pertag->prevtag;
710 + selmon->pertag->prevtag = selmon->pertag->curtag;
711 + selmon->pertag->curtag = tmptag;
712 + }
713 + selmon->nmaster = selmon->pertag->nmasters[selmon->pertag->curtag];
714 + selmon->mfact = selmon->pertag->mfacts[selmon->pertag->curtag];
715 + selmon->sellt = selmon->pertag->sellts[selmon->pertag->curtag];
716 + selmon->lt[selmon->sellt] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt];
717 + selmon->lt[selmon->sellt^1] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt^1];
718 + if (selmon->showbar != selmon->pertag->showbars[selmon->pertag->curtag])
719 + togglebar(NULL);
720 + if (selmon->showtab != selmon->pertag->showtabs[selmon->pertag->curtag])
721 + toggletab(NULL);
722 focus(NULL);
723 arrange(selmon);
724 }
725 @@ -2073,7 +2347,7 @@
726 if(w == root && getrootptr(&x, &y))
727 return recttomon(x, y, 1, 1);
728 for(m = mons; m; m = m->next)
729 - if(w == m->barwin)
730 + if(w == m->barwin || w == m->tabwin)
731 return m;
732 if((c = wintoclient(w)))
733 return c->mon;