diff options
Diffstat (limited to 'dwm.c')
-rw-r--r-- | dwm.c | 194 |
1 files changed, 188 insertions, 6 deletions
@@ -40,6 +40,7 @@ #include <X11/extensions/Xinerama.h> #endif /* XINERAMA */ #include <X11/Xft/Xft.h> +#include <X11/XF86keysym.h> #include "drw.h" #include "util.h" @@ -110,6 +111,8 @@ typedef struct { void (*arrange)(Monitor *); } Layout; +typedef struct Pertag Pertag; + struct Monitor { char ltsymbol[16]; float mfact; @@ -118,6 +121,7 @@ struct Monitor { int by; /* bar geometry */ int mx, my, mw, mh; /* screen size */ int wx, wy, ww, wh; /* window area */ + int gappx; /* gaps between windows */ unsigned int seltags; unsigned int sellt; unsigned int tagset[2]; @@ -129,6 +133,7 @@ struct Monitor { Monitor *next; Window barwin; const Layout *lt[2]; + Pertag *pertag; }; typedef struct { @@ -160,6 +165,7 @@ static void destroynotify(XEvent *e); static void detach(Client *c); static void detachstack(Client *c); static Monitor *dirtomon(int dir); +static Monitor *numtomon(int num); static void drawbar(Monitor *m); static void drawbars(void); static void enternotify(XEvent *e); @@ -167,6 +173,7 @@ static void expose(XEvent *e); static void focus(Client *c); static void focusin(XEvent *e); static void focusmon(const Arg *arg); +static void focusnthmon(const Arg *arg); static void focusstack(const Arg *arg); static Atom getatomprop(Client *c, Atom prop); static int getrootptr(int *x, int *y); @@ -187,6 +194,7 @@ static Client *nexttiled(Client *c); static void pop(Client *c); static void propertynotify(XEvent *e); static void quit(const Arg *arg); +static void quitprompt(const Arg * arg); static Monitor *recttomon(int x, int y, int w, int h); static void resize(Client *c, int x, int y, int w, int h, int interact); static void resizeclient(Client *c, int x, int y, int w, int h); @@ -199,6 +207,7 @@ static void sendmon(Client *c, Monitor *m); static void setclientstate(Client *c, long state); static void setfocus(Client *c); static void setfullscreen(Client *c, int fullscreen); +static void setgaps(const Arg *arg); static void setlayout(const Arg *arg); static void setmfact(const Arg *arg); static void setup(void); @@ -207,9 +216,11 @@ static void showhide(Client *c); static void spawn(const Arg *arg); static void tag(const Arg *arg); static void tagmon(const Arg *arg); +static void tagnthmon(const Arg *arg); static void tile(Monitor *m); static void togglebar(const Arg *arg); static void togglefloating(const Arg *arg); +static void togglescratch(const Arg *arg); static void toggletag(const Arg *arg); static void toggleview(const Arg *arg); static void unfocus(Client *c, int setfocus); @@ -260,6 +271,7 @@ static void (*handler[LASTEvent]) (XEvent *) = { }; static Atom wmatom[WMLast], netatom[NetLast]; static int running = 1; +static int restart = 1; static Cur *cursor[CurLast]; static Clr **scheme; static Display *dpy; @@ -269,6 +281,19 @@ static Window root, wmcheckwin; /* configuration, allows nested code to access above variables */ #include "config.h" +struct Pertag { + unsigned int curtag, prevtag; + int nmasters[LENGTH(tags) + 1]; + float mfacts[LENGTH(tags) + 1]; + unsigned int sellts[LENGTH(tags) + 1]; + const Layout *ltidxs[LENGTH(tags) + 1][2]; + int showbars[LENGTH(tags) + 1]; + +}; + + + +static unsigned int scratchtag = 1 << LENGTH(tags); /* compile-time check if all tags fit into an unsigned int bit array. */ struct NumTags { char limitexceeded[LENGTH(tags) > 31 ? -1 : 1]; }; @@ -633,6 +658,7 @@ Monitor * createmon(void) { Monitor *m; + unsigned int i; m = ecalloc(1, sizeof(Monitor)); m->tagset[0] = m->tagset[1] = 1; @@ -640,9 +666,23 @@ createmon(void) m->nmaster = nmaster; m->showbar = showbar; m->topbar = topbar; + m->gappx = gappx; m->lt[0] = &layouts[0]; m->lt[1] = &layouts[1 % LENGTH(layouts)]; strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol); + m->pertag = ecalloc(1, sizeof(Pertag)); + m->pertag->curtag = m->pertag->prevtag = 1; + + for ( i = 0; i <= LENGTH(tags); i ++) { + m->pertag->nmasters[i] = m->nmaster; + m->pertag->mfacts[i] = m->mfact; + + m->pertag->ltidxs[i][0] = m->lt[0]; + m->pertag->ltidxs[i][1] = m->lt[1]; + m->pertag->sellts[i] = m->sellt; + + m->pertag->showbars[i] = m->showbar; + } return m; } @@ -678,6 +718,17 @@ detachstack(Client *c) c->mon->sel = t; } } +Monitor * +numtomon(int num) +{ + Monitor *m = NULL; + int i = 0; + + for(m = mons, i=0; m->next && i < num; m = m->next){ + i++; + } + return m; +} Monitor * dirtomon(int dir) @@ -835,6 +886,19 @@ focusmon(const Arg *arg) } void +focusnthmon(const Arg *arg) +{ + Monitor *m; + if(!mons->next) + return; + if((m = numtomon(arg->i)) == selmon) + return; + unfocus(selmon->sel, 0); + selmon = m; + focus(NULL); +} + +void focusstack(const Arg *arg) { Client *c = NULL, *i; @@ -860,6 +924,14 @@ focusstack(const Arg *arg) } } +void +tagnthmon(const Arg *arg) +{ + if (!selmon->sel || !mons->next) + return; + sendmon(selmon->sel, numtomon(arg->i)); +} + Atom getatomprop(Client *c, Atom prop) { @@ -979,7 +1051,7 @@ grabkeys(void) void incnmaster(const Arg *arg) { - selmon->nmaster = MAX(selmon->nmaster + arg->i, 0); + selmon->nmaster = selmon->pertag->nmasters[selmon->pertag->curtag] = MAX(selmon->nmaster + arg->i, 0); arrange(selmon); } @@ -1060,6 +1132,15 @@ manage(Window w, XWindowAttributes *wa) c->y = MAX(c->y, c->mon->wy); c->bw = borderpx; + selmon->tagset[selmon->seltags] &= ~scratchtag; + if (!strcmp(c->name, scratchpadname)) { + c->mon->tagset[c->mon->seltags] |= c->tags = scratchtag; + c->isfloating = True; + c->x = c->mon->wx + (c->mon->ww / 2 - WIDTH(c) / 2); + c->y = c->mon->wy + (c->mon->wh / 2 - HEIGHT(c) / 2); + + } + wc.border_width = c->bw; XConfigureWindow(dpy, w, CWBorderWidth, &wc); XSetWindowBorder(dpy, w, scheme[SchemeNorm][ColBorder].pixel); @@ -1201,6 +1282,31 @@ movemouse(const Arg *arg) } } +void +quitprompt(const Arg *arg) +{ + FILE *pp = popen("echo -e \"no\nrestart\nyes\" | dmenu -i -sb red -fn monospace:size=25 -p \"Quit DWM?\"", "r"); + if (pp != NULL) { + char buf[1024]; + if (fgets(buf, sizeof(buf), pp) == NULL) { + fprintf(stderr, "Quitprompt: Error reading pipe!\n"); + return; + } + if (strcmp(buf, "yes\n") == 0) { + pclose(pp); + restart = 0; + quit(NULL); + } else if (strcmp(buf, "restart\n") == 0) { + pclose(pp); + restart = 1; + quit(NULL); + } else if (strcmp(buf, "no\n") == 0) { + pclose(pp); + return; + } + } +} + Client * nexttiled(Client *c) { @@ -1282,6 +1388,16 @@ resize(Client *c, int x, int y, int w, int h, int interact) } void +setgaps(const Arg *arg) +{ + if ((arg->i == 0) || (selmon->gappx + arg->i < 0)) + selmon->gappx = 0; + else + selmon->gappx += arg->i; + arrange(selmon); +} + +void resizeclient(Client *c, int x, int y, int w, int h) { XWindowChanges wc; @@ -1510,9 +1626,9 @@ void setlayout(const Arg *arg) { if (!arg || !arg->v || arg->v != selmon->lt[selmon->sellt]) - selmon->sellt ^= 1; + selmon->sellt = selmon->pertag->sellts[selmon->pertag->curtag] ^= 1; if (arg && arg->v) - selmon->lt[selmon->sellt] = (Layout *)arg->v; + selmon->lt[selmon->sellt] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt] = (Layout *)arg->v; strncpy(selmon->ltsymbol, selmon->lt[selmon->sellt]->symbol, sizeof selmon->ltsymbol); if (selmon->sel) arrange(selmon); @@ -1531,7 +1647,7 @@ setmfact(const Arg *arg) f = arg->f < 1.0 ? arg->f + selmon->mfact : arg->f - 1.0; if (f < 0.05 || f > 0.95) return; - selmon->mfact = f; + selmon->mfact = selmon->pertag->mfacts[selmon->pertag->curtag] = f; arrange(selmon); } @@ -1650,6 +1766,7 @@ spawn(const Arg *arg) if (arg->v == dmenucmd) dmenumon[0] = '0' + selmon->num; + selmon->tagset[selmon->seltags] &= ~scratchtag; if (fork() == 0) { if (dpy) close(ConnectionNumber(dpy)); @@ -1714,7 +1831,7 @@ tile(Monitor *m) void togglebar(const Arg *arg) { - selmon->showbar = !selmon->showbar; + selmon->showbar = selmon->pertag->showbars[selmon->pertag->curtag] = !selmon->showbar; updatebarpos(selmon); XMoveResizeWindow(dpy, selmon->barwin, selmon->wx, selmon->by, selmon->ww, bh); arrange(selmon); @@ -1735,6 +1852,28 @@ togglefloating(const Arg *arg) } void +togglescratch(const Arg *arg) +{ + Client *c; + unsigned int found = 0; + + for (c = selmon->clients; c && !(found = c->tags & scratchtag); c = c->next); + if (found) { + unsigned int newtagset = selmon->tagset[selmon->seltags] ^ scratchtag; + if (newtagset) { + selmon->tagset[selmon->seltags] = newtagset; + focus(NULL); + arrange(selmon); + } + if (ISVISIBLE(c)) { + focus(c); + restack(selmon); + } + } else + spawn(arg); +} + +void toggletag(const Arg *arg) { unsigned int newtags; @@ -1753,9 +1892,28 @@ void toggleview(const Arg *arg) { unsigned int newtagset = selmon->tagset[selmon->seltags] ^ (arg->ui & TAGMASK); + int i; if (newtagset) { selmon->tagset[selmon->seltags] = newtagset; + if (newtagset == ~0) { + selmon->pertag->prevtag = selmon->pertag->curtag; + selmon->pertag->curtag = 0; + } + + if (!(newtagset & 1 << (selmon->pertag->curtag-1))) { + selmon->pertag->prevtag = selmon->pertag->curtag; + for (i = 0; !(newtagset & 1 << i); i++) ; + selmon->pertag->curtag = i + 1; + } + selmon->nmaster = selmon->pertag->nmasters[selmon->pertag->curtag]; + selmon->mfact = selmon->pertag->mfacts[selmon->pertag->curtag]; + selmon->sellt = selmon->pertag->sellts[selmon->pertag->curtag]; + selmon->lt[selmon->sellt] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt]; + selmon->lt[selmon->sellt^1] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt^1]; + + if (selmon->showbar != selmon->pertag->showbars[selmon->pertag->curtag]) + togglebar(NULL); focus(NULL); arrange(selmon); } @@ -2052,11 +2210,32 @@ updatewmhints(Client *c) void view(const Arg *arg) { + int i; + unsigned int tmptag; if ((arg->ui & TAGMASK) == selmon->tagset[selmon->seltags]) return; selmon->seltags ^= 1; /* toggle sel tagset */ - if (arg->ui & TAGMASK) + if (arg->ui & TAGMASK) { selmon->tagset[selmon->seltags] = arg->ui & TAGMASK; + selmon->pertag->prevtag = selmon->pertag->curtag; + if (arg->ui == ~0) + selmon->pertag->curtag = 0; + else { + for (i = 0; !(arg->ui & 1 << i); i++) ; + selmon->pertag->curtag = i + 1; + } + } else { + tmptag = selmon->pertag->prevtag; + selmon->pertag->prevtag = selmon->pertag->curtag; + selmon->pertag->curtag = tmptag; + } + selmon->nmaster = selmon->pertag->nmasters[selmon->pertag->curtag]; + selmon->mfact = selmon->pertag->mfacts[selmon->pertag->curtag]; + selmon->sellt = selmon->pertag->sellts[selmon->pertag->curtag]; + selmon->lt[selmon->sellt] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt]; + selmon->lt[selmon->sellt^1] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt^1]; + if (selmon->showbar != selmon->pertag->showbars[selmon->pertag->curtag]) + togglebar(NULL); focus(NULL); arrange(selmon); } @@ -2160,5 +2339,8 @@ main(int argc, char *argv[]) run(); cleanup(); XCloseDisplay(dpy); + if (restart == 1) { + execlp("dwm", "dwm", NULL); + } return EXIT_SUCCESS; } |