JasonWoof Got questions, comments, patches, etc.? Contact Jason Woofenden
Added tag 4.6 for changeset bcd7e18e196a
[dwm.git] / dwm.c
diff --git a/dwm.c b/dwm.c
index ab9c11b..487fafb 100644 (file)
--- a/dwm.c
+++ b/dwm.c
@@ -25,8 +25,6 @@
  *
  * To understand everything else, start reading main().
  */
-#include "dwm.h"
-
 #include <errno.h>
 #include <locale.h>
 #include <stdarg.h>
@@ -41,6 +39,7 @@
 #include <X11/cursorfont.h>
 #include <X11/keysym.h>
 #include <X11/Xatom.h>
+#include <X11/Xlib.h>
 #include <X11/Xproto.h>
 #include <X11/Xutil.h>
 
 #define CLEANMASK(mask)                (mask & ~(numlockmask | LockMask))
 #define MOUSEMASK              (BUTTONMASK | PointerMotionMask)
 
-/* local typedefs */
+/* enums */
+enum { BarTop, BarBot, BarOff };                       /* bar position */
+enum { CurNormal, CurResize, CurMove, CurLast };       /* cursor */
+enum { ColBorder, ColFG, ColBG, ColLast };             /* color */
+enum { NetSupported, NetWMName, NetLast };             /* EWMH atoms */
+enum { WMProtocols, WMDelete, WMName, WMState, WMLast };/* default atoms */
+
+/* typedefs */
+typedef struct Client Client;
+struct Client {
+       char name[256];
+       int x, y, w, h;
+       int rx, ry, rw, rh; /* revert geometry */
+       int basew, baseh, incw, inch, maxw, maxh, minw, minh;
+       int minax, maxax, minay, maxay;
+       long flags;
+       unsigned int border, oldborder;
+       Bool isbanned, isfixed, ismax, isfloating, wasfloating;
+       Bool *tags;
+       Client *next;
+       Client *prev;
+       Client *snext;
+       Window win;
+};
+
+typedef struct {
+       int x, y, w, h;
+       unsigned long norm[ColLast];
+       unsigned long sel[ColLast];
+       Drawable drawable;
+       GC gc;
+       struct {
+               int ascent;
+               int descent;
+               int height;
+               XFontSet set;
+               XFontStruct *xfont;
+       } font;
+} DC; /* draw context */
+
+typedef struct {
+       unsigned long mod;
+       KeySym keysym;
+       void (*func)(const char *arg);
+       const char *arg;
+} Key;
+
+typedef struct {
+       const char *symbol;
+       void (*arrange)(void);
+} Layout;
+
 typedef struct {
        const char *prop;
        const char *tags;
@@ -61,6 +111,86 @@ typedef struct {
        regex_t *tagregex;
 } Regs;
 
+/* function declarations */
+void applyrules(Client *c);
+void arrange(void);
+void attach(Client *c);
+void attachstack(Client *c);
+void ban(Client *c);
+void buttonpress(XEvent *e);
+void checkotherwm(void);
+void cleanup(void);
+void compileregs(void);
+void configure(Client *c);
+void configurenotify(XEvent *e);
+void configurerequest(XEvent *e);
+void destroynotify(XEvent *e);
+void detach(Client *c);
+void detachstack(Client *c);
+void drawbar(void);
+void drawsquare(Bool filled, Bool empty, unsigned long col[ColLast]);
+void drawtext(const char *text, unsigned long col[ColLast]);
+void *emallocz(unsigned int size);
+void enternotify(XEvent *e);
+void eprint(const char *errstr, ...);
+void expose(XEvent *e);
+void floating(void); /* default floating layout */
+void focus(Client *c);
+void focusnext(const char *arg);
+void focusprev(const char *arg);
+Client *getclient(Window w);
+unsigned long getcolor(const char *colstr);
+long getstate(Window w);
+Bool gettextprop(Window w, Atom atom, char *text, unsigned int size);
+void grabbuttons(Client *c, Bool focused);
+unsigned int idxoftag(const char *tag);
+void initfont(const char *fontstr);
+Bool isarrange(void (*func)());
+Bool isoccupied(unsigned int t);
+Bool isprotodel(Client *c);
+Bool isvisible(Client *c);
+void keypress(XEvent *e);
+void killclient(const char *arg);
+void leavenotify(XEvent *e);
+void manage(Window w, XWindowAttributes *wa);
+void mappingnotify(XEvent *e);
+void maprequest(XEvent *e);
+void movemouse(Client *c);
+Client *nexttiled(Client *c);
+void propertynotify(XEvent *e);
+void quit(const char *arg);
+void resize(Client *c, int x, int y, int w, int h, Bool sizehints);
+void resizemouse(Client *c);
+void restack(void);
+void run(void);
+void scan(void);
+void setclientstate(Client *c, long state);
+void setlayout(const char *arg);
+void setmwfact(const char *arg);
+void setup(void);
+void spawn(const char *arg);
+void tag(const char *arg);
+unsigned int textnw(const char *text, unsigned int len);
+unsigned int textw(const char *text);
+void tile(void);
+void togglebar(const char *arg);
+void togglefloating(const char *arg);
+void togglemax(const char *arg);
+void toggletag(const char *arg);
+void toggleview(const char *arg);
+void unban(Client *c);
+void unmanage(Client *c);
+void unmapnotify(XEvent *e);
+void updatebarpos(void);
+void updatesizehints(Client *c);
+void updatetitle(Client *c);
+void view(const char *arg);
+void viewprevtag(const char *arg);     /* views previous selected tags */
+int xerror(Display *dpy, XErrorEvent *ee);
+int xerrordummy(Display *dsply, XErrorEvent *ee);
+int xerrorstart(Display *dsply, XErrorEvent *ee);
+void zoom(const char *arg);
+
 /* variables */
 char stext[256];
 double mwfact;
@@ -102,12 +232,11 @@ Regs *regs = NULL;
 /* configuration, allows nested code to access above variables */
 #include "config.h"
 
-/* Statically define the number of tags. */
-unsigned int ntags = sizeof tags / sizeof tags[0];
-Bool seltags[sizeof tags / sizeof tags[0]] = {[0] = True};
-Bool prevtags[sizeof tags / sizeof tags[0]] = {[0] = True};
+#define NTAGS (sizeof tags / sizeof tags[0])
+Bool seltags[NTAGS] = {[0] = True};
+Bool prevtags[NTAGS] = {[0] = True};
 
-/* functions*/
+/* function implementations */
 void
 applyrules(Client *c) {
        static char buf[512];
@@ -124,7 +253,7 @@ applyrules(Client *c) {
        for(i = 0; i < nrules; i++)
                if(regs[i].propregex && !regexec(regs[i].propregex, buf, 1, &tmp, 0)) {
                        c->isfloating = rules[i].isfloating;
-                       for(j = 0; regs[i].tagregex && j < ntags; j++) {
+                       for(j = 0; regs[i].tagregex && j < NTAGS; j++) {
                                if(!regexec(regs[i].tagregex, tags[j], 1, &tmp, 0)) {
                                        matched = True;
                                        c->tags[j] = True;
@@ -183,7 +312,7 @@ buttonpress(XEvent *e) {
 
        if(barwin == ev->window) {
                x = 0;
-               for(i = 0; i < ntags; i++) {
+               for(i = 0; i < NTAGS; i++) {
                        x += textw(tags[i]);
                        if(ev->x < x) {
                                if(ev->button == Button1) {
@@ -216,7 +345,7 @@ buttonpress(XEvent *e) {
                        movemouse(c);
                }
                else if(ev->button == Button2) {
-                       if(ISTILE && !c->isfixed && c->isfloating)
+                       if((ISTILE) && !c->isfixed && c->isfloating)
                                togglefloating(NULL);
                        else
                                zoom(NULL);
@@ -407,7 +536,7 @@ drawbar(void) {
        int i, x;
 
        dc.x = dc.y = 0;
-       for(i = 0; i < ntags; i++) {
+       for(i = 0; i < NTAGS; i++) {
                dc.w = textw(tags[i]);
                if(seltags[i]) {
                        drawtext(tags[i], dc.sel);
@@ -717,10 +846,8 @@ unsigned int
 idxoftag(const char *tag) {
        unsigned int i;
 
-       for(i = 0; i < ntags; i++)
-               if(tags[i] == tag)
-                       return i;
-       return 0;
+       for(i = 0; (i < NTAGS) && (tags[i] != tag); i++);
+       return (i < NTAGS) ? i : 0;
 }
 
 void
@@ -800,7 +927,7 @@ Bool
 isvisible(Client *c) {
        unsigned int i;
 
-       for(i = 0; i < ntags; i++)
+       for(i = 0; i < NTAGS; i++)
                if(c->tags[i] && seltags[i])
                        return True;
        return False;
@@ -1010,7 +1137,7 @@ propertynotify(XEvent *e) {
                        default: break;
                        case XA_WM_TRANSIENT_FOR:
                                XGetTransientForHint(dpy, c->win, &trans);
-                               if(!c->isfloating && (c->isfloating = (getclient(trans) != NULL)))
+                               if(!c->isfloating && (c->isfloating = (NULL != getclient(trans))))
                                        arrange();
                                break;
                        case XA_WM_NORMAL_HINTS:
@@ -1032,7 +1159,6 @@ quit(const char *arg) {
 
 void
 resize(Client *c, int x, int y, int w, int h, Bool sizehints) {
-       double dx, dy, max, min, ratio;
        XWindowChanges wc;
 
        if(sizehints) {
@@ -1273,7 +1399,7 @@ void
 setmwfact(const char *arg) {
        double delta;
 
-       if(!ISTILE)
+       if(!(ISTILE))
                return;
        /* arg handling, manipulate mwfact */
        if(arg == NULL)
@@ -1413,11 +1539,9 @@ tag(const char *arg) {
 
        if(!sel)
                return;
-       for(i = 0; i < ntags; i++)
-               sel->tags[i] = arg == NULL;
-       i = idxoftag(arg);
-       if(i >= 0 && i < ntags)
-               sel->tags[i] = True;
+       for(i = 0; i < NTAGS; i++)
+               sel->tags[i] = (NULL == arg);
+       sel->tags[idxoftag(arg)] = True;
        arrange();
 }
 
@@ -1471,7 +1595,10 @@ tile(void) {
                        else
                                nh = th - 2 * c->border;
                }
-               resize(c, nx, ny, nw, nh, RESIZEHINTS);
+               resize(c, nx, ny, nw, nh, True);
+               if((c->h < bh) || (c->h > nh) || (c->w < bh) || (c->w > nw))
+                       /* client doesn't accept size constraints */
+                       resize(c, nx, ny, nw, nh, False);
                if(n > 1 && th != wah)
                        ny = c->y + c->h + 2 * c->border;
        }
@@ -1533,9 +1660,9 @@ toggletag(const char *arg) {
                return;
        i = idxoftag(arg);
        sel->tags[i] = !sel->tags[i];
-       for(j = 0; j < ntags && !sel->tags[j]; j++);
-       if(j == ntags)
-               sel->tags[i] = True;
+       for(j = 0; j < NTAGS && !sel->tags[j]; j++);
+       if(j == NTAGS)
+               sel->tags[i] = True; /* at least one tag must be enabled */
        arrange();
 }
 
@@ -1545,8 +1672,8 @@ toggleview(const char *arg) {
 
        i = idxoftag(arg);
        seltags[i] = !seltags[i];
-       for(j = 0; j < ntags && !seltags[j]; j++);
-       if(j == ntags)
+       for(j = 0; j < NTAGS && !seltags[j]; j++);
+       if(j == NTAGS)
                seltags[i] = True; /* at least one tag must be viewed */
        arrange();
 }
@@ -1712,11 +1839,9 @@ view(const char *arg) {
        unsigned int i;
 
        memcpy(prevtags, seltags, sizeof seltags);
-       for(i = 0; i < ntags; i++)
+       for(i = 0; i < NTAGS; i++)
                seltags[i] = arg == NULL;
-       i = idxoftag(arg);
-       if(i >= 0 && i < ntags)
-               seltags[i] = True;
+       seltags[idxoftag(arg)] = True;
        arrange();
 }
 
@@ -1734,7 +1859,7 @@ void
 zoom(const char *arg) {
        Client *c;
 
-       if(!sel || !ISTILE || sel->isfloating)
+       if(!sel || !(ISTILE) || sel->isfloating)
                return;
        if((c = sel) == nexttiled(clients))
                if(!(c = nexttiled(c->next)))