diff options
32 files changed, 1989 insertions, 1807 deletions
@@ -17,6 +17,7 @@ MIT/X Consortium License  © 2015-2016 Quentin Rameau <quinq@fifth.space>  © 2015-2016 Eric Pruitt <eric.pruitt@gmail.com>  © 2016-2017 Markus Teich <markus.teich@stusta.mhn.de> +© 2020-2022 Chris Down <chris@chrisdown.name>  Permission is hereby granted, free of charge, to any person obtaining a  copy of this software and associated documentation files (the "Software"), @@ -6,27 +6,21 @@ include config.mk  SRC = drw.c dwm.c util.c  OBJ = ${SRC:.c=.o} -all: options dwm - -options: -	@echo dwm build options: -	@echo "CFLAGS   = ${CFLAGS}" -	@echo "LDFLAGS  = ${LDFLAGS}" -	@echo "CC       = ${CC}" +all: dwm  .c.o:  	${CC} -c ${CFLAGS} $<  ${OBJ}: config.h config.mk -config.h: config.def.h +config.h:  	cp config.def.h $@  dwm: ${OBJ}  	${CC} -o $@ ${OBJ} ${LDFLAGS}  clean: -	rm -f dwm ${OBJ} dwm-${VERSION}.tar.gz +	rm -f dwm ${OBJ} dwm-${VERSION}.tar.gz config.h  dist: clean  	mkdir -p dwm-${VERSION} @@ -48,4 +42,4 @@ uninstall:  	rm -f ${DESTDIR}${PREFIX}/bin/dwm\  		${DESTDIR}${MANPREFIX}/man1/dwm.1 -.PHONY: all options clean dist install uninstall +.PHONY: all clean dist install uninstall @@ -1,75 +1,48 @@ -Joe's dwm (the dynamic window manager) build -The original dwm build I used to run. Based on version 6.2. +dwm - dynamic window manager +============================ +dwm is an extremely fast, small, and dynamic window manager for X. -Dependencies + +Requirements  ------------ - Required: - --------- -   - A C compiler -   - make -   - xorg -   - libX11 -   - libXft - - Optional: - --------- -   - st -   - dmenu +In order to build dwm you need the Xlib header files. +  Installation  ------------ -To install this open a terminal and run these commands: - -  $ git clone git://jozanleclerc.xyz/jozan/dwm.git -  $ cd dwm -  $ make -  # make install clean - -To use it as a default WM, if you are using xinit, add this to your .xinitrc: -  exec dwm - -Bindings --------- -Some of the main key bindings: - - switch to workspace 1-12 with super+{F1-F12} - - move selected stack to workspace 1-12 with super+shift+{F1-F12} - - fire up st terminal with super+return - - kill selected stack with super+q - - cycle through stacks down/up with super+j/k - - move selected stack down/up with super+shift+j/k - - resize master stack to left/right with super+h/l - - invoke dmenu_run application launcher with super+p - - toggle better tiled mode with super+s - - toggle alternative tiled mode with super+shift+s - - toggle normal tiled mode with super+t - - toggle fullscreen mode on selected stack with super+f - - toggle floating mode on selected stack with super+space - - toggle top bar with super+b. Hidden by default - - restart dwm with super+shift+r - - exit dwm with super+shift+e - -Patches -------- -List of patches in use: - - actualfullscreen - - alwayscenter - - alwaysfullscreen - - attachasideandbelow - - centeredmaster - - fibonacci - - focusonclick - - nmaster - - moveresize - - movestack - - noborder - - nodmenu - - pertag - - restartsig - - savefloats - - sizehints - - switchtotag - - tagothermon - -My own autostart script can be found under my dotfiles-bsd repository: -https://git.jozanleclerc.xyz/jozan/dotfiles-bsd/files.html -It should be placed in ~/.config/dwm directory. +Edit config.mk to match your local setup (dwm is installed into +the /usr/local namespace by default). + +Afterwards enter the following command to build and install dwm (if +necessary as root): + +    make clean install + + +Running dwm +----------- +Add the following line to your .xinitrc to start dwm using startx: + +    exec dwm + +In order to connect dwm to a specific display, make sure that +the DISPLAY environment variable is set correctly, e.g.: + +    DISPLAY=foo.bar:1 exec dwm + +(This will start dwm on display :1 of the host foo.bar.) + +In order to display status info in the bar, you can do something +like this in your .xinitrc: + +    while xsetroot -name "`date` `uptime | sed 's/.*,//'`" +    do +    	sleep 1 +    done & +    exec dwm + + +Configuration +------------- +The configuration of dwm is done by creating a custom config.h +and (re)compiling the source code. diff --git a/README.org b/README.org deleted file mode 100644 index 343e089..0000000 --- a/README.org +++ /dev/null @@ -1,72 +0,0 @@ -#+TITLE: Joe's dwm (the dynamic window manager) build -The original [[https://dwm.suckless.org/][dwm]] build I used to run. Based on version 6.2. - -* Dependencies -** Required: -	 - A C Compiler -	 - ~make~ -	 - ~xorg~ -	 - ~libX11~ -	 - ~libXft~ - -** Optional: -	 - ~st~ find my custom improved build [[https://github.com/JozanLeClerc/st][here]] -	 - ~dmenu~ - -* Installation -To install this open a terminal and run these commands: -#+BEGIN_SRC shell -git clone git://jozanleclerc.xyz/jozan/dwm.git -cd dwm -make -make install clean -#+END_SRC -To use it as a default WM, if you are using xinit, add this to your ~.xinitrc~: -#+BEGIN_SRC shell -exec dwm -#+END_SRC -I am not shure about how to set it up on regular desktop managers like ~gdm~ or ~lightdm~. - -* Bindings -Some of the main key bindings: -- *switch* to workspace 1-12 with ~super+{F1-F12}~ -- *move* selected stack to workspace 1-12 with ~super+shift+{F1-F12}~ -- *fire up* ~st~ terminal with ~super+return~ -- *kill* selected stack with ~super+q~ -- *cycle through* stacks down/up with ~super+j/k~ -- *move* selected stack down/up with ~super+shift+j/k~ -- *resize* master stack to left/right with ~super+h/l~ -- *invoke* ~dmenu_run~ application launcher with ~super+p~. Get it [[https://tools.suckless.org/dmenu/][here]] -- toggle *better tiled mode* with ~super+s~ -- toggle *alternative tiled mode* with ~super+shift+s~ -- toggle *normal tiled mode* with ~super+t~ -- toggle *fullscreen mode* on selected stack with ~super+f~ -- toggle *floating mode* on selected stack with ~super+space~ -- toggle *top bar* with ~super+b~. Hidden by default -- *restart* dwm with ~super+shift+r~ -- *exit* dwm with ~super+shift+e~ - -* Patches -List of patches in use: -- /actualfullscreen/ -- /alwayscenter/ -- /alwaysfullscreen/ -- /attachasideandbelow/ -- /centeredmaster/ -- /fibonacci/ -- /focusonclick/ -- /nmaster/ -- /moveresize/ -- /movestack/ -- /noborder/ -- /nodmenu/ -- /pertag/ -- /restartsig/ -- /savefloats/ -- /sizehints/ -- /switchtotag/ -- /tagothermon/ - -My own autostart script can be found under my -[[https://git.jozanleclerc.xyz/jozan/dotfiles-bsd/files.html][dotfiles-bsd]] repository. It should -be placed in =~/.config/dwm= directory. diff --git a/applied/dwm-6.0-winview.diff b/applied/dwm-6.0-winview.diff new file mode 100644 index 0000000..1b796b5 --- /dev/null +++ b/applied/dwm-6.0-winview.diff @@ -0,0 +1,65 @@ +diff --git a/config.def.h b/config.def.h +index 77ff358..3ba0efe 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -84,6 +84,7 @@ static Key keys[] = { + 	TAGKEYS(                        XK_8,                      7) + 	TAGKEYS(                        XK_9,                      8) + 	{ MODKEY|ShiftMask,             XK_q,      quit,           {0} }, ++	{ MODKEY,                       XK_o,      winview,        {0} }, + }; +  + /* button definitions */ +diff --git a/dwm.1 b/dwm.1 +index 5268a06..1188c82 100644 +--- a/dwm.1 ++++ b/dwm.1 +@@ -104,6 +104,9 @@ Increase master area size. + .B Mod1\-h + Decrease master area size. + .TP ++.B Mod1\-o ++Select view of the window in focus. The list of tags to be displayed is matched to the window tag list. ++.TP + .B Mod1\-Return + Zooms/cycles focused window to/from master area (tiled layouts only). + .TP +diff --git a/dwm.c b/dwm.c +index 1d78655..abf944c 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -247,6 +247,7 @@ static void updatewmhints(Client *c); + static void view(const Arg *arg); + static Client *wintoclient(Window w); + static Monitor *wintomon(Window w); ++static void winview(const Arg* arg); + static int xerror(Display *dpy, XErrorEvent *ee); + static int xerrordummy(Display *dpy, XErrorEvent *ee); + static int xerrorstart(Display *dpy, XErrorEvent *ee); +@@ -2080,6 +2081,26 @@ wintomon(Window w) { + 	return selmon; + } +  ++/* Selects for the view of the focused window. The list of tags */ ++/* to be displayed is matched to the focused window tag list. */ ++void ++winview(const Arg* arg){ ++	Window win, win_r, win_p, *win_c; ++	unsigned nc; ++	int unused; ++	Client* c; ++	Arg a; ++ ++	if (!XGetInputFocus(dpy, &win, &unused)) return; ++	while(XQueryTree(dpy, win, &win_r, &win_p, &win_c, &nc) ++	      && win_p != win_r) win = win_p; ++ ++	if (!(c = wintoclient(win))) return; ++ ++	a.ui = c->tags; ++	view(&a); ++} ++ + /* 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.  */ diff --git a/applied/dwm-attachasideandbelow-20200702-f04cac6.diff b/applied/dwm-attachasideandbelow-6.4.diff index 1b9219d..326f757 100644 --- a/applied/dwm-attachasideandbelow-20200702-f04cac6.diff +++ b/applied/dwm-attachasideandbelow-6.4.diff @@ -1,6 +1,7 @@ -diff -up b/dwm.c a/dwm.c ---- b/dwm.c	2020-07-05 16:05:02.555947738 -0300 -+++ a/dwm.c	2020-07-05 16:06:19.592609932 -0300 +diff --git a/dwm.c b/dwm.c +index e5efb6a..7b8d4a0 100644 +--- a/dwm.c ++++ b/dwm.c  @@ -49,7 +49,8 @@   #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)) \ @@ -11,7 +12,7 @@ diff -up b/dwm.c a/dwm.c   #define LENGTH(X)               (sizeof X / sizeof X[0])   #define MOUSEMASK               (BUTTONMASK|PointerMotionMask)   #define WIDTH(X)                ((X)->w + 2 * (X)->bw) -@@ -147,6 +148,7 @@ static int applysizehints(Client *c, int +@@ -147,6 +148,7 @@ static int applysizehints(Client *c, int *x, int *y, int *w, int *h, int interac   static void arrange(Monitor *m);   static void arrangemon(Monitor *m);   static void attach(Client *c); @@ -25,9 +26,9 @@ diff -up b/dwm.c a/dwm.c   static void movemouse(const Arg *arg);  +static Client *nexttagged(Client *c);   static Client *nexttiled(Client *c); - static void pop(Client *); + static void pop(Client *c);   static void propertynotify(XEvent *e); -@@ -406,6 +409,27 @@ attach(Client *c) +@@ -408,6 +411,27 @@ attach(Client *c)   	c->next = c->mon->clients;   	c->mon->clients = c;   } @@ -55,7 +56,7 @@ diff -up b/dwm.c a/dwm.c   void   attachstack(Client *c) -@@ -1063,7 +1087,7 @@ manage(Window w, XWindowAttributes *wa) +@@ -1065,7 +1089,7 @@ manage(Window w, XWindowAttributes *wa)   		c->isfloating = c->oldstate = trans != None || c->isfixed;   	if (c->isfloating)   		XRaiseWindow(dpy, c->win); @@ -90,11 +91,14 @@ diff -up b/dwm.c a/dwm.c   	attachstack(c);   	focus(NULL);   	arrange(NULL); -@@ -1901,6 +1935,7 @@ updategeom(void) - 					detachstack(c); - 					c->mon = mons; - 					attach(c); -+					attachBelow(c); - 					attachstack(c); - 				} - 				if (m == selmon) +@@ -1898,6 +1932,7 @@ updategeom(void) + 				detachstack(c); + 				c->mon = mons; + 				attach(c); ++				attachBelow(c); + 				attachstack(c); + 			} + 			if (m == selmon) +--  +2.41.0 + diff --git a/applied/dwm-bar-height-6.2.diff b/applied/dwm-bar-height-6.2.diff deleted file mode 100644 index a576111..0000000 --- a/applied/dwm-bar-height-6.2.diff +++ /dev/null @@ -1,25 +0,0 @@ -diff --git a/config.def.h b/config.def.h -index 1c0b587..9814500 100644 ---- a/config.def.h -+++ b/config.def.h -@@ -5,6 +5,7 @@ static const unsigned int borderpx  = 1;        /* border pixel of windows */ - static const unsigned int snap      = 32;       /* snap pixel */ - static const int showbar            = 1;        /* 0 means no bar */ - static const int topbar             = 1;        /* 0 means bottom bar */ -+static const int user_bh            = 0;        /* 0 means that dwm will calculate bar height, >= 1 means dwm will user_bh as bar height */ - static const char *fonts[]          = { "monospace:size=10" }; - static const char dmenufont[]       = "monospace:size=10"; - static const char col_gray1[]       = "#222222"; -diff --git a/dwm.c b/dwm.c -index 4465af1..2c27cb3 100644 ---- a/dwm.c -+++ b/dwm.c -@@ -1545,7 +1545,7 @@ setup(void) - 	if (!drw_fontset_create(drw, fonts, LENGTH(fonts))) - 		die("no fonts could be loaded."); - 	lrpad = drw->fonts->h; --	bh = drw->fonts->h + 2; -+	bh = user_bh ? user_bh : drw->fonts->h + 2; - 	updategeom(); - 	/* init atoms */ - 	utf8string = XInternAtom(dpy, "UTF8_STRING", False); diff --git a/applied/dwm-dash_above_activeWindow-20240604-061e9fe.diff b/applied/dwm-dash_above_activeWindow-20240604-061e9fe.diff new file mode 100644 index 0000000..4d66f6c --- /dev/null +++ b/applied/dwm-dash_above_activeWindow-20240604-061e9fe.diff @@ -0,0 +1,44 @@ +From 89303c44ed3c65e106f7e2e7711c112867226695 Mon Sep 17 00:00:00 2001 +From: DonRehan <30264386+donRehan@users.noreply.github.com> +Date: Tue, 4 Jun 2024 04:33:48 +0300 +Subject: [PATCH] Add a dash above current active window in dwm bar + +Give user ability to modify its position , width and text position. +--- + config.def.h | 3 +++ + dwm.c        | 4 +++- + 2 files changed, 6 insertions(+), 1 deletion(-) + +diff --git a/config.def.h b/config.def.h +index 9efa774..2ec5f52 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -2,6 +2,9 @@ +  + /* appearance */ + static const unsigned int borderpx  = 1;        /* border pixel of windows */ ++static const unsigned int brdsh_w  = 2;        /* width of the app bar dash */ ++static const unsigned int brdsh_ypos  = 18;        /* y-position of the dash */ ++static const unsigned int text_ypos  = 1;        /* y-position of text */ + static const unsigned int snap      = 32;       /* snap pixel */ + static const int showbar            = 1;        /* 0 means no bar */ + static const int topbar             = 1;        /* 0 means bottom bar */ +diff --git a/dwm.c b/dwm.c +index f1d86b2..3c9b293 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -736,8 +736,10 @@ drawbar(Monitor *m) +  + 	if ((w = m->ww - tw - x) > bh) { + 		if (m->sel) { ++			drw_setscheme(drw, scheme[SchemeNorm]); ++			drw_text(drw, x, text_ypos, w, bh, lrpad / 2, m->sel->name, 0); + 			drw_setscheme(drw, scheme[m == selmon ? SchemeSel : SchemeNorm]); +-			drw_text(drw, x, 0, w, bh, lrpad / 2, m->sel->name, 0); ++			drw_rect(drw, x , bh - brdsh_ypos , w , brdsh_w , 1, 1); + 			if (m->sel->isfloating) + 				drw_rect(drw, x + boxs, boxs, boxw, boxw, m->sel->isfixed, 0); + 		} else { +--  +2.34.1 + diff --git a/applied/dwm-foreground-20240220-9f88553.diff b/applied/dwm-foreground-20240220-9f88553.diff new file mode 100644 index 0000000..d5e4502 --- /dev/null +++ b/applied/dwm-foreground-20240220-9f88553.diff @@ -0,0 +1,180 @@ +From 507895940574e77386d53f81df541e3903bf1ba3 Mon Sep 17 00:00:00 2001 +From: espro1 <ericspero@icloud.com> +Date: Tue, 20 Feb 2024 16:11:05 -0500 +Subject: [PATCH] Essentially a layout for a special class of floating windows. + When a window is foregrounded, it is floated, resized, and moved to a + predictable location + +--- + config.def.h |  3 ++ + dwm.c        | 82 +++++++++++++++++++++++++++++++++++++++++++++++++++- + 2 files changed, 84 insertions(+), 1 deletion(-) + +diff --git a/config.def.h b/config.def.h +index 9efa774..718e7c3 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -37,6 +37,8 @@ static const int nmaster     = 1;    /* number of clients in master area */ + static const int resizehints = 1;    /* 1 means respect size hints in tiled resizals */ + static const int lockfullscreen = 1; /* 1 will force focus on the fullscreen window */ + ++static const float fgw = .6,fgh = .6; ++ + static const Layout layouts[] = { + 	/* symbol     arrange function */ + 	{ "[]=",      tile },    /* first entry is default */ +@@ -78,6 +80,7 @@ static const Key keys[] = { + 	{ MODKEY,                       XK_f,      setlayout,      {.v = &layouts[1]} }, + 	{ MODKEY,                       XK_m,      setlayout,      {.v = &layouts[2]} }, + 	{ MODKEY,                       XK_space,  setlayout,      {0} }, ++	{ MODKEY|Mod4Mask,              XK_space,  toggleforegrounded, {0} }, + 	{ MODKEY|ShiftMask,             XK_space,  togglefloating, {0} }, + 	{ MODKEY,                       XK_0,      view,           {.ui = ~0 } }, + 	{ MODKEY|ShiftMask,             XK_0,      tag,            {.ui = ~0 } }, +diff --git a/dwm.c b/dwm.c +index f1d86b2..12b037d 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -92,9 +92,10 @@ struct Client { + 	int basew, baseh, incw, inch, maxw, maxh, minw, minh, hintsvalid; + 	int bw, oldbw; + 	unsigned int tags; +-	int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen; ++	int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen, isforegrounded; + 	Client *next; + 	Client *snext; ++	Client *tnext; + 	Monitor *mon; + 	Window win; + }; +@@ -127,6 +128,7 @@ struct Monitor { + 	Client *clients; + 	Client *sel; + 	Client *stack; ++	Client *foregrounded; + 	Monitor *next; + 	Window barwin; + 	const Layout *lt[2]; +@@ -210,6 +212,7 @@ static void tag(const Arg *arg); + static void tagmon(const Arg *arg); + static void tile(Monitor *m); + static void togglebar(const Arg *arg); ++static void toggleforegrounded(const Arg *arg); + static void togglefloating(const Arg *arg); + static void toggletag(const Arg *arg); + static void toggleview(const Arg *arg); +@@ -415,6 +418,21 @@ attachstack(Client *c) + 	c->mon->stack = c; + } + ++void ++attachforegrounded (Client *c) ++{ ++	c->tnext = c->mon->foregrounded; ++	c->mon->foregrounded = c; ++} ++ ++void ++detachforegrounded (Client *c) ++{ ++	Client **tc; ++	for (tc = &c->mon->foregrounded; *tc && *tc != c; tc = &(*tc)->tnext); ++	*tc = c->tnext; ++} ++ + void + buttonpress(XEvent *e) + { +@@ -1209,6 +1227,39 @@ nexttiled(Client *c) + 	return c; + } + ++Client * ++nextforegrounded(Client *c) ++{ ++	for (; c && (!c->isforegrounded || !ISVISIBLE(c)); c = c->tnext); ++	return c; ++} ++ ++void ++arrangeforegrounded (Monitor *m) ++{ ++	unsigned int n,i,x,y,w,h; ++	Client *c; ++ ++	for (n = 0, c = nextforegrounded(m->foregrounded); c; c = nextforegrounded(c->tnext), n++); ++	if (n == 0) ++		return; ++ ++	for (i = 0, c = nextforegrounded(m->foregrounded); c; c = nextforegrounded(c->tnext), i++){ ++		if (n == 1) { ++			x = m->mx + (m->mw - m->mw * fgw) / 2; ++			y = m->my + (m->mh - m->mh * fgh) / 2; ++			w = (m->mw * fgw) - (2 * (m->foregrounded->bw)); ++			h = (m->mh * fgh) - (2 * (m->foregrounded->bw)); ++		} else { ++			x = (n - 1 - i) * (m->mw / n); ++			y = m->my + (m->mh - m->mh * fgh) / 2; ++			w = (m->mw * (1 / (float)n)) - (2 * (m->foregrounded->bw)); ++			h = (m->mh * fgh) - (2 * (m->foregrounded->bw)); ++		} ++		resize(c,x,y,w,h,0); ++	} ++} ++ + void + pop(Client *c) + { +@@ -1721,6 +1772,24 @@ togglebar(const Arg *arg) + 	arrange(selmon); + } + ++void ++toggleforegrounded(const Arg *arg) ++{ ++	if (!selmon->sel) ++		return; ++	if (selmon->sel->isfullscreen) /* no support for fullscreen windows */ ++		return; ++ ++	selmon->sel->isforegrounded || selmon->sel->isfloating ? ++		detachforegrounded(selmon->sel) : attachforegrounded(selmon->sel); ++ ++	selmon->sel->isforegrounded = selmon->sel->isfloating = ++		!selmon->sel->isfloating && !selmon->sel->isforegrounded; ++ ++	arrangeforegrounded(selmon); ++	arrange(selmon); ++} ++ + void + togglefloating(const Arg *arg) + { +@@ -1732,6 +1801,11 @@ togglefloating(const Arg *arg) + 	if (selmon->sel->isfloating) + 		resize(selmon->sel, selmon->sel->x, selmon->sel->y, + 			selmon->sel->w, selmon->sel->h, 0); ++	if (selmon->sel->isforegrounded) { ++		selmon->sel->isforegrounded = 0; ++		detachforegrounded(selmon->sel); ++		arrangeforegrounded(selmon); ++	} + 	arrange(selmon); + } + +@@ -1783,6 +1857,12 @@ unmanage(Client *c, int destroyed) + + 	detach(c); + 	detachstack(c); ++ ++	if (c->isforegrounded){ ++		detachforegrounded(c); ++		arrangeforegrounded(m); ++	} ++ + 	if (!destroyed) { + 		wc.border_width = c->oldbw; + 		XGrabServer(dpy); /* avoid race conditions */ +-- +2.43.0 + diff --git a/applied/dwm-fullgaps-20200508-7b77734.diff b/applied/dwm-fullgaps-6.4.diff index 29bd6dc..dc52139 100644 --- a/applied/dwm-fullgaps-20200508-7b77734.diff +++ b/applied/dwm-fullgaps-6.4.diff @@ -1,41 +1,27 @@ -From 7b7773458c072e4b24d6ea32d0364a8e402e4a43 Mon Sep 17 00:00:00 2001 -From: swy7ch <swy7ch@protonmail.com> -Date: Fri, 8 May 2020 19:07:24 +0200 -Subject: [PATCH] [PATCH] update dwm-fullgaps patch to be used with tile layout - update - -the recent tile layout changes in commit HEAD~1 (f09418b) broke the -patch - -this patch adapt the new `if` statements to take gaps into account - -this patch also provides manpage entries for the keybindings ---- -diff --git a/dwm.1 b/dwm.1 -index 13b3729..0202d96 100644 ---- a/dwm.1 -+++ b/dwm.1 -@@ -140,6 +140,16 @@ View all windows with any tag. - .B Mod1\-Control\-[1..n] - Add/remove all windows with nth tag to/from the view. - .TP -+.B Mod1\-- -+Decrease the gaps around windows. -+.TP -+.B Mod1\-= -+Increase the gaps around windows. -+.TP -+.B Mod1\-Shift-= -+Reset the gaps around windows to -+.BR 0 . -+.TP - .B Mod1\-Shift\-q - Quit dwm. - .SS Mouse commands -diff --git a/dwm.c b/dwm.c -index 9fd0286..45a58f3 100644 ---- a/dwm.c -+++ b/dwm.c +diff -up a/config.def.h b/config.def.h +--- a/config.def.h ++++ b/config.def.h +@@ -2,6 +2,7 @@ +  + /* appearance */ + static const unsigned int borderpx  = 1;        /* border pixel of windows */ ++static const unsigned int gappx     = 5;        /* gaps between windows */ + static const unsigned int snap      = 32;       /* snap pixel */ + static const int showbar            = 1;        /* 0 means no bar */ + static const int topbar             = 1;        /* 0 means bottom bar */ +@@ -85,6 +86,9 @@ static const Key keys[] = { + 	{ MODKEY,                       XK_period, focusmon,       {.i = +1 } }, + 	{ MODKEY|ShiftMask,             XK_comma,  tagmon,         {.i = -1 } }, + 	{ MODKEY|ShiftMask,             XK_period, tagmon,         {.i = +1 } }, ++	{ MODKEY,                       XK_minus,  setgaps,        {.i = -1 } }, ++	{ MODKEY,                       XK_equal,  setgaps,        {.i = +1 } }, ++	{ MODKEY|ShiftMask,             XK_equal,  setgaps,        {.i = 0  } }, + 	TAGKEYS(                        XK_1,                      0) + 	TAGKEYS(                        XK_2,                      1) + 	TAGKEYS(                        XK_3,                      2) +diff -up a/dwm.c b/dwm.c +--- a/dwm.c	2023-04-30 ++++ b/dwm.c	2023-04-30  @@ -119,6 +119,7 @@ struct Monitor {   	int by;               /* bar geometry */   	int mx, my, mw, mh;   /* screen size */ @@ -44,7 +30,7 @@ index 9fd0286..45a58f3 100644   	unsigned int seltags;   	unsigned int sellt;   	unsigned int tagset[2]; -@@ -200,6 +201,7 @@ static void sendmon(Client *c, Monitor *m); +@@ -200,6 +201,7 @@ static void sendmon(Client *c, Monitor *   static void setclientstate(Client *c, long state);   static void setfocus(Client *c);   static void setfullscreen(Client *c, int fullscreen); @@ -52,7 +38,7 @@ index 9fd0286..45a58f3 100644   static void setlayout(const Arg *arg);   static void setmfact(const Arg *arg);   static void setup(void); -@@ -639,6 +641,7 @@ createmon(void) +@@ -641,6 +643,7 @@ createmon(void)   	m->nmaster = nmaster;   	m->showbar = showbar;   	m->topbar = topbar; @@ -60,11 +46,10 @@ index 9fd0286..45a58f3 100644   	m->lt[0] = &layouts[0];   	m->lt[1] = &layouts[1 % LENGTH(layouts)];   	strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol); -@@ -1498,6 +1501,16 @@ setfullscreen(Client *c, int fullscreen) - 	} +@@ -1508,6 +1511,16 @@ setfullscreen(Client *c, int fullscreen)   } -+void + void  +setgaps(const Arg *arg)  +{  +	if ((arg->i == 0) || (selmon->gappx + arg->i < 0)) @@ -74,22 +59,24 @@ index 9fd0286..45a58f3 100644  +	arrange(selmon);  +}  + - void ++void   setlayout(const Arg *arg)   { -@@ -1684,18 +1697,18 @@ tile(Monitor *m) + 	if (!arg || !arg->v || arg->v != selmon->lt[selmon->sellt]) +@@ -1697,18 +1710,18 @@ tile(Monitor *m)   	if (n > m->nmaster)   		mw = m->nmaster ? m->ww * m->mfact : 0;   	else  -		mw = m->ww;  -	for (i = my = ty = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) -+		mw = m->ww - m->gappx; -+	for (i = 0, my = ty = m->gappx, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) - 		if (i < m->nmaster) { +-		if (i < m->nmaster) {  -			h = (m->wh - my) / (MIN(n, m->nmaster) - i);  -			resize(c, m->wx, m->wy + my, mw - (2*c->bw), h - (2*c->bw), 0);  -			if (my + HEIGHT(c) < m->wh)  -				my += HEIGHT(c); ++		mw = m->ww - m->gappx; ++	for (i = 0, my = ty = m->gappx, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) ++			if (i < m->nmaster) {  +			h = (m->wh - my) / (MIN(n, m->nmaster) - i) - m->gappx;  +			resize(c, m->wx + m->gappx, m->wy + my, mw - (2*c->bw) - m->gappx, h - (2*c->bw), 0);  +			if (my + HEIGHT(c) + m->gappx < m->wh) @@ -105,7 +92,3 @@ index 9fd0286..45a58f3 100644  +				ty += HEIGHT(c) + m->gappx;   		}   } -  ---  -2.26.2 - diff --git a/applied/dwm-nrowgrid-6.1.diff b/applied/dwm-nrowgrid-6.1.diff new file mode 100644 index 0000000..e2e6505 --- /dev/null +++ b/applied/dwm-nrowgrid-6.1.diff @@ -0,0 +1,77 @@ +Author: Chris Noxz <chris@noxz.tech> + +diff -upN dwm-6.1/config.def.h dwm-nrowgrid-6.1/config.def.h +--- dwm-6.1/config.def.h	2015-11-08 23:11:48.000000000 +0100 ++++ dwm-nrowgrid-6.1/config.def.h	2018-10-01 10:44:05.631382842 +0200 +@@ -34,11 +34,15 @@ static const float mfact     = 0.55; /* + static const int nmaster     = 1;    /* number of clients in master area */ + static const int resizehints = 1;    /* 1 means respect size hints in tiled resizals */ +  ++#define FORCE_VSPLIT 1 ++#include "nrowgrid.c" ++ + static const Layout layouts[] = { + 	/* symbol     arrange function */ + 	{ "[]=",      tile },    /* first entry is default */ + 	{ "><>",      NULL },    /* no layout function means floating behavior */ + 	{ "[M]",      monocle }, ++	{ "###",      nrowgrid }, + }; +  + /* key definitions */ +diff -upN dwm-6.1/nrowgrid.c dwm-nrowgrid-6.1/nrowgrid.c +--- dwm-6.1/nrowgrid.c	1970-01-01 01:00:00.000000000 +0100 ++++ dwm-nrowgrid-6.1/nrowgrid.c	2018-10-01 10:44:27.741263063 +0200 +@@ -0,0 +1,52 @@ ++void ++nrowgrid(Monitor *m) ++{ ++    unsigned int n = 0, i = 0, ri = 0, ci = 0;  /* counters */ ++    unsigned int cx, cy, cw, ch;                /* client geometry */ ++    unsigned int uw = 0, uh = 0, uc = 0;        /* utilization trackers */ ++    unsigned int cols, rows = m->nmaster + 1; ++    Client *c; ++ ++    /* count clients */ ++    for (c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); ++ ++    /* nothing to do here */ ++    if (n == 0) ++        return; ++ ++    /* force 2 clients to always split vertically */ ++    if (FORCE_VSPLIT && n == 2) ++        rows = 1; ++ ++    /* never allow empty rows */ ++    if (n < rows) ++        rows = n; ++ ++    /* define first row */ ++    cols = n / rows; ++    uc = cols; ++    cy = m->wy; ++    ch = m->wh / rows; ++    uh = ch; ++ ++    for (c = nexttiled(m->clients); c; c = nexttiled(c->next), i++, ci++) { ++        if (ci == cols) { ++            uw = 0; ++            ci = 0; ++            ri++; ++ ++            /* next row */ ++            cols = (n - uc) / (rows - ri); ++            uc += cols; ++            cy = m->wy + uh; ++            ch = (m->wh - uh) / (rows - ri); ++            uh += ch; ++        } ++ ++        cx = m->wx + uw; ++        cw = (m->ww - uw) / (cols - ci); ++        uw += cw; ++ ++        resize(c, cx, cy, cw - 2 * c->bw, ch - 2 * c->bw, 0); ++    } ++} diff --git a/applied/dwm-preventfocusshift-20240831-6.5.diff b/applied/dwm-preventfocusshift-20240831-6.5.diff new file mode 100644 index 0000000..78a24cb --- /dev/null +++ b/applied/dwm-preventfocusshift-20240831-6.5.diff @@ -0,0 +1,25 @@ +From 554f5a8a2205a7c52280babf5685462d8991b038 Mon Sep 17 00:00:00 2001 +From: Suleyman Farajli <suleyman@farajli.net> +Date: Sat, 31 Aug 2024 13:34:58 +0400 +Subject: [PATCH] prevent focus shifting when a window is spawned in fullscreen + +--- + dwm.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/dwm.c b/dwm.c +index f1d86b2..31b5d07 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -1080,6 +1080,8 @@ manage(Window w, XWindowAttributes *wa) + 		(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(selmon->sel && selmon->sel->isfullscreen && !c->isfloating) ++		setfullscreen(selmon->sel, 0); + 	if (c->mon == selmon) + 		unfocus(selmon->sel, 0); + 	c->mon->sel = c; +--  +2.44.2 + diff --git a/applied/dwm-sizehints-isfreesize-6.2.diff b/applied/dwm-sizehints-isfreesize-6.2.diff deleted file mode 100644 index bd9e5da..0000000 --- a/applied/dwm-sizehints-isfreesize-6.2.diff +++ /dev/null @@ -1,103 +0,0 @@ -From 5d4e92801206d47090236498d35f199e46dd07f6 Mon Sep 17 00:00:00 2001 -From: MLquest8 <miskuzius@gmail.com> -Date: Sat, 20 Jun 2020 15:40:43 +0400 -Subject: [PATCH] sizehints-ruled now with a separate rule "isfreesize" and - cleaner code. - ---- - config.def.h |  8 +++++--- - dwm.c        | 16 +++++++++++++--- - 2 files changed, 18 insertions(+), 6 deletions(-) - -diff --git a/config.def.h b/config.def.h -index 1c0b587..0e4a5ea 100644 ---- a/config.def.h -+++ b/config.def.h -@@ -26,9 +26,11 @@ static const Rule rules[] = { - 	 *	WM_CLASS(STRING) = instance, class - 	 *	WM_NAME(STRING) = title - 	 */ --	/* class      instance    title       tags mask     isfloating   monitor */ --	{ "Gimp",     NULL,       NULL,       0,            1,           -1 }, --	{ "Firefox",  NULL,       NULL,       1 << 8,       0,           -1 }, -+	/* class      instance    title       tags mask     isfloating   isfreesize   monitor */ -+	{ "Gimp",     NULL,       NULL,       0,            1,           1,           -1 }, -+	{ "Firefox",  NULL,       NULL,       1 << 8,       0,           0,	      -1 }, -+	{ "st",       NULL,       NULL,       0,    	    0,           0,	      -1 }, -+	{ "St",       NULL,       NULL,       0,	    0,           0,	      -1 }, /* St with Xresources patch */ - }; -  - /* layout(s) */ -diff --git a/dwm.c b/dwm.c -index 9fd0286..73825d1 100644 ---- a/dwm.c -+++ b/dwm.c -@@ -92,7 +92,7 @@ struct Client { - 	int basew, baseh, incw, inch, maxw, maxh, minw, minh; - 	int bw, oldbw; - 	unsigned int tags; --	int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen; -+	int isfixed, isfloating, isfreesize, isurgent, neverfocus, oldstate, isfullscreen; - 	Client *next; - 	Client *snext; - 	Monitor *mon; -@@ -138,6 +138,7 @@ typedef struct { - 	const char *title; - 	unsigned int tags; - 	int isfloating; -+	int isfreesize; - 	int monitor; - } Rule; -  -@@ -287,6 +288,7 @@ applyrules(Client *c) -  - 	/* rule matching */ - 	c->isfloating = 0; -+	c->isfreesize = 1; - 	c->tags = 0; - 	XGetClassHint(dpy, c->win, &ch); - 	class    = ch.res_class ? ch.res_class : broken; -@@ -299,6 +301,7 @@ applyrules(Client *c) - 		&& (!r->instance || strstr(instance, r->instance))) - 		{ - 			c->isfloating = r->isfloating; -+			c->isfreesize = r->isfreesize; - 			c->tags |= r->tags; - 			for (m = mons; m && m->num != r->monitor; m = m->next); - 			if (m) -@@ -1952,7 +1955,7 @@ updatesizehints(Client *c) -  - 	if (!XGetWMNormalHints(dpy, c->win, &size, &msize)) - 		/* size is uninitialized, ensure that size.flags aren't used */ --		size.flags = PSize; -+		size.flags = 0; - 	if (size.flags & PBaseSize) { - 		c->basew = size.base_width; - 		c->baseh = size.base_height; -@@ -1984,6 +1987,11 @@ updatesizehints(Client *c) - 		c->maxa = (float)size.max_aspect.x / size.max_aspect.y; - 	} else - 		c->maxa = c->mina = 0.0; -+	if((size.flags & PSize) && c->isfreesize) { -+		c->basew = size.base_width; -+		c->baseh = size.base_height; -+		c->isfloating = 1; -+	} - 	c->isfixed = (c->maxw && c->maxh && c->maxw == c->minw && c->maxh == c->minh); - } -  -@@ -2012,8 +2020,10 @@ updatewindowtype(Client *c) -  - 	if (state == netatom[NetWMFullscreen]) - 		setfullscreen(c, 1); --	if (wtype == netatom[NetWMWindowTypeDialog]) -+	if (wtype == netatom[NetWMWindowTypeDialog]) { - 		c->isfloating = 1; -+		c->isfreesize = 1; -+	} - } -  - void ---  -2.26.2 - diff --git a/applied/dwm-stairs-fullgaps-20220430-8b48e30.diff b/applied/dwm-stairs-fullgaps-20220430-8b48e30.diff deleted file mode 100644 index 53e7966..0000000 --- a/applied/dwm-stairs-fullgaps-20220430-8b48e30.diff +++ /dev/null @@ -1,98 +0,0 @@ -From 2004db267a9478918699961ab2f3579c2c8113fb Mon Sep 17 00:00:00 2001 -From: Ehsan Ghorbannezhad <ehsan@disroot.org> -Date: Sat, 30 Apr 2022 02:48:58 +0430 -Subject: [PATCH] add the stairs layout with fullgaps support - ---- - config.def.h |  5 +++++ - dwm.c        | 38 ++++++++++++++++++++++++++++++++++++++ - 2 files changed, 43 insertions(+) - -diff --git a/config.def.h b/config.def.h -index 5b0d4de..c0f24f4 100644 ---- a/config.def.h -+++ b/config.def.h -@@ -6,6 +6,9 @@ static const unsigned int gappx     = 5;        /* gaps between windows */ - static const unsigned int snap      = 32;       /* snap pixel */ - static const int showbar            = 1;        /* 0 means no bar */ - static const int topbar             = 1;        /* 0 means bottom bar */ -+static const unsigned int stairpx   = 20;       /* depth of the stairs layout */ -+static const int stairdirection     = 1;        /* 0: left-aligned, 1: right-aligned */ -+static const int stairsamesize      = 1;        /* 1 means shrink all the staired windows to the same size */ - static const char *fonts[]          = { "monospace:size=10" }; - static const char dmenufont[]       = "monospace:size=10"; - static const char col_gray1[]       = "#222222"; -@@ -43,6 +46,7 @@ static const Layout layouts[] = { - 	{ "[]=",      tile },    /* first entry is default */ - 	{ "><>",      NULL },    /* no layout function means floating behavior */ - 	{ "[M]",      monocle }, -+	{ "[S]",      stairs }, - }; - - /* key definitions */ -@@ -78,6 +82,7 @@ static Key keys[] = { - 	{ MODKEY,                       XK_t,      setlayout,      {.v = &layouts[0]} }, - 	{ MODKEY,                       XK_f,      setlayout,      {.v = &layouts[1]} }, - 	{ MODKEY,                       XK_m,      setlayout,      {.v = &layouts[2]} }, -+	{ MODKEY,                       XK_s,      setlayout,      {.v = &layouts[3]} }, - 	{ MODKEY,                       XK_space,  setlayout,      {0} }, - 	{ MODKEY|ShiftMask,             XK_space,  togglefloating, {0} }, - 	{ MODKEY,                       XK_0,      view,           {.ui = ~0 } }, -diff --git a/dwm.c b/dwm.c -index 5b7348c..2c5380f 100644 ---- a/dwm.c -+++ b/dwm.c -@@ -209,6 +209,7 @@ 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 stairs(Monitor *m); - static void tag(const Arg *arg); - static void tagmon(const Arg *arg); - static void tile(Monitor *); -@@ -1672,6 +1673,43 @@ spawn(const Arg *arg) - 	} - } - -+void -+stairs(Monitor *m) -+{ -+	unsigned int i, n, h, mw, my; -+	unsigned int ox, oy, ow, oh; /* stair offset values */ -+	Client *c; -+ -+	for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); -+	if (n == 0) -+		return; -+ -+	if (n > m->nmaster) -+		mw = m->nmaster ? m->ww * m->mfact : 0; -+	else -+		mw = m->ww - m->gappx; -+ -+	for (i = 0, my = m->gappx, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) { -+		if (i < m->nmaster) { -+			h = (m->wh - my) / (MIN(n, m->nmaster) - i) - m->gappx; -+			resize(c, m->wx + m->gappx, m->wy + my, mw - (2 * c->bw) - m->gappx, h - (2 * c->bw), 0); -+			if (my + HEIGHT(c) + m->gappx < m->wh) -+				my += HEIGHT(c) + m->gappx; -+		} else { -+			oy = i - m->nmaster; -+			ox = stairdirection ? n - i - 1 : (stairsamesize ? i - m->nmaster : 0); -+			ow = stairsamesize ? n - m->nmaster - 1 : n - i - 1; -+			oh = stairsamesize ? ow : i - m->nmaster; -+			resize(c, -+			       m->wx + mw + (ox * stairpx) + m->gappx, -+			       m->wy + (oy * stairpx) + m->gappx, -+			       m->ww - mw - (2 * c->bw) - (ow * stairpx) - (2 * m->gappx), -+			       m->wh - (2 * c->bw) - (oh * stairpx) - (2 * m->gappx), -+			       0); -+		} -+	} -+} -+ - void - tag(const Arg *arg) - { --- -2.36.0 diff --git a/applied/dwm-swallow-6.3.diff b/applied/dwm-swallow-6.3.diff new file mode 100644 index 0000000..47586a0 --- /dev/null +++ b/applied/dwm-swallow-6.3.diff @@ -0,0 +1,412 @@ +From 0cf9a007511f7dfd7dd94171b172562ebac9b6d5 Mon Sep 17 00:00:00 2001 +From: Tom Schwindl <schwindl@posteo.de> +Date: Sat, 10 Sep 2022 12:51:09 +0200 +Subject: [PATCH] 6.3 swallow patch + +--- + config.def.h |   9 +- + config.mk    |   3 +- + dwm.c        | 235 +++++++++++++++++++++++++++++++++++++++++++++++++-- + 3 files changed, 237 insertions(+), 10 deletions(-) + +diff --git a/config.def.h b/config.def.h +index 061ad662f82a..0b2b8ffd30d5 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -3,6 +3,7 @@ + /* appearance */ + static const unsigned int borderpx  = 1;        /* border pixel of windows */ + static const unsigned int snap      = 32;       /* snap pixel */ ++static const int swallowfloating    = 0;        /* 1 means swallow floating windows by default */ + static const int showbar            = 1;        /* 0 means no bar */ + static const int topbar             = 1;        /* 0 means bottom bar */ + static const char *fonts[]          = { "monospace:size=10" }; +@@ -26,9 +27,11 @@ static const Rule rules[] = { + 	 *	WM_CLASS(STRING) = instance, class + 	 *	WM_NAME(STRING) = title + 	 */ +-	/* class      instance    title       tags mask     isfloating   monitor */ +-	{ "Gimp",     NULL,       NULL,       0,            1,           -1 }, +-	{ "Firefox",  NULL,       NULL,       1 << 8,       0,           -1 }, ++	/* class     instance  title           tags mask  isfloating  isterminal  noswallow  monitor */ ++	{ "Gimp",    NULL,     NULL,           0,         1,          0,           0,        -1 }, ++	{ "Firefox", NULL,     NULL,           1 << 8,    0,          0,          -1,        -1 }, ++	{ "St",      NULL,     NULL,           0,         0,          1,           0,        -1 }, ++	{ NULL,      NULL,     "Event Tester", 0,         0,          0,           1,        -1 }, /* xev */ + }; +  + /* layout(s) */ +diff --git a/config.mk b/config.mk +index 81c493ef4aff..52d1ebf30bec 100644 +--- a/config.mk ++++ b/config.mk +@@ -20,10 +20,11 @@ FREETYPEINC = /usr/include/freetype2 + # OpenBSD (uncomment) + #FREETYPEINC = ${X11INC}/freetype2 + #MANPREFIX = ${PREFIX}/man ++#KVMLIB = -lkvm +  + # includes and libs + INCS = -I${X11INC} -I${FREETYPEINC} +-LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} ++LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} -lX11-xcb -lxcb -lxcb-res ${KVMLIB} +  + # flags + CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_POSIX_C_SOURCE=200809L -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS} +diff --git a/dwm.c b/dwm.c +index e5efb6a22806..e68294b6b679 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -40,6 +40,12 @@ + #include <X11/extensions/Xinerama.h> + #endif /* XINERAMA */ + #include <X11/Xft/Xft.h> ++#include <X11/Xlib-xcb.h> ++#include <xcb/res.h> ++#ifdef __OpenBSD__ ++#include <sys/sysctl.h> ++#include <kvm.h> ++#endif /* __OpenBSD */ +  + #include "drw.h" + #include "util.h" +@@ -92,9 +98,11 @@ struct Client { + 	int basew, baseh, incw, inch, maxw, maxh, minw, minh, hintsvalid; + 	int bw, oldbw; + 	unsigned int tags; +-	int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen; ++	int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen, isterminal, noswallow; ++	pid_t pid; + 	Client *next; + 	Client *snext; ++	Client *swallowing; + 	Monitor *mon; + 	Window win; + }; +@@ -138,6 +146,8 @@ typedef struct { + 	const char *title; + 	unsigned int tags; + 	int isfloating; ++	int isterminal; ++	int noswallow; + 	int monitor; + } Rule; +  +@@ -235,6 +245,12 @@ static int xerrordummy(Display *dpy, XErrorEvent *ee); + static int xerrorstart(Display *dpy, XErrorEvent *ee); + static void zoom(const Arg *arg); +  ++static pid_t getparentprocess(pid_t p); ++static int isdescprocess(pid_t p, pid_t c); ++static Client *swallowingclient(Window w); ++static Client *termforwin(const Client *c); ++static pid_t winpid(Window w); ++ + /* variables */ + static const char broken[] = "broken"; + static char stext[256]; +@@ -269,6 +285,8 @@ static Drw *drw; + static Monitor *mons, *selmon; + static Window root, wmcheckwin; +  ++static xcb_connection_t *xcon; ++ + /* configuration, allows nested code to access above variables */ + #include "config.h" +  +@@ -298,6 +316,8 @@ applyrules(Client *c) + 		&& (!r->class || strstr(class, r->class)) + 		&& (!r->instance || strstr(instance, r->instance))) + 		{ ++			c->isterminal = r->isterminal; ++			c->noswallow  = r->noswallow; + 			c->isfloating = r->isfloating; + 			c->tags |= r->tags; + 			for (m = mons; m && m->num != r->monitor; m = m->next); +@@ -416,6 +436,53 @@ attachstack(Client *c) + 	c->mon->stack = c; + } +  ++void ++swallow(Client *p, Client *c) ++{ ++ ++	if (c->noswallow || c->isterminal) ++		return; ++	if (c->noswallow && !swallowfloating && c->isfloating) ++		return; ++ ++	detach(c); ++	detachstack(c); ++ ++	setclientstate(c, WithdrawnState); ++	XUnmapWindow(dpy, p->win); ++ ++	p->swallowing = c; ++	c->mon = p->mon; ++ ++	Window w = p->win; ++	p->win = c->win; ++	c->win = w; ++	updatetitle(p); ++	XMoveResizeWindow(dpy, p->win, p->x, p->y, p->w, p->h); ++	arrange(p->mon); ++	configure(p); ++	updateclientlist(); ++} ++ ++void ++unswallow(Client *c) ++{ ++	c->win = c->swallowing->win; ++ ++	free(c->swallowing); ++	c->swallowing = NULL; ++ ++	/* unfullscreen the client */ ++	setfullscreen(c, 0); ++	updatetitle(c); ++	arrange(c->mon); ++	XMapWindow(dpy, c->win); ++	XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h); ++	setclientstate(c, NormalState); ++	focus(NULL); ++	arrange(c->mon); ++} ++ + void + buttonpress(XEvent *e) + { +@@ -656,6 +723,9 @@ destroynotify(XEvent *e) +  + 	if ((c = wintoclient(ev->window))) + 		unmanage(c, 1); ++ ++	else if ((c = swallowingclient(ev->window))) ++		unmanage(c->swallowing, 1); + } +  + void +@@ -1022,12 +1092,13 @@ killclient(const Arg *arg) + void + manage(Window w, XWindowAttributes *wa) + { +-	Client *c, *t = NULL; ++	Client *c, *t = NULL, *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; +@@ -1042,6 +1113,7 @@ manage(Window w, XWindowAttributes *wa) + 	} else { + 		c->mon = selmon; + 		applyrules(c); ++		term = termforwin(c); + 	} +  + 	if (c->x + WIDTH(c) > c->mon->wx + c->mon->ww) +@@ -1076,6 +1148,8 @@ manage(Window w, XWindowAttributes *wa) + 	c->mon->sel = c; + 	arrange(c->mon); + 	XMapWindow(dpy, c->win); ++	if (term) ++		swallow(term, c); + 	focus(NULL); + } +  +@@ -1763,6 +1837,20 @@ 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) { +@@ -1778,9 +1866,12 @@ unmanage(Client *c, int destroyed) + 		XUngrabServer(dpy); + 	} + 	free(c); +-	focus(NULL); +-	updateclientlist(); +-	arrange(m); ++ ++	if (!s) { ++		arrange(m); ++		focus(NULL); ++		updateclientlist(); ++	} + } +  + void +@@ -2044,6 +2135,136 @@ view(const Arg *arg) + 	arrange(selmon); + } +  ++pid_t ++winpid(Window w) ++{ ++ ++	pid_t result = 0; ++ ++#ifdef __linux__ ++	xcb_res_client_id_spec_t spec = {0}; ++	spec.client = w; ++	spec.mask = XCB_RES_CLIENT_ID_MASK_LOCAL_CLIENT_PID; ++ ++	xcb_generic_error_t *e = NULL; ++	xcb_res_query_client_ids_cookie_t c = xcb_res_query_client_ids(xcon, 1, &spec); ++	xcb_res_query_client_ids_reply_t *r = xcb_res_query_client_ids_reply(xcon, c, &e); ++ ++	if (!r) ++		return (pid_t)0; ++ ++	xcb_res_client_id_value_iterator_t i = xcb_res_query_client_ids_ids_iterator(r); ++	for (; i.rem; xcb_res_client_id_value_next(&i)) { ++		spec = i.data->spec; ++		if (spec.mask & XCB_RES_CLIENT_ID_MASK_LOCAL_CLIENT_PID) { ++			uint32_t *t = xcb_res_client_id_value_value(i.data); ++			result = *t; ++			break; ++		} ++	} ++ ++	free(r); ++ ++	if (result == (pid_t)-1) ++		result = 0; ++ ++#endif /* __linux__ */ ++ ++#ifdef __OpenBSD__ ++        Atom type; ++        int format; ++        unsigned long len, bytes; ++        unsigned char *prop; ++        pid_t ret; ++ ++        if (XGetWindowProperty(dpy, w, XInternAtom(dpy, "_NET_WM_PID", 0), 0, 1, False, AnyPropertyType, &type, &format, &len, &bytes, &prop) != Success || !prop) ++               return 0; ++ ++        ret = *(pid_t*)prop; ++        XFree(prop); ++        result = ret; ++ ++#endif /* __OpenBSD__ */ ++	return result; ++} ++ ++pid_t ++getparentprocess(pid_t p) ++{ ++	unsigned int v = 0; ++ ++#ifdef __linux__ ++	FILE *f; ++	char buf[256]; ++	snprintf(buf, sizeof(buf) - 1, "/proc/%u/stat", (unsigned)p); ++ ++	if (!(f = fopen(buf, "r"))) ++		return 0; ++ ++	fscanf(f, "%*u %*s %*c %u", &v); ++	fclose(f); ++#endif /* __linux__*/ ++ ++#ifdef __OpenBSD__ ++	int n; ++	kvm_t *kd; ++	struct kinfo_proc *kp; ++ ++	kd = kvm_openfiles(NULL, NULL, NULL, KVM_NO_FILES, NULL); ++	if (!kd) ++		return 0; ++ ++	kp = kvm_getprocs(kd, KERN_PROC_PID, p, sizeof(*kp), &n); ++	v = kp->p_ppid; ++#endif /* __OpenBSD__ */ ++ ++	return (pid_t)v; ++} ++ ++int ++isdescprocess(pid_t p, pid_t c) ++{ ++	while (p != c && c != 0) ++		c = getparentprocess(c); ++ ++	return (int)c; ++} ++ ++Client * ++termforwin(const Client *w) ++{ ++	Client *c; ++	Monitor *m; ++ ++	if (!w->pid || w->isterminal) ++		return NULL; ++ ++	for (m = mons; m; m = m->next) { ++		for (c = m->clients; c; c = c->next) { ++			if (c->isterminal && !c->swallowing && c->pid && isdescprocess(c->pid, w->pid)) ++				return c; ++		} ++	} ++ ++	return NULL; ++} ++ ++Client * ++swallowingclient(Window w) ++{ ++	Client *c; ++	Monitor *m; ++ ++	for (m = mons; m; m = m->next) { ++		for (c = m->clients; c; c = c->next) { ++			if (c->swallowing && c->swallowing->win == w) ++				return c; ++		} ++	} ++ ++	return NULL; ++} ++ + Client * + wintoclient(Window w) + { +@@ -2133,10 +2354,12 @@ main(int argc, char *argv[]) + 		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(); + 	setup(); + #ifdef __OpenBSD__ +-	if (pledge("stdio rpath proc exec", NULL) == -1) ++	if (pledge("stdio rpath proc exec ps", NULL) == -1) + 		die("pledge"); + #endif /* __OpenBSD__ */ + 	scan(); +--  +2.37.2 + diff --git a/applied/dwm-switchtotag-6.2.diff b/applied/dwm-switchtotag-6.2.diff deleted file mode 100644 index 453f8ef..0000000 --- a/applied/dwm-switchtotag-6.2.diff +++ /dev/null @@ -1,58 +0,0 @@ -diff -up dwm-6.2-original/config.def.h dwm-6.2-modified/config.def.h ---- dwm-6.2-original/config.def.h	2019-02-02 14:55:28.000000000 +0200 -+++ dwm-6.2-modified/config.def.h	2019-11-18 19:36:22.515566509 +0200 -@@ -26,9 +26,9 @@ static const Rule rules[] = { - 	 *	WM_CLASS(STRING) = instance, class - 	 *	WM_NAME(STRING) = title - 	 */ --	/* class      instance    title       tags mask     isfloating   monitor */ --	{ "Gimp",     NULL,       NULL,       0,            1,           -1 }, --	{ "Firefox",  NULL,       NULL,       1 << 8,       0,           -1 }, -+	/* class      instance    title       tags mask     switchtotag    isfloating   monitor */ -+	{ "Gimp",     NULL,       NULL,       0,            0,             1,           -1 }, -+	{ "Firefox",  NULL,       NULL,       1 << 8,       0,             0,           -1 }, - }; -  - /* layout(s) */ -diff -up dwm-6.2-original/dwm.c dwm-6.2-modified/dwm.c ---- dwm-6.2-original/dwm.c	2019-02-02 14:55:28.000000000 +0200 -+++ dwm-6.2-modified/dwm.c	2019-11-18 19:37:18.792187705 +0200 -@@ -92,6 +92,7 @@ struct Client { - 	int basew, baseh, incw, inch, maxw, maxh, minw, minh; - 	int bw, oldbw; - 	unsigned int tags; -+	unsigned int switchtotag; - 	int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen; - 	Client *next; - 	Client *snext; -@@ -137,6 +138,7 @@ typedef struct { - 	const char *instance; - 	const char *title; - 	unsigned int tags; -+	unsigned int switchtotag; - 	int isfloating; - 	int monitor; - } Rule; -@@ -302,6 +304,11 @@ applyrules(Client *c) - 			for (m = mons; m && m->num != r->monitor; m = m->next); - 			if (m) - 				c->mon = m; -+			if (r->switchtotag) { -+				Arg a = { .ui = r->tags }; -+				c->switchtotag = selmon->tagset[selmon->seltags]; -+				view(&a); -+			} - 		} - 	} - 	if (ch.res_class) -@@ -1782,6 +1789,10 @@ unmanage(Client *c, int destroyed) - 	focus(NULL); - 	updateclientlist(); - 	arrange(m); -+	if (c->switchtotag) { -+		Arg a = { .ui = c->switchtotag }; -+		view(&a); -+	} - } -  - void diff --git a/applied/dwm-systray-6.4.diff b/applied/dwm-systray-20230922-9f88553.diff index 58e4a69..9356ec1 100644 --- a/applied/dwm-systray-6.4.diff +++ b/applied/dwm-systray-20230922-9f88553.diff @@ -1,5 +1,5 @@  diff --git a/config.def.h b/config.def.h -index 9efa774..750529d 100644 +index 9efa774..fed4fb9 100644  --- a/config.def.h  +++ b/config.def.h  @@ -3,6 +3,11 @@ @@ -14,19 +14,8 @@ index 9efa774..750529d 100644   static const int showbar            = 1;        /* 0 means no bar */   static const int topbar             = 1;        /* 0 means bottom bar */   static const char *fonts[]          = { "monospace:size=10" }; -@@ -101,8 +106,8 @@ static const Key keys[] = { - /* click can be ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, or ClkRootWin */ - static const Button buttons[] = { - 	/* click                event mask      button          function        argument */ --	{ ClkLtSymbol,          0,              Button1,        setlayout,      {0} }, --	{ ClkLtSymbol,          0,              Button3,        setlayout,      {.v = &layouts[2]} }, -+	{ ClkTagBar,            MODKEY,         Button1,        tag,            {0} }, -+	{ ClkTagBar,            MODKEY,         Button3,        toggletag,      {0} }, - 	{ ClkWinTitle,          0,              Button2,        zoom,           {0} }, - 	{ ClkStatusText,        0,              Button2,        spawn,          {.v = termcmd } }, - 	{ ClkClientWin,         MODKEY,         Button1,        movemouse,      {0} },  diff --git a/dwm.c b/dwm.c -index 03baf42..4611a03 100644 +index f1d86b2..f9e7e4a 100644  --- a/dwm.c  +++ b/dwm.c  @@ -57,12 +57,27 @@ @@ -96,15 +85,15 @@ index 03baf42..4611a03 100644   static void sendmon(Client *c, Monitor *m);   static void setclientstate(Client *c, long state);   static void setfocus(Client *c); -@@ -207,6 +232,7 @@ static void seturgent(Client *c, int urg); +@@ -206,6 +231,7 @@ 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 Monitor *systraytomon(Monitor *m);   static void tag(const Arg *arg);   static void tagmon(const Arg *arg);   static void tile(Monitor *m); -@@ -224,18 +250,23 @@ static int updategeom(void); +@@ -223,18 +249,23 @@ static int updategeom(void);   static void updatenumlockmask(void);   static void updatesizehints(Client *c);   static void updatestatus(void); @@ -128,7 +117,7 @@ index 03baf42..4611a03 100644   static const char broken[] = "broken";   static char stext[256];   static int screen; -@@ -258,9 +289,10 @@ static void (*handler[LASTEvent]) (XEvent *) = { +@@ -257,9 +288,10 @@ static void (*handler[LASTEvent]) (XEvent *) = {   	[MapRequest] = maprequest,   	[MotionNotify] = motionnotify,   	[PropertyNotify] = propertynotify, @@ -140,7 +129,7 @@ index 03baf42..4611a03 100644   static int running = 1;   static Cur *cursor[CurLast];   static Clr **scheme; -@@ -442,7 +474,7 @@ buttonpress(XEvent *e) +@@ -441,7 +473,7 @@ buttonpress(XEvent *e)   			arg.ui = 1 << i;   		} else if (ev->x < x + TEXTW(selmon->ltsymbol))   			click = ClkLtSymbol; @@ -149,7 +138,7 @@ index 03baf42..4611a03 100644   			click = ClkStatusText;   		else   			click = ClkWinTitle; -@@ -485,6 +517,13 @@ cleanup(void) +@@ -484,6 +516,13 @@ cleanup(void)   	XUngrabKey(dpy, AnyKey, AnyModifier, root);   	while (mons)   		cleanupmon(mons); @@ -163,7 +152,7 @@ index 03baf42..4611a03 100644   	for (i = 0; i < CurLast; i++)   		drw_cur_free(drw, cursor[i]);   	for (i = 0; i < LENGTH(colors); i++) -@@ -516,9 +555,58 @@ cleanupmon(Monitor *mon) +@@ -515,9 +554,58 @@ cleanupmon(Monitor *mon)   void   clientmessage(XEvent *e)   { @@ -222,7 +211,7 @@ index 03baf42..4611a03 100644   	if (!c)   		return;   	if (cme->message_type == netatom[NetWMState]) { -@@ -571,7 +659,7 @@ configurenotify(XEvent *e) +@@ -570,7 +658,7 @@ configurenotify(XEvent *e)   				for (c = m->clients; c; c = c->next)   					if (c->isfullscreen)   						resizeclient(c, m->mx, m->my, m->mw, m->mh); @@ -231,7 +220,7 @@ index 03baf42..4611a03 100644   			}   			focus(NULL);   			arrange(NULL); -@@ -656,6 +744,11 @@ destroynotify(XEvent *e) +@@ -655,6 +743,11 @@ destroynotify(XEvent *e)   	if ((c = wintoclient(ev->window)))   		unmanage(c, 1); @@ -243,7 +232,7 @@ index 03baf42..4611a03 100644   }   void -@@ -699,7 +792,7 @@ dirtomon(int dir) +@@ -698,7 +791,7 @@ dirtomon(int dir)   void   drawbar(Monitor *m)   { @@ -252,7 +241,7 @@ index 03baf42..4611a03 100644   	int boxs = drw->fonts->h / 9;   	int boxw = drw->fonts->h / 6 + 2;   	unsigned int i, occ = 0, urg = 0; -@@ -708,13 +801,17 @@ drawbar(Monitor *m) +@@ -707,13 +800,17 @@ drawbar(Monitor *m)   	if (!m->showbar)   		return; @@ -272,7 +261,7 @@ index 03baf42..4611a03 100644   	for (c = m->clients; c; c = c->next) {   		occ |= c->tags;   		if (c->isurgent) -@@ -735,7 +832,7 @@ drawbar(Monitor *m) +@@ -734,7 +831,7 @@ drawbar(Monitor *m)   	drw_setscheme(drw, scheme[SchemeNorm]);   	x = drw_text(drw, x, 0, w, bh, lrpad / 2, m->ltsymbol, 0); @@ -281,7 +270,7 @@ index 03baf42..4611a03 100644   		if (m->sel) {   			drw_setscheme(drw, scheme[m == selmon ? SchemeSel : SchemeNorm]);   			drw_text(drw, x, 0, w, bh, lrpad / 2, m->sel->name, 0); -@@ -746,7 +843,7 @@ drawbar(Monitor *m) +@@ -745,7 +842,7 @@ drawbar(Monitor *m)   			drw_rect(drw, x, 0, w, bh, 1, 1);   		}   	} @@ -290,7 +279,7 @@ index 03baf42..4611a03 100644   }   void -@@ -783,8 +880,11 @@ expose(XEvent *e) +@@ -782,8 +879,11 @@ expose(XEvent *e)   	Monitor *m;   	XExposeEvent *ev = &e->xexpose; @@ -303,7 +292,7 @@ index 03baf42..4611a03 100644   }   void -@@ -870,14 +970,32 @@ getatomprop(Client *c, Atom prop) +@@ -869,14 +969,32 @@ getatomprop(Client *c, Atom prop)   	unsigned char *p = NULL;   	Atom da, atom = None; @@ -337,7 +326,7 @@ index 03baf42..4611a03 100644   int   getrootptr(int *x, int *y)   { -@@ -1018,7 +1136,8 @@ killclient(const Arg *arg) +@@ -1017,7 +1135,8 @@ killclient(const Arg *arg)   {   	if (!selmon->sel)   		return; @@ -347,7 +336,7 @@ index 03baf42..4611a03 100644   		XGrabServer(dpy);   		XSetErrorHandler(xerrordummy);   		XSetCloseDownMode(dpy, DestroyAll); -@@ -1105,6 +1224,13 @@ maprequest(XEvent *e) +@@ -1104,6 +1223,13 @@ maprequest(XEvent *e)   	static XWindowAttributes wa;   	XMapRequestEvent *ev = &e->xmaprequest; @@ -361,7 +350,7 @@ index 03baf42..4611a03 100644   	if (!XGetWindowAttributes(dpy, ev->window, &wa) || wa.override_redirect)   		return;   	if (!wintoclient(ev->window)) -@@ -1226,6 +1352,17 @@ propertynotify(XEvent *e) +@@ -1225,6 +1351,17 @@ propertynotify(XEvent *e)   	Window trans;   	XPropertyEvent *ev = &e->xproperty; @@ -379,7 +368,7 @@ index 03baf42..4611a03 100644   	if ((ev->window == root) && (ev->atom == XA_WM_NAME))   		updatestatus();   	else if (ev->state == PropertyDelete) -@@ -1276,6 +1413,19 @@ recttomon(int x, int y, int w, int h) +@@ -1275,6 +1412,19 @@ recttomon(int x, int y, int w, int h)   	return r;   } @@ -399,7 +388,7 @@ index 03baf42..4611a03 100644   void   resize(Client *c, int x, int y, int w, int h, int interact)   { -@@ -1283,6 +1433,14 @@ resize(Client *c, int x, int y, int w, int h, int interact) +@@ -1282,6 +1432,14 @@ resize(Client *c, int x, int y, int w, int h, int interact)   		resizeclient(c, x, y, w, h);   } @@ -414,7 +403,7 @@ index 03baf42..4611a03 100644   void   resizeclient(Client *c, int x, int y, int w, int h)   { -@@ -1298,6 +1456,19 @@ resizeclient(Client *c, int x, int y, int w, int h) +@@ -1297,6 +1455,19 @@ resizeclient(Client *c, int x, int y, int w, int h)   	XSync(dpy, False);   } @@ -434,7 +423,7 @@ index 03baf42..4611a03 100644   void   resizemouse(const Arg *arg)   { -@@ -1444,26 +1615,37 @@ setclientstate(Client *c, long state) +@@ -1443,26 +1614,37 @@ setclientstate(Client *c, long state)   }   int @@ -483,7 +472,7 @@ index 03baf42..4611a03 100644   	}   	return exists;   } -@@ -1477,7 +1659,7 @@ setfocus(Client *c) +@@ -1476,7 +1658,7 @@ setfocus(Client *c)   			XA_WINDOW, 32, PropModeReplace,   			(unsigned char *) &(c->win), 1);   	} @@ -492,7 +481,7 @@ index 03baf42..4611a03 100644   }   void -@@ -1566,6 +1748,10 @@ setup(void) +@@ -1572,6 +1754,10 @@ setup(void)   	wmatom[WMTakeFocus] = XInternAtom(dpy, "WM_TAKE_FOCUS", False);   	netatom[NetActiveWindow] = XInternAtom(dpy, "_NET_ACTIVE_WINDOW", False);   	netatom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False); @@ -503,7 +492,7 @@ index 03baf42..4611a03 100644   	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); -@@ -1573,6 +1759,9 @@ setup(void) +@@ -1579,6 +1765,9 @@ setup(void)   	netatom[NetWMWindowType] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE", False);   	netatom[NetWMWindowTypeDialog] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DIALOG", False);   	netatom[NetClientList] = XInternAtom(dpy, "_NET_CLIENT_LIST", False); @@ -513,7 +502,7 @@ index 03baf42..4611a03 100644   	/* init cursors */   	cursor[CurNormal] = drw_cur_create(drw, XC_left_ptr);   	cursor[CurResize] = drw_cur_create(drw, XC_sizing); -@@ -1581,6 +1770,8 @@ setup(void) +@@ -1587,6 +1776,8 @@ setup(void)   	scheme = ecalloc(LENGTH(colors), sizeof(Clr *));   	for (i = 0; i < LENGTH(colors); i++)   		scheme[i] = drw_scm_create(drw, colors[i], 3); @@ -522,7 +511,7 @@ index 03baf42..4611a03 100644   	/* init bars */   	updatebars();   	updatestatus(); -@@ -1711,7 +1902,18 @@ togglebar(const Arg *arg) +@@ -1717,7 +1908,18 @@ togglebar(const Arg *arg)   {   	selmon->showbar = !selmon->showbar;   	updatebarpos(selmon); @@ -542,7 +531,7 @@ index 03baf42..4611a03 100644   	arrange(selmon);   } -@@ -1807,11 +2009,18 @@ unmapnotify(XEvent *e) +@@ -1813,11 +2015,18 @@ unmapnotify(XEvent *e)   		else   			unmanage(c, 0);   	} @@ -561,7 +550,7 @@ index 03baf42..4611a03 100644   	Monitor *m;   	XSetWindowAttributes wa = {   		.override_redirect = True, -@@ -1822,10 +2031,15 @@ updatebars(void) +@@ -1828,10 +2037,15 @@ updatebars(void)   	for (m = mons; m; m = m->next) {   		if (m->barwin)   			continue; @@ -578,7 +567,7 @@ index 03baf42..4611a03 100644   		XMapRaised(dpy, m->barwin);   		XSetClassHint(dpy, m->barwin, &ch);   	} -@@ -2002,6 +2216,125 @@ updatestatus(void) +@@ -2008,6 +2222,125 @@ updatestatus(void)   	if (!gettextprop(root, XA_WM_NAME, stext, sizeof(stext)))   		strcpy(stext, "dwm-"VERSION);   	drawbar(selmon); @@ -704,7 +693,7 @@ index 03baf42..4611a03 100644   }   void -@@ -2069,6 +2402,16 @@ wintoclient(Window w) +@@ -2075,6 +2408,16 @@ wintoclient(Window w)   	return NULL;   } @@ -721,7 +710,7 @@ index 03baf42..4611a03 100644   Monitor *   wintomon(Window w)   { -@@ -2122,6 +2465,22 @@ xerrorstart(Display *dpy, XErrorEvent *ee) +@@ -2128,6 +2471,22 @@ xerrorstart(Display *dpy, XErrorEvent *ee)   	return -1;   } diff --git a/cancelled/dwm-6.2-tagintostack-onemaster.diff b/cancelled/dwm-6.2-tagintostack-onemaster.diff deleted file mode 100644 index 18fa42b..0000000 --- a/cancelled/dwm-6.2-tagintostack-onemaster.diff +++ /dev/null @@ -1,34 +0,0 @@ -From 43fb204a53e3f1bee47f51a2f4e52e5bf242e314 Mon Sep 17 00:00:00 2001 -From: astier <aleksandrs.stier@uni-bielefeld.de> -Date: Tue, 26 Feb 2019 01:04:55 +0100 -Subject: [PATCH] Attach clients from toggled tag into stack instead of master area - -New clients attach into the stack area when you toggle a new tag into -view. This means your master area will remain unchanged when toggling -views. ---- - dwm.c | 9 +++++++++ - 1 file changed, 9 insertions(+) - -diff --git a/dwm.c b/dwm.c -index 4465af1..567fa8b 100644 ---- a/dwm.c -+++ b/dwm.c -@@ -1739,6 +1739,15 @@ toggleview(const Arg *arg) - { - 	unsigned int newtagset = selmon->tagset[selmon->seltags] ^ (arg->ui & TAGMASK); -  -+	// the first visible client should be the same after we add a new tag -+	// we also want to be sure not to mutate the focus -+	Client *const c = nexttiled(selmon->clients); -+	if (c) { -+		Client * const selected = selmon->sel; -+		pop(c); -+		focus(selected); -+	} -+ - 	if (newtagset) { - 		selmon->tagset[selmon->seltags] = newtagset; - 		focus(NULL); ---  -2.20.1 diff --git a/cancelled/dwm-bartabgroups-20210802-138b405.diff b/cancelled/dwm-bartabgroups-20210802-138b405.diff deleted file mode 100644 index fc275f3..0000000 --- a/cancelled/dwm-bartabgroups-20210802-138b405.diff +++ /dev/null @@ -1,187 +0,0 @@ -From 653c99b94cc780a2def9c7e50a87703156535f8b Mon Sep 17 00:00:00 2001 -From: Jack Bird <jack.bird@durham.ac.uk> -Date: Mon, 2 Aug 2021 18:50:02 +0100 -Subject: [PATCH] bartabgroups updated to work with 138b405 - ---- - config.def.h |  11 +++++ - dwm.c        | 112 ++++++++++++++++++++++++++++++++++++++++++++++----- - 2 files changed, 112 insertions(+), 11 deletions(-) - -diff --git a/config.def.h b/config.def.h -index a2ac963..82accf1 100644 ---- a/config.def.h -+++ b/config.def.h -@@ -16,6 +16,8 @@ static const char *colors[][3]      = { - 	/*               fg         bg         border   */ - 	[SchemeNorm] = { col_gray3, col_gray1, col_gray2 }, - 	[SchemeSel]  = { col_gray4, col_cyan,  col_cyan  }, -+	[SchemeTabActive]  = { col_gray2, col_gray3,  col_gray2 }, -+	[SchemeTabInactive]  = { col_gray1, col_gray3,  col_gray1 } - }; -  - /* tagging */ -@@ -37,6 +39,15 @@ static const int nmaster     = 1;    /* number of clients in master area */ - static const int resizehints = 1;    /* 1 means respect size hints in tiled resizals */ - static const int lockfullscreen = 1; /* 1 will force focus on the fullscreen window */ -  -+/* Bartabgroups properties */ -+#define BARTAB_BORDERS 1       // 0 = off, 1 = on -+#define BARTAB_BOTTOMBORDER 1  // 0 = off, 1 = on -+#define BARTAB_TAGSINDICATOR 1 // 0 = off, 1 = on if >1 client/view tag, 2 = always on -+#define BARTAB_TAGSPX 5        // # pixels for tag grid boxes -+#define BARTAB_TAGSROWS 3      // # rows in tag grid (9 tags, e.g. 3x3) -+static void (*bartabmonfns[])(Monitor *) = { monocle /* , customlayoutfn */ }; -+static void (*bartabfloatfns[])(Monitor *) = { NULL /* , customlayoutfn */ }; -+ - static const Layout layouts[] = { - 	/* symbol     arrange function */ - 	{ "[]=",      tile },    /* first entry is default */ -diff --git a/dwm.c b/dwm.c -index 5e4d494..1839a56 100644 ---- a/dwm.c -+++ b/dwm.c -@@ -59,7 +59,7 @@ -  - /* enums */ - enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */ --enum { SchemeNorm, SchemeSel }; /* color schemes */ -+enum { SchemeNorm, SchemeSel, SchemeTabActive, SchemeTabInactive }; /* color schemes */ - enum { NetSupported, NetWMName, NetWMState, NetWMCheck, -        NetWMFullscreen, NetActiveWindow, NetWMWindowType, -        NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH atoms */ -@@ -378,6 +378,98 @@ applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact) - 	return *x != c->x || *y != c->y || *w != c->w || *h != c->h; - } -  -+void -+bartabdraw(Monitor *m, Client *c, int unused, int x, int w, int groupactive) { -+	if (!c) return; -+	int i, nclienttags = 0, nviewtags = 0; -+ -+	drw_setscheme(drw, scheme[ -+		m->sel == c ? SchemeSel : (groupactive ? SchemeTabActive: SchemeTabInactive) -+	]); -+	drw_text(drw, x, 0, w, bh, lrpad / 2, c->name, 0); -+ -+	// Floating win indicator -+	if (c->isfloating) drw_rect(drw, x + 2, 2, 5, 5, 0, 0); -+ -+	// Optional borders between tabs -+	if (BARTAB_BORDERS) { -+		XSetForeground(drw->dpy, drw->gc, drw->scheme[ColBorder].pixel); -+		XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, 0, 1, bh); -+		XFillRectangle(drw->dpy, drw->drawable, drw->gc, x + w, 0, 1, bh); -+	} -+ -+	// Optional tags icons -+	for (i = 0; i < LENGTH(tags); i++) { -+		if ((m->tagset[m->seltags] >> i) & 1) { nviewtags++; } -+		if ((c->tags >> i) & 1) { nclienttags++; } -+	} -+	if (BARTAB_TAGSINDICATOR == 2 || nclienttags > 1 || nviewtags > 1) { -+		for (i = 0; i < LENGTH(tags); i++) { -+			drw_rect(drw, -+				( x + w - 2 - ((LENGTH(tags) / BARTAB_TAGSROWS) * BARTAB_TAGSPX) -+					- (i % (LENGTH(tags)/BARTAB_TAGSROWS)) + ((i % (LENGTH(tags) / BARTAB_TAGSROWS)) * BARTAB_TAGSPX) -+				), -+				( 2 + ((i / (LENGTH(tags)/BARTAB_TAGSROWS)) * BARTAB_TAGSPX) -+					- ((i / (LENGTH(tags)/BARTAB_TAGSROWS))) -+				), -+				BARTAB_TAGSPX, BARTAB_TAGSPX, (c->tags >> i) & 1, 0 -+			); -+		} -+	} -+} -+ -+void -+battabclick(Monitor *m, Client *c, int passx, int x, int w, int unused) { -+	if (passx >= x && passx <= x + w) { -+		focus(c); -+		restack(selmon); -+	} -+} -+ -+void -+bartabcalculate( -+	Monitor *m, int offx, int sw, int passx, -+	void(*tabfn)(Monitor *, Client *, int, int, int, int) -+) { -+	Client *c; -+	int -+		i, clientsnmaster = 0, clientsnstack = 0, clientsnfloating = 0, -+		masteractive = 0, fulllayout = 0, floatlayout = 0, -+		x, w, tgactive; -+ -+	for (i = 0, c = m->clients; c; c = c->next) { -+		if (!ISVISIBLE(c)) continue; -+		if (c->isfloating) { clientsnfloating++; continue; } -+		if (m->sel == c) { masteractive = i < m->nmaster; } -+		if (i < m->nmaster) { clientsnmaster++; } else { clientsnstack++; } -+		i++; -+	} -+	for (i = 0; i < LENGTH(bartabfloatfns); i++) if (m ->lt[m->sellt]->arrange == bartabfloatfns[i]) { floatlayout = 1; break; } -+	for (i = 0; i < LENGTH(bartabmonfns); i++) if (m ->lt[m->sellt]->arrange == bartabmonfns[i]) { fulllayout = 1; break; } -+	for (c = m->clients, i = 0; c; c = c->next) { -+		if (!ISVISIBLE(c)) continue; -+		if (clientsnmaster + clientsnstack == 0 || floatlayout) { -+			 x = offx + (((m->mw - offx - sw) / (clientsnmaster + clientsnstack + clientsnfloating)) * i); -+			 w = (m->mw - offx - sw) / (clientsnmaster + clientsnstack + clientsnfloating); -+			 tgactive = 1; -+		} else if (!c->isfloating && (fulllayout || ((clientsnmaster == 0) ^ (clientsnstack == 0)))) { -+			 x = offx + (((m->mw - offx - sw) / (clientsnmaster + clientsnstack)) * i); -+			 w = (m->mw - offx - sw) / (clientsnmaster + clientsnstack); -+			 tgactive = 1; -+		} else if (i < m->nmaster && !c->isfloating) { -+			 x = offx + ((((m->mw * m->mfact) - offx) /clientsnmaster) * i); -+			 w = ((m->mw * m->mfact) - offx) / clientsnmaster; -+			 tgactive = masteractive; -+		} else if (!c->isfloating) { -+			 x = (m->mw * m->mfact) + ((((m->mw * (1 - m->mfact)) - sw) / clientsnstack) * (i - m->nmaster)); -+			 w = ((m->mw * (1 - m->mfact)) - sw) / clientsnstack; -+			 tgactive = !masteractive; -+		} else continue; -+		tabfn(m, c, passx, x, w, tgactive); -+		i++; -+	} -+} -+ - void - arrange(Monitor *m) - { -@@ -442,8 +534,8 @@ buttonpress(XEvent *e) - 			click = ClkLtSymbol; - 		else if (ev->x > selmon->ww - (int)TEXTW(stext)) - 			click = ClkStatusText; --		else --			click = ClkWinTitle; -+		else // Focus clicked tab bar item -+			bartabcalculate(selmon, x, TEXTW(stext) - lrpad + 2, ev->x, battabclick); - 	} else if ((c = wintoclient(ev->window))) { - 		focus(c); - 		restack(selmon); -@@ -729,15 +821,13 @@ drawbar(Monitor *m) - 	drw_setscheme(drw, scheme[SchemeNorm]); - 	x = drw_text(drw, x, 0, w, bh, lrpad / 2, m->ltsymbol, 0); -  -+	// Draw bartabgroups -+	drw_rect(drw, x, 0, m->ww - tw - x, bh, 1, 1); - 	if ((w = m->ww - tw - x) > bh) { --		if (m->sel) { --			drw_setscheme(drw, scheme[m == selmon ? SchemeSel : SchemeNorm]); --			drw_text(drw, x, 0, w, bh, lrpad / 2, m->sel->name, 0); --			if (m->sel->isfloating) --				drw_rect(drw, x + boxs, boxs, boxw, boxw, m->sel->isfixed, 0); --		} else { --			drw_setscheme(drw, scheme[SchemeNorm]); --			drw_rect(drw, x, 0, w, bh, 1, 1); -+		bartabcalculate(m, x, tw, -1, bartabdraw); -+		if (BARTAB_BOTTOMBORDER) { -+			drw_setscheme(drw, scheme[SchemeTabActive]); -+			drw_rect(drw, 0, bh - 1, m->ww, 1, 1, 0); - 		} - 	} - 	drw_map(drw, m->barwin, 0, 0, m->ww, bh); ---  -2.32.0 - diff --git a/cancelled/dwm-noborder-6.2.diff b/cancelled/dwm-noborder-6.2.diff deleted file mode 100644 index f381eb8..0000000 --- a/cancelled/dwm-noborder-6.2.diff +++ /dev/null @@ -1,30 +0,0 @@ -From 9102fdb9c670218373bbe83c891c8e8138d6a6f4 Mon Sep 17 00:00:00 2001 -From: redacted <redacted@example.com> -Date: Tue, 23 Apr 2019 00:39:27 +0100 -Subject: [PATCH] added noborder patch - ---- - dwm.c | 7 +++++++ - 1 file changed, 7 insertions(+) - -diff --git a/dwm.c b/dwm.c -index 4465af1..685eca1 100644 ---- a/dwm.c -+++ b/dwm.c -@@ -1282,6 +1282,13 @@ resizeclient(Client *c, int x, int y, int w, int h) - 	c->oldw = c->w; c->w = wc.width = w; - 	c->oldh = c->h; c->h = wc.height = h; - 	wc.border_width = c->bw; -+	if (((nexttiled(c->mon->clients) == c && !nexttiled(c->next)) -+	    || &monocle == c->mon->lt[c->mon->sellt]->arrange) -+	    && !c->isfullscreen && !c->isfloating) { -+		c->w = wc.width += c->bw * 2; -+		c->h = wc.height += c->bw * 2; -+		wc.border_width = 0; -+	} - 	XConfigureWindow(dpy, c->win, CWX|CWY|CWWidth|CWHeight|CWBorderWidth, &wc); - 	configure(c); - 	XSync(dpy, False); ---  -2.21.0 - diff --git a/cancelled/dwm-showselmon-6.2.diff b/cancelled/dwm-showselmon-6.2.diff deleted file mode 100644 index bbf837e..0000000 --- a/cancelled/dwm-showselmon-6.2.diff +++ /dev/null @@ -1,46 +0,0 @@ -diff -up a/config.def.h b/config.def.h ---- a/config.def.h	2020-07-04 13:56:23.316739958 +0200 -+++ b/config.def.h	2020-07-04 13:57:58.020554340 +0200 -@@ -15,6 +15,7 @@ static const char col_cyan[]        = "# - static const char *colors[][3]      = { - 	/*               fg         bg         border   */ - 	[SchemeNorm] = { col_gray3, col_gray1, col_gray2 }, -+	[SchemeInv]  = { col_gray1, col_gray3, col_gray2 }, - 	[SchemeSel]  = { col_gray4, col_cyan,  col_cyan  }, - }; -  -diff -up a/dwm.c b/dwm.c ---- a/dwm.c	2020-07-04 13:56:23.316739958 +0200 -+++ b/dwm.c	2020-07-04 14:14:54.124590755 +0200 -@@ -59,7 +59,7 @@ -  - /* enums */ - enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */ --enum { SchemeNorm, SchemeSel }; /* color schemes */ -+enum { SchemeNorm, SchemeInv, SchemeSel }; /* color schemes */ - enum { NetSupported, NetWMName, NetWMState, NetWMCheck, -        NetWMFullscreen, NetActiveWindow, NetWMWindowType, -        NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH atoms */ -@@ -716,7 +716,12 @@ drawbar(Monitor *m) - 	x = 0; - 	for (i = 0; i < LENGTH(tags); i++) { - 		w = TEXTW(tags[i]); --		drw_setscheme(drw, scheme[m->tagset[m->seltags] & 1 << i ? SchemeSel : SchemeNorm]); -+		if (m == selmon) { -+			drw_setscheme(drw, scheme[m->tagset[m->seltags] & 1 << i ? SchemeSel : SchemeNorm]); -+		} -+		else { -+			drw_setscheme(drw, scheme[m->tagset[m->seltags] & 1 << i ? SchemeInv : SchemeNorm]); -+		} - 		drw_text(drw, x, 0, w, bh, lrpad / 2, tags[i], urg & 1 << i); - 		if (occ & 1 << i) - 			drw_rect(drw, x + boxs, boxs, boxw, boxw, -@@ -730,7 +735,7 @@ drawbar(Monitor *m) -  - 	if ((w = m->ww - sw - x) > bh) { - 		if (m->sel) { --			drw_setscheme(drw, scheme[m == selmon ? SchemeSel : SchemeNorm]); -+			drw_setscheme(drw, scheme[m == selmon ? SchemeSel : SchemeInv]); - 			drw_text(drw, x, 0, w, bh, lrpad / 2, m->sel->name, 0); - 			if (m->sel->isfloating) - 				drw_rect(drw, x + boxs, boxs, boxw, boxw, m->sel->isfixed, 0); diff --git a/compile_commands.json b/compile_commands.json new file mode 100644 index 0000000..dcff5ac --- /dev/null +++ b/compile_commands.json @@ -0,0 +1,27 @@ +[ +  { +    "arguments": [ +      "/usr/bin/cc", +      "-c", +      "-std=c99", +      "-pedantic", +      "-Wall", +      "-Wno-deprecated-declarations", +      "-march=alderlake", +      "-Os", +      "-pipe", +      "-I/usr/X11R6/include", +      "-I/usr/include/freetype2", +      "-D_DEFAULT_SOURCE", +      "-D_BSD_SOURCE", +      "-D_XOPEN_SOURCE=700L", +      "-DVERSION=\"6.5\"", +      "-DXINERAMA", +      "-DHOME=\"/home/r_bousset/\"", +      "-DHOMEBIN=\"/home/r_bousset/.local/bin/\"", +      "dwm.c" +    ], +    "directory": "/home/r_bousset/.local/packs/dwm", +    "file": "/home/r_bousset/.local/packs/dwm/dwm.c" +  } +] diff --git a/config.def.h b/config.def.h index cfe9aa1..de85588 100644 --- a/config.def.h +++ b/config.def.h @@ -2,27 +2,27 @@  /* appearance */  static const unsigned int borderpx  = 3;        /* border pixel of windows */ -static const unsigned int gappx     = 10;        /* gaps between windows */ +static const unsigned int brdsh_w  = 3;        /* width of the app bar dash */ +static const unsigned int brdsh_ypos  = 20;        /* y-position of the dash */ +static const unsigned int text_ypos  = 1;        /* y-position of text */ +static const unsigned int gappx     = 6;        /* gaps between windows */  static const unsigned int snap      = 32;       /* snap pixel */ +static const int swallowfloating    = 1;        /* 1 means swallow floating windows by default */  static const unsigned int systraypinning = 0;   /* 0: sloppy systray follows selected monitor, >0: pin systray to monitor X */  static const unsigned int systrayonleft = 0;    /* 0: systray in the right corner, >0: systray on left of status text */  static const unsigned int systrayspacing = 2;   /* systray spacing */  static const int systraypinningfailfirst = 1;   /* 1: if pinning fails, display systray on the first monitor, False: display systray on the last monitor*/  static const int showsystray        = 1;        /* 0 means no systray */ -static const int showbar            = 1;        /* 0 means no bar */ +static const int showbar            = 0;        /* 0 means no bar */  static const int topbar             = 1;        /* 0 means bottom bar */ -static const int user_bh            = 22;        /* 0 means that dwm will calculate bar height, >= 1 means dwm will user_bh as bar height */  static const int focusonwheel       = 0; -static const unsigned int stairpx   = 25;       /* depth of the stairs layout */ -static const int stairdirection     = 0;        /* 0: left-aligned, 1: right-aligned */ -static const int stairsamesize      = 1;        /* 1 means shrink all the staired windows to the same size */  static const char *fonts[]          = { "UbuntuMono Nerd Font:size=14" };  static const char dmenufont[]       = "monospace:size=11";  static const char col_gray1[]       = "#222222";  static const char col_gray2[]       = "#444444";  static const char col_gray3[]       = "#bbbbbb";  static const char col_gray4[]       = "#eeeeee"; -static const char col_cyan[]        = "#6e0000"; +static const char col_cyan[]        = "#900000";  static const char *colors[][3]      = {  	/*               fg         bg         border   */  	[SchemeNorm] = { col_gray3, col_gray1, col_gray2 }, @@ -53,14 +53,17 @@ static const Rule rules[] = {  	 *	WM_CLASS(STRING) = instance, class  	 *	WM_NAME(STRING) = title  	 */ -	/* class             instance    title             tags mask     switchtotag,   isfloating   isfreesize   monitor */ -	{ "st",              NULL,       NULL,             0,            0,             0,           0,           -1 }, -	{ "St",              NULL,       NULL,             0,            0,             0,           0,           -1 }, /* St with Xresources patch */ -	{ "xterm-256color",  NULL,       NULL,             0,            0,             0,           0,           -1 }, -	{ "mpv",             NULL,       NULL,             0,            0,             0,           0,           -1 }, -	{ "Alacritty",       NULL,       NULL,             0,            0,             0,           0,           -1 }, -	{ "KeePass2",        NULL,       NULL,             0,            0,             1,           0,           -1 }, -	{ NULL,              NULL,       "Event Tester",   0,            0,             0,           0,           -1 }, /* xev */ +	/* class                 instance    title  tags mask  isfloating   isterminal noswallow   monitor */ +	{ "st",                  NULL,       NULL,  0,         0,           1,         0,         -1 }, +	{ "St",                  NULL,       NULL,  0,         0,           1,         0,         -1 }, /* St with Xresources patch */ +	{ "xterm-256color",      NULL,       NULL,  0,         0,           1,         0,         -1 }, +	{ "mpv",                 NULL,       NULL,  0,         0,           0,         0,         -1 }, +	{ "Alacritty",           NULL,       NULL,  0,         0,           1,         0,         -1 }, +	{ "rclone-browser",      NULL,       NULL,  1 << 1,    0,           0,         0,          2 }, +	{ "org.remmina.Remmina", NULL,       NULL,  1 << 2,    0,           0,         0,          2 }, +	{ "Vmware",              NULL,       NULL,  1 << 3,    0,           0,         0,          2 }, +	{ "teams-for-linux",     NULL,       NULL,  0,         1,           0,         0,          1 }, +	{ "thunderbird",         NULL,       NULL,  1 << 1,    0,           0,         0,          1 },  };  /* layout(s) */ @@ -68,15 +71,18 @@ static const float mfact     = 0.5; /* factor of master area size [0.05..0.95] *  static const int nmaster     = 1;    /* number of clients in master area */  static const int resizehints = 0;    /* 1 means respect size hints in tiled resizals */  static const int lockfullscreen = 1; /* 1 will force focus on the fullscreen window */ +static const float fgw = .75, fgh = .75; + +#define FORCE_VSPLIT 1  static const Layout layouts[] = {  	/* symbol     arrange function */ -	{ "[S]",      stairs },  	{ "[]=",      tile },    /* first entry is default */  	{ "TTT",      bstack },  	{ "===",      bstackhoriz },  	{ "|M|",      centeredmaster },  	{ ">M>",      centeredfloatingmaster }, +	{ "###",      nrowgrid },  	{ "[M]",      monocle },  	{ "><>",      NULL },    /* no layout function means floating behavior */  }; @@ -86,38 +92,39 @@ static const Layout layouts[] = {  #define METAKEY Mod1Mask  #define TAGKEYS(KEY,TAG) \  	{ MODKEY,                       KEY,      view,           {.ui = 1 << TAG} }, \ +	{ MODKEY|METAKEY|ControlMask,   KEY,      toggleview,     {.ui = 1 << TAG} }, \  	{ MODKEY|ShiftMask,             KEY,      tag,            {.ui = 1 << TAG} }, \ -	{ MODKEY|ControlMask,           KEY,      tagprevmon,     {.ui = 1 << TAG} }, \ -	{ MODKEY|ControlMask|ShiftMask, KEY,      tagnextmon,     {.ui = 1 << TAG} }, \  	{ MODKEY|METAKEY,               KEY,      toggletag,      {.ui = 1 << TAG} }, \ -	{ MODKEY|METAKEY|ControlMask,   KEY,      toggleview,     {.ui = 1 << TAG} }, +	{ MODKEY|ControlMask,           KEY,      tagprevmon,     {.ui = 1 << TAG} }, \ +	{ MODKEY|ControlMask|ShiftMask, KEY,      tagnextmon,     {.ui = 1 << TAG} },  /* helper for spawning shell commands in the pre dwm-5.0 fashion */  #define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } }  /* commands */  static char dmenumon[2] = "0"; /* component of dmenucmd, manipulated in spawn() */ -static const char *term_cmd[]        = { "st", NULL }; -static const char *coolterm_cmd[]    = { "cool-retro-term", NULL }; -static const char *dmenu_cmd[]       = { "dmenu_run", "-i", "-m", "0", NULL }; -static const char *dmpc_cmd[]        = { "/home/jozan/.local/bin/dmpc", NULL }; -static const char *dmkill_cmd[]      = { "/home/jozan/.local/bin/dmkill", NULL }; -static const char *dmsearch_cmd[]    = { "/home/jozan/.local/bin/dmsearch", NULL }; -static const char *dmscrot_cmd[]     = { "/home/jozan/.local/bin/dmscrot", NULL }; -static const char *dmlog_cmd[]       = { "/home/jozan/.local/bin/dmlog", NULL }; -static const char *dmpass_full_cmd[] = { "/home/jozan/.local/bin/dmpass", "--full", NULL }; -static const char *dmpass_cmd[]      = { "/home/jozan/.local/bin/dmpass", NULL }; -static const char *dmotp_cmd[]       = { "/home/jozan/.local/bin/dmotp", NULL }; -static const char *ndate_cmd[]       = { "/home/jozan/.local/bin/ndate", NULL }; +static const char *term_cmd[]        = { "alacritty", NULL }; +static const char *hardflip_cmd[]    = { "alacritty", "-e", "hf", NULL }; +static const char *dmenucmd[]       = { "dmenu_run", "-i", "-m", "0", NULL }; +static const char *dmapps_cmd[]      = { "/home/r_bousset/.local/bin/dmapps", NULL }; +static const char *dmpc_cmd[]        = { "/home/r_bousset/.local/bin/dmpc", NULL }; +static const char *dmkill_cmd[]      = { "/home/r_bousset/.local/bin/dmkill", NULL }; +static const char *dmsearch_cmd[]    = { "/home/r_bousset/.local/bin/dmsearch", NULL }; +static const char *dmscrot_cmd[]     = { "/home/r_bousset/.local/bin/dmscrot", NULL }; +static const char *dmlog_cmd[]       = { "/home/r_bousset/.local/bin/dmlog", NULL }; +static const char *dmpass_full_cmd[] = { "/home/r_bousset/.local/bin/dmpass", "--full", NULL }; +static const char *dmpass_cmd[]      = { "/home/r_bousset/.local/bin/dmpass", NULL }; +static const char *dmotp_cmd[]       = { "/home/r_bousset/.local/bin/dmotp", NULL }; +static const char *ndate_cmd[]       = { "/home/r_bousset/.local/bin/ndate", NULL };  static const char *file_cmd[]        = { "alacritty", "-e", "zsh", "-ic", "lf", NULL };  static const char *file_alt_cmd[]    = { "pcmanfm", NULL };  static const char *edit_cmd[]        = { "emacsclient", "-c", NULL }; -static const char *browser_cmd[]     = { "iridium", "--force-dark-mode", NULL }; -static const char *torbro_cmd[]      = { "torify", "iridium", "--force-dark-mode", NULL }; +static const char *browser_cmd[]     = { "firefox", NULL }; +static const char *torbro_cmd[]      = { "torify", "librewolf", NULL };  static const char *w3m_cmd[]         = { "alacritty", "-e", "w3m", "https://start.duckduckgo.com/", NULL };  static const char *nb_cmd[]          = { "alacritty", "-e", "newsboat", NULL };  static const char *ncmpc_cmd[]       = { "alacritty", "-e", "ncmpc", NULL }; -static const char *cal_cmd[]         = { "alacritty", "-e", "calcurse", "-C", "/home/jozan/.config/calcurse", "-D", "/home/jozan/.local/share/calcurse", NULL }; +static const char *cal_cmd[]         = { "alacritty", "-e", "calcurse", "-C", "/home/r_bousset/.config/calcurse", "-D", "/home/r_bousset/.local/share/calcurse", NULL };  static const char *scli_cmd[]        = { "alacritty", "-e", "scli", NULL };  static const char *mutt_cmd[]        = { "alacritty", "-e", "neomutt", NULL };  static const char *gotop_cmd[]       = { "alacritty", "-e", "gotop", NULL }; @@ -125,23 +132,22 @@ static const char *htop_cmd[]        = { "alacritty", "-e", "htop", NULL };  static const char *top_cmd[]         = { "alacritty", "-e", "top", NULL };  static const char *bl_inc_cmd[]      = { "xbacklight", "-inc", "10", NULL };  static const char *bl_dec_cmd[]      = { "xbacklight", "-dec", "10", NULL }; -static const char *vol_tog_cmd[]     = { "/home/jozan/.local/bin/mixer-set", "toggle", NULL }; -static const char *vol_dec_cmd[]     = { "/home/jozan/.local/bin/mixer-set", "lower", NULL }; -static const char *vol_inc_cmd[]     = { "/home/jozan/.local/bin/mixer-set", "raise", NULL }; -static const char *mic_cmd[]         = { "/home/jozan/.local/bin/mic", NULL }; +static const char *vol_tog_cmd[]     = { "/home/r_bousset/.local/bin/mixer-set", "toggle", NULL }; +static const char *vol_dec_cmd[]     = { "/home/r_bousset/.local/bin/mixer-set", "lower", NULL }; +static const char *vol_inc_cmd[]     = { "/home/r_bousset/.local/bin/mixer-set", "raise", NULL }; +static const char *mic_cmd[]         = { "/home/r_bousset/.local/bin/mic", NULL };  static const char *mpc_prev_cmd[]    = { "mpc", "prev", NULL };  static const char *mpc_next_cmd[]    = { "mpc", "next", NULL };  static const char *mpc_tog_cmd[]     = { "mpc", "toggle", NULL };  static const char *mpc_stop_cmd[]    = { "mpc", "stop", NULL }; -static const char *killespeak_cmd[]  = { "/home/jozan/.local/bin/shutup", NULL }; +static const char *killespeak_cmd[]  = { "/home/r_bousset/.local/bin/shutup", NULL }; -#include "movestack.c"  #include <X11/XF86keysym.h> -static Key keys[] = { -	/* modifier                     key        function        argument */ -	{ MODKEY,                       XK_p,                     spawn,          {.v = dmenu_cmd } }, +static const Key keys[] = { +	{ MODKEY,                       XK_p,                     spawn,          {.v = dmenucmd } },  	{ MODKEY,                       XK_Return,                spawn,          {.v = term_cmd } }, -	{ MODKEY|ControlMask,           XK_Return,                spawn,          {.v = coolterm_cmd } }, +	{ MODKEY|ControlMask|ShiftMask, XK_Return,                spawn,          {.v = hardflip_cmd } }, +	{ MODKEY|ControlMask,           XK_Return,                spawn,          {.v = dmapps_cmd } },  	{ MODKEY,                       XK_F1,                    spawn,          {.v = file_cmd } },  	{ MODKEY|ShiftMask,             XK_F1,                    spawn,          {.v = file_alt_cmd } },  	{ MODKEY,                       XK_F2,                    spawn,          {.v = edit_cmd } }, @@ -197,18 +203,20 @@ static Key keys[] = {  	{ MODKEY|ShiftMask,             XK_Return,                zoom,           {0} },  	{ METAKEY,                      XK_Escape,                view,           {0} },  	{ MODKEY,                       XK_q,                     killclient,     {0} }, -	{ MODKEY,                       XK_s,                     setlayout,      {.v = &layouts[0]} }, /* stairs */ -	{ MODKEY|ShiftMask,             XK_s,                     setlayout,      {.v = &layouts[1]} }, /* tile */ -	{ MODKEY,                       XK_z,                     setlayout,      {.v = &layouts[0]} }, /* stairs */ -	{ MODKEY|ShiftMask,             XK_z,                     setlayout,      {.v = &layouts[1]} }, /* tile */ -	{ MODKEY,                       XK_x,                     setlayout,      {.v = &layouts[2]} }, /* bottoastack */ -	{ MODKEY|ShiftMask,             XK_x,                     setlayout,      {.v = &layouts[3]} }, /* bottomstackhoriz */ -	{ MODKEY,                       XK_c,                     setlayout,      {.v = &layouts[4]} }, /* centeredmaster */ -	{ MODKEY|ShiftMask,             XK_c,                     setlayout,      {.v = &layouts[5]} }, /* centeredfloatingmaster */ +	{ MODKEY,                       XK_s,                     setlayout,      {.v = &layouts[0]} }, /* tile */ +	{ MODKEY|ShiftMask,             XK_s,                     setlayout,      {.v = &layouts[0]} }, /* tile */ +	{ MODKEY,                       XK_z,                     setlayout,      {.v = &layouts[0]} }, /* tile */ +	{ MODKEY|ShiftMask,             XK_z,                     setlayout,      {.v = &layouts[0]} }, /* tile */ +	{ MODKEY,                       XK_x,                     setlayout,      {.v = &layouts[1]} }, /* bottoastack */ +	{ MODKEY|ShiftMask,             XK_x,                     setlayout,      {.v = &layouts[2]} }, /* bottomstackhoriz */ +	{ MODKEY,                       XK_c,                     setlayout,      {.v = &layouts[3]} }, /* centeredmaster */ +	{ MODKEY|ShiftMask,             XK_c,                     setlayout,      {.v = &layouts[4]} }, /* centeredfloatingmaster */ +	{ MODKEY,                       XK_v,                     setlayout,      {.v = &layouts[5]} }, /* centeredmaster */  	{ MODKEY,                       XK_m,                     setlayout,      {.v = &layouts[6]} }, /* monocle */  	{ MODKEY,                       XK_n,                     setlayout,      {.v = &layouts[7]} }, /* floating */  	{ MODKEY|ShiftMask,             XK_space,                 setlayout,      {0} },  	{ MODKEY,                       XK_space,                 togglefloating, {0} }, +	{ MODKEY|ControlMask,           XK_space,                 toggleforegrounded, {0} },  	{ MODKEY,                       XK_f,                     togglefullscr,  {0} },  	{ MODKEY,                       XK_bracketleft,           focusmon,       {.i = +1 } },  	{ MODKEY,                       XK_bracketright,          focusmon,       {.i = -1 } }, @@ -247,14 +255,15 @@ static Key keys[] = {  	{ MODKEY,                       XK_0,                      view,          {.ui = ~0 } },  	{ MODKEY|ShiftMask,             XK_0,                      tag,           {.ui = ~0 } },  	{ MODKEY|ShiftMask,             XK_e,                      quit,          {0} }, +	{ MODKEY,                       XK_o,                      winview,       {0} },  };  /* button definitions */  /* click can be ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, or ClkRootWin */ -static Button buttons[] = { +static const Button buttons[] = {  	/* click                event mask      button          function        argument */ -	{ ClkTagBar,            MODKEY,         Button1,        tag,            {0} }, -	{ ClkTagBar,            MODKEY,         Button3,        toggletag,      {0} }, +	{ ClkLtSymbol,          0,              Button1,        setlayout,      {0} }, +	{ ClkLtSymbol,          0,              Button3,        setlayout,      {.v = &layouts[2]} },  	{ ClkWinTitle,          0,              Button2,        zoom,           {0} },  	{ ClkStatusText,        0,              Button2,        spawn,          {.v = term_cmd } },  	{ ClkClientWin,         MODKEY,         Button1,        movemouse,      {0} }, diff --git a/config.h b/config.h deleted file mode 100644 index 549b8b0..0000000 --- a/config.h +++ /dev/null @@ -1,286 +0,0 @@ -/* See LICENSE file for copyright and license details. */ - -/* appearance */ -static const unsigned int borderpx  = 3;        /* border pixel of windows */ -static const unsigned int gappx     = 10;        /* gaps between windows */ -static const unsigned int snap      = 32;       /* snap pixel */ -static const unsigned int systraypinning = 0;   /* 0: sloppy systray follows selected monitor, >0: pin systray to monitor X */ -static const unsigned int systrayonleft = 0;    /* 0: systray in the right corner, >0: systray on left of status text */ -static const unsigned int systrayspacing = 2;   /* systray spacing */ -static const int systraypinningfailfirst = 1;   /* 1: if pinning fails, display systray on the first monitor, False: display systray on the last monitor*/ -static const int showsystray        = 1;        /* 0 means no systray */ -static const int showbar            = 0;        /* 0 means no bar */ -static const int topbar             = 1;        /* 0 means bottom bar */ -static const int user_bh            = 22;        /* 0 means that dwm will calculate bar height, >= 1 means dwm will user_bh as bar height */ -static const int focusonwheel       = 0; -static const unsigned int stairpx   = 25;       /* depth of the stairs layout */ -static const int stairdirection     = 1;        /* 0: left-aligned, 1: right-aligned */ -static const int stairsamesize      = 1;        /* 1 means shrink all the staired windows to the same size */ -static const char *fonts[]          = { "UbuntuMono Nerd Font:size=14" }; -static const char dmenufont[]       = "monospace:size=11"; -static const char col_gray1[]       = "#222222"; -static const char col_gray2[]       = "#444444"; -static const char col_gray3[]       = "#bbbbbb"; -static const char col_gray4[]       = "#eeeeee"; -static const char col_cyan[]        = "#900000"; -static const char *colors[][3]      = { -	/*               fg         bg         border   */ -	[SchemeNorm] = { col_gray3, col_gray1, col_gray2 }, -	[SchemeSel]  = { col_gray4, col_cyan,  col_cyan  }, -}; - -/* tagging */ -static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" }; -static const char *tagsel[][2] = { -	{ "#ffffff", "#900000" }, -	{ "#ffffff", "#ff7f00" }, -	{ "#000000", "#ffff00" }, -	{ "#000000", "#00ff00" }, -	{ "#ffffff", "#0000ff" }, -	{ "#ffffff", "#4b0082" }, -	{ "#ffffff", "#9400d3" }, -	{ "#000000", "#ffffff" }, -	{ "#ffffff", "#000000" }, -}; - - -/* grid of tags */ -#define DRAWCLASSICTAGS             1 << 0 -#define DRAWTAGGRID                 1 << 1 - -#define SWITCHTAG_UP                1 << 0 -#define SWITCHTAG_DOWN              1 << 1 -#define SWITCHTAG_LEFT              1 << 2 -#define SWITCHTAG_RIGHT             1 << 3 -#define SWITCHTAG_TOGGLETAG         1 << 4 -#define SWITCHTAG_TAG               1 << 5 -#define SWITCHTAG_VIEW              1 << 6 -#define SWITCHTAG_TOGGLEVIEW        1 << 7 - -static const unsigned int drawtagmask = DRAWTAGGRID; /* | DRAWCLASSICTAGS to show classic row of tags */ -static const int tagrows = 2; - -static const Rule rules[] = { -	/* xprop(1): -	 *	WM_CLASS(STRING) = instance, class -	 *	WM_NAME(STRING) = title -	 */ -	/* class                         instance    title             tags mask     switchtotag,   isfloating   isfreesize   monitor */ -	{ "st",                          NULL,       NULL,             0,            0,             0,           0,           -1 }, -	{ "St",                          NULL,       NULL,             0,            0,             0,           0,           -1 }, /* St with Xresources patch */ -	{ "xterm-256color",              NULL,       NULL,             0,            0,             0,           0,           -1 }, -	{ "mpv",                         NULL,       NULL,             0,            0,             0,           0,           -1 }, -	{ "Alacritty",                   NULL,       NULL,             0,            0,             0,           0,           -1 }, -	{ "rclone-browser",              NULL,       NULL,             1 << 1,       0,             0,           0,            2 }, -	{ "org.remmina.Remmina",         NULL,       NULL,             1 << 2,       0,             0,           0,            2 }, -	{ "Vmware",                      NULL,       NULL,             1 << 3,       0,             0,           0,            2 }, -	{ "Microsoft Teams - Preview",   NULL,       NULL,             0,            0,             0,           0,            1 }, -	{ "thunderbird",                 NULL,       NULL,             1 << 1,       0,             0,           0,            1 }, -	{ NULL,                          NULL,       "Event Tester",   0,            0,             0,           0,           -1 }, /* xev */ -}; - -/* layout(s) */ -static const float mfact     = 0.5; /* factor of master area size [0.05..0.95] */ -static const int nmaster     = 1;    /* number of clients in master area */ -static const int resizehints = 0;    /* 1 means respect size hints in tiled resizals */ -static const int lockfullscreen = 1; /* 1 will force focus on the fullscreen window */ - -static const Layout layouts[] = { -	/* symbol     arrange function */ -	{ "[S]",      stairs }, -	{ "[]=",      tile },    /* first entry is default */ -	{ "TTT",      bstack }, -	{ "===",      bstackhoriz }, -	{ "|M|",      centeredmaster }, -	{ ">M>",      centeredfloatingmaster }, -	{ "[M]",      monocle }, -	{ "><>",      NULL },    /* no layout function means floating behavior */ -}; - -/* key definitions */ -#define MODKEY Mod4Mask -#define METAKEY Mod1Mask -#define TAGKEYS(KEY,TAG) \ -	{ MODKEY,                       KEY,      view,           {.ui = 1 << TAG} }, \ -	{ MODKEY|ShiftMask,             KEY,      tag,            {.ui = 1 << TAG} }, \ -	{ MODKEY|ControlMask,           KEY,      tagprevmon,     {.ui = 1 << TAG} }, \ -	{ MODKEY|ControlMask|ShiftMask, KEY,      tagnextmon,     {.ui = 1 << TAG} }, \ -	{ MODKEY|METAKEY,               KEY,      toggletag,      {.ui = 1 << TAG} }, \ -	{ MODKEY|METAKEY|ControlMask,   KEY,      toggleview,     {.ui = 1 << TAG} }, - -/* helper for spawning shell commands in the pre dwm-5.0 fashion */ -#define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } } - -/* commands */ -static char dmenumon[2] = "0"; /* component of dmenucmd, manipulated in spawn() */ -static const char *term_cmd[]        = { "alacritty", NULL }; -static const char *hardflip_cmd[]    = { "alacritty", "-e", "hf", NULL }; -static const char *dmenu_cmd[]       = { "dmenu_run", "-i", "-m", "0", NULL }; -static const char *dmapps_cmd[]      = { "/home/jozan/.local/bin/dmapps", NULL }; -static const char *dmpc_cmd[]        = { "/home/jozan/.local/bin/dmpc", NULL }; -static const char *dmkill_cmd[]      = { "/home/jozan/.local/bin/dmkill", NULL }; -static const char *dmsearch_cmd[]    = { "/home/jozan/.local/bin/dmsearch", NULL }; -static const char *dmscrot_cmd[]     = { "/home/jozan/.local/bin/dmscrot", NULL }; -static const char *dmlog_cmd[]       = { "/home/jozan/.local/bin/dmlog", NULL }; -static const char *dmpass_full_cmd[] = { "/home/jozan/.local/bin/dmpass", "--full", NULL }; -static const char *dmpass_cmd[]      = { "/home/jozan/.local/bin/dmpass", NULL }; -static const char *dmotp_cmd[]       = { "/home/jozan/.local/bin/dmotp", NULL }; -static const char *ndate_cmd[]       = { "/home/jozan/.local/bin/ndate", NULL }; -static const char *file_cmd[]        = { "alacritty", "-e", "zsh", "-ic", "lf", NULL }; -static const char *file_alt_cmd[]    = { "pcmanfm", NULL }; -static const char *edit_cmd[]        = { "emacsclient", "-c", NULL }; -static const char *browser_cmd[]     = { "firefox", NULL }; -static const char *torbro_cmd[]      = { "torify", "librewolf", NULL }; -static const char *w3m_cmd[]         = { "alacritty", "-e", "w3m", "https://start.duckduckgo.com/", NULL }; -static const char *nb_cmd[]          = { "alacritty", "-e", "newsboat", NULL }; -static const char *ncmpc_cmd[]       = { "alacritty", "-e", "ncmpc", NULL }; -static const char *cal_cmd[]         = { "alacritty", "-e", "calcurse", "-C", "/home/jozan/.config/calcurse", "-D", "/home/jozan/.local/share/calcurse", NULL }; -static const char *scli_cmd[]        = { "alacritty", "-e", "scli", NULL }; -static const char *mutt_cmd[]        = { "alacritty", "-e", "neomutt", NULL }; -static const char *gotop_cmd[]       = { "alacritty", "-e", "gotop", NULL }; -static const char *htop_cmd[]        = { "alacritty", "-e", "htop", NULL }; -static const char *top_cmd[]         = { "alacritty", "-e", "top", NULL }; -static const char *bl_inc_cmd[]      = { "xbacklight", "-inc", "10", NULL }; -static const char *bl_dec_cmd[]      = { "xbacklight", "-dec", "10", NULL }; -static const char *vol_tog_cmd[]     = { "/home/jozan/.local/bin/mixer-set", "toggle", NULL }; -static const char *vol_dec_cmd[]     = { "/home/jozan/.local/bin/mixer-set", "lower", NULL }; -static const char *vol_inc_cmd[]     = { "/home/jozan/.local/bin/mixer-set", "raise", NULL }; -static const char *mic_cmd[]         = { "/home/jozan/.local/bin/mic", NULL }; -static const char *mpc_prev_cmd[]    = { "mpc", "prev", NULL }; -static const char *mpc_next_cmd[]    = { "mpc", "next", NULL }; -static const char *mpc_tog_cmd[]     = { "mpc", "toggle", NULL }; -static const char *mpc_stop_cmd[]    = { "mpc", "stop", NULL }; -static const char *killespeak_cmd[]  = { "/home/jozan/.local/bin/shutup", NULL }; - -#include "movestack.c" -#include <X11/XF86keysym.h> -static Key keys[] = { -	/* modifier                     key        function        argument */ -	{ MODKEY,                       XK_p,                     spawn,          {.v = dmenu_cmd } }, -	{ MODKEY,                       XK_Return,                spawn,          {.v = term_cmd } }, -	{ MODKEY|ControlMask|ShiftMask, XK_Return,                spawn,          {.v = hardflip_cmd } }, -	{ MODKEY|ControlMask,           XK_Return,                spawn,          {.v = dmapps_cmd } }, -	{ MODKEY,                       XK_F1,                    spawn,          {.v = file_cmd } }, -	{ MODKEY|ShiftMask,             XK_F1,                    spawn,          {.v = file_alt_cmd } }, -	{ MODKEY,                       XK_F2,                    spawn,          {.v = edit_cmd } }, -	{ MODKEY,                       XK_F3,                    spawn,          {.v = browser_cmd } }, -	{ MODKEY|ShiftMask,             XK_F3,                    spawn,          {.v = torbro_cmd } }, -	{ MODKEY,                       XK_F4,                    spawn,          {.v = w3m_cmd } }, -	{ MODKEY,                       XK_F5,                    spawn,          {.v = ncmpc_cmd } }, -	{ MODKEY,                       XK_F6,                    spawn,          {.v = nb_cmd} }, -	{ MODKEY,                       XK_F7,                    spawn,          {.v = cal_cmd } }, -	{ MODKEY,                       XK_F8,                    spawn,          {.v = scli_cmd } }, -	{ MODKEY,                       XK_F9,                    spawn,          {.v = mutt_cmd } }, -	{ MODKEY,                       XK_F10,                   spawn,          {.v = gotop_cmd } }, -	{ MODKEY,                       XK_F11,                   spawn,          {.v = htop_cmd } }, -	{ MODKEY,                       XK_F12,                   spawn,          {.v = top_cmd } }, -	{ MODKEY|ShiftMask,             XK_F6,                    spawn,          {.v = mpc_prev_cmd } }, -	{ MODKEY|ShiftMask,             XK_F7,                    spawn,          {.v = mpc_tog_cmd } }, -	{ MODKEY|ShiftMask,             XK_F8,                    spawn,          {.v = mpc_next_cmd } }, -	{ MODKEY|ShiftMask,             XK_F9,                    spawn,          {.v = mpc_stop_cmd } }, -	{ MODKEY|ShiftMask,             XK_F10,                   spawn,          {.v = vol_tog_cmd } }, -	{ MODKEY|ShiftMask,             XK_F11,                   spawn,          {.v = vol_dec_cmd } }, -	{ MODKEY|ShiftMask,             XK_F12,                   spawn,          {.v = vol_inc_cmd } }, -	{ MODKEY|ShiftMask,             XK_Delete,                spawn,          {.v = mic_cmd } }, -	{ MODKEY|ControlMask,           XK_F9,                    spawn,          {.v = dmkill_cmd } }, -	{ MODKEY|ControlMask,           XK_F10,                   spawn,          {.v = dmscrot_cmd } }, -	{ MODKEY|ControlMask,           XK_F11,                   spawn,          {.v = dmsearch_cmd } }, -	{ MODKEY|ControlMask,           XK_F12,                   spawn,          {.v = dmlog_cmd } }, -	{ MODKEY|ControlMask,           XK_BackSpace,             spawn,          {.v = dmlog_cmd } }, -	{ MODKEY,                       XK_BackSpace,             spawn,          {.v = dmpc_cmd } }, -	{ MODKEY|ControlMask,           XK_p,                     spawn,          {.v = dmpass_cmd } }, -	{ MODKEY|ControlMask|ShiftMask, XK_p,                     spawn,          {.v = dmpass_full_cmd } }, -	{ MODKEY|ControlMask,           XK_o,                     spawn,          {.v = dmotp_cmd } }, -	{ MODKEY,                       XK_End,                   spawn,          {.v = ndate_cmd } }, -	{ 0,                            XF86XK_MonBrightnessUp,   spawn,          {.v = bl_inc_cmd } }, -	{ 0,                            XF86XK_MonBrightnessDown, spawn,          {.v = bl_dec_cmd } }, -	{ 0,                            XF86XK_AudioRaiseVolume,  spawn,          {.v = vol_inc_cmd } }, -	{ 0,                            XF86XK_AudioLowerVolume,  spawn,          {.v = vol_dec_cmd } }, -	{ 0,                            XF86XK_AudioMute,         spawn,          {.v = vol_tog_cmd } }, -	{ 0,                            XF86XK_AudioPlay,         spawn,          {.v = mpc_tog_cmd } }, -	{ 0,                            XF86XK_AudioPrev,         spawn,          {.v = mpc_prev_cmd } }, -	{ 0,                            XF86XK_AudioNext,         spawn,          {.v = mpc_next_cmd } }, -	{ MODKEY,                       XK_Delete,                spawn,          {.v = killespeak_cmd } }, -	{ MODKEY,                       XK_b,                     togglebar,      {0} }, -	{ MODKEY,                       XK_j,                     focusstack,     {.i = +1 } }, -	{ MODKEY,                       XK_k,                     focusstack,     {.i = -1 } }, -	{ MODKEY,                       XK_i,                     incnmaster,     {.i = +1 } }, -	{ MODKEY,                       XK_d,                     incnmaster,     {.i = -1 } }, -	{ MODKEY|ControlMask,           XK_a,                     incnmaster,     {.i = +1 } }, -	{ MODKEY|ControlMask,           XK_x,                     incnmaster,     {.i = -1 } }, -	{ MODKEY|ControlMask,           XK_minus,                 setmfact,       {.f = -0.025} }, -	{ MODKEY|ControlMask,           XK_equal,                 setmfact,       {.f = +0.025} }, -	{ MODKEY|ShiftMask,             XK_j,                     movestack,      {.i = +1 } }, -	{ MODKEY|ShiftMask,             XK_k,                     movestack,      {.i = -1 } }, -	{ MODKEY|ShiftMask,             XK_Return,                zoom,           {0} }, -	{ METAKEY,                      XK_Escape,                view,           {0} }, -	{ MODKEY,                       XK_q,                     killclient,     {0} }, -	{ MODKEY,                       XK_s,                     setlayout,      {.v = &layouts[0]} }, /* stairs */ -	{ MODKEY|ShiftMask,             XK_s,                     setlayout,      {.v = &layouts[1]} }, /* tile */ -	{ MODKEY,                       XK_z,                     setlayout,      {.v = &layouts[0]} }, /* stairs */ -	{ MODKEY|ShiftMask,             XK_z,                     setlayout,      {.v = &layouts[1]} }, /* tile */ -	{ MODKEY,                       XK_x,                     setlayout,      {.v = &layouts[2]} }, /* bottoastack */ -	{ MODKEY|ShiftMask,             XK_x,                     setlayout,      {.v = &layouts[3]} }, /* bottomstackhoriz */ -	{ MODKEY,                       XK_c,                     setlayout,      {.v = &layouts[4]} }, /* centeredmaster */ -	{ MODKEY|ShiftMask,             XK_c,                     setlayout,      {.v = &layouts[5]} }, /* centeredfloatingmaster */ -	{ MODKEY,                       XK_m,                     setlayout,      {.v = &layouts[6]} }, /* monocle */ -	{ MODKEY,                       XK_n,                     setlayout,      {.v = &layouts[7]} }, /* floating */ -	{ MODKEY|ShiftMask,             XK_space,                 setlayout,      {0} }, -	{ MODKEY,                       XK_space,                 togglefloating, {0} }, -	{ MODKEY,                       XK_f,                     togglefullscr,  {0} }, -	{ MODKEY,                       XK_bracketleft,           focusmon,       {.i = +1 } }, -	{ MODKEY,                       XK_bracketright,          focusmon,       {.i = -1 } }, -	{ MODKEY,                       XK_h,                     focusmon,       {.i = +1 } }, -	{ MODKEY,                       XK_l,                     focusmon,       {.i = -1 } }, -	{ MODKEY|ShiftMask,             XK_bracketleft,           tagmon,         {.i = +1 } }, -	{ MODKEY|ShiftMask,             XK_bracketright,          tagmon,         {.i = -1 } }, -	{ MODKEY|ShiftMask,             XK_h,                     tagmon,         {.i = +1 } }, -	{ MODKEY|ShiftMask,             XK_l,                     tagmon,         {.i = -1 } }, -	{ MODKEY|ShiftMask,             XK_bracketleft,           focusmon,       {.i = +1 } }, -	{ MODKEY|ShiftMask,             XK_bracketright,          focusmon,       {.i = -1 } }, -	{ MODKEY|ShiftMask,             XK_h,                     focusmon,       {.i = +1 } }, -	{ MODKEY|ShiftMask,             XK_l,                     focusmon,       {.i = -1 } }, -	{ MODKEY,                       XK_w,                     movemouse,      {0} }, -	{ MODKEY|ShiftMask,             XK_w,                     resizemouse,    {0} }, -	{ MODKEY,                       XK_minus,                 setgaps,        {.i = -1 } }, -	{ MODKEY,                       XK_equal,                 setgaps,        {.i = +1 } }, -	{ MODKEY|ShiftMask,             XK_equal,                 setgaps,        {.i = 0  } }, -	{ MODKEY|ControlMask,           XK_k,                     switchtag,      { .ui = SWITCHTAG_UP     | SWITCHTAG_VIEW } }, -	{ MODKEY|ControlMask,           XK_j,                     switchtag,      { .ui = SWITCHTAG_DOWN   | SWITCHTAG_VIEW } }, -	{ MODKEY|ControlMask,           XK_l,                     switchtag,      { .ui = SWITCHTAG_RIGHT  | SWITCHTAG_VIEW } }, -	{ MODKEY|ControlMask,           XK_h,                     switchtag,      { .ui = SWITCHTAG_LEFT   | SWITCHTAG_VIEW } }, -	{ MODKEY|METAKEY,               XK_k,                     switchtag,      { .ui = SWITCHTAG_UP     | SWITCHTAG_TAG | SWITCHTAG_VIEW } }, -	{ MODKEY|METAKEY,               XK_j,                     switchtag,      { .ui = SWITCHTAG_DOWN   | SWITCHTAG_TAG | SWITCHTAG_VIEW } }, -	{ MODKEY|METAKEY,               XK_l,                     switchtag,      { .ui = SWITCHTAG_RIGHT  | SWITCHTAG_TAG | SWITCHTAG_VIEW } }, -	{ MODKEY|METAKEY,               XK_h,                     switchtag,      { .ui = SWITCHTAG_LEFT   | SWITCHTAG_TAG | SWITCHTAG_VIEW } }, -	TAGKEYS(                        XK_1,                                     0) -	TAGKEYS(                        XK_2,                                     1) -	TAGKEYS(                        XK_3,                                     2) -	TAGKEYS(                        XK_4,                                     3) -	TAGKEYS(                        XK_5,                                     4) -	TAGKEYS(                        XK_6,                                     5) -	TAGKEYS(                        XK_7,                                     6) -	TAGKEYS(                        XK_8,                                     7) -	TAGKEYS(                        XK_9,                                     8) -	{ MODKEY,                       XK_0,                      view,          {.ui = ~0 } }, -	{ MODKEY|ShiftMask,             XK_0,                      tag,           {.ui = ~0 } }, -	{ MODKEY|ShiftMask,             XK_e,                      quit,          {0} }, -}; - -/* button definitions */ -/* click can be ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, or ClkRootWin */ -static Button buttons[] = { -	/* click                event mask      button          function        argument */ -	{ ClkTagBar,            MODKEY,         Button1,        tag,            {0} }, -	{ ClkTagBar,            MODKEY,         Button3,        toggletag,      {0} }, -	{ ClkWinTitle,          0,              Button2,        zoom,           {0} }, -	{ ClkStatusText,        0,              Button2,        spawn,          {.v = term_cmd } }, -	{ ClkClientWin,         MODKEY,         Button1,        movemouse,      {0} }, -	{ ClkClientWin,         MODKEY,         Button2,        togglefloating, {0} }, -	{ ClkClientWin,         MODKEY,         Button3,        resizemouse,    {0} }, -	{ ClkTagBar,            0,              Button1,        view,           {0} }, -	{ ClkTagBar,            0,              Button3,        toggleview,     {0} }, -	{ ClkTagBar,            MODKEY,         Button1,        tag,            {0} }, -	{ ClkTagBar,            MODKEY,         Button3,        toggletag,      {0} }, -}; - @@ -1,5 +1,5 @@  # dwm version -VERSION = 6.3 +VERSION = 6.5  # Customize below to fit your system @@ -7,8 +7,8 @@ VERSION = 6.3  PREFIX = /usr/local  MANPREFIX = ${PREFIX}/share/man -X11INC = /usr/local/include -X11LIB = /usr/local/lib +X11INC = /usr/X11R6/include +X11LIB = /usr/X11R6/lib  # Xinerama, comment if you don't want it  XINERAMALIBS  = -lXinerama @@ -18,16 +18,17 @@ XINERAMAFLAGS = -DXINERAMA  FREETYPELIBS = -lfontconfig -lXft  FREETYPEINC = /usr/include/freetype2  # OpenBSD (uncomment) -# FREETYPEINC = ${X11INC}/freetype2 +#FREETYPEINC = ${X11INC}/freetype2 +#MANPREFIX = ${PREFIX}/man  # includes and libs  INCS = -I${X11INC} -I${FREETYPEINC} -LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} +LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} -lX11-xcb -lxcb -lxcb-res ${KVMLIB}  # flags -CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_POSIX_C_SOURCE=200809L -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS} -DHOME=\"${HOME}/\" -DHOMEBIN=\"${HOME}/.local/bin/\" +CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_XOPEN_SOURCE=700L -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS} -DHOME=\"${HOME}/\" -DHOMEBIN=\"${HOME}/.local/bin/\"  #CFLAGS   = -g -std=c99 -pedantic -Wall -O0 ${INCS} ${CPPFLAGS} -CFLAGS   = -std=c99 -pedantic -Wall -Wno-deprecated-declarations -march=haswell -O3 -pipe ${INCS} ${CPPFLAGS} +CFLAGS   = -std=c99 -pedantic -Wall -Wno-deprecated-declarations -march=alderlake -Os -pipe ${INCS} ${CPPFLAGS}  LDFLAGS  = ${LIBS}  # Solaris @@ -9,54 +9,40 @@  #include "util.h"  #define UTF_INVALID 0xFFFD -#define UTF_SIZ     4 -static const unsigned char utfbyte[UTF_SIZ + 1] = {0x80,    0, 0xC0, 0xE0, 0xF0}; -static const unsigned char utfmask[UTF_SIZ + 1] = {0xC0, 0x80, 0xE0, 0xF0, 0xF8}; -static const long utfmin[UTF_SIZ + 1] = {       0,    0,  0x80,  0x800,  0x10000}; -static const long utfmax[UTF_SIZ + 1] = {0x10FFFF, 0x7F, 0x7FF, 0xFFFF, 0x10FFFF}; - -static long -utf8decodebyte(const char c, size_t *i) -{ -	for (*i = 0; *i < (UTF_SIZ + 1); ++(*i)) -		if (((unsigned char)c & utfmask[*i]) == utfbyte[*i]) -			return (unsigned char)c & ~utfmask[*i]; -	return 0; -} - -static size_t -utf8validate(long *u, size_t i) -{ -	if (!BETWEEN(*u, utfmin[i], utfmax[i]) || BETWEEN(*u, 0xD800, 0xDFFF)) -		*u = UTF_INVALID; -	for (i = 1; *u > utfmax[i]; ++i) -		; -	return i; -} - -static size_t -utf8decode(const char *c, long *u, size_t clen) +static int +utf8decode(const char *s_in, long *u, int *err)  { -	size_t i, j, len, type; -	long udecoded; - +	static const unsigned char lens[] = { +		/* 0XXXX */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +		/* 10XXX */ 0, 0, 0, 0, 0, 0, 0, 0,  /* invalid */ +		/* 110XX */ 2, 2, 2, 2, +		/* 1110X */ 3, 3, +		/* 11110 */ 4, +		/* 11111 */ 0,  /* invalid */ +	}; +	static const unsigned char leading_mask[] = { 0x7F, 0x1F, 0x0F, 0x07 }; +	static const unsigned int overlong[] = { 0x0, 0x80, 0x0800, 0x10000 }; + +	const unsigned char *s = (const unsigned char *)s_in; +	int len = lens[*s >> 3];  	*u = UTF_INVALID; -	if (!clen) -		return 0; -	udecoded = utf8decodebyte(c[0], &len); -	if (!BETWEEN(len, 1, UTF_SIZ)) +	*err = 1; +	if (len == 0)  		return 1; -	for (i = 1, j = 1; i < clen && j < len; ++i, ++j) { -		udecoded = (udecoded << 6) | utf8decodebyte(c[i], &type); -		if (type) -			return j; + +	long cp = s[0] & leading_mask[len - 1]; +	for (int i = 1; i < len; ++i) { +		if (s[i] == '\0' || (s[i] & 0xC0) != 0x80) +			return i; +		cp = (cp << 6) | (s[i] & 0x3F);  	} -	if (j < len) -		return 0; -	*u = udecoded; -	utf8validate(u, len); +	/* out of range, surrogate, overlong encoding */ +	if (cp > 0x10FFFF || (cp >> 11) == 0x1B || cp < overlong[len - 1]) +		return len; +	*err = 0; +	*u = cp;  	return len;  } @@ -133,19 +119,6 @@ xfont_create(Drw *drw, const char *fontname, FcPattern *fontpattern)  		die("no font specified.");  	} -	/* Do not allow using color fonts. This is a workaround for a BadLength -	 * error from Xft with color glyphs. Modelled on the Xterm workaround. See -	 * https://bugzilla.redhat.com/show_bug.cgi?id=1498269 -	 * https://lists.suckless.org/dev/1701/30932.html -	 * https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=916349 -	 * and lots more all over the internet. -	 */ -	FcBool iscol; -	if(FcPatternGetBool(xfont->pattern, FC_COLOR, 0, &iscol) == FcResultMatch && iscol) { -		XftFontClose(drw->dpy, xfont); -		return NULL; -	} -  	font = ecalloc(1, sizeof(Fnt));  	font->xfont = xfont;  	font->pattern = pattern; @@ -203,6 +176,7 @@ drw_clr_create(Drw *drw, Clr *dest, const char *clrname)  	                       DefaultColormap(drw->dpy, drw->screen),  	                       clrname, dest))  		die("error, cannot allocate color '%s'", clrname); +  	dest->pixel |= 0xff << 24;  } @@ -252,29 +226,32 @@ drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int  int  drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert)  { -	char buf[1024]; -	int ty; -	unsigned int ew; +	int ty, ellipsis_x = 0; +	unsigned int tmpw, ew, ellipsis_w = 0, ellipsis_len, hash, h0, h1;  	XftDraw *d = NULL;  	Fnt *usedfont, *curfont, *nextfont; -	size_t i, len; -	int utf8strlen, utf8charlen, render = x || y || w || h; +	int utf8strlen, utf8charlen, utf8err, render = x || y || w || h;  	long utf8codepoint = 0;  	const char *utf8str;  	FcCharSet *fccharset;  	FcPattern *fcpattern;  	FcPattern *match;  	XftResult result; -	int charexists = 0; +	int charexists = 0, overflow = 0; +	/* keep track of a couple codepoints for which we have no match. */ +	static unsigned int nomatches[128], ellipsis_width, invalid_width; +	static const char invalid[] = "�"; -	if (!drw || (render && !drw->scheme) || !text || !drw->fonts) +	if (!drw || (render && (!drw->scheme || !w)) || !text || !drw->fonts)  		return 0;  	if (!render) { -		w = ~w; +		w = invert ? invert : ~invert;  	} else {  		XSetForeground(drw->dpy, drw->gc, drw->scheme[invert ? ColFg : ColBg].pixel);  		XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h); +		if (w < lpad) +			return x + w;  		d = XftDrawCreate(drw->dpy, drw->drawable,  		                  DefaultVisual(drw->dpy, drw->screen),  		                  DefaultColormap(drw->dpy, drw->screen)); @@ -283,18 +260,40 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp  	}  	usedfont = drw->fonts; +	if (!ellipsis_width && render) +		ellipsis_width = drw_fontset_getwidth(drw, "..."); +	if (!invalid_width && render) +		invalid_width = drw_fontset_getwidth(drw, invalid);  	while (1) { -		utf8strlen = 0; +		ew = ellipsis_len = utf8err = utf8charlen = utf8strlen = 0;  		utf8str = text;  		nextfont = NULL;  		while (*text) { -			utf8charlen = utf8decode(text, &utf8codepoint, UTF_SIZ); +			utf8charlen = utf8decode(text, &utf8codepoint, &utf8err);  			for (curfont = drw->fonts; curfont; curfont = curfont->next) {  				charexists = charexists || XftCharExists(drw->dpy, curfont->xfont, utf8codepoint);  				if (charexists) { -					if (curfont == usedfont) { -						utf8strlen += utf8charlen; +					drw_font_getexts(curfont, text, utf8charlen, &tmpw, NULL); +					if (ew + ellipsis_width <= w) { +						/* keep track where the ellipsis still fits */ +						ellipsis_x = x + ew; +						ellipsis_w = w - ew; +						ellipsis_len = utf8strlen; +					} + +					if (ew + tmpw > w) { +						overflow = 1; +						/* called from drw_fontset_getwidth_clamp(): +						 * it wants the width AFTER the overflow +						 */ +						if (!render) +							x += tmpw; +						else +							utf8strlen = ellipsis_len; +					} else if (curfont == usedfont) {  						text += utf8charlen; +						utf8strlen += utf8err ? 0 : utf8charlen; +						ew += utf8err ? 0 : tmpw;  					} else {  						nextfont = curfont;  					} @@ -302,36 +301,31 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp  				}  			} -			if (!charexists || nextfont) +			if (overflow || !charexists || nextfont || utf8err)  				break;  			else  				charexists = 0;  		}  		if (utf8strlen) { -			drw_font_getexts(usedfont, utf8str, utf8strlen, &ew, NULL); -			/* shorten text if necessary */ -			for (len = MIN(utf8strlen, sizeof(buf) - 1); len && ew > w; len--) -				drw_font_getexts(usedfont, utf8str, len, &ew, NULL); - -			if (len) { -				memcpy(buf, utf8str, len); -				buf[len] = '\0'; -				if (len < utf8strlen) -					for (i = len; i && i > len - 3; buf[--i] = '.') -						; /* NOP */ - -				if (render) { -					ty = y + (h - usedfont->h) / 2 + usedfont->xfont->ascent; -					XftDrawStringUtf8(d, &drw->scheme[invert ? ColBg : ColFg], -					                  usedfont->xfont, x, ty, (XftChar8 *)buf, len); -				} -				x += ew; -				w -= ew; +			if (render) { +				ty = y + (h - usedfont->h) / 2 + usedfont->xfont->ascent; +				XftDrawStringUtf8(d, &drw->scheme[invert ? ColBg : ColFg], +				                  usedfont->xfont, x, ty, (XftChar8 *)utf8str, utf8strlen);  			} +			x += ew; +			w -= ew;  		} +		if (utf8err && (!render || invalid_width < w)) { +			if (render) +				drw_text(drw, x, y, w, h, 0, invalid, invert); +			x += invalid_width; +			w -= invalid_width; +		} +		if (render && overflow) +			drw_text(drw, ellipsis_x, y, ellipsis_w, h, 0, "...", invert); -		if (!*text) { +		if (!*text || overflow) {  			break;  		} else if (nextfont) {  			charexists = 0; @@ -341,6 +335,15 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp  			 * character must be drawn. */  			charexists = 1; +			hash = (unsigned int)utf8codepoint; +			hash = ((hash >> 16) ^ hash) * 0x21F0AAAD; +			hash = ((hash >> 15) ^ hash) * 0xD35A2D97; +			h0 = ((hash >> 15) ^ hash) % LENGTH(nomatches); +			h1 = (hash >> 17) % LENGTH(nomatches); +			/* avoid expensive XftFontMatch call when we know we won't find a match */ +			if (nomatches[h0] == utf8codepoint || nomatches[h1] == utf8codepoint) +				goto no_match; +  			fccharset = FcCharSetCreate();  			FcCharSetAddChar(fccharset, utf8codepoint); @@ -352,7 +355,6 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp  			fcpattern = FcPatternDuplicate(drw->fonts->pattern);  			FcPatternAddCharSet(fcpattern, FC_CHARSET, fccharset);  			FcPatternAddBool(fcpattern, FC_SCALABLE, FcTrue); -			FcPatternAddBool(fcpattern, FC_COLOR, FcFalse);  			FcConfigSubstitute(NULL, fcpattern, FcMatchPattern);  			FcDefaultSubstitute(fcpattern); @@ -369,6 +371,8 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp  					curfont->next = usedfont;  				} else {  					xfont_free(usedfont); +					nomatches[nomatches[h0] ? h1 : h0] = utf8codepoint; +no_match:  					usedfont = drw->fonts;  				}  			} @@ -398,6 +402,15 @@ drw_fontset_getwidth(Drw *drw, const char *text)  	return drw_text(drw, 0, 0, 0, 0, 0, text, 0);  } +unsigned int +drw_fontset_getwidth_clamp(Drw *drw, const char *text, unsigned int n) +{ +	unsigned int tmp = 0; +	if (drw && drw->fonts && text && n) +		tmp = drw_text(drw, 0, 0, 0, 0, 0, text, n); +	return MIN(n, tmp); +} +  void  drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h)  { @@ -35,6 +35,7 @@ void drw_free(Drw *drw);  Fnt *drw_fontset_create(Drw* drw, const char *fonts[], size_t fontcount);  void drw_fontset_free(Fnt* set);  unsigned int drw_fontset_getwidth(Drw *drw, const char *text); +unsigned int drw_fontset_getwidth_clamp(Drw *drw, const char *text, unsigned int n);  void drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h);  /* Colorscheme abstraction */ @@ -110,6 +110,9 @@ Increase master area size.  .B Mod1\-h  Decrease master area size.  .TP +.B Mod1\-o +Select view of the window in focus. The list of tags to be displayed is matched to the window tag list. +.TP  .B Mod1\-Return  Zooms/cycles focused window to/from master area (tiled layouts only).  .TP @@ -143,16 +146,6 @@ View all windows with any tag.  .B Mod1\-Control\-[1..n]  Add/remove all windows with nth tag to/from the view.  .TP -.B Mod1\-- -Decrease the gaps around windows. -.TP -.B Mod1\-= -Increase the gaps around windows. -.TP -.B Mod1\-Shift-= -Reset the gaps around windows to -.BR 0 . -.TP  .B Mod1\-Shift\-q  Quit dwm.  .SS Mouse commands @@ -40,6 +40,12 @@  #include <X11/extensions/Xinerama.h>  #endif /* XINERAMA */  #include <X11/Xft/Xft.h> +#include <X11/Xlib-xcb.h> +#include <xcb/res.h> +#ifdef __OpenBSD__ +#include <sys/sysctl.h> +#include <kvm.h> +#endif /* __OpenBSD */  #include "drw.h"  #include "util.h" @@ -51,7 +57,6 @@                                 * 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) @@ -106,13 +111,15 @@ struct Client {  	int x, y, w, h;  	int sfx, sfy, sfw, sfh; /* stored float geometry, used on mode revert */  	int oldx, oldy, oldw, oldh; -	int basew, baseh, incw, inch, maxw, maxh, minw, minh; +	int basew, baseh, incw, inch, maxw, maxh, minw, minh, hintsvalid;  	int bw, oldbw;  	unsigned int tags; -	unsigned int switchtotag; -	int isfixed, isfloating, isfreesize, isurgent, neverfocus, oldstate, isfullscreen; +	int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen, isterminal, noswallow, isforegrounded; +	pid_t pid;  	Client *next;  	Client *snext; +	Client *tnext; +	Client *swallowing;  	Monitor *mon;  	Window win;  }; @@ -147,6 +154,7 @@ struct Monitor {  	Client *clients;  	Client *sel;  	Client *stack; +	Client *foregrounded;  	Monitor *next;  	Window barwin;  	const Layout *lt[2]; @@ -158,9 +166,9 @@ typedef struct {  	const char *instance;  	const char *title;  	unsigned int tags; -	unsigned int switchtotag;  	int isfloating; -	int isfreesize; +	int isterminal; +	int noswallow;  	int monitor;  } Rule; @@ -179,6 +187,10 @@ static void attach(Client *c);  static void attachBelow(Client *c);  static void attachstack(Client *c);  static void buttonpress(XEvent *e); +static void bstack(Monitor *m); +static void bstackhoriz(Monitor *m); +static void centeredmaster(Monitor *m); +static void centeredfloatingmaster(Monitor *m);  static void checkotherwm(void);  static void cleanup(void);  static void cleanupmon(Monitor *mon); @@ -203,7 +215,7 @@ static void focusstack(const Arg *arg);  static Atom getatomprop(Client *c, Atom prop);  static int getrootptr(int *x, int *y);  static long getstate(Window w); -static unsigned int getsystraywidth(); +static unsigned int getsystraywidth(void);  static int gettextprop(Window w, Atom atom, char *text, unsigned int size);  static void grabbuttons(Client *c, int focused);  static void grabkeys(void); @@ -215,9 +227,10 @@ static void mappingnotify(XEvent *e);  static void maprequest(XEvent *e);  static void monocle(Monitor *m);  static void movemouse(const Arg *arg); +static void movestack(const Arg *arg);  static Client *nexttagged(Client *c);  static Client *nexttiled(Client *c); -static void pop(Client *); +static void nrowgrid(Monitor *m);  static void propertynotify(XEvent *e);  static void quit(const Arg *arg);  static Monitor *recttomon(int x, int y, int w, int h); @@ -241,7 +254,6 @@ 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 Monitor *systraytomon(Monitor *m);  static void switchtag(const Arg *arg); @@ -250,9 +262,10 @@ static void tagmon(const Arg *arg);  static void tagnextmon(const Arg *arg);  static void tagprevmon(const Arg *arg);  static void tagothermon(const Arg *arg, int dir); -static void tile(Monitor *); +static void tile(Monitor *m);  static void togglebar(const Arg *arg);  static void togglefloating(const Arg *arg); +static void toggleforegrounded(const Arg *arg);  static void togglefullscr(const Arg *arg);  static void toggletag(const Arg *arg);  static void toggleview(const Arg *arg); @@ -276,15 +289,17 @@ static void view(const Arg *arg);  static Client *wintoclient(Window w);  static Monitor *wintomon(Window w);  static Client *wintosystrayicon(Window w); +static void winview(const Arg* arg);  static int xerror(Display *dpy, XErrorEvent *ee);  static int xerrordummy(Display *dpy, XErrorEvent *ee);  static int xerrorstart(Display *dpy, XErrorEvent *ee);  static void zoom(const Arg *arg); -static void centeredmaster(Monitor *m); -static void centeredfloatingmaster(Monitor *m); -static void bstack(Monitor *m); -static void bstackhoriz(Monitor *m); -static void stairs(Monitor *m); + +static pid_t getparentprocess(pid_t p); +static int isdescprocess(pid_t p, pid_t c); +static Client *swallowingclient(Window w); +static Client *termforwin(const Client *c); +static pid_t winpid(Window w);  /* variables */  static Systray *systray = NULL; @@ -293,7 +308,7 @@ static const char broken[] = "broken";  static char stext[256];  static int screen;  static int sw, sh;           /* X display screen geometry width, height */ -static int bh, blw = 0;      /* bar geometry */ +static int bh;               /* bar height */  static int lrpad;            /* sum of left and right padding for text */  static int (*xerrorxlib)(Display *, XErrorEvent *);  static unsigned int numlockmask = 0; @@ -316,12 +331,14 @@ static Atom wmatom[WMLast], netatom[NetLast], xatom[XLast];  static int running = 1;  static Cur *cursor[CurLast];  static Clr **scheme; -static Clr **tagscheme;  static Display *dpy;  static Drw *drw;  static Monitor *mons, *selmon;  static Window root, wmcheckwin; +static xcb_connection_t *xcon; + +  /* configuration, allows nested code to access above variables */  #include "config.h" @@ -349,7 +366,6 @@ applyrules(Client *c)  	/* rule matching */  	c->isfloating = 0; -	c->isfreesize = 1;  	c->tags = 0;  	XGetClassHint(dpy, c->win, &ch);  	class    = ch.res_class ? ch.res_class : broken; @@ -361,17 +377,13 @@ applyrules(Client *c)  		&& (!r->class || strstr(class, r->class))  		&& (!r->instance || strstr(instance, r->instance)))  		{ +			c->isterminal = r->isterminal; +			c->noswallow  = r->noswallow;  			c->isfloating = r->isfloating; -			c->isfreesize = r->isfreesize;  			c->tags |= r->tags;  			for (m = mons; m && m->num != r->monitor; m = m->next);  			if (m)  				c->mon = m; -			if (r->switchtotag) { -				Arg a = { .ui = r->tags }; -				c->switchtotag = selmon->tagset[selmon->seltags]; -				view(&a); -			}  		}  	}  	if (ch.res_class) @@ -414,6 +426,8 @@ applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact)  	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 */ @@ -475,18 +489,19 @@ attach(Client *c)  	c->next = c->mon->clients;  	c->mon->clients = c;  } +  void  attachBelow(Client *c)  {  	//If there is nothing on the monitor or the selected client is floating, attach as normal  	if(c->mon->sel == NULL || c->mon->sel->isfloating) { -        Client *at = nexttagged(c); -        if(!at) { -            attach(c); -            return; -            } -        c->next = at->next; -        at->next = c; +		Client *at = nexttagged(c); +		if(!at) { +			attach(c); +			return; +		} +		c->next = at->next; +		at->next = c;  		return;  	} @@ -505,6 +520,68 @@ attachstack(Client *c)  }  void +attachforegrounded (Client *c) +{ +	c->tnext = c->mon->foregrounded; +	c->mon->foregrounded = c; +} + +void +detachforegrounded (Client *c) +{ +	Client **tc; +	for (tc = &c->mon->foregrounded; *tc && *tc != c; tc = &(*tc)->tnext); +	*tc = c->tnext; +} + +void +swallow(Client *p, Client *c) +{ + +	if (c->noswallow || c->isterminal) +		return; +	if (c->noswallow && !swallowfloating && c->isfloating) +		return; + +	detach(c); +	detachstack(c); + +	setclientstate(c, WithdrawnState); +	XUnmapWindow(dpy, p->win); + +	p->swallowing = c; +	c->mon = p->mon; + +	Window w = p->win; +	p->win = c->win; +	c->win = w; +	updatetitle(p); +	XMoveResizeWindow(dpy, p->win, p->x, p->y, p->w, p->h); +	arrange(p->mon); +	configure(p); +	updateclientlist(); +} + +void +unswallow(Client *c) +{ +	c->win = c->swallowing->win; + +	free(c->swallowing); +	c->swallowing = NULL; + +	/* unfullscreen the client */ +	setfullscreen(c, 0); +	updatetitle(c); +	arrange(c->mon); +	XMapWindow(dpy, c->win); +	XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h); +	setclientstate(c, NormalState); +	focus(NULL); +	arrange(c->mon); +} + +void  buttonpress(XEvent *e)  {  	unsigned int i, x, click; @@ -532,7 +609,7 @@ buttonpress(XEvent *e)  		if(i < LENGTH(tags) && (drawtagmask & DRAWCLASSICTAGS)) {  			click = ClkTagBar;  			arg.ui = 1 << i; -		} else if((ev->x < x + columns * bh / tagrows) && (drawtagmask & DRAWTAGGRID) != 0) { +		} else if(ev->x < x + columns * bh / tagrows && (drawtagmask & DRAWTAGGRID)) {  			click = ClkTagBar;  			i = (ev->x - x) / (bh / tagrows);  			i = i + columns * (ev->y / (bh / tagrows)); @@ -541,7 +618,7 @@ buttonpress(XEvent *e)  			}  			arg.ui = 1 << i;  		} -		else if(ev->x < x + blw + columns * bh / tagrows) +		else if (ev->x < x + TEXTW(selmon->ltsymbol) + columns * bh / tagrows)  			click = ClkLtSymbol;  		else if (ev->x > selmon->ww - (int)TEXTW(stext) - getsystraywidth())  			click = ClkStatusText; @@ -559,6 +636,171 @@ buttonpress(XEvent *e)  			buttons[i].func(click == ClkTagBar && buttons[i].arg.i == 0 ? &arg : &buttons[i].arg);  } +static void +bstack(Monitor *m) { +	int w, h, mh, mx, tx, ty, tw; +	unsigned int i, n; +	Client *c; + +	for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); +	if (n == 0) +		return; +	if (n > m->nmaster) { +		mh = m->nmaster ? m->mfact * m->wh : 0; +		tw = m->ww / (n - m->nmaster); +		ty = m->wy + mh; +	} else { +		mh = m->wh; +		tw = m->ww; +		ty = m->wy; +	} +	for (i = mx = 0, tx = m->wx, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) { +		if (i < m->nmaster) { +			w = (m->ww - mx) / (MIN(n, m->nmaster) - i); +			resize(c, m->wx + mx, m->wy, w - (2 * c->bw), mh - (2 * c->bw), 0); +			mx += WIDTH(c); +		} else { +			h = m->wh - mh; +			resize(c, tx, ty, tw - (2 * c->bw), h - (2 * c->bw), 0); +			if (tw != m->ww) +				tx += WIDTH(c); +		} +	} +} + +static void +bstackhoriz(Monitor *m) { +	int w, mh, mx, tx, ty, th; +	unsigned int i, n; +	Client *c; + +	for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); +	if (n == 0) +		return; +	if (n > m->nmaster) { +		mh = m->nmaster ? m->mfact * m->wh : 0; +		th = (m->wh - mh) / (n - m->nmaster); +		ty = m->wy + mh; +	} else { +		th = mh = m->wh; +		ty = m->wy; +	} +	for (i = mx = 0, tx = m->wx, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) { +		if (i < m->nmaster) { +			w = (m->ww - mx) / (MIN(n, m->nmaster) - i); +			resize(c, m->wx + mx, m->wy, w - (2 * c->bw), mh - (2 * c->bw), 0); +			mx += WIDTH(c); +		} else { +			resize(c, tx, ty, m->ww - (2 * c->bw), th - (2 * c->bw), 0); +			if (th != m->wh) +				ty += HEIGHT(c); +		} +	} +} + +void +centeredmaster(Monitor *m) +{ +	unsigned int i, n, h, mw, mx, my, oty, ety, tw; +	Client *c; + +	/* count number of clients in the selected monitor */ +	for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); +	if (n == 0) +		return; + +	/* initialize areas */ +	mw = m->ww; +	mx = 0; +	my = 0; +	tw = mw; + +	if (n > m->nmaster) { +		/* go mfact box in the center if more than nmaster clients */ +		mw = m->nmaster ? m->ww * m->mfact : 0; +		tw = m->ww - mw; + +		if (n - m->nmaster > 1) { +			/* only one client */ +			mx = (m->ww - mw) / 2; +			tw = (m->ww - mw) / 2; +		} +	} + +	oty = 0; +	ety = 0; +	for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) +	if (i < m->nmaster) { +		/* nmaster clients are stacked vertically, in the center +		 * of the screen */ +		h = (m->wh - my) / (MIN(n, m->nmaster) - i); +		resize(c, m->wx + mx, m->wy + my, mw - (2*c->bw), +		       h - (2*c->bw), 0); +		my += HEIGHT(c); +	} else { +		/* stack clients are stacked vertically */ +		if ((i - m->nmaster) % 2 ) { +			h = (m->wh - ety) / ( (1 + n - i) / 2); +			resize(c, m->wx, m->wy + ety, tw - (2*c->bw), +			       h - (2*c->bw), 0); +			ety += HEIGHT(c); +		} else { +			h = (m->wh - oty) / ((1 + n - i) / 2); +			resize(c, m->wx + mx + mw, m->wy + oty, +			       tw - (2*c->bw), h - (2*c->bw), 0); +			oty += HEIGHT(c); +		} +	} +} + +void +centeredfloatingmaster(Monitor *m) +{ +	unsigned int i, n, w, mh, mw, mx, mxo, my, myo, tx; +	Client *c; + +	/* count number of clients in the selected monitor */ +	for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); +	if (n == 0) +		return; + +	/* initialize nmaster area */ +	if (n > m->nmaster) { +		/* go mfact box in the center if more than nmaster clients */ +		if (m->ww > m->wh) { +			mw = m->nmaster ? m->ww * m->mfact : 0; +			mh = m->nmaster ? m->wh * 0.9 : 0; +		} else { +			mh = m->nmaster ? m->wh * m->mfact : 0; +			mw = m->nmaster ? m->ww * 0.9 : 0; +		} +		mx = mxo = (m->ww - mw) / 2; +		my = myo = (m->wh - mh) / 2; +	} else { +		/* go fullscreen if all clients are in the master area */ +		mh = m->wh; +		mw = m->ww; +		mx = mxo = 0; +		my = myo = 0; +	} + +	for(i = tx = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) +	if (i < m->nmaster) { +		/* nmaster clients are stacked horizontally, in the center +		 * of the screen */ +		w = (mw + mxo - mx) / (MIN(n, m->nmaster) - i); +		resize(c, m->wx + mx, m->wy + my, w - (2*c->bw), +		       mh - (2*c->bw), 0); +		mx += WIDTH(c); +	} else { +		/* stack clients are stacked horizontally */ +		w = (m->ww - tx) / (n - i); +		resize(c, m->wx + tx, m->wy, w - (2*c->bw), +		       m->wh - (2*c->bw), 0); +		tx += WIDTH(c); +	} +} +  void  checkotherwm(void)  { @@ -597,6 +839,7 @@ cleanup(void)  		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); @@ -828,6 +1071,8 @@ destroynotify(XEvent *e)  	if ((c = wintoclient(ev->window)))  		unmanage(c, 1); +	else if ((c = swallowingclient(ev->window))) +		unmanage(c->swallowing, 1);  	else if ((c = wintosystrayicon(ev->window))) {  		removesystrayicon(c);  		resizebarwin(selmon); @@ -907,7 +1152,7 @@ drawbar(Monitor *m)  	if (drawtagmask & DRAWCLASSICTAGS)  	for (i = 0; i < LENGTH(tags); i++) {  		w = TEXTW(tags[i]); -		drw_setscheme(drw, (m->tagset[m->seltags] & 1 << i ? tagscheme[i] : scheme[SchemeNorm])); +		drw_setscheme(drw, scheme[m->tagset[m->seltags] & 1 << i ? SchemeSel : SchemeNorm]);  		drw_text(drw, x, 0, w, bh, lrpad / 2, tags[i], urg & 1 << i);  		if (occ & 1 << i)  			drw_rect(drw, x + boxs, boxs, boxw, boxw, @@ -918,7 +1163,7 @@ drawbar(Monitor *m)  	if (drawtagmask & DRAWTAGGRID) {  		drawtaggrid(m,&x,occ);  	} -	w = blw = TEXTW(m->ltsymbol); +	w = TEXTW(m->ltsymbol);  	drw_setscheme(drw, scheme[SchemeNorm]);  	x = drw_text(drw, x, 0, w, bh, lrpad / 2, m->ltsymbol, 0); @@ -945,9 +1190,11 @@ drawbar(Monitor *m)  					continue;  				tw = MIN(m->sel == c ? w : mw, TEXTW(c->name)); -				drw_setscheme(drw, scheme[m == selmon && m->sel == c ? SchemeSel : SchemeNorm]); +				drw_setscheme(drw, scheme[SchemeNorm]);  				if (tw > lrpad / 2) -					drw_text(drw, x, 0, tw, bh, lrpad / 2, c->name, 0); +					drw_text(drw, x, text_ypos, tw, bh, lrpad / 2, c->name, 0); +				drw_setscheme(drw, scheme[m == selmon && m->sel == c ? SchemeSel : SchemeNorm]); +				drw_rect(drw, x , bh - brdsh_ypos , tw , brdsh_w , 1, 1);  				if (c->isfloating)  					drw_rect(drw, x + boxs, boxs, boxw, boxw, c->isfixed, 0);  				x += tw; @@ -969,47 +1216,48 @@ drawbars(void)  		drawbar(m);  } -void drawtaggrid(Monitor *m, int *x_pos, unsigned int occ) +void +drawtaggrid(Monitor *m, int *x_pos, unsigned int occ)  { -    unsigned int x, y, h, max_x, columns; -    int invert, i,j, k; +	unsigned int x, y, h, max_x, columns; +	int invert, i,j, k; -    h = bh / tagrows; -    x = max_x = *x_pos; -    y = 0; -    columns = LENGTH(tags) / tagrows + ((LENGTH(tags) % tagrows > 0) ? 1 : 0); +	h = bh / tagrows; +	x = max_x = *x_pos; +	y = 0; +	columns = LENGTH(tags) / tagrows + ((LENGTH(tags) % tagrows > 0) ? 1 : 0); -    /* Firstly we will fill the borders of squares */ +	/* Firstly we will fill the borders of squares */ -    XSetForeground(drw->dpy, drw->gc, scheme[SchemeNorm][ColBorder].pixel); -    XFillRectangle(dpy, drw->drawable, drw->gc, x, y, h*columns + 1, bh); +	XSetForeground(drw->dpy, drw->gc, scheme[SchemeNorm][ColBorder].pixel); +	XFillRectangle(dpy, drw->drawable, drw->gc, x, y, h*columns + 1, bh); -    /* We will draw LENGTH(tags) squares in tagraws raws. */ +	/* We will draw LENGTH(tags) squares in tagraws raws. */  	for(j = 0,  i= 0; j < tagrows; j++) { -        x = *x_pos; -        for (k = 0; k < columns && i < LENGTH(tags); k++, i++) { -		    invert = m->tagset[m->seltags] & 1 << i ? 0 : 1; - -            /* Select active color for current square */ -            XSetForeground(drw->dpy, drw->gc, !invert ? scheme[SchemeSel][ColBg].pixel : -                                scheme[SchemeNorm][ColFg].pixel); -            XFillRectangle(dpy, drw->drawable, drw->gc, x+1, y+1, h-1, h-1); - -            /* Mark square if tag has client */ -            if (occ & 1 << i) { -                XSetForeground(drw->dpy, drw->gc, !invert ? scheme[SchemeSel][ColFg].pixel : -                                scheme[SchemeNorm][ColBg].pixel); -                XFillRectangle(dpy, drw->drawable, drw->gc, x + 1, y + 1, -                               h / 2, h / 2); -            } -		    x += h; -            if (x > max_x) { -                max_x = x; -            } -        } -        y += h; +		x = *x_pos; +		for (k = 0; k < columns && i < LENGTH(tags); k++, i++) { +			invert = m->tagset[m->seltags] & 1 << i ? 0 : 1; + +			/* Select active color for current square */ +			XSetForeground(drw->dpy, drw->gc, !invert ? scheme[SchemeSel][ColBg].pixel : +				  scheme[SchemeNorm][ColFg].pixel); +			XFillRectangle(dpy, drw->drawable, drw->gc, x+1, y+1, h-1, h-1); + +			/* Mark square if tag has client */ +			if (occ & 1 << i) { +				XSetForeground(drw->dpy, drw->gc, !invert ? scheme[SchemeSel][ColFg].pixel : +				   scheme[SchemeNorm][ColBg].pixel); +				XFillRectangle(dpy, drw->drawable, drw->gc, x + 1, y + 1, +				   h / 2, h / 2); +			} +			x += h; +			if (x > max_x) { +				max_x = x; +			} +		} +		y += h;  	} -    *x_pos = max_x + 1; +	*x_pos = max_x + 1;  }  void @@ -1184,13 +1432,11 @@ gettextprop(Window w, Atom atom, char *text, unsigned int size)  	text[0] = '\0';  	if (!XGetTextProperty(dpy, w, &name, atom) || !name.nitems)  		return 0; -	if (name.encoding == XA_STRING) +	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); -		} +	} 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); @@ -1223,16 +1469,26 @@ grabkeys(void)  {  	updatenumlockmask();  	{ -		unsigned int i, j; +		unsigned int i, j, k;  		unsigned int modifiers[] = { 0, LockMask, numlockmask, numlockmask|LockMask }; -		KeyCode code; +		int start, end, skip; +		KeySym *syms;  		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); +		XDisplayKeycodes(dpy, &start, &end); +		syms = XGetKeyboardMapping(dpy, start, end - start + 1, &skip); +		if (!syms) +			return; +		for (k = start; k <= end; k++) +			for (i = 0; i < LENGTH(keys); i++) +				/* skip modifier codes, we do that ourselves */ +				if (keys[i].keysym == syms[(k - start) * skip]) +					for (j = 0; j < LENGTH(modifiers); j++) +						XGrabKey(dpy, k, +							 keys[i].mod | modifiers[j], +							 root, True, +							 GrabModeAsync, GrabModeAsync); +		XFree(syms);  	}  } @@ -1291,12 +1547,13 @@ killclient(const Arg *arg)  void  manage(Window w, XWindowAttributes *wa)  { -	Client *c, *t = NULL; +	Client *c, *t = NULL, *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; @@ -1311,16 +1568,15 @@ manage(Window w, XWindowAttributes *wa)  	} else {  		c->mon = selmon;  		applyrules(c); +		term = termforwin(c);  	} -	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->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); +	if (c->x + WIDTH(c) > c->mon->wx + c->mon->ww) +		c->x = c->mon->wx + c->mon->ww - WIDTH(c); +	if (c->y + HEIGHT(c) > c->mon->wy + c->mon->wh) +		c->y = c->mon->wy + c->mon->wh - HEIGHT(c); +	c->x = MAX(c->x, c->mon->wx); +	c->y = MAX(c->y, c->mon->wy);  	c->bw = borderpx;  	wc.border_width = c->bw; @@ -1336,7 +1592,6 @@ manage(Window w, XWindowAttributes *wa)  	c->sfy = c->y;  	c->sfw = c->w;  	c->sfh = c->h; -  	XSelectInput(dpy, w, EnterWindowMask|FocusChangeMask|PropertyChangeMask|StructureNotifyMask);  	grabbuttons(c, 0);  	if (!c->isfloating) @@ -1349,11 +1604,15 @@ manage(Window w, XWindowAttributes *wa)  		(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(selmon->sel && selmon->sel->isfullscreen && !c->isfloating) +		setfullscreen(selmon->sel, 0);  	if (c->mon == selmon)  		unfocus(selmon->sel, 0);  	c->mon->sel = c;  	arrange(c->mon);  	XMapWindow(dpy, c->win); +	if (term) +		swallow(term, c);  	focus(NULL);  } @@ -1380,9 +1639,7 @@ maprequest(XEvent *e)  		updatesystray();  	} -	if (!XGetWindowAttributes(dpy, ev->window, &wa)) -		return; -	if (wa.override_redirect) +	if (!XGetWindowAttributes(dpy, ev->window, &wa) || wa.override_redirect)  		return;  	if (!wintoclient(ev->window))  		manage(ev->window, &wa); @@ -1463,6 +1720,55 @@ movemouse(const Arg *arg)  	}  } +void +movestack(const Arg *arg) { +	Client *c = NULL, *p = NULL, *pc = NULL, *i; + +	if(arg->i > 0) { +		/* find the client after selmon->sel */ +		for(c = selmon->sel->next; c && (!ISVISIBLE(c) || c->isfloating); c = c->next); +		if(!c) +			for(c = selmon->clients; c && (!ISVISIBLE(c) || c->isfloating); c = c->next); + +	} +	else { +		/* find the client before selmon->sel */ +		for(i = selmon->clients; i != selmon->sel; i = i->next) +			if(ISVISIBLE(i) && !i->isfloating) +				c = i; +		if(!c) +			for(; i; i = i->next) +				if(ISVISIBLE(i) && !i->isfloating) +					c = i; +	} +	/* find the client before selmon->sel and c */ +	for(i = selmon->clients; i && (!p || !pc); i = i->next) { +		if(i->next == selmon->sel) +			p = i; +		if(i->next == c) +			pc = i; +	} + +	/* swap c and selmon->sel selmon->clients in the selmon->clients list */ +	if(c && c != selmon->sel) { +		Client *temp = selmon->sel->next==c?selmon->sel:selmon->sel->next; +		selmon->sel->next = c->next==selmon->sel?c:c->next; +		c->next = temp; + +		if(p && p != c) +			p->next = c; +		if(pc && pc != selmon->sel) +			pc->next = selmon->sel; + +		if(selmon->sel == selmon->clients) +			selmon->clients = c; +		else if(c == selmon->clients) +			selmon->clients = selmon->sel; + +		arrange(selmon); +	} +} +   Client *  nexttagged(Client *c) {  	Client *walked = c->mon->clients; @@ -1480,13 +1786,90 @@ nexttiled(Client *c)  	return c;  } +Client* +nextforegrounded(Client *c) +{ +	for (; c && (!c->isforegrounded || !ISVISIBLE(c)); c = c->tnext); +	return c; +} +  void -pop(Client *c) +arrangeforegrounded (Monitor *m)  { -	detach(c); -	attach(c); -	focus(c); -	arrange(c->mon); +	unsigned int n,i,x,y,w,h; +	Client *c; + +	for (n = 0, c = nextforegrounded(m->foregrounded); c; c = nextforegrounded(c->tnext), n++); +	if (n == 0) +		return; + +	for (i = 0, c = nextforegrounded(m->foregrounded); c; c = nextforegrounded(c->tnext), i++){ +		if (n == 1) { +			x = m->mx + (m->mw - m->mw * fgw) / 2; +			y = m->my + (m->mh - m->mh * fgh) / 2; +			w = (m->mw * fgw) - (2 * (m->foregrounded->bw)); +			h = (m->mh * fgh) - (2 * (m->foregrounded->bw)); +		} else { +			x = m->mx + (n - 1 - i) * (m->mw / n); +			y = m->my + (m->mh - m->mh * fgh) / 2; +			w = (m->mw * (1 / (float)n)) - (2 * (m->foregrounded->bw)); +			h = (m->mh * fgh) - (2 * (m->foregrounded->bw)); +		} +		resize(c,x,y,w,h,0); +	} +} + +void +nrowgrid(Monitor *m) +{ +	unsigned int n = 0, i = 0, ri = 0, ci = 0;  /* counters */ +	unsigned int cx, cy, cw, ch;                /* client geometry */ +	unsigned int uw = 0, uh = 0, uc = 0;        /* utilization trackers */ +	unsigned int cols, rows = m->nmaster + 1; +	Client *c; + +	/* count clients */ +	for (c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); + +	/* nothing to do here */ +	if (n == 0) +		return; + +	/* force 2 clients to always split vertically */ +	if (FORCE_VSPLIT && n == 2) +		rows = 1; + +	/* never allow empty rows */ +	if (n < rows) +		rows = n; + +	/* define first row */ +	cols = n / rows; +	uc = cols; +	cy = m->wy; +	ch = m->wh / rows; +	uh = ch; + +	for (c = nexttiled(m->clients); c; c = nexttiled(c->next), i++, ci++) { +		if (ci == cols) { +			uw = 0; +			ci = 0; +			ri++; + +			/* next row */ +			cols = (n - uc) / (rows - ri); +			uc += cols; +			cy = m->wy + uh; +			ch = (m->wh - uh) / (rows - ri); +			uh += ch; +		} + +		cx = m->wx + uw; +		cw = (m->ww - uw) / (cols - ci); +		uw += cw; + +		resize(c, cx, cy, cw - 2 * c->bw, ch - 2 * c->bw, 0); +	}  }  void @@ -1520,7 +1903,7 @@ propertynotify(XEvent *e)  				arrange(c->mon);  			break;  		case XA_WM_NORMAL_HINTS: -			updatesizehints(c); +			c->hintsvalid = 0;  			break;  		case XA_WM_HINTS:  			updatewmhints(c); @@ -1879,9 +2262,16 @@ setup(void)  	int i;  	XSetWindowAttributes wa;  	Atom utf8string; +	struct sigaction sa; + +	/* do not transform children into zombies when they terminate */ +	sigemptyset(&sa.sa_mask); +	sa.sa_flags = SA_NOCLDSTOP | SA_NOCLDWAIT | SA_RESTART; +	sa.sa_handler = SIG_IGN; +	sigaction(SIGCHLD, &sa, NULL); -	/* clean up any zombies immediately */ -	sigchld(0); +	/* clean up any zombies (inherited from .xinitrc etc) immediately */ +	while (waitpid(-1, NULL, WNOHANG) > 0);  	/* init screen */  	screen = DefaultScreen(dpy); @@ -1892,7 +2282,7 @@ setup(void)  	if (!drw_fontset_create(drw, fonts, LENGTH(fonts)))  		die("no fonts could be loaded.");  	lrpad = drw->fonts->h; -	bh = user_bh ? user_bh : drw->fonts->h + 2; +	bh = drw->fonts->h + 2;  	updategeom();  	/* init atoms */  	utf8string = XInternAtom(dpy, "UTF8_STRING", False); @@ -1921,14 +2311,9 @@ setup(void)  	cursor[CurResize] = drw_cur_create(drw, XC_sizing);  	cursor[CurMove] = drw_cur_create(drw, XC_fleur);  	/* init appearance */ -	if (LENGTH(tags) > LENGTH(tagsel)) -		die("too few color schemes for the tags");  	scheme = ecalloc(LENGTH(colors), sizeof(Clr *));  	for (i = 0; i < LENGTH(colors); i++)  		scheme[i] = drw_scm_create(drw, colors[i], 3); -	tagscheme = ecalloc(LENGTH(tagsel), sizeof(Clr *)); -	for (i = 0; i < LENGTH(tagsel); i++) -		tagscheme[i] = drw_scm_create(drw, tagsel[i], 2);  	/* init system tray */  	updatesystray();  	/* init bars */ @@ -1957,7 +2342,6 @@ setup(void)  	focus(NULL);  } -  void  seturgent(Client *c, int urg)  { @@ -1988,140 +2372,103 @@ showhide(Client *c)  		XMoveWindow(dpy, c->win, WIDTH(c) * -2, c->y);  	}  } -void switchtag(const Arg *arg) -{ -    unsigned int columns; -    unsigned int new_tagset = 0; -    unsigned int pos, i; -    int col, row; -    Arg new_arg; - -    columns = LENGTH(tags) / tagrows + ((LENGTH(tags) % tagrows > 0) ? 1 : 0); - -    for (i = 0; i < LENGTH(tags); ++i) { -        if (!(selmon->tagset[selmon->seltags] & 1 << i)) { -            continue; -        } -        pos = i; -        row = pos / columns; -        col = pos % columns; -        if (arg->ui & SWITCHTAG_UP) {     /* UP */ -            row --; -            if (row < 0) { -                row = tagrows - 1; -            } -            do { -                pos = row * columns + col; -                row --; -            } while (pos >= LENGTH(tags)); -        } -        if (arg->ui & SWITCHTAG_DOWN) {     /* DOWN */ -            row ++; -            if (row >= tagrows) { -                row = 0; -            } -            pos = row * columns + col; -            if (pos >= LENGTH(tags)) { -                row = 0; -            } -            pos = row * columns + col; -        } -        if (arg->ui & SWITCHTAG_LEFT) {     /* LEFT */ -            col --; -            if (col < 0) { -                col = columns - 1; -            } -            do { -                pos = row * columns + col; -                col --; -            } while (pos >= LENGTH(tags)); -        } -        if (arg->ui & SWITCHTAG_RIGHT) {     /* RIGHT */ -            col ++; -            if (col >= columns) { -                col = 0; -            } -            pos = row * columns + col; -            if (pos >= LENGTH(tags)) { -                col = 0; -                pos = row * columns + col; -            } -        } -        new_tagset |= 1 << pos; -    } -    new_arg.ui = new_tagset; -    if (arg->ui & SWITCHTAG_TOGGLETAG) { -        toggletag(&new_arg); -    } -    if (arg->ui & SWITCHTAG_TAG) { -        tag(&new_arg); -    } -    if (arg->ui & SWITCHTAG_VIEW) { -        view (&new_arg); -    } -    if (arg->ui & SWITCHTAG_TOGGLEVIEW) { -        toggleview (&new_arg); -    } -} - -void -sigchld(int unused) -{ -	if (signal(SIGCHLD, sigchld) == SIG_ERR) -		die("can't install SIGCHLD handler:"); -	while (0 < waitpid(-1, NULL, WNOHANG)); -}  void  spawn(const Arg *arg)  { -	if (arg->v == dmenu_cmd) +	struct sigaction sa; + +	if (arg->v == dmenucmd)  		dmenumon[0] = '0' + selmon->num;  	if (fork() == 0) {  		if (dpy)  			close(ConnectionNumber(dpy));  		setsid(); + +		sigemptyset(&sa.sa_mask); +		sa.sa_flags = 0; +		sa.sa_handler = SIG_DFL; +		sigaction(SIGCHLD, &sa, NULL); +  		execvp(((char **)arg->v)[0], (char **)arg->v); -		fprintf(stderr, "dwm: execvp %s", ((char **)arg->v)[0]); -		perror(" failed"); -		exit(EXIT_SUCCESS); +		die("dwm: execvp '%s' failed:", ((char **)arg->v)[0]);  	}  }  void -stairs(Monitor *m) +switchtag(const Arg *arg)  { -	unsigned int i, n, h, mw, my; -	unsigned int ox, oy, ow, oh; /* stair offset values */ -	Client *c; - -	for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); -	if (n == 0) -		return; +	unsigned int columns; +	unsigned int new_tagset = 0; +	unsigned int pos, i; +	int col, row; +	Arg new_arg; -	if (n > m->nmaster) -		mw = m->nmaster ? m->ww * m->mfact : 0; -	else -		mw = m->ww - m->gappx; +	columns = LENGTH(tags) / tagrows + ((LENGTH(tags) % tagrows > 0) ? 1 : 0); -	for (i = 0, my = m->gappx, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) { -		if (i < m->nmaster) { -			h = (m->wh - my) / (MIN(n, m->nmaster) - i) - m->gappx; -			resize(c, m->wx + m->gappx, m->wy + my, mw - (2 * c->bw) - m->gappx, h - (2 * c->bw), 0); -			if (my + HEIGHT(c) + m->gappx < m->wh) -				my += HEIGHT(c) + m->gappx; -		} else { -			oy = i - m->nmaster; -			ox = stairdirection ? n - i - 1 : (stairsamesize ? i - m->nmaster : 0); -			ow = stairsamesize ? n - m->nmaster - 1 : n - i - 1; -			oh = stairsamesize ? ow : i - m->nmaster; -			resize(c, -			       m->wx + mw + (ox * stairpx) + m->gappx, -			       m->wy + (oy * stairpx) + m->gappx, -			       m->ww - mw - (2 * c->bw) - (ow * stairpx) - (2 * m->gappx), -			       m->wh - (2 * c->bw) - (oh * stairpx) - (2 * m->gappx), -			       0); +	for (i = 0; i < LENGTH(tags); ++i) { +		if (!(selmon->tagset[selmon->seltags] & 1 << i)) { +			continue; +		} +		pos = i; +		row = pos / columns; +		col = pos % columns; +		if (arg->ui & SWITCHTAG_UP) {     /* UP */ +			row --; +			if (row < 0) { +				row = tagrows - 1; +			} +			do { +				pos = row * columns + col; +				row --; +			} while (pos >= LENGTH(tags));  		} +		if (arg->ui & SWITCHTAG_DOWN) {     /* DOWN */ +			row ++; +			if (row >= tagrows) { +				row = 0; +			} +			pos = row * columns + col; +			if (pos >= LENGTH(tags)) { +				row = 0; +			} +			pos = row * columns + col; +		} +		if (arg->ui & SWITCHTAG_LEFT) {     /* LEFT */ +			col --; +			if (col < 0) { +				col = columns - 1; +			} +			do { +				pos = row * columns + col; +				col --; +			} while (pos >= LENGTH(tags)); +		} +		if (arg->ui & SWITCHTAG_RIGHT) {     /* RIGHT */ +			col ++; +			if (col >= columns) { +				col = 0; +			} +			pos = row * columns + col; +			if (pos >= LENGTH(tags)) { +				col = 0; +				pos = row * columns + col; +			} +		} +		new_tagset |= 1 << pos; +	} +	new_arg.ui = new_tagset; +	if (arg->ui & SWITCHTAG_TOGGLETAG) { +		toggletag(&new_arg); +	} +	if (arg->ui & SWITCHTAG_TAG) { +		tag(&new_arg); +	} +	if (arg->ui & SWITCHTAG_VIEW) { +		view (&new_arg); +	} +	if (arg->ui & SWITCHTAG_TOGGLEVIEW) { +		toggleview (&new_arg);  	}  } @@ -2188,7 +2535,7 @@ tile(Monitor *m)  	else  		mw = m->ww - m->gappx;  	for (i = 0, my = ty = m->gappx, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) -		if (i < m->nmaster) { +			if (i < m->nmaster) {  			h = (m->wh - my) / (MIN(n, m->nmaster) - i) - m->gappx;  			resize(c, m->wx + m->gappx, m->wy + my, mw - (2*c->bw) - m->gappx, h - (2*c->bw), 0);  			if (my + HEIGHT(c) + m->gappx < m->wh) @@ -2240,14 +2587,37 @@ togglefloating(const Arg *arg)  		selmon->sel->sfw = selmon->sel->w;  		selmon->sel->sfh = selmon->sel->h;  	} +	if (selmon->sel->isforegrounded) { +		selmon->sel->isforegrounded = 0; +		detachforegrounded(selmon->sel); +		arrangeforegrounded(selmon); +	} +	arrange(selmon); +} + +void +toggleforegrounded(const Arg *arg) +{ +	if (!selmon->sel) +		return; +	if (selmon->sel->isfullscreen) /* no support for fullscreen windows */ +		return; + +	selmon->sel->isforegrounded || selmon->sel->isfloating ? +		detachforegrounded(selmon->sel) : attachforegrounded(selmon->sel); + +	selmon->sel->isforegrounded = selmon->sel->isfloating = +		!selmon->sel->isfloating && !selmon->sel->isforegrounded; + +	arrangeforegrounded(selmon);  	arrange(selmon);  }  void  togglefullscr(const Arg *arg)  { -  if(selmon->sel) -    setfullscreen(selmon->sel, !selmon->sel->isfullscreen); +	if(selmon->sel) +		setfullscreen(selmon->sel, !selmon->sel->isfullscreen);  }  void @@ -2320,12 +2690,33 @@ 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 (c->isforegrounded){ +		detachforegrounded(c); +		arrangeforegrounded(m); +	} +  	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); @@ -2334,12 +2725,11 @@ unmanage(Client *c, int destroyed)  		XUngrabServer(dpy);  	}  	free(c); -	focus(NULL); -	updateclientlist(); -	arrange(m); -	if (c->switchtotag) { -		Arg a = { .ui = c->switchtotag }; -		view(&a); + +	if (!s) { +		arrange(m); +		focus(NULL); +		updateclientlist();  	}  } @@ -2405,7 +2795,7 @@ updatebarpos(Monitor *m)  }  void -updateclientlist() +updateclientlist(void)  {  	Client *c;  	Monitor *m; @@ -2439,43 +2829,43 @@ updategeom(void)  				memcpy(&unique[j++], &info[i], sizeof(XineramaScreenInfo));  		XFree(info);  		nn = j; -		if (n <= nn) { /* new monitors available */ -			for (i = 0; i < (nn - n); i++) { -				for (m = mons; m && m->next; m = m->next); -				if (m) -					m->next = createmon(); -				else -					mons = createmon(); + +		/* 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);  			} -			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); -				} -		} else { /* less monitors available nn < n */ -			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); -					attachBelow(c); -					attachstack(c); -				} -				if (m == selmon) -					selmon = mons; -				cleanupmon(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); +				attachBelow(c); +				attachstack(c);  			} +			if (m == selmon) +				selmon = mons; +			cleanupmon(m);  		}  		free(unique);  	} else @@ -2521,7 +2911,7 @@ updatesizehints(Client *c)  	if (!XGetWMNormalHints(dpy, c->win, &size, &msize))  		/* size is uninitialized, ensure that size.flags aren't used */ -		size.flags = 0; +		size.flags = PSize;  	if (size.flags & PBaseSize) {  		c->basew = size.base_width;  		c->baseh = size.base_height; @@ -2553,18 +2943,15 @@ updatesizehints(Client *c)  		c->maxa = (float)size.max_aspect.x / size.max_aspect.y;  	} else  		c->maxa = c->mina = 0.0; -	if((size.flags & PSize) && c->isfreesize) { -		c->basew = size.base_width; -		c->baseh = size.base_height; -		c->isfloating = 1; -	}  	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) @@ -2707,10 +3094,8 @@ updatewindowtype(Client *c)  	if (state == netatom[NetWMFullscreen])  		setfullscreen(c, 1); -	if (wtype == netatom[NetWMWindowTypeDialog]) { +	if (wtype == netatom[NetWMWindowTypeDialog])  		c->isfloating = 1; -		c->isfreesize = 1; -	}  }  void @@ -2770,6 +3155,137 @@ view(const Arg *arg)  	arrange(selmon);  } +pid_t +winpid(Window w) +{ +	pid_t result = 0; + +#ifdef __linux__ +	xcb_res_client_id_spec_t spec = {0}; +	spec.client = w; +	spec.mask = XCB_RES_CLIENT_ID_MASK_LOCAL_CLIENT_PID; + +	xcb_generic_error_t *e = NULL; +	xcb_res_query_client_ids_cookie_t c = xcb_res_query_client_ids(xcon, 1, &spec); +	xcb_res_query_client_ids_reply_t *r = xcb_res_query_client_ids_reply(xcon, c, &e); + +	if (!r) +		return (pid_t)0; + +	xcb_res_client_id_value_iterator_t i = xcb_res_query_client_ids_ids_iterator(r); +	for (; i.rem; xcb_res_client_id_value_next(&i)) { +		spec = i.data->spec; +		if (spec.mask & XCB_RES_CLIENT_ID_MASK_LOCAL_CLIENT_PID) { +			uint32_t *t = xcb_res_client_id_value_value(i.data); +			result = *t; +			break; +		} +	} + +	free(r); + +	if (result == (pid_t)-1) +		result = 0; + +#endif /* __linux__ */ + +#ifdef __OpenBSD__ +        Atom type; +        int format; +        unsigned long len, bytes; +        unsigned char *prop; +        pid_t ret; + +        if (XGetWindowProperty(dpy, w, XInternAtom(dpy, "_NET_WM_PID", 0), 0, 1, False, AnyPropertyType, &type, &format, &len, &bytes, &prop) != Success || !prop) +               return 0; + +        ret = *(pid_t*)prop; +        XFree(prop); +        result = ret; + +#endif /* __OpenBSD__ */ +	return result; +} + +pid_t +getparentprocess(pid_t p) +{ +	unsigned int v = 0; +	int s; + +#ifdef __linux__ +	FILE *f; +	char buf[256]; +	snprintf(buf, sizeof(buf) - 1, "/proc/%u/stat", (unsigned)p); + +	if (!(f = fopen(buf, "r"))) +		return 0; + +	s = fscanf(f, "%*u %*s %*c %u", &v); +	(void)s; +	fclose(f); +#endif /* __linux__*/ + +#ifdef __OpenBSD__ +	int n; +	kvm_t *kd; +	struct kinfo_proc *kp; + +	kd = kvm_openfiles(NULL, NULL, NULL, KVM_NO_FILES, NULL); +	if (!kd) +		return 0; + +	kp = kvm_getprocs(kd, KERN_PROC_PID, p, sizeof(*kp), &n); +	v = kp->p_ppid; +#endif /* __OpenBSD__ */ + +	return (pid_t)v; +} + +int +isdescprocess(pid_t p, pid_t c) +{ +	while (p != c && c != 0) +		c = getparentprocess(c); + +	return (int)c; +} + +Client * +termforwin(const Client *w) +{ +	Client *c; +	Monitor *m; + +	if (!w->pid || w->isterminal) +		return NULL; + +	for (m = mons; m; m = m->next) { +		for (c = m->clients; c; c = c->next) { +			if (c->isterminal && !c->swallowing && c->pid && isdescprocess(c->pid, w->pid)) +				return c; +		} +	} + +	return NULL; +} + +Client * +swallowingclient(Window w) +{ +	Client *c; +	Monitor *m; + +	for (m = mons; m; m = m->next) { +		for (c = m->clients; c; c = c->next) { +			if (c->swallowing && c->swallowing->win == w) +				return c; +		} +	} + +	return NULL; +} +  Client *  wintoclient(Window w)  { @@ -2810,6 +3326,29 @@ wintomon(Window w)  	return selmon;  } +/* Selects for the view of the focused window. The list of tags */ +/* to be displayed is matched to the focused window tag list. */ +void +winview(const Arg* arg){ +	Window win, win_r, win_p, *win_c; +	unsigned nc; +	int unused; +	Client* c; +	Arg a; + +	if (!XGetInputFocus(dpy, &win, &unused)) +		return; +	while (XQueryTree(dpy, win, &win_r, &win_p, &win_c, &nc) +	       && win_p != win_r) +		win = win_p; + +	if (!(c = wintoclient(win))) +		return; + +	a.ui = c->tags; +	view(&a); +} +  /* 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. */ @@ -2868,8 +3407,7 @@ zoom(const Arg *arg)  	Client *c = selmon->sel;  	Client *at = NULL, *cold, *cprevious = NULL; -	if (!selmon->lt[selmon->sellt]->arrange -	|| (selmon->sel && selmon->sel->isfloating)) +	if (!selmon->lt[selmon->sellt]->arrange || !c || c->isfloating)  		return;  	if (c == nexttiled(selmon->clients)) {  		at = findbefore(prevzoom); @@ -2911,10 +3449,12 @@ main(int argc, char *argv[])  		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();  	setup();  #ifdef __OpenBSD__ -	if (pledge("stdio rpath proc exec", NULL) == -1) +	if (pledge("stdio rpath proc exec ps", NULL) == -1)  		die("pledge");  #endif /* __OpenBSD__ */  	scan(); @@ -2923,168 +3463,3 @@ main(int argc, char *argv[])  	XCloseDisplay(dpy);  	return EXIT_SUCCESS;  } - -static void -bstack(Monitor *m) { -	int w, h, mh, mx, tx, ty, tw; -	unsigned int i, n; -	Client *c; - -	for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); -	if (n == 0) -		return; -	if (n > m->nmaster) { -		mh = m->nmaster ? m->mfact * m->wh : 0; -		tw = m->ww / (n - m->nmaster); -		ty = m->wy + mh; -	} else { -		mh = m->wh; -		tw = m->ww; -		ty = m->wy; -	} -	for (i = mx = 0, tx = m->wx, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) { -		if (i < m->nmaster) { -			w = (m->ww - mx) / (MIN(n, m->nmaster) - i); -			resize(c, m->wx + mx, m->wy, w - (2 * c->bw), mh - (2 * c->bw), 0); -			mx += WIDTH(c); -		} else { -			h = m->wh - mh; -			resize(c, tx, ty, tw - (2 * c->bw), h - (2 * c->bw), 0); -			if (tw != m->ww) -				tx += WIDTH(c); -		} -	} -} - -static void -bstackhoriz(Monitor *m) { -	int w, mh, mx, tx, ty, th; -	unsigned int i, n; -	Client *c; - -	for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); -	if (n == 0) -		return; -	if (n > m->nmaster) { -		mh = m->nmaster ? m->mfact * m->wh : 0; -		th = (m->wh - mh) / (n - m->nmaster); -		ty = m->wy + mh; -	} else { -		th = mh = m->wh; -		ty = m->wy; -	} -	for (i = mx = 0, tx = m->wx, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) { -		if (i < m->nmaster) { -			w = (m->ww - mx) / (MIN(n, m->nmaster) - i); -			resize(c, m->wx + mx, m->wy, w - (2 * c->bw), mh - (2 * c->bw), 0); -			mx += WIDTH(c); -		} else { -			resize(c, tx, ty, m->ww - (2 * c->bw), th - (2 * c->bw), 0); -			if (th != m->wh) -				ty += HEIGHT(c); -		} -	} -} - -void -centeredmaster(Monitor *m) -{ -	unsigned int i, n, h, mw, mx, my, oty, ety, tw; -	Client *c; - -	/* count number of clients in the selected monitor */ -	for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); -	if (n == 0) -		return; - -	/* initialize areas */ -	mw = m->ww; -	mx = 0; -	my = 0; -	tw = mw; - -	if (n > m->nmaster) { -		/* go mfact box in the center if more than nmaster clients */ -		mw = m->nmaster ? m->ww * m->mfact : 0; -		tw = m->ww - mw; - -		if (n - m->nmaster > 1) { -			/* only one client */ -			mx = (m->ww - mw) / 2; -			tw = (m->ww - mw) / 2; -		} -	} - -	oty = 0; -	ety = 0; -	for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) -	if (i < m->nmaster) { -		/* nmaster clients are stacked vertically, in the center -		 * of the screen */ -		h = (m->wh - my) / (MIN(n, m->nmaster) - i); -		resize(c, m->wx + mx, m->wy + my, mw - (2*c->bw), -		       h - (2*c->bw), 0); -		my += HEIGHT(c); -	} else { -		/* stack clients are stacked vertically */ -		if ((i - m->nmaster) % 2 ) { -			h = (m->wh - ety) / ( (1 + n - i) / 2); -			resize(c, m->wx, m->wy + ety, tw - (2*c->bw), -			       h - (2*c->bw), 0); -			ety += HEIGHT(c); -		} else { -			h = (m->wh - oty) / ((1 + n - i) / 2); -			resize(c, m->wx + mx + mw, m->wy + oty, -			       tw - (2*c->bw), h - (2*c->bw), 0); -			oty += HEIGHT(c); -		} -	} -} - -void -centeredfloatingmaster(Monitor *m) -{ -	unsigned int i, n, w, mh, mw, mx, mxo, my, myo, tx; -	Client *c; - -	/* count number of clients in the selected monitor */ -	for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); -	if (n == 0) -		return; - -	/* initialize nmaster area */ -	if (n > m->nmaster) { -		/* go mfact box in the center if more than nmaster clients */ -		if (m->ww > m->wh) { -			mw = m->nmaster ? m->ww * m->mfact : 0; -			mh = m->nmaster ? m->wh * 0.9 : 0; -		} else { -			mh = m->nmaster ? m->wh * m->mfact : 0; -			mw = m->nmaster ? m->ww * 0.9 : 0; -		} -		mx = mxo = (m->ww - mw) / 2; -		my = myo = (m->wh - mh) / 2; -	} else { -		/* go fullscreen if all clients are in the master area */ -		mh = m->wh; -		mw = m->ww; -		mx = mxo = 0; -		my = myo = 0; -	} - -	for(i = tx = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) -	if (i < m->nmaster) { -		/* nmaster clients are stacked horizontally, in the center -		 * of the screen */ -		w = (mw + mxo - mx) / (MIN(n, m->nmaster) - i); -		resize(c, m->wx + mx, m->wy + my, w - (2*c->bw), -		       mh - (2*c->bw), 0); -		mx += WIDTH(c); -	} else { -		/* stack clients are stacked horizontally */ -		w = (m->ww - tx) / (n - i); -		resize(c, m->wx + tx, m->wy, w - (2*c->bw), -		       m->wh - (2*c->bw), 0); -		tx += WIDTH(c); -	} -} diff --git a/movestack.c b/movestack.c deleted file mode 100644 index 8d22a6b..0000000 --- a/movestack.c +++ /dev/null @@ -1,48 +0,0 @@ -void -movestack(const Arg *arg) { -	Client *c = NULL, *p = NULL, *pc = NULL, *i; - -	if(arg->i > 0) { -		/* find the client after selmon->sel */ -		for(c = selmon->sel->next; c && (!ISVISIBLE(c) || c->isfloating); c = c->next); -		if(!c) -			for(c = selmon->clients; c && (!ISVISIBLE(c) || c->isfloating); c = c->next); - -	} -	else { -		/* find the client before selmon->sel */ -		for(i = selmon->clients; i != selmon->sel; i = i->next) -			if(ISVISIBLE(i) && !i->isfloating) -				c = i; -		if(!c) -			for(; i; i = i->next) -				if(ISVISIBLE(i) && !i->isfloating) -					c = i; -	} -	/* find the client before selmon->sel and c */ -	for(i = selmon->clients; i && (!p || !pc); i = i->next) { -		if(i->next == selmon->sel) -			p = i; -		if(i->next == c) -			pc = i; -	} - -	/* swap c and selmon->sel selmon->clients in the selmon->clients list */ -	if(c && c != selmon->sel) { -		Client *temp = selmon->sel->next==c?selmon->sel:selmon->sel->next; -		selmon->sel->next = c->next==selmon->sel?c:c->next; -		c->next = temp; - -		if(p && p != c) -			p->next = c; -		if(pc && pc != selmon->sel) -			pc->next = selmon->sel; - -		if(selmon->sel == selmon->clients) -			selmon->clients = c; -		else if(c == selmon->clients) -			selmon->clients = selmon->sel; - -		arrange(selmon); -	} -} @@ -1,4 +1,5 @@  /* See LICENSE file for copyright and license details. */ +#include <errno.h>  #include <stdarg.h>  #include <stdio.h>  #include <stdlib.h> @@ -6,30 +7,31 @@  #include "util.h" -void * -ecalloc(size_t nmemb, size_t size) -{ -	void *p; - -	if (!(p = calloc(nmemb, size))) -		die("calloc:"); -	return p; -} -  void -die(const char *fmt, ...) { +die(const char *fmt, ...) +{  	va_list ap; +	int saved_errno; + +	saved_errno = errno;  	va_start(ap, fmt);  	vfprintf(stderr, fmt, ap);  	va_end(ap); -	if (fmt[0] && fmt[strlen(fmt)-1] == ':') { -		fputc(' ', stderr); -		perror(NULL); -	} else { -		fputc('\n', stderr); -	} +	if (fmt[0] && fmt[strlen(fmt)-1] == ':') +		fprintf(stderr, " %s", strerror(saved_errno)); +	fputc('\n', stderr);  	exit(1);  } + +void * +ecalloc(size_t nmemb, size_t size) +{ +	void *p; + +	if (!(p = calloc(nmemb, size))) +		die("calloc:"); +	return p; +} @@ -3,6 +3,7 @@  #define MAX(A, B)               ((A) > (B) ? (A) : (B))  #define MIN(A, B)               ((A) < (B) ? (A) : (B))  #define BETWEEN(X, A, B)        ((A) <= (X) && (X) <= (B)) +#define LENGTH(X)               (sizeof (X) / sizeof (X)[0])  void die(const char *fmt, ...);  void *ecalloc(size_t nmemb, size_t size);  | 
