autolinux


Logs | Files | LICENSE | LICENSE | GitLab


1
commit 8e1ed04344cae8c2f0ed22e68a11919af8277e29 (HEAD -> master, serv/master)
2
Author: Connor Etherington <[email protected]>
3
Date:   Wed Jul 17 00:14:10 2024 +0200
4
5
    Auto-Commit Update 17.07.2024 - 00:14:10
6
---
7
 AutoLinux                                          |  Bin 0 -> 135816 bytes
8
 AutoLinux.c                                        | 2961 ++++++++++++++++++++
9
 AutoLinux.desktop                                  |    6 +
10
 AutoLinux.o                                        |  Bin 0 -> 132144 bytes
11
 LICENSE                                            |   39 +
12
 Makefile                                           |   53 +
13
 PKGBUILD                                           |   28 +
14
 config.h                                           |  615 ++++
15
 config.mk                                          |   36 +
16
 definitions.h                                      |   46 +
17
 drw.c                                              |  424 +++
18
 drw.h                                              |   57 +
19
 drw.o                                              |  Bin 0 -> 10248 bytes
20
 icons/hicolor/1024x1024/apps/AutoLinux.png         |  Bin 0 -> 162233 bytes
21
 icons/hicolor/128x128/apps/AutoLinux.png           |  Bin 0 -> 15015 bytes
22
 icons/hicolor/16x16/apps/AutoLinux.png             |  Bin 0 -> 1125 bytes
23
 icons/hicolor/192x192/apps/AutoLinux.png           |  Bin 0 -> 23356 bytes
24
 icons/hicolor/22x22/apps/AutoLinux.png             |  Bin 0 -> 1708 bytes
25
 icons/hicolor/24x24/apps/AutoLinux.png             |  Bin 0 -> 1907 bytes
26
 icons/hicolor/256x256/apps/AutoLinux.png           |  Bin 0 -> 33215 bytes
27
 icons/hicolor/32x32/apps/AutoLinux.png             |  Bin 0 -> 2758 bytes
28
 icons/hicolor/36x36/apps/AutoLinux.png             |  Bin 0 -> 3094 bytes
29
 icons/hicolor/48x48/apps/AutoLinux.png             |  Bin 0 -> 4686 bytes
30
 icons/hicolor/512x512/apps/AutoLinux.png           |  Bin 0 -> 72652 bytes
31
 icons/hicolor/64x64/apps/AutoLinux.png             |  Bin 0 -> 6575 bytes
32
 icons/hicolor/72x72/apps/AutoLinux.png             |  Bin 0 -> 7702 bytes
33
 icons/hicolor/96x96/apps/AutoLinux.png             |  Bin 0 -> 10787 bytes
34
 icons/hicolor/scalable/apps/AutoLinux.svg          |    1 +
35
 icons/hicolor/symbolic/apps/AutoLinux-symbolic.svg |    1 +
36
 patch/bar_ltsymbol.c                               |   18 +
37
 patch/bar_ltsymbol.h                               |    3 +
38
 patch/bar_status.c                                 |   19 +
39
 patch/bar_status.h                                 |    3 +
40
 patch/bar_tags.c                                   |   57 +
41
 patch/bar_tags.h                                   |    3 +
42
 patch/bar_wintitle.c                               |   31 +
43
 patch/bar_wintitle.h                               |    3 +
44
 patch/cust/async.c                                 |   21 +
45
 patch/cust/bar_date.c                              |   43 +
46
 patch/cust/bar_date.h                              |    3 +
47
 patch/cust/bar_datetime.c                          |   17 +
48
 patch/cust/bar_datetime.h                          |    2 +
49
 patch/cust/bar_time.c                              |   49 +
50
 patch/cust/bar_time.h                              |    4 +
51
 patch/cust/rtxt.c                                  |   20 +
52
 patch/functions.c                                  |   21 +
53
 patch/functions.h                                  |    0
54
 patch/include.c                                    |    9 +
55
 patch/include.h                                    |    8 +
56
 shiftview.c                                        |   64 +
57
 transient.c                                        |   42 +
58
 util.c                                             |   35 +
59
 util.h                                             |    8 +
60
 util.o                                             |  Bin 0 -> 2224 bytes
61
 vanitygaps.c                                       |  542 ++++
62
 55 files changed, 5292 insertions(+)
