summaryrefslogtreecommitdiff
path: root/patch/tab.c
diff options
context:
space:
mode:
Diffstat (limited to 'patch/tab.c')
-rw-r--r--patch/tab.c133
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);
+}
+