dwm-6.1-taggrid.diff (8516B)
1 diff --git a/config.def.h b/config.def.h 2 index 875885b..d6670dc 100644 3 --- a/config.def.h 4 +++ b/config.def.h 5 @@ -16,6 +16,22 @@ static const Bool topbar = True; /* False means bottom bar */ 6 /* tagging */ 7 static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" }; 8 9 +/* grid of tags */ 10 +#define DRAWCLASSICTAGS 1 << 0 11 +#define DRAWTAGGRID 1 << 1 12 + 13 +#define SWITCHTAG_UP 1 << 0 14 +#define SWITCHTAG_DOWN 1 << 1 15 +#define SWITCHTAG_LEFT 1 << 2 16 +#define SWITCHTAG_RIGHT 1 << 3 17 +#define SWITCHTAG_TOGGLETAG 1 << 4 18 +#define SWITCHTAG_TAG 1 << 5 19 +#define SWITCHTAG_VIEW 1 << 6 20 +#define SWITCHTAG_TOGGLEVIEW 1 << 7 21 + 22 +static const unsigned int drawtagmask = DRAWTAGGRID; /* | DRAWCLASSICTAGS to show classic row of tags */ 23 +static const int tagrows = 3; 24 + 25 static const Rule rules[] = { 26 /* xprop(1): 27 * WM_CLASS(STRING) = instance, class 28 @@ -89,6 +105,16 @@ static Key keys[] = { 29 TAGKEYS( XK_8, 7) 30 TAGKEYS( XK_9, 8) 31 { MODKEY|ShiftMask, XK_q, quit, {0} }, 32 + 33 + { MODKEY|ControlMask, XK_Up, switchtag, { .ui = SWITCHTAG_UP | SWITCHTAG_VIEW } }, 34 + { MODKEY|ControlMask, XK_Down, switchtag, { .ui = SWITCHTAG_DOWN | SWITCHTAG_VIEW } }, 35 + { MODKEY|ControlMask, XK_Right, switchtag, { .ui = SWITCHTAG_RIGHT | SWITCHTAG_VIEW } }, 36 + { MODKEY|ControlMask, XK_Left, switchtag, { .ui = SWITCHTAG_LEFT | SWITCHTAG_VIEW } }, 37 + 38 + { MODKEY|Mod4Mask, XK_Up, switchtag, { .ui = SWITCHTAG_UP | SWITCHTAG_TAG | SWITCHTAG_VIEW } }, 39 + { MODKEY|Mod4Mask, XK_Down, switchtag, { .ui = SWITCHTAG_DOWN | SWITCHTAG_TAG | SWITCHTAG_VIEW } }, 40 + { MODKEY|Mod4Mask, XK_Right, switchtag, { .ui = SWITCHTAG_RIGHT | SWITCHTAG_TAG | SWITCHTAG_VIEW } }, 41 + { MODKEY|Mod4Mask, XK_Left, switchtag, { .ui = SWITCHTAG_LEFT | SWITCHTAG_TAG | SWITCHTAG_VIEW } }, 42 }; 43 44 /* button definitions */ 45 diff --git a/dwm.c b/dwm.c 46 index 1bbb4b3..d1b8799 100644 47 --- a/dwm.c 48 +++ b/dwm.c 49 @@ -163,6 +163,7 @@ static void detachstack(Client *c); 50 static Monitor *dirtomon(int dir); 51 static void drawbar(Monitor *m); 52 static void drawbars(void); 53 +static void drawtaggrid(Monitor *m, int *x_pos, unsigned int occ); 54 static void enternotify(XEvent *e); 55 static void expose(XEvent *e); 56 static void focus(Client *c); 57 @@ -205,6 +206,7 @@ static void setup(void); 58 static void showhide(Client *c); 59 static void sigchld(int unused); 60 static void spawn(const Arg *arg); 61 +static void switchtag(const Arg *arg); 62 static void tag(const Arg *arg); 63 static void tagmon(const Arg *arg); 64 static void tile(Monitor *); 65 @@ -409,11 +411,13 @@ attachstack(Client *c) { 66 void 67 buttonpress(XEvent *e) { 68 unsigned int i, x, click; 69 + unsigned int columns; 70 Arg arg = {0}; 71 Client *c; 72 Monitor *m; 73 XButtonPressedEvent *ev = &e->xbutton; 74 75 + columns = LENGTH(tags) / tagrows + ((LENGTH(tags) % tagrows > 0) ? 1 : 0); 76 click = ClkRootWin; 77 /* focus monitor if necessary */ 78 if((m = wintomon(ev->window)) && m != selmon) { 79 @@ -423,14 +427,24 @@ buttonpress(XEvent *e) { 80 } 81 if(ev->window == selmon->barwin) { 82 i = x = 0; 83 + if (drawtagmask & DRAWCLASSICTAGS) 84 do 85 x += TEXTW(tags[i]); 86 while(ev->x >= x && ++i < LENGTH(tags)); 87 - if(i < LENGTH(tags)) { 88 + if(i < LENGTH(tags) && (drawtagmask & DRAWCLASSICTAGS)) { 89 click = ClkTagBar; 90 arg.ui = 1 << i; 91 } 92 - else if(ev->x < x + blw) 93 + else if(ev->x < x + columns * bh / tagrows && (drawtagmask & DRAWTAGGRID)) { 94 + click = ClkTagBar; 95 + i = (ev->x - x) / (bh / tagrows); 96 + i = i + columns * (ev->y / (bh / tagrows)); 97 + if (i >= LENGTH(tags)) { 98 + i = LENGTH(tags) - 1; 99 + } 100 + arg.ui = 1 << i; 101 + } 102 + else if(ev->x < x + blw + columns * bh / tagrows) 103 click = ClkLtSymbol; 104 else if(ev->x > selmon->ww - TEXTW(stext)) 105 click = ClkStatusText; 106 @@ -702,6 +716,7 @@ drawbar(Monitor *m) { 107 urg |= c->tags; 108 } 109 x = 0; 110 + if (drawtagmask & DRAWCLASSICTAGS) 111 for(i = 0; i < LENGTH(tags); i++) { 112 w = TEXTW(tags[i]); 113 drw_setscheme(drw, m->tagset[m->seltags] & 1 << i ? &scheme[SchemeSel] : &scheme[SchemeNorm]); 114 @@ -710,6 +725,9 @@ drawbar(Monitor *m) { 115 occ & 1 << i, urg & 1 << i); 116 x += w; 117 } 118 + if (drawtagmask & DRAWTAGGRID) { 119 + drawtaggrid(m,&x,occ); 120 + } 121 w = blw = TEXTW(m->ltsymbol); 122 drw_setscheme(drw, &scheme[SchemeNorm]); 123 drw_text(drw, x, 0, w, bh, m->ltsymbol, 0); 124 @@ -748,6 +766,47 @@ drawbars(void) { 125 for(m = mons; m; m = m->next) 126 drawbar(m); 127 } 128 +void drawtaggrid(Monitor *m, int *x_pos, unsigned int occ) 129 +{ 130 + unsigned int x, y, h, max_x, columns; 131 + int invert, i,j, k; 132 + 133 + h = bh / tagrows; 134 + x = max_x = *x_pos; 135 + y = 0; 136 + columns = LENGTH(tags) / tagrows + ((LENGTH(tags) % tagrows > 0) ? 1 : 0); 137 + 138 + /* Firstly we will fill the borders of squares */ 139 + XSetForeground(drw->dpy, drw->gc, scheme[SchemeNorm].border->rgb); 140 + XFillRectangle(dpy, drw->drawable, drw->gc, x, y, h*columns + 1, bh); 141 + 142 + /* We will draw LENGTH(tags) squares in tagraws raws. */ 143 + for(j = 0, i= 0; j < tagrows; j++) { 144 + x = *x_pos; 145 + for (k = 0; k < columns && i < LENGTH(tags); k++, i++) { 146 + invert = m->tagset[m->seltags] & 1 << i ? 0 : 1; 147 + 148 + /* Select active color for current square */ 149 + XSetForeground(drw->dpy, drw->gc, !invert ? scheme[SchemeSel].bg->rgb : 150 + scheme[SchemeNorm].fg->rgb); 151 + XFillRectangle(dpy, drw->drawable, drw->gc, x+1, y+1, h-1, h-1); 152 + 153 + /* Mark square if tag has client */ 154 + if (occ & 1 << i) { 155 + XSetForeground(drw->dpy, drw->gc, !invert ? scheme[SchemeSel].fg->rgb : 156 + scheme[SchemeNorm].bg->rgb); 157 + XFillRectangle(dpy, drw->drawable, drw->gc, x + 1, y + 1, 158 + h / 2, h / 2); 159 + } 160 + x += h; 161 + if (x > max_x) { 162 + max_x = x; 163 + } 164 + } 165 + y += h; 166 + } 167 + *x_pos = max_x + 1; 168 +} 169 170 void 171 enternotify(XEvent *e) { 172 @@ -1582,6 +1641,81 @@ spawn(const Arg *arg) { 173 exit(EXIT_SUCCESS); 174 } 175 } 176 +void switchtag(const Arg *arg) 177 +{ 178 + unsigned int columns; 179 + unsigned int new_tagset = 0; 180 + unsigned int pos, i; 181 + int col, row; 182 + Arg new_arg; 183 + 184 + columns = LENGTH(tags) / tagrows + ((LENGTH(tags) % tagrows > 0) ? 1 : 0); 185 + 186 + for (i = 0; i < LENGTH(tags); ++i) { 187 + if (!(selmon->tagset[selmon->seltags] & 1 << i)) { 188 + continue; 189 + } 190 + pos = i; 191 + row = pos / columns; 192 + col = pos % columns; 193 + if (arg->ui & SWITCHTAG_UP) { /* UP */ 194 + row --; 195 + if (row < 0) { 196 + row = tagrows - 1; 197 + } 198 + do { 199 + pos = row * columns + col; 200 + row --; 201 + } while (pos >= LENGTH(tags)); 202 + } 203 + if (arg->ui & SWITCHTAG_DOWN) { /* DOWN */ 204 + row ++; 205 + if (row >= tagrows) { 206 + row = 0; 207 + } 208 + pos = row * columns + col; 209 + if (pos >= LENGTH(tags)) { 210 + row = 0; 211 + } 212 + pos = row * columns + col; 213 + } 214 + if (arg->ui & SWITCHTAG_LEFT) { /* LEFT */ 215 + col --; 216 + if (col < 0) { 217 + col = columns - 1; 218 + } 219 + do { 220 + pos = row * columns + col; 221 + col --; 222 + } while (pos >= LENGTH(tags)); 223 + } 224 + if (arg->ui & SWITCHTAG_RIGHT) { /* RIGHT */ 225 + col ++; 226 + if (col >= columns) { 227 + col = 0; 228 + } 229 + pos = row * columns + col; 230 + if (pos >= LENGTH(tags)) { 231 + col = 0; 232 + pos = row * columns + col; 233 + } 234 + } 235 + new_tagset |= 1 << pos; 236 + } 237 + new_arg.ui = new_tagset; 238 + if (arg->ui & SWITCHTAG_TOGGLETAG) { 239 + toggletag(&new_arg); 240 + } 241 + if (arg->ui & SWITCHTAG_TAG) { 242 + tag(&new_arg); 243 + } 244 + if (arg->ui & SWITCHTAG_VIEW) { 245 + view (&new_arg); 246 + } 247 + if (arg->ui & SWITCHTAG_TOGGLEVIEW) { 248 + toggleview (&new_arg); 249 + } 250 +} 251 252 void 253 tag(const Arg *arg) {