diff options
author | Joe <rbo@gmx.us> | 2024-12-19 15:06:27 +0100 |
---|---|---|
committer | Joe <rbo@gmx.us> | 2024-12-19 15:06:27 +0100 |
commit | 03765f41f101502e9825047419fa9d8667e710ea (patch) | |
tree | cef6445d9c3df3081aed9f8cd28555ecfd88e401 | |
parent | conflict (diff) | |
download | dwm-03765f41f101502e9825047419fa9d8667e710ea.tar.gz dwm-03765f41f101502e9825047419fa9d8667e710ea.tar.bz2 dwm-03765f41f101502e9825047419fa9d8667e710ea.tar.xz dwm-03765f41f101502e9825047419fa9d8667e710ea.tar.zst dwm-03765f41f101502e9825047419fa9d8667e710ea.zip |
6.5
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); |