| Hash | Commit message | Author | Date | Files | + | - |
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); |