--- a/config.def.h 2010-06-04 06:39:15.000000000 -0400 +++ b/config.def.h 2011-06-11 09:30:07.032880714 -0400 @@ -89,6 +89,7 @@ /* click event mask button function argument */ { ClkLtSymbol, 0, Button1, setlayout, {0} }, { ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]} }, + { ClkWinTitle, 0, Button1, focusonclick, {0} }, { ClkWinTitle, 0, Button2, zoom, {0} }, { ClkStatusText, 0, Button2, spawn, {.v = termcmd } }, { ClkClientWin, MODKEY, Button1, movemouse, {0} }, --- a/dwm.c 2010-06-04 06:39:15.000000000 -0400 +++ b/dwm.c 2011-05-31 10:36:47.906683796 -0400 @@ -140,6 +140,8 @@ Monitor *next; Window barwin; const Layout *lt[2]; + int titlebarbegin; + int titlebarend; }; typedef struct { @@ -175,11 +177,13 @@ static Monitor *dirtomon(int dir); static void drawbar(Monitor *m); static void drawbars(void); +static void drawvline(unsigned long col[ColLast]); 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 enternotify(XEvent *e); static void expose(XEvent *e); static void focus(Client *c); +static void focusonclick(const Arg *arg); static void focusin(XEvent *e); static void focusmon(const Arg *arg); static void focusstack(const Arg *arg); @@ -443,10 +447,12 @@ } else if(ev->x < x + blw) click = ClkLtSymbol; - else if(ev->x > selmon->wx + selmon->ww - TEXTW(stext)) + else if(ev->x > selmon->titlebarend) click = ClkStatusText; - else + else { + arg.ui = ev->x; click = ClkWinTitle; + } } else if((c = wintoclient(ev->window))) { focus(c); @@ -455,7 +461,7 @@ 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); + buttons[i].func((click == ClkTagBar || click == ClkWinTitle) && buttons[i].arg.i == 0 ? &arg : &buttons[i].arg); } void @@ -683,12 +689,15 @@ void drawbar(Monitor *m) { - int x; - unsigned int i, occ = 0, urg = 0; + int x, ow, mw = 0, extra, tw; + unsigned int i, n = 0, occ = 0, urg = 0; unsigned long *col; - Client *c; + Client *c, *firstvis, *lastvis = NULL; + DC seldc; for(c = m->clients; c; c = c->next) { + if(ISVISIBLE(c)) + n++; occ |= c->tags; if(c->isurgent) urg |= c->tags; @@ -714,19 +723,68 @@ dc.w = m->ww - x; } drawtext(stext, dc.norm, False); + m->titlebarend=dc.x; } - else + 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); - drawsquare(m->sel->isfixed, m->sel->isfloating, False, col); + m->titlebarbegin=dc.x; + } + + for(c = m->clients; c && !ISVISIBLE(c); c = c->next); + firstvis = c; + + col = m == selmon ? dc.sel : dc.norm; + dc.w = dc.x - x; + dc.x = x; + + if(n > 0) { + mw = dc.w / n; + extra = 0; + seldc = dc; + i = 0; + + while(c) { + lastvis = c; + tw = TEXTW(c->name); + if(tw < mw) extra += (mw - tw); else i++; + for(c = c->next; c && !ISVISIBLE(c); c = c->next); } - else + + if(i > 0) mw += extra / i; + + c = firstvis; + x = dc.x; + } + m->titlebarbegin=dc.x; + while(dc.w > bh) { + if(c) { + ow = dc.w; + tw = TEXTW(c->name); + dc.w = MIN(ow, tw); + + if(dc.w > mw) dc.w = mw; + if(m->sel == c) seldc = dc; + if(c == lastvis) dc.w = ow; + + drawtext(c->name, col, True); + if(c != firstvis) drawvline(col); + drawsquare(c->isfixed, c->isfloating, False, col); + + dc.x += dc.w; + dc.w = ow - dc.w; + for(c = c->next; c && !ISVISIBLE(c); c = c->next); + } else { drawtext(NULL, dc.norm, False); + break; + } } + + if(m == selmon && m->sel && ISVISIBLE(m->sel)) { + dc = seldc; + drawtext(m->sel->name, col, False); + drawsquare(m->sel->isfixed, m->sel->isfloating, True, col); + } + XCopyArea(dpy, dc.drawable, m->barwin, dc.gc, 0, 0, m->ww, bh, 0, 0); XSync(dpy, False); } @@ -740,6 +798,15 @@ } void +drawvline(unsigned long col[ColLast]) { + XGCValues gcv; + + gcv.foreground = col[ColBG]; + XChangeGC(dpy, dc.gc, GCForeground, &gcv); + XDrawLine(dpy, dc.drawable, dc.gc, dc.x, dc.y, dc.x, dc.y + (dc.font.ascent + dc.font.descent + 2)); +} + +void drawsquare(Bool filled, Bool empty, Bool invert, unsigned long col[ColLast]) { int x; XGCValues gcv; @@ -840,6 +907,50 @@ } void +focusonclick(const Arg *arg) { + int x, w, mw = 0, tw, n = 0, i = 0, extra = 0; + Monitor *m = selmon; + Client *c, *firstvis; + + for(c = m->clients; c && !ISVISIBLE(c); c = c->next); + firstvis = c; + + for(c = m->clients; c; c = c->next) + if (ISVISIBLE(c)) + n++; + + if(n > 0) { + mw = (m->titlebarend - m->titlebarbegin) / n; + c = firstvis; + while(c) { + tw = TEXTW(c->name); + if(tw < mw) extra += (mw - tw); else i++; + for(c = c->next; c && !ISVISIBLE(c); c = c->next); + } + if(i > 0) mw += extra / i; + } + + x=m->titlebarbegin; + + c = firstvis; + while(x < m->titlebarend) { + if(c) { + w=MIN(TEXTW(c->name), mw); + if (x < arg->i && x+w > arg->i) { + focus(c); + restack(selmon); + break; + } else + x+=w; + + for(c = c->next; c && !ISVISIBLE(c); c = c->next); + } else { + break; + } + } +} + +void focusin(XEvent *e) { /* there are some broken focus acquiring clients */ XFocusChangeEvent *ev = &e->xfocus; @@ -1291,8 +1402,7 @@ } if(ev->atom == XA_WM_NAME || ev->atom == netatom[NetWMName]) { updatetitle(c); - if(c == c->mon->sel) - drawbar(c->mon); + drawbar(c->mon); } } }