dwm

Kris's build of dwm
git clone git clone https://git.krisyotam.com/krisyotam/dwm.git
Log | Files | Refs | README | LICENSE

dwm.c (149408B)


      1 /* See LICENSE file for copyright and license details.
      2  *
      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.
      8  *
      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
     11  * in O(1) time.
     12  *
     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
     17  * client.
     18  *
     19  * Keys and tagging rules are organized as arrays and defined in config.h.
     20  *
     21  * To understand everything else, start reading main().
     22  */
     23 #include <errno.h>
     24 #include <locale.h>
     25 #include <signal.h>
     26 #include <stdarg.h>
     27 #include <stdio.h>
     28 #include <stdlib.h>
     29 #include <string.h>
     30 #include <unistd.h>
     31 #include <sys/types.h>
     32 #include <sys/wait.h>
     33 #include <X11/cursorfont.h>
     34 #include <X11/keysym.h>
     35 #include <X11/Xatom.h>
     36 #include <X11/Xlib.h>
     37 #include <X11/Xproto.h>
     38 #include <X11/Xutil.h>
     39 #ifdef XINERAMA
     40 #include <X11/extensions/Xinerama.h>
     41 #endif /* XINERAMA */
     42 #include <X11/Xft/Xft.h>
     43 
     44 #include "patches.h"
     45 #include "drw.h"
     46 #include "util.h"
     47 
     48 #if BAR_FLEXWINTITLE_PATCH
     49 #ifndef FLEXTILE_DELUXE_LAYOUT
     50 #define FLEXTILE_DELUXE_LAYOUT 1
     51 #endif
     52 #endif
     53 
     54 #if BAR_PANGO_PATCH
     55 #include <pango/pango.h>
     56 #endif // BAR_PANGO_PATCH
     57 
     58 #if RESTARTSIG_PATCH
     59 #include <poll.h>
     60 #endif // RESTARTSIG_PATCH
     61 
     62 #if XKB_PATCH
     63 #include <X11/XKBlib.h>
     64 #endif // XKB_PATCH
     65 
     66 #if SPAWNCMD_PATCH
     67 #include <assert.h>
     68 #include <libgen.h>
     69 #include <sys/stat.h>
     70 #define SPAWN_CWD_DELIM " []{}()<>\"':"
     71 #endif // SPAWNCMD_PATCH
     72 
     73 /* macros */
     74 #define Button6                 6
     75 #define Button7                 7
     76 #define Button8                 8
     77 #define Button9                 9
     78 #define NUMTAGS                 9
     79 #define NUMVIEWHIST             NUMTAGS
     80 #define BARRULES                20
     81 #if TAB_PATCH
     82 #define MAXTABS                 50
     83 #endif // TAB_PATCH
     84 #define BUTTONMASK              (ButtonPressMask|ButtonReleaseMask)
     85 #define CLEANMASK(mask)         (mask & ~(numlockmask|LockMask) & (ShiftMask|ControlMask|Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask))
     86 #if BAR_ANYBAR_PATCH
     87 #define INTERSECT(x,y,w,h,m)    (MAX(0, MIN((x)+(w),(m)->mx+(m)->mw) - MAX((x),(m)->mx)) \
     88                                * MAX(0, MIN((y)+(h),(m)->my+(m)->mh) - MAX((y),(m)->my)))
     89 #else
     90 #define INTERSECT(x,y,w,h,m)    (MAX(0, MIN((x)+(w),(m)->wx+(m)->ww) - MAX((x),(m)->wx)) \
     91                                * MAX(0, MIN((y)+(h),(m)->wy+(m)->wh) - MAX((y),(m)->wy)))
     92 #endif // BAR_ANYBAR_PATCH
     93 #if ATTACHASIDE_PATCH && STICKY_PATCH
     94 #define ISVISIBLEONTAG(C, T)    ((C->tags & T) || C->issticky)
     95 #define ISVISIBLE(C)            ISVISIBLEONTAG(C, C->mon->tagset[C->mon->seltags])
     96 #elif ATTACHASIDE_PATCH
     97 #define ISVISIBLEONTAG(C, T)    ((C->tags & T))
     98 #define ISVISIBLE(C)            ISVISIBLEONTAG(C, C->mon->tagset[C->mon->seltags])
     99 #elif STICKY_PATCH
    100 #define ISVISIBLE(C)            ((C->tags & C->mon->tagset[C->mon->seltags]) || C->issticky)
    101 #else
    102 #define ISVISIBLE(C)            ((C->tags & C->mon->tagset[C->mon->seltags]))
    103 #endif // ATTACHASIDE_PATCH
    104 #define MOUSEMASK               (BUTTONMASK|PointerMotionMask)
    105 #define WIDTH(X)                ((X)->w + 2 * (X)->bw)
    106 #define HEIGHT(X)               ((X)->h + 2 * (X)->bw)
    107 #define WTYPE                   "_NET_WM_WINDOW_TYPE_"
    108 #if SCRATCHPADS_PATCH && !RENAMED_SCRATCHPADS_PATCH
    109 #define TOTALTAGS               (NUMTAGS + LENGTH(scratchpads))
    110 #define TAGMASK                 ((1 << TOTALTAGS) - 1)
    111 #define SPTAG(i)                ((1 << NUMTAGS) << (i))
    112 #define SPTAGMASK               (((1 << LENGTH(scratchpads))-1) << NUMTAGS)
    113 #else
    114 #define TAGMASK                 ((1 << NUMTAGS) - 1)
    115 #endif // SCRATCHPADS_PATCH
    116 #define TEXTWM(X)               (drw_fontset_getwidth(drw, (X), True) + lrpad)
    117 #define TEXTW(X)                (drw_fontset_getwidth(drw, (X), False) + lrpad)
    118 #define HIDDEN(C)               ((getstate(C->win) == IconicState))
    119 
    120 /* enums */
    121 enum {
    122 	#if RESIZEPOINT_PATCH || RESIZECORNERS_PATCH
    123 	CurResizeBR,
    124 	CurResizeBL,
    125 	CurResizeTR,
    126 	CurResizeTL,
    127 	#endif // RESIZEPOINT_PATCH | RESIZECORNERS_PATCH
    128 	#if DRAGMFACT_PATCH
    129 	CurResizeHorzArrow,
    130 	CurResizeVertArrow,
    131 	#endif // DRAGMFACT_PATCH
    132 	#if DRAGCFACT_PATCH
    133 	CurIronCross,
    134 	#endif // DRAGCFACT_PATCH
    135 	CurNormal,
    136 	CurResize,
    137 	CurMove,
    138 	CurLast
    139 }; /* cursor */
    140 
    141 enum {
    142 	SchemeNorm,
    143 	SchemeSel,
    144 	SchemeTitleNorm,
    145 	SchemeTitleSel,
    146 	SchemeTagsNorm,
    147 	SchemeTagsSel,
    148 	SchemeHidNorm,
    149 	SchemeHidSel,
    150 	SchemeUrg,
    151 	#if BAR_LTSYMBOL_SCHEME_PATCH
    152 	SchemeLtSymbol,
    153 	#endif // BAR_LTSYMBOL_SCHEME_PATCH
    154 	#if RENAMED_SCRATCHPADS_PATCH
    155 	SchemeScratchSel,
    156 	SchemeScratchNorm,
    157 	#endif // RENAMED_SCRATCHPADS_PATCH
    158 	#if BAR_FLEXWINTITLE_PATCH
    159 	SchemeFlexActTTB,
    160 	SchemeFlexActLTR,
    161 	SchemeFlexActMONO,
    162 	SchemeFlexActGRID,
    163 	SchemeFlexActGRD1,
    164 	SchemeFlexActGRD2,
    165 	SchemeFlexActGRDM,
    166 	SchemeFlexActHGRD,
    167 	SchemeFlexActDWDL,
    168 	SchemeFlexActSPRL,
    169 	SchemeFlexInaTTB,
    170 	SchemeFlexInaLTR,
    171 	SchemeFlexInaMONO,
    172 	SchemeFlexInaGRID,
    173 	SchemeFlexInaGRD1,
    174 	SchemeFlexInaGRD2,
    175 	SchemeFlexInaGRDM,
    176 	SchemeFlexInaHGRD,
    177 	SchemeFlexInaDWDL,
    178 	SchemeFlexInaSPRL,
    179 	SchemeFlexSelTTB,
    180 	SchemeFlexSelLTR,
    181 	SchemeFlexSelMONO,
    182 	SchemeFlexSelGRID,
    183 	SchemeFlexSelGRD1,
    184 	SchemeFlexSelGRD2,
    185 	SchemeFlexSelGRDM,
    186 	SchemeFlexSelHGRD,
    187 	SchemeFlexSelDWDL,
    188 	SchemeFlexSelSPRL,
    189 	SchemeFlexActFloat,
    190 	SchemeFlexInaFloat,
    191 	SchemeFlexSelFloat,
    192 	#endif // BAR_FLEXWINTITLE_PATCH
    193 }; /* color schemes */
    194 
    195 enum {
    196 	NetSupported, NetWMName, NetWMState, NetWMCheck,
    197 	NetWMFullscreen, NetActiveWindow, NetWMWindowType,
    198 	#if BAR_WINICON_PATCH
    199 	NetWMIcon,
    200 	#endif // BAR_WINICON_PATCH
    201 	#if BAR_SYSTRAY_PATCH
    202 	NetSystemTray, NetSystemTrayOP, NetSystemTrayOrientation,
    203 	NetSystemTrayVisual, NetWMWindowTypeDock, NetSystemTrayOrientationHorz,
    204 	#endif // BAR_SYSTRAY_PATCH
    205 	#if BAR_EWMHTAGS_PATCH
    206 	NetDesktopNames, NetDesktopViewport, NetNumberOfDesktops, NetCurrentDesktop,
    207 	#endif // BAR_EWMHTAGS_PATCH
    208 	NetClientList,
    209 	#if NET_CLIENT_LIST_STACKING_PATCH
    210 	NetClientListStacking,
    211 	#endif // NET_CLIENT_LIST_STACKING_PATCH
    212 	NetLast
    213 }; /* EWMH atoms */
    214 
    215 enum {
    216 	WMProtocols,
    217 	WMDelete,
    218 	WMState,
    219 	WMTakeFocus,
    220 	#if WINDOWROLERULE_PATCH
    221 	WMWindowRole,
    222 	#endif // WINDOWROLERULE_PATCH
    223 	WMLast
    224 }; /* default atoms */
    225 
    226 #if SEAMLESS_RESTART_PATCH
    227 enum {
    228 	ClientFields,
    229 	ClientTags,
    230 	ClientLast
    231 }; /* dwm client atoms */
    232 #endif // SEAMLESS_RESTART_PATCH
    233 
    234 enum {
    235 	#if BAR_STATUSBUTTON_PATCH
    236 	ClkButton,
    237 	#endif // BAR_STATUSBUTTON_PATCH
    238 	#if TAB_PATCH
    239 	ClkTabBar,
    240 	#endif // TAB_PATCH
    241 	ClkTagBar,
    242 	ClkLtSymbol,
    243 	ClkStatusText,
    244 	ClkWinTitle,
    245 	ClkClientWin,
    246 	ClkRootWin,
    247 	#if XKB_PATCH
    248 	ClkXKB,
    249 	#endif // XKB_PATCH
    250 	ClkLast
    251 }; /* clicks */
    252 
    253 enum {
    254 	BAR_ALIGN_LEFT,
    255 	BAR_ALIGN_CENTER,
    256 	BAR_ALIGN_RIGHT,
    257 	BAR_ALIGN_LEFT_LEFT,
    258 	BAR_ALIGN_LEFT_RIGHT,
    259 	BAR_ALIGN_LEFT_CENTER,
    260 	BAR_ALIGN_NONE,
    261 	BAR_ALIGN_RIGHT_LEFT,
    262 	BAR_ALIGN_RIGHT_RIGHT,
    263 	BAR_ALIGN_RIGHT_CENTER,
    264 	BAR_ALIGN_LAST
    265 }; /* bar alignment */
    266 
    267 #if IPC_PATCH
    268 typedef struct TagState TagState;
    269 struct TagState {
    270        int selected;
    271        int occupied;
    272        int urgent;
    273 };
    274 
    275 typedef struct ClientState ClientState;
    276 struct ClientState {
    277        int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen;
    278 };
    279 #endif // IPC_PATCH
    280 
    281 typedef union {
    282 	#if IPC_PATCH
    283 	long i;
    284 	unsigned long ui;
    285 	#else
    286 	int i;
    287 	unsigned int ui;
    288 	#endif // IPC_PATCH
    289 	float f;
    290 	const void *v;
    291 } Arg;
    292 
    293 typedef struct Monitor Monitor;
    294 typedef struct Bar Bar;
    295 struct Bar {
    296 	Window win;
    297 	Monitor *mon;
    298 	Bar *next;
    299 	int idx;
    300 	int showbar;
    301 	int topbar;
    302 	int external;
    303 	int borderpx;
    304 	int borderscheme;
    305 	int bx, by, bw, bh; /* bar geometry */
    306 	int w[BARRULES]; // width, array length == barrules, then use r index for lookup purposes
    307 	int x[BARRULES]; // x position, array length == ^
    308 };
    309 
    310 typedef struct {
    311 	int x;
    312 	int y;
    313 	int h;
    314 	int w;
    315 } BarArg;
    316 
    317 typedef struct {
    318 	int monitor;
    319 	int bar;
    320 	int alignment; // see bar alignment enum
    321 	int (*widthfunc)(Bar *bar, BarArg *a);
    322 	int (*drawfunc)(Bar *bar, BarArg *a);
    323 	int (*clickfunc)(Bar *bar, Arg *arg, BarArg *a);
    324 	int (*hoverfunc)(Bar *bar, BarArg *a, XMotionEvent *ev);
    325 	char *name; // for debugging
    326 	int x, w; // position, width for internal use
    327 } BarRule;
    328 
    329 typedef struct {
    330 	unsigned int click;
    331 	unsigned int mask;
    332 	unsigned int button;
    333 	void (*func)(const Arg *arg);
    334 	const Arg arg;
    335 } Button;
    336 
    337 #if XKB_PATCH
    338 typedef struct XkbInfo XkbInfo;
    339 struct XkbInfo {
    340 	XkbInfo *next;
    341 	XkbInfo *prev;
    342 	int group;
    343 	Window w;
    344 };
    345 #endif // XKB_PATCH
    346 
    347 typedef struct Client Client;
    348 struct Client {
    349 	char name[256];
    350 	float mina, maxa;
    351 	#if CFACTS_PATCH
    352 	float cfact;
    353 	#endif // CFACTS_PATCH
    354 	int x, y, w, h;
    355 	#if SAVEFLOATS_PATCH || EXRESIZE_PATCH
    356 	int sfx, sfy, sfw, sfh; /* stored float geometry, used on mode revert */
    357 	#endif // SAVEFLOATS_PATCH / EXRESIZE_PATCH
    358 	#if SEAMLESS_RESTART_PATCH
    359 	unsigned int idx;
    360 	#endif // SEAMLESS_RESTART_PATCH
    361 	int oldx, oldy, oldw, oldh;
    362 	int basew, baseh, incw, inch, maxw, maxh, minw, minh, hintsvalid;
    363 	int bw, oldbw;
    364 	unsigned int tags;
    365 	#if SWITCHTAG_PATCH
    366 	unsigned int switchtag;
    367 	#endif // SWITCHTAG_PATCH
    368 	int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen;
    369 	#if ALWAYSONTOP_PATCH
    370 	int alwaysontop;
    371 	#endif // ALWAYSONTOP_PATCH
    372 	#if !FAKEFULLSCREEN_PATCH && FAKEFULLSCREEN_CLIENT_PATCH
    373 	int fakefullscreen;
    374 	#endif // FAKEFULLSCREEN_CLIENT_PATCH
    375 	#if GAMES_PATCH
    376 	int isgame;
    377 	#endif // GAMES_PATCH
    378 	#if EXRESIZE_PATCH
    379 	unsigned char expandmask;
    380 	int expandx1, expandy1, expandx2, expandy2;
    381 	#if !MAXIMIZE_PATCH
    382 	int wasfloating;
    383 	#endif // MAXIMIZE_PATCH
    384 	#endif // EXRESIZE_PATCH
    385 	#if MAXIMIZE_PATCH
    386 	int ismax, wasfloating;
    387 	#endif // MAXIMIZE_PATCH
    388 	#if AUTORESIZE_PATCH
    389 	int needresize;
    390 	#endif // AUTORESIZE_PATCH
    391 	#if CENTER_PATCH
    392 	int iscentered;
    393 	#endif // CENTER_PATCH
    394 	#if ISPERMANENT_PATCH
    395 	int ispermanent;
    396 	#endif // ISPERMANENT_PATCH
    397 	#if PLACEMOUSE_PATCH
    398 	int beingmoved;
    399 	#endif // PLACEMOUSE_PATCH
    400 	#if SIZEHINTS_ISFREESIZE_PATCH
    401 	int isfreesize;
    402 	#endif // SIZEHINTS_ISFREESIZE_PATCH
    403 	#if SWALLOW_PATCH
    404 	int isterminal, noswallow;
    405 	pid_t pid;
    406 	#endif // SWALLOW_PATCH
    407 	#if STEAM_PATCH
    408 	int issteam;
    409 	#endif // STEAM_PATCH
    410 	#if STICKY_PATCH
    411 	int issticky;
    412 	#endif // STICKY_PATCH
    413 	Client *next;
    414 	Client *snext;
    415 	#if SWALLOW_PATCH
    416 	Client *swallowing;
    417 	#endif // SWALLOW_PATCH
    418 	Monitor *mon;
    419 	Window win;
    420 	#if IPC_PATCH
    421 	ClientState prevstate;
    422 	#endif // IPC_PATCH
    423 	#if RENAMED_SCRATCHPADS_PATCH
    424 	char scratchkey;
    425 	#endif // RENAMED_SCRATCHPADS_PATCH
    426 	#if XKB_PATCH
    427 	XkbInfo *xkb;
    428 	#endif // XKB_PATCH
    429 	#if BAR_WINICON_PATCH
    430 	unsigned int icw, ich;
    431 	Picture icon;
    432 	#endif // BAR_WINICON_PATCH
    433 };
    434 
    435 typedef struct {
    436 	unsigned int mod;
    437 	KeySym keysym;
    438 	void (*func)(const Arg *);
    439 	const Arg arg;
    440 } Key;
    441 
    442 #if FLEXTILE_DELUXE_LAYOUT
    443 typedef struct {
    444 	int nmaster;
    445 	int nstack;
    446 	int layout;
    447 	int masteraxis; // master stack area
    448 	int stack1axis; // primary stack area
    449 	int stack2axis; // secondary stack area, e.g. centered master
    450 	void (*symbolfunc)(Monitor *, unsigned int);
    451 } LayoutPreset;
    452 #endif // FLEXTILE_DELUXE_LAYOUT
    453 
    454 typedef struct {
    455 	const char *symbol;
    456 	void (*arrange)(Monitor *);
    457 	#if FLEXTILE_DELUXE_LAYOUT
    458 	LayoutPreset preset;
    459 	#endif // FLEXTILE_DELUXE_LAYOUT
    460 } Layout;
    461 
    462 #if INSETS_PATCH
    463 typedef struct {
    464 	int x;
    465 	int y;
    466 	int w;
    467 	int h;
    468 } Inset;
    469 #endif // INSETS_PATCH
    470 
    471 #if PERTAG_PATCH
    472 typedef struct Pertag Pertag;
    473 #endif // PERTAG_PATCH
    474 struct Monitor {
    475 	char ltsymbol[16];
    476 	float mfact;
    477 	#if FLEXTILE_DELUXE_LAYOUT
    478 	int ltaxis[4];
    479 	int nstack;
    480 	#endif // FLEXTILE_DELUXE_LAYOUT
    481 	int nmaster;
    482 	int num;
    483 	int mx, my, mw, mh;   /* screen size */
    484 	int wx, wy, ww, wh;   /* window area  */
    485 	#if TAB_PATCH
    486 	int ty;               /* tab bar geometry */
    487 	#endif // TAB_PATCH
    488 	#if VANITYGAPS_PATCH
    489 	int gappih;           /* horizontal gap between windows */
    490 	int gappiv;           /* vertical gap between windows */
    491 	int gappoh;           /* horizontal outer gaps */
    492 	int gappov;           /* vertical outer gaps */
    493 	#if PERMON_VANITYGAPS_PATCH
    494 	int enablegaps;       /* whether gaps are enabled  */
    495 	#endif // PERMON_VANITYGAPS_PATCH
    496 	#endif // VANITYGAPS_PATCH
    497 	#if SETBORDERPX_PATCH
    498 	int borderpx;
    499 	#endif // SETBORDERPX_PATCH
    500 	unsigned int seltags;
    501 	unsigned int sellt;
    502 	#if VIEW_HISTORY_PATCH
    503 	unsigned int tagset[NUMVIEWHIST];
    504 	#else
    505 	unsigned int tagset[2];
    506 	#endif // VIEW_HISTORY_PATCH
    507 	int showbar;
    508 	#if TAB_PATCH
    509 	int showtab;
    510 	int toptab;
    511 	Window tabwin;
    512 	int ntabs;
    513 	int tab_widths[MAXTABS];
    514 	#endif // TAB_PATCH
    515 	Client *clients;
    516 	Client *sel;
    517 	Client *stack;
    518 	#if FOCUSMASTER_RETURN_PATCH
    519 	Client *tagmarked[32];
    520 	#endif // FOCUSMASTER_RETURN_PATCH
    521 	Monitor *next;
    522 	Bar *bar;
    523 	const Layout *lt[2];
    524 	#if BAR_ALTERNATIVE_TAGS_PATCH
    525 	unsigned int alttag;
    526 	#endif // BAR_ALTERNATIVE_TAGS_PATCH
    527 	#if PERTAG_PATCH
    528 	Pertag *pertag;
    529 	#endif // PERTAG_PATCH
    530 	#if INSETS_PATCH
    531 	Inset inset;
    532 	#endif // INSETS_PATCH
    533 	#if BAR_TAGLABELS_PATCH
    534 	char taglabel[NUMTAGS][64];
    535 	#endif // BAR_TAGLABELS_PATCH
    536 	#if IPC_PATCH
    537 	char lastltsymbol[16];
    538 	TagState tagstate;
    539 	Client *lastsel;
    540 	const Layout *lastlt;
    541 	#endif // IPC_PATCH
    542 	#if BAR_TAGPREVIEW_PATCH
    543 	Window tagwin;
    544 	int previewshow;
    545 	Pixmap tagmap[NUMTAGS];
    546 	#endif // BAR_TAGPREVIEW_PATCH
    547 };
    548 
    549 typedef struct {
    550 	const char *class;
    551 	#if WINDOWROLERULE_PATCH
    552 	const char *role;
    553 	#endif // WINDOWROLERULE_PATCH
    554 	const char *instance;
    555 	const char *title;
    556 	const char *wintype;
    557 	unsigned int tags;
    558 	#if SWITCHTAG_PATCH
    559 	int switchtag;
    560 	#endif // SWITCHTAG_PATCH
    561 	#if CENTER_PATCH
    562 	int iscentered;
    563 	#endif // CENTER_PATCH
    564 	int isfloating;
    565 	#if SELECTIVEFAKEFULLSCREEN_PATCH && FAKEFULLSCREEN_CLIENT_PATCH && !FAKEFULLSCREEN_PATCH
    566 	int isfakefullscreen;
    567 	#endif // SELECTIVEFAKEFULLSCREEN_PATCH
    568 	#if SIZEHINTS_ISFREESIZE_PATCH
    569 	int isfreesize;
    570 	#endif // SIZEHINTS_ISFREESIZE_PATCH
    571 	#if ISPERMANENT_PATCH
    572 	int ispermanent;
    573 	#endif // ISPERMANENT_PATCH
    574 	#if SWALLOW_PATCH
    575 	int isterminal;
    576 	int noswallow;
    577 	#endif // SWALLOW_PATCH
    578 	#if FLOATPOS_PATCH
    579 	const char *floatpos;
    580 	#endif // FLOATPOS_PATCH
    581 	int monitor;
    582 	#if RENAMED_SCRATCHPADS_PATCH
    583 	const char scratchkey;
    584 	#endif // RENAMED_SCRATCHPADS_PATCH
    585 	#if UNMANAGED_PATCH
    586 	int unmanaged;
    587 	#endif // UNMANAGED_PATCH
    588 	#if XKB_PATCH
    589 	int xkb_layout;
    590 	#endif // XKB_PATCH
    591 	#if BORDER_RULE_PATCH
    592 	int bw;
    593 	#endif // BORDER_RULE_PATCH
    594 	#if GAMES_PATCH
    595 	int isgame;
    596 	#endif // GAMES_PATCH
    597 } Rule;
    598 
    599 #if BORDER_RULE_PATCH && XKB_PATCH
    600 #define RULE(...) { .monitor = -1, .xkb_layout = -1, .bw = -1, __VA_ARGS__ },
    601 #elif XKB_PATCH
    602 #define RULE(...) { .monitor = -1, .xkb_layout = -1, __VA_ARGS__ },
    603 #elif BORDER_RULE_PATCH
    604 #define RULE(...) { .monitor = -1, .bw = -1, __VA_ARGS__ },
    605 #else
    606 #define RULE(...) { .monitor = -1, __VA_ARGS__ },
    607 #endif // XKB_PATCH
    608 
    609 /* Cross patch compatibility rule macro helper macros */
    610 #define FLOATING , .isfloating = 1
    611 #if CENTER_PATCH
    612 #define CENTERED , .iscentered = 1
    613 #else
    614 #define CENTERED
    615 #endif // CENTER_PATCH
    616 #if ISPERMANENT_PATCH
    617 #define PERMANENT , .ispermanent = 1
    618 #else
    619 #define PERMANENT
    620 #endif // ISPERMANENT_PATCH
    621 #if SELECTIVEFAKEFULLSCREEN_PATCH && FAKEFULLSCREEN_CLIENT_PATCH && !FAKEFULLSCREEN_PATCH
    622 #define FAKEFULLSCREEN , .isfakefullscreen = 1
    623 #else
    624 #define FAKEFULLSCREEN
    625 #endif // SELECTIVEFAKEFULLSCREEN_PATCH
    626 #if SWALLOW_PATCH
    627 #define NOSWALLOW , .noswallow = 1
    628 #define TERMINAL , .isterminal = 1
    629 #else
    630 #define NOSWALLOW
    631 #define TERMINAL
    632 #endif // SWALLOW_PATCH
    633 #if SWITCHTAG_PATCH
    634 #define SWITCHTAG , .switchtag = 1
    635 #else
    636 #define SWITCHTAG
    637 #endif // SWITCHTAG_PATCH
    638 
    639 #if MONITOR_RULES_PATCH
    640 typedef struct {
    641 	int monitor;
    642 	#if PERTAG_PATCH
    643 	int tag;
    644 	#endif // PERTAG_PATCH
    645 	int layout;
    646 	float mfact;
    647 	int nmaster;
    648 	int showbar;
    649 	int topbar;
    650 } MonitorRule;
    651 #endif // MONITOR_RULES_PATCH
    652 
    653 /* function declarations */
    654 static void applyrules(Client *c);
    655 static int applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact);
    656 static void arrange(Monitor *m);
    657 static void arrangemon(Monitor *m);
    658 static void attach(Client *c);
    659 static void attachstack(Client *c);
    660 static void buttonpress(XEvent *e);
    661 static void checkotherwm(void);
    662 static void cleanup(void);
    663 static void cleanupmon(Monitor *mon);
    664 static void clientmessage(XEvent *e);
    665 static void configure(Client *c);
    666 static void configurenotify(XEvent *e);
    667 static void configurerequest(XEvent *e);
    668 static Monitor *createmon(void);
    669 static void destroynotify(XEvent *e);
    670 static void detach(Client *c);
    671 static void detachstack(Client *c);
    672 static Monitor *dirtomon(int dir);
    673 static void drawbar(Monitor *m);
    674 static void drawbars(void);
    675 static void drawbarwin(Bar *bar);
    676 #if !FOCUSONCLICK_PATCH
    677 static void enternotify(XEvent *e);
    678 #endif // FOCUSONCLICK_PATCH
    679 static void expose(XEvent *e);
    680 static void focus(Client *c);
    681 static void focusin(XEvent *e);
    682 static void focusmon(const Arg *arg);
    683 #if !STACKER_PATCH
    684 static void focusstack(const Arg *arg);
    685 #endif // STACKER_PATCH
    686 static Atom getatomprop(Client *c, Atom prop, Atom req);
    687 static int getrootptr(int *x, int *y);
    688 static long getstate(Window w);
    689 static int gettextprop(Window w, Atom atom, char *text, unsigned int size);
    690 static void grabbuttons(Client *c, int focused);
    691 #if KEYMODES_PATCH
    692 static void grabdefkeys(void);
    693 #else
    694 static void grabkeys(void);
    695 #endif // KEYMODES_PATCH
    696 static void incnmaster(const Arg *arg);
    697 #if KEYMODES_PATCH
    698 static void keydefpress(XEvent *e);
    699 #else
    700 static void keypress(XEvent *e);
    701 #endif // KEYMODES_PATCH
    702 static void killclient(const Arg *arg);
    703 static void manage(Window w, XWindowAttributes *wa);
    704 static void mappingnotify(XEvent *e);
    705 static void maprequest(XEvent *e);
    706 static void motionnotify(XEvent *e);
    707 static void movemouse(const Arg *arg);
    708 static Client *nexttiled(Client *c);
    709 #if NOBORDER_PATCH
    710 static int noborder(Client *c);
    711 #endif // NOBORDER_PATCH
    712 #if !ZOOMSWAP_PATCH || TAGINTOSTACK_ALLMASTER_PATCH || TAGINTOSTACK_ONEMASTER_PATCH
    713 static void pop(Client *c);
    714 #endif // !ZOOMSWAP_PATCH / TAGINTOSTACK_ALLMASTER_PATCH / TAGINTOSTACK_ONEMASTER_PATCH
    715 static void propertynotify(XEvent *e);
    716 static void quit(const Arg *arg);
    717 static Monitor *recttomon(int x, int y, int w, int h);
    718 static void resize(Client *c, int x, int y, int w, int h, int interact);
    719 static void resizeclient(Client *c, int x, int y, int w, int h);
    720 static void resizemouse(const Arg *arg);
    721 static void restack(Monitor *m);
    722 static void run(void);
    723 static void scan(void);
    724 #if BAR_SYSTRAY_PATCH
    725 static int sendevent(Window w, Atom proto, int m, long d0, long d1, long d2, long d3, long d4);
    726 #else
    727 static int sendevent(Client *c, Atom proto);
    728 #endif // BAR_SYSTRAY_PATCH
    729 static void sendmon(Client *c, Monitor *m);
    730 static void setclientstate(Client *c, long state);
    731 static void setfocus(Client *c);
    732 static void setfullscreen(Client *c, int fullscreen);
    733 static void setlayout(const Arg *arg);
    734 static void setmfact(const Arg *arg);
    735 static void setup(void);
    736 static void seturgent(Client *c, int urg);
    737 #if COOL_AUTOSTART_PATCH
    738 static void sigchld(int unused);
    739 #endif // COOL_AUTOSTART_PATCH
    740 static void showhide(Client *c);
    741 static void spawn(const Arg *arg);
    742 #if RIODRAW_PATCH
    743 static pid_t spawncmd(const Arg *arg);
    744 #endif // RIODRAW_PATCH
    745 static void tag(const Arg *arg);
    746 static void tagmon(const Arg *arg);
    747 static void togglebar(const Arg *arg);
    748 static void togglefloating(const Arg *arg);
    749 static void toggletag(const Arg *arg);
    750 static void toggleview(const Arg *arg);
    751 static void unfocus(Client *c, int setfocus, Client *nextfocus);
    752 static void unmanage(Client *c, int destroyed);
    753 static void unmapnotify(XEvent *e);
    754 static void updatebarpos(Monitor *m);
    755 static void updatebars(void);
    756 static void updateclientlist(void);
    757 static int updategeom(void);
    758 static void updatenumlockmask(void);
    759 static void updatesizehints(Client *c);
    760 static void updatestatus(void);
    761 static void updatetitle(Client *c);
    762 static void updatewmhints(Client *c);
    763 static void view(const Arg *arg);
    764 static Client *wintoclient(Window w);
    765 static Monitor *wintomon(Window w);
    766 static int xerror(Display *dpy, XErrorEvent *ee);
    767 static int xerrordummy(Display *dpy, XErrorEvent *ee);
    768 static int xerrorstart(Display *dpy, XErrorEvent *ee);
    769 static void zoom(const Arg *arg);
    770 
    771 /* bar functions */
    772 
    773 #include "patch/include.h"
    774 
    775 /* variables */
    776 static const char broken[] = "broken";
    777 #if BAR_PANGO_PATCH || BAR_STATUS2D_PATCH && !BAR_STATUSCOLORS_PATCH
    778 static char stext[1024];
    779 #else
    780 static char stext[512];
    781 #endif // BAR_PANGO_PATCH | BAR_STATUS2D_PATCH
    782 #if BAR_EXTRASTATUS_PATCH || BAR_STATUSCMD_PATCH
    783 #if BAR_STATUS2D_PATCH
    784 static char rawstext[1024];
    785 #else
    786 static char rawstext[512];
    787 #endif // BAR_STATUS2D_PATCH
    788 #endif // BAR_EXTRASTATUS_PATCH | BAR_STATUSCMD_PATCH
    789 #if BAR_EXTRASTATUS_PATCH
    790 #if BAR_STATUS2D_PATCH && !BAR_STATUSCOLORS_PATCH
    791 static char estext[1024];
    792 #else
    793 static char estext[512];
    794 #endif // BAR_STATUS2D_PATCH
    795 #if BAR_STATUSCMD_PATCH
    796 static char rawestext[1024];
    797 #endif // BAR_STATUS2D_PATCH | BAR_STATUSCMD_PATCH
    798 #endif // BAR_EXTRASTATUS_PATCH
    799 
    800 #if XKB_PATCH
    801 static int xkbEventType = 0;
    802 #endif // XKB_PATCH
    803 static int screen;
    804 static int sw, sh;           /* X display screen geometry width, height */
    805 static int bh;               /* bar geometry */
    806 #if UNMANAGED_PATCH
    807 static int unmanaged = 0;    /* whether the window manager should manage the new window or not */
    808 #endif // UNMANAGED_PATCH
    809 static int lrpad;            /* sum of left and right padding for text */
    810 /* Some clients (e.g. alacritty) helpfully send configure requests with a new size or position
    811  * when they detect that they have been moved to another monitor. This can cause visual glitches
    812  * when moving (or resizing) client windows from one monitor to another. This variable is used
    813  * internally to ignore such configure requests while movemouse or resizemouse are being used. */
    814 static int ignoreconfigurerequests = 0;
    815 #if WARP_PATCH
    816 static int force_warp = 0; // force warp in some situations, e.g. killclient
    817 static int ignore_warp = 0; // force skip warp in some situations, e.g. dragmfact, dragcfact
    818 #endif // WARP_PATCH
    819 static int (*xerrorxlib)(Display *, XErrorEvent *);
    820 static unsigned int numlockmask = 0;
    821 #if RIODRAW_PATCH
    822 static int riodimensions[4] = { -1, -1, -1, -1 };
    823 static pid_t riopid = 0;
    824 #endif // RIODRAW_PATCH
    825 static void (*handler[LASTEvent]) (XEvent *) = {
    826 	[ButtonPress] = buttonpress,
    827 	#if COMBO_PATCH || BAR_HOLDBAR_PATCH
    828 	[ButtonRelease] = keyrelease,
    829 	#endif // COMBO_PATCH / BAR_HOLDBAR_PATCH
    830 	[ClientMessage] = clientmessage,
    831 	[ConfigureRequest] = configurerequest,
    832 	[ConfigureNotify] = configurenotify,
    833 	[DestroyNotify] = destroynotify,
    834 	#if !FOCUSONCLICK_PATCH
    835 	[EnterNotify] = enternotify,
    836 	#endif // FOCUSONCLICK_PATCH
    837 	[Expose] = expose,
    838 	#if BANISH_PATCH
    839 	[GenericEvent] = genericevent,
    840 	#endif // BANISH_PATCH
    841 	[FocusIn] = focusin,
    842 	[KeyPress] = keypress,
    843 	#if COMBO_PATCH || BAR_HOLDBAR_PATCH
    844 	[KeyRelease] = keyrelease,
    845 	#endif // COMBO_PATCH / BAR_HOLDBAR_PATCH
    846 	[MappingNotify] = mappingnotify,
    847 	[MapRequest] = maprequest,
    848 	[MotionNotify] = motionnotify,
    849 	[PropertyNotify] = propertynotify,
    850 	#if BAR_SYSTRAY_PATCH
    851 	[ResizeRequest] = resizerequest,
    852 	#endif // BAR_SYSTRAY_PATCH
    853 	[UnmapNotify] = unmapnotify
    854 };
    855 static Atom wmatom[WMLast], netatom[NetLast];
    856 #if BAR_SYSTRAY_PATCH
    857 static Atom xatom[XLast];
    858 #endif // BAR_SYSTRAY_PATCH
    859 #if SEAMLESS_RESTART_PATCH
    860 static Atom clientatom[ClientLast];
    861 #endif // SEAMLESS_RESTART_PATCH
    862 #if ON_EMPTY_KEYS_PATCH
    863 static int isempty = 0;
    864 #endif // ON_EMPTY_KEYS_PATCH
    865 #if RESTARTSIG_PATCH
    866 static volatile sig_atomic_t running = 1;
    867 #else
    868 static int running = 1;
    869 #endif // RESTARTSIG_PATCH
    870 static Cur *cursor[CurLast];
    871 static Clr **scheme;
    872 static Display *dpy;
    873 static Drw *drw;
    874 static Monitor *mons, *selmon;
    875 static Window root, wmcheckwin;
    876 
    877 /* configuration, allows nested code to access above variables */
    878 #include "config.h"
    879 
    880 #include "patch/include.c"
    881 
    882 /* compile-time check if all tags fit into an unsigned int bit array. */
    883 #if SCRATCHPAD_ALT_1_PATCH
    884 struct NumTags { char limitexceeded[NUMTAGS > 30 ? -1 : 1]; };
    885 #else
    886 struct NumTags { char limitexceeded[NUMTAGS > 31 ? -1 : 1]; };
    887 #endif // SCRATCHPAD_ALT_1_PATCH
    888 
    889 /* function implementations */
    890 void
    891 applyrules(Client *c)
    892 {
    893 	const char *class, *instance;
    894 	Atom wintype;
    895 	#if WINDOWROLERULE_PATCH
    896 	char role[64];
    897 	#endif // WINDOWROLERULE_PATCH
    898 	unsigned int i;
    899 	#if SWITCHTAG_PATCH
    900 	unsigned int newtagset;
    901 	#endif // SWITCHTAG_PATCH
    902 	const Rule *r;
    903 	Monitor *m;
    904 	XClassHint ch = { NULL, NULL };
    905 
    906 	/* rule matching */
    907 	#if SWALLOW_PATCH
    908 	c->noswallow = -1;
    909 	#endif // SWALLOW_PATCH
    910 	#if SIZEHINTS_ISFREESIZE_PATCH
    911 	c->isfreesize = 1;
    912 	#endif // SIZEHINTS_ISFREESIZE_PATCH
    913 	c->isfloating = 0;
    914 	c->tags = 0;
    915 	#if RENAMED_SCRATCHPADS_PATCH
    916 	c->scratchkey = 0;
    917 	#endif // RENAMED_SCRATCHPADS_PATCH
    918 	XGetClassHint(dpy, c->win, &ch);
    919 	class    = ch.res_class ? ch.res_class : broken;
    920 	instance = ch.res_name  ? ch.res_name  : broken;
    921 	wintype  = getatomprop(c, netatom[NetWMWindowType], XA_ATOM);
    922 	#if WINDOWROLERULE_PATCH
    923 	gettextprop(c->win, wmatom[WMWindowRole], role, sizeof(role));
    924 	#endif // WINDOWROLERULE_PATCH
    925 
    926 	#if STEAM_PATCH
    927 	if (strstr(class, "Steam") || strstr(class, "steam_app_"))
    928 		c->issteam = 1;
    929 	#endif // STEAM_PATCH
    930 
    931 	for (i = 0; i < LENGTH(rules); i++) {
    932 		r = &rules[i];
    933 		if ((!r->title || strstr(c->name, r->title))
    934 		&& (!r->class || strstr(class, r->class))
    935 		#if WINDOWROLERULE_PATCH
    936 		&& (!r->role || strstr(role, r->role))
    937 		#endif // WINDOWROLERULE_PATCH
    938 		&& (!r->instance || strstr(instance, r->instance))
    939 		&& (!r->wintype || wintype == XInternAtom(dpy, r->wintype, False)))
    940 		{
    941 			#if CENTER_PATCH
    942 			c->iscentered = r->iscentered;
    943 			#endif // CENTER_PATCH
    944 			#if BORDER_RULE_PATCH
    945 			if (r->bw != -1)
    946 				c->bw = r->bw;
    947 			#endif // BORDER_RULE_PATCH
    948 			#if ISPERMANENT_PATCH
    949 			c->ispermanent = r->ispermanent;
    950 			#endif // ISPERMANENT_PATCH
    951 			#if SELECTIVEFAKEFULLSCREEN_PATCH && FAKEFULLSCREEN_CLIENT_PATCH && !FAKEFULLSCREEN_PATCH
    952 			c->fakefullscreen = r->isfakefullscreen;
    953 			#endif // SELECTIVEFAKEFULLSCREEN_PATCH
    954 			#if GAMES_PATCH
    955 			c->isgame = r->isgame;
    956 			#endif // GAMES_PATCH
    957 			#if SWALLOW_PATCH
    958 			c->isterminal = r->isterminal;
    959 			c->noswallow = r->noswallow;
    960 			#endif // SWALLOW_PATCH
    961 			#if SIZEHINTS_ISFREESIZE_PATCH
    962 			c->isfreesize = r->isfreesize;
    963 			#endif // SIZEHINTS_ISFREESIZE_PATCH
    964 			c->isfloating = r->isfloating;
    965 			c->tags |= r->tags;
    966 			#if RENAMED_SCRATCHPADS_PATCH
    967 			c->scratchkey = r->scratchkey;
    968 			#elif SCRATCHPADS_PATCH
    969 			if ((r->tags & SPTAGMASK) && r->isfloating) {
    970 				c->x = c->mon->wx + (c->mon->ww / 2 - WIDTH(c) / 2);
    971 				c->y = c->mon->wy + (c->mon->wh / 2 - HEIGHT(c) / 2);
    972 			}
    973 			#endif // SCRATCHPADS_PATCH
    974 			#if UNMANAGED_PATCH
    975 			unmanaged = r->unmanaged;
    976 			#endif // UNMANAGED_PATCH
    977 			for (m = mons; m && m->num != r->monitor; m = m->next);
    978 			if (m)
    979 				c->mon = m;
    980 			#if FLOATPOS_PATCH
    981 			if (c->isfloating && r->floatpos) {
    982 				#if CENTER_PATCH
    983 				c->iscentered = 0;
    984 				#endif // CENTER_PATCH
    985 				setfloatpos(c, r->floatpos);
    986 			}
    987 			#endif // FLOATPOS_PATCH
    988 
    989 			#if SWITCHTAG_PATCH
    990 			#if SWALLOW_PATCH
    991 			if (r->switchtag && (
    992 				c->noswallow > 0 ||
    993 				!termforwin(c) ||
    994 				!(c->isfloating && swallowfloating && c->noswallow < 0)))
    995 			#else
    996 			if (r->switchtag)
    997 			#endif // SWALLOW_PATCH
    998 			{
    999 				unfocus(selmon->sel, 1, NULL);
   1000 				selmon = c->mon;
   1001 				if (r->switchtag == 2 || r->switchtag == 4)
   1002 					newtagset = c->mon->tagset[c->mon->seltags] ^ c->tags;
   1003 				else
   1004 					newtagset = c->tags;
   1005 
   1006 				/* Switch to the client's tag, but only if that tag is not already shown */
   1007 				if (newtagset && !(c->tags & c->mon->tagset[c->mon->seltags])) {
   1008 					if (r->switchtag == 3 || r->switchtag == 4)
   1009 						c->switchtag = c->mon->tagset[c->mon->seltags];
   1010 					if (r->switchtag == 1 || r->switchtag == 3) {
   1011 						view(&((Arg) { .ui = newtagset }));
   1012 					} else {
   1013 						#if TAGSYNC_PATCH
   1014 						for (m = mons; m; m = m->next)
   1015 							m->tagset[m->seltags] = newtagset;
   1016 						arrange(NULL);
   1017 						#else
   1018 						c->mon->tagset[c->mon->seltags] = newtagset;
   1019 						arrange(c->mon);
   1020 						#endif // TAGSYNC_PATCH
   1021 					}
   1022 				}
   1023 			}
   1024 			#endif // SWITCHTAG_PATCH
   1025 			#if XKB_PATCH
   1026 			if (r->xkb_layout > -1)
   1027 				c->xkb->group = r->xkb_layout;
   1028 			#endif // XKB_PATCH
   1029 			#if ONLY_ONE_RULE_MATCH_PATCH
   1030 			break;
   1031 			#endif // ONLY_ONE_RULE_MATCH_PATCH
   1032 		}
   1033 	}
   1034 	if (ch.res_class)
   1035 		XFree(ch.res_class);
   1036 	if (ch.res_name)
   1037 		XFree(ch.res_name);
   1038 	#if EMPTYVIEW_PATCH
   1039 	if (c->tags & TAGMASK)                    c->tags = c->tags & TAGMASK;
   1040 	#if SCRATCHPADS_PATCH && !RENAMED_SCRATCHPADS_PATCH
   1041 	else if (c->mon->tagset[c->mon->seltags]) c->tags = c->mon->tagset[c->mon->seltags] & ~SPTAGMASK;
   1042 	#elif SCRATCHPAD_ALT_1_PATCH
   1043 	else if (c->tags != SCRATCHPAD_MASK && c->mon->tagset[c->mon->seltags]) c->tags = c->mon->tagset[c->mon->seltags];
   1044 	#else
   1045 	else if (c->mon->tagset[c->mon->seltags]) c->tags = c->mon->tagset[c->mon->seltags];
   1046 	#endif // SCRATCHPADS_PATCH
   1047 	else                                      c->tags = 1;
   1048 	#elif SCRATCHPADS_PATCH && !RENAMED_SCRATCHPADS_PATCH
   1049 	c->tags = c->tags & TAGMASK ? c->tags & TAGMASK : (c->mon->tagset[c->mon->seltags] & ~SPTAGMASK);
   1050 	#elif SCRATCHPAD_ALT_1_PATCH
   1051 	if (c->tags != SCRATCHPAD_MASK)
   1052 		c->tags = c->tags & TAGMASK ? c->tags & TAGMASK : c->mon->tagset[c->mon->seltags];
   1053 	#else
   1054 	c->tags = c->tags & TAGMASK ? c->tags & TAGMASK : c->mon->tagset[c->mon->seltags];
   1055 	#endif // EMPTYVIEW_PATCH
   1056 }
   1057 
   1058 int
   1059 applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact)
   1060 {
   1061 	int baseismin;
   1062 	Monitor *m = c->mon;
   1063 
   1064 	/* set minimum possible */
   1065 	*w = MAX(1, *w);
   1066 	*h = MAX(1, *h);
   1067 	if (interact) {
   1068 		if (*x > sw)
   1069 			*x = sw - WIDTH(c);
   1070 		if (*y > sh)
   1071 			*y = sh - HEIGHT(c);
   1072 		if (*x + *w + 2 * c->bw < 0)
   1073 			*x = 0;
   1074 		if (*y + *h + 2 * c->bw < 0)
   1075 			*y = 0;
   1076 	} else {
   1077 		if (*x >= m->wx + m->ww)
   1078 			*x = m->wx + m->ww - WIDTH(c);
   1079 		if (*y >= m->wy + m->wh)
   1080 			*y = m->wy + m->wh - HEIGHT(c);
   1081 		if (*x + *w + 2 * c->bw <= m->wx)
   1082 			*x = m->wx;
   1083 		if (*y + *h + 2 * c->bw <= m->wy)
   1084 			*y = m->wy;
   1085 	}
   1086 	if (*h < bh)
   1087 		*h = bh;
   1088 	if (*w < bh)
   1089 		*w = bh;
   1090 	if (resizehints || c->isfloating || !c->mon->lt[c->mon->sellt]->arrange) {
   1091 		if (!c->hintsvalid)
   1092 			updatesizehints(c);
   1093 		/* see last two sentences in ICCCM 4.1.2.3 */
   1094 		baseismin = c->basew == c->minw && c->baseh == c->minh;
   1095 		if (!baseismin) { /* temporarily remove base dimensions */
   1096 			*w -= c->basew;
   1097 			*h -= c->baseh;
   1098 		}
   1099 		/* adjust for aspect limits */
   1100 		if (c->mina > 0 && c->maxa > 0) {
   1101 			if (c->maxa < (float)*w / *h)
   1102 				*w = *h * c->maxa + 0.5;
   1103 			else if (c->mina < (float)*h / *w)
   1104 				*h = *w * c->mina + 0.5;
   1105 		}
   1106 		if (baseismin) { /* increment calculation requires this */
   1107 			*w -= c->basew;
   1108 			*h -= c->baseh;
   1109 		}
   1110 		/* adjust for increment value */
   1111 		if (c->incw)
   1112 			*w -= *w % c->incw;
   1113 		if (c->inch)
   1114 			*h -= *h % c->inch;
   1115 		/* restore base dimensions */
   1116 		*w = MAX(*w + c->basew, c->minw);
   1117 		*h = MAX(*h + c->baseh, c->minh);
   1118 		if (c->maxw)
   1119 			*w = MIN(*w, c->maxw);
   1120 		if (c->maxh)
   1121 			*h = MIN(*h, c->maxh);
   1122 	}
   1123 	return *x != c->x || *y != c->y || *w != c->w || *h != c->h;
   1124 }
   1125 
   1126 void
   1127 arrange(Monitor *m)
   1128 {
   1129 	if (m)
   1130 		showhide(m->stack);
   1131 	else for (m = mons; m; m = m->next)
   1132 		showhide(m->stack);
   1133 	if (m) {
   1134 		arrangemon(m);
   1135 		restack(m);
   1136 	} else for (m = mons; m; m = m->next)
   1137 		arrangemon(m);
   1138 }
   1139 
   1140 void
   1141 arrangemon(Monitor *m)
   1142 {
   1143 	#if BAR_PADDING_SMART_PATCH
   1144 	updatebarpos(selmon);
   1145 	for (Bar *bar = selmon->bar; bar; bar = bar->next)
   1146 		XMoveResizeWindow(dpy, bar->win, bar->bx, bar->by, bar->bw, bar->bh);
   1147 	#endif // BAR_PADDING_SMART_PATCH
   1148 	#if TAB_PATCH
   1149 	updatebarpos(m);
   1150 	XMoveResizeWindow(dpy, m->tabwin, m->wx, m->ty, m->ww, th);
   1151 	#endif // TAB_PATCH
   1152 	strncpy(m->ltsymbol, m->lt[m->sellt]->symbol, sizeof m->ltsymbol);
   1153 	if (m->lt[m->sellt]->arrange)
   1154 		m->lt[m->sellt]->arrange(m);
   1155 }
   1156 
   1157 void
   1158 attach(Client *c)
   1159 {
   1160 	c->next = c->mon->clients;
   1161 	c->mon->clients = c;
   1162 }
   1163 
   1164 void
   1165 attachstack(Client *c)
   1166 {
   1167 	c->snext = c->mon->stack;
   1168 	c->mon->stack = c;
   1169 }
   1170 
   1171 void
   1172 buttonpress(XEvent *e)
   1173 {
   1174 	int click, i, r;
   1175 	#if TAB_PATCH
   1176 	int x;
   1177 	#endif // TAB_PATCH
   1178 	Arg arg = {0};
   1179 	Client *c;
   1180 	Monitor *m;
   1181 	Bar *bar;
   1182 	XButtonPressedEvent *ev = &e->xbutton;
   1183 	const BarRule *br;
   1184 	BarArg carg = { 0, 0, 0, 0 };
   1185 	click = ClkRootWin;
   1186 
   1187 	#if BAR_STATUSCMD_PATCH && !BAR_DWMBLOCKS_PATCH
   1188 	*lastbutton = '0' + ev->button;
   1189 	#endif // BAR_STATUSCMD_PATCH | BAR_DWMBLOCKS_PATCH
   1190 
   1191 	/* focus monitor if necessary */
   1192 	if ((m = wintomon(ev->window)) && m != selmon
   1193 		#if FOCUSONCLICK_PATCH
   1194 		&& (focusonwheel || (ev->button != Button4 && ev->button != Button5))
   1195 		#endif // FOCUSONCLICK_PATCH
   1196 	) {
   1197 		unfocus(selmon->sel, 1, NULL);
   1198 		selmon = m;
   1199 		focus(NULL);
   1200 	}
   1201 
   1202 	#if BANISH_PATCH
   1203 	c = wintoclient(ev->window);
   1204 
   1205 	if (!c && cursor_hidden) {
   1206 		c = recttoclient(mouse_x, mouse_y, 1, 1, 1);
   1207 		showcursor(NULL);
   1208 	}
   1209 
   1210 	if (c) {
   1211 		#if FOCUSONCLICK_PATCH
   1212 		if (focusonwheel || (ev->button != Button4 && ev->button != Button5))
   1213 			focus(c);
   1214 		#else
   1215 		focus(c);
   1216 		restack(selmon);
   1217 		#endif // FOCUSONCLICK_PATCH
   1218 		XAllowEvents(dpy, ReplayPointer, CurrentTime);
   1219 		click = ClkClientWin;
   1220 	}
   1221 	#endif // BANISH_PATCH
   1222 
   1223 	for (bar = selmon->bar; bar; bar = bar->next) {
   1224 		if (ev->window == bar->win) {
   1225 			for (r = 0; r < LENGTH(barrules); r++) {
   1226 				br = &barrules[r];
   1227 				if (br->bar != bar->idx || (br->monitor == 'A' && m != selmon) || br->clickfunc == NULL)
   1228 					continue;
   1229 				if (br->monitor != 'A' && br->monitor != -1 && br->monitor != bar->mon->num)
   1230 					continue;
   1231 				if (bar->x[r] <= ev->x && ev->x <= bar->x[r] + bar->w[r]) {
   1232 					carg.x = ev->x - bar->x[r];
   1233 					carg.y = ev->y - bar->borderpx;
   1234 					carg.w = bar->w[r];
   1235 					carg.h = bar->bh - 2 * bar->borderpx;
   1236 					click = br->clickfunc(bar, &arg, &carg);
   1237 					if (click < 0)
   1238 						return;
   1239 					break;
   1240 				}
   1241 			}
   1242 			break;
   1243 		}
   1244 	}
   1245 
   1246 	#if TAB_PATCH
   1247 	if (ev->window == selmon->tabwin) {
   1248 		for (i = 0, x = 0, c = selmon->clients; c; c = c->next) {
   1249 			if (!ISVISIBLE(c) || HIDDEN(c))
   1250 				continue;
   1251 			x += selmon->tab_widths[i];
   1252 			if (ev->x > x)
   1253 				++i;
   1254 			else
   1255 				break;
   1256 			if (i >= m->ntabs)
   1257 				break;
   1258 		}
   1259 		if (c) {
   1260 			click = ClkTabBar;
   1261 			arg.ui = i;
   1262 		}
   1263 	}
   1264 	#endif // TAB_PATCH
   1265 
   1266 	#if !BANISH_PATCH
   1267 	if (click == ClkRootWin && (c = wintoclient(ev->window))) {
   1268 		#if FOCUSONCLICK_PATCH
   1269 		if (focusonwheel || (ev->button != Button4 && ev->button != Button5))
   1270 			focus(c);
   1271 		#else
   1272 		focus(c);
   1273 		restack(selmon);
   1274 		#endif // FOCUSONCLICK_PATCH
   1275 		XAllowEvents(dpy, ReplayPointer, CurrentTime);
   1276 		click = ClkClientWin;
   1277 	}
   1278 	#endif // BANISH_PATCH
   1279 
   1280 	for (i = 0; i < LENGTH(buttons); i++) {
   1281 		if (click == buttons[i].click && buttons[i].func && buttons[i].button == ev->button
   1282 				&& CLEANMASK(buttons[i].mask) == CLEANMASK(ev->state)) {
   1283 			buttons[i].func(
   1284 				(
   1285 					click == ClkTagBar
   1286 					#if TAB_PATCH
   1287 					|| click == ClkTabBar
   1288 					#endif // TAB_PATCH
   1289 					#if BAR_WINTITLEACTIONS_PATCH
   1290 					|| click == ClkWinTitle
   1291 					#endif // BAR_WINTITLEACTIONS_PATCH
   1292 				) && buttons[i].arg.i == 0 ? &arg : &buttons[i].arg
   1293 			);
   1294 		}
   1295 	}
   1296 
   1297 	#if BANISH_PATCH
   1298 	last_button_press = now();
   1299 	#endif // BANISH_PATCH
   1300 }
   1301 
   1302 void
   1303 checkotherwm(void)
   1304 {
   1305 	xerrorxlib = XSetErrorHandler(xerrorstart);
   1306 	/* this causes an error if some other window manager is running */
   1307 	XSelectInput(dpy, DefaultRootWindow(dpy), SubstructureRedirectMask);
   1308 	XSync(dpy, False);
   1309 	XSetErrorHandler(xerror);
   1310 	XSync(dpy, False);
   1311 }
   1312 
   1313 void
   1314 cleanup(void)
   1315 {
   1316 	Monitor *m;
   1317 	Layout foo = { "", NULL };
   1318 	size_t i;
   1319 
   1320 	#if ALT_TAB_PATCH
   1321 	alttabend();
   1322 	#endif // ALT_TAB_PATCH
   1323 
   1324 	#if SEAMLESS_RESTART_PATCH
   1325 	for (m = mons; m; m = m->next)
   1326 		persistmonitorstate(m);
   1327 	#endif // SEAMLESS_RESTART_PATCH
   1328 
   1329 	#if COOL_AUTOSTART_PATCH
   1330 	/* kill child processes, but not on restart (autostart_exec will handle it) */
   1331 	#if RESTARTSIG_PATCH
   1332 	if (!restart) {
   1333 	#endif // RESTARTSIG_PATCH
   1334 		for (i = 0; i < autostart_len; i++) {
   1335 			if (0 < autostart_pids[i]) {
   1336 				kill(autostart_pids[i], SIGTERM);
   1337 				waitpid(autostart_pids[i], NULL, 0);
   1338 			}
   1339 		}
   1340 	#if RESTARTSIG_PATCH
   1341 	}
   1342 	#endif // RESTARTSIG_PATCH
   1343 	#endif // COOL_AUTOSTART_PATCH
   1344 
   1345 	selmon->lt[selmon->sellt] = &foo;
   1346 	for (m = mons; m; m = m->next)
   1347 		while (m->stack)
   1348 			unmanage(m->stack, 0);
   1349 	XUngrabKey(dpy, AnyKey, AnyModifier, root);
   1350 	while (mons)
   1351 		cleanupmon(mons);
   1352 	#if BAR_SYSTRAY_PATCH
   1353 	if (showsystray && systray) {
   1354 		while (systray->icons)
   1355 			removesystrayicon(systray->icons);
   1356 		if (systray->win) {
   1357 			XUnmapWindow(dpy, systray->win);
   1358 			XDestroyWindow(dpy, systray->win);
   1359 		}
   1360 		free(systray);
   1361 	}
   1362 	#endif // BAR_SYSTRAY_PATCH
   1363 	for (i = 0; i < CurLast; i++)
   1364 		drw_cur_free(drw, cursor[i]);
   1365 	#if BAR_STATUS2D_PATCH && !BAR_STATUSCOLORS_PATCH
   1366 	for (i = 0; i < LENGTH(colors) + 1; i++)
   1367 	#else
   1368 	for (i = 0; i < LENGTH(colors); i++)
   1369 	#endif // BAR_STATUS2D_PATCH
   1370 		free(scheme[i]);
   1371 	free(scheme);
   1372 	XDestroyWindow(dpy, wmcheckwin);
   1373 	drw_free(drw);
   1374 	XSync(dpy, False);
   1375 	XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime);
   1376 	XDeleteProperty(dpy, root, netatom[NetActiveWindow]);
   1377 
   1378 	#if IPC_PATCH
   1379 	ipc_cleanup();
   1380 
   1381 	if (close(epoll_fd) < 0)
   1382 		fprintf(stderr, "Failed to close epoll file descriptor\n");
   1383 	#endif // IPC_PATCH
   1384 }
   1385 
   1386 void
   1387 cleanupmon(Monitor *mon)
   1388 {
   1389 	Monitor *m;
   1390 	Bar *bar;
   1391 
   1392 	if (mon == mons)
   1393 		mons = mons->next;
   1394 	else {
   1395 		for (m = mons; m && m->next != mon; m = m->next);
   1396 		m->next = mon->next;
   1397 	}
   1398 	for (bar = mon->bar; bar; bar = mon->bar) {
   1399 		if (!bar->external) {
   1400 			XUnmapWindow(dpy, bar->win);
   1401 			XDestroyWindow(dpy, bar->win);
   1402 		}
   1403 		mon->bar = bar->next;
   1404 		#if BAR_SYSTRAY_PATCH
   1405 		if (systray && bar == systray->bar)
   1406 			systray->bar = NULL;
   1407 		#endif // BAR_SYSTRAY_PATCH
   1408 		free(bar);
   1409 	}
   1410 	#if TAB_PATCH
   1411 	XUnmapWindow(dpy, mon->tabwin);
   1412 	XDestroyWindow(dpy, mon->tabwin);
   1413 	#endif // TAB_PATCH
   1414 	#if PERTAG_PATCH
   1415 	free(mon->pertag);
   1416 	#endif // PERTAG_PATCH
   1417 	#if BAR_TAGPREVIEW_PATCH
   1418 	for (size_t i = 0; i < NUMTAGS; i++)
   1419 		if (mon->tagmap[i])
   1420 			XFreePixmap(dpy, mon->tagmap[i]);
   1421 	XUnmapWindow(dpy, mon->tagwin);
   1422 	XDestroyWindow(dpy, mon->tagwin);
   1423 	#endif // BAR_TAGPREVIEW_PATCH
   1424 	free(mon);
   1425 }
   1426 
   1427 void
   1428 clientmessage(XEvent *e)
   1429 {
   1430 	#if BAR_SYSTRAY_PATCH
   1431 	XWindowAttributes wa;
   1432 	XSetWindowAttributes swa;
   1433 	#endif // BAR_SYSTRAY_PATCH
   1434 	XClientMessageEvent *cme = &e->xclient;
   1435 	Client *c = wintoclient(cme->window);
   1436 	#if FOCUSONNETACTIVE_PATCH
   1437 	unsigned int i;
   1438 	#endif // FOCUSONNETACTIVE_PATCH
   1439 
   1440 	#if BAR_SYSTRAY_PATCH
   1441 	if (showsystray && systray && cme->window == systray->win && cme->message_type == netatom[NetSystemTrayOP]) {
   1442 		/* add systray icons */
   1443 		if (cme->data.l[1] == SYSTEM_TRAY_REQUEST_DOCK) {
   1444 			if (!(c = (Client *)calloc(1, sizeof(Client))))
   1445 				die("fatal: could not malloc() %u bytes\n", sizeof(Client));
   1446 			if (!(c->win = cme->data.l[2])) {
   1447 				free(c);
   1448 				return;
   1449 			}
   1450 
   1451 			c->mon = selmon;
   1452 			c->next = systray->icons;
   1453 			systray->icons = c;
   1454 			XGetWindowAttributes(dpy, c->win, &wa);
   1455 			c->x = c->oldx = c->y = c->oldy = 0;
   1456 			c->w = c->oldw = wa.width;
   1457 			c->h = c->oldh = wa.height;
   1458 			c->oldbw = wa.border_width;
   1459 			c->bw = 0;
   1460 			c->isfloating = True;
   1461 			/* reuse tags field as mapped status */
   1462 			c->tags = 1;
   1463 			updatesizehints(c);
   1464 			updatesystrayicongeom(c, wa.width, wa.height);
   1465 			XAddToSaveSet(dpy, c->win);
   1466 			XSelectInput(dpy, c->win, StructureNotifyMask | PropertyChangeMask | ResizeRedirectMask);
   1467 			XClassHint ch = {"dwmsystray", "dwmsystray"};
   1468 			XSetClassHint(dpy, c->win, &ch);
   1469 			XReparentWindow(dpy, c->win, systray->win, 0, 0);
   1470 			/* use parents background color */
   1471 			swa.background_pixel = scheme[SchemeNorm][ColBg].pixel;
   1472 			XChangeWindowAttributes(dpy, c->win, CWBackPixel, &swa);
   1473 			sendevent(c->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_EMBEDDED_NOTIFY, 0 , systray->win, XEMBED_EMBEDDED_VERSION);
   1474 			XSync(dpy, False);
   1475 			setclientstate(c, NormalState);
   1476 		}
   1477 		return;
   1478 	}
   1479 	#endif // BAR_SYSTRAY_PATCH
   1480 
   1481 	if (!c)
   1482 		return;
   1483 	if (cme->message_type == netatom[NetWMState]) {
   1484 		if (cme->data.l[1] == netatom[NetWMFullscreen]
   1485 		|| cme->data.l[2] == netatom[NetWMFullscreen]) {
   1486 			#if FAKEFULLSCREEN_CLIENT_PATCH && !FAKEFULLSCREEN_PATCH
   1487 			if (c->fakefullscreen == 2 && c->isfullscreen)
   1488 				c->fakefullscreen = 3;
   1489 			#endif // FAKEFULLSCREEN_CLIENT_PATCH
   1490 			setfullscreen(c, (cme->data.l[0] == 1 /* _NET_WM_STATE_ADD    */
   1491 				|| (cme->data.l[0] == 2 /* _NET_WM_STATE_TOGGLE */
   1492 				#if !FAKEFULLSCREEN_PATCH
   1493 				&& !c->isfullscreen
   1494 				#endif // !FAKEFULLSCREEN_PATCH
   1495 			)));
   1496 		}
   1497 	} else if (cme->message_type == netatom[NetActiveWindow]) {
   1498 		#if FOCUSONNETACTIVE_PATCH
   1499 		if (c->tags & c->mon->tagset[c->mon->seltags])
   1500 			focus(c);
   1501 		else {
   1502 			for (i = 0; i < NUMTAGS && !((1 << i) & c->tags); i++);
   1503 			if (i < NUMTAGS) {
   1504 				if (c != selmon->sel)
   1505 					unfocus(selmon->sel, 0, NULL);
   1506 				selmon = c->mon;
   1507 				if (((1 << i) & TAGMASK) != selmon->tagset[selmon->seltags])
   1508 					view(&((Arg) { .ui = 1 << i }));
   1509 				focus(c);
   1510 				restack(selmon);
   1511 			}
   1512 		}
   1513 		#else
   1514 		if (c != selmon->sel && !c->isurgent)
   1515 			seturgent(c, 1);
   1516 		#endif // FOCUSONNETACTIVE_PATCH
   1517 	}
   1518 }
   1519 
   1520 void
   1521 configure(Client *c)
   1522 {
   1523 	XConfigureEvent ce;
   1524 
   1525 	ce.type = ConfigureNotify;
   1526 	ce.display = dpy;
   1527 	ce.event = c->win;
   1528 	ce.window = c->win;
   1529 	ce.x = c->x;
   1530 	ce.y = c->y;
   1531 	ce.width = c->w;
   1532 	ce.height = c->h;
   1533 	ce.border_width = c->bw;
   1534 
   1535 	#if NOBORDER_PATCH
   1536 	if (noborder(c)) {
   1537 		ce.width += c->bw * 2;
   1538 		ce.height += c->bw * 2;
   1539 		ce.border_width = 0;
   1540 	}
   1541 	#endif // NOBORDER_PATCH
   1542 
   1543 	ce.above = None;
   1544 	ce.override_redirect = False;
   1545 	XSendEvent(dpy, c->win, False, StructureNotifyMask, (XEvent *)&ce);
   1546 }
   1547 
   1548 void
   1549 configurenotify(XEvent *e)
   1550 {
   1551 	Monitor *m;
   1552 	Bar *bar;
   1553 	#if !FAKEFULLSCREEN_PATCH
   1554 	Client *c;
   1555 	#endif // !FAKEFULLSCREEN_PATCH
   1556 	XConfigureEvent *ev = &e->xconfigure;
   1557 	int dirty;
   1558 	/* TODO: updategeom handling sucks, needs to be simplified */
   1559 	if (ev->window == root) {
   1560 		dirty = (sw != ev->width || sh != ev->height);
   1561 		sw = ev->width;
   1562 		sh = ev->height;
   1563 		if (updategeom() || dirty) {
   1564 			drw_resize(drw, sw, sh);
   1565 			updatebars();
   1566 			for (m = mons; m; m = m->next) {
   1567 				#if !FAKEFULLSCREEN_PATCH
   1568 				for (c = m->clients; c; c = c->next)
   1569 					#if FAKEFULLSCREEN_CLIENT_PATCH
   1570 					if (c->isfullscreen && c->fakefullscreen != 1)
   1571 					#else
   1572 					if (c->isfullscreen)
   1573 					#endif // FAKEFULLSCREEN_CLIENT_PATCH
   1574 						resizeclient(c, m->mx, m->my, m->mw, m->mh);
   1575 				#endif // !FAKEFULLSCREEN_PATCH
   1576 				for (bar = m->bar; bar; bar = bar->next)
   1577 					XMoveResizeWindow(dpy, bar->win, bar->bx, bar->by, bar->bw, bar->bh);
   1578 				#if BAR_TAGPREVIEW_PATCH
   1579 				createpreview(m);
   1580 				#endif // BAR_TAGPREVIEW_PATCH
   1581 			}
   1582 			arrange(NULL);
   1583 			focus(NULL);
   1584 		}
   1585 	}
   1586 }
   1587 
   1588 void
   1589 configurerequest(XEvent *e)
   1590 {
   1591 	Client *c;
   1592 	Monitor *m;
   1593 	#if BAR_ANYBAR_PATCH
   1594 	Bar *bar;
   1595 	#endif // BAR_ANYBAR_PATCH
   1596 	XConfigureRequestEvent *ev = &e->xconfigurerequest;
   1597 	XWindowChanges wc;
   1598 
   1599 	if (ignoreconfigurerequests)
   1600 		return;
   1601 
   1602 	if ((c = wintoclient(ev->window))) {
   1603 		if (ev->value_mask & CWBorderWidth)
   1604 			c->bw = ev->border_width;
   1605 		else if (c->isfloating || !selmon->lt[selmon->sellt]->arrange) {
   1606 			m = c->mon;
   1607 			#if STEAM_PATCH
   1608 			if (!c->issteam) {
   1609 				if (ev->value_mask & CWX) {
   1610 					c->oldx = c->x;
   1611 					c->x = m->mx + ev->x;
   1612 				}
   1613 				if (ev->value_mask & CWY) {
   1614 					c->oldy = c->y;
   1615 					c->y = m->my + ev->y;
   1616 				}
   1617 			}
   1618 			#else
   1619 			if (ev->value_mask & CWX) {
   1620 				c->oldx = c->x;
   1621 				c->x = m->mx + ev->x;
   1622 			}
   1623 			if (ev->value_mask & CWY) {
   1624 				c->oldy = c->y;
   1625 				c->y = m->my + ev->y;
   1626 			}
   1627 			#endif // STEAM_PATCH
   1628 			if (ev->value_mask & CWWidth) {
   1629 				c->oldw = c->w;
   1630 				c->w = ev->width;
   1631 			}
   1632 			if (ev->value_mask & CWHeight) {
   1633 				c->oldh = c->h;
   1634 				c->h = ev->height;
   1635 			}
   1636 			if ((c->x + c->w) > m->mx + m->mw && c->isfloating)
   1637 				c->x = m->mx + (m->mw / 2 - WIDTH(c) / 2);  /* center in x direction */
   1638 			if ((c->y + c->h) > m->my + m->mh && c->isfloating)
   1639 				c->y = m->my + (m->mh / 2 - HEIGHT(c) / 2); /* center in y direction */
   1640 			if ((ev->value_mask & (CWX|CWY)) && !(ev->value_mask & (CWWidth|CWHeight)))
   1641 				configure(c);
   1642 			if (ISVISIBLE(c))
   1643 				XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h);
   1644 			#if AUTORESIZE_PATCH
   1645 			else
   1646 				c->needresize = 1;
   1647 			#endif // AUTORESIZE_PATCH
   1648 		} else
   1649 			configure(c);
   1650 	} else {
   1651 		wc.x = ev->x;
   1652 		wc.y = ev->y;
   1653 		#if BAR_ANYBAR_PATCH
   1654 		m = wintomon(ev->window);
   1655 		for (bar = m->bar; bar; bar = bar->next) {
   1656 			if (bar->win == ev->window) {
   1657 				wc.y = bar->by;
   1658 				wc.x = bar->bx;
   1659 			}
   1660 		}
   1661 		#endif // BAR_ANYBAR_PATCH
   1662 		wc.width = ev->width;
   1663 		wc.height = ev->height;
   1664 		wc.border_width = ev->border_width;
   1665 		wc.sibling = ev->above;
   1666 		wc.stack_mode = ev->detail;
   1667 		XConfigureWindow(dpy, ev->window, ev->value_mask, &wc);
   1668 	}
   1669 	XSync(dpy, False);
   1670 }
   1671 
   1672 Monitor *
   1673 createmon(void)
   1674 {
   1675 	Monitor *m, *mon;
   1676 	int i, n, mi, max_bars = 2, istopbar = topbar;
   1677 	#if MONITOR_RULES_PATCH
   1678 	int layout;
   1679 	#endif // MONITOR_RULES_PATCH
   1680 
   1681 	const BarRule *br;
   1682 	Bar *bar;
   1683 	#if MONITOR_RULES_PATCH
   1684 	int j;
   1685 	const MonitorRule *mr;
   1686 	#endif // MONITOR_RULES_PATCH
   1687 
   1688 	m = ecalloc(1, sizeof(Monitor));
   1689 	#if !EMPTYVIEW_PATCH
   1690 	#if VIEW_HISTORY_PATCH
   1691 	for (i = 0; i < LENGTH(m->tagset); i++)
   1692 		m->tagset[i] = 1;
   1693 	#else
   1694 	m->tagset[0] = m->tagset[1] = 1;
   1695 	#endif // VIEW_HISTORY_PATCH
   1696 	#endif // EMPTYVIEW_PATCH
   1697 	m->mfact = mfact;
   1698 	m->nmaster = nmaster;
   1699 	#if FLEXTILE_DELUXE_LAYOUT
   1700 	m->nstack = nstack;
   1701 	#endif // FLEXTILE_DELUXE_LAYOUT
   1702 	m->showbar = showbar;
   1703 	#if TAB_PATCH
   1704 	m->showtab = showtab;
   1705 	m->toptab = toptab;
   1706 	m->ntabs = 0;
   1707 	#endif // TAB_PATCH
   1708 	#if SETBORDERPX_PATCH
   1709 	m->borderpx = borderpx;
   1710 	#endif // SETBORDERPX_PATCH
   1711 	#if VANITYGAPS_PATCH
   1712 	m->gappih = gappih;
   1713 	m->gappiv = gappiv;
   1714 	m->gappoh = gappoh;
   1715 	m->gappov = gappov;
   1716 	#endif // VANITYGAPS_PATCH
   1717 	for (mi = 0, mon = mons; mon; mon = mon->next, mi++); // monitor index
   1718 	m->num = mi;
   1719 	#if MONITOR_RULES_PATCH
   1720 	for (j = 0; j < LENGTH(monrules); j++) {
   1721 		mr = &monrules[j];
   1722 		if ((mr->monitor == -1 || mr->monitor == m->num)
   1723 		#if PERTAG_PATCH
   1724 				&& (mr->tag <= 0 || (m->tagset[0] & (1 << (mr->tag - 1))))
   1725 		#endif // PERTAG_PATCH
   1726 		) {
   1727 			layout = MAX(mr->layout, 0);
   1728 			layout = MIN(layout, LENGTH(layouts) - 1);
   1729 			m->lt[0] = &layouts[layout];
   1730 			m->lt[1] = &layouts[1 % LENGTH(layouts)];
   1731 			strncpy(m->ltsymbol, layouts[layout].symbol, sizeof m->ltsymbol);
   1732 
   1733 			if (mr->mfact > -1)
   1734 				m->mfact = mr->mfact;
   1735 			if (mr->nmaster > -1)
   1736 				m->nmaster = mr->nmaster;
   1737 			if (mr->showbar > -1)
   1738 				m->showbar = mr->showbar;
   1739 			if (mr->topbar > -1)
   1740 				istopbar = mr->topbar;
   1741 			break;
   1742 		}
   1743 	}
   1744 	#else
   1745 	m->lt[0] = &layouts[0];
   1746 	m->lt[1] = &layouts[1 % LENGTH(layouts)];
   1747 	strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol);
   1748 	#endif // MONITOR_RULES_PATCH
   1749 
   1750 	/* Derive the number of bars for this monitor based on bar rules */
   1751 	for (n = -1, i = 0; i < LENGTH(barrules); i++) {
   1752 		br = &barrules[i];
   1753 		if (br->monitor == 'A' || br->monitor == -1 || br->monitor == m->num)
   1754 			n = MAX(br->bar, n);
   1755 	}
   1756 
   1757 	m->bar = NULL;
   1758 	for (i = 0; i <= n && i < max_bars; i++) {
   1759 		bar = ecalloc(1, sizeof(Bar));
   1760 		bar->mon = m;
   1761 		bar->idx = i;
   1762 		bar->next = m->bar;
   1763 		bar->topbar = istopbar;
   1764 		m->bar = bar;
   1765 		istopbar = !istopbar;
   1766 		bar->showbar = 1;
   1767 		bar->external = 0;
   1768 		#if BAR_BORDER_PATCH
   1769 		bar->borderpx = (barborderpx ? barborderpx : borderpx);
   1770 		#else
   1771 		bar->borderpx = 0;
   1772 		#endif // BAR_BORDER_PATCH
   1773 		bar->bh = bh + bar->borderpx * 2;
   1774 		bar->borderscheme = SchemeNorm;
   1775 	}
   1776 
   1777 	#if FLEXTILE_DELUXE_LAYOUT
   1778 	m->ltaxis[LAYOUT] = m->lt[0]->preset.layout;
   1779 	m->ltaxis[MASTER] = m->lt[0]->preset.masteraxis;
   1780 	m->ltaxis[STACK]  = m->lt[0]->preset.stack1axis;
   1781 	m->ltaxis[STACK2] = m->lt[0]->preset.stack2axis;
   1782 	#endif // FLEXTILE_DELUXE_LAYOUT
   1783 
   1784 	#if PERTAG_PATCH
   1785 	if (!(m->pertag = (Pertag *)calloc(1, sizeof(Pertag))))
   1786 		die("fatal: could not malloc() %u bytes\n", sizeof(Pertag));
   1787 	m->pertag->curtag = 1;
   1788 	for (i = 0; i <= NUMTAGS; i++) {
   1789 		#if FLEXTILE_DELUXE_LAYOUT
   1790 		m->pertag->nstacks[i] = m->nstack;
   1791 		#endif // FLEXTILE_DELUXE_LAYOUT
   1792 
   1793 		#if !MONITOR_RULES_PATCH
   1794 		/* init nmaster */
   1795 		m->pertag->nmasters[i] = m->nmaster;
   1796 
   1797 		/* init mfacts */
   1798 		m->pertag->mfacts[i] = m->mfact;
   1799 
   1800 		#if PERTAGBAR_PATCH
   1801 		/* init showbar */
   1802 		m->pertag->showbars[i] = m->showbar;
   1803 		#endif // PERTAGBAR_PATCH
   1804 		#endif // MONITOR_RULES_PATCH
   1805 
   1806 		#if ZOOMSWAP_PATCH
   1807 		m->pertag->prevzooms[i] = NULL;
   1808 		#endif // ZOOMSWAP_PATCH
   1809 
   1810 		/* init layouts */
   1811 		#if MONITOR_RULES_PATCH
   1812 		for (j = 0; j < LENGTH(monrules); j++) {
   1813 			mr = &monrules[j];
   1814 			if ((mr->monitor == -1 || mr->monitor == m->num) && (mr->tag == -1 || mr->tag == i)) {
   1815 				layout = MAX(mr->layout, 0);
   1816 				layout = MIN(layout, LENGTH(layouts) - 1);
   1817 				m->pertag->ltidxs[i][0] = &layouts[layout];
   1818 				m->pertag->ltidxs[i][1] = m->lt[0];
   1819 				m->pertag->nmasters[i] = (mr->nmaster > -1 ? mr->nmaster : m->nmaster);
   1820 				m->pertag->mfacts[i] = (mr->mfact > -1 ? mr->mfact : m->mfact);
   1821 				#if PERTAGBAR_PATCH
   1822 				m->pertag->showbars[i] = (mr->showbar > -1 ? mr->showbar : m->showbar);
   1823 				#endif // PERTAGBAR_PATCH
   1824 				#if FLEXTILE_DELUXE_LAYOUT
   1825 				m->pertag->ltaxis[i][LAYOUT] = m->pertag->ltidxs[i][0]->preset.layout;
   1826 				m->pertag->ltaxis[i][MASTER] = m->pertag->ltidxs[i][0]->preset.masteraxis;
   1827 				m->pertag->ltaxis[i][STACK]  = m->pertag->ltidxs[i][0]->preset.stack1axis;
   1828 				m->pertag->ltaxis[i][STACK2] = m->pertag->ltidxs[i][0]->preset.stack2axis;
   1829 				#endif // FLEXTILE_DELUXE_LAYOUT
   1830 				break;
   1831 			}
   1832 		}
   1833 		#else
   1834 		m->pertag->ltidxs[i][0] = m->lt[0];
   1835 		m->pertag->ltidxs[i][1] = m->lt[1];
   1836 		#if FLEXTILE_DELUXE_LAYOUT
   1837 		/* init flextile axes */
   1838 		m->pertag->ltaxis[i][LAYOUT] = m->ltaxis[LAYOUT];
   1839 		m->pertag->ltaxis[i][MASTER] = m->ltaxis[MASTER];
   1840 		m->pertag->ltaxis[i][STACK]  = m->ltaxis[STACK];
   1841 		m->pertag->ltaxis[i][STACK2] = m->ltaxis[STACK2];
   1842 		#endif // FLEXTILE_DELUXE_LAYOUT
   1843 		#endif // MONITOR_RULES_PATCH
   1844 		m->pertag->sellts[i] = m->sellt;
   1845 
   1846 		#if PERTAG_VANITYGAPS_PATCH && VANITYGAPS_PATCH
   1847 		m->pertag->enablegaps[i] = 1;
   1848 		m->pertag->gaps[i] =
   1849 			((gappoh & 0xFF) << 0) | ((gappov & 0xFF) << 8) | ((gappih & 0xFF) << 16) | ((gappiv & 0xFF) << 24);
   1850 		#endif // PERTAG_VANITYGAPS_PATCH | VANITYGAPS_PATCH
   1851 	}
   1852 	#endif // PERTAG_PATCH
   1853 
   1854 	#if PERMON_VANITYGAPS_PATCH
   1855 	m->enablegaps = 1;
   1856 	#endif // PERMON_VANITYGAPS_PATCH
   1857 
   1858 	#if SEAMLESS_RESTART_PATCH
   1859 	restoremonitorstate(m);
   1860 	#endif // SEAMLESS_RESTART_PATCH
   1861 
   1862 	#if INSETS_PATCH
   1863 	m->inset = default_inset;
   1864 	#endif // INSETS_PATCH
   1865 	return m;
   1866 }
   1867 
   1868 void
   1869 destroynotify(XEvent *e)
   1870 {
   1871 	Client *c;
   1872 	#if BAR_ANYBAR_PATCH
   1873 	Monitor *m;
   1874 	Bar *bar;
   1875 	#endif // BAR_ANYBAR_PATCH
   1876 	XDestroyWindowEvent *ev = &e->xdestroywindow;
   1877 
   1878 	if ((c = wintoclient(ev->window)))
   1879 		unmanage(c, 1);
   1880 	#if SWALLOW_PATCH
   1881 	else if ((c = swallowingclient(ev->window)))
   1882 		unmanage(c->swallowing, 1);
   1883 	#endif // SWALLOW_PATCH
   1884 	#if BAR_SYSTRAY_PATCH
   1885 	else if (showsystray && (c = wintosystrayicon(ev->window))) {
   1886 		removesystrayicon(c);
   1887 		drawbarwin(systray->bar);
   1888 	}
   1889 	#endif // BAR_SYSTRAY_PATCH
   1890 	#if BAR_ANYBAR_PATCH
   1891 	else {
   1892 		 m = wintomon(ev->window);
   1893 		 for (bar = m->bar; bar; bar = bar->next) {
   1894 		 	if (bar->win == ev->window) {
   1895 				unmanagealtbar(ev->window);
   1896 				break;
   1897 			}
   1898 		}
   1899 	}
   1900 	#endif // BAR_ANYBAR_PATCH
   1901 }
   1902 
   1903 void
   1904 detach(Client *c)
   1905 {
   1906 	Client **tc;
   1907 	#if SEAMLESS_RESTART_PATCH
   1908 	c->idx = 0;
   1909 	#endif // SEAMLESS_RESTART_PATCH
   1910 	#if FOCUSMASTER_RETURN_PATCH
   1911 	for (int i = 1; i < NUMTAGS; i++)
   1912 		if (c == c->mon->tagmarked[i])
   1913 			c->mon->tagmarked[i] = NULL;
   1914 	#endif // FOCUSMASTER_RETURN_PATCH
   1915 
   1916 	for (tc = &c->mon->clients; *tc && *tc != c; tc = &(*tc)->next);
   1917 	*tc = c->next;
   1918 	c->next = NULL;
   1919 }
   1920 
   1921 void
   1922 detachstack(Client *c)
   1923 {
   1924 	Client **tc, *t;
   1925 
   1926 	for (tc = &c->mon->stack; *tc && *tc != c; tc = &(*tc)->snext);
   1927 	*tc = c->snext;
   1928 
   1929 	if (c == c->mon->sel) {
   1930 		for (t = c->mon->stack; t && !ISVISIBLE(t); t = t->snext);
   1931 		c->mon->sel = t;
   1932 	}
   1933 	c->snext = NULL;
   1934 }
   1935 
   1936 Monitor *
   1937 dirtomon(int dir)
   1938 {
   1939 	Monitor *m = NULL;
   1940 
   1941 	if (dir > 0) {
   1942 		if (!(m = selmon->next))
   1943 			m = mons;
   1944 	} else if (selmon == mons)
   1945 		for (m = mons; m->next; m = m->next);
   1946 	else
   1947 		for (m = mons; m->next != selmon; m = m->next);
   1948 	return m;
   1949 }
   1950 
   1951 void
   1952 drawbar(Monitor *m)
   1953 {
   1954 	Bar *bar;
   1955 	
   1956 	#if !BAR_FLEXWINTITLE_PATCH
   1957 	if (m->showbar)
   1958 	#endif // BAR_FLEXWINTITLE_PATCH
   1959 		for (bar = m->bar; bar; bar = bar->next)
   1960 			drawbarwin(bar);
   1961 }
   1962 
   1963 void
   1964 drawbars(void)
   1965 {
   1966 	Monitor *m;
   1967 	for (m = mons; m; m = m->next)
   1968 		drawbar(m);
   1969 }
   1970 
   1971 void
   1972 drawbarwin(Bar *bar)
   1973 {
   1974 	if (!bar || !bar->win || bar->external)
   1975 		return;
   1976 	int r, w, total_drawn = 0;
   1977 	int rx, lx, rw, lw; // bar size, split between left and right if a center module is added
   1978 	const BarRule *br;
   1979 
   1980 	if (bar->borderpx) {
   1981 		#if BAR_BORDER_COLBG_PATCH
   1982 		XSetForeground(drw->dpy, drw->gc, scheme[bar->borderscheme][ColBg].pixel);
   1983 		#else
   1984 		XSetForeground(drw->dpy, drw->gc, scheme[bar->borderscheme][ColBorder].pixel);
   1985 		#endif // BAR_BORDER_COLBG_PATCH
   1986 		XFillRectangle(drw->dpy, drw->drawable, drw->gc, 0, 0, bar->bw, bar->bh);
   1987 	}
   1988 
   1989 	BarArg warg = { 0 };
   1990 	BarArg darg  = { 0 };
   1991 	warg.h = bar->bh - 2 * bar->borderpx;
   1992 
   1993 	rw = lw = bar->bw - 2 * bar->borderpx;
   1994 	rx = lx = bar->borderpx;
   1995 
   1996 	drw_setscheme(drw, scheme[SchemeNorm]);
   1997 	drw_rect(drw, lx, bar->borderpx, lw, bar->bh - 2 * bar->borderpx, 1, 1);
   1998 	for (r = 0; r < LENGTH(barrules); r++) {
   1999 		br = &barrules[r];
   2000 		if (br->bar != bar->idx || !br->widthfunc || (br->monitor == 'A' && bar->mon != selmon))
   2001 			continue;
   2002 		if (br->monitor != 'A' && br->monitor != -1 && br->monitor != bar->mon->num)
   2003 			continue;
   2004 		drw_setscheme(drw, scheme[SchemeNorm]);
   2005 		warg.w = (br->alignment < BAR_ALIGN_RIGHT_LEFT ? lw : rw);
   2006 
   2007 		w = br->widthfunc(bar, &warg);
   2008 		w = MIN(warg.w, w);
   2009 
   2010 		if (lw <= 0) { // if left is exhausted then switch to right side, and vice versa
   2011 			lw = rw;
   2012 			lx = rx;
   2013 		} else if (rw <= 0) {
   2014 			rw = lw;
   2015 			rx = lx;
   2016 		}
   2017 
   2018 		switch(br->alignment) {
   2019 		default:
   2020 		case BAR_ALIGN_NONE:
   2021 		case BAR_ALIGN_LEFT_LEFT:
   2022 		case BAR_ALIGN_LEFT:
   2023 			bar->x[r] = lx;
   2024 			if (lx == rx) {
   2025 				rx += w;
   2026 				rw -= w;
   2027 			}
   2028 			lx += w;
   2029 			lw -= w;
   2030 			break;
   2031 		case BAR_ALIGN_LEFT_RIGHT:
   2032 		case BAR_ALIGN_RIGHT:
   2033 			bar->x[r] = lx + lw - w;
   2034 			if (lx == rx)
   2035 				rw -= w;
   2036 			lw -= w;
   2037 			break;
   2038 		case BAR_ALIGN_LEFT_CENTER:
   2039 		case BAR_ALIGN_CENTER:
   2040 			bar->x[r] = lx + lw / 2 - w / 2;
   2041 			if (lx == rx) {
   2042 				rw = rx + rw - bar->x[r] - w;
   2043 				rx = bar->x[r] + w;
   2044 			}
   2045 			lw = bar->x[r] - lx;
   2046 			break;
   2047 		case BAR_ALIGN_RIGHT_LEFT:
   2048 			bar->x[r] = rx;
   2049 			if (lx == rx) {
   2050 				lx += w;
   2051 				lw -= w;
   2052 			}
   2053 			rx += w;
   2054 			rw -= w;
   2055 			break;
   2056 		case BAR_ALIGN_RIGHT_RIGHT:
   2057 			bar->x[r] = rx + rw - w;
   2058 			if (lx == rx)
   2059 				lw -= w;
   2060 			rw -= w;
   2061 			break;
   2062 		case BAR_ALIGN_RIGHT_CENTER:
   2063 			bar->x[r] = rx + rw / 2 - w / 2;
   2064 			if (lx == rx) {
   2065 				lw = lx + lw - bar->x[r] + w;
   2066 				lx = bar->x[r] + w;
   2067 			}
   2068 			rw = bar->x[r] - rx;
   2069 			break;
   2070 		}
   2071 		bar->w[r] = w;
   2072 		darg.x = bar->x[r];
   2073 		darg.y = bar->borderpx;
   2074 		darg.h = bar->bh - 2 * bar->borderpx;
   2075 		darg.w = bar->w[r];
   2076 		if (br->drawfunc)
   2077 			total_drawn += br->drawfunc(bar, &darg);
   2078 	}
   2079 
   2080 	if (total_drawn == 0 && bar->showbar) {
   2081 		bar->showbar = 0;
   2082 		updatebarpos(bar->mon);
   2083 		XMoveResizeWindow(dpy, bar->win, bar->bx, bar->by, bar->bw, bar->bh);
   2084 		arrange(bar->mon);
   2085 	}
   2086 	else if (total_drawn > 0 && !bar->showbar) {
   2087 		bar->showbar = 1;
   2088 		updatebarpos(bar->mon);
   2089 		XMoveResizeWindow(dpy, bar->win, bar->bx, bar->by, bar->bw, bar->bh);
   2090 		drw_map(drw, bar->win, 0, 0, bar->bw, bar->bh);
   2091 		arrange(bar->mon);
   2092 	} else
   2093 		drw_map(drw, bar->win, 0, 0, bar->bw, bar->bh);
   2094 }
   2095 
   2096 #if !FOCUSONCLICK_PATCH
   2097 void
   2098 enternotify(XEvent *e)
   2099 {
   2100 	Client *c;
   2101 	#if LOSEFULLSCREEN_PATCH
   2102 	Client *sel;
   2103 	#endif // LOSEFULLSCREEN_PATCH
   2104 	Monitor *m;
   2105 	XCrossingEvent *ev = &e->xcrossing;
   2106 
   2107 	#if BANISH_PATCH
   2108 	if (cursor_hidden)
   2109 		return;
   2110 	#endif // BANISH_PATCH
   2111 
   2112 	if ((ev->mode != NotifyNormal || ev->detail == NotifyInferior) && ev->window != root)
   2113 		return;
   2114 	c = wintoclient(ev->window);
   2115 	m = c ? c->mon : wintomon(ev->window);
   2116 	if (m != selmon) {
   2117 		#if LOSEFULLSCREEN_PATCH
   2118 		sel = selmon->sel;
   2119 		selmon = m;
   2120 		unfocus(sel, 1, c);
   2121 		#else
   2122 		unfocus(selmon->sel, 1, c);
   2123 		selmon = m;
   2124 		#endif // LOSEFULLSCREEN_PATCH
   2125 	} else if (!c || c == selmon->sel)
   2126 		return;
   2127 	focus(c);
   2128 }
   2129 #endif // FOCUSONCLICK_PATCH
   2130 
   2131 void
   2132 expose(XEvent *e)
   2133 {
   2134 	Monitor *m;
   2135 	XExposeEvent *ev = &e->xexpose;
   2136 
   2137 	if (ev->count == 0 && (m = wintomon(ev->window))) {
   2138 		drawbar(m);
   2139 		#if TAB_PATCH
   2140 		drawtabs();
   2141 		#endif // TAB_PATCH
   2142 	}
   2143 }
   2144 
   2145 void
   2146 focus(Client *c)
   2147 {
   2148 	#if FOCUSFOLLOWMOUSE_PATCH
   2149 	if (!c || !ISVISIBLE(c))
   2150 		c = getpointerclient();
   2151 	#endif // FOCUSFOLLOWMOUSE_PATCH
   2152 	#if STICKY_PATCH
   2153 	if (!c || !ISVISIBLE(c))
   2154 		for (c = selmon->stack; c && (!ISVISIBLE(c) || c->issticky); c = c->snext);
   2155 	#endif // STICKY_PATCH
   2156 	if (!c || !ISVISIBLE(c))
   2157 		for (c = selmon->stack; c && !ISVISIBLE(c); c = c->snext);
   2158 	if (selmon->sel && selmon->sel != c)
   2159 		unfocus(selmon->sel, 0, c);
   2160 	if (c) {
   2161 		if (c->mon != selmon)
   2162 			selmon = c->mon;
   2163 		if (c->isurgent)
   2164 			seturgent(c, 0);
   2165 		detachstack(c);
   2166 		attachstack(c);
   2167 		grabbuttons(c, 1);
   2168 		#if !BAR_FLEXWINTITLE_PATCH
   2169 		#if RENAMED_SCRATCHPADS_PATCH
   2170 		if (c->scratchkey != 0 && c->isfloating)
   2171 			XSetWindowBorder(dpy, c->win, scheme[SchemeScratchSel][ColFloat].pixel);
   2172 		else if (c->scratchkey != 0)
   2173 			XSetWindowBorder(dpy, c->win, scheme[SchemeScratchSel][ColBorder].pixel);
   2174 		else if (c->isfloating)
   2175 			XSetWindowBorder(dpy, c->win, scheme[SchemeSel][ColFloat].pixel);
   2176 		else
   2177 			XSetWindowBorder(dpy, c->win, scheme[SchemeSel][ColBorder].pixel);
   2178 		#else
   2179 		if (c->isfloating)
   2180 			XSetWindowBorder(dpy, c->win, scheme[SchemeSel][ColFloat].pixel);
   2181 		else
   2182 			XSetWindowBorder(dpy, c->win, scheme[SchemeSel][ColBorder].pixel);
   2183 		#endif // RENAMED_SCRATCHPADS_PATCH
   2184 		#endif // BAR_FLEXWINTITLE_PATCH
   2185 		setfocus(c);
   2186 	} else {
   2187 		#if NODMENU_PATCH
   2188 		XSetInputFocus(dpy, selmon->bar && selmon->bar->win ? selmon->bar->win : root, RevertToPointerRoot, CurrentTime);
   2189 		#else
   2190 		XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime);
   2191 		#endif // NODMENU_PATCH
   2192 		XDeleteProperty(dpy, root, netatom[NetActiveWindow]);
   2193 	}
   2194 	selmon->sel = c;
   2195 	drawbars();
   2196 
   2197 	#if ON_EMPTY_KEYS_PATCH
   2198 	if ((isempty && selmon->sel) || (!isempty && !selmon->sel)) {
   2199 		isempty = !isempty;
   2200 		grabkeys();
   2201 	}
   2202 	#endif // ON_EMPTY_KEYS_PATCH
   2203 }
   2204 
   2205 /* there are some broken focus acquiring clients needing extra handling */
   2206 void
   2207 focusin(XEvent *e)
   2208 {
   2209 	XFocusChangeEvent *ev = &e->xfocus;
   2210 
   2211 	if (selmon->sel && ev->window != selmon->sel->win)
   2212 		setfocus(selmon->sel);
   2213 }
   2214 
   2215 void
   2216 focusmon(const Arg *arg)
   2217 {
   2218 	Monitor *m;
   2219 	#if LOSEFULLSCREEN_PATCH
   2220 	Client *sel;
   2221 	#endif // LOSEFULLSCREEN_PATCH
   2222 
   2223 	if (!mons->next)
   2224 		return;
   2225 	if ((m = dirtomon(arg->i)) == selmon)
   2226 		return;
   2227 	#if LOSEFULLSCREEN_PATCH
   2228 	sel = selmon->sel;
   2229 	selmon = m;
   2230 	unfocus(sel, 0, NULL);
   2231 	#else
   2232 	unfocus(selmon->sel, 0, NULL);
   2233 	selmon = m;
   2234 	#endif // LOSEFULLSCREEN_PATCH
   2235 	focus(NULL);
   2236 	#if WARP_PATCH
   2237 	warp(selmon->sel);
   2238 	#endif // WARP_PATCH
   2239 }
   2240 
   2241 #if !STACKER_PATCH
   2242 void
   2243 focusstack(const Arg *arg)
   2244 {
   2245 	Client *c = NULL, *i;
   2246 
   2247 	#if LOSEFULLSCREEN_PATCH
   2248 	if (!selmon->sel)
   2249 		return;
   2250 	#elif FAKEFULLSCREEN_CLIENT_PATCH && !FAKEFULLSCREEN_PATCH
   2251 	if (!selmon->sel || (selmon->sel->isfullscreen && !selmon->sel->fakefullscreen))
   2252 		return;
   2253 	#else
   2254 	if (!selmon->sel || (selmon->sel->isfullscreen && lockfullscreen))
   2255 		return;
   2256 	#endif // LOSEFULLSCREEN_PATCH
   2257 	#if BAR_WINTITLEACTIONS_PATCH
   2258 	if (arg->i > 0) {
   2259 		for (c = selmon->sel->next; c && (!ISVISIBLE(c) || (arg->i == 1 && HIDDEN(c))); c = c->next);
   2260 		if (!c)
   2261 			for (c = selmon->clients; c && (!ISVISIBLE(c) || (arg->i == 1 && HIDDEN(c))); c = c->next);
   2262 	} else {
   2263 		for (i = selmon->clients; i != selmon->sel; i = i->next)
   2264 			if (ISVISIBLE(i) && !(arg->i == -1 && HIDDEN(i)))
   2265 				c = i;
   2266 		if (!c)
   2267 			for (; i; i = i->next)
   2268 				if (ISVISIBLE(i) && !(arg->i == -1 && HIDDEN(i)))
   2269 					c = i;
   2270 	}
   2271 	#else
   2272 	if (arg->i > 0) {
   2273 		for (c = selmon->sel->next; c && !ISVISIBLE(c); c = c->next);
   2274 		if (!c)
   2275 			for (c = selmon->clients; c && !ISVISIBLE(c); c = c->next);
   2276 	} else {
   2277 		for (i = selmon->clients; i != selmon->sel; i = i->next)
   2278 			if (ISVISIBLE(i))
   2279 				c = i;
   2280 		if (!c)
   2281 			for (; i; i = i->next)
   2282 				if (ISVISIBLE(i))
   2283 					c = i;
   2284 	}
   2285 	#endif // BAR_WINTITLEACTIONS_PATCH
   2286 	if (c) {
   2287 		focus(c);
   2288 		restack(selmon);
   2289 	}
   2290 }
   2291 #endif // STACKER_PATCH
   2292 
   2293 Atom
   2294 getatomprop(Client *c, Atom prop, Atom req)
   2295 {
   2296 	int di;
   2297 	unsigned long nitems, dl;
   2298 	unsigned char *p = NULL;
   2299 	Atom da, atom = None;
   2300 
   2301 	#if BAR_SYSTRAY_PATCH
   2302 	if (prop == xatom[XembedInfo])
   2303 		req = xatom[XembedInfo];
   2304 	#endif // BAR_SYSTRAY_PATCH
   2305 
   2306 	/* FIXME getatomprop should return the number of items and a pointer to
   2307 	 * the stored data instead of this workaround */
   2308 	if (XGetWindowProperty(dpy, c->win, prop, 0L, sizeof atom, False, req,
   2309 		&da, &di, &nitems, &dl, &p) == Success && p) {
   2310 		if (nitems > 0)
   2311 			atom = *(Atom *)p;
   2312 		#if BAR_SYSTRAY_PATCH
   2313 		if (da == xatom[XembedInfo] && dl == 2)
   2314 			atom = ((Atom *)p)[1];
   2315 		#endif // BAR_SYSTRAY_PATCH
   2316 		XFree(p);
   2317 	}
   2318 	return atom;
   2319 }
   2320 
   2321 int
   2322 getrootptr(int *x, int *y)
   2323 {
   2324 	int di;
   2325 	unsigned int dui;
   2326 	Window dummy;
   2327 
   2328 	#if BANISH_PATCH
   2329 	if (cursor_hidden) {
   2330 		*x = mouse_x;
   2331 		*y = mouse_y;
   2332 		return 1;
   2333 	}
   2334 	#endif // BANISH_PATCH
   2335 
   2336 	return XQueryPointer(dpy, root, &dummy, &dummy, x, y, &di, &di, &dui);
   2337 }
   2338 
   2339 long
   2340 getstate(Window w)
   2341 {
   2342 	int format;
   2343 	long result = -1;
   2344 	unsigned char *p = NULL;
   2345 	unsigned long n, extra;
   2346 	Atom real;
   2347 
   2348 	if (XGetWindowProperty(dpy, w, wmatom[WMState], 0L, 2L, False, wmatom[WMState],
   2349 		&real, &format, &n, &extra, (unsigned char **)&p) != Success)
   2350 		return -1;
   2351 	if (n != 0)
   2352 		result = *p;
   2353 	XFree(p);
   2354 	return result;
   2355 }
   2356 
   2357 int
   2358 gettextprop(Window w, Atom atom, char *text, unsigned int size)
   2359 {
   2360 	char **list = NULL;
   2361 	int n;
   2362 	XTextProperty name;
   2363 
   2364 	if (!text || size == 0)
   2365 		return 0;
   2366 	text[0] = '\0';
   2367 	if (!XGetTextProperty(dpy, w, &name, atom) || !name.nitems)
   2368 		return 0;
   2369 	if (name.encoding == XA_STRING) {
   2370 		strncpy(text, (char *)name.value, size - 1);
   2371 	} else if (XmbTextPropertyToTextList(dpy, &name, &list, &n) >= Success && n > 0 && *list) {
   2372 		strncpy(text, *list, size - 1);
   2373 		XFreeStringList(list);
   2374 	}
   2375 	text[size - 1] = '\0';
   2376 	XFree(name.value);
   2377 	return 1;
   2378 }
   2379 
   2380 void
   2381 grabbuttons(Client *c, int focused)
   2382 {
   2383 	updatenumlockmask();
   2384 	{
   2385 		unsigned int i, j;
   2386 		unsigned int modifiers[] = { 0, LockMask, numlockmask, numlockmask|LockMask };
   2387 		XUngrabButton(dpy, AnyButton, AnyModifier, c->win);
   2388 		if (!focused)
   2389 			XGrabButton(dpy, AnyButton, AnyModifier, c->win, False,
   2390 				BUTTONMASK, GrabModeSync, GrabModeSync, None, None);
   2391 		for (i = 0; i < LENGTH(buttons); i++)
   2392 			if (buttons[i].click == ClkClientWin
   2393 			#if NO_MOD_BUTTONS_PATCH
   2394 				&& (nomodbuttons || buttons[i].mask != 0)
   2395 			#endif // NO_MOD_BUTTONS_PATCH
   2396 			)
   2397 				for (j = 0; j < LENGTH(modifiers); j++)
   2398 					XGrabButton(dpy, buttons[i].button,
   2399 						buttons[i].mask | modifiers[j],
   2400 						c->win, False, BUTTONMASK,
   2401 						GrabModeAsync, GrabModeSync, None, None);
   2402 	}
   2403 }
   2404 
   2405 void
   2406 #if KEYMODES_PATCH
   2407 grabdefkeys(void)
   2408 #else
   2409 grabkeys(void)
   2410 #endif // KEYMODES_PATCH
   2411 {
   2412 	updatenumlockmask();
   2413 	{
   2414 		unsigned int i, j, k;
   2415 		unsigned int modifiers[] = { 0, LockMask, numlockmask, numlockmask|LockMask };
   2416 		int start, end, skip;
   2417 		KeySym *syms;
   2418 
   2419 		XUngrabKey(dpy, AnyKey, AnyModifier, root);
   2420 		XDisplayKeycodes(dpy, &start, &end);
   2421 		syms = XGetKeyboardMapping(dpy, start, end - start + 1, &skip);
   2422 		if (!syms)
   2423 			return;
   2424 		for (k = start; k <= end; k++)
   2425 			for (i = 0; i < LENGTH(keys); i++)
   2426 				/* skip modifier codes, we do that ourselves */
   2427 				if (keys[i].keysym == syms[(k - start) * skip])
   2428 					for (j = 0; j < LENGTH(modifiers); j++)
   2429 						XGrabKey(dpy, k,
   2430 							 keys[i].mod | modifiers[j],
   2431 							 root, True,
   2432 							 GrabModeAsync, GrabModeAsync);
   2433 		#if ON_EMPTY_KEYS_PATCH
   2434 		if (!selmon->sel)
   2435 			for (k = start; k <= end; k++)
   2436 				for (i = 0; i < LENGTH(on_empty_keys); i++)
   2437 					/* skip modifier codes, we do that ourselves */
   2438 					if (on_empty_keys[i].keysym == syms[(k - start) * skip])
   2439 						for (j = 0; j < LENGTH(modifiers); j++)
   2440 							XGrabKey(dpy, k,
   2441 								 on_empty_keys[i].mod | modifiers[j],
   2442 								 root, True,
   2443 								 GrabModeAsync, GrabModeAsync);
   2444 		#endif // ON_EMPTY_KEYS_PATCH
   2445 		XFree(syms);
   2446 	}
   2447 }
   2448 
   2449 void
   2450 incnmaster(const Arg *arg)
   2451 {
   2452 	#if PERTAG_PATCH
   2453 	selmon->nmaster = selmon->pertag->nmasters[selmon->pertag->curtag] = MAX(selmon->nmaster + arg->i, 0);
   2454 	#else
   2455 	selmon->nmaster = MAX(selmon->nmaster + arg->i, 0);
   2456 	#endif // PERTAG_PATCH
   2457 	arrange(selmon);
   2458 }
   2459 
   2460 #ifdef XINERAMA
   2461 static int
   2462 isuniquegeom(XineramaScreenInfo *unique, size_t n, XineramaScreenInfo *info)
   2463 {
   2464 	while (n--)
   2465 		if (unique[n].x_org == info->x_org && unique[n].y_org == info->y_org
   2466 		&& unique[n].width == info->width && unique[n].height == info->height)
   2467 			return 0;
   2468 	return 1;
   2469 }
   2470 #endif /* XINERAMA */
   2471 
   2472 void
   2473 #if KEYMODES_PATCH
   2474 keydefpress(XEvent *e)
   2475 #else
   2476 keypress(XEvent *e)
   2477 #endif // KEYMODES_PATCH
   2478 {
   2479 	unsigned int i;
   2480 	int keysyms_return;
   2481 	KeySym* keysym;
   2482 	XKeyEvent *ev;
   2483 
   2484 	ev = &e->xkey;
   2485 	keysym = XGetKeyboardMapping(dpy, (KeyCode)ev->keycode, 1, &keysyms_return);
   2486 	for (i = 0; i < LENGTH(keys); i++)
   2487 		if (*keysym == keys[i].keysym
   2488 				&& CLEANMASK(keys[i].mod) == CLEANMASK(ev->state)
   2489 				&& keys[i].func)
   2490 			keys[i].func(&(keys[i].arg));
   2491 	#if ON_EMPTY_KEYS_PATCH
   2492 	if (!selmon->sel)
   2493 		for (i = 0; i < LENGTH(on_empty_keys); i++)
   2494 			if (*keysym == on_empty_keys[i].keysym
   2495 					&& CLEANMASK(on_empty_keys[i].mod) == CLEANMASK(ev->state)
   2496 					&& on_empty_keys[i].func)
   2497 				on_empty_keys[i].func(&(on_empty_keys[i].arg));
   2498 	#endif // ON_EMPTY_KEYS_PATCH
   2499 	XFree(keysym);
   2500 }
   2501 
   2502 void
   2503 killclient(const Arg *arg)
   2504 {
   2505 	#if ISPERMANENT_PATCH
   2506 	if (!selmon->sel || selmon->sel->ispermanent)
   2507 	#else
   2508 	if (!selmon->sel)
   2509 	#endif // ISPERMANENT_PATCH
   2510 		return;
   2511 	#if BAR_SYSTRAY_PATCH
   2512 	if (!sendevent(selmon->sel->win, wmatom[WMDelete], NoEventMask, wmatom[WMDelete], CurrentTime, 0, 0, 0))
   2513 	#else
   2514 	if (!sendevent(selmon->sel, wmatom[WMDelete]))
   2515 	#endif // BAR_SYSTRAY_PATCH
   2516 	{
   2517 		XGrabServer(dpy);
   2518 		XSetErrorHandler(xerrordummy);
   2519 		XSetCloseDownMode(dpy, DestroyAll);
   2520 		XKillClient(dpy, selmon->sel->win);
   2521 		XSync(dpy, False);
   2522 		XSetErrorHandler(xerror);
   2523 		XUngrabServer(dpy);
   2524 		#if WARP_PATCH
   2525 		force_warp = 1;
   2526 		#endif // WARP_PATCH
   2527 	}
   2528 	#if SWAPFOCUS_PATCH && PERTAG_PATCH
   2529 	selmon->pertag->prevclient[selmon->pertag->curtag] = NULL;
   2530 	#endif // SWAPFOCUS_PATCH
   2531 }
   2532 
   2533 void
   2534 manage(Window w, XWindowAttributes *wa)
   2535 {
   2536 	Client *c, *t = NULL;
   2537 	#if SWALLOW_PATCH
   2538 	Client *term = NULL;
   2539 	#endif // SWALLOW_PATCH
   2540 	#if SEAMLESS_RESTART_PATCH
   2541 	int settings_restored;
   2542 	#endif // SEAMLESS_RESTART_PATCH
   2543 	Window trans = None;
   2544 	XWindowChanges wc;
   2545 
   2546 	c = ecalloc(1, sizeof(Client));
   2547 	c->win = w;
   2548 	#if SWALLOW_PATCH
   2549 	c->pid = winpid(w);
   2550 	#endif // SWALLOW_PATCH
   2551 	/* geometry */
   2552 	#if SAVEFLOATS_PATCH || EXRESIZE_PATCH
   2553 	c->sfx = c->sfy = c->sfw = c->sfh = -9999;
   2554 	#endif // SAVEFLOATS_PATCH | EXRESIZE_PATCH
   2555 	c->x = c->oldx = wa->x;
   2556 	c->y = c->oldy = wa->y;
   2557 	c->w = c->oldw = wa->width;
   2558 	c->h = c->oldh = wa->height;
   2559 	c->oldbw = wa->border_width;
   2560 	#if CFACTS_PATCH
   2561 	c->cfact = 1.0;
   2562 	#endif // CFACTS_PATCH
   2563 	#if SEAMLESS_RESTART_PATCH
   2564 	settings_restored = restoreclientstate(c);
   2565 	#endif // SEAMLESS_RESTART_PATCH
   2566 	#if BAR_WINICON_PATCH
   2567 	updateicon(c);
   2568 	#endif // BAR_WINICON_PATCH
   2569 	updatetitle(c);
   2570 
   2571 	#if XKB_PATCH
   2572 	/* Setting current xkb state must be before applyrules */
   2573 	if (!(c->xkb = findxkb(c->win)))
   2574 		c->xkb = createxkb(c->win);
   2575 	#endif // XKB_PATCH
   2576 
   2577 	if (XGetTransientForHint(dpy, w, &trans) && (t = wintoclient(trans))) {
   2578 		c->mon = t->mon;
   2579 		c->tags = t->tags;
   2580 		#if SETBORDERPX_PATCH
   2581 		c->bw = c->mon->borderpx;
   2582 		#else
   2583 		c->bw = borderpx;
   2584 		#endif // SETBORDERPX_PATCH
   2585 		#if CENTER_TRANSIENT_WINDOWS_BY_PARENT_PATCH
   2586 		c->x = t->x + WIDTH(t) / 2 - WIDTH(c) / 2;
   2587 		c->y = t->y + HEIGHT(t) / 2 - HEIGHT(c) / 2;
   2588 		#elif CENTER_PATCH && CENTER_TRANSIENT_WINDOWS_PATCH
   2589 		c->iscentered = 1;
   2590 		#elif CENTER_TRANSIENT_WINDOWS_PATCH
   2591 		c->x = c->mon->wx + (c->mon->ww - WIDTH(c)) / 2;
   2592 		c->y = c->mon->wy + (c->mon->wh - HEIGHT(c)) / 2;
   2593 		#elif CENTER_PATCH
   2594 		if (c->x == c->mon->wx && c->y == c->mon->wy)
   2595 			c->iscentered = 1;
   2596 		#endif // CENTER_TRANSIENT_WINDOWS_PATCH | CENTER_TRANSIENT_WINDOWS_BY_PARENT_PATCH | CENTER_PATCH
   2597 	} else {
   2598 		#if SEAMLESS_RESTART_PATCH
   2599 		if (!settings_restored || c->mon == NULL) {
   2600 			c->mon = selmon;
   2601 			settings_restored = 0;
   2602 		}
   2603 		#else
   2604 		c->mon = selmon;
   2605 		#endif // SEAMLESS_RESTART_PATCH
   2606 		#if CENTER_PATCH
   2607 		if (c->x == c->mon->wx && c->y == c->mon->wy)
   2608 			c->iscentered = 1;
   2609 		#endif // CENTER_PATCH
   2610 		#if SETBORDERPX_PATCH
   2611 		c->bw = c->mon->borderpx;
   2612 		#else
   2613 		c->bw = borderpx;
   2614 		#endif // SETBORDERPX_PATCH
   2615 		#if SEAMLESS_RESTART_PATCH
   2616 		if (!settings_restored)
   2617 			applyrules(c);
   2618 		#else
   2619 		applyrules(c);
   2620 		#endif // SEAMLESS_RESTART_PATCH
   2621 		#if SWALLOW_PATCH
   2622 		term = termforwin(c);
   2623 		if (term)
   2624 			c->mon = term->mon;
   2625 		#endif // SWALLOW_PATCH
   2626 	}
   2627 
   2628 	#if UNMANAGED_PATCH
   2629 	if (unmanaged) {
   2630 		XMapWindow(dpy, c->win);
   2631 		if (unmanaged == 1)
   2632 			XRaiseWindow(dpy, c->win);
   2633 		else if (unmanaged == 2)
   2634 			XLowerWindow(dpy, c->win);
   2635 
   2636 		updatewmhints(c);
   2637 		if (!c->neverfocus)
   2638 			XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime);
   2639 		#if BAR_SYSTRAY_PATCH
   2640 		sendevent(c->win, wmatom[WMTakeFocus], NoEventMask, wmatom[WMTakeFocus], CurrentTime, 0, 0, 0);
   2641 		#else
   2642 		sendevent(c, wmatom[WMTakeFocus]);
   2643 		#endif // BAR_SYSTRAY_PATCH
   2644 
   2645 		free(c);
   2646 		unmanaged = 0;
   2647 		return;
   2648 	}
   2649 	#endif // UNMANAGED_PATCH
   2650 
   2651 	if (c->x + WIDTH(c) > c->mon->wx + c->mon->ww)
   2652 		c->x = c->mon->wx + c->mon->ww - WIDTH(c);
   2653 	if (c->y + HEIGHT(c) > c->mon->wy + c->mon->wh)
   2654 		c->y = c->mon->wy + c->mon->wh - HEIGHT(c);
   2655 	c->x = MAX(c->x, c->mon->wx);
   2656 	c->y = MAX(c->y, c->mon->wy);
   2657 
   2658 	wc.border_width = c->bw;
   2659 	XConfigureWindow(dpy, w, CWBorderWidth, &wc);
   2660 	#if !BAR_FLEXWINTITLE_PATCH
   2661 	if (c->isfloating)
   2662 		XSetWindowBorder(dpy, w, scheme[SchemeNorm][ColFloat].pixel);
   2663 	else
   2664 		XSetWindowBorder(dpy, w, scheme[SchemeNorm][ColBorder].pixel);
   2665 	#endif // BAR_FLEXWINTITLE_PATCH
   2666 	configure(c); /* propagates border_width, if size doesn't change */
   2667 	updatesizehints(c);
   2668 	updatewmhints(c);
   2669 	#if DECORATION_HINTS_PATCH
   2670 	updatemotifhints(c);
   2671 	#endif // DECORATION_HINTS_PATCH
   2672 
   2673 	#if CENTER_PATCH && SAVEFLOATS_PATCH || CENTER_PATCH && EXRESIZE_PATCH
   2674 	if (c->iscentered) {
   2675 		c->sfx = c->x = c->mon->wx + (c->mon->ww - WIDTH(c)) / 2;
   2676 		c->sfy = c->y = c->mon->wy + (c->mon->wh - HEIGHT(c)) / 2;
   2677 	}
   2678 	#elif CENTER_PATCH
   2679 	if (c->iscentered) {
   2680 		c->x = c->mon->wx + (c->mon->ww - WIDTH(c)) / 2;
   2681 		c->y = c->mon->wy + (c->mon->wh - HEIGHT(c)) / 2;
   2682 	}
   2683 	#elif ALWAYSCENTER_PATCH && SAVEFLOATS_PATCH || ALWAYSCENTER_PATCH && EXRESIZE_PATCH
   2684 	c->sfx = c->x = c->mon->wx + (c->mon->ww - WIDTH(c)) / 2;
   2685 	c->sfy = c->y = c->mon->wy + (c->mon->wh - HEIGHT(c)) / 2;
   2686 	#elif ALWAYSCENTER_PATCH
   2687 	c->x = c->mon->wx + (c->mon->ww - WIDTH(c)) / 2;
   2688 	c->y = c->mon->wy + (c->mon->wh - HEIGHT(c)) / 2;
   2689 	#endif // CENTER_PATCH / ALWAYSCENTER_PATCH / SAVEFLOATS_PATCH
   2690 	#if SAVEFLOATS_PATCH || EXRESIZE_PATCH
   2691 	if (c->sfw == -9999) {
   2692 		c->sfw = c->w;
   2693 		c->sfh = c->h;
   2694 	}
   2695 	#endif // SAVEFLOATS_PATCH / EXRESIZE_PATCH
   2696 
   2697 	if (getatomprop(c, netatom[NetWMState], XA_ATOM) == netatom[NetWMFullscreen])
   2698 		setfullscreen(c, 1);
   2699 
   2700 	XSelectInput(dpy, w, EnterWindowMask|FocusChangeMask|PropertyChangeMask|StructureNotifyMask);
   2701 	grabbuttons(c, 0);
   2702 	#if MAXIMIZE_PATCH
   2703 	c->wasfloating = 0;
   2704 	c->ismax = 0;
   2705 	#elif EXRESIZE_PATCH
   2706 	c->wasfloating = 0;
   2707 	#endif // MAXIMIZE_PATCH / EXRESIZE_PATCH
   2708 
   2709 	if (!c->isfloating)
   2710 		c->isfloating = c->oldstate = trans != None || c->isfixed;
   2711 	if (c->isfloating) {
   2712 		XRaiseWindow(dpy, c->win);
   2713 		XSetWindowBorder(dpy, w, scheme[SchemeNorm][ColFloat].pixel);
   2714 	}
   2715 	#if ATTACHABOVE_PATCH || ATTACHASIDE_PATCH || ATTACHBELOW_PATCH || ATTACHBOTTOM_PATCH || SEAMLESS_RESTART_PATCH
   2716 	attachx(c);
   2717 	#else
   2718 	attach(c);
   2719 	#endif
   2720 	attachstack(c);
   2721 	XChangeProperty(dpy, root, netatom[NetClientList], XA_WINDOW, 32, PropModeAppend,
   2722 		(unsigned char *) &(c->win), 1);
   2723 	#if NET_CLIENT_LIST_STACKING_PATCH
   2724 	XChangeProperty(dpy, root, netatom[NetClientListStacking], XA_WINDOW, 32, PropModePrepend,
   2725 		(unsigned char *) &(c->win), 1);
   2726 	#endif // NET_CLIENT_LIST_STACKING_PATCH
   2727 	XMoveResizeWindow(dpy, c->win, c->x + 2 * sw, c->y, c->w, c->h); /* some windows require this */
   2728 
   2729 	#if BAR_WINTITLEACTIONS_PATCH
   2730 	if (!HIDDEN(c))
   2731 		setclientstate(c, NormalState);
   2732 	#else
   2733 	setclientstate(c, NormalState);
   2734 	#endif // BAR_WINTITLEACTIONS_PATCH
   2735 	if (c->mon == selmon)
   2736 		unfocus(selmon->sel, 0, c);
   2737 	c->mon->sel = c;
   2738 	#if SWALLOW_PATCH
   2739 	if (!(term && swallow(term, c))) {
   2740 		#if RIODRAW_PATCH
   2741 		if (riopid && (!riodraw_matchpid || isdescprocess(riopid, c->pid))) {
   2742 			if (riodimensions[3] != -1)
   2743 				rioposition(c, riodimensions[0], riodimensions[1], riodimensions[2], riodimensions[3]);
   2744 			else {
   2745 				killclient(&((Arg) { .v = c }));
   2746 				return;
   2747 			}
   2748 		}
   2749 		#endif // RIODRAW_PATCH
   2750 		arrange(c->mon);
   2751 		#if BAR_WINTITLEACTIONS_PATCH
   2752 		if (!HIDDEN(c))
   2753 			XMapWindow(dpy, c->win);
   2754 		#else
   2755 		XMapWindow(dpy, c->win);
   2756 		#endif // BAR_WINTITLEACTIONS_PATCH
   2757 	}
   2758 	#else
   2759 	#if RIODRAW_PATCH
   2760 	if (riopid) {
   2761 		if (riodimensions[3] != -1)
   2762 			rioposition(c, riodimensions[0], riodimensions[1], riodimensions[2], riodimensions[3]);
   2763 		else {
   2764 			killclient(&((Arg) { .v = c }));
   2765 			return;
   2766 		}
   2767 	}
   2768 	#endif // RIODRAW_PATCH
   2769 	arrange(c->mon);
   2770 	#if BAR_WINTITLEACTIONS_PATCH
   2771 	if (!HIDDEN(c))
   2772 		XMapWindow(dpy, c->win);
   2773 	#else
   2774 	XMapWindow(dpy, c->win);
   2775 	#endif // BAR_WINTITLEACTIONS_PATCH
   2776 	#endif // SWALLOW_PATCH
   2777 	focus(NULL);
   2778 
   2779 	#if BAR_EWMHTAGS_PATCH
   2780 	setfloatinghint(c);
   2781 	#endif // BAR_EWMHTAGS_PATCH
   2782 }
   2783 
   2784 void
   2785 mappingnotify(XEvent *e)
   2786 {
   2787 	XMappingEvent *ev = &e->xmapping;
   2788 
   2789 	XRefreshKeyboardMapping(ev);
   2790 	if (ev->request == MappingKeyboard)
   2791 		grabkeys();
   2792 }
   2793 
   2794 void
   2795 maprequest(XEvent *e)
   2796 {
   2797 	static XWindowAttributes wa;
   2798 	XMapRequestEvent *ev = &e->xmaprequest;
   2799 
   2800 	#if BAR_SYSTRAY_PATCH
   2801 	Client *i;
   2802 	if (showsystray && systray && (i = wintosystrayicon(ev->window))) {
   2803 		sendevent(i->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_WINDOW_ACTIVATE, 0, systray->win, XEMBED_EMBEDDED_VERSION);
   2804 		drawbarwin(systray->bar);
   2805 	}
   2806 	#endif // BAR_SYSTRAY_PATCH
   2807 
   2808 	if (!XGetWindowAttributes(dpy, ev->window, &wa) || wa.override_redirect)
   2809 		return;
   2810 	#if BAR_ANYBAR_PATCH
   2811 	if (wmclasscontains(ev->window, altbarclass, ""))
   2812 		managealtbar(ev->window, &wa);
   2813 	else
   2814 	#endif // BAR_ANYBAR_PATCH
   2815 	if (!wintoclient(ev->window))
   2816 		manage(ev->window, &wa);
   2817 }
   2818 
   2819 void
   2820 motionnotify(XEvent *e)
   2821 {
   2822 	#if !FOCUSONCLICK_PATCH
   2823 	static Monitor *mon = NULL;
   2824 	Monitor *m;
   2825 	#if LOSEFULLSCREEN_PATCH
   2826 	Client *sel;
   2827 	#endif // LOSEFULLSCREEN_PATCH
   2828 	#endif // FOCUSONCLICK_PATCH
   2829 	Bar *bar;
   2830 	XMotionEvent *ev = &e->xmotion;
   2831 
   2832 	if ((bar = wintobar(ev->window))) {
   2833 		barhover(e, bar);
   2834 		return;
   2835 	}
   2836 
   2837 	#if BAR_TAGPREVIEW_PATCH
   2838 	if (selmon->previewshow != 0)
   2839 		hidetagpreview(selmon);
   2840 	#endif // BAR_TAGPREVIEW_PATCH
   2841 
   2842 	#if !FOCUSONCLICK_PATCH
   2843 	if (ev->window != root)
   2844 		return;
   2845 	if ((m = recttomon(ev->x_root, ev->y_root, 1, 1)) != mon && mon) {
   2846 		#if LOSEFULLSCREEN_PATCH
   2847 		sel = selmon->sel;
   2848 		selmon = m;
   2849 		unfocus(sel, 1, NULL);
   2850 		#else
   2851 		unfocus(selmon->sel, 1, NULL);
   2852 		selmon = m;
   2853 		#endif // LOSEFULLSCREEN_PATCH
   2854 		focus(NULL);
   2855 	}
   2856 	mon = m;
   2857 	#endif // FOCUSONCLICK_PATCH
   2858 }
   2859 
   2860 void
   2861 movemouse(const Arg *arg)
   2862 {
   2863 	int x, y, ocx, ocy, nx, ny;
   2864 	Client *c;
   2865 	Monitor *m;
   2866 	XEvent ev;
   2867 	Time lasttime = 0;
   2868 
   2869 	if (!(c = selmon->sel))
   2870 		return;
   2871 	#if !FAKEFULLSCREEN_PATCH
   2872 	#if FAKEFULLSCREEN_CLIENT_PATCH && !FAKEFULLSCREEN_PATCH
   2873 	if (c->isfullscreen && c->fakefullscreen != 1) /* no support moving fullscreen windows by mouse */
   2874 		return;
   2875 	#else
   2876 	if (c->isfullscreen) /* no support moving fullscreen windows by mouse */
   2877 		return;
   2878 	#endif // FAKEFULLSCREEN_CLIENT_PATCH
   2879 	#endif // FAKEFULLSCREEN_PATCH
   2880 	restack(selmon);
   2881 	nx = ocx = c->x;
   2882 	ny = ocy = c->y;
   2883 	if (XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync,
   2884 		None, cursor[CurMove]->cursor, CurrentTime) != GrabSuccess)
   2885 		return;
   2886 	if (!getrootptr(&x, &y))
   2887 		return;
   2888 	ignoreconfigurerequests = 1;
   2889 	do {
   2890 		XMaskEvent(dpy, MOUSEMASK|ExposureMask|SubstructureRedirectMask, &ev);
   2891 		switch(ev.type) {
   2892 		case ConfigureRequest:
   2893 		case Expose:
   2894 		case MapRequest:
   2895 			handler[ev.type](&ev);
   2896 			break;
   2897 		case MotionNotify:
   2898 			if ((ev.xmotion.time - lasttime) <= (1000 / refreshrate))
   2899 				continue;
   2900 			lasttime = ev.xmotion.time;
   2901 
   2902 			nx = ocx + (ev.xmotion.x - x);
   2903 			ny = ocy + (ev.xmotion.y - y);
   2904 			if (abs(selmon->wx - nx) < snap)
   2905 				nx = selmon->wx;
   2906 			else if (abs((selmon->wx + selmon->ww) - (nx + WIDTH(c))) < snap)
   2907 				nx = selmon->wx + selmon->ww - WIDTH(c);
   2908 			if (abs(selmon->wy - ny) < snap)
   2909 				ny = selmon->wy;
   2910 			else if (abs((selmon->wy + selmon->wh) - (ny + HEIGHT(c))) < snap)
   2911 				ny = selmon->wy + selmon->wh - HEIGHT(c);
   2912 			if (!c->isfloating && selmon->lt[selmon->sellt]->arrange
   2913 			&& (abs(nx - c->x) > snap || abs(ny - c->y) > snap)) {
   2914 				#if SAVEFLOATS_PATCH || EXRESIZE_PATCH
   2915 				c->sfx = -9999; // disable savefloats when using movemouse
   2916 				#endif // SAVEFLOATS_PATCH | EXRESIZE_PATCH
   2917 				togglefloating(NULL);
   2918 			}
   2919 			if (!selmon->lt[selmon->sellt]->arrange || c->isfloating) {
   2920 				resize(c, nx, ny, c->w, c->h, 1);
   2921 			}
   2922 			break;
   2923 		}
   2924 	} while (ev.type != ButtonRelease);
   2925 
   2926 	XUngrabPointer(dpy, CurrentTime);
   2927 	if ((m = recttomon(c->x, c->y, c->w, c->h)) != selmon) {
   2928 		#if SCRATCHPADS_PATCH && !RENAMED_SCRATCHPADS_PATCH
   2929 		if (c->tags & SPTAGMASK) {
   2930 			c->mon->tagset[c->mon->seltags] ^= (c->tags & SPTAGMASK);
   2931 			m->tagset[m->seltags] |= (c->tags & SPTAGMASK);
   2932 		}
   2933 		#endif // SCRATCHPADS_PATCH
   2934 		sendmon(c, m);
   2935 		selmon = m;
   2936 		focus(NULL);
   2937 	}
   2938 	#if SAVEFLOATS_PATCH || EXRESIZE_PATCH
   2939 	/* save last known float coordinates */
   2940 	if (!selmon->lt[selmon->sellt]->arrange || c->isfloating) {
   2941 		c->sfx = nx;
   2942 		c->sfy = ny;
   2943 	}
   2944 	#endif // SAVEFLOATS_PATCH / EXRESIZE_PATCH
   2945 	ignoreconfigurerequests = 0;
   2946 }
   2947 
   2948 Client *
   2949 nexttiled(Client *c)
   2950 {
   2951 	#if BAR_WINTITLEACTIONS_PATCH
   2952 	for (; c && (c->isfloating || !ISVISIBLE(c) || HIDDEN(c)); c = c->next);
   2953 	#else
   2954 	for (; c && (c->isfloating || !ISVISIBLE(c)); c = c->next);
   2955 	#endif // BAR_WINTITLEACTIONS_PATCH
   2956 	return c;
   2957 }
   2958 
   2959 #if NOBORDER_PATCH
   2960 int
   2961 noborder(Client *c)
   2962 {
   2963 	int monocle_layout = 0;
   2964 
   2965 	#if MONOCLE_LAYOUT
   2966 	if (&monocle == c->mon->lt[c->mon->sellt]->arrange)
   2967 		monocle_layout = 1;
   2968 	#endif // MONOCLE_LAYOUT
   2969 
   2970 	#if DECK_LAYOUT
   2971 	if (&deck == c->mon->lt[c->mon->sellt]->arrange && c->mon->nmaster == 0)
   2972 		monocle_layout = 1;
   2973 	#endif // DECK_LAYOUT
   2974 
   2975 	#if FLEXTILE_DELUXE_LAYOUT
   2976 	if (&flextile == c->mon->lt[c->mon->sellt]->arrange && (
   2977 		(c->mon->ltaxis[LAYOUT] == NO_SPLIT && c->mon->ltaxis[MASTER] == MONOCLE) ||
   2978 		(c->mon->ltaxis[STACK] == MONOCLE && c->mon->nmaster == 0)
   2979 	)) {
   2980 		monocle_layout = 1;
   2981 	}
   2982 	#endif //FLEXTILE_DELUXE_LAYOUT
   2983 
   2984 	if (!monocle_layout && (nexttiled(c->mon->clients) != c || nexttiled(c->next)))
   2985 		return 0;
   2986 
   2987 	if (c->isfloating)
   2988 		return 0;
   2989 
   2990 	if (!c->mon->lt[c->mon->sellt]->arrange)
   2991 		return 0;
   2992 
   2993 	#if FAKEFULLSCREEN_CLIENT_PATCH && !FAKEFULLSCREEN_PATCH
   2994 	if (c->fakefullscreen != 1 && c->isfullscreen)
   2995 		return 0;
   2996 	#elif !FAKEFULLSCREEN_PATCH
   2997 	if (c->isfullscreen)
   2998 		return 0;
   2999 	#endif // FAKEFULLSCREEN_CLIENT_PATCH
   3000 
   3001 	return 1;
   3002 }
   3003 #endif // NOBORDER_PATCH
   3004 
   3005 #if !ZOOMSWAP_PATCH || TAGINTOSTACK_ALLMASTER_PATCH || TAGINTOSTACK_ONEMASTER_PATCH
   3006 void
   3007 pop(Client *c)
   3008 {
   3009 	#if FOCUSMASTER_RETURN_PATCH
   3010 	int i;
   3011 	for (i = 0; !(selmon->tagset[selmon->seltags] & 1 << i); i++);
   3012 	i++;
   3013 
   3014 	c->mon->tagmarked[i] = nexttiled(c->mon->clients);
   3015 	#endif // FOCUSMASTER_RETURN_PATCH
   3016 	detach(c);
   3017 	attach(c);
   3018 	focus(c);
   3019 	arrange(c->mon);
   3020 }
   3021 #endif // !ZOOMSWAP_PATCH / TAGINTOSTACK_ALLMASTER_PATCH / TAGINTOSTACK_ONEMASTER_PATCH
   3022 
   3023 void
   3024 propertynotify(XEvent *e)
   3025 {
   3026 	Client *c;
   3027 	Window trans;
   3028 	XPropertyEvent *ev = &e->xproperty;
   3029 
   3030 	#if BAR_SYSTRAY_PATCH
   3031 	if (showsystray && (c = wintosystrayicon(ev->window))) {
   3032 		if (ev->atom == XA_WM_NORMAL_HINTS) {
   3033 			updatesizehints(c);
   3034 			updatesystrayicongeom(c, c->w, c->h);
   3035 		}
   3036 		else
   3037 			updatesystrayiconstate(c, ev);
   3038 		drawbarwin(systray->bar);
   3039 	}
   3040 	#endif // BAR_SYSTRAY_PATCH
   3041 
   3042 	if ((ev->window == root) && (ev->atom == XA_WM_NAME)) {
   3043 		#if DWMC_PATCH || FSIGNAL_PATCH
   3044 		if (!fake_signal())
   3045 			updatestatus();
   3046 		#else
   3047 		updatestatus();
   3048 		#endif // DWMC_PATCH / FSIGNAL_PATCH
   3049 	} else if (ev->state == PropertyDelete) {
   3050 		return; /* ignore */
   3051 	} else if ((c = wintoclient(ev->window))) {
   3052 		switch(ev->atom) {
   3053 		default: break;
   3054 		case XA_WM_TRANSIENT_FOR:
   3055 			if (!c->isfloating && (XGetTransientForHint(dpy, c->win, &trans)) &&
   3056 				(c->isfloating = (wintoclient(trans)) != NULL))
   3057 				arrange(c->mon);
   3058 			break;
   3059 		case XA_WM_NORMAL_HINTS:
   3060 			c->hintsvalid = 0;
   3061 			break;
   3062 		case XA_WM_HINTS:
   3063 			updatewmhints(c);
   3064 			if (c->isurgent)
   3065 				drawbars();
   3066 			#if TAB_PATCH
   3067 			drawtabs();
   3068 			#endif // TAB_PATCH
   3069 			break;
   3070 		}
   3071 		if (ev->atom == XA_WM_NAME || ev->atom == netatom[NetWMName]) {
   3072 			updatetitle(c);
   3073 			if (c == c->mon->sel)
   3074 				drawbar(c->mon);
   3075 			#if TAB_PATCH
   3076 			drawtab(c->mon);
   3077 			#endif // TAB_PATCH
   3078 		}
   3079 		#if DECORATION_HINTS_PATCH
   3080 		if (ev->atom == motifatom)
   3081 			updatemotifhints(c);
   3082 		#endif // DECORATION_HINTS_PATCH
   3083 		#if BAR_WINICON_PATCH
   3084 		else if (ev->atom == netatom[NetWMIcon]) {
   3085 			updateicon(c);
   3086 			if (c == c->mon->sel)
   3087 				drawbar(c->mon);
   3088 		}
   3089 		#endif // BAR_WINICON_PATCH
   3090 	}
   3091 }
   3092 
   3093 void
   3094 quit(const Arg *arg)
   3095 {
   3096 	#if RESTARTSIG_PATCH
   3097 	restart = arg->i;
   3098 	#endif // RESTARTSIG_PATCH
   3099 	#if ONLYQUITONEMPTY_PATCH
   3100 	Monitor *m;
   3101 	Client *c;
   3102 	unsigned int n = 0;
   3103 
   3104 	for (m = mons; m; m = m->next)
   3105 		for (c = m->clients; c; c = c->next, n++);
   3106 
   3107 	#if RESTARTSIG_PATCH
   3108 	if (restart || n <= quit_empty_window_count)
   3109 	#else
   3110 	if (n <= quit_empty_window_count)
   3111 	#endif // RESTARTSIG_PATCH
   3112 		running = 0;
   3113 	else
   3114 		fprintf(stderr, "[dwm] not exiting (n=%d)\n", n);
   3115 
   3116 	#else // !ONLYQUITONEMPTY_PATCH
   3117 	running = 0;
   3118 	#endif // ONLYQUITONEMPTY_PATCH
   3119 }
   3120 
   3121 Monitor *
   3122 recttomon(int x, int y, int w, int h)
   3123 {
   3124 	Monitor *m, *r = selmon;
   3125 	int a, area = 0;
   3126 
   3127 	for (m = mons; m; m = m->next)
   3128 		if ((a = INTERSECT(x, y, w, h, m)) > area) {
   3129 			area = a;
   3130 			r = m;
   3131 		}
   3132 	return r;
   3133 }
   3134 
   3135 void
   3136 resize(Client *c, int x, int y, int w, int h, int interact)
   3137 {
   3138 	if (applysizehints(c, &x, &y, &w, &h, interact))
   3139 		resizeclient(c, x, y, w, h);
   3140 }
   3141 
   3142 void
   3143 resizeclient(Client *c, int x, int y, int w, int h)
   3144 {
   3145 	XWindowChanges wc;
   3146 
   3147 	c->oldx = c->x; c->x = wc.x = x;
   3148 	c->oldy = c->y; c->y = wc.y = y;
   3149 	c->oldw = c->w; c->w = wc.width = w;
   3150 	c->oldh = c->h; c->h = wc.height = h;
   3151 	#if EXRESIZE_PATCH
   3152 	c->expandmask = 0;
   3153 	#endif // EXRESIZE_PATCH
   3154 	wc.border_width = c->bw;
   3155 	#if ROUNDED_CORNERS_PATCH
   3156 	drawroundedcorners(c);
   3157 	#endif // ROUNDED_CORNERS_PATCH
   3158 	#if NOBORDER_PATCH
   3159 	if (noborder(c)) {
   3160 		wc.width += c->bw * 2;
   3161 		wc.height += c->bw * 2;
   3162 		wc.border_width = 0;
   3163 	}
   3164 	#endif // NOBORDER_PATCH
   3165 	XConfigureWindow(dpy, c->win, CWX|CWY|CWWidth|CWHeight|CWBorderWidth, &wc);
   3166 	configure(c);
   3167 	XSync(dpy, False);
   3168 }
   3169 
   3170 void
   3171 resizemouse(const Arg *arg)
   3172 {
   3173 	int ocx, ocy, nw, nh, nx, ny;
   3174 	#if RESIZEPOINT_PATCH || RESIZECORNERS_PATCH
   3175 	int opx, opy, och, ocw;
   3176 	int horizcorner, vertcorner;
   3177 	unsigned int dui;
   3178 	Window dummy;
   3179 	#endif // RESIZEPOINT_PATCH | RESIZECORNERS_PATCH
   3180 	Client *c;
   3181 	Monitor *m;
   3182 	XEvent ev;
   3183 	Time lasttime = 0;
   3184 
   3185 	if (!(c = selmon->sel))
   3186 		return;
   3187 	#if !FAKEFULLSCREEN_PATCH
   3188 	#if FAKEFULLSCREEN_CLIENT_PATCH
   3189 	if (c->isfullscreen && c->fakefullscreen != 1) /* no support resizing fullscreen windows by mouse */
   3190 		return;
   3191 	#else
   3192 	if (c->isfullscreen) /* no support resizing fullscreen windows by mouse */
   3193 		return;
   3194 	#endif // FAKEFULLSCREEN_CLIENT_PATCH
   3195 	#endif // !FAKEFULLSCREEN_PATCH
   3196 	restack(selmon);
   3197 	nx = ocx = c->x;
   3198 	ny = ocy = c->y;
   3199 	nh = c->h;
   3200 	nw = c->w;
   3201 	#if RESIZEPOINT_PATCH
   3202 	och = c->h;
   3203 	ocw = c->w;
   3204 	#elif RESIZECORNERS_PATCH
   3205 	och = c->y + c->h;
   3206 	ocw = c->x + c->w;
   3207 	#endif // RESIZEPOINT_PATCH | RESIZECORNERS_PATCH
   3208 	#if RESIZEPOINT_PATCH || RESIZECORNERS_PATCH
   3209 	if (!XQueryPointer(dpy, c->win, &dummy, &dummy, &opx, &opy, &nx, &ny, &dui))
   3210 		return;
   3211 	horizcorner = nx < c->w / 2;
   3212 	vertcorner  = ny < c->h / 2;
   3213 	if (XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync,
   3214 		None, cursor[horizcorner | (vertcorner << 1)]->cursor, CurrentTime) != GrabSuccess)
   3215 		return;
   3216 	#if RESIZECORNERS_PATCH
   3217 	XWarpPointer (dpy, None, c->win, 0, 0, 0, 0,
   3218 			horizcorner ? (-c->bw) : (c->w + c->bw - 1),
   3219 			vertcorner ? (-c->bw) : (c->h + c->bw - 1));
   3220 	#endif // RESIZECORNERS_PATCH
   3221 	#else
   3222 	if (XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync,
   3223 		None, cursor[CurResize]->cursor, CurrentTime) != GrabSuccess)
   3224 		return;
   3225 	XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w + c->bw - 1, c->h + c->bw - 1);
   3226 	#endif // RESIZEPOINT_PATCH | RESIZECORNERS_PATCH
   3227 	ignoreconfigurerequests = 1;
   3228 	do {
   3229 		XMaskEvent(dpy, MOUSEMASK|ExposureMask|SubstructureRedirectMask, &ev);
   3230 		switch(ev.type) {
   3231 		case ConfigureRequest:
   3232 		case Expose:
   3233 		case MapRequest:
   3234 			handler[ev.type](&ev);
   3235 			break;
   3236 		case MotionNotify:
   3237 			if ((ev.xmotion.time - lasttime) <= (1000 / refreshrate))
   3238 				continue;
   3239 			lasttime = ev.xmotion.time;
   3240 
   3241 			#if RESIZEPOINT_PATCH
   3242 			nx = horizcorner ? (ocx + ev.xmotion.x - opx) : c->x;
   3243 			ny = vertcorner ? (ocy + ev.xmotion.y - opy) : c->y;
   3244 			nw = MAX(horizcorner ? (ocx + ocw - nx) : (ocw + (ev.xmotion.x - opx)), 1);
   3245 			nh = MAX(vertcorner ? (ocy + och - ny) : (och + (ev.xmotion.y - opy)), 1);
   3246 			#elif RESIZECORNERS_PATCH
   3247 			nx = horizcorner ? ev.xmotion.x : c->x;
   3248 			ny = vertcorner ? ev.xmotion.y : c->y;
   3249 			nw = MAX(horizcorner ? (ocw - nx) : (ev.xmotion.x - ocx - 2 * c->bw + 1), 1);
   3250 			nh = MAX(vertcorner ? (och - ny) : (ev.xmotion.y - ocy - 2 * c->bw + 1), 1);
   3251 			#else
   3252 			nw = MAX(ev.xmotion.x - ocx - 2 * c->bw + 1, 1);
   3253 			nh = MAX(ev.xmotion.y - ocy - 2 * c->bw + 1, 1);
   3254 			#endif // RESIZEPOINT_PATCH | RESIZECORNERS_PATCH
   3255 			if (c->mon->wx + nw >= selmon->wx && c->mon->wx + nw <= selmon->wx + selmon->ww
   3256 			&& c->mon->wy + nh >= selmon->wy && c->mon->wy + nh <= selmon->wy + selmon->wh)
   3257 			{
   3258 				if (!c->isfloating && selmon->lt[selmon->sellt]->arrange
   3259 				&& (abs(nw - c->w) > snap || abs(nh - c->h) > snap)) {
   3260 					#if SAVEFLOATS_PATCH || EXRESIZE_PATCH
   3261 					c->sfx = -9999; // disable savefloats when using resizemouse
   3262 					#endif // SAVEFLOATS_PATCH | EXRESIZE_PATCH
   3263 					togglefloating(NULL);
   3264 				}
   3265 			}
   3266 			if (!selmon->lt[selmon->sellt]->arrange || c->isfloating) {
   3267 				resize(c, nx, ny, nw, nh, 1);
   3268 			}
   3269 			break;
   3270 		}
   3271 	} while (ev.type != ButtonRelease);
   3272 
   3273 	#if !RESIZEPOINT_PATCH
   3274 	#if RESIZECORNERS_PATCH
   3275 	XWarpPointer(dpy, None, c->win, 0, 0, 0, 0,
   3276 			horizcorner ? (-c->bw) : (c->w + c->bw - 1),
   3277 			vertcorner ? (-c->bw) : (c->h + c->bw - 1));
   3278 	#else
   3279 	XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w + c->bw - 1, c->h + c->bw - 1);
   3280 	#endif // RESIZECORNERS_PATCH
   3281 	#endif // RESIZEPOINT_PATCH
   3282 	XUngrabPointer(dpy, CurrentTime);
   3283 	while (XCheckMaskEvent(dpy, EnterWindowMask, &ev));
   3284 	if ((m = recttomon(c->x, c->y, c->w, c->h)) != selmon) {
   3285 		#if SCRATCHPADS_PATCH && !RENAMED_SCRATCHPADS_PATCH
   3286 		if (c->tags & SPTAGMASK) {
   3287 			c->mon->tagset[c->mon->seltags] ^= (c->tags & SPTAGMASK);
   3288 			m->tagset[m->seltags] |= (c->tags & SPTAGMASK);
   3289 		}
   3290 		#endif // SCRATCHPADS_PATCH
   3291 		sendmon(c, m);
   3292 		selmon = m;
   3293 		focus(NULL);
   3294 	}
   3295 	#if SAVEFLOATS_PATCH || EXRESIZE_PATCH
   3296 	/* save last known float dimensions */
   3297 	if (!selmon->lt[selmon->sellt]->arrange || c->isfloating) {
   3298 		c->sfx = nx;
   3299 		c->sfy = ny;
   3300 		c->sfw = nw;
   3301 		c->sfh = nh;
   3302 	}
   3303 	#endif // SAVEFLOATS_PATCH | EXRESIZE_PATCH
   3304 	ignoreconfigurerequests = 0;
   3305 }
   3306 
   3307 void
   3308 restack(Monitor *m)
   3309 {
   3310 	Client *c, *f = NULL;
   3311 	XEvent ev;
   3312 	XWindowChanges wc;
   3313 	#if WARP_PATCH && FLEXTILE_DELUXE_LAYOUT
   3314 	int n;
   3315 	#endif // WARP_PATCH
   3316 	#if ALWAYSONTOP_PATCH
   3317 	Monitor *mon;
   3318 	#endif // ALWAYSONTOP_PATCH
   3319 
   3320 	drawbar(m);
   3321 	#if TAB_PATCH
   3322 	drawtab(m);
   3323 	#endif // TAB_PATCH
   3324 	if (!m->sel)
   3325 		return;
   3326 	if (m->sel->isfloating || !m->lt[m->sellt]->arrange)
   3327 		XRaiseWindow(dpy, m->sel->win);
   3328 
   3329 	#if ALWAYSONTOP_PATCH
   3330 	/* raise the aot windows */
   3331 	for (mon = mons; mon; mon = mon->next) {
   3332 		for (c = mon->clients; c; c = c->next) {
   3333 			if (c->alwaysontop) {
   3334 				XRaiseWindow(dpy, c->win);
   3335 			}
   3336 		}
   3337 	}
   3338 	#endif // ALWAYSONTOP_PATCH
   3339 
   3340 	if (m->lt[m->sellt]->arrange) {
   3341 		wc.stack_mode = Below;
   3342 		if (m->bar) {
   3343 			wc.sibling = m->bar->win;
   3344 		} else {
   3345 			for (f = m->stack; f && (f->isfloating || !ISVISIBLE(f)); f = f->snext); // find first tiled stack client
   3346 			if (f)
   3347 				wc.sibling = f->win;
   3348 		}
   3349 		for (c = m->stack; c; c = c->snext)
   3350 			if (!c->isfloating && ISVISIBLE(c) && c != f) {
   3351 				XConfigureWindow(dpy, c->win, CWSibling|CWStackMode, &wc);
   3352 				wc.sibling = c->win;
   3353 			}
   3354 	}
   3355 	XSync(dpy, False);
   3356 	while (XCheckMaskEvent(dpy, EnterWindowMask, &ev));
   3357 	#if WARP_PATCH && FLEXTILE_DELUXE_LAYOUT || WARP_PATCH && MONOCLE_LAYOUT
   3358 	#if FLEXTILE_DELUXE_LAYOUT
   3359 	for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++);
   3360 	#endif // FLEXTILE_DELUXE_LAYOUT
   3361 	if (m == selmon && (m->tagset[m->seltags] & m->sel->tags) && (
   3362 		#if MONOCLE_LAYOUT && FLEXTILE_DELUXE_LAYOUT
   3363 		(m->lt[m->sellt]->arrange != &monocle
   3364 		&& !(m->ltaxis[MASTER] == MONOCLE && (abs(m->ltaxis[LAYOUT] == NO_SPLIT || !m->nmaster || n <= m->nmaster))))
   3365 		#elif MONOCLE_LAYOUT
   3366 		m->lt[m->sellt]->arrange != &monocle
   3367 		#else
   3368 		!(m->ltaxis[MASTER] == MONOCLE && (abs(m->ltaxis[LAYOUT] == NO_SPLIT || !m->nmaster || n <= m->nmaster)))
   3369 		#endif // FLEXTILE_DELUXE_LAYOUT
   3370 		|| m->sel->isfloating)
   3371 	)
   3372 		warp(m->sel);
   3373 	#endif // WARP_PATCH
   3374 }
   3375 
   3376 #if IPC_PATCH
   3377 void
   3378 run(void)
   3379 {
   3380 	int event_count = 0;
   3381 	const int MAX_EVENTS = 10;
   3382 	struct epoll_event events[MAX_EVENTS];
   3383 
   3384 	XSync(dpy, False);
   3385 
   3386 	/* main event loop */
   3387 	while (running) {
   3388 		event_count = epoll_wait(epoll_fd, events, MAX_EVENTS, -1);
   3389 
   3390 		for (int i = 0; i < event_count; i++) {
   3391 			int event_fd = events[i].data.fd;
   3392 			DEBUG("Got event from fd %d\n", event_fd);
   3393 
   3394 			if (event_fd == dpy_fd) {
   3395 				// -1 means EPOLLHUP
   3396 				if (handlexevent(events + i) == -1)
   3397 					return;
   3398 			} else if (event_fd == ipc_get_sock_fd()) {
   3399 				ipc_handle_socket_epoll_event(events + i);
   3400 			} else if (ipc_is_client_registered(event_fd)) {
   3401 				if (ipc_handle_client_epoll_event(events + i, mons, &lastselmon, selmon,
   3402 						NUMTAGS, layouts, LENGTH(layouts)) < 0) {
   3403 					fprintf(stderr, "Error handling IPC event on fd %d\n", event_fd);
   3404 				}
   3405 			} else {
   3406 				fprintf(stderr, "Got event from unknown fd %d, ptr %p, u32 %d, u64 %lu",
   3407 				event_fd, events[i].data.ptr, events[i].data.u32,
   3408 				events[i].data.u64);
   3409 				fprintf(stderr, " with events %d\n", events[i].events);
   3410 			}
   3411 		}
   3412 	}
   3413 }
   3414 #elif RESTARTSIG_PATCH
   3415 void
   3416 run(void)
   3417 {
   3418 	XEvent ev;
   3419 	XSync(dpy, False);
   3420 	/* main event loop */
   3421 	while (running) {
   3422 		struct pollfd pfd = {
   3423 			.fd = ConnectionNumber(dpy),
   3424 			.events = POLLIN,
   3425 		};
   3426 		int pending = XPending(dpy) > 0 || poll(&pfd, 1, -1) > 0;
   3427 
   3428 		if (!running)
   3429 			break;
   3430 		if (!pending)
   3431 			continue;
   3432 
   3433 		XNextEvent(dpy, &ev);
   3434 		if (handler[ev.type])
   3435 			handler[ev.type](&ev); /* call handler */
   3436 	}
   3437 }
   3438 #else
   3439 void
   3440 run(void)
   3441 {
   3442 	XEvent ev;
   3443 	/* main event loop */
   3444 	XSync(dpy, False);
   3445 	while (running && !XNextEvent(dpy, &ev)) {
   3446 
   3447 		#if XKB_PATCH
   3448 		/* Unfortunately the xkbEventType is not constant hence it can't be part of the
   3449 		 * normal event handler below */
   3450 		if (ev.type == xkbEventType) {
   3451 			xkbeventnotify(&ev);
   3452 			continue;
   3453 		}
   3454 		#endif // XKB_PATCH
   3455 
   3456 		if (handler[ev.type])
   3457 			handler[ev.type](&ev); /* call handler */
   3458 	}
   3459 }
   3460 #endif // IPC_PATCH | RESTARTSIG_PATCH
   3461 
   3462 void
   3463 scan(void)
   3464 {
   3465 	#if SWALLOW_PATCH
   3466 	scanner = 1;
   3467 	char swin[256];
   3468 	#endif // SWALLOW_PATCH
   3469 	unsigned int i, num;
   3470 	Window d1, d2, *wins = NULL;
   3471 	XWindowAttributes wa;
   3472 
   3473 	if (XQueryTree(dpy, root, &d1, &d2, &wins, &num)) {
   3474 		for (i = 0; i < num; i++) {
   3475 			if (!XGetWindowAttributes(dpy, wins[i], &wa)
   3476 			|| wa.override_redirect || XGetTransientForHint(dpy, wins[i], &d1))
   3477 				continue;
   3478 			#if BAR_ANYBAR_PATCH
   3479 			if (wmclasscontains(wins[i], altbarclass, ""))
   3480 				managealtbar(wins[i], &wa);
   3481 			else
   3482 			#endif // BAR_ANYBAR_PATCH
   3483 			if (wa.map_state == IsViewable || getstate(wins[i]) == IconicState)
   3484 				manage(wins[i], &wa);
   3485 			#if SWALLOW_PATCH
   3486 			else if (gettextprop(wins[i], netatom[NetClientList], swin, sizeof swin))
   3487 				manage(wins[i], &wa);
   3488 			#endif // SWALLOW_PATCH
   3489 		}
   3490 		for (i = 0; i < num; i++) { /* now the transients */
   3491 			if (!XGetWindowAttributes(dpy, wins[i], &wa))
   3492 				continue;
   3493 			if (XGetTransientForHint(dpy, wins[i], &d1)
   3494 			&& (wa.map_state == IsViewable || getstate(wins[i]) == IconicState))
   3495 				manage(wins[i], &wa);
   3496 		}
   3497 		XFree(wins);
   3498 	}
   3499 	#if SWALLOW_PATCH
   3500 	scanner = 0;
   3501 	#endif // SWALLOW_PATCH
   3502 }
   3503 
   3504 void
   3505 sendmon(Client *c, Monitor *m)
   3506 {
   3507 	#if EXRESIZE_PATCH
   3508 	Monitor *oldm = selmon;
   3509 	#endif // EXRESIZE_PATCH
   3510 	if (c->mon == m)
   3511 		return;
   3512 	#if SENDMON_KEEPFOCUS_PATCH && !EXRESIZE_PATCH
   3513 	int hadfocus = (c == selmon->sel);
   3514 	#endif // SENDMON_KEEPFOCUS_PATCH
   3515 	unfocus(c, 1, NULL);
   3516 	detach(c);
   3517 	detachstack(c);
   3518 	#if SENDMON_KEEPFOCUS_PATCH && !EXRESIZE_PATCH
   3519 	arrange(c->mon);
   3520 	#endif // SENDMON_KEEPFOCUS_PATCH
   3521 	c->mon = m;
   3522 	#if SCRATCHPADS_PATCH && !RENAMED_SCRATCHPADS_PATCH
   3523 	if (!(c->tags & SPTAGMASK))
   3524 	#endif // SCRATCHPADS_PATCH
   3525 	#if EMPTYVIEW_PATCH
   3526 	c->tags = (m->tagset[m->seltags] ? m->tagset[m->seltags] : 1);
   3527 	#else
   3528 	c->tags = m->tagset[m->seltags]; /* assign tags of target monitor */
   3529 	#endif // EMPTYVIEW_PATCH
   3530 	#if SENDMON_CENTER_PATCH
   3531 	c->x = m->mx + (m->mw - WIDTH(c)) / 2;
   3532 	c->y = m->my + (m->mh - HEIGHT(c)) / 2;
   3533 	#if SAVEFLOATS_PATCH
   3534 	c->sfx = m->mx + (m->mw - c->sfw - 2 * c->bw) / 2;
   3535 	c->sfy = m->my + (m->mh - c->sfh - 2 * c->bw) / 2;
   3536 	#endif // SAVEFLOATS_PATCH
   3537 	#endif // SENDMON_CENTER_PATCH
   3538 	#if ATTACHABOVE_PATCH || ATTACHASIDE_PATCH || ATTACHBELOW_PATCH || ATTACHBOTTOM_PATCH
   3539 	attachx(c);
   3540 	#else
   3541 	attach(c);
   3542 	#endif
   3543 	attachstack(c);
   3544 	#if EXRESIZE_PATCH
   3545 	if (oldm != m)
   3546 		arrange(oldm);
   3547 	arrange(m);
   3548 	focus(c);
   3549 	restack(m);
   3550 	#elif SENDMON_KEEPFOCUS_PATCH
   3551 	arrange(m);
   3552 	if (hadfocus) {
   3553 		focus(c);
   3554 		restack(m);
   3555 	} else {
   3556 		focus(NULL);
   3557 	}
   3558 	#else
   3559 	arrange(NULL);
   3560 	focus(NULL);
   3561 	#endif // EXRESIZE_PATCH / SENDMON_KEEPFOCUS_PATCH
   3562 	#if SWITCHTAG_PATCH
   3563 	if (c->switchtag)
   3564 		c->switchtag = 0;
   3565 	#endif // SWITCHTAG_PATCH
   3566 }
   3567 
   3568 void
   3569 setclientstate(Client *c, long state)
   3570 {
   3571 	long data[] = { state, None };
   3572 
   3573 	XChangeProperty(dpy, c->win, wmatom[WMState], wmatom[WMState], 32,
   3574 		PropModeReplace, (unsigned char *)data, 2);
   3575 }
   3576 
   3577 int
   3578 #if BAR_SYSTRAY_PATCH
   3579 sendevent(Window w, Atom proto, int mask, long d0, long d1, long d2, long d3, long d4)
   3580 #else
   3581 sendevent(Client *c, Atom proto)
   3582 #endif // BAR_SYSTRAY_PATCH
   3583 {
   3584 	int n;
   3585 	Atom *protocols;
   3586 	#if BAR_SYSTRAY_PATCH
   3587 	Atom mt;
   3588 	#endif // BAR_SYSTRAY_PATCH
   3589 	int exists = 0;
   3590 	XEvent ev;
   3591 
   3592 	#if BAR_SYSTRAY_PATCH
   3593 	if (proto == wmatom[WMTakeFocus] || proto == wmatom[WMDelete]) {
   3594 		mt = wmatom[WMProtocols];
   3595 		if (XGetWMProtocols(dpy, w, &protocols, &n)) {
   3596 			while (!exists && n--)
   3597 				exists = protocols[n] == proto;
   3598 			XFree(protocols);
   3599 		}
   3600 	} else {
   3601 		exists = True;
   3602 		mt = proto;
   3603 	}
   3604 	#else
   3605 	if (XGetWMProtocols(dpy, c->win, &protocols, &n)) {
   3606 		while (!exists && n--)
   3607 			exists = protocols[n] == proto;
   3608 		XFree(protocols);
   3609 	}
   3610 	#endif // BAR_SYSTRAY_PATCH
   3611 
   3612 	if (exists) {
   3613 		#if BAR_SYSTRAY_PATCH
   3614 		ev.type = ClientMessage;
   3615 		ev.xclient.window = w;
   3616 		ev.xclient.message_type = mt;
   3617 		ev.xclient.format = 32;
   3618 		ev.xclient.data.l[0] = d0;
   3619 		ev.xclient.data.l[1] = d1;
   3620 		ev.xclient.data.l[2] = d2;
   3621 		ev.xclient.data.l[3] = d3;
   3622 		ev.xclient.data.l[4] = d4;
   3623 		XSendEvent(dpy, w, False, mask, &ev);
   3624 		#else
   3625 		ev.type = ClientMessage;
   3626 		ev.xclient.window = c->win;
   3627 		ev.xclient.message_type = wmatom[WMProtocols];
   3628 		ev.xclient.format = 32;
   3629 		ev.xclient.data.l[0] = proto;
   3630 		ev.xclient.data.l[1] = CurrentTime;
   3631 		XSendEvent(dpy, c->win, False, NoEventMask, &ev);
   3632 		#endif // BAR_SYSTRAY_PATCH
   3633 	}
   3634 	return exists;
   3635 }
   3636 
   3637 void
   3638 setfocus(Client *c)
   3639 {
   3640 	if (!c->neverfocus) {
   3641 		XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime);
   3642 		XChangeProperty(dpy, root, netatom[NetActiveWindow],
   3643 			XA_WINDOW, 32, PropModeReplace,
   3644 			(unsigned char *) &(c->win), 1);
   3645 		#if XKB_PATCH
   3646 		XkbLockGroup(dpy, XkbUseCoreKbd, c->xkb->group);
   3647 		#endif // XKB_PATCH
   3648 	}
   3649 
   3650 	#if GAMES_PATCH
   3651 	if (c->isgame && c->isfullscreen)
   3652 		unminimize(c);
   3653 	#endif // GAMES_PATCH
   3654 
   3655 	#if BAR_SYSTRAY_PATCH
   3656 	sendevent(c->win, wmatom[WMTakeFocus], NoEventMask, wmatom[WMTakeFocus], CurrentTime, 0, 0, 0);
   3657 	#else
   3658 	sendevent(c, wmatom[WMTakeFocus]);
   3659 	#endif // BAR_SYSTRAY_PATCH
   3660 }
   3661 
   3662 #if FAKEFULLSCREEN_CLIENT_PATCH && !FAKEFULLSCREEN_PATCH
   3663 void
   3664 setfullscreen(Client *c, int fullscreen)
   3665 {
   3666 	XEvent ev;
   3667 	int savestate = 0, restorestate = 0;
   3668 
   3669 	if ((c->fakefullscreen == 0 && fullscreen && !c->isfullscreen) // normal fullscreen
   3670 			|| (c->fakefullscreen == 2 && fullscreen)) // fake fullscreen --> actual fullscreen
   3671 		savestate = 1; // go actual fullscreen
   3672 	else if ((c->fakefullscreen == 0 && !fullscreen && c->isfullscreen) // normal fullscreen exit
   3673 			|| (c->fakefullscreen >= 2 && !fullscreen)) // fullscreen exit --> fake fullscreen
   3674 		restorestate = 1; // go back into tiled
   3675 
   3676 	/* If leaving fullscreen and the window was previously fake fullscreen (2), then restore
   3677 	 * that while staying in fullscreen. The exception to this is if we are in said state, but
   3678 	 * the client itself disables fullscreen (3) then we let the client go out of fullscreen
   3679 	 * while keeping fake fullscreen enabled (as otherwise there will be a mismatch between the
   3680 	 * client and the window manager's perception of the client's fullscreen state). */
   3681 	if (c->fakefullscreen == 2 && !fullscreen && c->isfullscreen) {
   3682 		c->fakefullscreen = 1;
   3683 		c->isfullscreen = 1;
   3684 		fullscreen = 1;
   3685 	} else if (c->fakefullscreen == 3) // client exiting actual fullscreen
   3686 		c->fakefullscreen = 1;
   3687 
   3688 	if (fullscreen != c->isfullscreen) { // only send property change if necessary
   3689 		if (fullscreen)
   3690 			XChangeProperty(dpy, c->win, netatom[NetWMState], XA_ATOM, 32,
   3691 				PropModeReplace, (unsigned char*)&netatom[NetWMFullscreen], 1);
   3692 		else
   3693 			XChangeProperty(dpy, c->win, netatom[NetWMState], XA_ATOM, 32,
   3694 				PropModeReplace, (unsigned char*)0, 0);
   3695 	}
   3696 
   3697 	c->isfullscreen = fullscreen;
   3698 
   3699 	/* Some clients, e.g. firefox, will send a client message informing the window manager
   3700 	 * that it is going into fullscreen after receiving the above signal. This has the side
   3701 	 * effect of this function (setfullscreen) sometimes being called twice when toggling
   3702 	 * fullscreen on and off via the window manager as opposed to the application itself.
   3703 	 * To protect against obscure issues where the client settings are stored or restored
   3704 	 * when they are not supposed to we add an additional bit-lock on the old state so that
   3705 	 * settings can only be stored and restored in that precise order. */
   3706 	if (savestate && !(c->oldstate & (1 << 1))) {
   3707 		c->oldbw = c->bw;
   3708 		c->oldstate = c->isfloating | (1 << 1);
   3709 		c->bw = 0;
   3710 		c->isfloating = 1;
   3711 		resizeclient(c, c->mon->mx, c->mon->my, c->mon->mw, c->mon->mh);
   3712 		XRaiseWindow(dpy, c->win);
   3713 	} else if (restorestate && (c->oldstate & (1 << 1))) {
   3714 		c->bw = c->oldbw;
   3715 		c->isfloating = c->oldstate = c->oldstate & 1;
   3716 		c->x = c->oldx;
   3717 		c->y = c->oldy;
   3718 		c->w = c->oldw;
   3719 		c->h = c->oldh;
   3720 		resizeclient(c, c->x, c->y, c->w, c->h);
   3721 		restack(c->mon);
   3722 	} else
   3723 		resizeclient(c, c->x, c->y, c->w, c->h);
   3724 
   3725 	/* Exception: if the client was in actual fullscreen and we exit out to fake fullscreen
   3726 	 * mode, then the focus would sometimes drift to whichever window is under the mouse cursor
   3727 	 * at the time. To avoid this we ask X for all EnterNotify events and just ignore them.
   3728 	 */
   3729 	if (!c->isfullscreen)
   3730 		while (XCheckMaskEvent(dpy, EnterWindowMask, &ev));
   3731 }
   3732 #else
   3733 void
   3734 setfullscreen(Client *c, int fullscreen)
   3735 {
   3736 	if (fullscreen && !c->isfullscreen) {
   3737 		XChangeProperty(dpy, c->win, netatom[NetWMState], XA_ATOM, 32,
   3738 			PropModeReplace, (unsigned char*)&netatom[NetWMFullscreen], 1);
   3739 		c->isfullscreen = 1;
   3740 		#if !FAKEFULLSCREEN_PATCH
   3741 		c->oldbw = c->bw;
   3742 		c->oldstate = c->isfloating;
   3743 		c->bw = 0;
   3744 		c->isfloating = 1;
   3745 		resizeclient(c, c->mon->mx, c->mon->my, c->mon->mw, c->mon->mh);
   3746 		XRaiseWindow(dpy, c->win);
   3747 		#endif // !FAKEFULLSCREEN_PATCH
   3748 	} else if (!fullscreen && c->isfullscreen){
   3749 		XChangeProperty(dpy, c->win, netatom[NetWMState], XA_ATOM, 32,
   3750 			PropModeReplace, (unsigned char*)0, 0);
   3751 		c->isfullscreen = 0;
   3752 		#if !FAKEFULLSCREEN_PATCH
   3753 		c->bw = c->oldbw;
   3754 		c->isfloating = c->oldstate;
   3755 		c->x = c->oldx;
   3756 		c->y = c->oldy;
   3757 		c->w = c->oldw;
   3758 		c->h = c->oldh;
   3759 		resizeclient(c, c->x, c->y, c->w, c->h);
   3760 		arrange(c->mon);
   3761 		#endif // !FAKEFULLSCREEN_PATCH
   3762 	}
   3763 	#if FAKEFULLSCREEN_PATCH
   3764 	resizeclient(c, c->x, c->y, c->w, c->h);
   3765 	#endif // FAKEFULLSCREEN_PATCH
   3766 }
   3767 #endif // FAKEFULLSCREEN_CLIENT_PATCH
   3768 
   3769 void
   3770 setlayout(const Arg *arg)
   3771 {
   3772 	#if !TOGGLELAYOUT_PATCH
   3773 	if (!arg || !arg->v || arg->v != selmon->lt[selmon->sellt]) {
   3774 	#endif // TOGGLELAYOUT_PATCH
   3775 		#if PERTAG_PATCH
   3776 		selmon->pertag->sellts[selmon->pertag->curtag] ^= 1;
   3777 		selmon->sellt = selmon->pertag->sellts[selmon->pertag->curtag];
   3778 		#else
   3779 		selmon->sellt ^= 1;
   3780 		#endif // PERTAG_PATCH
   3781 		#if EXRESIZE_PATCH
   3782 		if (!selmon->lt[selmon->sellt]->arrange) {
   3783 			for (Client *c = selmon->clients ; c ; c = c->next) {
   3784 				if (!c->isfloating) {
   3785 					/*restore last known float dimensions*/
   3786 					resize(c, selmon->mx + c->sfx, selmon->my + c->sfy,
   3787 					       c->sfw, c->sfh, False);
   3788 				}
   3789 			}
   3790 		}
   3791 		#endif // EXRESIZE_PATCH
   3792 	#if !TOGGLELAYOUT_PATCH
   3793 	}
   3794 	#endif // TOGGLELAYOUT_PATCH
   3795 	#if TOGGLELAYOUT_PATCH
   3796 	if (arg && arg->v && arg->v != selmon->lt[selmon->sellt ^ 1])
   3797 	#else
   3798 	if (arg && arg->v)
   3799 	#endif // TOGGLELAYOUT_PATCH
   3800 	#if PERTAG_PATCH
   3801 		selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt] = (Layout *)arg->v;
   3802 	selmon->lt[selmon->sellt] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt];
   3803 	#else
   3804 		selmon->lt[selmon->sellt] = (Layout *)arg->v;
   3805 	#endif // PERTAG_PATCH
   3806 
   3807 	#if FLEXTILE_DELUXE_LAYOUT
   3808 	if (selmon->lt[selmon->sellt]->preset.nmaster && selmon->lt[selmon->sellt]->preset.nmaster != -1)
   3809 		selmon->nmaster = selmon->lt[selmon->sellt]->preset.nmaster;
   3810 	if (selmon->lt[selmon->sellt]->preset.nstack && selmon->lt[selmon->sellt]->preset.nstack != -1)
   3811 		selmon->nstack = selmon->lt[selmon->sellt]->preset.nstack;
   3812 
   3813 	selmon->ltaxis[LAYOUT] = selmon->lt[selmon->sellt]->preset.layout;
   3814 	selmon->ltaxis[MASTER] = selmon->lt[selmon->sellt]->preset.masteraxis;
   3815 	selmon->ltaxis[STACK]  = selmon->lt[selmon->sellt]->preset.stack1axis;
   3816 	selmon->ltaxis[STACK2] = selmon->lt[selmon->sellt]->preset.stack2axis;
   3817 
   3818 	#if PERTAG_PATCH
   3819 	selmon->pertag->ltaxis[selmon->pertag->curtag][LAYOUT] = selmon->ltaxis[LAYOUT];
   3820 	selmon->pertag->ltaxis[selmon->pertag->curtag][MASTER] = selmon->ltaxis[MASTER];
   3821 	selmon->pertag->ltaxis[selmon->pertag->curtag][STACK]  = selmon->ltaxis[STACK];
   3822 	selmon->pertag->ltaxis[selmon->pertag->curtag][STACK2] = selmon->ltaxis[STACK2];
   3823 	#endif // PERTAG_PATCH
   3824 	#endif // FLEXTILE_DELUXE_LAYOUT
   3825 	strncpy(selmon->ltsymbol, selmon->lt[selmon->sellt]->symbol, sizeof selmon->ltsymbol);
   3826 	if (selmon->sel)
   3827 		arrange(selmon);
   3828 	else
   3829 		drawbar(selmon);
   3830 }
   3831 
   3832 /* arg > 1.0 will set mfact absolutely */
   3833 void
   3834 setmfact(const Arg *arg)
   3835 {
   3836 	float f;
   3837 
   3838 	if (!arg || !selmon->lt[selmon->sellt]->arrange)
   3839 		return;
   3840 	f = arg->f < 1.0 ? arg->f + selmon->mfact : arg->f - 1.0;
   3841 	if (f < 0.05 || f > 0.95)
   3842 		return;
   3843 	#if PERTAG_PATCH
   3844 	selmon->mfact = selmon->pertag->mfacts[selmon->pertag->curtag] = f;
   3845 	#else
   3846 	selmon->mfact = f;
   3847 	#endif // PERTAG_PATCH
   3848 	arrange(selmon);
   3849 }
   3850 
   3851 void
   3852 setup(void)
   3853 {
   3854 	int i;
   3855 	XSetWindowAttributes wa;
   3856 	#if XKB_PATCH
   3857 	XkbStateRec xkbstate;
   3858 	#endif // XKB_PATCH
   3859 	Atom utf8string;
   3860 	#if COOL_AUTOSTART_PATCH
   3861 	/* clean up any zombies immediately */
   3862 	sigchld(0);
   3863 	#else
   3864 	struct sigaction sa;
   3865 
   3866 	/* do not transform children into zombies when they terminate */
   3867 	sigemptyset(&sa.sa_mask);
   3868 	sa.sa_flags = SA_NOCLDSTOP | SA_NOCLDWAIT | SA_RESTART;
   3869 	sa.sa_handler = SIG_IGN;
   3870 	sigaction(SIGCHLD, &sa, NULL);
   3871 
   3872 	/* clean up any zombies (inherited from .xinitrc etc) immediately */
   3873 	while (waitpid(-1, NULL, WNOHANG) > 0);
   3874 	#endif // COOL_AUTOSTART_PATCH
   3875 
   3876 	#if RESTARTSIG_PATCH
   3877 	signal(SIGHUP, sighup);
   3878 	signal(SIGTERM, sigterm);
   3879 	#endif // RESTARTSIG_PATCH
   3880 
   3881 	/* the one line of bloat that would have saved a lot of time for a lot of people */
   3882 	putenv("_JAVA_AWT_WM_NONREPARENTING=1");
   3883 
   3884 	/* init screen */
   3885 	screen = DefaultScreen(dpy);
   3886 	sw = DisplayWidth(dpy, screen);
   3887 	sh = DisplayHeight(dpy, screen);
   3888 	root = RootWindow(dpy, screen);
   3889 	#if BAR_ALPHA_PATCH
   3890 	xinitvisual();
   3891 	drw = drw_create(dpy, screen, root, sw, sh, visual, depth, cmap);
   3892 	#else
   3893 	drw = drw_create(dpy, screen, root, sw, sh);
   3894 	#endif // BAR_ALPHA_PATCH
   3895 	#if BAR_PANGO_PATCH
   3896 	if (!drw_font_create(drw, font))
   3897 	#else
   3898 	if (!drw_fontset_create(drw, fonts, LENGTH(fonts)))
   3899 	#endif // BAR_PANGO_PATCH
   3900 		die("no fonts could be loaded.");
   3901 	#if BAR_STATUSPADDING_PATCH
   3902 	lrpad = drw->fonts->h + horizpadbar;
   3903 	bh = drw->fonts->h + vertpadbar;
   3904 	#else
   3905 	lrpad = drw->fonts->h;
   3906 	#if BAR_HEIGHT_PATCH
   3907 	bh = bar_height ? bar_height : drw->fonts->h + 2;
   3908 	#else
   3909 	bh = drw->fonts->h + 2;
   3910 	#endif // BAR_HEIGHT_PATCH
   3911 	#endif // BAR_STATUSPADDING_PATCH
   3912 	#if TAB_PATCH
   3913 	th = bh;
   3914 	#endif // TAB_PATCH
   3915 	updategeom();
   3916 	/* init atoms */
   3917 	utf8string = XInternAtom(dpy, "UTF8_STRING", False);
   3918 	wmatom[WMProtocols] = XInternAtom(dpy, "WM_PROTOCOLS", False);
   3919 	wmatom[WMDelete] = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
   3920 	wmatom[WMState] = XInternAtom(dpy, "WM_STATE", False);
   3921 	wmatom[WMTakeFocus] = XInternAtom(dpy, "WM_TAKE_FOCUS", False);
   3922 	#if WINDOWROLERULE_PATCH
   3923 	wmatom[WMWindowRole] = XInternAtom(dpy, "WM_WINDOW_ROLE", False);
   3924 	#endif // WINDOWROLERULE_PATCH
   3925 	#if SEAMLESS_RESTART_PATCH
   3926 	clientatom[ClientFields] = XInternAtom(dpy, "_DWM_CLIENT_FIELDS", False);
   3927 	clientatom[ClientTags] = XInternAtom(dpy, "_DWM_CLIENT_TAGS", False);
   3928 	#endif // SEAMLESS_RESTART_PATCH
   3929 	netatom[NetActiveWindow] = XInternAtom(dpy, "_NET_ACTIVE_WINDOW", False);
   3930 	netatom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False);
   3931 	#if BAR_SYSTRAY_PATCH
   3932 	netatom[NetSystemTray] = XInternAtom(dpy, "_NET_SYSTEM_TRAY_S0", False);
   3933 	netatom[NetSystemTrayOP] = XInternAtom(dpy, "_NET_SYSTEM_TRAY_OPCODE", False);
   3934 	netatom[NetSystemTrayOrientation] = XInternAtom(dpy, "_NET_SYSTEM_TRAY_ORIENTATION", False);
   3935 	netatom[NetSystemTrayOrientationHorz] = XInternAtom(dpy, "_NET_SYSTEM_TRAY_ORIENTATION_HORZ", False);
   3936 	netatom[NetSystemTrayVisual] = XInternAtom(dpy, "_NET_SYSTEM_TRAY_VISUAL", False);
   3937 	netatom[NetWMWindowTypeDock] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DOCK", False);
   3938 	xatom[Manager] = XInternAtom(dpy, "MANAGER", False);
   3939 	xatom[Xembed] = XInternAtom(dpy, "_XEMBED", False);
   3940 	xatom[XembedInfo] = XInternAtom(dpy, "_XEMBED_INFO", False);
   3941 	#endif // BAR_SYSTRAY_PATCH
   3942 	#if BAR_EWMHTAGS_PATCH
   3943 	netatom[NetDesktopViewport] = XInternAtom(dpy, "_NET_DESKTOP_VIEWPORT", False);
   3944 	netatom[NetNumberOfDesktops] = XInternAtom(dpy, "_NET_NUMBER_OF_DESKTOPS", False);
   3945 	netatom[NetCurrentDesktop] = XInternAtom(dpy, "_NET_CURRENT_DESKTOP", False);
   3946 	netatom[NetDesktopNames] = XInternAtom(dpy, "_NET_DESKTOP_NAMES", False);
   3947 	#endif // BAR_EWMHTAGS_PATCH
   3948 	#if BAR_WINICON_PATCH
   3949 	netatom[NetWMIcon] = XInternAtom(dpy, "_NET_WM_ICON", False);
   3950 	#endif // BAR_WINICON_PATCH
   3951 	netatom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False);
   3952 	netatom[NetWMState] = XInternAtom(dpy, "_NET_WM_STATE", False);
   3953 	netatom[NetWMCheck] = XInternAtom(dpy, "_NET_SUPPORTING_WM_CHECK", False);
   3954 	netatom[NetWMFullscreen] = XInternAtom(dpy, "_NET_WM_STATE_FULLSCREEN", False);
   3955 	netatom[NetWMWindowType] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE", False);
   3956 	netatom[NetClientList] = XInternAtom(dpy, "_NET_CLIENT_LIST", False);
   3957 	#if NET_CLIENT_LIST_STACKING_PATCH
   3958 	netatom[NetClientListStacking] = XInternAtom(dpy, "_NET_CLIENT_LIST_STACKING", False);
   3959 	#endif // NET_CLIENT_LIST_STACKING_PATCH
   3960 	#if DECORATION_HINTS_PATCH
   3961 	motifatom = XInternAtom(dpy, "_MOTIF_WM_HINTS", False);
   3962 	#endif // DECORATION_HINTS_PATCH
   3963 	/* init cursors */
   3964 	cursor[CurNormal] = drw_cur_create(drw, XC_left_ptr);
   3965 	cursor[CurResize] = drw_cur_create(drw, XC_sizing);
   3966 	#if RESIZEPOINT_PATCH || RESIZECORNERS_PATCH
   3967 	cursor[CurResizeBR] = drw_cur_create(drw, XC_bottom_right_corner);
   3968 	cursor[CurResizeBL] = drw_cur_create(drw, XC_bottom_left_corner);
   3969 	cursor[CurResizeTR] = drw_cur_create(drw, XC_top_right_corner);
   3970 	cursor[CurResizeTL] = drw_cur_create(drw, XC_top_left_corner);
   3971 	#endif // RESIZEPOINT_PATCH | RESIZECORNERS_PATCH
   3972 	#if DRAGMFACT_PATCH
   3973 	cursor[CurResizeHorzArrow] = drw_cur_create(drw, XC_sb_h_double_arrow);
   3974 	cursor[CurResizeVertArrow] = drw_cur_create(drw, XC_sb_v_double_arrow);
   3975 	#endif // DRAGMFACT_PATCH
   3976 	#if DRAGCFACT_PATCH
   3977 	cursor[CurIronCross] = drw_cur_create(drw, XC_iron_cross);
   3978 	#endif // DRAGCFACT_PATCH
   3979 	cursor[CurMove] = drw_cur_create(drw, XC_fleur);
   3980 	/* init appearance */
   3981 	#if BAR_VTCOLORS_PATCH
   3982 	get_vt_colors();
   3983 	if (get_luminance(colors[SchemeTagsNorm][ColBg]) > 50) {
   3984 		strcpy(colors[SchemeTitleNorm][ColBg], title_bg_light);
   3985 		strcpy(colors[SchemeTitleSel][ColBg], title_bg_light);
   3986 	} else {
   3987 		strcpy(colors[SchemeTitleNorm][ColBg], title_bg_dark);
   3988 		strcpy(colors[SchemeTitleSel][ColBg], title_bg_dark);
   3989 	}
   3990 	#endif // BAR_VTCOLORS_PATCH
   3991 	#if BAR_STATUS2D_PATCH && !BAR_STATUSCOLORS_PATCH
   3992 	scheme = ecalloc(LENGTH(colors) + 1, sizeof(Clr *));
   3993 	#if BAR_ALPHA_PATCH
   3994 	scheme[LENGTH(colors)] = drw_scm_create(drw, colors[0], alphas[0], ColCount);
   3995 	#else
   3996 	scheme[LENGTH(colors)] = drw_scm_create(drw, colors[0], ColCount);
   3997 	#endif // BAR_ALPHA_PATCH
   3998 	#else
   3999 	scheme = ecalloc(LENGTH(colors), sizeof(Clr *));
   4000 	#endif // BAR_STATUS2D_PATCH
   4001 	for (i = 0; i < LENGTH(colors); i++)
   4002 		#if BAR_ALPHA_PATCH
   4003 		scheme[i] = drw_scm_create(drw, colors[i], alphas[i], ColCount);
   4004 		#else
   4005 		scheme[i] = drw_scm_create(drw, colors[i], ColCount);
   4006 		#endif // BAR_ALPHA_PATCH
   4007 	#if BAR_POWERLINE_STATUS_PATCH
   4008 	statusscheme = ecalloc(LENGTH(statuscolors), sizeof(Clr *));
   4009 	for (i = 0; i < LENGTH(statuscolors); i++)
   4010 		#if BAR_ALPHA_PATCH
   4011 		statusscheme[i] = drw_scm_create(drw, statuscolors[i], alphas[0], ColCount);
   4012 		#else
   4013 		statusscheme[i] = drw_scm_create(drw, statuscolors[i], ColCount);
   4014 		#endif // BAR_ALPHA_PATCH
   4015 	#endif // BAR_POWERLINE_STATUS_PATCH
   4016 
   4017 	updatebars();
   4018 	updatestatus();
   4019 
   4020 	/* supporting window for NetWMCheck */
   4021 	wmcheckwin = XCreateSimpleWindow(dpy, root, 0, 0, 1, 1, 0, 0, 0);
   4022 	XChangeProperty(dpy, wmcheckwin, netatom[NetWMCheck], XA_WINDOW, 32,
   4023 		PropModeReplace, (unsigned char *) &wmcheckwin, 1);
   4024 	#if LG3D_PATCH
   4025 	XChangeProperty(dpy, wmcheckwin, netatom[NetWMName], utf8string, 8,
   4026 		PropModeReplace, (unsigned char *) "LG3D", 4);
   4027 	#else
   4028 	XChangeProperty(dpy, wmcheckwin, netatom[NetWMName], utf8string, 8,
   4029 		PropModeReplace, (unsigned char *) "dwm", 3);
   4030 	#endif // LG3D_PATCH
   4031 	XChangeProperty(dpy, root, netatom[NetWMCheck], XA_WINDOW, 32,
   4032 		PropModeReplace, (unsigned char *) &wmcheckwin, 1);
   4033 	/* EWMH support per view */
   4034 	XChangeProperty(dpy, root, netatom[NetSupported], XA_ATOM, 32,
   4035 		PropModeReplace, (unsigned char *) netatom, NetLast);
   4036 	#if BAR_EWMHTAGS_PATCH
   4037 	setnumdesktops();
   4038 	setcurrentdesktop();
   4039 	setdesktopnames();
   4040 	setviewport();
   4041 	#endif // BAR_EWMHTAGS_PATCH
   4042 	XDeleteProperty(dpy, root, netatom[NetClientList]);
   4043 	#if NET_CLIENT_LIST_STACKING_PATCH
   4044 	XDeleteProperty(dpy, root, netatom[NetClientListStacking]);
   4045 	#endif // NET_CLIENT_LIST_STACKING_PATCH
   4046 	/* select events */
   4047 	wa.cursor = cursor[CurNormal]->cursor;
   4048 	wa.event_mask = SubstructureRedirectMask|SubstructureNotifyMask
   4049 		|ButtonPressMask|PointerMotionMask|EnterWindowMask
   4050 		|LeaveWindowMask|StructureNotifyMask|PropertyChangeMask;
   4051 	XChangeWindowAttributes(dpy, root, CWEventMask|CWCursor, &wa);
   4052 	XSelectInput(dpy, root, wa.event_mask);
   4053 
   4054 	#if XKB_PATCH
   4055 	/* get xkb extension info, events and current state */
   4056 	if (!XkbQueryExtension(dpy, NULL, &xkbEventType, NULL, NULL, NULL))
   4057 		fputs("warning: can not query xkb extension\n", stderr);
   4058 	XkbSelectEventDetails(dpy, XkbUseCoreKbd, XkbStateNotify,
   4059 	                      XkbAllStateComponentsMask, XkbGroupStateMask);
   4060 	XkbGetState(dpy, XkbUseCoreKbd, &xkbstate);
   4061 	xkbGlobal.group = xkbstate.locked_group;
   4062 	#endif // XKB_PATCH
   4063 
   4064 	#if BANISH_PATCH
   4065 	if (!XQueryExtension(dpy, "XInputExtension", &xi_opcode, &i, &i)) {
   4066 		fprintf(stderr, "Warning: XInput is not available.");
   4067 	}
   4068 	/* Tell XInput to send us all RawMotion events. */
   4069 	unsigned char mask_bytes[XIMaskLen(XI_LASTEVENT)];
   4070 	memset(mask_bytes, 0, sizeof(mask_bytes));
   4071 	XISetMask(mask_bytes, XI_RawMotion);
   4072 	XISetMask(mask_bytes, XI_RawKeyRelease);
   4073 	XISetMask(mask_bytes, XI_RawTouchBegin);
   4074 	XISetMask(mask_bytes, XI_RawTouchEnd);
   4075 	XISetMask(mask_bytes, XI_RawTouchUpdate);
   4076 
   4077 	XIEventMask mask;
   4078 	mask.deviceid = XIAllMasterDevices;
   4079 	mask.mask_len = sizeof(mask_bytes);
   4080 	mask.mask = mask_bytes;
   4081 	XISelectEvents(dpy, root, &mask, 1);
   4082 	#endif // BANISH_PATCH
   4083 
   4084 	grabkeys();
   4085 	focus(NULL);
   4086 	#if IPC_PATCH
   4087 	setupepoll();
   4088 	#endif // IPC_PATCH
   4089 	#if BAR_ANYBAR_PATCH
   4090 	if (usealtbar)
   4091 		spawnbar();
   4092 	#endif // BAR_ANYBAR_PATCH
   4093 }
   4094 
   4095 
   4096 void
   4097 seturgent(Client *c, int urg)
   4098 {
   4099 	XWMHints *wmh;
   4100 
   4101 	c->isurgent = urg;
   4102 	if (!(wmh = XGetWMHints(dpy, c->win)))
   4103 		return;
   4104 	wmh->flags = urg ? (wmh->flags | XUrgencyHint) : (wmh->flags & ~XUrgencyHint);
   4105 	XSetWMHints(dpy, c->win, wmh);
   4106 	XFree(wmh);
   4107 }
   4108 
   4109 void
   4110 showhide(Client *c)
   4111 {
   4112 	if (!c)
   4113 		return;
   4114 	if (ISVISIBLE(c)) {
   4115 		#if !RENAMED_SCRATCHPADS_PATCH
   4116 		#if SCRATCHPADS_PATCH && SCRATCHPADS_KEEP_POSITION_AND_SIZE_PATCH
   4117 		if (
   4118 			(c->tags & SPTAGMASK) &&
   4119 			c->isfloating &&
   4120 			(
   4121 				c->x < c->mon->mx ||
   4122 				c->x > c->mon->mx + c->mon->mw ||
   4123 				c->y < c->mon->my ||
   4124 				c->y > c->mon->my + c->mon->mh
   4125 			)
   4126 		) {
   4127 			c->x = c->mon->wx + (c->mon->ww / 2 - WIDTH(c) / 2);
   4128 			c->y = c->mon->wy + (c->mon->wh / 2 - HEIGHT(c) / 2);
   4129 		}
   4130 		#elif SCRATCHPADS_PATCH
   4131 		if ((c->tags & SPTAGMASK) && c->isfloating) {
   4132 			c->x = c->mon->wx + (c->mon->ww / 2 - WIDTH(c) / 2);
   4133 			c->y = c->mon->wy + (c->mon->wh / 2 - HEIGHT(c) / 2);
   4134 		}
   4135 		#endif // SCRATCHPADS_KEEP_POSITION_AND_SIZE_PATCH | SCRATCHPADS_PATCH
   4136 		#endif // RENAMED_SCRATCHPADS_PATCH
   4137 		/* show clients top down */
   4138 		#if SAVEFLOATS_PATCH || EXRESIZE_PATCH
   4139 		if (!c->mon->lt[c->mon->sellt]->arrange && c->sfx != -9999 && !c->isfullscreen) {
   4140 			XMoveResizeWindow(dpy, c->win, c->sfx, c->sfy, c->sfw, c->sfh);
   4141 			resize(c, c->sfx, c->sfy, c->sfw, c->sfh, 0);
   4142 			showhide(c->snext);
   4143 			return;
   4144 		}
   4145 		#endif // SAVEFLOATS_PATCH / EXRESIZE_PATCH
   4146 		#if AUTORESIZE_PATCH
   4147 		if (c->needresize) {
   4148 			c->needresize = 0;
   4149 			XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h);
   4150 		} else {
   4151 			XMoveWindow(dpy, c->win, c->x, c->y);
   4152 		}
   4153 		#else
   4154 		XMoveWindow(dpy, c->win, c->x, c->y);
   4155 		#endif // AUTORESIZE_PATCH
   4156 		if ((!c->mon->lt[c->mon->sellt]->arrange || c->isfloating)
   4157 			#if !FAKEFULLSCREEN_PATCH
   4158 			&& !c->isfullscreen
   4159 			#endif // !FAKEFULLSCREEN_PATCH
   4160 			)
   4161 			resize(c, c->x, c->y, c->w, c->h, 0);
   4162 		showhide(c->snext);
   4163 	} else {
   4164 		#if RENAMED_SCRATCHPADS_PATCH && RENAMED_SCRATCHPADS_AUTO_HIDE_PATCH
   4165 		/* optional: auto-hide scratchpads when moving to other tags */
   4166 		if (c->scratchkey != 0 && !(c->tags & c->mon->tagset[c->mon->seltags]))
   4167 			c->tags = 0;
   4168 		#endif // RENAMED_SCRATCHPADS_AUTO_HIDE_PATCH
   4169 		/* hide clients bottom up */
   4170 		showhide(c->snext);
   4171 		XMoveWindow(dpy, c->win, WIDTH(c) * -2, c->y);
   4172 	}
   4173 }
   4174 
   4175 #if COOL_AUTOSTART_PATCH
   4176 void
   4177 sigchld(int unused)
   4178 {
   4179 	pid_t pid;
   4180 
   4181 	if (signal(SIGCHLD, sigchld) == SIG_ERR)
   4182 		die("can't install SIGCHLD handler:");
   4183 
   4184 	while (0 < (pid = waitpid(-1, NULL, WNOHANG))) {
   4185 		pid_t *p, *lim;
   4186 
   4187 		if (!(p = autostart_pids))
   4188 			continue;
   4189 		lim = &p[autostart_len];
   4190 
   4191 		for (; p < lim; p++) {
   4192 			if (*p == pid) {
   4193 				*p = -1;
   4194 				break;
   4195 			}
   4196 		}
   4197 	}
   4198 }
   4199 #endif // COOL_AUTOSTART_PATCH
   4200 
   4201 #if RIODRAW_PATCH
   4202 void
   4203 spawn(const Arg *arg)
   4204 {
   4205 	spawncmd(arg);
   4206 }
   4207 
   4208 pid_t
   4209 spawncmd(const Arg *arg)
   4210 #else
   4211 void
   4212 spawn(const Arg *arg)
   4213 #endif // RIODRAW_PATCH
   4214 {
   4215 	struct sigaction sa;
   4216 
   4217 	#if RIODRAW_PATCH
   4218 	pid_t pid;
   4219 	#endif // RIODRAW_PATCH
   4220 	#if !NODMENU_PATCH
   4221 	if (arg->v == dmenucmd)
   4222 		dmenumon[0] = '0' + selmon->num;
   4223 	#endif // NODMENU_PATCH
   4224 
   4225 	#if RIODRAW_PATCH
   4226 	if ((pid = fork()) == 0)
   4227 	#else
   4228 	if (fork() == 0)
   4229 	#endif // RIODRAW_PATCH
   4230 	{
   4231 		if (dpy)
   4232 			close(ConnectionNumber(dpy));
   4233 
   4234 		#if BAR_STATUSCMD_PATCH && !BAR_DWMBLOCKS_PATCH
   4235 		if (arg->v == statuscmd) {
   4236 			for (int i = 0; i < LENGTH(statuscmds); i++) {
   4237 				if (statuscmdn == statuscmds[i].id) {
   4238 					statuscmd[2] = statuscmds[i].cmd;
   4239 					setenv("BUTTON", lastbutton, 1);
   4240 					break;
   4241 				}
   4242 			}
   4243 			if (!statuscmd[2])
   4244 				exit(EXIT_SUCCESS);
   4245 		}
   4246 		#endif // BAR_STATUSCMD_PATCH | BAR_DWMBLOCKS_PATCH
   4247 		#if SPAWNCMD_PATCH
   4248 		if (selmon->sel) {
   4249 			const char* const home = getenv("HOME");
   4250 			assert(home && strchr(home, '/'));
   4251 			const size_t homelen = strlen(home);
   4252 			char *cwd, *pathbuf = NULL;
   4253 			struct stat statbuf;
   4254 
   4255 			cwd = strtok(selmon->sel->name, SPAWN_CWD_DELIM);
   4256 			/* NOTE: strtok() alters selmon->sel->name in-place,
   4257 			 * but that does not matter because we are going to
   4258 			 * exec() below anyway; nothing else will use it */
   4259 			while (cwd) {
   4260 				if (*cwd == '~') { /* replace ~ with $HOME */
   4261 					if (!(pathbuf = malloc(homelen + strlen(cwd)))) /* ~ counts for NULL term */
   4262 						die("fatal: could not malloc() %u bytes\n", homelen + strlen(cwd));
   4263 					strcpy(strcpy(pathbuf, home) + homelen, cwd + 1);
   4264 					cwd = pathbuf;
   4265 				}
   4266 
   4267 				if (strchr(cwd, '/') && !stat(cwd, &statbuf)) {
   4268 					if (!S_ISDIR(statbuf.st_mode))
   4269 						cwd = dirname(cwd);
   4270 
   4271 					if (!chdir(cwd))
   4272 						break;
   4273 				}
   4274 
   4275 				cwd = strtok(NULL, SPAWN_CWD_DELIM);
   4276 			}
   4277 
   4278 			free(pathbuf);
   4279 		}
   4280 		#endif // SPAWNCMD_PATCH
   4281 		setsid();
   4282 
   4283 		sigemptyset(&sa.sa_mask);
   4284 		sa.sa_flags = 0;
   4285 		sa.sa_handler = SIG_DFL;
   4286 		sigaction(SIGCHLD, &sa, NULL);
   4287 
   4288 		execvp(((char **)arg->v)[0], (char **)arg->v);
   4289 		die("dwm: execvp '%s' failed:", ((char **)arg->v)[0]);
   4290 	}
   4291 	#if RIODRAW_PATCH
   4292 	return pid;
   4293 	#endif // RIODRAW_PATCH
   4294 }
   4295 
   4296 void
   4297 tag(const Arg *arg)
   4298 {
   4299 	#if SWAPFOCUS_PATCH && PERTAG_PATCH
   4300 	unsigned int tagmask, tagindex;
   4301 	#endif // SWAPFOCUS_PATCH
   4302 
   4303 	if (selmon->sel && arg->ui & TAGMASK) {
   4304 		selmon->sel->tags = arg->ui & TAGMASK;
   4305 		#if SWITCHTAG_PATCH
   4306 		if (selmon->sel->switchtag)
   4307 			selmon->sel->switchtag = 0;
   4308 		#endif // SWITCHTAG_PATCH
   4309 		arrange(selmon);
   4310 		focus(NULL);
   4311 		#if SWAPFOCUS_PATCH && PERTAG_PATCH
   4312 		selmon->pertag->prevclient[selmon->pertag->curtag] = NULL;
   4313 		for (tagmask = arg->ui & TAGMASK, tagindex = 1; tagmask!=0; tagmask >>= 1, tagindex++)
   4314 			if (tagmask & 1)
   4315 				selmon->pertag->prevclient[tagindex] = NULL;
   4316 		#endif // SWAPFOCUS_PATCH
   4317 		#if VIEWONTAG_PATCH
   4318 		if ((arg->ui & TAGMASK) != selmon->tagset[selmon->seltags])
   4319 			view(arg);
   4320 		#endif // VIEWONTAG_PATCH
   4321 	}
   4322 }
   4323 
   4324 void
   4325 tagmon(const Arg *arg)
   4326 {
   4327 	Client *c = selmon->sel;
   4328 	Monitor *dest;
   4329 	#if SEAMLESS_RESTART_PATCH && SAVEFLOATS_PATCH
   4330 	int restored;
   4331 	#endif // SEAMLESS_RESTART_PATCH | SAVEFLOATS_PATCH
   4332 	if (!c || !mons->next)
   4333 		return;
   4334 	dest = dirtomon(arg->i);
   4335 	#if SEAMLESS_RESTART_PATCH && SAVEFLOATS_PATCH
   4336 	savewindowfloatposition(c, c->mon);
   4337 	restored = restorewindowfloatposition(c, dest);
   4338 	if (restored && (!dest->lt[dest->sellt]->arrange || c->isfloating)) {
   4339 		XMoveResizeWindow(dpy, c->win, c->sfx, c->sfy, c->sfw, c->sfh);
   4340 		resize(c, c->sfx, c->sfy, c->sfw, c->sfh, 1);
   4341 	}
   4342 	#endif // SEAMLESS_RESTART_PATCH | SAVEFLOATS_PATCH
   4343 	#if TAGMONFIXFS_PATCH
   4344 	if (c->isfullscreen) {
   4345 		c->isfullscreen = 0;
   4346 		sendmon(c, dest);
   4347 		c->isfullscreen = 1;
   4348 		#if !FAKEFULLSCREEN_PATCH && FAKEFULLSCREEN_CLIENT_PATCH
   4349 		if (c->fakefullscreen != 1) {
   4350 			resizeclient(c, c->mon->mx, c->mon->my, c->mon->mw, c->mon->mh);
   4351 			XRaiseWindow(dpy, c->win);
   4352 		}
   4353 		#elif !FAKEFULLSCREEN_PATCH
   4354 		resizeclient(c, c->mon->mx, c->mon->my, c->mon->mw, c->mon->mh);
   4355 		XRaiseWindow(dpy, c->win);
   4356 		#endif // FAKEFULLSCREEN_CLIENT_PATCH
   4357 	} else
   4358 		sendmon(c, dest);
   4359 	#else
   4360 	sendmon(c, dest);
   4361 	#endif // TAGMONFIXFS_PATCH
   4362 }
   4363 
   4364 void
   4365 togglebar(const Arg *arg)
   4366 {
   4367 	Bar *bar;
   4368 	#if BAR_HOLDBAR_PATCH && PERTAG_PATCH && PERTAGBAR_PATCH
   4369 	selmon->showbar = selmon->pertag->showbars[selmon->pertag->curtag] = (selmon->showbar == 2 ? 1 : !selmon->showbar);
   4370 	#elif BAR_HOLDBAR_PATCH
   4371 	selmon->showbar = (selmon->showbar == 2 ? 1 : !selmon->showbar);
   4372 	#elif PERTAG_PATCH && PERTAGBAR_PATCH
   4373 	selmon->showbar = selmon->pertag->showbars[selmon->pertag->curtag] = !selmon->showbar;
   4374 	#else
   4375 	selmon->showbar = !selmon->showbar;
   4376 	#endif // BAR_HOLDBAR_PATCH | PERTAG_PATCH
   4377 	updatebarpos(selmon);
   4378 	for (bar = selmon->bar; bar; bar = bar->next)
   4379 		XMoveResizeWindow(dpy, bar->win, bar->bx, bar->by, bar->bw, bar->bh);
   4380 	#if BAR_SYSTRAY_PATCH
   4381 	if (!selmon->showbar && systray)
   4382 		XMoveWindow(dpy, systray->win, -32000, -32000);
   4383 	#endif // BAR_SYSTRAY_PATCH
   4384 	arrange(selmon);
   4385 }
   4386 
   4387 void
   4388 togglefloating(const Arg *arg)
   4389 {
   4390 	Client *c = selmon->sel;
   4391 	if (arg && arg->v)
   4392 		c = (Client*)arg->v;
   4393 	if (!c)
   4394 		return;
   4395 	#if !FAKEFULLSCREEN_PATCH
   4396 	#if FAKEFULLSCREEN_CLIENT_PATCH
   4397 	if (c->isfullscreen && c->fakefullscreen != 1) /* no support for fullscreen windows */
   4398 		return;
   4399 	#else
   4400 	if (c->isfullscreen) /* no support for fullscreen windows */
   4401 		return;
   4402 	#endif // FAKEFULLSCREEN_CLIENT_PATCH
   4403 	#endif // !FAKEFULLSCREEN_PATCH
   4404 	c->isfloating = !c->isfloating || c->isfixed;
   4405 	#if !BAR_FLEXWINTITLE_PATCH
   4406 	#if RENAMED_SCRATCHPADS_PATCH
   4407 	if (c->scratchkey != 0 && c->isfloating)
   4408 		XSetWindowBorder(dpy, c->win, scheme[SchemeScratchSel][ColFloat].pixel);
   4409 	else if (c->scratchkey != 0)
   4410 		XSetWindowBorder(dpy, c->win, scheme[SchemeScratchSel][ColBorder].pixel);
   4411 	else if (c->isfloating)
   4412 		XSetWindowBorder(dpy, c->win, scheme[SchemeSel][ColFloat].pixel);
   4413 	else
   4414 		XSetWindowBorder(dpy, c->win, scheme[SchemeSel][ColBorder].pixel);
   4415 	#else
   4416 	if (c->isfloating)
   4417 		XSetWindowBorder(dpy, c->win, scheme[SchemeSel][ColFloat].pixel);
   4418 	else
   4419 		XSetWindowBorder(dpy, c->win, scheme[SchemeSel][ColBorder].pixel);
   4420 	#endif // RENAMED_SCRATCHPADS_PATCH
   4421 	#endif // BAR_FLEXWINTITLE_PATCH
   4422 	if (c->isfloating) {
   4423 		#if SAVEFLOATS_PATCH || EXRESIZE_PATCH
   4424 		if (c->sfx != -9999) {
   4425 			/* restore last known float dimensions */
   4426 			resize(c, c->sfx, c->sfy, c->sfw, c->sfh, 0);
   4427 		} else
   4428 		#endif // SAVEFLOATS_PATCH // EXRESIZE_PATCH
   4429 		resize(c, c->x, c->y, c->w, c->h, 0);
   4430 	#if SAVEFLOATS_PATCH || EXRESIZE_PATCH
   4431 	} else {
   4432 		/* save last known float dimensions */
   4433 		c->sfx = c->x;
   4434 		c->sfy = c->y;
   4435 		c->sfw = c->w;
   4436 		c->sfh = c->h;
   4437 		#if ALWAYSONTOP_PATCH
   4438 		c->alwaysontop = 0;
   4439 		#endif // ALWAYSONTOP_PATCH
   4440 	#elif ALWAYSONTOP_PATCH
   4441 	} else {
   4442 		c->alwaysontop = 0;
   4443 	#endif // SAVEFLOATS_PATCH | EXRESIZE_PATCH | ALWAYSONTOP_PATCH
   4444 	}
   4445 	arrange(c->mon);
   4446 
   4447 	#if BAR_EWMHTAGS_PATCH
   4448 	setfloatinghint(c);
   4449 	#endif // BAR_EWMHTAGS_PATCH
   4450 }
   4451 
   4452 void
   4453 toggletag(const Arg *arg)
   4454 {
   4455 	unsigned int newtags;
   4456 	#if SWAPFOCUS_PATCH && PERTAG_PATCH
   4457 	unsigned int tagmask, tagindex;
   4458 	#endif // SWAPFOCUS_PATCH
   4459 
   4460 	if (!selmon->sel)
   4461 		return;
   4462 	newtags = selmon->sel->tags ^ (arg->ui & TAGMASK);
   4463 	if (newtags) {
   4464 		selmon->sel->tags = newtags;
   4465 		arrange(selmon);
   4466 		focus(NULL);
   4467 		#if SWAPFOCUS_PATCH && PERTAG_PATCH
   4468 		for (tagmask = arg->ui & TAGMASK, tagindex = 1; tagmask!=0; tagmask >>= 1, tagindex++)
   4469 			if (tagmask & 1)
   4470 				selmon->pertag->prevclient[tagindex] = NULL;
   4471 		#endif // SWAPFOCUS_PATCH
   4472 	}
   4473 	#if BAR_EWMHTAGS_PATCH
   4474 	updatecurrentdesktop();
   4475 	#endif // BAR_EWMHTAGS_PATCH
   4476 }
   4477 
   4478 void
   4479 toggleview(const Arg *arg)
   4480 {
   4481 	unsigned int newtagset = selmon->tagset[selmon->seltags] ^ (arg->ui & TAGMASK);;
   4482 	#if TAGSYNC_PATCH
   4483 	Monitor *origselmon = selmon;
   4484 	for (selmon = mons; selmon; selmon = selmon->next) {
   4485 	#endif // TAGSYNC_PATCH
   4486 	#if PERTAG_PATCH
   4487 	int i;
   4488 	#endif // PERTAG_PATCH
   4489 
   4490 	#if TAGINTOSTACK_ALLMASTER_PATCH
   4491 	Client *const selected = selmon->sel;
   4492 
   4493 	// clients in the master area should be the same after we add a new tag
   4494 	Client **const masters = calloc(selmon->nmaster, sizeof(Client *));
   4495 	if (!masters) {
   4496 		die("fatal: could not calloc() %u bytes \n", selmon->nmaster * sizeof(Client *));
   4497 	}
   4498 	// collect (from last to first) references to all clients in the master area
   4499 	Client *c;
   4500 	size_t j;
   4501 	for (c = nexttiled(selmon->clients), j = 0; c && j < selmon->nmaster; c = nexttiled(c->next), ++j)
   4502 		masters[selmon->nmaster - (j + 1)] = c;
   4503 	// put the master clients at the front of the list
   4504 	// > go from the 'last' master to the 'first'
   4505 	for (j = 0; j < selmon->nmaster; ++j)
   4506 		if (masters[j])
   4507 			pop(masters[j]);
   4508 	free(masters);
   4509 
   4510 	// we also want to be sure not to mutate the focus
   4511 	focus(selected);
   4512 	#elif TAGINTOSTACK_ONEMASTER_PATCH
   4513 	// the first visible client should be the same after we add a new tag
   4514 	// we also want to be sure not to mutate the focus
   4515 	Client *const c = nexttiled(selmon->clients);
   4516 	if (c) {
   4517 		Client * const selected = selmon->sel;
   4518 		pop(c);
   4519 		focus(selected);
   4520 	}
   4521 	#endif // TAGINTOSTACK_ALLMASTER_PATCH / TAGINTOSTACK_ONEMASTER_PATCH
   4522 
   4523 	#if !EMPTYVIEW_PATCH
   4524 	if (newtagset) {
   4525 	#endif // EMPTYVIEW_PATCH
   4526 		#if BAR_TAGPREVIEW_PATCH
   4527 		tagpreviewswitchtag();
   4528 		#endif // BAR_TAGPREVIEW_PATCH
   4529 		selmon->tagset[selmon->seltags] = newtagset;
   4530 
   4531 		#if PERTAG_PATCH
   4532 		#if SCRATCHPADS_PATCH && !RENAMED_SCRATCHPADS_PATCH
   4533 		if (newtagset == ~SPTAGMASK)
   4534 		#else
   4535 		if (newtagset == ~0)
   4536 		#endif // SCRATCHPADS_PATCH
   4537 		{
   4538 			selmon->pertag->curtag = 0;
   4539 		}
   4540 		/* test if the user did not select the same tag */
   4541 		if (!(newtagset & 1 << (selmon->pertag->curtag - 1))) {
   4542 			for (i = 0; !(newtagset & 1 << i); i++) ;
   4543 			selmon->pertag->curtag = i + 1;
   4544 		}
   4545 
   4546 		/* apply settings for this view */
   4547 		selmon->nmaster = selmon->pertag->nmasters[selmon->pertag->curtag];
   4548 		selmon->mfact = selmon->pertag->mfacts[selmon->pertag->curtag];
   4549 		selmon->sellt = selmon->pertag->sellts[selmon->pertag->curtag];
   4550 		selmon->lt[selmon->sellt] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt];
   4551 		selmon->lt[selmon->sellt^1] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt^1];
   4552 		#if PERTAGBAR_PATCH
   4553 		if (selmon->showbar != selmon->pertag->showbars[selmon->pertag->curtag])
   4554 			togglebar(NULL);
   4555 		#endif // PERTAGBAR_PATCH
   4556 		#endif // PERTAG_PATCH
   4557 		#if !TAGSYNC_PATCH
   4558 		arrange(selmon);
   4559 		focus(NULL);
   4560 		#endif // TAGSYNC_PATCH
   4561 	#if !EMPTYVIEW_PATCH
   4562 	}
   4563 	#endif // EMPTYVIEW_PATCH
   4564 	#if TAGSYNC_PATCH
   4565 	}
   4566 	selmon = origselmon;
   4567 	#if !EMPTYVIEW_PATCH
   4568 	if (newtagset) {
   4569 	#endif // EMPTYVIEW_PATCH
   4570 		arrange(NULL);
   4571 		focus(NULL);
   4572 	#if !EMPTYVIEW_PATCH
   4573 	}
   4574 	#endif // EMPTYVIEW_PATCH
   4575 	#endif // TAGSYNC_PATCH
   4576 	#if BAR_EWMHTAGS_PATCH
   4577 	updatecurrentdesktop();
   4578 	#endif // BAR_EWMHTAGS_PATCH
   4579 }
   4580 
   4581 void
   4582 unfocus(Client *c, int setfocus, Client *nextfocus)
   4583 {
   4584 	if (!c)
   4585 		return;
   4586 
   4587 	#if SWAPFOCUS_PATCH && PERTAG_PATCH
   4588 	selmon->pertag->prevclient[selmon->pertag->curtag] = c;
   4589 	#endif // SWAPFOCUS_PATCH
   4590 	#if GAMES_PATCH
   4591 	if (c->isgame && c->isfullscreen) {
   4592 		minimize(c);
   4593 	}
   4594 	#endif // GAMES_PATCH
   4595 	#if GAMES_PATCH && LOSEFULLSCREEN_PATCH
   4596 	else
   4597 	#endif // GAMES_PATCH | LOSEFULLSCREEN_PATCH
   4598 	#if LOSEFULLSCREEN_PATCH
   4599 	if (c->isfullscreen && ISVISIBLE(c) && c->mon == selmon && nextfocus && !nextfocus->isfloating) {
   4600 		#if RENAMED_SCRATCHPADS_PATCH && RENAMED_SCRATCHPADS_AUTO_HIDE_PATCH
   4601 		#if FAKEFULLSCREEN_CLIENT_PATCH
   4602 		if (c->scratchkey != 0 && c->fakefullscreen != 1)
   4603 			togglescratch(&((Arg) {.v = (const char*[]){ &c->scratchkey, NULL } }));
   4604 		#else
   4605 		if (c->scratchkey != 0)
   4606 			togglescratch(&((Arg) {.v = (const char*[]){ &c->scratchkey, NULL } }));
   4607 		#endif // FAKEFULLSCREEN_CLIENT_PATCH
   4608 		else
   4609 		#endif // RENAMED_SCRATCHPADS_AUTO_HIDE_PATCH
   4610 		#if FAKEFULLSCREEN_CLIENT_PATCH
   4611 		if (c->fakefullscreen != 1)
   4612 			setfullscreen(c, 0);
   4613 		#else
   4614 		setfullscreen(c, 0);
   4615 		#endif // #if FAKEFULLSCREEN_CLIENT_PATCH
   4616 	}
   4617 	#endif // LOSEFULLSCREEN_PATCH
   4618 	grabbuttons(c, 0);
   4619 	#if !BAR_FLEXWINTITLE_PATCH
   4620 	#if RENAMED_SCRATCHPADS_PATCH
   4621 	if (c->scratchkey != 0 && c->isfloating)
   4622 		XSetWindowBorder(dpy, c->win, scheme[SchemeScratchNorm][ColFloat].pixel);
   4623 	else if (c->scratchkey != 0)
   4624 		XSetWindowBorder(dpy, c->win, scheme[SchemeScratchNorm][ColBorder].pixel);
   4625 	else if (c->isfloating)
   4626 		XSetWindowBorder(dpy, c->win, scheme[SchemeNorm][ColFloat].pixel);
   4627 	else
   4628 		XSetWindowBorder(dpy, c->win, scheme[SchemeNorm][ColBorder].pixel);
   4629 	#else
   4630 	if (c->isfloating)
   4631 		XSetWindowBorder(dpy, c->win, scheme[SchemeNorm][ColFloat].pixel);
   4632 	else
   4633 		XSetWindowBorder(dpy, c->win, scheme[SchemeNorm][ColBorder].pixel);
   4634 	#endif // RENAMED_SCRATCHPADS_PATCH
   4635 	#endif // BAR_FLEXWINTITLE_PATCH
   4636 	if (setfocus) {
   4637 		XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime);
   4638 		XDeleteProperty(dpy, root, netatom[NetActiveWindow]);
   4639 	}
   4640 }
   4641 
   4642 void
   4643 unmanage(Client *c, int destroyed)
   4644 {
   4645 	Monitor *m;
   4646 	#if SWITCHTAG_PATCH
   4647 	unsigned int switchtag = c->switchtag;
   4648 	#endif // SWITCHTAG_PATCH
   4649 	XWindowChanges wc;
   4650 	#if XKB_PATCH
   4651 	XkbInfo *xkb;
   4652 	#endif // XKB_PATCH
   4653 
   4654 	#if ZOOMSWAP_PATCH
   4655 	/* Make sure to clear any previous zoom references to the client being removed. */
   4656 	#if PERTAG_PATCH
   4657 	int i;
   4658 	for (m = mons; m; m = m->next) {
   4659 		for (i = 0; i <= NUMTAGS; i++) {
   4660 			if (m->pertag->prevzooms[i] == c) {
   4661 				m->pertag->prevzooms[i] = NULL;
   4662 			}
   4663 		}
   4664 	}
   4665 	#else
   4666 	if (c == prevzoom)
   4667 		prevzoom = NULL;
   4668 	#endif // PERTAG_PATCH
   4669 	#endif // ZOOMSWAP_PATCH
   4670 	m = c->mon;
   4671 
   4672 	#if SWALLOW_PATCH
   4673 	if (c->swallowing) {
   4674 		unswallow(c);
   4675 		return;
   4676 	}
   4677 
   4678 	Client *s = swallowingclient(c->win);
   4679 	if (s) {
   4680 		free(s->swallowing);
   4681 		s->swallowing = NULL;
   4682 		arrange(m);
   4683 		focus(NULL);
   4684 		return;
   4685 	}
   4686 	#endif // SWALLOW_PATCH
   4687 
   4688 	detach(c);
   4689 	detachstack(c);
   4690 	#if BAR_WINICON_PATCH
   4691 	freeicon(c);
   4692 	#endif // BAR_WINICON_PATCH
   4693 	if (!destroyed) {
   4694 		wc.border_width = c->oldbw;
   4695 		XGrabServer(dpy); /* avoid race conditions */
   4696 		XSetErrorHandler(xerrordummy);
   4697 		XSelectInput(dpy, c->win, NoEventMask);
   4698 		XConfigureWindow(dpy, c->win, CWBorderWidth, &wc); /* restore border */
   4699 		XUngrabButton(dpy, AnyButton, AnyModifier, c->win);
   4700 		if (!HIDDEN(c))
   4701 			setclientstate(c, WithdrawnState);
   4702 		XSync(dpy, False);
   4703 		XSetErrorHandler(xerror);
   4704 		XUngrabServer(dpy);
   4705 	}
   4706 	#if XKB_PATCH
   4707 	else {
   4708 		xkb = findxkb(c->win);
   4709 		if (xkb != NULL) {
   4710 			if (xkb->prev)
   4711 				xkb->prev->next = xkb->next;
   4712 			if (xkb->next)
   4713 				xkb->next->prev = xkb->prev;
   4714 			free(xkb);
   4715 		}
   4716 	}
   4717 	#endif // XKB_PATCH
   4718 
   4719 	#if SCRATCHPAD_ALT_1_PATCH
   4720 	if (scratchpad_last_showed == c)
   4721 		scratchpad_last_showed = NULL;
   4722 	#endif // SCRATCHPAD_ALT_1_PATCH
   4723 
   4724 	free(c);
   4725 	#if SWALLOW_PATCH
   4726 	if (s)
   4727 		return;
   4728 	#endif // SWALLOW_PATCH
   4729 	arrange(m);
   4730 	focus(NULL);
   4731 	updateclientlist();
   4732 	#if SWITCHTAG_PATCH
   4733 	if (switchtag && ((switchtag & TAGMASK) != selmon->tagset[selmon->seltags]))
   4734 		view(&((Arg) { .ui = switchtag }));
   4735 	#endif // SWITCHTAG_PATCH
   4736 }
   4737 
   4738 void
   4739 unmapnotify(XEvent *e)
   4740 {
   4741 	Client *c;
   4742 	#if BAR_ANYBAR_PATCH
   4743 	Monitor *m;
   4744 	Bar *bar;
   4745 	#endif // BAR_ANYBAR_PATCH
   4746 	XUnmapEvent *ev = &e->xunmap;
   4747 
   4748 	if ((c = wintoclient(ev->window))) {
   4749 		if (ev->send_event)
   4750 			setclientstate(c, WithdrawnState);
   4751 		else
   4752 			unmanage(c, 0);
   4753 	#if BAR_SYSTRAY_PATCH
   4754 	} else if (showsystray && (c = wintosystrayicon(ev->window))) {
   4755 		/* KLUDGE! sometimes icons occasionally unmap their windows, but do
   4756 		 * _not_ destroy them. We map those windows back */
   4757 		XMapRaised(dpy, c->win);
   4758 		removesystrayicon(c);
   4759 		drawbarwin(systray->bar);
   4760 	#endif // BAR_SYSTRAY_PATCH
   4761 	}
   4762 	#if BAR_ANYBAR_PATCH
   4763 	else {
   4764 		 m = wintomon(ev->window);
   4765 		 for (bar = m->bar; bar; bar = bar->next) {
   4766 		 	if (bar->win == ev->window) {
   4767 				unmanagealtbar(ev->window);
   4768 				break;
   4769 			}
   4770 		}
   4771 	}
   4772 	#endif // BAR_ANYBAR_PATCH
   4773 }
   4774 
   4775 void
   4776 updatebars(void)
   4777 {
   4778 	Bar *bar;
   4779 	Monitor *m;
   4780 	XSetWindowAttributes wa = {
   4781 		.override_redirect = True,
   4782 		#if BAR_ALPHA_PATCH
   4783 		.background_pixel = 0,
   4784 		.border_pixel = 0,
   4785 		.colormap = cmap,
   4786 		#else
   4787 		.background_pixmap = ParentRelative,
   4788 		#endif // BAR_ALPHA_PATCH
   4789 		#if BAR_TAGPREVIEW_PATCH
   4790 		.event_mask = ButtonPressMask|ExposureMask|PointerMotionMask
   4791 		#else
   4792 		.event_mask = ButtonPressMask|ExposureMask
   4793 		#endif // BAR_TAGPREVIEW_PATCH
   4794 	};
   4795 	XClassHint ch = {"dwm", "dwm"};
   4796 	for (m = mons; m; m = m->next) {
   4797 		for (bar = m->bar; bar; bar = bar->next) {
   4798 			if (bar->external)
   4799 				continue;
   4800 			if (!bar->win) {
   4801 				#if BAR_ALPHA_PATCH
   4802 				bar->win = XCreateWindow(dpy, root, bar->bx, bar->by, bar->bw, bar->bh, 0, depth,
   4803 				                          InputOutput, visual,
   4804 				                          CWOverrideRedirect|CWBackPixel|CWBorderPixel|CWColormap|CWEventMask, &wa);
   4805 				#else
   4806 				bar->win = XCreateWindow(dpy, root, bar->bx, bar->by, bar->bw, bar->bh, 0, DefaultDepth(dpy, screen),
   4807 						CopyFromParent, DefaultVisual(dpy, screen),
   4808 						CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa);
   4809 				#endif // BAR_ALPHA_PATCH
   4810 				XDefineCursor(dpy, bar->win, cursor[CurNormal]->cursor);
   4811 				XMapRaised(dpy, bar->win);
   4812 				XSetClassHint(dpy, bar->win, &ch);
   4813 			}
   4814 		}
   4815 		#if TAB_PATCH
   4816 		if (!m->tabwin) {
   4817 			#if BAR_ALPHA_PATCH
   4818 			m->tabwin = XCreateWindow(dpy, root, m->wx, m->ty, m->ww, th, 0, depth,
   4819 							InputOutput, visual,
   4820 							CWOverrideRedirect|CWBackPixel|CWBorderPixel|CWColormap|CWEventMask, &wa);
   4821 			#else
   4822 			m->tabwin = XCreateWindow(dpy, root, m->wx, m->ty, m->ww, th, 0, DefaultDepth(dpy, screen),
   4823 							CopyFromParent, DefaultVisual(dpy, screen),
   4824 							CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa);
   4825 			#endif // BAR_ALPHA_PATCH
   4826 			XDefineCursor(dpy, m->tabwin, cursor[CurNormal]->cursor);
   4827 			XMapRaised(dpy, m->tabwin);
   4828 		}
   4829 		#endif // TAB_PATCH
   4830 	}
   4831 }
   4832 
   4833 void
   4834 updatebarpos(Monitor *m)
   4835 {
   4836 	#if TAB_PATCH
   4837 	Client *c;
   4838 	int nvis = 0;
   4839 	#endif // TAB_PATCH
   4840 
   4841 	m->wx = m->mx;
   4842 	m->wy = m->my;
   4843 	m->ww = m->mw;
   4844 	m->wh = m->mh;
   4845 	Bar *bar;
   4846 	int y_pad = 0;
   4847 	int x_pad = 0;
   4848 	#if BAR_PADDING_VANITYGAPS_PATCH && VANITYGAPS_PATCH
   4849 	#if PERTAG_VANITYGAPS_PATCH && PERTAG_PATCH
   4850 	if (!selmon || selmon->pertag->enablegaps[selmon->pertag->curtag])
   4851 	#elif PERMON_VANITYGAPS_PATCH
   4852 	if (!selmon || selmon->enablegaps)
   4853 	#else
   4854 	if (enablegaps)
   4855 	#endif // PERTAG_VANITYGAPS_PATCH
   4856 	{
   4857 		#if BAR_PADDING_SMART_PATCH
   4858 		unsigned int n; Client *c;
   4859 		for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++);
   4860 		if (n > 1) {
   4861 			y_pad = gappoh;
   4862 			x_pad = gappov;
   4863 		}
   4864 		#else
   4865 		y_pad = gappoh;
   4866 		x_pad = gappov;
   4867 		#endif // BAR_PADDING_SMART_PATCH
   4868 	}
   4869 	#elif BAR_PADDING_PATCH
   4870 	#if BAR_PADDING_SMART_PATCH
   4871 	unsigned int n; Client *c;
   4872 	for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++);
   4873 	if (n > 1) {
   4874 		y_pad = vertpad;
   4875 		x_pad = sidepad;
   4876 	}
   4877 	#else
   4878 	y_pad = vertpad;
   4879 	x_pad = sidepad;
   4880 	#endif // BAR_PADDING_SMART_PATCH
   4881 	#endif // BAR_PADDING_PATCH | BAR_PADDING_VANITYGAPS_PATCH
   4882 
   4883 	#if INSETS_PATCH
   4884 	// Custom insets
   4885 	Inset inset = m->inset;
   4886 	m->wx += inset.x;
   4887 	m->wy += inset.y;
   4888 	m->ww -= inset.w + inset.x;
   4889 	m->wh -= inset.h + inset.y;
   4890 	#endif // INSETS_PATCH
   4891 
   4892 	for (bar = m->bar; bar; bar = bar->next) {
   4893 		bar->bx = m->wx + x_pad;
   4894 		#if BAR_ANYBAR_PATCH && !BAR_ANYBAR_MANAGE_WIDTH_PATCH
   4895 		if (bar->external)
   4896 			continue;
   4897 		#endif // BAR_ANYBAR_PATCH | BAR_ANYBAR_MANAGE_WIDTH_PATCH
   4898 		bar->bw = m->ww - 2 * x_pad;
   4899 	}
   4900 
   4901 	for (bar = m->bar; bar; bar = bar->next)
   4902 		if (!m->showbar || !bar->showbar)
   4903 			bar->by = -bar->bh - y_pad;
   4904 
   4905 	#if TAB_PATCH
   4906 	for (c = m->clients; c; c = c->next) {
   4907 		if (ISVISIBLE(c) && !HIDDEN(c))
   4908 			++nvis;
   4909 	}
   4910 
   4911 	if (m->showtab == showtab_always
   4912 	   || ((m->showtab == showtab_auto) && (nvis > 1) && (m->lt[m->sellt]->arrange == monocle))) {
   4913 		m->wh -= th;
   4914 		m->ty = m->toptab ? m->wy : m->wy + m->wh;
   4915 		if (m->toptab)
   4916 			m->wy += th;
   4917 	} else {
   4918 		m->ty = -th;
   4919 	}
   4920 	#endif // TAB_PATCH
   4921 
   4922 	if (!m->showbar)
   4923 		return;
   4924 	for (bar = m->bar; bar; bar = bar->next) {
   4925 		if (!bar->showbar)
   4926 			continue;
   4927 		#if BAR_HOLDBAR_PATCH
   4928 		if (m->showbar == 2) {
   4929 			bar->by = (bar->topbar ? m->wy : m->wy + m->wh - bar->bh);
   4930 			continue;
   4931 		}
   4932 		#endif // BAR_HOLDBAR_PATCH
   4933 		if (bar->topbar)
   4934 			m->wy = m->wy + bar->bh + y_pad;
   4935 		m->wh -= y_pad + bar->bh;
   4936 		bar->by = (bar->topbar ? m->wy - bar->bh : m->wy + m->wh);
   4937 	}
   4938 }
   4939 
   4940 void
   4941 updateclientlist(void)
   4942 {
   4943 	Client *c;
   4944 	Monitor *m;
   4945 
   4946 	XDeleteProperty(dpy, root, netatom[NetClientList]);
   4947 	for (m = mons; m; m = m->next)
   4948 		for (c = m->clients; c; c = c->next)
   4949 			XChangeProperty(dpy, root, netatom[NetClientList],
   4950 				XA_WINDOW, 32, PropModeAppend,
   4951 				(unsigned char *) &(c->win), 1);
   4952 
   4953 	#if NET_CLIENT_LIST_STACKING_PATCH
   4954 	XDeleteProperty(dpy, root, netatom[NetClientListStacking]);
   4955 	for (m = mons; m; m = m->next)
   4956 		for (c = m->stack; c; c = c->snext)
   4957 			XChangeProperty(dpy, root, netatom[NetClientListStacking],
   4958 				XA_WINDOW, 32, PropModeAppend,
   4959 				(unsigned char *) &(c->win), 1);
   4960 	#endif // NET_CLIENT_LIST_STACKING_PATCH
   4961 }
   4962 
   4963 int
   4964 updategeom(void)
   4965 {
   4966 	int dirty = 0;
   4967 
   4968 #ifdef XINERAMA
   4969 	if (XineramaIsActive(dpy)) {
   4970 		int i, j, n, nn;
   4971 		Client *c;
   4972 		Monitor *m;
   4973 		XineramaScreenInfo *info = XineramaQueryScreens(dpy, &nn);
   4974 		XineramaScreenInfo *unique = NULL;
   4975 
   4976 		for (n = 0, m = mons; m; m = m->next, n++);
   4977 		/* only consider unique geometries as separate screens */
   4978 		unique = ecalloc(nn, sizeof(XineramaScreenInfo));
   4979 		for (i = 0, j = 0; i < nn; i++)
   4980 			if (isuniquegeom(unique, j, &info[i]))
   4981 				memcpy(&unique[j++], &info[i], sizeof(XineramaScreenInfo));
   4982 		XFree(info);
   4983 		nn = j;
   4984 		#if SORTSCREENS_PATCH
   4985 		sortscreens(unique, nn);
   4986 		#endif // SORTSCREENS_PATCH
   4987 		/* new monitors if nn > n */
   4988 		for (i = n; i < nn; i++) {
   4989 			for (m = mons; m && m->next; m = m->next);
   4990 			if (m)
   4991 				m->next = createmon();
   4992 			else
   4993 				mons = createmon();
   4994 		}
   4995 		for (i = 0, m = mons; i < nn && m; m = m->next, i++)
   4996 			if (i >= n
   4997 			|| unique[i].x_org != m->mx || unique[i].y_org != m->my
   4998 			|| unique[i].width != m->mw || unique[i].height != m->mh)
   4999 			{
   5000 				dirty = 1;
   5001 				m->num = i;
   5002 				m->mx = m->wx = unique[i].x_org;
   5003 				m->my = m->wy = unique[i].y_org;
   5004 				m->mw = m->ww = unique[i].width;
   5005 				m->mh = m->wh = unique[i].height;
   5006 				updatebarpos(m);
   5007 			}
   5008 		/* removed monitors if n > nn */
   5009 		for (i = nn; i < n; i++) {
   5010 			for (m = mons; m && m->next; m = m->next);
   5011 			while ((c = m->clients)) {
   5012 				dirty = 1;
   5013 				m->clients = c->next;
   5014 				detachstack(c);
   5015 				c->mon = mons;
   5016 				attach(c);
   5017 				attachstack(c);
   5018 			}
   5019 			if (m == selmon)
   5020 				selmon = mons;
   5021 			cleanupmon(m);
   5022 		}
   5023 		free(unique);
   5024 	} else
   5025 #endif /* XINERAMA */
   5026 	{ /* default monitor setup */
   5027 		if (!mons)
   5028 			mons = createmon();
   5029 		if (mons->mw != sw || mons->mh != sh) {
   5030 			dirty = 1;
   5031 			mons->mw = mons->ww = sw;
   5032 			mons->mh = mons->wh = sh;
   5033 			updatebarpos(mons);
   5034 		}
   5035 	}
   5036 	if (dirty) {
   5037 		selmon = mons;
   5038 		selmon = wintomon(root);
   5039 	}
   5040 	return dirty;
   5041 }
   5042 
   5043 void
   5044 updatenumlockmask(void)
   5045 {
   5046 	unsigned int i, j;
   5047 	XModifierKeymap *modmap;
   5048 
   5049 	numlockmask = 0;
   5050 	modmap = XGetModifierMapping(dpy);
   5051 	for (i = 0; i < 8; i++)
   5052 		for (j = 0; j < modmap->max_keypermod; j++)
   5053 			if (modmap->modifiermap[i * modmap->max_keypermod + j]
   5054 				== XKeysymToKeycode(dpy, XK_Num_Lock))
   5055 				numlockmask = (1 << i);
   5056 	XFreeModifiermap(modmap);
   5057 }
   5058 
   5059 void
   5060 updatesizehints(Client *c)
   5061 {
   5062 	long msize;
   5063 	XSizeHints size;
   5064 
   5065 	if (!XGetWMNormalHints(dpy, c->win, &size, &msize))
   5066 		/* size is uninitialized, ensure that size.flags aren't used */
   5067 		#if SIZEHINTS_PATCH || SIZEHINTS_RULED_PATCH || SIZEHINTS_ISFREESIZE_PATCH
   5068 		size.flags = 0;
   5069 		#else
   5070 		size.flags = PSize;
   5071 		#endif // SIZEHINTS_PATCH | SIZEHINTS_RULED_PATCH | SIZEHINTS_ISFREESIZE_PATCH
   5072 	if (size.flags & PBaseSize) {
   5073 		c->basew = size.base_width;
   5074 		c->baseh = size.base_height;
   5075 	} else if (size.flags & PMinSize) {
   5076 		c->basew = size.min_width;
   5077 		c->baseh = size.min_height;
   5078 	} else
   5079 		c->basew = c->baseh = 0;
   5080 	if (size.flags & PResizeInc) {
   5081 		c->incw = size.width_inc;
   5082 		c->inch = size.height_inc;
   5083 	} else
   5084 		c->incw = c->inch = 0;
   5085 	if (size.flags & PMaxSize) {
   5086 		c->maxw = size.max_width;
   5087 		c->maxh = size.max_height;
   5088 	} else
   5089 		c->maxw = c->maxh = 0;
   5090 	if (size.flags & PMinSize) {
   5091 		c->minw = size.min_width;
   5092 		c->minh = size.min_height;
   5093 	} else if (size.flags & PBaseSize) {
   5094 		c->minw = size.base_width;
   5095 		c->minh = size.base_height;
   5096 	} else
   5097 		c->minw = c->minh = 0;
   5098 	if (size.flags & PAspect) {
   5099 		c->mina = (float)size.min_aspect.y / size.min_aspect.x;
   5100 		c->maxa = (float)size.max_aspect.x / size.max_aspect.y;
   5101 	} else
   5102 		c->maxa = c->mina = 0.0;
   5103 	#if SIZEHINTS_PATCH || SIZEHINTS_RULED_PATCH || SIZEHINTS_ISFREESIZE_PATCH
   5104 	#if SIZEHINTS_ISFREESIZE_PATCH
   5105 	if ((size.flags & PSize) && c->isfreesize)
   5106 	#else
   5107 	if (size.flags & PSize)
   5108 	#endif // SIZEHINTS_ISFREESIZE_PATCH
   5109 	{
   5110 		c->basew = size.base_width;
   5111 		c->baseh = size.base_height;
   5112 		c->isfloating = 1;
   5113 	}
   5114 	#if SIZEHINTS_RULED_PATCH
   5115 	checkfloatingrules(c);
   5116 	#endif // SIZEHINTS_RULED_PATCH
   5117 	#endif // SIZEHINTS_PATCH
   5118 	c->isfixed = (c->maxw && c->maxh && c->maxw == c->minw && c->maxh == c->minh);
   5119 	c->hintsvalid = 1;
   5120 }
   5121 
   5122 void
   5123 updatestatus(void)
   5124 {
   5125 	Monitor *m;
   5126 	#if BAR_EXTRASTATUS_PATCH
   5127 	if (!gettextprop(root, XA_WM_NAME, rawstext, sizeof(rawstext))) {
   5128 		strcpy(stext, "dwm-"VERSION);
   5129 		estext[0] = '\0';
   5130 	} else {
   5131 		char *e = strchr(rawstext, statussep);
   5132 		if (e) {
   5133 			*e = '\0'; e++;
   5134 			#if BAR_STATUSCMD_PATCH
   5135 			strncpy(rawestext, e, sizeof(estext) - 1);
   5136 			copyvalidchars(estext, rawestext);
   5137 			#else
   5138 			strncpy(estext, e, sizeof(estext) - 1);
   5139 			#endif // BAR_STATUSCMD_PATCH
   5140 		} else {
   5141 			estext[0] = '\0';
   5142 		}
   5143 		#if BAR_STATUSCMD_PATCH
   5144 		copyvalidchars(stext, rawstext);
   5145 		#else
   5146 		strncpy(stext, rawstext, sizeof(stext) - 1);
   5147 		#endif // BAR_STATUSCMD_PATCH
   5148 	}
   5149 	#elif BAR_STATUSCMD_PATCH
   5150 	if (!gettextprop(root, XA_WM_NAME, rawstext, sizeof(rawstext)))
   5151 		strcpy(stext, "dwm-"VERSION);
   5152 	else
   5153 		copyvalidchars(stext, rawstext);
   5154 	#else
   5155 	if (!gettextprop(root, XA_WM_NAME, stext, sizeof(stext)))
   5156 		strcpy(stext, "dwm-"VERSION);
   5157 	#endif // BAR_EXTRASTATUS_PATCH | BAR_STATUSCMD_PATCH
   5158 	for (m = mons; m; m = m->next)
   5159 		drawbar(m);
   5160 }
   5161 
   5162 void
   5163 updatetitle(Client *c)
   5164 {
   5165 	#if IPC_PATCH
   5166 	char oldname[sizeof(c->name)];
   5167 	strcpy(oldname, c->name);
   5168 	#endif // IPC_PATCH
   5169 
   5170 	if (!gettextprop(c->win, netatom[NetWMName], c->name, sizeof c->name))
   5171 		gettextprop(c->win, XA_WM_NAME, c->name, sizeof c->name);
   5172 	if (c->name[0] == '\0') /* hack to mark broken clients */
   5173 		strcpy(c->name, broken);
   5174 
   5175 	#if IPC_PATCH
   5176 	for (Monitor *m = mons; m; m = m->next) {
   5177 		if (m->sel == c && strcmp(oldname, c->name) != 0)
   5178 			ipc_focused_title_change_event(m->num, c->win, oldname, c->name);
   5179 	}
   5180 	#endif // IPC_PATCH
   5181 }
   5182 
   5183 void
   5184 updatewmhints(Client *c)
   5185 {
   5186 	XWMHints *wmh;
   5187 
   5188 	if ((wmh = XGetWMHints(dpy, c->win))) {
   5189 		if (c == selmon->sel && wmh->flags & XUrgencyHint) {
   5190 			wmh->flags &= ~XUrgencyHint;
   5191 			XSetWMHints(dpy, c->win, wmh);
   5192 		} else
   5193 			c->isurgent = (wmh->flags & XUrgencyHint) ? 1 : 0;
   5194 		if (c->isurgent) {
   5195 			if (c->isfloating)
   5196 				XSetWindowBorder(dpy, c->win, scheme[SchemeUrg][ColFloat].pixel);
   5197 			else
   5198 				XSetWindowBorder(dpy, c->win, scheme[SchemeUrg][ColBorder].pixel);
   5199 		}
   5200 		if (wmh->flags & InputHint)
   5201 			c->neverfocus = !wmh->input;
   5202 		else
   5203 			c->neverfocus = 0;
   5204 		XFree(wmh);
   5205 	}
   5206 }
   5207 
   5208 void
   5209 view(const Arg *arg)
   5210 {
   5211 	#if TAGSYNC_PATCH
   5212 	Monitor *origselmon = selmon;
   5213 	for (selmon = mons; selmon; selmon = selmon->next) {
   5214 	#endif // TAGSYNC_PATCH
   5215 	#if EMPTYVIEW_PATCH
   5216 	if (arg->ui && (arg->ui & TAGMASK) == selmon->tagset[selmon->seltags])
   5217 	#else
   5218 	if ((arg->ui & TAGMASK) == selmon->tagset[selmon->seltags])
   5219 	#endif // EMPTYVIEW_PATCH
   5220 	{
   5221 		#if TOGGLETAG_PATCH
   5222 		view(&((Arg) { .ui = 0 }));
   5223 		#endif // TOGGLETAG_PATCH
   5224 		return;
   5225 	}
   5226 	#if BAR_TAGPREVIEW_PATCH
   5227 	tagpreviewswitchtag();
   5228 	#endif // BAR_TAGPREVIEW_PATCH
   5229 	#if VIEW_HISTORY_PATCH
   5230 	if (!arg->ui) {
   5231 		selmon->seltags += 1;
   5232 		if (selmon->seltags == LENGTH(selmon->tagset))
   5233 			selmon->seltags = 0;
   5234 	} else {
   5235 		if (selmon->seltags == 0)
   5236 			selmon->seltags = LENGTH(selmon->tagset) - 1;
   5237 		else
   5238 			selmon->seltags -= 1;
   5239 	}
   5240 	#else
   5241 	selmon->seltags ^= 1; /* toggle sel tagset */
   5242 	#endif // VIEW_HISTORY_PATCH
   5243 	if (arg->ui & TAGMASK)
   5244 		selmon->tagset[selmon->seltags] = arg->ui & TAGMASK;
   5245 	#if PERTAG_PATCH
   5246 	pertagview(arg);
   5247 	#endif // PERTAG_PATCH
   5248 	#if TAGSYNC_PATCH
   5249 	}
   5250 	selmon = origselmon;
   5251 	#endif // TAGSYNC_PATCH
   5252 	#if TAGSYNC_PATCH
   5253 	arrange(NULL);
   5254 	#else
   5255 	arrange(selmon);
   5256 	#endif // TAGSYNC_PATCH
   5257 	focus(NULL);
   5258 	#if BAR_EWMHTAGS_PATCH
   5259 	updatecurrentdesktop();
   5260 	#endif // BAR_EWMHTAGS_PATCH
   5261 }
   5262 
   5263 Client *
   5264 wintoclient(Window w)
   5265 {
   5266 	Client *c;
   5267 	Monitor *m;
   5268 
   5269 	for (m = mons; m; m = m->next)
   5270 		for (c = m->clients; c; c = c->next)
   5271 			if (c->win == w)
   5272 				return c;
   5273 	return NULL;
   5274 }
   5275 
   5276 Monitor *
   5277 wintomon(Window w)
   5278 {
   5279 	int x, y;
   5280 	Client *c;
   5281 	Monitor *m;
   5282 	Bar *bar;
   5283 
   5284 	if (w == root && getrootptr(&x, &y))
   5285 		return recttomon(x, y, 1, 1);
   5286 	for (m = mons; m; m = m->next)
   5287 		for (bar = m->bar; bar; bar = bar->next)
   5288 			if (w == bar->win)
   5289 				return m;
   5290 	if ((c = wintoclient(w)))
   5291 		return c->mon;
   5292 	return selmon;
   5293 }
   5294 
   5295 /* There's no way to check accesses to destroyed windows, thus those cases are
   5296  * ignored (especially on UnmapNotify's). Other types of errors call Xlibs
   5297  * default error handler, which may call exit. */
   5298 int
   5299 xerror(Display *dpy, XErrorEvent *ee)
   5300 {
   5301 	if (ee->error_code == BadWindow
   5302 	|| (ee->request_code == X_SetInputFocus && ee->error_code == BadMatch)
   5303 	|| (ee->request_code == X_PolyText8 && ee->error_code == BadDrawable)
   5304 	|| (ee->request_code == X_PolyFillRectangle && ee->error_code == BadDrawable)
   5305 	|| (ee->request_code == X_PolySegment && ee->error_code == BadDrawable)
   5306 	|| (ee->request_code == X_ConfigureWindow && ee->error_code == BadMatch)
   5307 	|| (ee->request_code == X_GrabButton && ee->error_code == BadAccess)
   5308 	|| (ee->request_code == X_GrabKey && ee->error_code == BadAccess)
   5309 	|| (ee->request_code == X_CopyArea && ee->error_code == BadDrawable))
   5310 		return 0;
   5311 	fprintf(stderr, "dwm: fatal error: request code=%d, error code=%d\n",
   5312 		ee->request_code, ee->error_code);
   5313 	return xerrorxlib(dpy, ee); /* may call exit */
   5314 }
   5315 
   5316 int
   5317 xerrordummy(Display *dpy, XErrorEvent *ee)
   5318 {
   5319 	return 0;
   5320 }
   5321 
   5322 /* Startup Error handler to check if another window manager
   5323  * is already running. */
   5324 int
   5325 xerrorstart(Display *dpy, XErrorEvent *ee)
   5326 {
   5327 	die("dwm: another window manager is already running");
   5328 	return -1;
   5329 }
   5330 
   5331 void
   5332 zoom(const Arg *arg)
   5333 {
   5334 	Client *c = selmon->sel;
   5335 	#if FOCUSMASTER_RETURN_PATCH && ZOOMSWAP_PATCH
   5336 	int i;
   5337 	#endif // FOCUSMASTER_RETURN_PATCH
   5338 	if (arg && arg->v)
   5339 		c = (Client*)arg->v;
   5340 	if (!c)
   5341 		return;
   5342 	#if ZOOMSWAP_PATCH
   5343 	Client *at = NULL, *cold, *cprevious = NULL, *p;
   5344 	#endif // ZOOMSWAP_PATCH
   5345 
   5346 	#if ZOOMFLOATING_PATCH
   5347 	if (c && c->isfloating)
   5348 		togglefloating(&((Arg) { .v = c }));
   5349 	#endif // ZOOMFLOATING_PATCH
   5350 
   5351 	#if SWAPFOCUS_PATCH && PERTAG_PATCH
   5352 	c->mon->pertag->prevclient[c->mon->pertag->curtag] = nexttiled(c->mon->clients);
   5353 	#endif // SWAPFOCUS_PATCH
   5354 
   5355 	if (!c->mon->lt[c->mon->sellt]->arrange || !c || c->isfloating)
   5356 		return;
   5357 
   5358 	#if ZOOMSWAP_PATCH
   5359 	if (c == nexttiled(c->mon->clients)) {
   5360 		#if PERTAG_PATCH
   5361 		p = c->mon->pertag->prevzooms[c->mon->pertag->curtag];
   5362 		#else
   5363 		p = prevzoom;
   5364 		#endif // PERTAG_PATCH
   5365 		at = findbefore(p);
   5366 		if (at)
   5367 			cprevious = nexttiled(at->next);
   5368 		if (!cprevious || cprevious != p) {
   5369 			#if PERTAG_PATCH
   5370 			c->mon->pertag->prevzooms[c->mon->pertag->curtag] = NULL;
   5371 			#else
   5372 			prevzoom = NULL;
   5373 			#endif // PERTAG_PATCH
   5374 			#if SWAPFOCUS_PATCH && PERTAG_PATCH
   5375 			if (!c || !(c = c->mon->pertag->prevclient[c->mon->pertag->curtag] = nexttiled(c->next)))
   5376 			#else
   5377 			if (!c || !(c = nexttiled(c->next)))
   5378 			#endif // SWAPFOCUS_PATCH
   5379 				return;
   5380 		} else
   5381 			#if SWAPFOCUS_PATCH && PERTAG_PATCH
   5382 			c = c->mon->pertag->prevclient[c->mon->pertag->curtag] = cprevious;
   5383 			#else
   5384 			c = cprevious;
   5385 			#endif // SWAPFOCUS_PATCH
   5386 	}
   5387 
   5388 	cold = nexttiled(c->mon->clients);
   5389 	if (c != cold && !at)
   5390 		at = findbefore(c);
   5391 	#if FOCUSMASTER_RETURN_PATCH
   5392 	for (i = 0; !(selmon->tagset[selmon->seltags] & 1 << i); i++);
   5393 	i++;
   5394 
   5395 	c->mon->tagmarked[i] = cold;
   5396 	#endif // FOCUSMASTER_RETURN_PATCH
   5397 	detach(c);
   5398 	attach(c);
   5399 	/* swap windows instead of pushing the previous one down */
   5400 	if (c != cold && at) {
   5401 		#if PERTAG_PATCH
   5402 		c->mon->pertag->prevzooms[c->mon->pertag->curtag] = cold;
   5403 		#else
   5404 		prevzoom = cold;
   5405 		#endif // PERTAG_PATCH
   5406 		if (cold && at != cold) {
   5407 			detach(cold);
   5408 			cold->next = at->next;
   5409 			at->next = cold;
   5410 		}
   5411 	}
   5412 	focus(c);
   5413 	arrange(c->mon);
   5414 	#elif SWAPFOCUS_PATCH && PERTAG_PATCH
   5415 	if (c == nexttiled(c->mon->clients) && !(c = c->mon->pertag->prevclient[c->mon->pertag->curtag] = nexttiled(c->next)))
   5416 		return;
   5417 	pop(c);
   5418 	#else
   5419 	if (c == nexttiled(selmon->clients) && !(c = nexttiled(c->next)))
   5420 		return;
   5421 	pop(c);
   5422 	#endif // ZOOMSWAP_PATCH
   5423 }
   5424 
   5425 int
   5426 main(int argc, char *argv[])
   5427 {
   5428 	#if CMDCUSTOMIZE_PATCH
   5429 	for (int i=1;i<argc;i+=1)
   5430 		if (!strcmp("-v", argv[i]))
   5431 			die("dwm-"VERSION);
   5432 		else if (!strcmp("-h", argv[i]) || !strcmp("--help", argv[i]))
   5433 			die(help());
   5434 		else if (!strcmp("-fn", argv[i])) /* font set */
   5435 		#if BAR_PANGO_PATCH
   5436 			strcpy(font, argv[++i]);
   5437 		#else
   5438 			fonts[0] = argv[++i];
   5439 		#endif // BAR_PANGO_PATCH
   5440 		#if !BAR_VTCOLORS_PATCH
   5441 		else if (!strcmp("-nb", argv[i])) /* normal background color */
   5442 			colors[SchemeNorm][1] = argv[++i];
   5443 		else if (!strcmp("-nf", argv[i])) /* normal foreground color */
   5444 			colors[SchemeNorm][0] = argv[++i];
   5445 		else if (!strcmp("-sb", argv[i])) /* selected background color */
   5446 			colors[SchemeSel][1] = argv[++i];
   5447 		else if (!strcmp("-sf", argv[i])) /* selected foreground color */
   5448 			colors[SchemeSel][0] = argv[++i];
   5449 		#endif // !BAR_VTCOLORS_PATCH
   5450 		#if NODMENU_PATCH
   5451 		else if (!strcmp("-df", argv[i])) /* dmenu font */
   5452 			dmenucmd[2] = argv[++i];
   5453 		else if (!strcmp("-dnb", argv[i])) /* dmenu normal background color */
   5454 			dmenucmd[4] = argv[++i];
   5455 		else if (!strcmp("-dnf", argv[i])) /* dmenu normal foreground color */
   5456 			dmenucmd[6] = argv[++i];
   5457 		else if (!strcmp("-dsb", argv[i])) /* dmenu selected background color */
   5458 			dmenucmd[8] = argv[++i];
   5459 		else if (!strcmp("-dsf", argv[i])) /* dmenu selected foreground color */
   5460 			dmenucmd[10] = argv[++i];
   5461 		#else
   5462 		else if (!strcmp("-df", argv[i])) /* dmenu font */
   5463 			dmenucmd[4] = argv[++i];
   5464 		else if (!strcmp("-dnb", argv[i])) /* dmenu normal background color */
   5465 			dmenucmd[6] = argv[++i];
   5466 		else if (!strcmp("-dnf", argv[i])) /* dmenu normal foreground color */
   5467 			dmenucmd[8] = argv[++i];
   5468 		else if (!strcmp("-dsb", argv[i])) /* dmenu selected background color */
   5469 			dmenucmd[10] = argv[++i];
   5470 		else if (!strcmp("-dsf", argv[i])) /* dmenu selected foreground color */
   5471 			dmenucmd[12] = argv[++i];
   5472 		#endif // NODMENU_PATCH
   5473 		else die(help());
   5474 	#else
   5475 	if (argc == 2 && !strcmp("-v", argv[1]))
   5476 		die("dwm-"VERSION);
   5477 	else if (argc != 1)
   5478 		die("usage: dwm [-v]");
   5479 	#endif // CMDCUSTOMIZE_PATCH
   5480 	if (!setlocale(LC_CTYPE, "") || !XSupportsLocale())
   5481 		fputs("warning: no locale support\n", stderr);
   5482 	if (!(dpy = XOpenDisplay(NULL)))
   5483 		die("dwm: cannot open display");
   5484 	#if SWALLOW_PATCH
   5485 	if (!(xcon = XGetXCBConnection(dpy)))
   5486 		die("dwm: cannot get xcb connection\n");
   5487 	#endif // SWALLOW_PATCH
   5488 	checkotherwm();
   5489 	#if XRESOURCES_PATCH || XRDB_PATCH
   5490 	XrmInitialize();
   5491 	load_xresources();
   5492 	#endif // XRESOURCES_PATCH | XRDB_PATCH
   5493 	#if COOL_AUTOSTART_PATCH
   5494 	autostart_exec();
   5495 	#endif // COOL_AUTOSTART_PATCH
   5496 	setup();
   5497 #ifdef __OpenBSD__
   5498 	#if SWALLOW_PATCH
   5499 	if (pledge("stdio rpath proc exec ps", NULL) == -1)
   5500 	#else
   5501 	if (pledge("stdio rpath proc exec", NULL) == -1)
   5502 	#endif // SWALLOW_PATCH
   5503 		die("pledge");
   5504 #endif /* __OpenBSD__ */
   5505 	scan();
   5506 	#if AUTOSTART_PATCH
   5507 	runautostart();
   5508 	#endif
   5509 	run();
   5510 	cleanup();
   5511 	XCloseDisplay(dpy);
   5512 	#if RESTARTSIG_PATCH
   5513 	if (restart)
   5514 		execvp(argv[0], argv);
   5515 	#endif // RESTARTSIG_PATCH
   5516 	return EXIT_SUCCESS;
   5517 }
   5518