From 5c820fe8ac5f8005f0cc943c733019f8f04bcb34 Mon Sep 17 00:00:00 2001 From: coast Date: Thu, 29 May 2025 22:47:44 +0200 Subject: [PATCH] Upload files to ".suckless/dwm" --- .suckless/dwm/drw.o | Bin 0 -> 10368 bytes .suckless/dwm/dwm.1 | 187 +++ .suckless/dwm/dwm.c | 2619 +++++++++++++++++++++++++++++++++++++++++ .suckless/dwm/dwm.o | Bin 0 -> 100416 bytes .suckless/dwm/dwm.png | Bin 0 -> 373 bytes 5 files changed, 2806 insertions(+) create mode 100644 .suckless/dwm/drw.o create mode 100644 .suckless/dwm/dwm.1 create mode 100644 .suckless/dwm/dwm.c create mode 100644 .suckless/dwm/dwm.o create mode 100644 .suckless/dwm/dwm.png diff --git a/.suckless/dwm/drw.o b/.suckless/dwm/drw.o new file mode 100644 index 0000000000000000000000000000000000000000..3303c6df9300ef0f891e9c7e323a421b071b2983 GIT binary patch literal 10368 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 HZu$QPaD#uy literal 0 HcmV?d00001 diff --git a/.suckless/dwm/dwm.1 b/.suckless/dwm/dwm.1 new file mode 100644 index 0000000..6020871 --- /dev/null +++ b/.suckless/dwm/dwm.1 @@ -0,0 +1,187 @@ +.TH DWM 1 dwm\-VERSION +.SH NAME +dwm \- dynamic window manager +.SH SYNOPSIS +.B dwm +.RB [ \-v ] +.SH DESCRIPTION +dwm is a dynamic window manager for X. It manages windows in tiled, monocle +and floating layouts. Either layout can be applied dynamically, optimising the +environment for the application in use and the task performed. +.P +In tiled layouts windows are managed in a master and stacking area. The master +area on the left contains one window by default, and the stacking area on the +right contains all other windows. The number of master area windows can be +adjusted from zero to an arbitrary number. In monocle layout all windows are +maximised to the screen size. In floating layout windows can be resized and +moved freely. Dialog windows are always managed floating, regardless of the +layout applied. +.P +Windows are grouped by tags. Each window can be tagged with one or multiple +tags. Selecting certain tags displays all windows with these tags. +.P +Each screen contains a small status bar which displays all available tags, the +layout, the title of the focused window, and the text read from the root window +name property, if the screen is focused. A floating window is indicated with an +empty square and a maximised floating window is indicated with a filled square +before the windows title. The selected tags are indicated with a different +color. The tags of the focused window are indicated with a filled square in the +top left corner. The tags which are applied to one or more windows are +indicated with an empty square in the top left corner. +.P +dwm draws a small border around windows to indicate the focus state. +.SH OPTIONS +.TP +.B \-v +prints version information to stderr, then exits. +.SH USAGE +.SS Status bar +.TP +.B X root window name +is read and displayed in the status text area. It can be set with the +.BR xsetroot (1) +command. +.TP +.B Button1 +click on a tag label to display all windows with that tag, click on the layout +label toggles between tiled and floating layout. +.TP +.B Button3 +click on a tag label adds/removes all windows with that tag to/from the view. +.TP +.B Super\-Button1 +click on a tag label applies that tag to the focused window. +.TP +.B Super\-Button3 +click on a tag label adds/removes that tag to/from the focused window. +.SS Keyboard commands +.TP +.B Super\-Return +Start +.BR st(1). +.TP +.B Super\-Shift\-Return +Start or toggle +.BR st(1) +as a floating (scratchpad) terminal. +.TP +.B Super\-d +Spawn +.BR dmenu(1) +for launching other programs. +.TP +.B Super\-f +Toggles fullscreen state of focused window. +.TP +.B Super\-, +Focus previous screen, if any. +.TP +.B Super\-. +Focus next screen, if any. +.TP +.B Super\-Shift\-, +Send focused window to previous screen, if any. +.TP +.B Super\-Shift\-. +Send focused window to next screen, if any. +.TP +.B Super\-b +Toggles bar on and off. +.TP +.B Super\-t +Sets tiled layout. +.TP +.B Super\-m +Zooms/cycles focused window to/from master area (tiled layouts only). +.TP +.B Super\-space +Toggles between floating and tiled layout. +.TP +.B Super\-j +Focus next window. +.TP +.B Super\-k +Focus previous window. +.TP +.B Super\-Shift\-j +Move focused stack window downward. +.TP +.B Super\-Shift\-k +Move focused stack window upward. +.TP +.B Super\-o +Increase number of windows in master area. +.TP +.B Super\-Shift\-o +Decrease number of windows in master area. +.TP +.B Super\-l +Increase master area size. +.TP +.B Super\-h +Decrease master area size. +.TP +.B Super\-m +Zooms/cycles focused window to/from master area (tiled layouts only). +.TP +.B Super\-q +Close focused window. +.TP +.B Super\-Shift\-space +Toggle focused window between tiled and floating state. +.TP +.B Super\-Tab +Toggles to the previously selected tags. +.TP +.B Super\-Shift\-[1..n] +Apply nth tag to focused window. +.TP +.B Super\-Shift\-0 +Apply all tags to focused window. +.TP +.B Super\-Control\-Shift\-[1..n] +Add/remove nth tag to/from focused window. +.TP +.B Super\-[1..n] +View all windows with nth tag. +.TP +.B Super\-0 +View all windows with any tag. +.TP +.B Super\-Control\-[1..n] +Add/remove all windows with nth tag to/from the view. +.TP +.B Super\-Shift\-q, Super\-Shift\-e +Quit dwm. +.SS Mouse commands +.TP +.B Super\-Button1 +Move focused window while dragging. Tiled windows will be toggled to the floating state. +.TP +.B Super\-Button2 +Toggles focused window between floating and tiled state. +.TP +.B Super\-Button3 +Resize focused window while dragging. Tiled windows will be toggled to the floating state. +.SH CUSTOMIZATION +dwm is customized by creating a custom config.h and (re)compiling the source +code. This keeps it fast, secure and simple. +.SH SEE ALSO +.BR dmenu (1), +.BR st (1) +.SH ISSUES +Java applications which use the XToolkit/XAWT backend may draw grey windows +only. The XToolkit/XAWT backend breaks ICCCM-compliance in recent JDK 1.5 and early +JDK 1.6 versions, because it assumes a reparenting window manager. Possible workarounds +are using JDK 1.4 (which doesn't contain the XToolkit/XAWT backend) or setting the +environment variable +.BR AWT_TOOLKIT=MToolkit +(to use the older Motif backend instead) or running +.B xprop -root -f _NET_WM_NAME 32a -set _NET_WM_NAME LG3D +or +.B wmname LG3D +(to pretend that a non-reparenting window manager is running that the +XToolkit/XAWT backend can recognize) or when using OpenJDK setting the environment variable +.BR _JAVA_AWT_WM_NONREPARENTING=1 . +.SH BUGS +Send all bug reports with a patch to hackers@suckless.org. diff --git a/.suckless/dwm/dwm.c b/.suckless/dwm/dwm.c new file mode 100644 index 0000000..7c87101 --- /dev/null +++ b/.suckless/dwm/dwm.c @@ -0,0 +1,2619 @@ +/* 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 Button6 6 +#define Button7 7 +#define Button8 8 +#define Button9 9 +#define NUMTAGS 9 +#define BARRULES 20 +#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 ISVISIBLEONTAG(C, T) ((C->tags & T)) +#define ISVISIBLE(C) ISVISIBLEONTAG(C, 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 WTYPE "_NET_WM_WINDOW_TYPE_" +#define TOTALTAGS (NUMTAGS + LENGTH(scratchpads)) +#define TAGMASK ((1 << TOTALTAGS) - 1) +#define SPTAG(i) ((1 << NUMTAGS) << (i)) +#define SPTAGMASK (((1 << LENGTH(scratchpads))-1) << NUMTAGS) +#define TEXTWM(X) (drw_fontset_getwidth(drw, (X), True) + lrpad) +#define TEXTW(X) (drw_fontset_getwidth(drw, (X), False) + lrpad) +#define HIDDEN(C) ((getstate(C->win) == IconicState)) + +/* enums */ +enum { + CurNormal, + CurResize, + CurMove, + CurLast +}; /* cursor */ + +enum { + SchemeNorm, + SchemeSel, + SchemeTitleNorm, + SchemeTitleSel, + SchemeTagsNorm, + SchemeTagsSel, + SchemeHidNorm, + SchemeHidSel, + SchemeUrg, +}; /* color schemes */ + +enum { + NetSupported, NetWMName, NetWMState, NetWMCheck, + NetWMFullscreen, NetActiveWindow, NetWMWindowType, + NetClientList, + NetLast +}; /* EWMH atoms */ + +enum { + WMProtocols, + WMDelete, + WMState, + WMTakeFocus, + WMLast +}; /* default atoms */ + + +enum { + ClkTagBar, + ClkLtSymbol, + ClkStatusText, + ClkWinTitle, + ClkClientWin, + ClkRootWin, + ClkLast +}; /* clicks */ + +enum { + BAR_ALIGN_LEFT, + BAR_ALIGN_CENTER, + BAR_ALIGN_RIGHT, + BAR_ALIGN_LEFT_LEFT, + BAR_ALIGN_LEFT_RIGHT, + BAR_ALIGN_LEFT_CENTER, + BAR_ALIGN_NONE, + BAR_ALIGN_RIGHT_LEFT, + BAR_ALIGN_RIGHT_RIGHT, + BAR_ALIGN_RIGHT_CENTER, + BAR_ALIGN_LAST +}; /* bar alignment */ + + +typedef union { + int i; + unsigned int ui; + float f; + const void *v; +} Arg; + +typedef struct Monitor Monitor; +typedef struct Bar Bar; +struct Bar { + Window win; + Monitor *mon; + Bar *next; + int idx; + int showbar; + int topbar; + int external; + int borderpx; + int borderscheme; + int bx, by, bw, bh; /* bar geometry */ + int w[BARRULES]; // width, array length == barrules, then use r index for lookup purposes + int x[BARRULES]; // x position, array length == ^ +}; + +typedef struct { + int x; + int y; + int h; + int w; +} BarArg; + +typedef struct { + int monitor; + int bar; + int alignment; // see bar alignment enum + int (*widthfunc)(Bar *bar, BarArg *a); + int (*drawfunc)(Bar *bar, BarArg *a); + int (*clickfunc)(Bar *bar, Arg *arg, BarArg *a); + int (*hoverfunc)(Bar *bar, BarArg *a, XMotionEvent *ev); + char *name; // for debugging + int x, w; // position, width for internal use +} BarRule; + +typedef struct { + unsigned int click; + unsigned int mask; + unsigned int button; + void (*func)(const Arg *arg); + const Arg arg; +} Button; + + +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; + int isterminal, noswallow; + pid_t pid; + Client *next; + Client *snext; + Client *swallowing; + 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 mx, my, mw, mh; /* screen size */ + int wx, wy, ww, wh; /* window area */ + int gappih; /* horizontal gap between windows */ + int gappiv; /* vertical gap between windows */ + int gappoh; /* horizontal outer gaps */ + int gappov; /* vertical outer gaps */ + unsigned int seltags; + unsigned int sellt; + unsigned int tagset[2]; + int showbar; + Client *clients; + Client *sel; + Client *stack; + Monitor *next; + Bar *bar; + const Layout *lt[2]; +}; + +typedef struct { + const char *class; + const char *instance; + const char *title; + const char *wintype; + unsigned int tags; + int isfloating; + int isterminal; + int noswallow; + int monitor; +} Rule; + +#define RULE(...) { .monitor = -1, __VA_ARGS__ }, + +/* Cross patch compatibility rule macro helper macros */ +#define FLOATING , .isfloating = 1 +#define CENTERED +#define PERMANENT +#define FAKEFULLSCREEN +#define NOSWALLOW , .noswallow = 1 +#define TERMINAL , .isterminal = 1 +#define SWITCHTAG + + +/* 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 drawbarwin(Bar *bar); +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, Atom req); +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 motionnotify(XEvent *e); +static void movemouse(const Arg *arg); +static Client *nexttiled(Client *c); +static void pop(Client *); +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 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 sigchld(int unused); +static void spawn(const Arg *arg); +static void tag(const Arg *arg); +static void tagmon(const Arg *arg); +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, Client *nextfocus); +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 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); + +/* bar functions */ + +#include "patch/include.h" + +/* variables */ +static const char broken[] = "broken"; +static char stext[512]; + +static int screen; +static int sw, sh; /* X display screen geometry width, height */ +static int bh; /* bar geometry */ +static int lrpad; /* sum of left and right padding for text */ +/* Some clients (e.g. alacritty) helpfully send configure requests with a new size or position + * when they detect that they have been moved to another monitor. This can cause visual glitches + * when moving (or resizing) client windows from one monitor to another. This variable is used + * internally to ignore such configure requests while movemouse or resizemouse are being used. */ +static int ignoreconfigurerequests = 0; +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" + +#include "patch/include.c" + +/* compile-time check if all tags fit into an unsigned int bit array. */ +struct NumTags { char limitexceeded[NUMTAGS > 31 ? -1 : 1]; }; + +/* function implementations */ +void +applyrules(Client *c) +{ + const char *class, *instance; + Atom wintype; + unsigned int i; + const Rule *r; + Monitor *m; + XClassHint ch = { NULL, NULL }; + + /* rule matching */ + c->noswallow = -1; + 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; + wintype = getatomprop(c, netatom[NetWMWindowType], XA_ATOM); + + + 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)) + && (!r->wintype || wintype == XInternAtom(dpy, r->wintype, False))) + { + c->isterminal = r->isterminal; + c->noswallow = r->noswallow; + c->isfloating = r->isfloating; + c->tags |= r->tags; + if ((r->tags & SPTAGMASK) && r->isfloating) { + c->x = c->mon->wx + (c->mon->ww / 2 - WIDTH(c) / 2); + c->y = c->mon->wy + (c->mon->wh / 2 - HEIGHT(c) / 2); + } + 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] & ~SPTAGMASK); +} + +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) +{ + int click, i, r; + Arg arg = {0}; + Client *c; + Monitor *m; + Bar *bar; + XButtonPressedEvent *ev = &e->xbutton; + const BarRule *br; + BarArg carg = { 0, 0, 0, 0 }; + click = ClkRootWin; + + + /* focus monitor if necessary */ + if ((m = wintomon(ev->window)) && m != selmon + ) { + unfocus(selmon->sel, 1, NULL); + selmon = m; + focus(NULL); + } + + for (bar = selmon->bar; bar; bar = bar->next) { + if (ev->window == bar->win) { + for (r = 0; r < LENGTH(barrules); r++) { + br = &barrules[r]; + if (br->bar != bar->idx || (br->monitor == 'A' && m != selmon) || br->clickfunc == NULL) + continue; + if (br->monitor != 'A' && br->monitor != -1 && br->monitor != bar->mon->num) + continue; + if (bar->x[r] <= ev->x && ev->x <= bar->x[r] + bar->w[r]) { + carg.x = ev->x - bar->x[r]; + carg.y = ev->y - bar->borderpx; + carg.w = bar->w[r]; + carg.h = bar->bh - 2 * bar->borderpx; + click = br->clickfunc(bar, &arg, &carg); + if (click < 0) + return; + break; + } + } + break; + } + } + + + if (click == ClkRootWin && (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) +{ + Monitor *m; + Layout foo = { "", NULL }; + size_t i; + + + /* kill child processes */ + for (i = 0; i < autostart_len; i++) { + if (0 < autostart_pids[i]) { + kill(autostart_pids[i], SIGTERM); + waitpid(autostart_pids[i], NULL, 0); + } + } + + 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; + Bar *bar; + + if (mon == mons) + mons = mons->next; + else { + for (m = mons; m && m->next != mon; m = m->next); + m->next = mon->next; + } + for (bar = mon->bar; bar; bar = mon->bar) { + if (!bar->external) { + XUnmapWindow(dpy, bar->win); + XDestroyWindow(dpy, bar->win); + } + mon->bar = bar->next; + free(bar); + } + 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; + Bar *bar; + 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, sh); + 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); + for (bar = m->bar; bar; bar = bar->next) + XMoveResizeWindow(dpy, bar->win, bar->bx, bar->by, bar->bw, bar->bh); + } + focus(NULL); + arrange(NULL); + } + } +} + +void +configurerequest(XEvent *e) +{ + Client *c; + Monitor *m; + XConfigureRequestEvent *ev = &e->xconfigurerequest; + XWindowChanges wc; + + if (ignoreconfigurerequests) + return; + + 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, *mon; + int i, n, mi, max_bars = 2, istopbar = topbar; + + const BarRule *br; + Bar *bar; + + m = ecalloc(1, sizeof(Monitor)); + m->tagset[0] = m->tagset[1] = 1; + m->mfact = mfact; + m->nmaster = nmaster; + m->showbar = showbar; + m->gappih = gappih; + m->gappiv = gappiv; + m->gappoh = gappoh; + m->gappov = gappov; + for (mi = 0, mon = mons; mon; mon = mon->next, mi++); // monitor index + m->num = mi; + m->lt[0] = &layouts[0]; + m->lt[1] = &layouts[1 % LENGTH(layouts)]; + strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol); + + /* Derive the number of bars for this monitor based on bar rules */ + for (n = -1, i = 0; i < LENGTH(barrules); i++) { + br = &barrules[i]; + if (br->monitor == 'A' || br->monitor == -1 || br->monitor == m->num) + n = MAX(br->bar, n); + } + + m->bar = NULL; + for (i = 0; i <= n && i < max_bars; i++) { + bar = ecalloc(1, sizeof(Bar)); + bar->mon = m; + bar->idx = i; + bar->next = m->bar; + bar->topbar = istopbar; + m->bar = bar; + istopbar = !istopbar; + bar->showbar = 1; + bar->external = 0; + bar->borderpx = 0; + bar->bh = bh + bar->borderpx * 2; + bar->borderscheme = SchemeNorm; + } + + + + + return m; +} + +void +destroynotify(XEvent *e) +{ + Client *c; + XDestroyWindowEvent *ev = &e->xdestroywindow; + + if ((c = wintoclient(ev->window))) + unmanage(c, 1); + else if ((c = swallowingclient(ev->window))) + unmanage(c->swallowing, 1); +} + +void +detach(Client *c) +{ + Client **tc; + + for (tc = &c->mon->clients; *tc && *tc != c; tc = &(*tc)->next); + *tc = c->next; + c->next = NULL; +} + +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; + } + c->snext = NULL; +} + +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) +{ + Bar *bar; + + if (m->showbar) + for (bar = m->bar; bar; bar = bar->next) + drawbarwin(bar); +} + +void +drawbars(void) +{ + Monitor *m; + for (m = mons; m; m = m->next) + drawbar(m); +} + +void +drawbarwin(Bar *bar) +{ + if (!bar || !bar->win || bar->external) + return; + int r, w, total_drawn = 0; + int rx, lx, rw, lw; // bar size, split between left and right if a center module is added + const BarRule *br; + + if (bar->borderpx) { + XSetForeground(drw->dpy, drw->gc, scheme[bar->borderscheme][ColBorder].pixel); + XFillRectangle(drw->dpy, drw->drawable, drw->gc, 0, 0, bar->bw, bar->bh); + } + + BarArg warg = { 0 }; + BarArg darg = { 0 }; + warg.h = bar->bh - 2 * bar->borderpx; + + rw = lw = bar->bw - 2 * bar->borderpx; + rx = lx = bar->borderpx; + + drw_setscheme(drw, scheme[SchemeNorm]); + drw_rect(drw, lx, bar->borderpx, lw, bar->bh - 2 * bar->borderpx, 1, 1); + for (r = 0; r < LENGTH(barrules); r++) { + br = &barrules[r]; + if (br->bar != bar->idx || !br->widthfunc || (br->monitor == 'A' && bar->mon != selmon)) + continue; + if (br->monitor != 'A' && br->monitor != -1 && br->monitor != bar->mon->num) + continue; + drw_setscheme(drw, scheme[SchemeNorm]); + warg.w = (br->alignment < BAR_ALIGN_RIGHT_LEFT ? lw : rw); + + w = br->widthfunc(bar, &warg); + w = MIN(warg.w, w); + + if (lw <= 0) { // if left is exhausted then switch to right side, and vice versa + lw = rw; + lx = rx; + } else if (rw <= 0) { + rw = lw; + rx = lx; + } + + switch(br->alignment) { + default: + case BAR_ALIGN_NONE: + case BAR_ALIGN_LEFT_LEFT: + case BAR_ALIGN_LEFT: + bar->x[r] = lx; + if (lx == rx) { + rx += w; + rw -= w; + } + lx += w; + lw -= w; + break; + case BAR_ALIGN_LEFT_RIGHT: + case BAR_ALIGN_RIGHT: + bar->x[r] = lx + lw - w; + if (lx == rx) + rw -= w; + lw -= w; + break; + case BAR_ALIGN_LEFT_CENTER: + case BAR_ALIGN_CENTER: + bar->x[r] = lx + lw / 2 - w / 2; + if (lx == rx) { + rw = rx + rw - bar->x[r] - w; + rx = bar->x[r] + w; + } + lw = bar->x[r] - lx; + break; + case BAR_ALIGN_RIGHT_LEFT: + bar->x[r] = rx; + if (lx == rx) { + lx += w; + lw -= w; + } + rx += w; + rw -= w; + break; + case BAR_ALIGN_RIGHT_RIGHT: + bar->x[r] = rx + rw - w; + if (lx == rx) + lw -= w; + rw -= w; + break; + case BAR_ALIGN_RIGHT_CENTER: + bar->x[r] = rx + rw / 2 - w / 2; + if (lx == rx) { + lw = lx + lw - bar->x[r] + w; + lx = bar->x[r] + w; + } + rw = bar->x[r] - rx; + break; + } + bar->w[r] = w; + darg.x = bar->x[r]; + darg.y = bar->borderpx; + darg.h = bar->bh - 2 * bar->borderpx; + darg.w = bar->w[r]; + if (br->drawfunc) + total_drawn += br->drawfunc(bar, &darg); + } + + if (total_drawn == 0 && bar->showbar) { + bar->showbar = 0; + updatebarpos(bar->mon); + XMoveResizeWindow(dpy, bar->win, bar->bx, bar->by, bar->bw, bar->bh); + arrange(bar->mon); + } + else if (total_drawn > 0 && !bar->showbar) { + bar->showbar = 1; + updatebarpos(bar->mon); + XMoveResizeWindow(dpy, bar->win, bar->bx, bar->by, bar->bw, bar->bh); + drw_map(drw, bar->win, 0, 0, bar->bw, bar->bh); + arrange(bar->mon); + } else + drw_map(drw, bar->win, 0, 0, bar->bw, bar->bh); +} + +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, c); + 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, c); + if (c) { + if (c->mon != selmon) + selmon = c->mon; + if (c->isurgent) + seturgent(c, 0); + detachstack(c); + attachstack(c); + grabbuttons(c, 1); + if (c->isfloating) + XSetWindowBorder(dpy, c->win, scheme[SchemeSel][ColFloat].pixel); + else + 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, NULL); + 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, Atom req) +{ + int di; + unsigned long dl; + unsigned char *p = NULL; + Atom da, atom = None; + + + /* FIXME getatomprop should return the number of items and a pointer to + * the stored data instead of this workaround */ + if (XGetWindowProperty(dpy, c->win, prop, 0L, sizeof atom, False, req, + &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; + unsigned int modifiers[] = { 0, LockMask, numlockmask, numlockmask|LockMask }; + KeyCode code; + + XUngrabKey(dpy, AnyKey, AnyModifier, root); + for (i = 0; i < LENGTH(keys); i++) + if ((code = XKeysymToKeycode(dpy, keys[i].keysym))) + for (j = 0; j < LENGTH(modifiers); j++) + XGrabKey(dpy, code, keys[i].mod | modifiers[j], root, + True, GrabModeAsync, GrabModeAsync); + } +} + +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; + int keysyms_return; + KeySym* keysym; + XKeyEvent *ev; + + ev = &e->xkey; + keysym = XGetKeyboardMapping(dpy, (KeyCode)ev->keycode, 1, &keysyms_return); + 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)); + XFree(keysym); +} + +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; + Client *term = NULL; + Window trans = None; + XWindowChanges wc; + + c = ecalloc(1, sizeof(Client)); + c->win = w; + c->pid = winpid(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; + c->bw = borderpx; + } else { + c->mon = selmon; + c->bw = borderpx; + applyrules(c); + term = termforwin(c); + if (term) + c->mon = term->mon; + } + + if (c->x + WIDTH(c) > c->mon->mx + c->mon->mw) + c->x = c->mon->mx + c->mon->mw - WIDTH(c); + if (c->y + HEIGHT(c) > c->mon->my + c->mon->mh) + c->y = c->mon->my + c->mon->mh - HEIGHT(c); + c->x = MAX(c->x, c->mon->mx); + /* only fix client y-offset, if the client center might cover the bar */ + c->y = MAX(c->y, ((!c->mon->bar || c->mon->bar->by == c->mon->my) && (c->x + (c->w / 2) >= c->mon->wx) + && (c->x + (c->w / 2) < c->mon->wx + c->mon->ww)) ? bh : c->mon->my); + + wc.border_width = c->bw; + XConfigureWindow(dpy, w, CWBorderWidth, &wc); + if (c->isfloating) + XSetWindowBorder(dpy, w, scheme[SchemeNorm][ColFloat].pixel); + else + XSetWindowBorder(dpy, w, scheme[SchemeNorm][ColBorder].pixel); + configure(c); /* propagates border_width, if size doesn't change */ + updatesizehints(c); + if (getatomprop(c, netatom[NetWMState], XA_ATOM) == netatom[NetWMFullscreen]) + setfullscreen(c, 1); + 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); + XSetWindowBorder(dpy, w, scheme[SchemeNorm][ColFloat].pixel); + } + attachx(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); + c->mon->sel = c; + if (!(term && swallow(term, 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)) + return; + if (wa.override_redirect) + return; + if (!wintoclient(ev->window)) + manage(ev->window, &wa); +} + +void +motionnotify(XEvent *e) +{ + static Monitor *mon = NULL; + Monitor *m; + Bar *bar; + XMotionEvent *ev = &e->xmotion; + + if ((bar = wintobar(ev->window))) { + barhover(e, bar); + return; + } + + + if (ev->window != root) + return; + if ((m = recttomon(ev->x_root, ev->y_root, 1, 1)) != mon && mon) { + unfocus(selmon->sel, 1, NULL); + 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); + nx = ocx = c->x; + ny = ocy = c->y; + if (XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, + None, cursor[CurMove]->cursor, CurrentTime) != GrabSuccess) + return; + if (!getrootptr(&x, &y)) + return; + ignoreconfigurerequests = 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; + + 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) { + if (c->tags & SPTAGMASK) { + c->mon->tagset[c->mon->seltags] ^= (c->tags & SPTAGMASK); + m->tagset[m->seltags] |= (c->tags & SPTAGMASK); + } + sendmon(c, m); + selmon = m; + focus(NULL); + } + ignoreconfigurerequests = 0; +} + +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)) { + if (!fake_signal()) + 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); + if (c->isurgent) + drawbars(); + break; + } + if (ev->atom == XA_WM_NAME || ev->atom == netatom[NetWMName]) { + updatetitle(c); + if (c == c->mon->sel) + drawbar(c->mon); + } + } +} + +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, nx, ny; + 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); + nx = ocx = c->x; + ny = ocy = c->y; + nh = c->h; + nw = c->w; + 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); + ignoreconfigurerequests = 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, nx, ny, 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) { + if (c->tags & SPTAGMASK) { + c->mon->tagset[c->mon->seltags] ^= (c->tags & SPTAGMASK); + m->tagset[m->seltags] |= (c->tags & SPTAGMASK); + } + sendmon(c, m); + selmon = m; + focus(NULL); + } + ignoreconfigurerequests = 0; +} + +void +restack(Monitor *m) +{ + Client *c, *f = NULL; + 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; + if (m->bar) { + wc.sibling = m->bar->win; + } else { + for (f = m->stack; f && (f->isfloating || !ISVISIBLE(f)); f = f->snext); // find first tiled stack client + if (f) + wc.sibling = f->win; + } + for (c = m->stack; c; c = c->snext) + if (!c->isfloating && ISVISIBLE(c) && c != f) { + 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) +{ + scanner = 1; + char swin[256]; + 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); + else if (gettextprop(wins[i], netatom[NetClientList], swin, sizeof swin)) + 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); + } + XFree(wins); + } + scanner = 0; +} + +void +sendmon(Client *c, Monitor *m) +{ + if (c->mon == m) + return; + unfocus(c, 1, NULL); + detach(c); + detachstack(c); + c->mon = m; + if (!(c->tags & SPTAGMASK)) + c->tags = m->tagset[m->seltags]; /* assign tags of target monitor */ + attachx(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->oldbw = c->bw; + c->oldstate = c->isfloating; + 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->bw = c->oldbw; + c->isfloating = c->oldstate; + 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 +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; + + /* clean up any zombies immediately */ + sigchld(0); + + + /* the one line of bloat that would have saved a lot of time for a lot of people */ + putenv("_JAVA_AWT_WM_NONREPARENTING=1"); + + /* init screen */ + screen = DefaultScreen(dpy); + sw = DisplayWidth(dpy, screen); + sh = DisplayHeight(dpy, screen); + root = RootWindow(dpy, screen); + xinitvisual(); + drw = drw_create(dpy, screen, root, sw, sh, visual, depth, cmap); + 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[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], alphas[i], ColCount); + + 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)) { + if ((c->tags & SPTAGMASK) && c->isfloating) { + c->x = c->mon->wx + (c->mon->ww / 2 - WIDTH(c) / 2); + c->y = c->mon->wy + (c->mon->wh / 2 - HEIGHT(c) / 2); + } + /* 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 +sigchld(int unused) +{ + pid_t pid; + if (signal(SIGCHLD, sigchld) == SIG_ERR) + die("can't install SIGCHLD handler:"); + while (0 < (pid = waitpid(-1, NULL, WNOHANG))) { + pid_t *p, *lim; + + if (!(p = autostart_pids)) + continue; + lim = &p[autostart_len]; + + for (; p < lim; p++) { + if (*p == pid) { + *p = -1; + break; + } + } + } +} + +void +spawn(const Arg *arg) +{ + if (arg->v == dmenucmd) + dmenumon[0] = '0' + selmon->num; + + if (fork() == 0) + { + if (dpy) + close(ConnectionNumber(dpy)); + + setsid(); + execvp(((char **)arg->v)[0], (char **)arg->v); + fprintf(stderr, "dwm: execvp %s", ((char **)arg->v)[0]); + perror(" failed"); + exit(EXIT_SUCCESS); + } +} + +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) +{ + Client *c = selmon->sel; + Monitor *dest; + if (!c || !mons->next) + return; + dest = dirtomon(arg->i); + sendmon(c, dest); +} + +void +togglebar(const Arg *arg) +{ + Bar *bar; + selmon->showbar = !selmon->showbar; + updatebarpos(selmon); + for (bar = selmon->bar; bar; bar = bar->next) + XMoveResizeWindow(dpy, bar->win, bar->bx, bar->by, bar->bw, bar->bh); + arrange(selmon); +} + +void +togglefloating(const Arg *arg) +{ + Client *c = selmon->sel; + if (arg && arg->v) + c = (Client*)arg->v; + if (!c) + return; + if (c->isfullscreen) /* no support for fullscreen windows */ + return; + c->isfloating = !c->isfloating || c->isfixed; + if (c->isfloating) + XSetWindowBorder(dpy, c->win, scheme[SchemeSel][ColFloat].pixel); + else + XSetWindowBorder(dpy, c->win, scheme[SchemeSel][ColBorder].pixel); + if (c->isfloating) { + resize(c, c->x, c->y, c->w, c->h, 0); + } + arrange(c->mon); + +} + +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, Client *nextfocus) +{ + if (!c) + return; + grabbuttons(c, 0); + if (c->isfloating) + XSetWindowBorder(dpy, c->win, scheme[SchemeNorm][ColFloat].pixel); + else + 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; + + if (c->swallowing) { + unswallow(c); + return; + } + + Client *s = swallowingclient(c->win); + if (s) { + free(s->swallowing); + s->swallowing = NULL; + arrange(m); + focus(NULL); + return; + } + + 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); + if (s) + return; + 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) +{ + Bar *bar; + Monitor *m; + XSetWindowAttributes wa = { + .override_redirect = True, + .background_pixel = 0, + .border_pixel = 0, + .colormap = cmap, + .event_mask = ButtonPressMask|ExposureMask + }; + XClassHint ch = {"dwm", "dwm"}; + for (m = mons; m; m = m->next) { + for (bar = m->bar; bar; bar = bar->next) { + if (bar->external) + continue; + if (!bar->win) { + bar->win = XCreateWindow(dpy, root, bar->bx, bar->by, bar->bw, bar->bh, 0, depth, + InputOutput, visual, + CWOverrideRedirect|CWBackPixel|CWBorderPixel|CWColormap|CWEventMask, &wa); + XDefineCursor(dpy, bar->win, cursor[CurNormal]->cursor); + XMapRaised(dpy, bar->win); + XSetClassHint(dpy, bar->win, &ch); + } + } + } +} + +void +updatebarpos(Monitor *m) +{ + + m->wx = m->mx; + m->wy = m->my; + m->ww = m->mw; + m->wh = m->mh; + Bar *bar; + int y_pad = 0; + int x_pad = 0; + + + for (bar = m->bar; bar; bar = bar->next) { + bar->bx = m->wx + x_pad; + bar->bw = m->ww - 2 * x_pad; + } + + for (bar = m->bar; bar; bar = bar->next) + if (!m->showbar || !bar->showbar) + bar->by = -bar->bh - y_pad; + + + if (!m->showbar) + return; + for (bar = m->bar; bar; bar = bar->next) { + if (!bar->showbar) + continue; + if (bar->topbar) + m->wy = m->wy + bar->bh + y_pad; + m->wh -= y_pad + bar->bh; + bar->by = (bar->topbar ? m->wy - bar->bh : m->wy + m->wh); + } +} + +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) +{ + Monitor *m; + if (!gettextprop(root, XA_WM_NAME, stext, sizeof(stext))) + strcpy(stext, "dwm-"VERSION); + for (m = mons; m; m = m->next) + drawbar(m); +} + +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 +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 (c->isurgent) { + if (c->isfloating) + XSetWindowBorder(dpy, c->win, scheme[SchemeUrg][ColFloat].pixel); + else + XSetWindowBorder(dpy, c->win, scheme[SchemeUrg][ColBorder].pixel); + } + 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; + Bar *bar; + + if (w == root && getrootptr(&x, &y)) + return recttomon(x, y, 1, 1); + for (m = mons; m; m = m->next) + for (bar = m->bar; bar; bar = bar->next) + if (w == bar->win) + 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 (arg && arg->v) + c = (Client*)arg->v; + if (!c) + return; + + + + if (!c->mon->lt[c->mon->sellt]->arrange + || (c && c->isfloating) + ) + return; + + if (c == nexttiled(c->mon->clients)) + if (!c || !(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"); + if (!(xcon = XGetXCBConnection(dpy))) + die("dwm: cannot get xcb connection\n"); + checkotherwm(); + XrmInitialize(); + loadxrdb(); + autostart_exec(); + setup(); +#ifdef __OpenBSD__ + if (pledge("stdio rpath proc exec ps", NULL) == -1) + die("pledge"); +#endif /* __OpenBSD__ */ + scan(); + run(); + cleanup(); + XCloseDisplay(dpy); + return EXIT_SUCCESS; +} + diff --git a/.suckless/dwm/dwm.o b/.suckless/dwm/dwm.o new file mode 100644 index 0000000000000000000000000000000000000000..871e25a880d0852d02eb26175cf0a2d14f455030 GIT binary patch literal 100416 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 z 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 AMgRZ+ literal 0 HcmV?d00001 diff --git a/.suckless/dwm/dwm.png b/.suckless/dwm/dwm.png new file mode 100644 index 0000000000000000000000000000000000000000..b1f9ba7e5f4cc7350ee2392ebcea5fcbe00fb49b GIT binary patch literal 373 zcmeAS@N?(olHy`uVBq!ia0vp^2Y@($g9*gC@m3f}u_bxCyDx`7I;J! zGca%iWx0hJ8D`Cq01C2~c>21sUt<^MF=V?Ztt9{yk}YwKC~?lu%}vcKVQ?-=O)N=G zQ7F$W$xsN%NL6t6^bL5QqM8R(c+=CxF{I+w+q;fj4F)_6j>`Z3pZ>_($QEQ&92OXP z%lpEKGwG8$G-U1H{@Y%;mx-mNK|p|siBVAj$Z~Mt-~h6K0!}~{PyozQ07(f5fTdVi zm=-zT`NweeJ#%S&{fequZGmkDDC*%x$$Sa*fAP=$`nJkhx1Y~k<8b2;Hq)FOdV=P$ q&oWzoxz_&nv&n0)xBzV8k*jsxheTIy&cCY600f?{elF{r5}E*x)opSB literal 0 HcmV?d00001