Xinqi Bao's Git
8b67cea49b2c3cc582b9b3ae2ad83135ee5fa237
   1 /* See LICENSE file for copyright and license details. 
   3  * dynamic window manager is designed like any other X client as well. It is 
   4  * driven through handling X events. In contrast to other X clients, a window 
   5  * manager selects for SubstructureRedirectMask on the root window, to receive 
   6  * events about window (dis-)appearance.  Only one X connection at a time is 
   7  * allowed to select for this event mask. 
   9  * The event handlers of dwm are organized in an array which is accessed 
  10  * whenever a new event has been fetched. This allows event dispatching 
  13  * Each child of the root window is called a client, except windows which have 
  14  * set the override_redirect flag.  Clients are organized in a linked client 
  15  * list on each monitor, the focus history is remembered through a stack list 
  16  * on each monitor. Each client contains a bit array to indicate the tags of a 
  19  * Keys and tagging rules are organized as arrays and defined in config.h. 
  21  * To understand everything else, start reading main(). 
  31 #include <sys/types.h> 
  33 #include <X11/cursorfont.h> 
  34 #include <X11/keysym.h> 
  35 #include <X11/Xatom.h> 
  37 #include <X11/Xproto.h> 
  38 #include <X11/Xutil.h> 
  40 #include <X11/extensions/Xinerama.h> 
  46 #define BUTTONMASK              (ButtonPressMask|ButtonReleaseMask) 
  47 #define CLEANMASK(mask)         (mask & ~(numlockmask|LockMask) & (ShiftMask|ControlMask|Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask)) 
  48 #define INTERSECT(x,y,w,h,m)    (MAX(0, MIN((x)+(w),(m)->wx+(m)->ww) - MAX((x),(m)->wx)) \ 
  49                                * MAX(0, MIN((y)+(h),(m)->wy+(m)->wh) - MAX((y),(m)->wy))) 
  50 #define ISVISIBLE(C)            ((C->tags & C->mon->tagset[C->mon->seltags])) 
  51 #define LENGTH(X)               (sizeof X / sizeof X[0]) 
  52 #define MAX(A, B)               ((A) > (B) ? (A) : (B)) 
  53 #define MIN(A, B)               ((A) < (B) ? (A) : (B)) 
  54 #define MOUSEMASK               (BUTTONMASK|PointerMotionMask) 
  55 #define WIDTH(X)                ((X)->w + 2 * (X)->bw) 
  56 #define HEIGHT(X)               ((X)->h + 2 * (X)->bw) 
  57 #define TAGMASK                 ((1 << LENGTH(tags)) - 1) 
  58 #define TEXTW(X)                (textnw(X, strlen(X)) + dc.font.height) 
  61 enum { CurNormal
, CurResize
, CurMove
, CurLast 
};        /* cursor */ 
  62 enum { ColBorder
, ColFG
, ColBG
, ColLast 
};              /* color */ 
  63 enum { NetSupported
, NetWMName
, NetWMState
, 
  64        NetWMFullscreen
, NetActiveWindow
, NetWMWindowType
, 
  65        NetWMWindowTypeDialog
, NetClientList
, NetLast 
};     /* EWMH atoms */ 
  66 enum { WMProtocols
, WMDelete
, WMState
, WMTakeFocus
, WMLast 
}; /* default atoms */ 
  67 enum { ClkTagBar
, ClkLtSymbol
, ClkStatusText
, ClkWinTitle
, 
  68        ClkClientWin
, ClkRootWin
, ClkLast 
};             /* clicks */ 
  81         void (*func
)(const Arg 
*arg
); 
  85 typedef struct Monitor Monitor
; 
  86 typedef struct Client Client
; 
  91         int oldx
, oldy
, oldw
, oldh
; 
  92         int basew
, baseh
, incw
, inch
, maxw
, maxh
, minw
, minh
; 
  95         Bool isfixed
, isfloating
, isurgent
, neverfocus
, oldstate
, isfullscreen
; 
 104         unsigned long norm
[ColLast
]; 
 105         unsigned long sel
[ColLast
]; 
 115 } DC
; /* draw context */ 
 120         void (*func
)(const Arg 
*); 
 126         void (*arrange
)(Monitor 
*); 
 134         int by
;               /* bar geometry */ 
 135         int mx
, my
, mw
, mh
;   /* screen size */ 
 136         int wx
, wy
, ww
, wh
;   /* window area  */ 
 137         unsigned int seltags
; 
 139         unsigned int tagset
[2]; 
 152         const char *instance
; 
 159 /* function declarations */ 
 160 static void applyrules(Client 
*c
); 
 161 static Bool 
applysizehints(Client 
*c
, int *x
, int *y
, int *w
, int *h
, Bool interact
); 
 162 static void arrange(Monitor 
*m
); 
 163 static void arrangemon(Monitor 
*m
); 
 164 static void attach(Client 
*c
); 
 165 static void attachstack(Client 
*c
); 
 166 static void buttonpress(XEvent 
*e
); 
 167 static void checkotherwm(void); 
 168 static void cleanup(void); 
 169 static void cleanupmon(Monitor 
*mon
); 
 170 static void clearurgent(Client 
*c
); 
 171 static void clientmessage(XEvent 
*e
); 
 172 static void configure(Client 
*c
); 
 173 static void configurenotify(XEvent 
*e
); 
 174 static void configurerequest(XEvent 
*e
); 
 175 static Monitor 
*createmon(void); 
 176 static void destroynotify(XEvent 
*e
); 
 177 static void detach(Client 
*c
); 
 178 static void detachstack(Client 
*c
); 
 179 static void die(const char *errstr
, ...); 
 180 static Monitor 
*dirtomon(int dir
); 
 181 static void drawbar(Monitor 
*m
); 
 182 static void drawbars(void); 
 183 static void drawsquare(Bool filled
, Bool empty
, Bool invert
, unsigned long col
[ColLast
]); 
 184 static void drawtext(const char *text
, unsigned long col
[ColLast
], Bool invert
); 
 185 static void enternotify(XEvent 
*e
); 
 186 static void expose(XEvent 
*e
); 
 187 static void focus(Client 
*c
); 
 188 static void focusin(XEvent 
*e
); 
 189 static void focusmon(const Arg 
*arg
); 
 190 static void focusstack(const Arg 
*arg
); 
 191 static unsigned long getcolor(const char *colstr
); 
 192 static Bool 
getrootptr(int *x
, int *y
); 
 193 static long getstate(Window w
); 
 194 static Bool 
gettextprop(Window w
, Atom atom
, char *text
, unsigned int size
); 
 195 static void grabbuttons(Client 
*c
, Bool focused
); 
 196 static void grabkeys(void); 
 197 static void incnmaster(const Arg 
*arg
); 
 198 static void initfont(const char *fontstr
); 
 199 static void keypress(XEvent 
*e
); 
 200 static void killclient(const Arg 
*arg
); 
 201 static void manage(Window w
, XWindowAttributes 
*wa
); 
 202 static void mappingnotify(XEvent 
*e
); 
 203 static void maprequest(XEvent 
*e
); 
 204 static void monocle(Monitor 
*m
); 
 205 static void motionnotify(XEvent 
*e
); 
 206 static void movemouse(const Arg 
*arg
); 
 207 static Client 
*nexttiled(Client 
*c
); 
 208 static void pop(Client 
*); 
 209 static void propertynotify(XEvent 
*e
); 
 210 static void quit(const Arg 
*arg
); 
 211 static Monitor 
*recttomon(int x
, int y
, int w
, int h
); 
 212 static void resize(Client 
*c
, int x
, int y
, int w
, int h
, Bool interact
); 
 213 static void resizeclient(Client 
*c
, int x
, int y
, int w
, int h
); 
 214 static void resizemouse(const Arg 
*arg
); 
 215 static void restack(Monitor 
*m
); 
 216 static void run(void); 
 217 static void scan(void); 
 218 static Bool 
sendevent(Client 
*c
, Atom proto
); 
 219 static void sendmon(Client 
*c
, Monitor 
*m
); 
 220 static void setclientstate(Client 
*c
, long state
); 
 221 static void setfocus(Client 
*c
); 
 222 static void setfullscreen(Client 
*c
, Bool fullscreen
); 
 223 static void setlayout(const Arg 
*arg
); 
 224 static void setmfact(const Arg 
*arg
); 
 225 static void setup(void); 
 226 static void showhide(Client 
*c
); 
 227 static void sigchld(int unused
); 
 228 static void spawn(const Arg 
*arg
); 
 229 static void tag(const Arg 
*arg
); 
 230 static void tagmon(const Arg 
*arg
); 
 231 static int textnw(const char *text
, unsigned int len
); 
 232 static void tile(Monitor 
*); 
 233 static void togglebar(const Arg 
*arg
); 
 234 static void togglefloating(const Arg 
*arg
); 
 235 static void toggletag(const Arg 
*arg
); 
 236 static void toggleview(const Arg 
*arg
); 
 237 static void unfocus(Client 
*c
, Bool setfocus
); 
 238 static void unmanage(Client 
*c
, Bool destroyed
); 
 239 static void unmapnotify(XEvent 
*e
); 
 240 static Bool 
updategeom(void); 
 241 static void updatebarpos(Monitor 
*m
); 
 242 static void updatebars(void); 
 243 static void updateclientlist(void); 
 244 static void updatenumlockmask(void); 
 245 static void updatesizehints(Client 
*c
); 
 246 static void updatestatus(void); 
 247 static void updatewindowtype(Client 
*c
); 
 248 static void updatetitle(Client 
*c
); 
 249 static void updatewmhints(Client 
*c
); 
 250 static void view(const Arg 
*arg
); 
 251 static Client 
*wintoclient(Window w
); 
 252 static Monitor 
