static void incnmaster(const Arg *arg);
static void keypress(XEvent *e);
static void killclient(const Arg *arg);
+static void layoutmenu(const Arg *arg);
static void manage(Window w, XWindowAttributes *wa);
static void mappingnotify(XEvent *e);
static void maprequest(XEvent *e);
static void monocle(Monitor *m);
static void motionnotify(XEvent *e);
static void movemouse(const Arg *arg);
+static void nametag(const Arg *arg);
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);
static int xerrorstart(Display *dpy, XErrorEvent *ee);
static void zoom(const Arg *arg);
+static void keyrelease(XEvent *e);
+static void combotag(const Arg *arg);
+static void comboview(const Arg *arg);
+
+
/* variables */
static const char broken[] = "broken";
static char stext[256];
static unsigned int numlockmask = 0;
static void (*handler[LASTEvent]) (XEvent *) = {
[ButtonPress] = buttonpress,
+ [ButtonRelease] = keyrelease,
[ClientMessage] = clientmessage,
[ConfigureRequest] = configurerequest,
[ConfigureNotify] = configurenotify,
[EnterNotify] = enternotify,
[Expose] = expose,
[FocusIn] = focusin,
+ [KeyRelease] = keyrelease,
[KeyPress] = keypress,
[MappingNotify] = mappingnotify,
[MapRequest] = maprequest,
};
static Atom wmatom[WMLast], netatom[NetLast];
static int running = 1;
+static int restart = 1;
static Cur *cursor[CurLast];
static Clr **scheme;
static Display *dpy;
struct NumTags { char limitexceeded[LENGTH(tags) > 31 ? -1 : 1]; };
/* function implementations */
+static int combo = 0;
+
+void
+keyrelease(XEvent *e) {
+ combo = 0;
+}
+
+void
+combotag(const Arg *arg) {
+ if(selmon->sel && arg->ui & TAGMASK) {
+ if (combo) {
+ selmon->sel->tags |= arg->ui & TAGMASK;
+ } else {
+ combo = 1;
+ selmon->sel->tags = arg->ui & TAGMASK;
+ }
+ focus(NULL);
+ arrange(selmon);
+ }
+}
+
+void
+comboview(const Arg *arg) {
+ unsigned newtags = arg->ui & TAGMASK;
+ if (combo) {
+ selmon->tagset[selmon->seltags] |= newtags;
+ } else {
+ selmon->seltags ^= 1; /*toggle tagset*/
+ combo = 1;
+ if (newtags)
+ selmon->tagset[selmon->seltags] = newtags;
+ }
+ focus(NULL);
+ arrange(selmon);
+}
+
void
applyrules(Client *c)
{
XFree(ch.res_class);
if (ch.res_name)
XFree(ch.res_name);
- c->tags = c->tags & TAGMASK ? c->tags & TAGMASK : c->mon->tagset[c->mon->seltags];
+ if(c->tags & TAGMASK) c->tags = c->tags & TAGMASK;
+ else if(c->mon->tagset[c->mon->seltags]) c->tags = c->mon->tagset[c->mon->seltags];
+ else c->tags = 1;
}
int
Monitor *m;
m = ecalloc(1, sizeof(Monitor));
- m->tagset[0] = m->tagset[1] = 1;
+ m->tagset[0] = m->tagset[1] = startontag ? 1 : 0;
m->mfact = mfact;
m->nmaster = nmaster;
m->showbar = showbar;
void
drawbar(Monitor *m)
{
+ int indn;
int x, w, tw = 0;
int boxs = drw->fonts->h / 9;
int boxw = drw->fonts->h / 6 + 2;
}
x = 0;
for (i = 0; i < LENGTH(tags); i++) {
+ indn = 0;
w = TEXTW(tags[i]);
drw_setscheme(drw, scheme[m->tagset[m->seltags] & 1 << i ? SchemeSel : SchemeNorm]);
drw_text(drw, x, 0, w, bh, lrpad / 2, tags[i], urg & 1 << i);
- if (occ & 1 << i)
- drw_rect(drw, x + boxs, boxs, boxw, boxw,
- m == selmon && selmon->sel && selmon->sel->tags & 1 << i,
- urg & 1 << i);
+
+ for (c = m->clients; c; c = c->next) {
+ if (c->tags & (1 << i)) {
+ drw_rect(drw, x, 1 + (indn * 2), selmon->sel == c ? 6 : 1, 1, 1, urg & 1 << i);
+ indn++;
+ }
+ }
+
x += w;
}
w = TEXTW(m->ltsymbol);
if ((w = m->ww - tw - x) > bh) {
if (m->sel) {
+ /* fix overflow when window name is bigger than window width */
+ int mid = (m->ww - (int)TEXTW(m->sel->name)) / 2 - x;
+ /* make sure name will not overlap on tags even when it is very long */
+ mid = mid >= lrpad / 2 ? mid : lrpad / 2;
drw_setscheme(drw, scheme[m == selmon ? SchemeSel : SchemeNorm]);
- drw_text(drw, x, 0, w, bh, lrpad / 2, m->sel->name, 0);
+ drw_text(drw, x, 0, w, bh, mid, m->sel->name, 0);
if (m->sel->isfloating)
drw_rect(drw, x + boxs, boxs, boxw, boxw, m->sel->isfixed, 0);
} else {
}
}
+void
+layoutmenu(const Arg *arg) {
+ FILE *p;
+ char c[3], *s;
+ int i;
+
+ if (!(p = popen(layoutmenu_cmd, "r")))
+ return;
+ s = fgets(c, sizeof(c), p);
+ pclose(p);
+
+ if (!s || *s == '\0' || c[0] == '\0')
+ return;
+
+ i = atoi(c);
+ setlayout(&((Arg) { .v = &layouts[i] }));
+}
+
void
manage(Window w, XWindowAttributes *wa)
{
}
}
+void
+nametag(const Arg *arg) {
+ char *p, name[MAX_TAGLEN];
+ FILE *f;
+ int i;
+
+ errno = 0; // popen(3p) says on failure it "may" set errno
+ // TODO: Create a central location for the dmenu font specification.
+ // It should not be hardcoded in multiple locations.
+ if(!(f = popen("dmenu -fn monospace:size=14 < /dev/null", "r"))) {
+ fprintf(stderr, "dwm: popen 'dmenu < /dev/null' failed%s%s\n", errno ? ": " : "", errno ? strerror(errno) : "");
+ return;
+ }
+ if (!(p = fgets(name, MAX_TAGLEN, f)) && (i = errno) && ferror(f))
+ fprintf(stderr, "dwm: fgets failed: %s\n", strerror(i));
+ if (pclose(f) < 0)
+ fprintf(stderr, "dwm: pclose failed: %s\n", strerror(errno));
+ if(!p)
+ return;
+ if((p = strchr(name, '\n')))
+ *p = '\0';
+
+ for(i = 0; i < LENGTH(tags); i++)
+ if(selmon->tagset[selmon->seltags] & (1 << i))
+ strcpy(tags[i], name);
+ drawbars();
+}
+
Client *
nexttiled(Client *c)
{
running = 0;
}
+void
+quitprompt(const Arg *arg)
+{
+ // TODO: Create a central location for the dmenu font specification.
+ // It should not be hardcoded in multiple locations.
+ FILE *pp = popen("echo -e \"no\nrestart\nyes\" | dmenu -fn monospace:size=14 -i -sb red -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;
+ }
+ }
+}
+
Monitor *
recttomon(int x, int y, int w, int h)
{
detach(c);
detachstack(c);
c->mon = m;
- c->tags = m->tagset[m->seltags]; /* assign tags of target monitor */
+ c->tags = (m->tagset[m->seltags] ? m->tagset[m->seltags] : 1);
attach(c);
attachstack(c);
focus(NULL);
{
unsigned int newtagset = selmon->tagset[selmon->seltags] ^ (arg->ui & TAGMASK);
- if (newtagset) {
- selmon->tagset[selmon->seltags] = newtagset;
- focus(NULL);
- arrange(selmon);
- }
+ selmon->tagset[selmon->seltags] = newtagset;
+ focus(NULL);
+ arrange(selmon);
}
void
void
view(const Arg *arg)
{
- if ((arg->ui & TAGMASK) == selmon->tagset[selmon->seltags])
+ if(arg->ui && (arg->ui & TAGMASK) == selmon->tagset[selmon->seltags])
return;
selmon->seltags ^= 1; /* toggle sel tagset */
if (arg->ui & TAGMASK)
run();
cleanup();
XCloseDisplay(dpy);
+ if (restart == 1) {
+ execlp("dwm-sgk", "dwm-sgk", NULL);
+ }
return EXIT_SUCCESS;
}