63
64
diff --git a/AutoLinux b/AutoLinux
65
new file mode 100755
66
index 0000000..d95dc27
67
Binary files /dev/null and b/AutoLinux differ
68
diff --git a/AutoLinux.c b/AutoLinux.c
69
new file mode 100644
70
index 0000000..9a1ddf2
71
--- /dev/null
72
+++ b/AutoLinux.c
73
@@ -0,0 +1,2961 @@
74
+/* See LICENSE file for copyright and license details.
75
+ *
76
+ * dynamic window manager is designed like any other X client as well. It is
77
+ * driven through handling X events. In contrast to other X clients, a window
78
+ * manager selects for SubstructureRedirectMask on the root window, to receive
79
+ * events about window (dis-)appearance. Only one X connection at a time is
80
+ * allowed to select for this event mask.
81
+ *
82
+ * The event handlers of AutoLinux are organized in an array which is accessed
83
+ * whenever a new event has been fetched. This allows event dispatching
84
+ * in O(1) time.
85
+ *
86
+ * Each child of the root window is called a client, except windows which have
87
+ * set the override_redirect flag. Clients are organized in a linked client
88
+ * list on each monitor, the focus history is remembered through a stack list
89
+ * on each monitor. Each client contains a bit array to indicate the tags of a
90
+ * client.
91
+ *
92
+ * Keys and tagging rules are organized as arrays and defined in config.h.
93
+ *
94
+ * To understand everything else, start reading main().
95
+ */
96
+#include <errno.h>
97
+#include <locale.h>
98
+#include <signal.h>
99
+#include <stdarg.h>
100
+#include <stdio.h>
101
+#include <stdlib.h>
102
+#include <string.h>
103
+#include <unistd.h>
104
+#include <sys/types.h>
105
+#include <sys/wait.h>
106
+#include <X11/cursorfont.h>
107
+#include <X11/keysym.h>
108
+#include <X11/Xatom.h>
109
+#include <X11/Xlib.h>
110
+#include <X11/Xproto.h>
111
+#include <X11/Xutil.h>
112
+#include <X11/Xresource.h>
113
+#ifdef XINERAMA
114
+#include <X11/extensions/Xinerama.h>
115
+#endif /* XINERAMA */
116
+#include <X11/Xft/Xft.h>
117
+#include <X11/Xlib-xcb.h>
118
+#include <xcb/res.h>
119
+
120
+#include "drw.h"
121
+#include "util.h"
122
+
123
+/* macros */
124
+#define BARRULES                20
125
+#define BUTTONMASK              (ButtonPressMask|ButtonReleaseMask)
126
+#define CLEANMASK(mask)         (mask & ~(numlockmask|LockMask) & (ShiftMask|ControlMask|Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask))
127
+#define GETINC(X)               ((X) - 2000)
128
+#define INC(X)                  ((X) + 2000)
129
+#define INTERSECT(x,y,w,h,m)    (MAX(0, MIN((x)+(w),(m)->wx+(m)->ww) - MAX((x),(m)->wx)) \
130
+                               * MAX(0, MIN((y)+(h),(m)->wy+(m)->wh) - MAX((y),(m)->wy)))
131
+#define ISINC(X)                ((X) > 1000 && (X) < 3000)
132
+#define ISVISIBLE(C)            ((C->tags & C->mon->tagset[C->mon->seltags]) || C->issticky)
133
+#define PREVSEL                 3000
134
+#define LENGTH(X)               (sizeof X / sizeof X[0])
135
+#define MOUSEMASK               (BUTTONMASK|PointerMotionMask)
136
+#define MOD(N,M)                ((N)%(M) < 0 ? (N)%(M) + (M) : (N)%(M))
137
+#define WIDTH(X)                ((X)->w + 2 * (X)->bw)
138
+#define HEIGHT(X)               ((X)->h + 2 * (X)->bw)
139
+#define NUMTAGS			(LENGTH(tags) + LENGTH(scratchpads))
140
+#define TAGMASK			((1 << NUMTAGS) - 1)
141
+#define SPTAG(i)		((1 << LENGTH(tags)) << (i))
142
+#define SPTAGMASK		(((1 << LENGTH(scratchpads))-1) << LENGTH(tags))
143
+#define TEXTW(X)                (drw_fontset_getwidth(drw, (X)) + lrpad)
144
+#define TRUNC(X,A,B)            (MAX((A), MIN((X), (B))))
145
+
146
+/* enums */
147
+enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */
148
+enum { SchemeNorm, SchemeSel, SchemeTime, SchemeActive, SchemeInactive }; /* color schemes */
149
+enum { NetSupported, NetWMName, NetWMState, NetWMCheck,
150
+       NetWMFullscreen, NetActiveWindow, NetWMWindowType,
151
+       NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH atoms */
152
+enum { WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast }; /* default atoms */
153
+enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle,
154
+       ClkClientWin, ClkRootWin, ClkLast }; /* clicks */
155
+enum {
156
+	BAR_ALIGN_LEFT,
157
+	BAR_ALIGN_CENTER,
158
+	BAR_ALIGN_RIGHT,
159
+	BAR_ALIGN_LEFT_LEFT,
160
+	BAR_ALIGN_LEFT_RIGHT,
161
+	BAR_ALIGN_LEFT_CENTER,
162
+	BAR_ALIGN_NONE,
163
+	BAR_ALIGN_RIGHT_LEFT,
164
+	BAR_ALIGN_RIGHT_RIGHT,
165
+	BAR_ALIGN_RIGHT_CENTER,
166
+	BAR_ALIGN_LAST
167
+}; /* bar alignment */
168
+
169
+typedef union {
170
+	int i;
171
+	unsigned int ui;
172
+	float f;
173
+	const void *v;
174
+} Arg;
175
+
176
+typedef struct Monitor Monitor;
177
+typedef struct Bar Bar;
178
+struct Bar {
179
+	Window win;
180
+	Monitor *mon;
181
+	Bar *next;
182
+	int idx;
183
+	int topbar;
184
+	int bx, by, bw, bh; /* bar geometry */
185
+	int w[BARRULES]; // module width
186
+	int x[BARRULES]; // module position
187
+};
188
+
189
+typedef struct {
190
+	int max_width;
191
+} BarWidthArg;
192
+
193
+typedef struct {
194
+	int x;
195
+	int w;
196
+} BarDrawArg;
197
+
198
+typedef struct {
199
+	int rel_x;
200
+	int rel_y;
201
+	int rel_w;
202
+	int rel_h;
203
+} BarClickArg;
204
+
205
+typedef struct {
206
+	int monitor;
207
+	int bar;
208
+	int alignment; // see bar alignment enum
209
+	int (*widthfunc)(Bar *bar, BarWidthArg *a);
210
+	int (*drawfunc)(Bar *bar, BarDrawArg *a);
211
+	int (*clickfunc)(Bar *bar, Arg *arg, BarClickArg *a);
212
+	char *name; // for debugging
213
+	int x, w; // position, width for internal use
214
+} BarRule;
215
+
216
+typedef struct {
217
+	unsigned int click;
218
+	unsigned int mask;
219
+	unsigned int button;
220
+	void (*func)(const Arg *arg);
221
+	const Arg arg;
222
+} Button;
223
+
224
+typedef struct Client Client;
225
+struct Client {
226
+	char name[256];
227
+	float mina, maxa;
228
+	int x, y, w, h;
229
+	int oldx, oldy, oldw, oldh;
230
+	int basew, baseh, incw, inch, maxw, maxh, minw, minh;
231
+	int bw, oldbw;
232
+	unsigned int tags;
233
+	int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen, isterminal, noswallow, issticky;
234
+	pid_t pid;
235
+	Client *next;
236
+	Client *snext;
237
+	Client *swallowing;
238
+	Monitor *mon;
239
+	Window win;
240
+};
241
+
242
+typedef struct {
243
+	unsigned int mod;
244
+	KeySym keysym;
245
+	void (*func)(const Arg *);
246
+	const Arg arg;
247
+} Key;
248
+
249
+typedef struct {
250
+	const char *symbol;
251
+	void (*arrange)(Monitor *);
252
+} Layout;
253
+
254
+struct Monitor {
255
+	char ltsymbol[16];
256
+	float mfact;
257
+	int nmaster;
258
+	int num;
259
+	int mx, my, mw, mh;   /* screen size */
260
+	int wx, wy, ww, wh;   /* window area  */
261
+	int gappih;           /* horizontal gap between windows */
262
+	int gappiv;           /* vertical gap between windows */
263
+	int gappoh;           /* horizontal outer gaps */
264
+	int gappov;           /* vertical outer gaps */
265
+	unsigned int seltags;
266
+	unsigned int sellt;
267
+	unsigned int tagset[2];
268
+	int showbar;
269
+	Client *clients;
270
+	Client *sel;
271
+	Client *stack;
272
+	Monitor *next;
273
+	Bar *bar;
274
+	const Layout *lt[2];
275
+};
276
+
277
+typedef struct {
278
+	const char *class;
279
+	const char *instance;
280
+	const char *title;
281
+	unsigned int tags;
282
+	int isfloating;
283
+	int isterminal;
284
+	int noswallow;
285
+	int monitor;
286
+} Rule;
287
+
288
+/* Xresources preferences */
289
+enum resource_type {
290
+	STRING = 0,
291
+	INTEGER = 1,
292
+	FLOAT = 2
293
+};
294
+
295
+typedef struct {
296
+	char *name;
297
+	enum resource_type type;
298
+	void *dst;
299
+} ResourcePref;
300
+
301
+/* function declarations */
302
+static void applyrules(Client *c);
303
+static int applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact);
304
+static void arrange(Monitor *m);
305
+static void arrangemon(Monitor *m);
306
+static void attach(Client *c);
307
+static void attachbottom(Client *c);
308
+static void attachstack(Client *c);
309
+static void buttonpress(XEvent *e);
310
+static void checkotherwm(void);
311
+static void cleanup(void);
312
+static void cleanupmon(Monitor *mon);
313
+static void clientmessage(XEvent *e);
314
+static void configure(Client *c);
315
+static void configurenotify(XEvent *e);
316
+static void configurerequest(XEvent *e);
317
+static void copyvalidchars(char *text, char *rawtext);
318
+static Monitor *createmon(void);
319
+static void destroynotify(XEvent *e);
320
+static void detach(Client *c);
321
+static void detachstack(Client *c);
322
+static Monitor *dirtomon(int dir);
323
+static void drawbar(Monitor *m);
324
+static void drawbars(void);
325
+static void drawbarwin(Bar *bar);
326
+static void enternotify(XEvent *e);
327
+static void expose(XEvent *e);
328
+static void focus(Client *c);
329
+static void focusin(XEvent *e);
330
+static void focusmon(const Arg *arg);
331
+static void focusstack(const Arg *arg);
332
+static Atom getatomprop(Client *c, Atom prop);
333
+static int getrootptr(int *x, int *y);
334
+static long getstate(Window w);
335
+static int gettextprop(Window w, Atom atom, char *text, unsigned int size);
336
+static void grabbuttons(Client *c, int focused);
337
+static void grabkeys(void);
338
+static void incnmaster(const Arg *arg);
339
+static void keypress(XEvent *e);
340
+static void killclient(const Arg *arg);
341
+static void manage(Window w, XWindowAttributes *wa);
342
+static void mappingnotify(XEvent *e);
343
+static void maprequest(XEvent *e);
344
+static void monocle(Monitor *m);
345
+static void motionnotify(XEvent *e);
346
+static void movemouse(const Arg *arg);
347
+static Client *nexttiled(Client *c);
348
+static void pop(Client *);
349
+static void propertynotify(XEvent *e);
350
+static void pushstack(const Arg *arg);
351
+static void quit(const Arg *arg);
352
+static Monitor *recttomon(int x, int y, int w, int h);
353
+static void resize(Client *c, int x, int y, int w, int h, int interact);
354
+static void resizeclient(Client *c, int x, int y, int w, int h);
355
+static void resizemouse(const Arg *arg);
356
+static void restack(Monitor *m);
357
+static void run(void);
358
+static void runAutostart(void);
359
+static void scan(void);
360
+static void scratchpad_hide ();
361
+static _Bool scratchpad_last_showed_is_killed (void);
362
+static void scratchpad_remove ();
363
+static void scratchpad_show ();
364
+static void scratchpad_show_client (Client * c);
365
+static void scratchpad_show_first (void);
366
+static int sendevent(Client *c, Atom proto);
367
+static void sendmon(Client *c, Monitor *m);
368
+static void setclientstate(Client *c, long state);
369
+static void setfocus(Client *c);
370
+static void setfullscreen(Client *c, int fullscreen);
371
+static void setlayout(const Arg *arg);
372
+static void setmfact(const Arg *arg);
373
+static void setup(void);
374
+static void seturgent(Client *c, int urg);
375
+static void showhide(Client *c);
376
+static void sigchld(int unused);
377
+#ifndef __OpenBSD__
378
+static int getdwmblockspid();
379
+static void sigdwmblocks(const Arg *arg);
380
+#endif
381
+static void sighup(int unused);
382
+static void sigterm(int unused);
383
+static void spawn(const Arg *arg);
384
+static int stackpos(const Arg *arg);
385
+static void tag(const Arg *arg);
386
+static void tagmon(const Arg *arg);
387
+static void togglebar(const Arg *arg);
388
+static void togglefloating(const Arg *arg);
389
+static void togglescratch(const Arg *arg);
390
+static void togglesticky(const Arg *arg);
391
+static void togglefullscr(const Arg *arg);
392
+static void toggletag(const Arg *arg);
393
+static void toggleview(const Arg *arg);
394
+static void unfocus(Client *c, int setfocus);
395
+static void unmanage(Client *c, int destroyed);
396
+static void unmapnotify(XEvent *e);
397
+static void updatebarpos(Monitor *m);
398
+static void updatebars(void);
399
+static void updateclientlist(void);
400
+static int updategeom(void);
401
+static void updatenumlockmask(void);
402
+static void updatesizehints(Client *c);
403
+static void updatestatus(void);
404
+static void updatetitle(Client *c);
405
+static void updatewindowtype(Client *c);
406
+static void updatewmhints(Client *c);
407
+static void view(const Arg *arg);
408
+static Client *wintoclient(Window w);
409
+static Monitor *wintomon(Window w);
410
+static int xerror(Display *dpy, XErrorEvent *ee);
411
+static int xerrordummy(Display *dpy, XErrorEvent *ee);
412
+static int xerrorstart(Display *dpy, XErrorEvent *ee);
413
+static int leftrotatebits(const int n, const unsigned int d);
414
+static int rightrotatebits(const int n, const unsigned int d);
415
+static void rightrotview(const Arg *arg);
416
+static void leftrotview(const Arg *arg);
417
+static void zoom(const Arg *arg);
418
+static void load_xresources(void);
419
+static void resource_load(XrmDatabase db, char *name, enum resource_type rtype, void *dst);
420
+
421
+static pid_t getparentprocess(pid_t p);
422
+static int isdescprocess(pid_t p, pid_t c);
423
+static Client *swallowingclient(Window w);
424
+static Client *termforwin(const Client *c);
425
+static pid_t winpid(Window w);
426
+
427
+#include "patch/include.h"
428
+/* variables */
429
+static const char broken[] = "broken";
430
+static char stext[256];
431
+static char rawstext[256];
432
+static int dwmblockssig;
433
+pid_t dwmblockspid = 0;
434
+static int screen;
435
+static int sw, sh;           /* X display screen geometry width, height */
436
+static int bh;               /* bar geometry */
437
+static int lrpad;            /* sum of left and right padding for text */
438
+static int vp;               /* vertical padding for bar */
439
+static int sp;               /* side padding for bar */
440
+static int (*xerrorxlib)(Display *, XErrorEvent *);
441
+static unsigned int numlockmask = 0;
442
+static void (*handler[LASTEvent]) (XEvent *) = {
443
+	[ButtonPress] = buttonpress,
444
+	[ClientMessage] = clientmessage,
445
+	[ConfigureRequest] = configurerequest,
446
+	[ConfigureNotify] = configurenotify,
447
+	[DestroyNotify] = destroynotify,
448
+	[EnterNotify] = enternotify,
449
+	[Expose] = expose,
450
+	[FocusIn] = focusin,
451
+	[KeyPress] = keypress,
452
+	[MappingNotify] = mappingnotify,
453
+	[MapRequest] = maprequest,
454
+	[MotionNotify] = motionnotify,
455
+	[PropertyNotify] = propertynotify,
456
+	[UnmapNotify] = unmapnotify
457
+};
458
+static Atom wmatom[WMLast], netatom[NetLast];
459
+static int restart = 0;
460
+static int running = 1;
461
+static Cur *cursor[CurLast];
462
+static Clr **scheme;
463
+static Display *dpy;
464
+static Drw *drw;
465
+static Monitor *mons, *selmon;
466
+static Window root, wmcheckwin;
467
+
468
+/* scratchpad */
469
+# define SCRATCHPAD_MASK (1u << sizeof tags / sizeof * tags)
470
+static Client * scratchpad_last_showed = NULL;
471
+
472
+static xcb_connection_t *xcon;
473
+
474
+/* configuration, allows nested code to access above variables */
475
+#include "config.h"
476
+
477
+#include "patch/include.c"
478
+
479
+/* compile-time check if all tags fit into an unsigned int bit array. */
480
+struct NumTags { char limitexceeded[LENGTH(tags) > 30 ? -1 : 1]; };
481
+
482
+/* function implementations */
483
+void
484
+applyrules(Client *c)
485
+{
486
+	const char *class, *instance;
487
+	unsigned int i;
488
+	const Rule *r;
489
+	Monitor *m;
490
+	XClassHint ch = { NULL, NULL };
491
+
492
+	/* rule matching */
493
+	c->isfloating = 0;
494
+	c->tags = 0;
495
+	XGetClassHint(dpy, c->win, &ch);
496
+	class    = ch.res_class ? ch.res_class : broken;
497
+	instance = ch.res_name  ? ch.res_name  : broken;
498
+
499
+	for (i = 0; i < LENGTH(rules); i++) {
500
+		r = &rules[i];
501
+		if ((!r->title || strstr(c->name, r->title))
502
+		&& (!r->class || strstr(class, r->class))
503
+		&& (!r->instance || strstr(instance, r->instance)))
504
+		{
505
+			c->isterminal = r->isterminal;
506
+			c->isfloating = r->isfloating;
507
+			c->noswallow  = r->noswallow;
508
+			c->tags |= r->tags;
509
+			if ((r->tags & SPTAGMASK) && r->isfloating) {
510
+				c->x = c->mon->wx + (c->mon->ww / 2 - WIDTH(c) / 2);
511
+				c->y = c->mon->wy + (c->mon->wh / 2 - HEIGHT(c) / 2);
512
+			}
513
+
514
+			for (m = mons; m && m->num != r->monitor; m = m->next);
515
+			if (m)
516
+				c->mon = m;
517
+		}
518
+	}
519
+	if (ch.res_class)
520
+		XFree(ch.res_class);
521
+	if (ch.res_name)
522
+		XFree(ch.res_name);
523
+	if (c->tags != SCRATCHPAD_MASK)
524
+		c->tags = c->tags & TAGMASK ? c->tags & TAGMASK : c->mon->tagset[c->mon->seltags];
525
+}
526
+
527
+int
528
+applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact)
529
+{
530
+	int baseismin;
531
+	Monitor *m = c->mon;
532
+
533
+	/* set minimum possible */
534
+	*w = MAX(1, *w);
535
+	*h = MAX(1, *h);
536
+	if (interact) {
537
+		if (*x > sw)
538
+			*x = sw - WIDTH(c);
539
+		if (*y > sh)
540
+			*y = sh - HEIGHT(c);
541
+		if (*x + *w + 2 * c->bw < 0)
542
+			*x = 0;
543
+		if (*y + *h + 2 * c->bw < 0)
544
+			*y = 0;
545
+	} else {
546
+		if (*x >= m->wx + m->ww)
547
+			*x = m->wx + m->ww - WIDTH(c);
548
+		if (*y >= m->wy + m->wh)
549
+			*y = m->wy + m->wh - HEIGHT(c);
550
+		if (*x + *w + 2 * c->bw <= m->wx)
551
+			*x = m->wx;
552
+		if (*y + *h + 2 * c->bw <= m->wy)
553
+			*y = m->wy;
554
+	}
555
+	if (*h < bh)
556
+		*h = bh;
557
+	if (*w < bh)
558
+		*w = bh;
559
+	if (resizehints || c->isfloating || !c->mon->lt[c->mon->sellt]->arrange) {
560
+		/* see last two sentences in ICCCM 4.1.2.3 */
561
+		baseismin = c->basew == c->minw && c->baseh == c->minh;
562
+		if (!baseismin) { /* temporarily remove base dimensions */
563
+			*w -= c->basew;
564
+			*h -= c->baseh;
565
+		}
566
+		/* adjust for aspect limits */
567
+		if (c->mina > 0 && c->maxa > 0) {
568
+			if (c->maxa < (float)*w / *h)
569
+				*w = *h * c->maxa + 0.5;
570
+			else if (c->mina < (float)*h / *w)
571
+				*h = *w * c->mina + 0.5;
572
+		}
573
+		if (baseismin) { /* increment calculation requires this */
574
+			*w -= c->basew;
575
+			*h -= c->baseh;
576
+		}
577
+		/* adjust for increment value */
578
+		if (c->incw)
579
+			*w -= *w % c->incw;
580
+		if (c->inch)
581
+			*h -= *h % c->inch;
582
+		/* restore base dimensions */
583
+		*w = MAX(*w + c->basew, c->minw);
584
+		*h = MAX(*h + c->baseh, c->minh);
585
+		if (c->maxw)
586
+			*w = MIN(*w, c->maxw);
587
+		if (c->maxh)
588
+			*h = MIN(*h, c->maxh);
589
+	}
590
+	return *x != c->x || *y != c->y || *w != c->w || *h != c->h;
591
+}
592
+
593
+void
594
+arrange(Monitor *m)
595
+{
596
+	if (m)
597
+		showhide(m->stack);
598
+	else for (m = mons; m; m = m->next)
599
+		showhide(m->stack);
600
+	if (m) {
601
+		arrangemon(m);
602
+		restack(m);
603
+	} else for (m = mons; m; m = m->next)
604
+		arrangemon(m);
605
+}
606
+
607
+void
608
+arrangemon(Monitor *m)
609
+{
610
+	strncpy(m->ltsymbol, m->lt[m->sellt]->symbol, sizeof m->ltsymbol);
611
+	if (m->lt[m->sellt]->arrange)
612
+		m->lt[m->sellt]->arrange(m);
613
+}
614
+
615
+void
616
+attach(Client *c)
617
+{
618
+	c->next = c->mon->clients;
619
+	c->mon->clients = c;
620
+}
621
+
622
+void
623
+attachbottom(Client *c)
624
+{
625
+	Client **tc;
626
+	c->next = NULL;
627
+	for (tc = &c->mon->clients; *tc; tc = &(*tc)->next);
628
+	*tc = c;
629
+}
630
+
631
+void
632
+attachstack(Client *c)
633
+{
634
+	c->snext = c->mon->stack;
635
+	c->mon->stack = c;
636
+}
637
+
638
+void
639
+swallow(Client *p, Client *c)
640
+{
641
+	if (c->noswallow || c->isterminal)
642
+		return;
643
+	if (!swallowfloating && c->isfloating)
644
+		return;
645
+
646
+	detach(c);
647
+	detachstack(c);
648
+
649
+	setclientstate(c, WithdrawnState);
650
+	XUnmapWindow(dpy, p->win);
651
+
652
+	p->swallowing = c;
653
+	c->mon = p->mon;
654
+
655
+	Window w = p->win;
656
+	p->win = c->win;
657
+	c->win = w;
658
+	updatetitle(p);
659
+
660
+	XWindowChanges wc;
661
+	wc.border_width = p->bw;
662
+	XConfigureWindow(dpy, p->win, CWBorderWidth, &wc);
663
+	XMoveResizeWindow(dpy, p->win, p->x, p->y, p->w, p->h);
664
+	XSetWindowBorder(dpy, p->win, scheme[SchemeNorm][ColBorder].pixel);
665
+
666
+	arrange(p->mon);
667
+	configure(p);
668
+	updateclientlist();
669
+}
670
+
671
+void
672
+unswallow(Client *c)
673
+{
674
+	c->win = c->swallowing->win;
675
+
676
+	free(c->swallowing);
677
+	c->swallowing = NULL;
678
+
679
+	/* unfullscreen the client */
680
+	setfullscreen(c, 0);
681
+	updatetitle(c);
682
+	arrange(c->mon);
683
+	XMapWindow(dpy, c->win);
684
+
685
+	XWindowChanges wc;
686
+	wc.border_width = c->bw;
687
+	XConfigureWindow(dpy, c->win, CWBorderWidth, &wc);
688
+	XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h);
689
+	XSetWindowBorder(dpy, c->win, scheme[SchemeNorm][ColBorder].pixel);
690
+
691
+	setclientstate(c, NormalState);
692
+	focus(NULL);
693
+	arrange(c->mon);
694
+}
695
+
696
+void
697
+buttonpress(XEvent *e)
698
+{
699
+	int click, i, r, mi;
700
+	Arg arg = {0};
701
+	Client *c;
702
+	Monitor *m;
703
+	Bar *bar;
704
+	XButtonPressedEvent *ev = &e->xbutton;
705
+	const BarRule *br;
706
+	BarClickArg carg = { 0, 0, 0, 0 };
707
+
708
+	click = ClkRootWin;
709
+	/* focus monitor if necessary */
710
+	if ((m = wintomon(ev->window)) && m != selmon
711
+	) {
712
+		unfocus(selmon->sel, 1);
713
+		selmon = m;
714
+		focus(NULL);
715
+	}
716
+
717
+	for (mi = 0, m = mons; m && m != selmon; m = m->next, mi++); // get the monitor index
718
+	for (bar = selmon->bar; bar; bar = bar->next) {
719
+		if (ev->window == bar->win) {
720
+			for (r = 0; r < LENGTH(barrules); r++) {
721
+				br = &barrules[r];
722
+				if (br->bar != bar->idx || (br->monitor == 'A' && m != selmon) || br->clickfunc == NULL)
723
+					continue;
724
+				if (br->monitor != 'A' && br->monitor != -1 && br->monitor != mi)
725
+					continue;
726
+				if (bar->x[r] <= ev->x && ev->x <= bar->x[r] + bar->w[r]) {
727
+					carg.rel_x = ev->x - bar->x[r];
728
+					carg.rel_y = ev->y;
729
+					carg.rel_w = bar->w[r];
730
+					carg.rel_h = bar->bh;
731
+					click = br->clickfunc(bar, &arg, &carg);
732
+					if (click < 0)
733
+						return;
734
+					break;
735
+				}
736
+			}
737
+			break;
738
+		}
739
+	}
740
+
741
+	if (click == ClkRootWin && (c = wintoclient(ev->window))) {
742
+		focus(c);
743
+		restack(selmon);
744
+		XAllowEvents(dpy, ReplayPointer, CurrentTime);
745
+		click = ClkClientWin;
746
+	}
747
+
748
+	for (i = 0; i < LENGTH(buttons); i++) {
749
+		if (click == buttons[i].click && buttons[i].func && buttons[i].button == ev->button
750
+				&& CLEANMASK(buttons[i].mask) == CLEANMASK(ev->state)) {
751
+			buttons[i].func(click == ClkTagBar && buttons[i].arg.i == 0 ? &arg : &buttons[i].arg);
752
+		}
753
+	}
754
+}
755
+
756
+void
757
+checkotherwm(void)
758
+{
759
+	xerrorxlib = XSetErrorHandler(xerrorstart);
760
+	/* this causes an error if some other window manager is running */
761
+	XSelectInput(dpy, DefaultRootWindow(dpy), SubstructureRedirectMask);
762
+	XSync(dpy, False);
763
+	XSetErrorHandler(xerror);
764
+	XSync(dpy, False);
765
+}
766
+
767
+void
768
+cleanup(void)
769
+{
770
+	Arg a = {.ui = ~0};
771
+	Layout foo = { "", NULL };
772
+	Monitor *m;
773
+	size_t i;
774
+
775
+	view(&a);
776
+	selmon->lt[selmon->sellt] = &foo;
777
+	for (m = mons; m; m = m->next)
778
+		while (m->stack)
779
+			unmanage(m->stack, 0);
780
+	XUngrabKey(dpy, AnyKey, AnyModifier, root);
781
+	while (mons)
782
+		cleanupmon(mons);
783
+	for (i = 0; i < CurLast; i++)
784
+		drw_cur_free(drw, cursor[i]);
785
+	for (i = 0; i < LENGTH(colors); i++)
786
+		free(scheme[i]);
787
+	XDestroyWindow(dpy, wmcheckwin);
788
+	drw_free(drw);
789
+	XSync(dpy, False);
790
+	XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime);
791
+	XDeleteProperty(dpy, root, netatom[NetActiveWindow]);
792
+}
793
+
794
+void
795
+cleanupmon(Monitor *mon)
796
+{
797
+	Monitor *m;
798
+	Bar *bar;
799
+
800
+	if (mon == mons)
801
+		mons = mons->next;
802
+	else {
803
+		for (m = mons; m && m->next != mon; m = m->next);
804
+		m->next = mon->next;
805
+	}
806
+	for (bar = mon->bar; bar; bar = mon->bar) {
807
+		XUnmapWindow(dpy, bar->win);
808
+		XDestroyWindow(dpy, bar->win);
809
+		mon->bar = bar->next;
810
+		free(bar);
811
+	}
812
+	free(mon);
813
+}
814
+
815
+void
816
+clientmessage(XEvent *e)
817
+{
818
+	XClientMessageEvent *cme = &e->xclient;
819
+	Client *c = wintoclient(cme->window);
820
+
821
+	if (!c)
822
+		return;
823
+	if (cme->message_type == netatom[NetWMState]) {
824
+		if (cme->data.l[1] == netatom[NetWMFullscreen]
825
+		|| cme->data.l[2] == netatom[NetWMFullscreen])
826
+			setfullscreen(c, (cme->data.l[0] == 1 /* _NET_WM_STATE_ADD    */
827
+				|| (cme->data.l[0] == 2 /* _NET_WM_STATE_TOGGLE */ && !c->isfullscreen)));
828
+	} else if (cme->message_type == netatom[NetActiveWindow]) {
829
+		if (c != selmon->sel && !c->isurgent)
830
+			seturgent(c, 1);
831
+	}
832
+}
833
+
834
+void
835
+configure(Client *c)
836
+{
837
+	XConfigureEvent ce;
838
+
839
+	ce.type = ConfigureNotify;
840
+	ce.display = dpy;
841
+	ce.event = c->win;
842
+	ce.window = c->win;
843
+	ce.x = c->x;
844
+	ce.y = c->y;
845
+	ce.width = c->w;
846
+	ce.height = c->h;
847
+	ce.border_width = c->bw;
848
+	ce.above = None;
849
+	ce.override_redirect = False;
850
+	XSendEvent(dpy, c->win, False, StructureNotifyMask, (XEvent *)&ce);
851
+}
852
+
853
+void
854
+configurenotify(XEvent *e)
855
+{
856
+	Monitor *m;
857
+	Bar *bar;
858
+	Client *c;
859
+	XConfigureEvent *ev = &e->xconfigure;
860
+	int dirty;
861
+
862
+	/* TODO: updategeom handling sucks, needs to be simplified */
863
+	if (ev->window == root) {
864
+		dirty = (sw != ev->width || sh != ev->height);
865
+		sw = ev->width;
866
+		sh = ev->height;
867
+		if (updategeom() || dirty) {
868
+			drw_resize(drw, sw, bh);
869
+			updatebars();
870
+			for (m = mons; m; m = m->next) {
871
+				for (c = m->clients; c; c = c->next)
872
+					if (c->isfullscreen)
873
+						resizeclient(c, m->mx, m->my, m->mw, m->mh);
874
+				for (bar = m->bar; bar; bar = bar->next)
875
+					XMoveResizeWindow(dpy, bar->win, bar->bx, bar->by, bar->bw, bar->bh);
876
+			}
877
+			focus(NULL);
878
+			arrange(NULL);
879
+		}
880
+	}
881
+}
882
+
883
+void
884
+configurerequest(XEvent *e)
885
+{
886
+	Client *c;
887
+	Monitor *m;
888
+	XConfigureRequestEvent *ev = &e->xconfigurerequest;
889
+	XWindowChanges wc;
890
+
891
+	if ((c = wintoclient(ev->window))) {
892
+		if (ev->value_mask & CWBorderWidth)
893
+			c->bw = ev->border_width;
894
+		else if (c->isfloating || !selmon->lt[selmon->sellt]->arrange) {
895
+			m = c->mon;
896
+			if (ev->value_mask & CWX) {
897
+				c->oldx = c->x;
898
+				c->x = m->mx + ev->x;
899
+			}
900
+			if (ev->value_mask & CWY) {
901
+				c->oldy = c->y;
902
+				c->y = m->my + ev->y;
903
+			}
904
+			if (ev->value_mask & CWWidth) {
905
+				c->oldw = c->w;
906
+				c->w = ev->width;
907
+			}
908
+			if (ev->value_mask & CWHeight) {
909
+				c->oldh = c->h;
910
+				c->h = ev->height;
911
+			}
912
+			if ((c->x + c->w) > m->mx + m->mw && c->isfloating)
913
+				c->x = m->mx + (m->mw / 2 - WIDTH(c) / 2); /* center in x direction */
914
+			if ((c->y + c->h) > m->my + m->mh && c->isfloating)
915
+				c->y = m->my + (m->mh / 2 - HEIGHT(c) / 2); /* center in y direction */
916
+			if ((ev->value_mask & (CWX|CWY)) && !(ev->value_mask & (CWWidth|CWHeight)))
917
+				configure(c);
918
+			if (ISVISIBLE(c))
919
+				XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h);
920
+		} else
921
+			configure(c);
922
+	} else {
923
+		wc.x = ev->x;
924
+		wc.y = ev->y;
925
+		wc.width = ev->width;
926
+		wc.height = ev->height;
927
+		wc.border_width = ev->border_width;
928
+		wc.sibling = ev->above;
929
+		wc.stack_mode = ev->detail;
930
+		XConfigureWindow(dpy, ev->window, ev->value_mask, &wc);
931
+	}
932
+	XSync(dpy, False);
933
+}
934
+
935
+void
936
+copyvalidchars(char *text, char *rawtext)
937
+{
938
+	int i = -1, j = 0;
939
+
940
+	while(rawtext[++i]) {
941
+		if ((unsigned char)rawtext[i] >= ' ') {
942
+			text[j++] = rawtext[i];
943
+		}
944
+	}
945
+	text[j] = '\0';
946
+}
947
+
948
+Monitor *
949
+createmon(void)
950
+{
951
+	Monitor *m, *mon;
952
+	int i, n, mi, max_bars = 2, istopbar = topbar;
953
+
954
+	const BarRule *br;
955
+	Bar *bar;
956
+
957
+	m = ecalloc(1, sizeof(Monitor));
958
+	m->tagset[0] = m->tagset[1] = 1;
959
+	m->mfact = mfact;
960
+	m->nmaster = nmaster;
961
+	m->showbar = showbar;
962
+	m->gappih = gappih;
963
+	m->gappiv = gappiv;
964
+	m->gappoh = gappoh;
965
+	m->gappov = gappov;
966
+
967
+	for (mi = 0, mon = mons; mon; mon = mon->next, mi++); // monitor index
968
+	m->lt[0] = &layouts[0];
969
+	m->lt[1] = &layouts[1 % LENGTH(layouts)];
970
+	strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol);
971
+
972
+	/* Derive the number of bars for this monitor based on bar rules */
973
+	for (n = -1, i = 0; i < LENGTH(barrules); i++) {
974
+		br = &barrules[i];
975
+		if (br->monitor == 'A' || br->monitor == -1 || br->monitor == mi)
976
+			n = MAX(br->bar, n);
977
+	}
978
+
979
+	for (i = 0; i <= n && i < max_bars; i++) {
980
+		bar = ecalloc(1, sizeof(Bar));
981
+		bar->mon = m;
982
+		bar->idx = i;
983
+		bar->next = m->bar;
984
+		bar->topbar = istopbar;
985
+		m->bar = bar;
986
+		istopbar = !istopbar;
987
+	}
988
+
989
+	return m;
990
+}
991
+
992
+void
993
+destroynotify(XEvent *e)
994
+{
995
+	Client *c;
996
+	XDestroyWindowEvent *ev = &e->xdestroywindow;
997
+
998
+	if ((c = wintoclient(ev->window)))
999
+		unmanage(c, 1);