diff options
Diffstat (limited to 'patch/tab.c')
| -rw-r--r-- | patch/tab.c | 133 |
1 files changed, 133 insertions, 0 deletions
diff --git a/patch/tab.c b/patch/tab.c new file mode 100644 index 0000000..30a14d1 --- /dev/null +++ b/patch/tab.c @@ -0,0 +1,133 @@ +static int th = 0; /* tab bar geometry */ + +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 < NUMTAGS; ++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 < NUMTAGS) { + snprintf(view_info, sizeof view_info, "[%s]", tagicon(m, 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) || HIDDEN(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) || HIDDEN(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, scheme[(c == m->sel) ? SchemeSel : SchemeNorm]); + drw_text(drw, x, 0, w, th, 0, c->name, 0, False); + 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, 0, "", 0, False); + + /* view info */ + x += w; + w = view_info_w; + drw_text(drw, x, 0, w, th, 0, view_info, 0, False); + + drw_map(drw, m->tabwin, 0, 0, m->ww, th); +} + +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) && !HIDDEN(c)) + --iwin; + }; + if (c) { + focus(c); + restack(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); +} + |
