From 159c71295421c87875c0e1b8ecf2f02a20d30e14 Mon Sep 17 00:00:00 2001 From: cptbbVM Date: Mon, 11 Dec 2023 20:50:24 +0100 Subject: [PATCH] patch dwm centered mode --- dwm/config.def.h | 30 +- dwm/config.def.h.orig | 120 ++ dwm/config.h | 4 + dwm/drw.o | Bin 11072 -> 0 bytes dwm/dwm | Bin 67392 -> 0 bytes dwm/dwm.c | 105 ++ dwm/dwm.c.orig | 2178 +++++++++++++++++++++++++++++++++++ dwm/dwm.o | Bin 58104 -> 0 bytes dwm/patches/centermode.diff | 142 +++ dwm/util.o | Bin 2224 -> 0 bytes 10 files changed, 2566 insertions(+), 13 deletions(-) create mode 100644 dwm/config.def.h.orig delete mode 100644 dwm/drw.o delete mode 100755 dwm/dwm create mode 100644 dwm/dwm.c.orig delete mode 100644 dwm/dwm.o create mode 100644 dwm/patches/centermode.diff delete mode 100644 dwm/util.o diff --git a/dwm/config.def.h b/dwm/config.def.h index 564de19..7171f40 100644 --- a/dwm/config.def.h +++ b/dwm/config.def.h @@ -43,6 +43,8 @@ static const Layout layouts[] = { { "[]=", tile }, /* first entry is default */ { "><>", NULL }, /* no layout function means floating behavior */ { "[M]", monocle }, + { "|M|", centeredmaster }, + { ">M>", centeredfloatingmaster }, }; /* key definitions */ @@ -78,26 +80,28 @@ static const Key keys[] = { { MODKEY, XK_t, setlayout, {.v = &layouts[0]} }, { MODKEY, XK_f, setlayout, {.v = &layouts[1]} }, { MODKEY, XK_m, setlayout, {.v = &layouts[2]} }, + { MODKEY, XK_u, setlayout, {.v = &layouts[3]} }, + { MODKEY, XK_o, setlayout, {.v = &layouts[4]} }, { MODKEY, XK_space, setlayout, {0} }, { MODKEY|ShiftMask, XK_space, togglefloating, {0} }, - { MODKEY, XK_0, view, {.ui = ~0 } }, - { MODKEY|ShiftMask, XK_0, tag, {.ui = ~0 } }, + { MODKEY, XK_agrave, view, {.ui = ~0 } }, + { MODKEY|ShiftMask, XK_agrave, tag, {.ui = ~0 } }, { MODKEY, XK_comma, focusmon, {.i = -1 } }, - { MODKEY, XK_period, focusmon, {.i = +1 } }, + { MODKEY, XK_semicolon, focusmon, {.i = +1 } }, { MODKEY|ShiftMask, XK_comma, tagmon, {.i = -1 } }, - { MODKEY|ShiftMask, XK_period, tagmon, {.i = +1 } }, + { MODKEY|ShiftMask, XK_semicolon, tagmon, {.i = +1 } }, { MODKEY|ShiftMask, XK_minus, setgaps, {.i = -5 } }, { MODKEY|ShiftMask, XK_equal, setgaps, {.i = +5 } }, { MODKEY, XK_equal, setgaps, {.i = 0 } }, - TAGKEYS( XK_1, 0) - TAGKEYS( XK_2, 1) - TAGKEYS( XK_3, 2) - TAGKEYS( XK_4, 3) - TAGKEYS( XK_5, 4) - TAGKEYS( XK_6, 5) - TAGKEYS( XK_7, 6) - TAGKEYS( XK_8, 7) - TAGKEYS( XK_9, 8) + TAGKEYS( XK_ampersand, 0) + TAGKEYS( XK_eacute, 1) + TAGKEYS( XK_quotedbl, 2) + TAGKEYS( XK_apostrophe, 3) + TAGKEYS( XK_parenleft, 4) + TAGKEYS( XK_minus, 5) + TAGKEYS( XK_egrave, 6) + TAGKEYS( XK_underscore, 7) + TAGKEYS( XK_ccedilla, 8) { MODKEY|ShiftMask, XK_q, quit, {0} }, }; diff --git a/dwm/config.def.h.orig b/dwm/config.def.h.orig new file mode 100644 index 0000000..1216706 --- /dev/null +++ b/dwm/config.def.h.orig @@ -0,0 +1,120 @@ +/* See LICENSE file for copyright and license details. */ + +/* appearance */ +static const unsigned int borderpx = 3; /* border pixel of windows */ +static const unsigned int gappx = 10; /* gaps between windows */ +static const unsigned int snap = 32; /* snap pixel */ +static const int showbar = 1; /* 0 means no bar */ +static const int topbar = 1; /* 0 means bottom bar */ +static const char *fonts[] = { "monospace:size=12" }; +static const char dmenufont[] = "monospace:size=12"; +static const char col_gray1[] = "#119822"; +static const char col_gray2[] = "#2A7221"; +static const char col_gray3[] = "#1E441E"; +static const char col_gray4[] = "#152614"; +static const char col_cyan[] = "#31CB00"; +static const char *colors[][3] = { + /* fg bg border */ + [SchemeNorm] = { col_gray3, col_gray1, col_gray2 }, + [SchemeSel] = { col_gray4, col_cyan, col_cyan }, +}; + +/* tagging */ +static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" }; + +static const Rule rules[] = { + /* xprop(1): + * WM_CLASS(STRING) = instance, class + * WM_NAME(STRING) = title + */ + /* class instance title tags mask isfloating monitor */ + { "Gimp", NULL, NULL, 0, 1, -1 }, + { "Firefox", NULL, NULL, 1 << 8, 0, -1 }, +}; + +/* layout(s) */ +static const float mfact = 0.55; /* factor of master area size [0.05..0.95] */ +static const int nmaster = 1; /* number of clients in master area */ +static const int resizehints = 1; /* 1 means respect size hints in tiled resizals */ +static const int lockfullscreen = 1; /* 1 will force focus on the fullscreen window */ + +static const Layout layouts[] = { + /* symbol arrange function */ + { "[]=", tile }, /* first entry is default */ + { "><>", NULL }, /* no layout function means floating behavior */ + { "[M]", monocle }, +}; + +/* key definitions */ +#define MODKEY Mod4Mask +#define TAGKEYS(KEY,TAG) \ + { MODKEY, KEY, view, {.ui = 1 << TAG} }, \ + { MODKEY|ControlMask, KEY, toggleview, {.ui = 1 << TAG} }, \ + { MODKEY|ShiftMask, KEY, tag, {.ui = 1 << TAG} }, \ + { MODKEY|ControlMask|ShiftMask, KEY, toggletag, {.ui = 1 << TAG} }, + +/* helper for spawning shell commands in the pre dwm-5.0 fashion */ +#define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } } + +/* commands */ +static char dmenumon[2] = "0"; /* component of dmenucmd, manipulated in spawn() */ +static const char *dmenucmd[] = { "dmenu_run", "-m", dmenumon, "-fn", dmenufont, "-nb", col_gray1, "-nf", col_gray3, "-sb", col_cyan, "-sf", col_gray4, NULL }; +static const char *termcmd[] = { "st", NULL }; + +static const Key keys[] = { + /* modifier key function argument */ + { MODKEY, XK_p, spawn, {.v = dmenucmd } }, + { MODKEY, XK_s, spawn, {.v = termcmd } }, + { MODKEY, XK_b, togglebar, {0} }, + { MODKEY, XK_j, focusstack, {.i = +1 } }, + { MODKEY, XK_k, focusstack, {.i = -1 } }, + { MODKEY, XK_i, incnmaster, {.i = +1 } }, + { MODKEY, XK_d, incnmaster, {.i = -1 } }, + { MODKEY, XK_h, setmfact, {.f = -0.05} }, + { MODKEY, XK_l, setmfact, {.f = +0.05} }, + { MODKEY, XK_Return, zoom, {0} }, + { MODKEY, XK_Tab, view, {0} }, + { MODKEY, XK_c, killclient, {0} }, + { MODKEY, XK_t, setlayout, {.v = &layouts[0]} }, + { MODKEY, XK_f, setlayout, {.v = &layouts[1]} }, + { MODKEY, XK_m, setlayout, {.v = &layouts[2]} }, + { MODKEY, XK_space, setlayout, {0} }, + { MODKEY|ShiftMask, XK_space, togglefloating, {0} }, + { MODKEY, XK_agrave, view, {.ui = ~0 } }, + { MODKEY|ShiftMask, XK_agrave, tag, {.ui = ~0 } }, + { MODKEY, XK_comma, focusmon, {.i = -1 } }, + { MODKEY, XK_semicolon, focusmon, {.i = +1 } }, + { MODKEY|ShiftMask, XK_comma, tagmon, {.i = -1 } }, + { MODKEY|ShiftMask, XK_semicolon, tagmon, {.i = +1 } }, + { MODKEY|ShiftMask, XK_minus, setgaps, {.i = -5 } }, + { MODKEY|ShiftMask, XK_equal, setgaps, {.i = +5 } }, + { MODKEY, XK_equal, setgaps, {.i = 0 } }, + TAGKEYS( XK_ampersand, 0) + TAGKEYS( XK_eacute, 1) + TAGKEYS( XK_quotedbl, 2) + TAGKEYS( XK_apostrophe, 3) + TAGKEYS( XK_parenleft, 4) + TAGKEYS( XK_minus, 5) + TAGKEYS( XK_egrave, 6) + TAGKEYS( XK_underscore, 7) + TAGKEYS( XK_ccedilla, 8) + { MODKEY|ShiftMask, XK_q, quit, {0} }, +}; + +/* button definitions */ +/* click can be ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, or ClkRootWin */ +static const Button buttons[] = { + /* click event mask button function argument */ + { ClkLtSymbol, 0, Button1, setlayout, {0} }, + { ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]} }, + { ClkWinTitle, 0, Button2, zoom, {0} }, + { ClkStatusText, 0, Button2, spawn, {.v = termcmd } }, + { ClkClientWin, MODKEY, Button1, movemouse, {0} }, + { ClkClientWin, MODKEY, Button2, togglefloating, {0} }, + { ClkClientWin, MODKEY, Button3, resizemouse, {0} }, + { ClkTagBar, 0, Button1, view, {0} }, + { ClkTagBar, 0, Button3, toggleview, {0} }, + { ClkTagBar, MODKEY, Button1, tag, {0} }, + { ClkTagBar, MODKEY, Button3, toggletag, {0} }, +}; + diff --git a/dwm/config.h b/dwm/config.h index 1216706..7171f40 100644 --- a/dwm/config.h +++ b/dwm/config.h @@ -43,6 +43,8 @@ static const Layout layouts[] = { { "[]=", tile }, /* first entry is default */ { "><>", NULL }, /* no layout function means floating behavior */ { "[M]", monocle }, + { "|M|", centeredmaster }, + { ">M>", centeredfloatingmaster }, }; /* key definitions */ @@ -78,6 +80,8 @@ static const Key keys[] = { { MODKEY, XK_t, setlayout, {.v = &layouts[0]} }, { MODKEY, XK_f, setlayout, {.v = &layouts[1]} }, { MODKEY, XK_m, setlayout, {.v = &layouts[2]} }, + { MODKEY, XK_u, setlayout, {.v = &layouts[3]} }, + { MODKEY, XK_o, setlayout, {.v = &layouts[4]} }, { MODKEY, XK_space, setlayout, {0} }, { MODKEY|ShiftMask, XK_space, togglefloating, {0} }, { MODKEY, XK_agrave, view, {.ui = ~0 } }, diff --git a/dwm/drw.o b/dwm/drw.o deleted file mode 100644 index eb6ee1a9c9f5e11a38ee2dc8ca0d4fbe2252e873..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11072 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 A8~^|S diff --git a/dwm/dwm b/dwm/dwm deleted file mode 100755 index c52410c589ad066cee14e614965d1f4e205314bd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 67392 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 c; c = nexttiled(c->next), n++); + if (n == 0) + return; + + /* initialize areas */ + mw = m->ww; + mx = 0; + my = 0; + tw = mw; + + if (n > m->nmaster) { + /* go mfact box in the center if more than nmaster clients */ + mw = m->nmaster ? m->ww * m->mfact : 0; + tw = m->ww - mw; + + if (n - m->nmaster > 1) { + /* only one client */ + mx = (m->ww - mw) / 2; + tw = (m->ww - mw) / 2; + } + } + + oty = 0; + ety = 0; + for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) + if (i < m->nmaster) { + /* nmaster clients are stacked vertically, in the center + * of the screen */ + h = (m->wh - my) / (MIN(n, m->nmaster) - i); + resize(c, m->wx + mx, m->wy + my, mw - (2*c->bw), + h - (2*c->bw), 0); + my += HEIGHT(c); + } else { + /* stack clients are stacked vertically */ + if ((i - m->nmaster) % 2 ) { + h = (m->wh - ety) / ( (1 + n - i) / 2); + resize(c, m->wx, m->wy + ety, tw - (2*c->bw), + h - (2*c->bw), 0); + ety += HEIGHT(c); + } else { + h = (m->wh - oty) / ((1 + n - i) / 2); + resize(c, m->wx + mx + mw, m->wy + oty, + tw - (2*c->bw), h - (2*c->bw), 0); + oty += HEIGHT(c); + } + } +} + +void +centeredfloatingmaster(Monitor *m) +{ + unsigned int i, n, w, mh, mw, mx, mxo, my, myo, tx; + Client *c; + + /* count number of clients in the selected monitor */ + for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); + if (n == 0) + return; + + /* initialize nmaster area */ + if (n > m->nmaster) { + /* go mfact box in the center if more than nmaster clients */ + if (m->ww > m->wh) { + mw = m->nmaster ? m->ww * m->mfact : 0; + mh = m->nmaster ? m->wh * 0.9 : 0; + } else { + mh = m->nmaster ? m->wh * m->mfact : 0; + mw = m->nmaster ? m->ww * 0.9 : 0; + } + mx = mxo = (m->ww - mw) / 2; + my = myo = (m->wh - mh) / 2; + } else { + /* go fullscreen if all clients are in the master area */ + mh = m->wh; + mw = m->ww; + mx = mxo = 0; + my = myo = 0; + } + + for(i = tx = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) + if (i < m->nmaster) { + /* nmaster clients are stacked horizontally, in the center + * of the screen */ + w = (mw + mxo - mx) / (MIN(n, m->nmaster) - i); + resize(c, m->wx + mx, m->wy + my, w - (2*c->bw), + mh - (2*c->bw), 0); + mx += WIDTH(c); + } else { + /* stack clients are stacked horizontally */ + w = (m->ww - tx) / (n - i); + resize(c, m->wx + tx, m->wy, w - (2*c->bw), + m->wh - (2*c->bw), 0); + tx += WIDTH(c); + } +} diff --git a/dwm/dwm.c.orig b/dwm/dwm.c.orig new file mode 100644 index 0000000..4acfec7 --- /dev/null +++ b/dwm/dwm.c.orig @@ -0,0 +1,2178 @@ +/* See LICENSE file for copyright and license details. + * + * dynamic window manager is designed like any other X client as well. It is + * driven through handling X events. In contrast to other X clients, a window + * manager selects for SubstructureRedirectMask on the root window, to receive + * events about window (dis-)appearance. Only one X connection at a time is + * allowed to select for this event mask. + * + * The event handlers of dwm are organized in an array which is accessed + * whenever a new event has been fetched. This allows event dispatching + * in O(1) time. + * + * Each child of the root window is called a client, except windows which have + * set the override_redirect flag. Clients are organized in a linked client + * list on each monitor, the focus history is remembered through a stack list + * on each monitor. Each client contains a bit array to indicate the tags of a + * client. + * + * Keys and tagging rules are organized as arrays and defined in config.h. + * + * To understand everything else, start reading main(). + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef XINERAMA +#include +#endif /* XINERAMA */ +#include + +#include "drw.h" +#include "util.h" + +/* macros */ +#define BUTTONMASK (ButtonPressMask|ButtonReleaseMask) +#define CLEANMASK(mask) (mask & ~(numlockmask|LockMask) & (ShiftMask|ControlMask|Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask)) +#define INTERSECT(x,y,w,h,m) (MAX(0, MIN((x)+(w),(m)->wx+(m)->ww) - MAX((x),(m)->wx)) \ + * MAX(0, MIN((y)+(h),(m)->wy+(m)->wh) - MAX((y),(m)->wy))) +#define ISVISIBLE(C) ((C->tags & C->mon->tagset[C->mon->seltags])) +#define LENGTH(X) (sizeof X / sizeof X[0]) +#define MOUSEMASK (BUTTONMASK|PointerMotionMask) +#define WIDTH(X) ((X)->w + 2 * (X)->bw) +#define HEIGHT(X) ((X)->h + 2 * (X)->bw) +#define TAGMASK ((1 << LENGTH(tags)) - 1) +#define TEXTW(X) (drw_fontset_getwidth(drw, (X)) + lrpad) + +/* enums */ +enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */ +enum { SchemeNorm, SchemeSel }; /* color schemes */ +enum { NetSupported, NetWMName, NetWMState, NetWMCheck, + NetWMFullscreen, NetActiveWindow, NetWMWindowType, + NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH atoms */ +enum { WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast }; /* default atoms */ +enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, + ClkClientWin, ClkRootWin, ClkLast }; /* clicks */ + +typedef union { + int i; + unsigned int ui; + float f; + const void *v; +} Arg; + +typedef struct { + unsigned int click; + unsigned int mask; + unsigned int button; + void (*func)(const Arg *arg); + const Arg arg; +} Button; + +typedef struct Monitor Monitor; +typedef struct Client Client; +struct Client { + char name[256]; + float mina, maxa; + int x, y, w, h; + int oldx, oldy, oldw, oldh; + int basew, baseh, incw, inch, maxw, maxh, minw, minh, hintsvalid; + int bw, oldbw; + unsigned int tags; + int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen; + Client *next; + Client *snext; + Monitor *mon; + Window win; +}; + +typedef struct { + unsigned int mod; + KeySym keysym; + void (*func)(const Arg *); + const Arg arg; +} Key; + +typedef struct { + const char *symbol; + void (*arrange)(Monitor *); +} Layout; + +struct Monitor { + char ltsymbol[16]; + float mfact; + int nmaster; + int num; + int by; /* bar geometry */ + int mx, my, mw, mh; /* screen size */ + int wx, wy, ww, wh; /* window area */ + int gappx; /* gaps between windows */ + unsigned int seltags; + unsigned int sellt; + unsigned int tagset[2]; + int showbar; + int topbar; + Client *clients; + Client *sel; + Client *stack; + Monitor *next; + Window barwin; + const Layout *lt[2]; +}; + +typedef struct { + const char *class; + const char *instance; + const char *title; + unsigned int tags; + int isfloating; + int monitor; +} Rule; + +/* function declarations */ +static void applyrules(Client *c); +static int applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact); +static void arrange(Monitor *m); +static void arrangemon(Monitor *m); +static void attach(Client *c); +static void attachstack(Client *c); +static void buttonpress(XEvent *e); +static void checkotherwm(void); +static void cleanup(void); +static void cleanupmon(Monitor *mon); +static void clientmessage(XEvent *e); +static void configure(Client *c); +static void configurenotify(XEvent *e); +static void configurerequest(XEvent *e); +static Monitor *createmon(void); +static void destroynotify(XEvent *e); +static void detach(Client *c); +static void detachstack(Client *c); +static Monitor *dirtomon(int dir); +static void drawbar(Monitor *m); +static void drawbars(void); +static void enternotify(XEvent *e); +static void expose(XEvent *e); +static void focus(Client *c); +static void focusin(XEvent *e); +static void focusmon(const Arg *arg); +static void focusstack(const Arg *arg); +static Atom getatomprop(Client *c, Atom prop); +static int getrootptr(int *x, int *y); +static long getstate(Window w); +static int gettextprop(Window w, Atom atom, char *text, unsigned int size); +static void grabbuttons(Client *c, int focused); +static void grabkeys(void); +static void incnmaster(const Arg *arg); +static void keypress(XEvent *e); +static void killclient(const Arg *arg); +static void manage(Window w, XWindowAttributes *wa); +static void mappingnotify(XEvent *e); +static void maprequest(XEvent *e); +static void monocle(Monitor *m); +static void motionnotify(XEvent *e); +static void movemouse(const Arg *arg); +static Client *nexttiled(Client *c); +static void pop(Client *c); +static void propertynotify(XEvent *e); +static void quit(const Arg *arg); +static Monitor *recttomon(int x, int y, int w, int h); +static void resize(Client *c, int x, int y, int w, int h, int interact); +static void resizeclient(Client *c, int x, int y, int w, int h); +static void resizemouse(const Arg *arg); +static void restack(Monitor *m); +static void run(void); +static void scan(void); +static int sendevent(Client *c, Atom proto); +static void sendmon(Client *c, Monitor *m); +static void setclientstate(Client *c, long state); +static void setfocus(Client *c); +static void setfullscreen(Client *c, int fullscreen); +static void setgaps(const Arg *arg); +static void setlayout(const Arg *arg); +static void setmfact(const Arg *arg); +static void setup(void); +static void seturgent(Client *c, int urg); +static void showhide(Client *c); +static void spawn(const Arg *arg); +static void tag(const Arg *arg); +static void tagmon(const Arg *arg); +static void tile(Monitor *m); +static void togglebar(const Arg *arg); +static void togglefloating(const Arg *arg); +static void toggletag(const Arg *arg); +static void toggleview(const Arg *arg); +static void unfocus(Client *c, int setfocus); +static void unmanage(Client *c, int destroyed); +static void unmapnotify(XEvent *e); +static void updatebarpos(Monitor *m); +static void updatebars(void); +static void updateclientlist(void); +static int updategeom(void); +static void updatenumlockmask(void); +static void updatesizehints(Client *c); +static void updatestatus(void); +static void updatetitle(Client *c); +static void updatewindowtype(Client *c); +static void updatewmhints(Client *c); +static void view(const Arg *arg); +static Client *wintoclient(Window w); +static Monitor *wintomon(Window w); +static int xerror(Display *dpy, XErrorEvent *ee); +static int xerrordummy(Display *dpy, XErrorEvent *ee); +static int xerrorstart(Display *dpy, XErrorEvent *ee); +static void zoom(const Arg *arg); + +/* variables */ +static const char broken[] = "broken"; +static char stext[256]; +static int screen; +static int sw, sh; /* X display screen geometry width, height */ +static int bh; /* bar height */ +static int lrpad; /* sum of left and right padding for text */ +static int (*xerrorxlib)(Display *, XErrorEvent *); +static unsigned int numlockmask = 0; +static void (*handler[LASTEvent]) (XEvent *) = { + [ButtonPress] = buttonpress, + [ClientMessage] = clientmessage, + [ConfigureRequest] = configurerequest, + [ConfigureNotify] = configurenotify, + [DestroyNotify] = destroynotify, + [EnterNotify] = enternotify, + [Expose] = expose, + [FocusIn] = focusin, + [KeyPress] = keypress, + [MappingNotify] = mappingnotify, + [MapRequest] = maprequest, + [MotionNotify] = motionnotify, + [PropertyNotify] = propertynotify, + [UnmapNotify] = unmapnotify +}; +static Atom wmatom[WMLast], netatom[NetLast]; +static int running = 1; +static Cur *cursor[CurLast]; +static Clr **scheme; +static Display *dpy; +static Drw *drw; +static Monitor *mons, *selmon; +static Window root, wmcheckwin; + +/* configuration, allows nested code to access above variables */ +#include "config.h" + +/* compile-time check if all tags fit into an unsigned int bit array. */ +struct NumTags { char limitexceeded[LENGTH(tags) > 31 ? -1 : 1]; }; + +/* function implementations */ +void +applyrules(Client *c) +{ + const char *class, *instance; + unsigned int i; + const Rule *r; + Monitor *m; + XClassHint ch = { NULL, NULL }; + + /* rule matching */ + c->isfloating = 0; + c->tags = 0; + XGetClassHint(dpy, c->win, &ch); + class = ch.res_class ? ch.res_class : broken; + instance = ch.res_name ? ch.res_name : broken; + + for (i = 0; i < LENGTH(rules); i++) { + r = &rules[i]; + if ((!r->title || strstr(c->name, r->title)) + && (!r->class || strstr(class, r->class)) + && (!r->instance || strstr(instance, r->instance))) + { + c->isfloating = r->isfloating; + c->tags |= r->tags; + for (m = mons; m && m->num != r->monitor; m = m->next); + if (m) + c->mon = m; + } + } + if (ch.res_class) + XFree(ch.res_class); + if (ch.res_name) + XFree(ch.res_name); + c->tags = c->tags & TAGMASK ? c->tags & TAGMASK : c->mon->tagset[c->mon->seltags]; +} + +int +applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact) +{ + int baseismin; + Monitor *m = c->mon; + + /* set minimum possible */ + *w = MAX(1, *w); + *h = MAX(1, *h); + if (interact) { + if (*x > sw) + *x = sw - WIDTH(c); + if (*y > sh) + *y = sh - HEIGHT(c); + if (*x + *w + 2 * c->bw < 0) + *x = 0; + if (*y + *h + 2 * c->bw < 0) + *y = 0; + } else { + if (*x >= m->wx + m->ww) + *x = m->wx + m->ww - WIDTH(c); + if (*y >= m->wy + m->wh) + *y = m->wy + m->wh - HEIGHT(c); + if (*x + *w + 2 * c->bw <= m->wx) + *x = m->wx; + if (*y + *h + 2 * c->bw <= m->wy) + *y = m->wy; + } + if (*h < bh) + *h = bh; + if (*w < bh) + *w = bh; + if (resizehints || c->isfloating || !c->mon->lt[c->mon->sellt]->arrange) { + if (!c->hintsvalid) + updatesizehints(c); + /* see last two sentences in ICCCM 4.1.2.3 */ + baseismin = c->basew == c->minw && c->baseh == c->minh; + if (!baseismin) { /* temporarily remove base dimensions */ + *w -= c->basew; + *h -= c->baseh; + } + /* adjust for aspect limits */ + if (c->mina > 0 && c->maxa > 0) { + if (c->maxa < (float)*w / *h) + *w = *h * c->maxa + 0.5; + else if (c->mina < (float)*h / *w) + *h = *w * c->mina + 0.5; + } + if (baseismin) { /* increment calculation requires this */ + *w -= c->basew; + *h -= c->baseh; + } + /* adjust for increment value */ + if (c->incw) + *w -= *w % c->incw; + if (c->inch) + *h -= *h % c->inch; + /* restore base dimensions */ + *w = MAX(*w + c->basew, c->minw); + *h = MAX(*h + c->baseh, c->minh); + if (c->maxw) + *w = MIN(*w, c->maxw); + if (c->maxh) + *h = MIN(*h, c->maxh); + } + return *x != c->x || *y != c->y || *w != c->w || *h != c->h; +} + +void +arrange(Monitor *m) +{ + if (m) + showhide(m->stack); + else for (m = mons; m; m = m->next) + showhide(m->stack); + if (m) { + arrangemon(m); + restack(m); + } else for (m = mons; m; m = m->next) + arrangemon(m); +} + +void +arrangemon(Monitor *m) +{ + strncpy(m->ltsymbol, m->lt[m->sellt]->symbol, sizeof m->ltsymbol); + if (m->lt[m->sellt]->arrange) + m->lt[m->sellt]->arrange(m); +} + +void +attach(Client *c) +{ + c->next = c->mon->clients; + c->mon->clients = c; +} + +void +attachstack(Client *c) +{ + c->snext = c->mon->stack; + c->mon->stack = c; +} + +void +buttonpress(XEvent *e) +{ + unsigned int i, x, click; + Arg arg = {0}; + Client *c; + Monitor *m; + XButtonPressedEvent *ev = &e->xbutton; + + click = ClkRootWin; + /* focus monitor if necessary */ + if ((m = wintomon(ev->window)) && m != selmon) { + unfocus(selmon->sel, 1); + selmon = m; + focus(NULL); + } + if (ev->window == selmon->barwin) { + i = x = 0; + do + x += TEXTW(tags[i]); + while (ev->x >= x && ++i < LENGTH(tags)); + if (i < LENGTH(tags)) { + click = ClkTagBar; + arg.ui = 1 << i; + } else if (ev->x < x + TEXTW(selmon->ltsymbol)) + click = ClkLtSymbol; + else if (ev->x > selmon->ww - (int)TEXTW(stext)) + click = ClkStatusText; + else + click = ClkWinTitle; + } else if ((c = wintoclient(ev->window))) { + focus(c); + restack(selmon); + XAllowEvents(dpy, ReplayPointer, CurrentTime); + click = ClkClientWin; + } + for (i = 0; i < LENGTH(buttons); i++) + if (click == buttons[i].click && buttons[i].func && buttons[i].button == ev->button + && CLEANMASK(buttons[i].mask) == CLEANMASK(ev->state)) + buttons[i].func(click == ClkTagBar && buttons[i].arg.i == 0 ? &arg : &buttons[i].arg); +} + +void +checkotherwm(void) +{ + xerrorxlib = XSetErrorHandler(xerrorstart); + /* this causes an error if some other window manager is running */ + XSelectInput(dpy, DefaultRootWindow(dpy), SubstructureRedirectMask); + XSync(dpy, False); + XSetErrorHandler(xerror); + XSync(dpy, False); +} + +void +cleanup(void) +{ + Arg a = {.ui = ~0}; + Layout foo = { "", NULL }; + Monitor *m; + size_t i; + + view(&a); + selmon->lt[selmon->sellt] = &foo; + for (m = mons; m; m = m->next) + while (m->stack) + unmanage(m->stack, 0); + XUngrabKey(dpy, AnyKey, AnyModifier, root); + while (mons) + cleanupmon(mons); + for (i = 0; i < CurLast; i++) + drw_cur_free(drw, cursor[i]); + for (i = 0; i < LENGTH(colors); i++) + free(scheme[i]); + free(scheme); + XDestroyWindow(dpy, wmcheckwin); + drw_free(drw); + XSync(dpy, False); + XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime); + XDeleteProperty(dpy, root, netatom[NetActiveWindow]); +} + +void +cleanupmon(Monitor *mon) +{ + Monitor *m; + + if (mon == mons) + mons = mons->next; + else { + for (m = mons; m && m->next != mon; m = m->next); + m->next = mon->next; + } + XUnmapWindow(dpy, mon->barwin); + XDestroyWindow(dpy, mon->barwin); + free(mon); +} + +void +clientmessage(XEvent *e) +{ + XClientMessageEvent *cme = &e->xclient; + Client *c = wintoclient(cme->window); + + if (!c) + return; + if (cme->message_type == netatom[NetWMState]) { + if (cme->data.l[1] == netatom[NetWMFullscreen] + || cme->data.l[2] == netatom[NetWMFullscreen]) + setfullscreen(c, (cme->data.l[0] == 1 /* _NET_WM_STATE_ADD */ + || (cme->data.l[0] == 2 /* _NET_WM_STATE_TOGGLE */ && !c->isfullscreen))); + } else if (cme->message_type == netatom[NetActiveWindow]) { + if (c != selmon->sel && !c->isurgent) + seturgent(c, 1); + } +} + +void +configure(Client *c) +{ + XConfigureEvent ce; + + ce.type = ConfigureNotify; + ce.display = dpy; + ce.event = c->win; + ce.window = c->win; + ce.x = c->x; + ce.y = c->y; + ce.width = c->w; + ce.height = c->h; + ce.border_width = c->bw; + ce.above = None; + ce.override_redirect = False; + XSendEvent(dpy, c->win, False, StructureNotifyMask, (XEvent *)&ce); +} + +void +configurenotify(XEvent *e) +{ + Monitor *m; + Client *c; + XConfigureEvent *ev = &e->xconfigure; + int dirty; + + /* TODO: updategeom handling sucks, needs to be simplified */ + if (ev->window == root) { + dirty = (sw != ev->width || sh != ev->height); + sw = ev->width; + sh = ev->height; + if (updategeom() || dirty) { + drw_resize(drw, sw, bh); + updatebars(); + for (m = mons; m; m = m->next) { + for (c = m->clients; c; c = c->next) + if (c->isfullscreen) + resizeclient(c, m->mx, m->my, m->mw, m->mh); + XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, bh); + } + focus(NULL); + arrange(NULL); + } + } +} + +void +configurerequest(XEvent *e) +{ + Client *c; + Monitor *m; + XConfigureRequestEvent *ev = &e->xconfigurerequest; + XWindowChanges wc; + + if ((c = wintoclient(ev->window))) { + if (ev->value_mask & CWBorderWidth) + c->bw = ev->border_width; + else if (c->isfloating || !selmon->lt[selmon->sellt]->arrange) { + m = c->mon; + if (ev->value_mask & CWX) { + c->oldx = c->x; + c->x = m->mx + ev->x; + } + if (ev->value_mask & CWY) { + c->oldy = c->y; + c->y = m->my + ev->y; + } + if (ev->value_mask & CWWidth) { + c->oldw = c->w; + c->w = ev->width; + } + if (ev->value_mask & CWHeight) { + c->oldh = c->h; + c->h = ev->height; + } + if ((c->x + c->w) > m->mx + m->mw && c->isfloating) + c->x = m->mx + (m->mw / 2 - WIDTH(c) / 2); /* center in x direction */ + if ((c->y + c->h) > m->my + m->mh && c->isfloating) + c->y = m->my + (m->mh / 2 - HEIGHT(c) / 2); /* center in y direction */ + if ((ev->value_mask & (CWX|CWY)) && !(ev->value_mask & (CWWidth|CWHeight))) + configure(c); + if (ISVISIBLE(c)) + XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h); + } else + configure(c); + } else { + wc.x = ev->x; + wc.y = ev->y; + wc.width = ev->width; + wc.height = ev->height; + wc.border_width = ev->border_width; + wc.sibling = ev->above; + wc.stack_mode = ev->detail; + XConfigureWindow(dpy, ev->window, ev->value_mask, &wc); + } + XSync(dpy, False); +} + +Monitor * +createmon(void) +{ + Monitor *m; + + m = ecalloc(1, sizeof(Monitor)); + m->tagset[0] = m->tagset[1] = 1; + m->mfact = mfact; + m->nmaster = nmaster; + m->showbar = showbar; + m->topbar = topbar; + m->gappx = gappx; + m->lt[0] = &layouts[0]; + m->lt[1] = &layouts[1 % LENGTH(layouts)]; + strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol); + return m; +} + +void +destroynotify(XEvent *e) +{ + Client *c; + XDestroyWindowEvent *ev = &e->xdestroywindow; + + if ((c = wintoclient(ev->window))) + unmanage(c, 1); +} + +void +detach(Client *c) +{ + Client **tc; + + for (tc = &c->mon->clients; *tc && *tc != c; tc = &(*tc)->next); + *tc = c->next; +} + +void +detachstack(Client *c) +{ + Client **tc, *t; + + for (tc = &c->mon->stack; *tc && *tc != c; tc = &(*tc)->snext); + *tc = c->snext; + + if (c == c->mon->sel) { + for (t = c->mon->stack; t && !ISVISIBLE(t); t = t->snext); + c->mon->sel = t; + } +} + +Monitor * +dirtomon(int dir) +{ + Monitor *m = NULL; + + if (dir > 0) { + if (!(m = selmon->next)) + m = mons; + } else if (selmon == mons) + for (m = mons; m->next; m = m->next); + else + for (m = mons; m->next != selmon; m = m->next); + return m; +} + +void +drawbar(Monitor *m) +{ + int x, w, tw = 0; + int boxs = drw->fonts->h / 9; + int boxw = drw->fonts->h / 6 + 2; + unsigned int i, occ = 0, urg = 0; + Client *c; + + if (!m->showbar) + return; + + /* draw status first so it can be overdrawn by tags later */ + if (m == selmon) { /* status is only drawn on selected monitor */ + drw_setscheme(drw, scheme[SchemeNorm]); + tw = TEXTW(stext) - lrpad + 2; /* 2px right padding */ + drw_text(drw, m->ww - tw, 0, tw, bh, 0, stext, 0); + } + + for (c = m->clients; c; c = c->next) { + occ |= c->tags; + if (c->isurgent) + urg |= c->tags; + } + x = 0; + for (i = 0; i < LENGTH(tags); i++) { + w = TEXTW(tags[i]); + drw_setscheme(drw, scheme[m->tagset[m->seltags] & 1 << i ? SchemeSel : SchemeNorm]); + drw_text(drw, x, 0, w, bh, lrpad / 2, tags[i], urg & 1 << i); + if (occ & 1 << i) + drw_rect(drw, x + boxs, boxs, boxw, boxw, + m == selmon && selmon->sel && selmon->sel->tags & 1 << i, + urg & 1 << i); + x += w; + } + w = TEXTW(m->ltsymbol); + drw_setscheme(drw, scheme[SchemeNorm]); + x = drw_text(drw, x, 0, w, bh, lrpad / 2, m->ltsymbol, 0); + + if ((w = m->ww - tw - x) > bh) { + if (m->sel) { + drw_setscheme(drw, scheme[m == selmon ? SchemeSel : SchemeNorm]); + drw_text(drw, x, 0, w, bh, lrpad / 2, m->sel->name, 0); + if (m->sel->isfloating) + drw_rect(drw, x + boxs, boxs, boxw, boxw, m->sel->isfixed, 0); + } else { + drw_setscheme(drw, scheme[SchemeNorm]); + drw_rect(drw, x, 0, w, bh, 1, 1); + } + } + drw_map(drw, m->barwin, 0, 0, m->ww, bh); +} + +void +drawbars(void) +{ + Monitor *m; + + for (m = mons; m; m = m->next) + drawbar(m); +} + +void +enternotify(XEvent *e) +{ + Client *c; + Monitor *m; + XCrossingEvent *ev = &e->xcrossing; + + if ((ev->mode != NotifyNormal || ev->detail == NotifyInferior) && ev->window != root) + return; + c = wintoclient(ev->window); + m = c ? c->mon : wintomon(ev->window); + if (m != selmon) { + unfocus(selmon->sel, 1); + selmon = m; + } else if (!c || c == selmon->sel) + return; + focus(c); +} + +void +expose(XEvent *e) +{ + Monitor *m; + XExposeEvent *ev = &e->xexpose; + + if (ev->count == 0 && (m = wintomon(ev->window))) + drawbar(m); +} + +void +focus(Client *c) +{ + if (!c || !ISVISIBLE(c)) + for (c = selmon->stack; c && !ISVISIBLE(c); c = c->snext); + if (selmon->sel && selmon->sel != c) + unfocus(selmon->sel, 0); + if (c) { + if (c->mon != selmon) + selmon = c->mon; + if (c->isurgent) + seturgent(c, 0); + detachstack(c); + attachstack(c); + grabbuttons(c, 1); + XSetWindowBorder(dpy, c->win, scheme[SchemeSel][ColBorder].pixel); + setfocus(c); + } else { + XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime); + XDeleteProperty(dpy, root, netatom[NetActiveWindow]); + } + selmon->sel = c; + drawbars(); +} + +/* there are some broken focus acquiring clients needing extra handling */ +void +focusin(XEvent *e) +{ + XFocusChangeEvent *ev = &e->xfocus; + + if (selmon->sel && ev->window != selmon->sel->win) + setfocus(selmon->sel); +} + +void +focusmon(const Arg *arg) +{ + Monitor *m; + + if (!mons->next) + return; + if ((m = dirtomon(arg->i)) == selmon) + return; + unfocus(selmon->sel, 0); + selmon = m; + focus(NULL); +} + +void +focusstack(const Arg *arg) +{ + Client *c = NULL, *i; + + if (!selmon->sel || (selmon->sel->isfullscreen && lockfullscreen)) + return; + if (arg->i > 0) { + for (c = selmon->sel->next; c && !ISVISIBLE(c); c = c->next); + if (!c) + for (c = selmon->clients; c && !ISVISIBLE(c); c = c->next); + } else { + for (i = selmon->clients; i != selmon->sel; i = i->next) + if (ISVISIBLE(i)) + c = i; + if (!c) + for (; i; i = i->next) + if (ISVISIBLE(i)) + c = i; + } + if (c) { + focus(c); + restack(selmon); + } +} + +Atom +getatomprop(Client *c, Atom prop) +{ + int di; + unsigned long dl; + unsigned char *p = NULL; + Atom da, atom = None; + + if (XGetWindowProperty(dpy, c->win, prop, 0L, sizeof atom, False, XA_ATOM, + &da, &di, &dl, &dl, &p) == Success && p) { + atom = *(Atom *)p; + XFree(p); + } + return atom; +} + +int +getrootptr(int *x, int *y) +{ + int di; + unsigned int dui; + Window dummy; + + return XQueryPointer(dpy, root, &dummy, &dummy, x, y, &di, &di, &dui); +} + +long +getstate(Window w) +{ + int format; + long result = -1; + unsigned char *p = NULL; + unsigned long n, extra; + Atom real; + + if (XGetWindowProperty(dpy, w, wmatom[WMState], 0L, 2L, False, wmatom[WMState], + &real, &format, &n, &extra, (unsigned char **)&p) != Success) + return -1; + if (n != 0) + result = *p; + XFree(p); + return result; +} + +int +gettextprop(Window w, Atom atom, char *text, unsigned int size) +{ + char **list = NULL; + int n; + XTextProperty name; + + if (!text || size == 0) + return 0; + text[0] = '\0'; + if (!XGetTextProperty(dpy, w, &name, atom) || !name.nitems) + return 0; + if (name.encoding == XA_STRING) { + strncpy(text, (char *)name.value, size - 1); + } else if (XmbTextPropertyToTextList(dpy, &name, &list, &n) >= Success && n > 0 && *list) { + strncpy(text, *list, size - 1); + XFreeStringList(list); + } + text[size - 1] = '\0'; + XFree(name.value); + return 1; +} + +void +grabbuttons(Client *c, int focused) +{ + updatenumlockmask(); + { + unsigned int i, j; + unsigned int modifiers[] = { 0, LockMask, numlockmask, numlockmask|LockMask }; + XUngrabButton(dpy, AnyButton, AnyModifier, c->win); + if (!focused) + XGrabButton(dpy, AnyButton, AnyModifier, c->win, False, + BUTTONMASK, GrabModeSync, GrabModeSync, None, None); + for (i = 0; i < LENGTH(buttons); i++) + if (buttons[i].click == ClkClientWin) + for (j = 0; j < LENGTH(modifiers); j++) + XGrabButton(dpy, buttons[i].button, + buttons[i].mask | modifiers[j], + c->win, False, BUTTONMASK, + GrabModeAsync, GrabModeSync, None, None); + } +} + +void +grabkeys(void) +{ + updatenumlockmask(); + { + unsigned int i, j, k; + unsigned int modifiers[] = { 0, LockMask, numlockmask, numlockmask|LockMask }; + int start, end, skip; + KeySym *syms; + + XUngrabKey(dpy, AnyKey, AnyModifier, root); + XDisplayKeycodes(dpy, &start, &end); + syms = XGetKeyboardMapping(dpy, start, end - start + 1, &skip); + if (!syms) + return; + for (k = start; k <= end; k++) + for (i = 0; i < LENGTH(keys); i++) + /* skip modifier codes, we do that ourselves */ + if (keys[i].keysym == syms[(k - start) * skip]) + for (j = 0; j < LENGTH(modifiers); j++) + XGrabKey(dpy, k, + keys[i].mod | modifiers[j], + root, True, + GrabModeAsync, GrabModeAsync); + XFree(syms); + } +} + +void +incnmaster(const Arg *arg) +{ + selmon->nmaster = MAX(selmon->nmaster + arg->i, 0); + arrange(selmon); +} + +#ifdef XINERAMA +static int +isuniquegeom(XineramaScreenInfo *unique, size_t n, XineramaScreenInfo *info) +{ + while (n--) + if (unique[n].x_org == info->x_org && unique[n].y_org == info->y_org + && unique[n].width == info->width && unique[n].height == info->height) + return 0; + return 1; +} +#endif /* XINERAMA */ + +void +keypress(XEvent *e) +{ + unsigned int i; + KeySym keysym; + XKeyEvent *ev; + + ev = &e->xkey; + keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0); + for (i = 0; i < LENGTH(keys); i++) + if (keysym == keys[i].keysym + && CLEANMASK(keys[i].mod) == CLEANMASK(ev->state) + && keys[i].func) + keys[i].func(&(keys[i].arg)); +} + +void +killclient(const Arg *arg) +{ + if (!selmon->sel) + return; + if (!sendevent(selmon->sel, wmatom[WMDelete])) { + XGrabServer(dpy); + XSetErrorHandler(xerrordummy); + XSetCloseDownMode(dpy, DestroyAll); + XKillClient(dpy, selmon->sel->win); + XSync(dpy, False); + XSetErrorHandler(xerror); + XUngrabServer(dpy); + } +} + +void +manage(Window w, XWindowAttributes *wa) +{ + Client *c, *t = NULL; + Window trans = None; + XWindowChanges wc; + + c = ecalloc(1, sizeof(Client)); + c->win = w; + /* geometry */ + c->x = c->oldx = wa->x; + c->y = c->oldy = wa->y; + c->w = c->oldw = wa->width; + c->h = c->oldh = wa->height; + c->oldbw = wa->border_width; + + updatetitle(c); + if (XGetTransientForHint(dpy, w, &trans) && (t = wintoclient(trans))) { + c->mon = t->mon; + c->tags = t->tags; + } else { + c->mon = selmon; + applyrules(c); + } + + if (c->x + WIDTH(c) > c->mon->wx + c->mon->ww) + c->x = c->mon->wx + c->mon->ww - WIDTH(c); + if (c->y + HEIGHT(c) > c->mon->wy + c->mon->wh) + c->y = c->mon->wy + c->mon->wh - HEIGHT(c); + c->x = MAX(c->x, c->mon->wx); + c->y = MAX(c->y, c->mon->wy); + c->bw = borderpx; + + wc.border_width = c->bw; + XConfigureWindow(dpy, w, CWBorderWidth, &wc); + XSetWindowBorder(dpy, w, scheme[SchemeNorm][ColBorder].pixel); + configure(c); /* propagates border_width, if size doesn't change */ + updatewindowtype(c); + updatesizehints(c); + updatewmhints(c); + XSelectInput(dpy, w, EnterWindowMask|FocusChangeMask|PropertyChangeMask|StructureNotifyMask); + grabbuttons(c, 0); + if (!c->isfloating) + c->isfloating = c->oldstate = trans != None || c->isfixed; + if (c->isfloating) + XRaiseWindow(dpy, c->win); + attach(c); + attachstack(c); + XChangeProperty(dpy, root, netatom[NetClientList], XA_WINDOW, 32, PropModeAppend, + (unsigned char *) &(c->win), 1); + XMoveResizeWindow(dpy, c->win, c->x + 2 * sw, c->y, c->w, c->h); /* some windows require this */ + setclientstate(c, NormalState); + if (c->mon == selmon) + unfocus(selmon->sel, 0); + c->mon->sel = c; + arrange(c->mon); + XMapWindow(dpy, c->win); + focus(NULL); +} + +void +mappingnotify(XEvent *e) +{ + XMappingEvent *ev = &e->xmapping; + + XRefreshKeyboardMapping(ev); + if (ev->request == MappingKeyboard) + grabkeys(); +} + +void +maprequest(XEvent *e) +{ + static XWindowAttributes wa; + XMapRequestEvent *ev = &e->xmaprequest; + + if (!XGetWindowAttributes(dpy, ev->window, &wa) || wa.override_redirect) + return; + if (!wintoclient(ev->window)) + manage(ev->window, &wa); +} + +void +monocle(Monitor *m) +{ + unsigned int n = 0; + Client *c; + + for (c = m->clients; c; c = c->next) + if (ISVISIBLE(c)) + n++; + if (n > 0) /* override layout symbol */ + snprintf(m->ltsymbol, sizeof m->ltsymbol, "[%d]", n); + for (c = nexttiled(m->clients); c; c = nexttiled(c->next)) + resize(c, m->wx, m->wy, m->ww - 2 * c->bw, m->wh - 2 * c->bw, 0); +} + +void +motionnotify(XEvent *e) +{ + static Monitor *mon = NULL; + Monitor *m; + XMotionEvent *ev = &e->xmotion; + + if (ev->window != root) + return; + if ((m = recttomon(ev->x_root, ev->y_root, 1, 1)) != mon && mon) { + unfocus(selmon->sel, 1); + selmon = m; + focus(NULL); + } + mon = m; +} + +void +movemouse(const Arg *arg) +{ + int x, y, ocx, ocy, nx, ny; + Client *c; + Monitor *m; + XEvent ev; + Time lasttime = 0; + + if (!(c = selmon->sel)) + return; + if (c->isfullscreen) /* no support moving fullscreen windows by mouse */ + return; + restack(selmon); + ocx = c->x; + ocy = c->y; + if (XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, + None, cursor[CurMove]->cursor, CurrentTime) != GrabSuccess) + return; + if (!getrootptr(&x, &y)) + return; + do { + XMaskEvent(dpy, MOUSEMASK|ExposureMask|SubstructureRedirectMask, &ev); + switch(ev.type) { + case ConfigureRequest: + case Expose: + case MapRequest: + handler[ev.type](&ev); + break; + case MotionNotify: + if ((ev.xmotion.time - lasttime) <= (1000 / 60)) + continue; + lasttime = ev.xmotion.time; + + nx = ocx + (ev.xmotion.x - x); + ny = ocy + (ev.xmotion.y - y); + if (abs(selmon->wx - nx) < snap) + nx = selmon->wx; + else if (abs((selmon->wx + selmon->ww) - (nx + WIDTH(c))) < snap) + nx = selmon->wx + selmon->ww - WIDTH(c); + if (abs(selmon->wy - ny) < snap) + ny = selmon->wy; + else if (abs((selmon->wy + selmon->wh) - (ny + HEIGHT(c))) < snap) + ny = selmon->wy + selmon->wh - HEIGHT(c); + if (!c->isfloating && selmon->lt[selmon->sellt]->arrange + && (abs(nx - c->x) > snap || abs(ny - c->y) > snap)) + togglefloating(NULL); + if (!selmon->lt[selmon->sellt]->arrange || c->isfloating) + resize(c, nx, ny, c->w, c->h, 1); + break; + } + } while (ev.type != ButtonRelease); + XUngrabPointer(dpy, CurrentTime); + if ((m = recttomon(c->x, c->y, c->w, c->h)) != selmon) { + sendmon(c, m); + selmon = m; + focus(NULL); + } +} + +Client * +nexttiled(Client *c) +{ + for (; c && (c->isfloating || !ISVISIBLE(c)); c = c->next); + return c; +} + +void +pop(Client *c) +{ + detach(c); + attach(c); + focus(c); + arrange(c->mon); +} + +void +propertynotify(XEvent *e) +{ + Client *c; + Window trans; + XPropertyEvent *ev = &e->xproperty; + + if ((ev->window == root) && (ev->atom == XA_WM_NAME)) + updatestatus(); + else if (ev->state == PropertyDelete) + return; /* ignore */ + else if ((c = wintoclient(ev->window))) { + switch(ev->atom) { + default: break; + case XA_WM_TRANSIENT_FOR: + if (!c->isfloating && (XGetTransientForHint(dpy, c->win, &trans)) && + (c->isfloating = (wintoclient(trans)) != NULL)) + arrange(c->mon); + break; + case XA_WM_NORMAL_HINTS: + c->hintsvalid = 0; + break; + case XA_WM_HINTS: + updatewmhints(c); + drawbars(); + break; + } + if (ev->atom == XA_WM_NAME || ev->atom == netatom[NetWMName]) { + updatetitle(c); + if (c == c->mon->sel) + drawbar(c->mon); + } + if (ev->atom == netatom[NetWMWindowType]) + updatewindowtype(c); + } +} + +void +quit(const Arg *arg) +{ + running = 0; +} + +Monitor * +recttomon(int x, int y, int w, int h) +{ + Monitor *m, *r = selmon; + int a, area = 0; + + for (m = mons; m; m = m->next) + if ((a = INTERSECT(x, y, w, h, m)) > area) { + area = a; + r = m; + } + return r; +} + +void +resize(Client *c, int x, int y, int w, int h, int interact) +{ + if (applysizehints(c, &x, &y, &w, &h, interact)) + resizeclient(c, x, y, w, h); +} + +void +resizeclient(Client *c, int x, int y, int w, int h) +{ + XWindowChanges wc; + + c->oldx = c->x; c->x = wc.x = x; + c->oldy = c->y; c->y = wc.y = y; + c->oldw = c->w; c->w = wc.width = w; + c->oldh = c->h; c->h = wc.height = h; + wc.border_width = c->bw; + XConfigureWindow(dpy, c->win, CWX|CWY|CWWidth|CWHeight|CWBorderWidth, &wc); + configure(c); + XSync(dpy, False); +} + +void +resizemouse(const Arg *arg) +{ + int ocx, ocy, nw, nh; + Client *c; + Monitor *m; + XEvent ev; + Time lasttime = 0; + + if (!(c = selmon->sel)) + return; + if (c->isfullscreen) /* no support resizing fullscreen windows by mouse */ + return; + restack(selmon); + ocx = c->x; + ocy = c->y; + if (XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, + None, cursor[CurResize]->cursor, CurrentTime) != GrabSuccess) + return; + XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w + c->bw - 1, c->h + c->bw - 1); + do { + XMaskEvent(dpy, MOUSEMASK|ExposureMask|SubstructureRedirectMask, &ev); + switch(ev.type) { + case ConfigureRequest: + case Expose: + case MapRequest: + handler[ev.type](&ev); + break; + case MotionNotify: + if ((ev.xmotion.time - lasttime) <= (1000 / 60)) + continue; + lasttime = ev.xmotion.time; + + nw = MAX(ev.xmotion.x - ocx - 2 * c->bw + 1, 1); + nh = MAX(ev.xmotion.y - ocy - 2 * c->bw + 1, 1); + if (c->mon->wx + nw >= selmon->wx && c->mon->wx + nw <= selmon->wx + selmon->ww + && c->mon->wy + nh >= selmon->wy && c->mon->wy + nh <= selmon->wy + selmon->wh) + { + if (!c->isfloating && selmon->lt[selmon->sellt]->arrange + && (abs(nw - c->w) > snap || abs(nh - c->h) > snap)) + togglefloating(NULL); + } + if (!selmon->lt[selmon->sellt]->arrange || c->isfloating) + resize(c, c->x, c->y, nw, nh, 1); + break; + } + } while (ev.type != ButtonRelease); + XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w + c->bw - 1, c->h + c->bw - 1); + XUngrabPointer(dpy, CurrentTime); + while (XCheckMaskEvent(dpy, EnterWindowMask, &ev)); + if ((m = recttomon(c->x, c->y, c->w, c->h)) != selmon) { + sendmon(c, m); + selmon = m; + focus(NULL); + } +} + +void +restack(Monitor *m) +{ + Client *c; + XEvent ev; + XWindowChanges wc; + + drawbar(m); + if (!m->sel) + return; + if (m->sel->isfloating || !m->lt[m->sellt]->arrange) + XRaiseWindow(dpy, m->sel->win); + if (m->lt[m->sellt]->arrange) { + wc.stack_mode = Below; + wc.sibling = m->barwin; + for (c = m->stack; c; c = c->snext) + if (!c->isfloating && ISVISIBLE(c)) { + XConfigureWindow(dpy, c->win, CWSibling|CWStackMode, &wc); + wc.sibling = c->win; + } + } + XSync(dpy, False); + while (XCheckMaskEvent(dpy, EnterWindowMask, &ev)); +} + +void +run(void) +{ + XEvent ev; + /* main event loop */ + XSync(dpy, False); + while (running && !XNextEvent(dpy, &ev)) + if (handler[ev.type]) + handler[ev.type](&ev); /* call handler */ +} + +void +scan(void) +{ + unsigned int i, num; + Window d1, d2, *wins = NULL; + XWindowAttributes wa; + + if (XQueryTree(dpy, root, &d1, &d2, &wins, &num)) { + for (i = 0; i < num; i++) { + if (!XGetWindowAttributes(dpy, wins[i], &wa) + || wa.override_redirect || XGetTransientForHint(dpy, wins[i], &d1)) + continue; + if (wa.map_state == IsViewable || getstate(wins[i]) == IconicState) + manage(wins[i], &wa); + } + for (i = 0; i < num; i++) { /* now the transients */ + if (!XGetWindowAttributes(dpy, wins[i], &wa)) + continue; + if (XGetTransientForHint(dpy, wins[i], &d1) + && (wa.map_state == IsViewable || getstate(wins[i]) == IconicState)) + manage(wins[i], &wa); + } + if (wins) + XFree(wins); + } +} + +void +sendmon(Client *c, Monitor *m) +{ + if (c->mon == m) + return; + unfocus(c, 1); + detach(c); + detachstack(c); + c->mon = m; + c->tags = m->tagset[m->seltags]; /* assign tags of target monitor */ + attach(c); + attachstack(c); + focus(NULL); + arrange(NULL); +} + +void +setclientstate(Client *c, long state) +{ + long data[] = { state, None }; + + XChangeProperty(dpy, c->win, wmatom[WMState], wmatom[WMState], 32, + PropModeReplace, (unsigned char *)data, 2); +} + +int +sendevent(Client *c, Atom proto) +{ + int n; + Atom *protocols; + int exists = 0; + XEvent ev; + + if (XGetWMProtocols(dpy, c->win, &protocols, &n)) { + while (!exists && n--) + exists = protocols[n] == proto; + XFree(protocols); + } + if (exists) { + ev.type = ClientMessage; + ev.xclient.window = c->win; + ev.xclient.message_type = wmatom[WMProtocols]; + ev.xclient.format = 32; + ev.xclient.data.l[0] = proto; + ev.xclient.data.l[1] = CurrentTime; + XSendEvent(dpy, c->win, False, NoEventMask, &ev); + } + return exists; +} + +void +setfocus(Client *c) +{ + if (!c->neverfocus) { + XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime); + XChangeProperty(dpy, root, netatom[NetActiveWindow], + XA_WINDOW, 32, PropModeReplace, + (unsigned char *) &(c->win), 1); + } + sendevent(c, wmatom[WMTakeFocus]); +} + +void +setfullscreen(Client *c, int fullscreen) +{ + if (fullscreen && !c->isfullscreen) { + XChangeProperty(dpy, c->win, netatom[NetWMState], XA_ATOM, 32, + PropModeReplace, (unsigned char*)&netatom[NetWMFullscreen], 1); + c->isfullscreen = 1; + c->oldstate = c->isfloating; + c->oldbw = c->bw; + c->bw = 0; + c->isfloating = 1; + resizeclient(c, c->mon->mx, c->mon->my, c->mon->mw, c->mon->mh); + XRaiseWindow(dpy, c->win); + } else if (!fullscreen && c->isfullscreen){ + XChangeProperty(dpy, c->win, netatom[NetWMState], XA_ATOM, 32, + PropModeReplace, (unsigned char*)0, 0); + c->isfullscreen = 0; + c->isfloating = c->oldstate; + c->bw = c->oldbw; + c->x = c->oldx; + c->y = c->oldy; + c->w = c->oldw; + c->h = c->oldh; + resizeclient(c, c->x, c->y, c->w, c->h); + arrange(c->mon); + } +} + +void +setgaps(const Arg *arg) +{ + if ((arg->i == 0) || (selmon->gappx + arg->i < 0)) + selmon->gappx = 0; + else + selmon->gappx += arg->i; + arrange(selmon); +} + +void +setlayout(const Arg *arg) +{ + if (!arg || !arg->v || arg->v != selmon->lt[selmon->sellt]) + selmon->sellt ^= 1; + if (arg && arg->v) + selmon->lt[selmon->sellt] = (Layout *)arg->v; + strncpy(selmon->ltsymbol, selmon->lt[selmon->sellt]->symbol, sizeof selmon->ltsymbol); + if (selmon->sel) + arrange(selmon); + else + drawbar(selmon); +} + +/* arg > 1.0 will set mfact absolutely */ +void +setmfact(const Arg *arg) +{ + float f; + + if (!arg || !selmon->lt[selmon->sellt]->arrange) + return; + f = arg->f < 1.0 ? arg->f + selmon->mfact : arg->f - 1.0; + if (f < 0.05 || f > 0.95) + return; + selmon->mfact = f; + arrange(selmon); +} + +void +setup(void) +{ + int i; + XSetWindowAttributes wa; + Atom utf8string; + struct sigaction sa; + + /* do not transform children into zombies when they terminate */ + sigemptyset(&sa.sa_mask); + sa.sa_flags = SA_NOCLDSTOP | SA_NOCLDWAIT | SA_RESTART; + sa.sa_handler = SIG_IGN; + sigaction(SIGCHLD, &sa, NULL); + + /* clean up any zombies (inherited from .xinitrc etc) immediately */ + while (waitpid(-1, NULL, WNOHANG) > 0); + + /* init screen */ + screen = DefaultScreen(dpy); + sw = DisplayWidth(dpy, screen); + sh = DisplayHeight(dpy, screen); + root = RootWindow(dpy, screen); + drw = drw_create(dpy, screen, root, sw, sh); + if (!drw_fontset_create(drw, fonts, LENGTH(fonts))) + die("no fonts could be loaded."); + lrpad = drw->fonts->h; + bh = drw->fonts->h + 2; + updategeom(); + /* init atoms */ + utf8string = XInternAtom(dpy, "UTF8_STRING", False); + wmatom[WMProtocols] = XInternAtom(dpy, "WM_PROTOCOLS", False); + wmatom[WMDelete] = XInternAtom(dpy, "WM_DELETE_WINDOW", False); + wmatom[WMState] = XInternAtom(dpy, "WM_STATE", False); + wmatom[WMTakeFocus] = XInternAtom(dpy, "WM_TAKE_FOCUS", False); + netatom[NetActiveWindow] = XInternAtom(dpy, "_NET_ACTIVE_WINDOW", False); + netatom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False); + netatom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False); + netatom[NetWMState] = XInternAtom(dpy, "_NET_WM_STATE", False); + netatom[NetWMCheck] = XInternAtom(dpy, "_NET_SUPPORTING_WM_CHECK", False); + netatom[NetWMFullscreen] = XInternAtom(dpy, "_NET_WM_STATE_FULLSCREEN", False); + netatom[NetWMWindowType] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE", False); + netatom[NetWMWindowTypeDialog] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DIALOG", False); + netatom[NetClientList] = XInternAtom(dpy, "_NET_CLIENT_LIST", False); + /* init cursors */ + cursor[CurNormal] = drw_cur_create(drw, XC_left_ptr); + cursor[CurResize] = drw_cur_create(drw, XC_sizing); + cursor[CurMove] = drw_cur_create(drw, XC_fleur); + /* init appearance */ + scheme = ecalloc(LENGTH(colors), sizeof(Clr *)); + for (i = 0; i < LENGTH(colors); i++) + scheme[i] = drw_scm_create(drw, colors[i], 3); + /* init bars */ + updatebars(); + updatestatus(); + /* supporting window for NetWMCheck */ + wmcheckwin = XCreateSimpleWindow(dpy, root, 0, 0, 1, 1, 0, 0, 0); + XChangeProperty(dpy, wmcheckwin, netatom[NetWMCheck], XA_WINDOW, 32, + PropModeReplace, (unsigned char *) &wmcheckwin, 1); + XChangeProperty(dpy, wmcheckwin, netatom[NetWMName], utf8string, 8, + PropModeReplace, (unsigned char *) "dwm", 3); + XChangeProperty(dpy, root, netatom[NetWMCheck], XA_WINDOW, 32, + PropModeReplace, (unsigned char *) &wmcheckwin, 1); + /* EWMH support per view */ + XChangeProperty(dpy, root, netatom[NetSupported], XA_ATOM, 32, + PropModeReplace, (unsigned char *) netatom, NetLast); + XDeleteProperty(dpy, root, netatom[NetClientList]); + /* select events */ + wa.cursor = cursor[CurNormal]->cursor; + wa.event_mask = SubstructureRedirectMask|SubstructureNotifyMask + |ButtonPressMask|PointerMotionMask|EnterWindowMask + |LeaveWindowMask|StructureNotifyMask|PropertyChangeMask; + XChangeWindowAttributes(dpy, root, CWEventMask|CWCursor, &wa); + XSelectInput(dpy, root, wa.event_mask); + grabkeys(); + focus(NULL); +} + +void +seturgent(Client *c, int urg) +{ + XWMHints *wmh; + + c->isurgent = urg; + if (!(wmh = XGetWMHints(dpy, c->win))) + return; + wmh->flags = urg ? (wmh->flags | XUrgencyHint) : (wmh->flags & ~XUrgencyHint); + XSetWMHints(dpy, c->win, wmh); + XFree(wmh); +} + +void +showhide(Client *c) +{ + if (!c) + return; + if (ISVISIBLE(c)) { + /* show clients top down */ + XMoveWindow(dpy, c->win, c->x, c->y); + if ((!c->mon->lt[c->mon->sellt]->arrange || c->isfloating) && !c->isfullscreen) + resize(c, c->x, c->y, c->w, c->h, 0); + showhide(c->snext); + } else { + /* hide clients bottom up */ + showhide(c->snext); + XMoveWindow(dpy, c->win, WIDTH(c) * -2, c->y); + } +} + +void +spawn(const Arg *arg) +{ + struct sigaction sa; + + if (arg->v == dmenucmd) + dmenumon[0] = '0' + selmon->num; + if (fork() == 0) { + if (dpy) + close(ConnectionNumber(dpy)); + setsid(); + + sigemptyset(&sa.sa_mask); + sa.sa_flags = 0; + sa.sa_handler = SIG_DFL; + sigaction(SIGCHLD, &sa, NULL); + + execvp(((char **)arg->v)[0], (char **)arg->v); + die("dwm: execvp '%s' failed:", ((char **)arg->v)[0]); + } +} + +void +tag(const Arg *arg) +{ + if (selmon->sel && arg->ui & TAGMASK) { + selmon->sel->tags = arg->ui & TAGMASK; + focus(NULL); + arrange(selmon); + } +} + +void +tagmon(const Arg *arg) +{ + if (!selmon->sel || !mons->next) + return; + sendmon(selmon->sel, dirtomon(arg->i)); +} + +void +tile(Monitor *m) +{ + unsigned int i, n, h, mw, my, ty; + Client *c; + + for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); + if (n == 0) + return; + + if (n > m->nmaster) + mw = m->nmaster ? m->ww * m->mfact : 0; + else + mw = m->ww - m->gappx; + for (i = 0, my = ty = m->gappx, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) + if (i < m->nmaster) { + h = (m->wh - my) / (MIN(n, m->nmaster) - i) - m->gappx; + resize(c, m->wx + m->gappx, m->wy + my, mw - (2*c->bw) - m->gappx, h - (2*c->bw), 0); + if (my + HEIGHT(c) + m->gappx < m->wh) + my += HEIGHT(c) + m->gappx; + } else { + h = (m->wh - ty) / (n - i) - m->gappx; + resize(c, m->wx + mw + m->gappx, m->wy + ty, m->ww - mw - (2*c->bw) - 2*m->gappx, h - (2*c->bw), 0); + if (ty + HEIGHT(c) + m->gappx < m->wh) + ty += HEIGHT(c) + m->gappx; + } +} + +void +togglebar(const Arg *arg) +{ + selmon->showbar = !selmon->showbar; + updatebarpos(selmon); + XMoveResizeWindow(dpy, selmon->barwin, selmon->wx, selmon->by, selmon->ww, bh); + arrange(selmon); +} + +void +togglefloating(const Arg *arg) +{ + if (!selmon->sel) + return; + if (selmon->sel->isfullscreen) /* no support for fullscreen windows */ + return; + selmon->sel->isfloating = !selmon->sel->isfloating || selmon->sel->isfixed; + if (selmon->sel->isfloating) + resize(selmon->sel, selmon->sel->x, selmon->sel->y, + selmon->sel->w, selmon->sel->h, 0); + arrange(selmon); +} + +void +toggletag(const Arg *arg) +{ + unsigned int newtags; + + if (!selmon->sel) + return; + newtags = selmon->sel->tags ^ (arg->ui & TAGMASK); + if (newtags) { + selmon->sel->tags = newtags; + focus(NULL); + arrange(selmon); + } +} + +void +toggleview(const Arg *arg) +{ + unsigned int newtagset = selmon->tagset[selmon->seltags] ^ (arg->ui & TAGMASK); + + if (newtagset) { + selmon->tagset[selmon->seltags] = newtagset; + focus(NULL); + arrange(selmon); + } +} + +void +unfocus(Client *c, int setfocus) +{ + if (!c) + return; + grabbuttons(c, 0); + XSetWindowBorder(dpy, c->win, scheme[SchemeNorm][ColBorder].pixel); + if (setfocus) { + XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime); + XDeleteProperty(dpy, root, netatom[NetActiveWindow]); + } +} + +void +unmanage(Client *c, int destroyed) +{ + Monitor *m = c->mon; + XWindowChanges wc; + + detach(c); + detachstack(c); + if (!destroyed) { + wc.border_width = c->oldbw; + XGrabServer(dpy); /* avoid race conditions */ + XSetErrorHandler(xerrordummy); + XSelectInput(dpy, c->win, NoEventMask); + XConfigureWindow(dpy, c->win, CWBorderWidth, &wc); /* restore border */ + XUngrabButton(dpy, AnyButton, AnyModifier, c->win); + setclientstate(c, WithdrawnState); + XSync(dpy, False); + XSetErrorHandler(xerror); + XUngrabServer(dpy); + } + free(c); + focus(NULL); + updateclientlist(); + arrange(m); +} + +void +unmapnotify(XEvent *e) +{ + Client *c; + XUnmapEvent *ev = &e->xunmap; + + if ((c = wintoclient(ev->window))) { + if (ev->send_event) + setclientstate(c, WithdrawnState); + else + unmanage(c, 0); + } +} + +void +updatebars(void) +{ + Monitor *m; + XSetWindowAttributes wa = { + .override_redirect = True, + .background_pixmap = ParentRelative, + .event_mask = ButtonPressMask|ExposureMask + }; + XClassHint ch = {"dwm", "dwm"}; + for (m = mons; m; m = m->next) { + if (m->barwin) + continue; + m->barwin = XCreateWindow(dpy, root, m->wx, m->by, m->ww, bh, 0, DefaultDepth(dpy, screen), + CopyFromParent, DefaultVisual(dpy, screen), + CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa); + XDefineCursor(dpy, m->barwin, cursor[CurNormal]->cursor); + XMapRaised(dpy, m->barwin); + XSetClassHint(dpy, m->barwin, &ch); + } +} + +void +updatebarpos(Monitor *m) +{ + m->wy = m->my; + m->wh = m->mh; + if (m->showbar) { + m->wh -= bh; + m->by = m->topbar ? m->wy : m->wy + m->wh; + m->wy = m->topbar ? m->wy + bh : m->wy; + } else + m->by = -bh; +} + +void +updateclientlist() +{ + Client *c; + Monitor *m; + + XDeleteProperty(dpy, root, netatom[NetClientList]); + for (m = mons; m; m = m->next) + for (c = m->clients; c; c = c->next) + XChangeProperty(dpy, root, netatom[NetClientList], + XA_WINDOW, 32, PropModeAppend, + (unsigned char *) &(c->win), 1); +} + +int +updategeom(void) +{ + int dirty = 0; + +#ifdef XINERAMA + if (XineramaIsActive(dpy)) { + int i, j, n, nn; + Client *c; + Monitor *m; + XineramaScreenInfo *info = XineramaQueryScreens(dpy, &nn); + XineramaScreenInfo *unique = NULL; + + for (n = 0, m = mons; m; m = m->next, n++); + /* only consider unique geometries as separate screens */ + unique = ecalloc(nn, sizeof(XineramaScreenInfo)); + for (i = 0, j = 0; i < nn; i++) + if (isuniquegeom(unique, j, &info[i])) + memcpy(&unique[j++], &info[i], sizeof(XineramaScreenInfo)); + XFree(info); + nn = j; + + /* new monitors if nn > n */ + for (i = n; i < nn; i++) { + for (m = mons; m && m->next; m = m->next); + if (m) + m->next = createmon(); + else + mons = createmon(); + } + for (i = 0, m = mons; i < nn && m; m = m->next, i++) + if (i >= n + || unique[i].x_org != m->mx || unique[i].y_org != m->my + || unique[i].width != m->mw || unique[i].height != m->mh) + { + dirty = 1; + m->num = i; + m->mx = m->wx = unique[i].x_org; + m->my = m->wy = unique[i].y_org; + m->mw = m->ww = unique[i].width; + m->mh = m->wh = unique[i].height; + updatebarpos(m); + } + /* removed monitors if n > nn */ + for (i = nn; i < n; i++) { + for (m = mons; m && m->next; m = m->next); + while ((c = m->clients)) { + dirty = 1; + m->clients = c->next; + detachstack(c); + c->mon = mons; + attach(c); + attachstack(c); + } + if (m == selmon) + selmon = mons; + cleanupmon(m); + } + free(unique); + } else +#endif /* XINERAMA */ + { /* default monitor setup */ + if (!mons) + mons = createmon(); + if (mons->mw != sw || mons->mh != sh) { + dirty = 1; + mons->mw = mons->ww = sw; + mons->mh = mons->wh = sh; + updatebarpos(mons); + } + } + if (dirty) { + selmon = mons; + selmon = wintomon(root); + } + return dirty; +} + +void +updatenumlockmask(void) +{ + unsigned int i, j; + XModifierKeymap *modmap; + + numlockmask = 0; + modmap = XGetModifierMapping(dpy); + for (i = 0; i < 8; i++) + for (j = 0; j < modmap->max_keypermod; j++) + if (modmap->modifiermap[i * modmap->max_keypermod + j] + == XKeysymToKeycode(dpy, XK_Num_Lock)) + numlockmask = (1 << i); + XFreeModifiermap(modmap); +} + +void +updatesizehints(Client *c) +{ + long msize; + XSizeHints size; + + if (!XGetWMNormalHints(dpy, c->win, &size, &msize)) + /* size is uninitialized, ensure that size.flags aren't used */ + size.flags = PSize; + if (size.flags & PBaseSize) { + c->basew = size.base_width; + c->baseh = size.base_height; + } else if (size.flags & PMinSize) { + c->basew = size.min_width; + c->baseh = size.min_height; + } else + c->basew = c->baseh = 0; + if (size.flags & PResizeInc) { + c->incw = size.width_inc; + c->inch = size.height_inc; + } else + c->incw = c->inch = 0; + if (size.flags & PMaxSize) { + c->maxw = size.max_width; + c->maxh = size.max_height; + } else + c->maxw = c->maxh = 0; + if (size.flags & PMinSize) { + c->minw = size.min_width; + c->minh = size.min_height; + } else if (size.flags & PBaseSize) { + c->minw = size.base_width; + c->minh = size.base_height; + } else + c->minw = c->minh = 0; + if (size.flags & PAspect) { + c->mina = (float)size.min_aspect.y / size.min_aspect.x; + c->maxa = (float)size.max_aspect.x / size.max_aspect.y; + } else + c->maxa = c->mina = 0.0; + c->isfixed = (c->maxw && c->maxh && c->maxw == c->minw && c->maxh == c->minh); + c->hintsvalid = 1; +} + +void +updatestatus(void) +{ + if (!gettextprop(root, XA_WM_NAME, stext, sizeof(stext))) + strcpy(stext, "dwm-"VERSION); + drawbar(selmon); +} + +void +updatetitle(Client *c) +{ + if (!gettextprop(c->win, netatom[NetWMName], c->name, sizeof c->name)) + gettextprop(c->win, XA_WM_NAME, c->name, sizeof c->name); + if (c->name[0] == '\0') /* hack to mark broken clients */ + strcpy(c->name, broken); +} + +void +updatewindowtype(Client *c) +{ + Atom state = getatomprop(c, netatom[NetWMState]); + Atom wtype = getatomprop(c, netatom[NetWMWindowType]); + + if (state == netatom[NetWMFullscreen]) + setfullscreen(c, 1); + if (wtype == netatom[NetWMWindowTypeDialog]) + c->isfloating = 1; +} + +void +updatewmhints(Client *c) +{ + XWMHints *wmh; + + if ((wmh = XGetWMHints(dpy, c->win))) { + if (c == selmon->sel && wmh->flags & XUrgencyHint) { + wmh->flags &= ~XUrgencyHint; + XSetWMHints(dpy, c->win, wmh); + } else + c->isurgent = (wmh->flags & XUrgencyHint) ? 1 : 0; + if (wmh->flags & InputHint) + c->neverfocus = !wmh->input; + else + c->neverfocus = 0; + XFree(wmh); + } +} + +void +view(const Arg *arg) +{ + if ((arg->ui & TAGMASK) == selmon->tagset[selmon->seltags]) + return; + selmon->seltags ^= 1; /* toggle sel tagset */ + if (arg->ui & TAGMASK) + selmon->tagset[selmon->seltags] = arg->ui & TAGMASK; + focus(NULL); + arrange(selmon); +} + +Client * +wintoclient(Window w) +{ + Client *c; + Monitor *m; + + for (m = mons; m; m = m->next) + for (c = m->clients; c; c = c->next) + if (c->win == w) + return c; + return NULL; +} + +Monitor * +wintomon(Window w) +{ + int x, y; + Client *c; + Monitor *m; + + if (w == root && getrootptr(&x, &y)) + return recttomon(x, y, 1, 1); + for (m = mons; m; m = m->next) + if (w == m->barwin) + return m; + if ((c = wintoclient(w))) + return c->mon; + return selmon; +} + +/* There's no way to check accesses to destroyed windows, thus those cases are + * ignored (especially on UnmapNotify's). Other types of errors call Xlibs + * default error handler, which may call exit. */ +int +xerror(Display *dpy, XErrorEvent *ee) +{ + if (ee->error_code == BadWindow + || (ee->request_code == X_SetInputFocus && ee->error_code == BadMatch) + || (ee->request_code == X_PolyText8 && ee->error_code == BadDrawable) + || (ee->request_code == X_PolyFillRectangle && ee->error_code == BadDrawable) + || (ee->request_code == X_PolySegment && ee->error_code == BadDrawable) + || (ee->request_code == X_ConfigureWindow && ee->error_code == BadMatch) + || (ee->request_code == X_GrabButton && ee->error_code == BadAccess) + || (ee->request_code == X_GrabKey && ee->error_code == BadAccess) + || (ee->request_code == X_CopyArea && ee->error_code == BadDrawable)) + return 0; + fprintf(stderr, "dwm: fatal error: request code=%d, error code=%d\n", + ee->request_code, ee->error_code); + return xerrorxlib(dpy, ee); /* may call exit */ +} + +int +xerrordummy(Display *dpy, XErrorEvent *ee) +{ + return 0; +} + +/* Startup Error handler to check if another window manager + * is already running. */ +int +xerrorstart(Display *dpy, XErrorEvent *ee) +{ + die("dwm: another window manager is already running"); + return -1; +} + +void +zoom(const Arg *arg) +{ + Client *c = selmon->sel; + + if (!selmon->lt[selmon->sellt]->arrange || !c || c->isfloating) + return; + if (c == nexttiled(selmon->clients) && !(c = nexttiled(c->next))) + return; + pop(c); +} + +int +main(int argc, char *argv[]) +{ + if (argc == 2 && !strcmp("-v", argv[1])) + die("dwm-"VERSION); + else if (argc != 1) + die("usage: dwm [-v]"); + if (!setlocale(LC_CTYPE, "") || !XSupportsLocale()) + fputs("warning: no locale support\n", stderr); + if (!(dpy = XOpenDisplay(NULL))) + die("dwm: cannot open display"); + checkotherwm(); + setup(); +#ifdef __OpenBSD__ + if (pledge("stdio rpath proc exec", NULL) == -1) + die("pledge"); +#endif /* __OpenBSD__ */ + scan(); + run(); + cleanup(); + XCloseDisplay(dpy); + return EXIT_SUCCESS; +} diff --git a/dwm/dwm.o b/dwm/dwm.o deleted file mode 100644 index be09fab1d335abadbd78d879d77d3bb77996fc96..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 58104 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 diff --git a/dwm/patches/centermode.diff b/dwm/patches/centermode.diff new file mode 100644 index 0000000..6926892 --- /dev/null +++ b/dwm/patches/centermode.diff @@ -0,0 +1,142 @@ +diff --git a/config.def.h b/config.def.h +index 7054c06..527b214 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -39,6 +39,8 @@ static const Layout layouts[] = { + { "[]=", tile }, /* first entry is default */ + { "><>", NULL }, /* no layout function means floating behavior */ + { "[M]", monocle }, ++ { "|M|", centeredmaster }, ++ { ">M>", centeredfloatingmaster }, + }; + + /* key definitions */ +@@ -74,6 +76,8 @@ static Key keys[] = { + { MODKEY, XK_t, setlayout, {.v = &layouts[0]} }, + { MODKEY, XK_f, setlayout, {.v = &layouts[1]} }, + { MODKEY, XK_m, setlayout, {.v = &layouts[2]} }, ++ { MODKEY, XK_u, setlayout, {.v = &layouts[3]} }, ++ { MODKEY, XK_o, setlayout, {.v = &layouts[4]} }, + { MODKEY, XK_space, setlayout, {0} }, + { MODKEY|ShiftMask, XK_space, togglefloating, {0} }, + { MODKEY, XK_0, view, {.ui = ~0 } }, +diff --git a/dwm.c b/dwm.c +index 0362114..1e81412 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -233,6 +233,8 @@ static int xerror(Display *dpy, XErrorEvent *ee); + static int xerrordummy(Display *dpy, XErrorEvent *ee); + static int xerrorstart(Display *dpy, XErrorEvent *ee); + static void zoom(const Arg *arg); ++static void centeredmaster(Monitor *m); ++static void centeredfloatingmaster(Monitor *m); + + /* variables */ + static const char broken[] = "broken"; +@@ -2139,3 +2141,106 @@ main(int argc, char *argv[]) + XCloseDisplay(dpy); + return EXIT_SUCCESS; + } ++ ++void ++centeredmaster(Monitor *m) ++{ ++ unsigned int i, n, h, mw, mx, my, oty, ety, tw; ++ Client *c; ++ ++ /* count number of clients in the selected monitor */ ++ for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); ++ if (n == 0) ++ return; ++ ++ /* initialize areas */ ++ mw = m->ww; ++ mx = 0; ++ my = 0; ++ tw = mw; ++ ++ if (n > m->nmaster) { ++ /* go mfact box in the center if more than nmaster clients */ ++ mw = m->nmaster ? m->ww * m->mfact : 0; ++ tw = m->ww - mw; ++ ++ if (n - m->nmaster > 1) { ++ /* only one client */ ++ mx = (m->ww - mw) / 2; ++ tw = (m->ww - mw) / 2; ++ } ++ } ++ ++ oty = 0; ++ ety = 0; ++ for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) ++ if (i < m->nmaster) { ++ /* nmaster clients are stacked vertically, in the center ++ * of the screen */ ++ h = (m->wh - my) / (MIN(n, m->nmaster) - i); ++ resize(c, m->wx + mx, m->wy + my, mw - (2*c->bw), ++ h - (2*c->bw), 0); ++ my += HEIGHT(c); ++ } else { ++ /* stack clients are stacked vertically */ ++ if ((i - m->nmaster) % 2 ) { ++ h = (m->wh - ety) / ( (1 + n - i) / 2); ++ resize(c, m->wx, m->wy + ety, tw - (2*c->bw), ++ h - (2*c->bw), 0); ++ ety += HEIGHT(c); ++ } else { ++ h = (m->wh - oty) / ((1 + n - i) / 2); ++ resize(c, m->wx + mx + mw, m->wy + oty, ++ tw - (2*c->bw), h - (2*c->bw), 0); ++ oty += HEIGHT(c); ++ } ++ } ++} ++ ++void ++centeredfloatingmaster(Monitor *m) ++{ ++ unsigned int i, n, w, mh, mw, mx, mxo, my, myo, tx; ++ Client *c; ++ ++ /* count number of clients in the selected monitor */ ++ for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); ++ if (n == 0) ++ return; ++ ++ /* initialize nmaster area */ ++ if (n > m->nmaster) { ++ /* go mfact box in the center if more than nmaster clients */ ++ if (m->ww > m->wh) { ++ mw = m->nmaster ? m->ww * m->mfact : 0; ++ mh = m->nmaster ? m->wh * 0.9 : 0; ++ } else { ++ mh = m->nmaster ? m->wh * m->mfact : 0; ++ mw = m->nmaster ? m->ww * 0.9 : 0; ++ } ++ mx = mxo = (m->ww - mw) / 2; ++ my = myo = (m->wh - mh) / 2; ++ } else { ++ /* go fullscreen if all clients are in the master area */ ++ mh = m->wh; ++ mw = m->ww; ++ mx = mxo = 0; ++ my = myo = 0; ++ } ++ ++ for(i = tx = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) ++ if (i < m->nmaster) { ++ /* nmaster clients are stacked horizontally, in the center ++ * of the screen */ ++ w = (mw + mxo - mx) / (MIN(n, m->nmaster) - i); ++ resize(c, m->wx + mx, m->wy + my, w - (2*c->bw), ++ mh - (2*c->bw), 0); ++ mx += WIDTH(c); ++ } else { ++ /* stack clients are stacked horizontally */ ++ w = (m->ww - tx) / (n - i); ++ resize(c, m->wx + tx, m->wy, w - (2*c->bw), ++ m->wh - (2*c->bw), 0); ++ tx += WIDTH(c); ++ } ++} diff --git a/dwm/util.o b/dwm/util.o deleted file mode 100644 index 8e55fa18d6ada0bfba70d02362b40ffaf2d35ebf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2224 zcmbtUO=uHQ5T0$TjWtbT?V(Z+5mrf{E}Ik~q$<%yyGoE+D{3#ACR-cKpPNldRWM>b zgb?V#qX!Qj6g(94C^YE7t4B}Pqfig^ASe~$%?e!*H_wR z+#gQLxBTIhT=s{b%5|js!_VYZOTUnxTl%%UX6d(b+tTmkPpGq6v+rmK4Gjy1B5kdC z3LW&mXss1_iv>os)~p=RT1i>`n3Mw^gi#NxEFAoX2Gl1&Yn~v>9Mc*b)Ud}2Xic>0 z4|+TC>cRCO#w|3`vDD_k`T&R4>1-_YvYq&(UG-`$t0N1T`;bZJ^QBB2U}|zQ9t=%g zx*85f#+9fN2}afExEfO#KRRyF-kt7tqjojnaLGz| z^@i91Tmi-r6@7;rexwT?>Vhj>aGJVXeVmikC-2WXC&VVY@S$qv@=6Aj)T9d8oDLN; zs~ZL^EtHL1(Of{^$m>N|C|Au4lrdB?K(FOY(Cv$XbxEqW!nxab;7`YvR}81SuooA{ z-!RcV5AE=@9h6{5Yy=>Xttsx zm@~xAiN_o+jADS!FTn{+*XXcOJS<^9+GN`A)BaCT{20R-oghnQoEtIR36CL8HUBlA z{(V$4ic1u}Kkt{v`2JicFhDl_*hQIR1pY7NF`mcu1q^VTb4V|_fiBz|h|xO}?<%@b zWBJa$oZoX7xkPp5zhwE-R7?