*wintomon(Window w
); 
 253 static int xerror(Display 
*dpy
, XErrorEvent 
*ee
); 
 254 static int xerrordummy(Display 
*dpy
, XErrorEvent 
*ee
); 
 255 static int xerrorstart(Display 
*dpy
, XErrorEvent 
*ee
); 
 256 static void zoom(const Arg 
*arg
); 
 259 static const char broken
[] = "broken"; 
 260 static char stext
[256]; 
 262 static int sw
, sh
;           /* X display screen geometry width, height */ 
 263 static int bh
, blw 
= 0;      /* bar geometry */ 
 264 static int (*xerrorxlib
)(Display 
*, XErrorEvent 
*); 
 265 static unsigned int numlockmask 
= 0; 
 266 static void (*handler
[LASTEvent
]) (XEvent 
*) = { 
 267         [ButtonPress
] = buttonpress
, 
 268         [ClientMessage
] = clientmessage
, 
 269         [ConfigureRequest
] = configurerequest
, 
 270         [ConfigureNotify
] = configurenotify
, 
 271         [DestroyNotify
] = destroynotify
, 
 272         [EnterNotify
] = enternotify
, 
 275         [KeyPress
] = keypress
, 
 276         [MappingNotify
] = mappingnotify
, 
 277         [MapRequest
] = maprequest
, 
 278         [MotionNotify
] = motionnotify
, 
 279         [PropertyNotify
] = propertynotify
, 
 280         [UnmapNotify
] = unmapnotify
 
 282 static Atom wmatom
[WMLast
], netatom
[NetLast
]; 
 283 static Bool running 
= True
; 
 284 static Cursor cursor
[CurLast
]; 
 287 static Monitor 
*mons 
= NULL
, *selmon 
= NULL
; 
 290 /* configuration, allows nested code to access above variables */ 
 293 /* compile-time check if all tags fit into an unsigned int bit array. */ 
 294 struct NumTags 
{ char limitexceeded
[LENGTH(tags
) > 31 ? -1 : 1]; }; 
 296 /* function implementations */ 
 298 applyrules(Client 
*c
) { 
 299         const char *class, *instance
; 
 303         XClassHint ch 
= { NULL
, NULL 
}; 
 306         c
->isfloating 
= c
->tags 
= 0; 
 307         XGetClassHint(dpy
, c
->win
, &ch
); 
 308         class    = ch
.res_class 
? ch
.res_class 
: broken
; 
 309         instance 
= ch
.res_name  
? ch
.res_name  
: broken
; 
 311         for(i 
= 0; i 
< LENGTH(rules
); i
++) { 
 313                 if((!r
->title 
|| strstr(c
->name
, r
->title
)) 
 314                 && (!r
->class || strstr(class, r
->class)) 
 315                 && (!r
->instance 
|| strstr(instance
, r
->instance
))) 
 317                         c
->isfloating 
= r
->isfloating
; 
 319                         for(m 
= mons
; m 
&& m
->num 
!= r
->monitor
; m 
= m
->next
); 
 328         c
->tags 
= c
->tags 
& TAGMASK 
? c
->tags 
& TAGMASK 
: c
->mon
->tagset
[c
->mon
->seltags
]; 
 332 applysizehints(Client 
*c
, int *x
, int *y
, int *w
, int *h
, Bool interact
) { 
 336         /* set minimum possible */ 
 344                 if(*x 
+ *w 
+ 2 * c
->bw 
< 0) 
 346                 if(*y 
+ *h 
+ 2 * c
->bw 
< 0) 
 350                 if(*x 
>= m
->wx 
+ m
->ww
) 
 351                         *x 
= m
->wx 
+ m
->ww 
- WIDTH(c
); 
 352                 if(*y 
>= m
->wy 
+ m
->wh
) 
 353                         *y 
= m
->wy 
+ m
->wh 
- HEIGHT(c
); 
 354                 if(*x 
+ *w 
+ 2 * c
->bw 
<= m
->wx
) 
 356                 if(*y 
+ *h 
+ 2 * c
->bw 
<= m
->wy
) 
 363         if(resizehints 
|| c
->isfloating 
|| !c
->mon
->lt
[c
->mon
->sellt
]->arrange
) { 
 364                 /* see last two sentences in ICCCM 4.1.2.3 */ 
 365                 baseismin 
= c
->basew 
== c
->minw 
&& c
->baseh 
== c
->minh
; 
 366                 if(!baseismin
) { /* temporarily remove base dimensions */ 
 370                 /* adjust for aspect limits */ 
 371                 if(c
->mina 
> 0 && c
->maxa 
> 0) { 
 372                         if(c
->maxa 
< (float)*w 
/ *h
) 
 373                                 *w 
= *h 
* c
->maxa 
+ 0.5; 
 374                         else if(c
->mina 
< (float)*h 
/ *w
) 
 375                                 *h 
= *w 
* c
->mina 
+ 0.5; 
 377                 if(baseismin
) { /* increment calculation requires this */ 
 381                 /* adjust for increment value */ 
 386                 /* restore base dimensions */ 
 387                 *w 
= MAX(*w 
+ c
->basew
, c
->minw
); 
 388                 *h 
= MAX(*h 
+ c
->baseh
, c
->minh
); 
 390                         *w 
= MIN(*w
, c
->maxw
); 
 392                         *h 
= MIN(*h
, c
->maxh
); 
 394         return *x 
!= c
->x 
|| *y 
!= c
->y 
|| *w 
!= c
->w 
|| *h 
!= c
->h
; 
 398 arrange(Monitor 
*m
) { 
 401         else for(m 
= mons
; m
; m 
= m
->next
) 
 406         } else for(m 
= mons
; m
; m 
= m
->next
) 
 411 arrangemon(Monitor 
*m
) { 
 412         strncpy(m
->ltsymbol
, m
->lt
[m
->sellt
]->symbol
, sizeof m
->ltsymbol
); 
 413         if(m
->lt
[m
->sellt
]->arrange
) 
 414                 m
->lt
[m
->sellt
]->arrange(m
); 
 419         c
->next 
= c
->mon
->clients
; 
 424 attachstack(Client 
*c
) { 
 425         c
->snext 
= c
->mon
->stack
; 
 430 buttonpress(XEvent 
*e
) { 
 431         unsigned int i
, x
, click
; 
 435         XButtonPressedEvent 
*ev 
= &e
->xbutton
; 
 438         /* focus monitor if necessary */ 
 439         if((m 
= wintomon(ev
->window
)) && m 
!= selmon
) { 
 440                 unfocus(selmon
->sel
, True
); 
 444         if(ev
->window 
== selmon
->barwin
) { 
 448                 while(ev
->x 
>= x 
&& ++i 
< LENGTH(tags
)); 
 449                 if(i 
< LENGTH(tags
)) { 
 453                 else if(ev
->x 
< x 
+ blw
) 
 455                 else if(ev
->x 
> selmon
->ww 
- TEXTW(stext
)) 
 456                         click 
= ClkStatusText
; 
 460         else if((c 
= wintoclient(ev
->window
))) { 
 462                 click 
= ClkClientWin
; 
 464         for(i 
= 0; i 
< LENGTH(buttons
); i
++) 
 465                 if(click 
== buttons
[i
].click 
&& buttons
[i
].func 
&& buttons
[i
].button 
== ev
->button
 
 466                 && CLEANMASK(buttons
[i
].mask
) == CLEANMASK(ev
->state
)) 
 467                         buttons
[i
].func(click 
== ClkTagBar 
&& buttons
[i
].arg
.i 
== 0 ? &arg 
: &buttons
[i
].arg
); 
 472         xerrorxlib 
= XSetErrorHandler(xerrorstart
); 
 473         /* this causes an error if some other window manager is running */ 
 474         XSelectInput(dpy
, DefaultRootWindow(dpy
), SubstructureRedirectMask
); 
 476         XSetErrorHandler(xerror
); 
 483         Layout foo 
= { "", NULL 
}; 
 487         selmon
->lt
[selmon
->sellt
] = &foo
; 
 488         for(m 
= mons
; m
; m 
= m
->next
) 
 490                         unmanage(m
->stack
, False
); 
 492                 XFreeFontSet(dpy
, dc
.font
.set
); 
 494                 XFreeFont(dpy
, dc
.font
.xfont
); 
 495         XUngrabKey(dpy
, AnyKey
, AnyModifier
, root
); 
 496         XFreePixmap(dpy
, dc
.drawable
); 
 498         XFreeCursor(dpy
, cursor
[CurNormal
]); 
 499         XFreeCursor(dpy
, cursor
[CurResize
]); 
 500         XFreeCursor(dpy
, cursor
[CurMove
]); 
 504         XSetInputFocus(dpy
, PointerRoot
, RevertToPointerRoot
, CurrentTime
); 
 505         XDeleteProperty(dpy
, root
, netatom
[NetActiveWindow
]); 
 509 cleanupmon(Monitor 
*mon
) { 
 515                 for(m 
= mons
; m 
&& m
->next 
!= mon
; m 
= m
->next
); 
 518         XUnmapWindow(dpy
, mon
->barwin
); 
 519         XDestroyWindow(dpy
, mon
->barwin
); 
 524 clearurgent(Client 
*c
) { 
 528         if(!(wmh 
= XGetWMHints(dpy
, c
->win
))) 
 530         wmh
->flags 
&= ~XUrgencyHint
; 
 531         XSetWMHints(dpy
, c
->win
, wmh
); 
 536 clientmessage(XEvent 
*e
) { 
 537         XClientMessageEvent 
*cme 
= &e
->xclient
; 
 538         Client 
*c 
= wintoclient(cme
->window
); 
 542         if(cme
->message_type 
== netatom
[NetWMState
]) { 
 543                 if(cme
->data
.l
[1] == netatom
[NetWMFullscreen
] || cme
->data
.l
[2] == netatom
[NetWMFullscreen
]) 
 544                         setfullscreen(c
, (cme
->data
.l
[0] == 1 /* _NET_WM_STATE_ADD    */ 
 545                                       || (cme
->data
.l
[0] == 2 /* _NET_WM_STATE_TOGGLE */ && !c
->isfullscreen
))); 
 547         else if(cme
->message_type 
== netatom
[NetActiveWindow
]) { 
 549                         c
->mon
->seltags 
^= 1; 
 550                         c
->mon
->tagset
[c
->mon
->seltags
] = c
->tags
; 
 557 configure(Client 
*c
) { 
 560         ce
.type 
= ConfigureNotify
; 
 568         ce
.border_width 
= c
->bw
; 
 570         ce
.override_redirect 
= False
; 
 571         XSendEvent(dpy
, c
->win
, False
, StructureNotifyMask
, (XEvent 
*)&ce
); 
 575 configurenotify(XEvent 
*e
) { 
 577         XConfigureEvent 
*ev 
= &e
->xconfigure
; 
 580         // TODO: updategeom handling sucks, needs to be simplified 
 581         if(ev
->window 
== root
) { 
 582                 dirty 
= (sw 
!= ev
->width 
|| sh 
!= ev
->height
); 
 585                 if(updategeom() || dirty
) { 
 587                                 XFreePixmap(dpy
, dc
.drawable
); 
 588                         dc
.drawable 
= XCreatePixmap(dpy
, root
, sw
, bh
, DefaultDepth(dpy
, screen
)); 
 590                         for(m 
= mons
; m
; m 
= m
->next
) 
 591                                 XMoveResizeWindow(dpy
, m
->barwin
, m
->wx
, m
->by
, m
->ww
, bh
); 
 599 configurerequest(XEvent 
*e
) { 
 602         XConfigureRequestEvent 
*ev 
= &e
->xconfigurerequest
; 
 605         if((c 
= wintoclient(ev
->window
))) { 
 606                 if(ev
->value_mask 
& CWBorderWidth
) 
 607                         c
->bw 
= ev
->border_width
; 
 608                 else if(c
->isfloating 
|| !selmon
->lt
[selmon
->sellt
]->arrange
) { 
 610                         if(ev
->value_mask 
& CWX
) { 
 612                                 c
->x 
= m
->mx 
+ ev
->x
; 
 614                         if(ev
->value_mask 
& CWY
) { 
 616                                 c
->y 
= m
->my 
+ ev
->y
; 
 618                         if(ev
->value_mask 
& CWWidth
) { 
 622                         if(ev
->value_mask 
& CWHeight
) { 
 626                         if((c
->x 
+ c
->w
) > m
->mx 
+ m
->mw 
&& c
->isfloating
) 
 627                                 c
->x 
= m
->mx 
+ (m
->mw 
/ 2 - WIDTH(c
) / 2); /* center in x direction */ 
 628                         if((c
->y 
+ c
->h
) > m
->my 
+ m
->mh 
&& c
->isfloating
) 
 629                                 c
->y 
= m
->my 
+ (m
->mh 
/ 2 - HEIGHT(c
) / 2); /* center in y direction */ 
 630                         if((ev
->value_mask 
& (CWX
|CWY
)) && !(ev
->value_mask 
& (CWWidth
|CWHeight
))) 
 633                                 XMoveResizeWindow(dpy
, c
->win
, c
->x
, c
->y
, c
->w
, c
->h
); 
 641                 wc
.width 
= ev
->width
; 
 642                 wc
.height 
= ev
->height
; 
 643                 wc
.border_width 
= ev
->border_width
; 
 644                 wc
.sibling 
= ev
->above
; 
 645                 wc
.stack_mode 
= ev
->detail
; 
 646                 XConfigureWindow(dpy
, ev
->window
, ev
->value_mask
, &wc
); 
 655         if(!(m 
= (Monitor 
*)calloc(1, sizeof(Monitor
)))) 
 656                 die("fatal: could not malloc() %u bytes\n", sizeof(Monitor
)); 
 657         m
->tagset
[0] = m
->tagset
[1] = 1; 
 659         m
->nmaster 
= nmaster
; 
 660         m
->showbar 
= showbar
; 
 662         m
->lt
[0] = &layouts
[0]; 
 663         m
->lt
[1] = &layouts
[1 % LENGTH(layouts
)]; 
 664         strncpy(m
->ltsymbol
, layouts
[0].symbol
, sizeof m
->ltsymbol
); 
 669 destroynotify(XEvent 
*e
) { 
 671         XDestroyWindowEvent 
*ev 
= &e
->xdestroywindow
; 
 673         if((c 
= wintoclient(ev
->window
))) 
 681         for(tc 
= &c
->mon
->clients
; *tc 
&& *tc 
!= c
; tc 
= &(*tc
)->next
); 
 686 detachstack(Client 
*c
) { 
 689         for(tc 
= &c
->mon
->stack
; *tc 
&& *tc 
!= c
; tc 
= &(*tc
)->snext
); 
 692         if(c 
== c
->mon
->sel
) { 
 693                 for(t 
= c
->mon
->stack
; t 
&& !ISVISIBLE(t
); t 
= t
->snext
); 
 699 die(const char *errstr
, ...) { 
 702         va_start(ap
, errstr
); 
 703         vfprintf(stderr
, errstr
, ap
); 
 713                 if(!(m 
= selmon
->next
)) 
 716         else if(selmon 
== mons
) 
 717                 for(m 
= mons
; m
->next
; m 
= m
->next
); 
 719                 for(m 
= mons
; m
->next 
!= selmon
; m 
= m
->next
); 
 724 drawbar(Monitor 
*m
) { 
 726         unsigned int i
, occ 
= 0, urg 
= 0; 
 730         for(c 
= m
->clients
; c
; c 
= c
->next
) { 
 736         for(i 
= 0; i 
< LENGTH(tags
); i
++) { 
 737                 dc
.w 
= TEXTW(tags
[i
]); 
 738                 col 
= m
->tagset
[m
->seltags
] & 1 << i 
? dc
.sel 
: dc
.norm
; 
 739                 drawtext(tags
[i
], col
, urg 
& 1 << i
); 
 740                 drawsquare(m 
== selmon 
&& selmon
->sel 
&& selmon
->sel
->tags 
& 1 << i
, 
 741                            occ 
& 1 << i
, urg 
& 1 << i
, col
); 
 744         dc
.w 
= blw 
= TEXTW(m
->ltsymbol
); 
 745         drawtext(m
->ltsymbol
, dc
.norm
, False
); 
 748         if(m 
== selmon
) { /* status is only drawn on selected monitor */ 
 755                 drawtext(stext
, dc
.norm
, False
); 
 759         if((dc
.w 
= dc
.x 
- x
) > bh
) { 
 762                         col 
= m 
== selmon 
? dc
.sel 
: dc
.norm
; 
 763                         drawtext(m
->sel
->name
, col
, False
); 
 764                         drawsquare(m
->sel
->isfixed
, m
->sel
->isfloating
, False
, col
); 
 767                         drawtext(NULL
, dc
.norm
, False
); 
 769         XCopyArea(dpy
, dc
.drawable
, m
->barwin
, dc
.gc
, 0, 0, m
->ww
, bh
, 0, 0); 
 777         for(m 
= mons
; m
; m 
= m
->next
) 
 782 drawsquare(Bool filled
, Bool empty
, Bool invert
, unsigned long col
[ColLast
]) { 
 785         XSetForeground(dpy
, dc
.gc
, col
[invert 
? ColBG 
: ColFG
]); 
 786         x 
= (dc
.font
.ascent 
+ dc
.font
.descent 
+ 2) / 4; 
 788                 XFillRectangle(dpy
, dc
.drawable
, dc
.gc
, dc
.x
+1, dc
.y
+1, x
+1, x
+1); 
 790                 XDrawRectangle(dpy
, dc
.drawable
, dc
.gc
, dc
.x
+1, dc
.y
+1, x
, x
); 
 794 drawtext(const char *text
, unsigned long col
[ColLast
], Bool invert
) { 
 796         int i
, x
, y
, h
, len
, olen
; 
 798         XSetForeground(dpy
, dc
.gc
, col
[invert 
? ColFG 
: ColBG
]); 
 799         XFillRectangle(dpy
, dc
.drawable
, dc
.gc
, dc
.x
, dc
.y
, dc
.w
, dc
.h
); 
 803         h 
= dc
.font
.ascent 
+ dc
.font
.descent
; 
 804         y 
= dc
.y 
+ (dc
.h 
/ 2) - (h 
/ 2) + dc
.font
.ascent
; 
 806         /* shorten text if necessary */ 
 807         for(len 
= MIN(olen
, sizeof buf
); len 
&& textnw(text
, len
) > dc
.w 
- h
; len
--); 
 810         memcpy(buf
, text
, len
); 
 812                 for(i 
= len
; i 
&& i 
> len 
- 3; buf
[--i
] = '.'); 
 813         XSetForeground(dpy
, dc
.gc
, col
[invert 
? ColBG 
: ColFG
]); 
 815                 XmbDrawString(dpy
, dc
.drawable
, dc
.font
.set
, dc
.gc
, x
, y
, buf
, len
); 
 817                 XDrawString(dpy
, dc
.drawable
, dc
.gc
, x
, y
, buf
, len
); 
 821 enternotify(XEvent 
*e
) { 
 824         XCrossingEvent 
*ev 
= &e
->xcrossing
; 
 826         if((ev
->mode 
!= NotifyNormal 
|| ev
->detail 
== NotifyInferior
) && ev
->window 
!= root
) 
 828         c 
= wintoclient(ev
->window
); 
 829         m 
= c 
? c
->mon 
: wintomon(ev
->window
); 
 831                 unfocus(selmon
->sel
, True
); 
 834         else if(!c 
|| c 
== selmon
->sel
) 
 842         XExposeEvent 
*ev 
= &e
->xexpose
; 
 844         if(ev
->count 
== 0 && (m 
= wintomon(ev
->window
))) 
 850         if(!c 
|| !ISVISIBLE(c
)) 
 851                 for(c 
= selmon
->stack
; c 
&& !ISVISIBLE(c
); c 
= c
->snext
); 
 852         /* was if(selmon->sel) */ 
 853         if(selmon
->sel 
&& selmon
->sel 
!= c
) 
 854                 unfocus(selmon
->sel
, False
); 
 862                 grabbuttons(c
, True
); 
 863                 XSetWindowBorder(dpy
, c
->win
, dc
.sel
[ColBorder
]); 
 867                 XSetInputFocus(dpy
, root
, RevertToPointerRoot
, CurrentTime
); 
 868                 XDeleteProperty(dpy
, root
, netatom
[NetActiveWindow
]); 
 875 focusin(XEvent 
*e
) { /* there are some broken focus acquiring clients */ 
 876         XFocusChangeEvent 
*ev 
= &e
->xfocus
; 
 878         if(selmon
->sel 
&& ev
->window 
!= selmon
->sel
->win
) 
 879                 setfocus(selmon
->sel
); 
 883 focusmon(const Arg 
*arg
) { 
 888         if((m 
= dirtomon(arg
->i
)) == selmon
) 
 890         unfocus(selmon
->sel
, False
); /* s/True/False/ fixes input focus issues 
 891                                         in gedit and anjuta */ 
 897 focusstack(const Arg 
*arg
) { 
 898         Client 
*c 
= NULL
, *i
; 
 903                 for(c 
= selmon
->sel
->next
; c 
&& !ISVISIBLE(c
); c 
= c
->next
); 
 905                         for(c 
= selmon
->clients
; c 
&& !ISVISIBLE(c
); c 
= c
->next
); 
 908                 for(i 
= selmon
->clients
; i 
!= selmon
->sel
; i 
= i
->next
) 
 912                         for(; i
; i 
= i
->next
) 
 923 getatomprop(Client 
*c
, Atom prop
) { 
 926         unsigned char *p 
= NULL
; 
 927         Atom da
, atom 
= None
; 
 929         if(XGetWindowProperty(dpy
, c
->win
, prop
, 0L, sizeof atom
, False
, XA_ATOM
, 
 930                               &da
, &di
, &dl
, &dl
, &p
) == Success 
&& p
) { 
 938 getcolor(const char *colstr
) { 
 939         Colormap cmap 
= DefaultColormap(dpy
, screen
); 
 942         if(!XAllocNamedColor(dpy
, cmap
, colstr
, &color
, &color
)) 
 943                 die("error, cannot allocate color '%s'\n", colstr
); 
 948 getrootptr(int *x
, int *y
) { 
 953         return XQueryPointer(dpy
, root
, &dummy
, &dummy
, x
, y
, &di
, &di
, &dui
); 
 960         unsigned char *p 
= NULL
; 
 961         unsigned long n
, extra
; 
 964         if(XGetWindowProperty(dpy
, w
, wmatom
[WMState
], 0L, 2L, False
, wmatom
[WMState
], 
 965                               &real
, &format
, &n
, &extra
, (unsigned char **)&p
) != Success
) 
 974 gettextprop(Window w
, Atom atom
, char *text
, unsigned int size
) { 
 979         if(!text 
|| size 
== 0) 
 982         XGetTextProperty(dpy
, w
, &name
, atom
); 
 985         if(name
.encoding 
== XA_STRING
) 
 986                 strncpy(text
, (char *)name
.value
, size 
- 1); 
 988                 if(XmbTextPropertyToTextList(dpy
, &name
, &list
, &n
) >= Success 
&& n 
> 0 && *list
) { 
 989                         strncpy(text
, *list
, size 
- 1); 
 990                         XFreeStringList(list
); 
 993         text
[size 
- 1] = '\0'; 
 999 grabbuttons(Client 
*c
, Bool focused
) { 
1000         updatenumlockmask(); 
1003                 unsigned int modifiers
[] = { 0, LockMask
, numlockmask
, numlockmask
|LockMask 
}; 
1004                 XUngrabButton(dpy
, AnyButton
, AnyModifier
, c
->win
); 
1006                         for(i 
= 0; i 
< LENGTH(buttons
); i
++) 
1007                                 if(buttons
[i
].click 
== ClkClientWin
) 
1008                                         for(j 
= 0; j 
< LENGTH(modifiers
); j
++) 
1009                                                 XGrabButton(dpy
, buttons
[i
].button
, 
1010                                                             buttons
[i
].mask 
| modifiers
[j
], 
1011                                                             c
->win
, False
, BUTTONMASK
, 
1012                                                             GrabModeAsync
, GrabModeSync
, None
, None
); 
1015                         XGrabButton(dpy
, AnyButton
, AnyModifier
, c
->win
, False
, 
1016                                     BUTTONMASK
, GrabModeAsync
, GrabModeSync
, None
, None
); 
1022         updatenumlockmask(); 
1025                 unsigned int modifiers
[] = { 0, LockMask
, numlockmask
, numlockmask
|LockMask 
}; 
1028                 XUngrabKey(dpy
, AnyKey
, AnyModifier
, root
); 
1029                 for(i 
= 0; i 
< LENGTH(keys
); i
++) 
1030                         if((code 
= XKeysymToKeycode(dpy
, keys
[i
].keysym
))) 
1031                                 for(j 
= 0; j 
< LENGTH(modifiers
); j
++) 
1032                                         XGrabKey(dpy
, code
, keys
[i
].mod 
| modifiers
[j
], root
, 
1033                                                  True
, GrabModeAsync
, GrabModeAsync
); 
1038 incnmaster(const Arg 
*arg
) { 
1039         selmon
->nmaster 
= MAX(selmon
->nmaster 
+ arg
->i
, 0); 
1044 initfont(const char *fontstr
) { 
1045         char *def
, **missing
; 
1048         dc
.font
.set 
= XCreateFontSet(dpy
, fontstr
, &missing
, &n
, &def
); 
1051                         fprintf(stderr
, "dwm: missing fontset: %s\n", missing
[n
]); 
1052                 XFreeStringList(missing
); 
1055                 XFontStruct 
**xfonts
; 
1058                 dc
.font
.ascent 
= dc
.font
.descent 
= 0; 
1059                 XExtentsOfFontSet(dc
.font
.set
); 
1060                 n 
= XFontsOfFontSet(dc
.font
.set
, &xfonts
, &font_names
); 
1062                         dc
.font
.ascent 
= MAX(dc
.font
.ascent
, (*xfonts
)->ascent
); 
1063                         dc
.font
.descent 
= MAX(dc
.font
.descent
,(*xfonts
)->descent
); 
1068                 if(!(dc
.font
.xfont 
= XLoadQueryFont(dpy
, fontstr
)) 
1069                 && !(dc
.font
.xfont 
= XLoadQueryFont(dpy
, "fixed"))) 
1070                         die("error, cannot load font: '%s'\n", fontstr
); 
1071                 dc
.font
.ascent 
= dc
.font
.xfont
->ascent
; 
1072                 dc
.font
.descent 
= dc
.font
.xfont
->descent
; 
1074         dc
.font
.height 
= dc
.font
.ascent 
+ dc
.font
.descent
; 
1079 isuniquegeom(XineramaScreenInfo 
*unique
, size_t n
, XineramaScreenInfo 
*info
) { 
1081                 if(unique
[n
].x_org 
== info
->x_org 
&& unique
[n
].y_org 
== info
->y_org
 
1082                 && unique
[n
].width 
== info
->width 
&& unique
[n
].height 
== info
->height
) 
1086 #endif /* XINERAMA */ 
1089 keypress(XEvent 
*e
) { 
1095         keysym 
= XKeycodeToKeysym(dpy
, (KeyCode
)ev
->keycode
, 0); 
1096         for(i 
= 0; i 
< LENGTH(keys
); i
++) 
1097                 if(keysym 
== keys
[i
].keysym
 
1098                 && CLEANMASK(keys
[i
].mod
) == CLEANMASK(ev
->state
) 
1100                         keys
[i
].func(&(keys
[i
].arg
)); 
1104 killclient(const Arg 
*arg
) { 
1107         if(!sendevent(selmon
->sel
, wmatom
[WMDelete
])) { 
1109                 XSetErrorHandler(xerrordummy
); 
1110                 XSetCloseDownMode(dpy
, DestroyAll
); 
1111                 XKillClient(dpy
, selmon
->sel
->win
); 
1113                 XSetErrorHandler(xerror
); 
1119 manage(Window w
, XWindowAttributes 
*wa
) { 
1120         Client 
*c
, *t 
= NULL
; 
1121         Window trans 
= None
; 
1124         if(!(c 
= calloc(1, sizeof(Client
)))) 
1125                 die("fatal: could not malloc() %u bytes\n", sizeof(Client
)); 
1128         if(XGetTransientForHint(dpy
, w
, &trans
) && (t 
= wintoclient(trans
))) { 
1137         c
->x 
= c
->oldx 
= wa
->x
; 
1138         c
->y 
= c
->oldy 
= wa
->y
; 
1139         c
->w 
= c
->oldw 
= wa
->width
; 
1140         c
->h 
= c
->oldh 
= wa
->height
; 
1141         c
->oldbw 
= wa
->border_width
; 
1143         if(c
->x 
+ WIDTH(c
) > c
->mon
->mx 
+ c
->mon
->mw
) 
1144                 c
->x 
= c
->mon
->mx 
+ c
->mon
->mw 
- WIDTH(c
); 
1145         if(c
->y 
+ HEIGHT(c
) > c
->mon
->my 
+ c
->mon
->mh
) 
1146                 c
->y 
= c
->mon
->my 
+ c
->mon
->mh 
- HEIGHT(c
); 
1147         c
->x 
= MAX(c
->x
, c
->mon
->mx
); 
1148         /* only fix client y-offset, if the client center might cover the bar */ 
1149         c
->y 
= MAX(c
->y
, ((c
->mon
->by 
== c
->mon
->my
) && (c
->x 
+ (c
->w 
/ 2) >= c
->mon
->wx
) 
1150                    && (c
->x 
+ (c
->w 
/ 2) < c
->mon
->wx 
+ c
->mon
->ww
)) ? bh 
: c
->mon
->my
); 
1153         wc
.border_width 
= c
->bw
; 
1154         XConfigureWindow(dpy
, w
, CWBorderWidth
, &wc
); 
1155         XSetWindowBorder(dpy
, w
, dc
.norm
[ColBorder
]); 
1156         configure(c
); /* propagates border_width, if size doesn't change */ 
1157         updatewindowtype(c
); 
1160         XSelectInput(dpy
, w
, EnterWindowMask
|FocusChangeMask
|PropertyChangeMask
|StructureNotifyMask
); 
1161         grabbuttons(c
, False
); 
1163                 c
->isfloating 
= c
->oldstate 
= trans 
!= None 
|| c
->isfixed
; 
1165                 XRaiseWindow(dpy
, c
->win
); 
1168         XChangeProperty(dpy
, root
, netatom
[NetClientList
], XA_WINDOW
, 32, PropModeAppend
, 
1169                         (unsigned char *) &(c
->win
), 1); 
1170         XMoveResizeWindow(dpy
, c
->win
, c
->x 
+ 2 * sw
, c
->y
, c
->w
, c
->h
); /* some windows require this */ 
1171         setclientstate(c
, NormalState
); 
1172         if (c
->mon 
== selmon
) 
1173                 unfocus(selmon
->sel
, False
); 
1176         XMapWindow(dpy
, c
->win
); 
1181 mappingnotify(XEvent 
*e
) { 
1182         XMappingEvent 
*ev 
= &e
->xmapping
; 
1184         XRefreshKeyboardMapping(ev
); 
1185         if(ev
->request 
== MappingKeyboard
) 
1190 maprequest(XEvent 
*e
) { 
1191         static XWindowAttributes wa
; 
1192         XMapRequestEvent 
*ev 
= &e
->xmaprequest
; 
1194         if(!XGetWindowAttributes(dpy
, ev
->window
, &wa
)) 
1196         if(wa
.override_redirect
) 
1198         if(!wintoclient(ev
->window
)) 
1199                 manage(ev
->window
, &wa
); 
1203 monocle(Monitor 
*m
) { 
1207         for(c 
= m
->clients
; c
; c 
= c
->next
) 
1210         if(n 
> 0) /* override layout symbol */ 
1211                 snprintf(m
->ltsymbol
, sizeof m
->ltsymbol
, "[%d]", n
); 
1212         for(c 
= nexttiled(m
->clients
); c
; c 
= nexttiled(c
->next
)) 
1213                 resize(c
, m
->wx
, m
->wy
, m
->ww 
- 2 * c
->bw
, m
->wh 
- 2 * c
->bw
, False
); 
1217 motionnotify(XEvent 
*e
) { 
1218         static Monitor 
*mon 
= NULL
; 
1220         XMotionEvent 
*ev 
= &e
->xmotion
; 
1222         if(ev
->window 
!= root
) 
1224         if((m 
= recttomon(ev
->x_root
, ev
->y_root
, 1, 1)) != mon 
&& mon
) { 
1225                 unfocus(selmon
->sel
, True
); 
1233 movemouse(const Arg 
*arg
) { 
1234         int x
, y
, ocx
, ocy
, nx
, ny
; 
1239         if(!(c 
= selmon
->sel
)) 
1241         if(c
->isfullscreen
) /* no support moving fullscreen windows by mouse */ 
1246         if(XGrabPointer(dpy
, root
, False
, MOUSEMASK
, GrabModeAsync
, GrabModeAsync
, 
1247         None
, cursor
[CurMove
], CurrentTime
) != GrabSuccess
) 
1249         if(!getrootptr(&x
, &y
)) 
1252                 XMaskEvent(dpy
, MOUSEMASK
|ExposureMask
|SubstructureRedirectMask
, &ev
); 
1254                 case ConfigureRequest
: 
1257                         handler
[ev
.type
](&ev
); 
1260                         nx 
= ocx 
+ (ev
.xmotion
.x 
- x
); 
1261                         ny 
= ocy 
+ (ev
.xmotion
.y 
- y
); 
1262                         if(nx 
>= selmon
->wx 
&& nx 
<= selmon
->wx 
+ selmon
->ww
 
1263                         && ny 
>= selmon
->wy 
&& ny 
<= selmon
->wy 
+ selmon
->wh
) { 
1264                                 if(abs(selmon
->wx 
- nx
) < snap
) 
1266                                 else if(abs((selmon
->wx 
+ selmon
->ww
) - (nx 
+ WIDTH(c
))) < snap
) 
1267                                         nx 
= selmon
->wx 
+ selmon
->ww 
- WIDTH(c
); 
1268                                 if(abs(selmon
->wy 
- ny
) < snap
) 
1270                                 else if(abs((selmon
->wy 
+ selmon
->wh
) - (ny 
+ HEIGHT(c
))) < snap
) 
1271                                         ny 
= selmon
->wy 
+ selmon
->wh 
- HEIGHT(c
); 
1272                                 if(!c
->isfloating 
&& selmon
->lt
[selmon
->sellt
]->arrange
 
1273                                 && (abs(nx 
- c
->x
) > snap 
|| abs(ny 
- c
->y
) > snap
)) 
1274                                         togglefloating(NULL
); 
1276                         if(!selmon
->lt
[selmon
->sellt
]->arrange 
|| c
->isfloating
) 
1277                                 resize(c
, nx
, ny
, c
->w
, c
->h
, True
); 
1280         } while(ev
.type 
!= ButtonRelease
); 
1281         XUngrabPointer(dpy
, CurrentTime
); 
1282         if((m 
= recttomon(c
->x
, c
->y
, c
->w
, c
->h
)) != selmon
) { 
1290 nexttiled(Client 
*c
) { 
1291         for(; c 
&& (c
->isfloating 
|| !ISVISIBLE(c
)); c 
= c
->next
); 
1304 propertynotify(XEvent 
*e
) { 
1307         XPropertyEvent 
*ev 
= &e
->xproperty
; 
1309         if((ev
->window 
== root
) && (ev
->atom 
== XA_WM_NAME
)) 
1311         else if(ev
->state 
== PropertyDelete
) 
1312                 return; /* ignore */ 
1313         else if((c 
= wintoclient(ev
->window
))) { 
1316                 case XA_WM_TRANSIENT_FOR
: 
1317                         if(!c
->isfloating 
&& (XGetTransientForHint(dpy
, c
->win
, &trans
)) && 
1318                            (c
->isfloating 
= (wintoclient(trans
)) != NULL
)) 
1321                 case XA_WM_NORMAL_HINTS
: 
1329                 if(ev
->atom 
== XA_WM_NAME 
|| ev
->atom 
== netatom
[NetWMName
]) { 
1331                         if(c 
== c
->mon
->sel
) 
1334                 if(ev
->atom 
== netatom
[NetWMWindowType
]) 
1335                         updatewindowtype(c
); 
1340 quit(const Arg 
*arg
) { 
1345 recttomon(int x
, int y
, int w
, int h
) { 
1346         Monitor 
*m
, *r 
= selmon
; 
1349         for(m 
= mons
; m
; m 
= m
->next
) 
1350                 if((a 
= INTERSECT(x
, y
, w
, h
, m
)) > area
) { 
1358 resize(Client 
*c
, int x
, int y
, int w
, int h
, Bool interact
) { 
1359         if(applysizehints(c
, &x
, &y
, &w
, &h
, interact
)) 
1360                 resizeclient(c
, x
, y
, w
, h
); 
1364 resizeclient(Client 
*c
, int x
, int y
, int w
, int h
) { 
1367         c
->oldx 
= c
->x
; c
->x 
= wc
.x 
= x
; 
1368         c
->oldy 
= c
->y
; c
->y 
= wc
.y 
= y
; 
1369         c
->oldw 
= c
->w
; c
->w 
= wc
.width 
= w
; 
1370         c
->oldh 
= c
->h
; c
->h 
= wc
.height 
= h
; 
1371         wc
.border_width 
= c
->bw
; 
1372         XConfigureWindow(dpy
, c
->win
, CWX
|CWY
|CWWidth
|CWHeight
|CWBorderWidth
, &wc
); 
1378 resizemouse(const Arg 
*arg
) { 
1385         if(!(c 
= selmon
->sel
)) 
1387         if(c
->isfullscreen
) /* no support resizing fullscreen windows by mouse */ 
1392         if(XGrabPointer(dpy
, root
, False
, MOUSEMASK
, GrabModeAsync
, GrabModeAsync
, 
1393                         None
, cursor
[CurResize
], CurrentTime
) != GrabSuccess
) 
1395         XWarpPointer(dpy
, None
, c
->win
, 0, 0, 0, 0, c
->w 
+ c
->bw 
- 1, c
->h 
+ c
->bw 
- 1); 
1397                 XMaskEvent(dpy
, MOUSEMASK
|ExposureMask
|SubstructureRedirectMask
, &ev
); 
1399                 case ConfigureRequest
: 
1402                         handler
[ev
.type
](&ev
); 
1405                         nw 
= MAX(ev
.xmotion
.x 
- ocx 
- 2 * c
->bw 
+ 1, 1); 
1406                         nh 
= MAX(ev
.xmotion
.y 
- ocy 
- 2 * c
->bw 
+ 1, 1); 
1407                         if(c
->mon
->wx 
+ nw 
>= selmon
->wx 
&& c
->mon
->wx 
+ nw 
<= selmon
->wx 
+ selmon
->ww
 
1408                         && c
->mon
->wy 
+ nh 
>= selmon
->wy 
&& c
->mon
->wy 
+ nh 
<= selmon
->wy 
+ selmon
->wh
) 
1410                                 if(!c
->isfloating 
&& selmon
->lt
[selmon
->sellt
]->arrange
 
1411                                 && (abs(nw 
- c
->w
) > snap 
|| abs(nh 
- c
->h
) > snap
)) 
1412                                         togglefloating(NULL
); 
1414                         if(!selmon
->lt
[selmon
->sellt
]->arrange 
|| c
->isfloating
) 
1415                                 resize(c
, c
->x
, c
->y
, nw
, nh
, True
); 
1418         } while(ev
.type 
!= ButtonRelease
); 
1419         XWarpPointer(dpy
, None
, c
->win
, 0, 0, 0, 0, c
->w 
+ c
->bw 
- 1, c
->h 
+ c
->bw 
- 1); 
1420         XUngrabPointer(dpy
, CurrentTime
); 
1421         while(XCheckMaskEvent(dpy
, EnterWindowMask
, &ev
)); 
1422         if((m 
= recttomon(c
->x
, c
->y
, c
->w
, c
->h
)) != selmon
) { 
1430 restack(Monitor 
*m
) { 
1438         if(m
->sel
->isfloating 
|| !m
->lt
[m
->sellt
]->arrange
) 
1439                 XRaiseWindow(dpy
, m
->sel
->win
); 
1440         if(m
->lt
[m
->sellt
]->arrange
) { 
1441                 wc
.stack_mode 
= Below
; 
1442                 wc
.sibling 
= m
->barwin
; 
1443                 for(c 
= m
->stack
; c
; c 
= c
->snext
) 
1444                         if(!c
->isfloating 
&& ISVISIBLE(c
)) { 
1445                                 XConfigureWindow(dpy
, c
->win
, CWSibling
|CWStackMode
, &wc
); 
1446                                 wc
.sibling 
= c
->win
; 
1450         while(XCheckMaskEvent(dpy
, EnterWindowMask
, &ev
)); 
1456         /* main event loop */ 
1458         while(running 
&& !XNextEvent(dpy
, &ev
)) 
1459                 if(handler
[ev
.type
]) 
1460                         handler
[ev
.type
](&ev
); /* call handler */ 
1465         unsigned int i
, num
; 
1466         Window d1
, d2
, *wins 
= NULL
; 
1467         XWindowAttributes wa
; 
1469         if(XQueryTree(dpy
, root
, &d1
, &d2
, &wins
, &num
)) { 
1470                 for(i 
= 0; i 
< num
; i
++) { 
1471                         if(!XGetWindowAttributes(dpy
, wins
[i
], &wa
) 
1472                         || wa
.override_redirect 
|| XGetTransientForHint(dpy
, wins
[i
], &d1
)) 
1474                         if(wa
.map_state 
== IsViewable 
|| getstate(wins
[i
]) == IconicState
) 
1475                                 manage(wins
[i
], &wa
); 
1477                 for(i 
= 0; i 
< num
; i
++) { /* now the transients */ 
1478                         if(!XGetWindowAttributes(dpy
, wins
[i
], &wa
)) 
1480                         if(XGetTransientForHint(dpy
, wins
[i
], &d1
) 
1481                         && (wa
.map_state 
== IsViewable 
|| getstate(wins
[i
]) == IconicState
)) 
1482                                 manage(wins
[i
], &wa
); 
1490 sendmon(Client 
*c
, Monitor 
*m
) { 
1497         c
->tags 
= m
->tagset
[m
->seltags
]; /* assign tags of target monitor */ 
1505 setclientstate(Client 
*c
, long state
) { 
1506         long data
[] = { state
, None 
}; 
1508         XChangeProperty(dpy
, c
->win
, wmatom
[WMState
], wmatom
[WMState
], 32, 
1509                         PropModeReplace
, (unsigned char *)data
, 2); 
1513 sendevent(Client 
*c
, Atom proto
) { 
1516         Bool exists 
= False
; 
1519         if(XGetWMProtocols(dpy
, c
->win
, &protocols
, &n
)) { 
1520                 while(!exists 
&& n
--) 
1521                         exists 
= protocols
[n
] == proto
; 
1525                 ev
.type 
= ClientMessage
; 
1526                 ev
.xclient
.window 
= c
->win
; 
1527                 ev
.xclient
.message_type 
= wmatom
[WMProtocols
]; 
1528                 ev
.xclient
.format 
= 32; 
1529                 ev
.xclient
.data
.l
[0] = proto
; 
1530                 ev
.xclient
.data
.l
[1] = CurrentTime
; 
1531                 XSendEvent(dpy
, c
->win
, False
, NoEventMask
, &ev
); 
1537 setfocus(Client 
*c
) { 
1538         if(!c
->neverfocus
) { 
1539                 XSetInputFocus(dpy
, c
->win
, RevertToPointerRoot
, CurrentTime
); 
1540                 XChangeProperty(dpy
, root
, netatom
[NetActiveWindow
], 
1541                                 XA_WINDOW
, 32, PropModeReplace
, 
1542                                 (unsigned char *) &(c
->win
), 1); 
1544         sendevent(c
, wmatom
[WMTakeFocus
]); 
1548 setfullscreen(Client 
*c
, Bool fullscreen
) { 
1550                 XChangeProperty(dpy
, c
->win
, netatom
[NetWMState
], XA_ATOM
, 32, 
1551                                 PropModeReplace
, (unsigned char*)&netatom
[NetWMFullscreen
], 1); 
1552                 c
->isfullscreen 
= True
; 
1553                 c
->oldstate 
= c
->isfloating
; 
1556                 c
->isfloating 
= True
; 
1557                 resizeclient(c
, c
->mon
->mx
, c
->mon
->my
, c
->mon
->mw
, c
->mon
->mh
); 
1558                 XRaiseWindow(dpy
, c
->win
); 
1561                 XChangeProperty(dpy
, c
->win
, netatom
[NetWMState
], XA_ATOM
, 32, 
1562                                 PropModeReplace
, (unsigned char*)0, 0); 
1563                 c
->isfullscreen 
= False
; 
1564                 c
->isfloating 
= c
->oldstate
; 
1570                 resizeclient(c
, c
->x
, c
->y
, c
->w
, c
->h
); 
1576 setlayout(const Arg 
*arg
) { 
1577         if(!arg 
|| !arg
->v 
|| arg
->v 
!= selmon
->lt
[selmon
->sellt
]) 
1580                 selmon
->lt
[selmon
->sellt
] = (Layout 
*)arg
->v
; 
1581         strncpy(selmon
->ltsymbol
, selmon
->lt
[selmon
->sellt
]->symbol
, sizeof selmon
->ltsymbol
); 
1588 /* arg > 1.0 will set mfact absolutly */ 
1590 setmfact(const Arg 
*arg
) { 
1593         if(!arg 
|| !selmon
->lt
[selmon
->sellt
]->arrange
) 
1595         f 
= arg
->f 
< 1.0 ? arg
->f 
+ selmon
->mfact 
: arg
->f 
- 1.0; 
1596         if(f 
< 0.1 || f 
> 0.9) 
1604         XSetWindowAttributes wa
; 
1606         /* clean up any zombies immediately */ 
1610         screen 
= DefaultScreen(dpy
); 
1611         root 
= RootWindow(dpy
, screen
); 
1613         sw 
= DisplayWidth(dpy
, screen
); 
1614         sh 
= DisplayHeight(dpy
, screen
); 
1615         bh 
= dc
.h 
= dc
.font
.height 
+ 2; 
1618         wmatom
[WMProtocols
] = XInternAtom(dpy
, "WM_PROTOCOLS", False
); 
1619         wmatom
[WMDelete
] = XInternAtom(dpy
, "WM_DELETE_WINDOW", False
); 
1620         wmatom
[WMState
] = XInternAtom(dpy
, "WM_STATE", False
); 
1621         wmatom
[WMTakeFocus
] = XInternAtom(dpy
, "WM_TAKE_FOCUS", False
); 
1622         netatom
[NetActiveWindow
] = XInternAtom(dpy
, "_NET_ACTIVE_WINDOW", False
); 
1623         netatom
[NetSupported
] = XInternAtom(dpy
, "_NET_SUPPORTED", False
); 
1624         netatom
[NetWMName
] = XInternAtom(dpy
, "_NET_WM_NAME", False
); 
1625         netatom
[NetWMState
] = XInternAtom(dpy
, "_NET_WM_STATE", False
); 
1626         netatom
[NetWMFullscreen
] = XInternAtom(dpy
, "_NET_WM_STATE_FULLSCREEN", False
); 
1627         netatom
[NetWMWindowType
] = XInternAtom(dpy
, "_NET_WM_WINDOW_TYPE", False
); 
1628         netatom
[NetWMWindowTypeDialog
] = XInternAtom(dpy
, "_NET_WM_WINDOW_TYPE_DIALOG", False
); 
1629         netatom
[NetClientList
] = XInternAtom(dpy
, "_NET_CLIENT_LIST", False
); 
1631         cursor
[CurNormal
] = XCreateFontCursor(dpy
, XC_left_ptr
); 
1632         cursor
[CurResize
] = XCreateFontCursor(dpy
, XC_sizing
); 
1633         cursor
[CurMove
] = XCreateFontCursor(dpy
, XC_fleur
); 
1634         /* init appearance */ 
1635         dc
.norm
[ColBorder
] = getcolor(normbordercolor
); 
1636         dc
.norm
[ColBG
] = getcolor(normbgcolor
); 
1637         dc
.norm
[ColFG
] = getcolor(normfgcolor
); 
1638         dc
.sel
[ColBorder
] = getcolor(selbordercolor
); 
1639         dc
.sel
[ColBG
] = getcolor(selbgcolor
); 
1640         dc
.sel
[ColFG
] = getcolor(selfgcolor
); 
1641         dc
.drawable 
= XCreatePixmap(dpy
, root
, DisplayWidth(dpy
, screen
), bh
, DefaultDepth(dpy
, screen
)); 
1642         dc
.gc 
= XCreateGC(dpy
, root
, 0, NULL
); 
1643         XSetLineAttributes(dpy
, dc
.gc
, 1, LineSolid
, CapButt
, JoinMiter
); 
1645                 XSetFont(dpy
, dc
.gc
, dc
.font
.xfont
->fid
); 
1649         /* EWMH support per view */ 
1650         XChangeProperty(dpy
, root
, netatom
[NetSupported
], XA_ATOM
, 32, 
1651                         PropModeReplace
, (unsigned char *) netatom
, NetLast
); 
1652         XDeleteProperty(dpy
, root
, netatom
[NetClientList
]); 
1653         /* select for events */ 
1654         wa
.cursor 
= cursor
[CurNormal
]; 
1655         wa
.event_mask 
= SubstructureRedirectMask
|SubstructureNotifyMask
|ButtonPressMask
|PointerMotionMask
 
1656                         |EnterWindowMask
|LeaveWindowMask
|StructureNotifyMask
|PropertyChangeMask
; 
1657         XChangeWindowAttributes(dpy
, root
, CWEventMask
|CWCursor
, &wa
); 
1658         XSelectInput(dpy
, root
, wa
.event_mask
); 
1663 showhide(Client 
*c
) { 
1666         if(ISVISIBLE(c
)) { /* show clients top down */ 
1667                 XMoveWindow(dpy
, c
->win
, c
->x
, c
->y
); 
1668                 if((!c
->mon
->lt
[c
->mon
->sellt
]->arrange 
|| c
->isfloating
) && !c
->isfullscreen
) 
1669                         resize(c
, c
->x
, c
->y
, c
->w
, c
->h
, False
); 
1672         else { /* hide clients bottom up */ 
1674                 XMoveWindow(dpy
, c
->win
, WIDTH(c
) * -2, c
->y
); 
1679 sigchld(int unused
) { 
1680         if(signal(SIGCHLD
, sigchld
) == SIG_ERR
) 
1681                 die("Can't install SIGCHLD handler"); 
1682         while(0 < waitpid(-1, NULL
, WNOHANG
)); 
1686 spawn(const Arg 
*arg
) { 
1689                         close(ConnectionNumber(dpy
)); 
1691                 execvp(((char **)arg
->v
)[0], (char **)arg
->v
); 
1692                 fprintf(stderr
, "dwm: execvp %s", ((char **)arg
->v
)[0]); 
1699 tag(const Arg 
*arg
) { 
1700         if(selmon
->sel 
&& arg
->ui 
& TAGMASK
) { 
1701                 selmon
->sel
->tags 
= arg
->ui 
& TAGMASK
; 
1708 tagmon(const Arg 
*arg
) { 
1709         if(!selmon
->sel 
|| !mons
->next
) 
1711         sendmon(selmon
->sel
, dirtomon(arg
->i
)); 
1715 textnw(const char *text
, unsigned int len
) { 
1719                 XmbTextExtents(dc
.font
.set
, text
, len
, NULL
, &r
); 
1722         return XTextWidth(dc
.font
.xfont
, text
, len
); 
1727         unsigned int i
, n
, h
, mw
, my
, ty
; 
1730         for(n 
= 0, c 
= nexttiled(m
->clients
); c
; c 
= nexttiled(c
->next
), n
++); 
1735                 mw 
= m
->nmaster 
? m
->ww 
* m
->mfact 
: 0; 
1738         for(i 
= my 
= ty 
= 0, c 
= nexttiled(m
->clients
); c
; c 
= nexttiled(c
->next
), i
++) 
1739                 if(i 
< m
->nmaster
) { 
1740                         h 
= (m
->wh 
- my
) / (MIN(n
, m
->nmaster
) - i
); 
1741                         resize(c
, m
->wx
, m
->wy 
+ my
, mw 
- (2*c
->bw
), h 
- (2*c
->bw
), False
); 
1745                         h 
= (m
->wh 
- ty
) / (n 
- i
); 
1746                         resize(c
, m
->wx 
+ mw
, m
->wy 
+ ty
, m
->ww 
- mw 
- (2*c
->bw
), h 
- (2*c
->bw
), False
); 
1752 togglebar(const Arg 
*arg
) { 
1753         selmon
->showbar 
= !selmon
->showbar
; 
1754         updatebarpos(selmon
); 
1755         XMoveResizeWindow(dpy
, selmon
->barwin
, selmon
->wx
, selmon
->by
, selmon
->ww
, bh
); 
1760 togglefloating(const Arg 
*arg
) { 
1763         if(selmon
->sel
->isfullscreen
) /* no support for fullscreen windows */ 
1765         selmon
->sel
->isfloating 
= !selmon
->sel
->isfloating 
|| selmon
->sel
->isfixed
; 
1766         if(selmon
->sel
->isfloating
) 
1767                 resize(selmon
->sel
, selmon
->sel
->x
, selmon
->sel
->y
, 
1768                        selmon
->sel
->w
, selmon
->sel
->h
, False
); 
1773 toggletag(const Arg 
*arg
) { 
1774         unsigned int newtags
; 
1778         newtags 
= selmon
->sel
->tags 
^ (arg
->ui 
& TAGMASK
); 
1780                 selmon
->sel
->tags 
= newtags
; 
1787 toggleview(const Arg 
*arg
) { 
1788         unsigned int newtagset 
= selmon
->tagset
[selmon
->seltags
] ^ (arg
->ui 
& TAGMASK
); 
1791                 selmon
->tagset
[selmon
->seltags
] = newtagset
; 
1798 unfocus(Client 
*c
, Bool setfocus
) { 
1801         grabbuttons(c
, False
); 
1802         XSetWindowBorder(dpy
, c
->win
, dc
.norm
[ColBorder
]); 
1804                 XSetInputFocus(dpy
, root
, RevertToPointerRoot
, CurrentTime
); 
1805                 XDeleteProperty(dpy
, root
, netatom
[NetActiveWindow
]); 
1810 unmanage(Client 
*c
, Bool destroyed
) { 
1811         Monitor 
*m 
= c
->mon
; 
1814         /* The server grab construct avoids race conditions. */ 
1818                 wc
.border_width 
= c
->oldbw
; 
1820                 XSetErrorHandler(xerrordummy
); 
1821                 XConfigureWindow(dpy
, c
->win
, CWBorderWidth
, &wc
); /* restore border */ 
1822                 XUngrabButton(dpy
, AnyButton
, AnyModifier
, c
->win
); 
1823                 setclientstate(c
, WithdrawnState
); 
1825                 XSetErrorHandler(xerror
); 
1835 unmapnotify(XEvent 
*e
) { 
1837         XUnmapEvent 
*ev 
= &e
->xunmap
; 
1839         if((c 
= wintoclient(ev
->window
))) { 
1841                         setclientstate(c
, WithdrawnState
); 
1850         XSetWindowAttributes wa 
= { 
1851                 .override_redirect 
= True
, 
1852                 .background_pixmap 
= ParentRelative
, 
1853                 .event_mask 
= ButtonPressMask
|ExposureMask
 
1855         for(m 
= mons
; m
; m 
= m
->next
) { 
1858                 m
->barwin 
= XCreateWindow(dpy
, root
, m
->wx
, m
->by
, m
->ww
, bh
, 0, DefaultDepth(dpy
, screen
), 
1859                                           CopyFromParent
, DefaultVisual(dpy
, screen
), 
1860                                           CWOverrideRedirect
|CWBackPixmap
|CWEventMask
, &wa
); 
1861                 XDefineCursor(dpy
, m
->barwin
, cursor
[CurNormal
]); 
1862                 XMapRaised(dpy
, m
->barwin
); 
1867 updatebarpos(Monitor 
*m
) { 
1872                 m
->by 
= m
->topbar 
? m
->wy 
: m
->wy 
+ m
->wh
; 
1873                 m
->wy 
= m
->topbar 
? m
->wy 
+ bh 
: m
->wy
; 
1880 updateclientlist() { 
1884         XDeleteProperty(dpy
, root
, netatom
[NetClientList
]); 
1885         for(m 
= mons
; m
; m 
= m
->next
) 
1886                 for(c 
= m
->clients
; c
; c 
= c
->next
) 
1887                         XChangeProperty(dpy
, root
, netatom
[NetClientList
], 
1888                                         XA_WINDOW
, 32, PropModeAppend
, 
1889                                         (unsigned char *) &(c
->win
), 1); 
1897         if(XineramaIsActive(dpy
)) { 
1901                 XineramaScreenInfo 
*info 
= XineramaQueryScreens(dpy
, &nn
); 
1902                 XineramaScreenInfo 
*unique 
= NULL
; 
1904                 for(n 
= 0, m 
= mons
; m
; m 
= m
->next
, n
++); 
1905                 /* only consider unique geometries as separate screens */ 
1906                 if(!(unique 
= (XineramaScreenInfo 
*)malloc(sizeof(XineramaScreenInfo
) * nn
))) 
1907                         die("fatal: could not malloc() %u bytes\n", sizeof(XineramaScreenInfo
) * nn
); 
1908                 for(i 
= 0, j 
= 0; i 
< nn
; i
++) 
1909                         if(isuniquegeom(unique
, j
, &info
[i
])) 
1910                                 memcpy(&unique
[j
++], &info
[i
], sizeof(XineramaScreenInfo
)); 
1914                         for(i 
= 0; i 
< (nn 
- n
); i
++) { /* new monitors available */ 
1915                                 for(m 
= mons
; m 
&& m
->next
; m 
= m
->next
); 
1917                                         m
->next 
= createmon(); 
1921                         for(i 
= 0, m 
= mons
; i 
< nn 
&& m
; m 
= m
->next
, i
++) 
1923                                 || (unique
[i
].x_org 
!= m
->mx 
|| unique
[i
].y_org 
!= m
->my
 
1924                                     || unique
[i
].width 
!= m
->mw 
|| unique
[i
].height 
!= m
->mh
)) 
1928                                         m
->mx 
= m
->wx 
= unique
[i
].x_org
; 
1929                                         m
->my 
= m
->wy 
= unique
[i
].y_org
; 
1930                                         m
->mw 
= m
->ww 
= unique
[i
].width
; 
1931                                         m
->mh 
= m
->wh 
= unique
[i
].height
; 
1935                 else { /* less monitors available nn < n */ 
1936                         for(i 
= nn
; i 
< n
; i
++) { 
1937                                 for(m 
= mons
; m 
&& m
->next
; m 
= m
->next
); 
1941                                         m
->clients 
= c
->next
; 
1955 #endif /* XINERAMA */ 
1956         /* default monitor setup */ 
1960                 if(mons
->mw 
!= sw 
|| mons
->mh 
!= sh
) { 
1962                         mons
->mw 
= mons
->ww 
= sw
; 
1963                         mons
->mh 
= mons
->wh 
= sh
; 
1969                 selmon 
= wintomon(root
); 
1975 updatenumlockmask(void) { 
1977         XModifierKeymap 
*modmap
; 
1980         modmap 
= XGetModifierMapping(dpy
); 
1981         for(i 
= 0; i 
< 8; i
++) 
1982                 for(j 
= 0; j 
< modmap
->max_keypermod
; j
++) 
1983                         if(modmap
->modifiermap
[i 
* modmap
->max_keypermod 
+ j
] 
1984                            == XKeysymToKeycode(dpy
, XK_Num_Lock
)) 
1985                                 numlockmask 
= (1 << i
); 
1986         XFreeModifiermap(modmap
); 
1990 updatesizehints(Client 
*c
) { 
1994         if(!XGetWMNormalHints(dpy
, c
->win
, &size
, &msize
)) 
1995                 /* size is uninitialized, ensure that size.flags aren't used */ 
1997         if(size
.flags 
& PBaseSize
) { 
1998                 c
->basew 
= size
.base_width
; 
1999                 c
->baseh 
= size
.base_height
; 
2001         else if(size
.flags 
& PMinSize
) { 
2002                 c
->basew 
= size
.min_width
; 
2003                 c
->baseh 
= size
.min_height
; 
2006                 c
->basew 
= c
->baseh 
= 0; 
2007         if(size
.flags 
& PResizeInc
) { 
2008                 c
->incw 
= size
.width_inc
; 
2009                 c
->inch 
= size
.height_inc
; 
2012                 c
->incw 
= c
->inch 
= 0; 
2013         if(size
.flags 
& PMaxSize
) { 
2014                 c
->maxw 
= size
.max_width
; 
2015                 c
->maxh 
= size
.max_height
; 
2018                 c
->maxw 
= c
->maxh 
= 0; 
2019         if(size
.flags 
& PMinSize
) { 
2020                 c
->minw 
= size
.min_width
; 
2021                 c
->minh 
= size
.min_height
; 
2023         else if(size
.flags 
& PBaseSize
) { 
2024                 c
->minw 
= size
.base_width
; 
2025                 c
->minh 
= size
.base_height
; 
2028                 c
->minw 
= c
->minh 
= 0; 
2029         if(size
.flags 
& PAspect
) { 
2030                 c
->mina 
= (float)size
.min_aspect
.y 
/ size
.min_aspect
.x
; 
2031                 c
->maxa 
= (float)size
.max_aspect
.x 
/ size
.max_aspect
.y
; 
2034                 c
->maxa 
= c
->mina 
= 0.0; 
2035         c
->isfixed 
= (c
->maxw 
&& c
->minw 
&& c
->maxh 
&& c
->minh
 
2036                      && c
->maxw 
== c
->minw 
&& c
->maxh 
== c
->minh
); 
2040 updatetitle(Client 
*c
) { 
2041         if(!gettextprop(c
->win
, netatom
[NetWMName
], c
->name
, sizeof c
->name
)) 
2042                 gettextprop(c
->win
, XA_WM_NAME
, c
->name
, sizeof c
->name
); 
2043         if(c
->name
[0] == '\0') /* hack to mark broken clients */ 
2044                 strcpy(c
->name
, broken
); 
2048 updatestatus(void) { 
2049         if(!gettextprop(root
, XA_WM_NAME
, stext
, sizeof(stext
))) 
2050                 strcpy(stext
, "dwm-"VERSION
); 
2055 updatewindowtype(Client 
*c
) { 
2056         Atom state 
= getatomprop(c
, netatom
[NetWMState
]); 
2057         Atom wtype 
= getatomprop(c
, netatom
[NetWMWindowType
]); 
2059         if(state 
== netatom
[NetWMFullscreen
]) 
2060                 setfullscreen(c
, True
); 
2061         if(wtype 
== netatom
[NetWMWindowTypeDialog
]) 
2062                 c
->isfloating 
= True
; 
2066 updatewmhints(Client 
*c
) { 
2069         if((wmh 
= XGetWMHints(dpy
, c
->win
))) { 
2070                 if(c 
== selmon
->sel 
&& wmh
->flags 
& XUrgencyHint
) { 
2071                         wmh
->flags 
&= ~XUrgencyHint
; 
2072                         XSetWMHints(dpy
, c
->win
, wmh
); 
2075                         c
->isurgent 
= (wmh
->flags 
& XUrgencyHint
) ? True 
: False
; 
2076                 if(wmh
->flags 
& InputHint
) 
2077                         c
->neverfocus 
= !wmh
->input
; 
2079                         c
->neverfocus 
= False
; 
2085 view(const Arg 
*arg
) { 
2086         if((arg
->ui 
& TAGMASK
) == selmon
->tagset
[selmon
->seltags
]) 
2088         selmon
->seltags 
^= 1; /* toggle sel tagset */ 
2089         if(arg
->ui 
& TAGMASK
) 
2090                 selmon
->tagset
[selmon
->seltags
] = arg
->ui 
& TAGMASK
; 
2096 wintoclient(Window w
) { 
2100         for(m 
= mons
; m
; m 
= m
->next
) 
2101                 for(c 
= m
->clients
; c
; c 
= c
->next
) 
2108 wintomon(Window w
) { 
2113         if(w 
== root 
&& getrootptr(&x
, &y
)) 
2114                 return recttomon(x
, y
, 1, 1); 
2115         for(m 
= mons
; m
; m 
= m
->next
) 
2118         if((c 
= wintoclient(w
))) 
2123 /* There's no way to check accesses to destroyed windows, thus those cases are 
2124  * ignored (especially on UnmapNotify's).  Other types of errors call Xlibs 
2125  * default error handler, which may call exit.  */ 
2127 xerror(Display 
*dpy
, XErrorEvent 
*ee
) { 
2128         if(ee
->error_code 
== BadWindow
 
2129         || (ee
->request_code 
== X_SetInputFocus 
&& ee
->error_code 
== BadMatch
) 
2130         || (ee
->request_code 
== X_PolyText8 
&& ee
->error_code 
== BadDrawable
) 
2131         || (ee
->request_code 
== X_PolyFillRectangle 
&& ee
->error_code 
== BadDrawable
) 
2132         || (ee
->request_code 
== X_PolySegment 
&& ee
->error_code 
== BadDrawable
) 
2133         || (ee
->request_code 
== X_ConfigureWindow 
&& ee
->error_code 
== BadMatch
) 
2134         || (ee
->request_code 
== X_GrabButton 
&& ee
->error_code 
== BadAccess
) 
2135         || (ee
->request_code 
== X_GrabKey 
&& ee
->error_code 
== BadAccess
) 
2136         || (ee
->request_code 
== X_CopyArea 
&& ee
->error_code 
== BadDrawable
)) 
2138         fprintf(stderr
, "dwm: fatal error: request code=%d, error code=%d\n", 
2139                         ee
->request_code
, ee
->error_code
); 
2140         return xerrorxlib(dpy
, ee
); /* may call exit */ 
2144 xerrordummy(Display 
*dpy
, XErrorEvent 
*ee
) { 
2148 /* Startup Error handler to check if another window manager 
2149  * is already running. */ 
2151 xerrorstart(Display 
*dpy
, XErrorEvent 
*ee
) { 
2152         die("dwm: another window manager is already running\n"); 
2157 zoom(const Arg 
*arg
) { 
2158         Client 
*c 
= selmon
->sel
; 
2160         if(!selmon
->lt
[selmon
->sellt
]->arrange
 
2161         || (selmon
->sel 
&& selmon
->sel
->isfloating
)) 
2163         if(c 
== nexttiled(selmon
->clients
)) 
2164                 if(!c 
|| !(c 
= nexttiled(c
->next
))) 
2170 main(int argc
, char *argv
[]) { 
2171         if(argc 
== 2 && !strcmp("-v", argv
[1])) 
2172                 die("dwm-"VERSION
", © 2006-2012 dwm engineers, see LICENSE for details\n"); 
2174                 die("usage: dwm [-v]\n"); 
2175         if(!setlocale(LC_CTYPE
, "") || !XSupportsLocale()) 
2176                 fputs("warning: no locale support\n", stderr
); 
2177         if(!(dpy 
= XOpenDisplay(NULL
))) 
2178                 die("dwm: cannot open display\n"); 
2185         return EXIT_SUCCESS
;