diff options
Diffstat (limited to '.repos/dwm')
-rw-r--r-- | .repos/dwm/LICENSE | 1 | ||||
-rw-r--r-- | .repos/dwm/Makefile | 10 | ||||
-rw-r--r-- | .repos/dwm/README | 48 | ||||
-rw-r--r-- | .repos/dwm/config.h | 278 | ||||
-rw-r--r-- | .repos/dwm/config.mk | 4 | ||||
-rw-r--r-- | .repos/dwm/drw.c | 17 | ||||
-rw-r--r-- | .repos/dwm/drw.h | 2 | ||||
-rw-r--r-- | .repos/dwm/dwm.1 | 135 | ||||
-rw-r--r-- | .repos/dwm/dwm.c | 558 | ||||
-rw-r--r-- | .repos/dwm/patches/attachbottom.diff | 60 | ||||
-rw-r--r-- | .repos/dwm/patches/horizgrid.diff | 70 | ||||
-rw-r--r-- | .repos/dwm/patches/noborder.diff | 30 | ||||
-rw-r--r-- | .repos/dwm/patches/rotate.diff | 102 | ||||
-rw-r--r-- | .repos/dwm/patches/scratchpad.diff | 90 | ||||
-rw-r--r-- | .repos/dwm/patches/singularborders.diff | 53 | ||||
-rw-r--r-- | .repos/dwm/patches/swallow.diff | 388 | ||||
-rw-r--r-- | .repos/dwm/shiftview.c | 68 | ||||
-rw-r--r-- | .repos/dwm/vanitygaps.c | 542 |
18 files changed, 1247 insertions, 1209 deletions
diff --git a/.repos/dwm/LICENSE b/.repos/dwm/LICENSE index d221f09..1e1b5a4 100644 --- a/.repos/dwm/LICENSE +++ b/.repos/dwm/LICENSE @@ -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> +© 2019-2020 Luke Smith <luke@lukesmith.xyz> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), diff --git a/.repos/dwm/Makefile b/.repos/dwm/Makefile index 77bcbc0..d40c2fc 100644 --- a/.repos/dwm/Makefile +++ b/.repos/dwm/Makefile @@ -19,19 +19,16 @@ options: ${OBJ}: config.h config.mk -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 *.orig *.rej dist: clean mkdir -p dwm-${VERSION} - cp -R LICENSE Makefile README config.def.h config.mk\ - dwm.1 drw.h util.h ${SRC} dwm.png transient.c dwm-${VERSION} + cp -R LICENSE Makefile README config.mk\ + dwm.1 drw.h util.h ${SRC} transient.c dwm-${VERSION} tar -cf dwm-${VERSION}.tar dwm-${VERSION} gzip dwm-${VERSION}.tar rm -rf dwm-${VERSION} @@ -43,6 +40,7 @@ install: all mkdir -p ${DESTDIR}${MANPREFIX}/man1 sed "s/VERSION/${VERSION}/g" < dwm.1 > ${DESTDIR}${MANPREFIX}/man1/dwm.1 chmod 644 ${DESTDIR}${MANPREFIX}/man1/dwm.1 + mkdir -p ${DESTDIR}${PREFIX}/share/dwm uninstall: rm -f ${DESTDIR}${PREFIX}/bin/dwm\ diff --git a/.repos/dwm/README b/.repos/dwm/README deleted file mode 100644 index 95d4fd0..0000000 --- a/.repos/dwm/README +++ /dev/null @@ -1,48 +0,0 @@ -dwm - dynamic window manager -============================ -dwm is an extremely fast, small, and dynamic window manager for X. - - -Requirements ------------- -In order to build dwm you need the Xlib header files. - - -Installation ------------- -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/.repos/dwm/config.h b/.repos/dwm/config.h index a29e174..bd684a2 100644 --- a/.repos/dwm/config.h +++ b/.repos/dwm/config.h @@ -1,39 +1,53 @@ /* See LICENSE file for copyright and license details. */ /* appearance */ -static const unsigned int borderpx = 1; /* border pixel of windows */ -static const unsigned int snap = 16; /* snap pixel */ -static const int showbar = 0; /* 0 means no bar */ -static const int topbar = 1; /* 0 means bottom bar */ -static const char *fonts[] = { "Iosevka Term:pixelsize=14:antialias=true:autohint=true" }; -static const char dmenufont[] = "Iosevka Term:pixelsize=14:antialias=true:autohint=true"; - -static const char col_base00[] = "#282c34"; -static const char col_base01[] = "#353b45"; -static const char col_base02[] = "#3e4451"; -static const char col_base03[] = "#545862"; -static const char col_base04[] = "#565c64"; -static const char col_base05[] = "#abb2bf"; -static const char col_base06[] = "#b6bdca"; -static const char col_base07[] = "#c8ccd4"; -static const char col_base08[] = "#e06c75"; -static const char col_base09[] = "#d19a66"; -static const char col_base0A[] = "#e5c07b"; -static const char col_base0B[] = "#98c379"; -static const char col_base0C[] = "#56b6c2"; -static const char col_base0D[] = "#61afef"; -static const char col_base0E[] = "#c678dd"; -static const char col_base0F[] = "#be5046"; - -static const char *colors[][3] = { +static const unsigned int borderpx = 3; /* border pixel of windows */ +static const unsigned int snap = 32; /* snap pixel */ +static const unsigned int gappih = 20; /* horiz inner gap between windows */ +static const unsigned int gappiv = 10; /* vert inner gap between windows */ +static const unsigned int gappoh = 10; /* horiz outer gap between windows and screen edge */ +static const unsigned int gappov = 30; /* vert outer gap between windows and screen edge */ +static const int swallowfloating = 0; /* 1 means swallow floating windows by default */ +static const int smartgaps = 0; /* 1 means no outer gap when there is only one window */ +static const int showbar = 0; /* 0 means no bar */ +static const int topbar = 1; /* 0 means bottom bar */ +static const char *fonts[] = { "Iosevka Term:pixelsize=14:antialias=true:autohint=true" }; +static char dmenufont[] = "Iosevka Term:pixelsize=14:antialias=true:autohint=true"; + +static const char col_base00[] = "#282c34"; +static const char col_base01[] = "#353b45"; +static const char col_base02[] = "#3e4451"; +static const char col_base03[] = "#545862"; +static const char col_base04[] = "#565c64"; +static const char col_base05[] = "#abb2bf"; +static const char col_base06[] = "#b6bdca"; +static const char col_base07[] = "#c8ccd4"; +static const char col_base08[] = "#e06c75"; +static const char col_base09[] = "#d19a66"; +static const char col_base0A[] = "#e5c07b"; +static const char col_base0B[] = "#98c379"; +static const char col_base0C[] = "#56b6c2"; +static const char col_base0D[] = "#61afef"; +static const char col_base0E[] = "#c678dd"; +static const char col_base0F[] = "#be5046"; + +static const char *colors[][3] = { /* fg bg border */ - [SchemeNorm] = { col_base05, col_base00, col_base00 }, - [SchemeSel] = { col_base05, col_base02, col_base02 }, + [SchemeNorm] = { col_base05, col_base00, col_base02 }, + [SchemeSel] = { col_base05, col_base02, col_base05 }, }; -/* scratchpad */ -static const char scratchpadname[] = "spterm"; -static const char *scratchpadcmd[] = { "st", "-t", scratchpadname, "-g", "120x34", NULL }; +typedef struct { + const char *name; + const void *cmd; +} Sp; +const char *spcmd1[] = { "st", "-n", "spterm", "-g", "120x34", NULL }; +const char *spcmd2[] = { "st", "-n", "spcalc", "-g", "50x20", "-e", "python3", "-q", NULL }; +static Sp scratchpads[] = { + /* name cmd */ + { "spterm", spcmd1 }, + { "spcalc", spcmd2 }, +}; /* tagging */ static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" }; @@ -42,112 +56,146 @@ static const Rule rules[] = { /* xprop(1): * WM_CLASS(STRING) = instance, class * WM_NAME(STRING) = title - */ - /* class instance title tags mask isfloating monitor */ - { "qutebrowser", NULL, NULL, 1 << 0, 0, -1 }, - { "Spotify", NULL, NULL, 1 << 8, 0, -1 }, - { "TelegramDesktop", NULL, NULL, 1 << 7, 0, -1 }, - { "Signal", NULL, NULL, 1 << 7, 0, -1 }, - { "discord", NULL, NULL, 1 << 7, 0, -1 }, - { "Thunderbird", NULL, NULL, 1 << 6, 0, -1 }, - { NULL, NULL, "WhatsApp", 1 << 7, 0, -1 }, - { NULL, NULL, "DISPATCH", 1 << 2, 0, -1 }, - { NULL, "spterm", NULL, 1 << 10, 1, -1 }, - { NULL, NULL, "flterm", 1 << 10, 1, -1 }, + */ + /* class instance title tags mask isfloating isterminal noswallow monitor */ + { "qutebrowser", NULL, NULL, 1 << 0, 0, 0, 0, -1 }, + { "Spotify", NULL, NULL, 1 << 8, 0, 0, 0, -1 }, + { "TelegramDesktop", NULL, NULL, 1 << 7, 0, 0, 0, -1 }, + { "Signal", NULL, NULL, 1 << 7, 0, 0, 0, -1 }, + { "discord", NULL, NULL, 1 << 7, 0, 0, 0, -1 }, + { "Thunderbird", NULL, NULL, 1 << 6, 0, 0, 0, -1 }, + { "St", NULL, NULL, 0, 0, 1, 0, -1 }, + { NULL, "spterm", NULL, SPTAG(0), 1, 1, 0, -1 }, + { NULL, "spcalc", NULL, SPTAG(1), 1, 1, 0, -1 }, + { NULL, NULL, "DISPATCH", 1 << 2, 0, 1, 0, -1 }, + { NULL, NULL, "WhatsApp", 1 << 7, 0, 0, 0, -1 }, }; /* layout(s) */ -static const float mfact = 0.55; /* 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 float mfact = 0.55; /* 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 */ +#define FORCE_VSPLIT 1 /* nrowgrid layout: force two clients to always split vertically */ +#include "vanitygaps.c" static const Layout layouts[] = { /* symbol arrange function */ - { "[T]", tile }, /* first entry is default */ - { "[F]", NULL }, /* no layout function means floating behavior */ - { "[M]", monocle }, + { "[t]", tile }, /* Default: Master on left, slaves on right */ + { "[T]", bstack }, /* Master on top, slaves on bottom */ + + { "[s]", spiral }, /* Fibonacci spiral */ + { "[S]", dwindle }, /* Decreasing in size right and leftward */ + + { "[d]", deck }, /* Master on left, slaves in monocle-like mode on right */ + { "[D]", monocle }, /* All windows on top of eachother */ + + { "[c]", centeredmaster }, /* Master in middle, slaves on sides */ + { "[C]", centeredfloatingmaster }, /* Same but master floats */ + + { "[F]", NULL }, /* no layout function means floating behavior */ + { NULL, NULL }, }; /* key definitions */ #define MODKEY Mod4Mask -#define TAGKEYS(KEY,TAG) \ - { MODKEY, KEY, view, {.ui = 1 << TAG} }, \ - { MODKEY|ControlMask, KEY, toggleview, {.ui = 1 << TAG} }, \ - { MODKEY|ShiftMask, KEY, tag, {.ui = 1 << TAG} }, \ - { MODKEY|ControlMask|ShiftMask, KEY, toggletag, {.ui = 1 << TAG} }, +#define TAGKEYS(KEY, TAG) \ + { MODKEY, KEY, view, { .ui = 1 << TAG } }, \ + { MODKEY | ControlMask, KEY, toggleview, { .ui = 1 << TAG } }, \ + { MODKEY | ShiftMask, KEY, tag, { .ui = 1 << TAG } }, \ + { MODKEY | ControlMask | ShiftMask, KEY, toggletag, { .ui = 1 << TAG } }, +#define STACKKEYS(MOD, ACTION) \ + { MOD, XK_j, ACTION##stack, { .i = INC(+1) } }, \ + { MOD, XK_k, ACTION##stack, { .i = INC(-1) } }, \ + { MOD, \ + XK_v, \ + ACTION##stack, \ + { .i = 0 } }, /* { MOD, XK_grave, ACTION##stack, {.i = PREVSEL } }, \ */ +/* { MOD, XK_a, ACTION##stack, {.i = 1 } }, \ */ +/* { MOD, XK_z, ACTION##stack, {.i = 2 } }, \ */ +/* { MOD, XK_x, ACTION##stack, {.i = -1 } }, */ /* helper for spawning shell commands in the pre dwm-5.0 fashion */ -#define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } } +#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 *dmenucmd[] = { "dmenu_run", "-m", dmenumon, "-fn", dmenufont, "-nb", col_base00, "-nf", col_base05, "-sb", col_base02, "-sf", col_base05, NULL }; -static const char *termcmd[] = { "st", NULL }; -static const char *fltermcmd[] = { "st", "-t", "flterm", "-g", "120x34", NULL }; -static const char *browsercmd[] = { "qutebrowser", NULL }; -static const char *musiccmd[] = { "spotify", NULL }; -static const char *lockcmd[] = { "slock", NULL }; +static const char *dmenucmd[] = { "dmenu_run", "-m", dmenumon, "-fn", dmenufont, + "-nb", col_base00, "-nf", col_base05, "-sb", + col_base02, "-sf", col_base05, NULL }; +static const char *termcmd[] = { "st", NULL }; +#include "shiftview.c" +#include <X11/XF86keysym.h> static Key keys[] = { /* modifier key function argument */ - { MODKEY, XK_p, spawn, {.v = dmenucmd } }, - { MODKEY, XK_Return, spawn, {.v = termcmd } }, - { MODKEY|ShiftMask, XK_Return, spawn, {.v = fltermcmd } }, - { MODKEY|ShiftMask, XK_b, spawn, {.v = browsercmd } }, - { MODKEY|ShiftMask, XK_s, spawn, {.v = musiccmd } }, - { MODKEY|ShiftMask, XK_l, spawn, {.v = lockcmd } }, - { MODKEY|ShiftMask, XK_space, togglescratch, {.v = scratchpadcmd } }, - - { MODKEY|ShiftMask, XK_Return, zoom, {0} }, - { MODKEY, XK_b, togglebar, {0} }, - { MODKEY, XK_j, focusstack, {.i = +1 } }, - { MODKEY, XK_k, focusstack, {.i = -1 } }, - { MODKEY|ShiftMask, XK_j, rotatestack, {.i = +1 } }, - { MODKEY|ShiftMask, XK_k, rotatestack, {.i = -1 } }, - { MODKEY, XK_i, incnmaster, {.i = +1 } }, - { MODKEY, XK_d, incnmaster, {.i = -1 } }, - { MODKEY, XK_h, setmfact, {.f = -0.05} }, - { MODKEY, XK_l, setmfact, {.f = +0.05} }, - { MODKEY, XK_Return, zoom, {0} }, - { MODKEY, XK_Tab, view, {0} }, - { MODKEY, XK_q, killclient, {0} }, - { MODKEY, XK_t, setlayout, {.v = &layouts[0]} }, - { MODKEY, XK_f, setlayout, {.v = &layouts[1]} }, - { MODKEY, XK_m, setlayout, {.v = &layouts[2]} }, - { MODKEY, XK_space, setlayout, {0} }, - { MODKEY, XK_0, view, {.ui = ~0 } }, - { MODKEY|ShiftMask, XK_0, tag, {.ui = ~0 } }, - { MODKEY, XK_comma, focusmon, {.i = -1 } }, - { MODKEY, XK_period, focusmon, {.i = +1 } }, - { MODKEY|ShiftMask, XK_comma, tagmon, {.i = -1 } }, - { MODKEY|ShiftMask, XK_period, tagmon, {.i = +1 } }, - 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|ShiftMask, XK_q, quit, {0} }, + STACKKEYS(MODKEY, focus) STACKKEYS(MODKEY | ShiftMask, push) 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, XK_Tab, view, { 0 } }, + { MODKEY, XK_q, killclient, { 0 } }, + { MODKEY | ShiftMask, XK_b, spawn, SHCMD("$BROWSER") }, + { MODKEY | ShiftMask, XK_r, spawn, SHCMD("st -e htop") }, + { MODKEY, XK_t, setlayout, { .v = &layouts[0] } }, /* tile */ + { MODKEY | ShiftMask, XK_t, setlayout, { .v = &layouts[1] } }, /* bstack */ + { MODKEY, XK_y, setlayout, { .v = &layouts[2] } }, /* spiral */ + { MODKEY | ShiftMask, XK_y, setlayout, { .v = &layouts[3] } }, /* dwindle */ + { MODKEY, XK_u, setlayout, { .v = &layouts[4] } }, /* deck */ + { MODKEY | ShiftMask, XK_u, setlayout, { .v = &layouts[5] } }, /* monocle */ + { MODKEY, XK_i, setlayout, { .v = &layouts[6] } }, /* centeredmaster */ + { MODKEY | ShiftMask, XK_i, setlayout, { .v = &layouts[7] } }, /* centeredfloatingmaster */ + { MODKEY, XK_o, incnmaster, { .i = +1 } }, + { MODKEY | ShiftMask, XK_o, incnmaster, { .i = -1 } }, + { MODKEY, XK_backslash, view, { 0 } }, + + { MODKEY, XK_a, togglegaps, { 0 } }, + { MODKEY | ShiftMask, XK_a, defaultgaps, { 0 } }, + { MODKEY, XK_s, togglesticky, { 0 } }, + { MODKEY, XK_p, spawn, { .v = dmenucmd } }, + { MODKEY, XK_f, togglefullscr, { 0 } }, + { MODKEY | ShiftMask, XK_f, setlayout, { .v = &layouts[8] } }, + { MODKEY, XK_g, shiftview, { .i = -1 } }, + { MODKEY | ShiftMask, XK_g, shifttag, { .i = -1 } }, + { MODKEY, XK_h, setmfact, { .f = -0.05 } }, + /* J and K are automatically bound above in STACKEYS */ + { MODKEY, XK_l, setmfact, { .f = +0.05 } }, + { MODKEY, XK_semicolon, shiftview, { .i = 1 } }, + { MODKEY | ShiftMask, XK_semicolon, shifttag, { .i = 1 } }, + { MODKEY, XK_apostrophe, togglescratch, { .ui = 1 } }, + { MODKEY, XK_Return, spawn, { .v = termcmd } }, + { MODKEY | ShiftMask, XK_Return, togglescratch, { .ui = 0 } }, + + { MODKEY, XK_z, incrgaps, { .i = +3 } }, + { MODKEY, XK_x, incrgaps, { .i = -3 } }, + /* V is automatically bound above in STACKKEYS */ + { MODKEY, XK_b, togglebar, { 0 } }, + + { 0, XF86XK_MonBrightnessUp, spawn, SHCMD("xbacklight -inc 15") }, + { 0, XF86XK_MonBrightnessDown, spawn, SHCMD("xbacklight -dec 15") }, }; /* button definitions */ /* click can be ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, or ClkRootWin */ static Button buttons[] = { /* click event mask button function argument */ - { ClkLtSymbol, 0, Button1, setlayout, {0} }, - { ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]} }, - { ClkWinTitle, 0, Button2, zoom, {0} }, - { ClkStatusText, 0, Button2, spawn, {.v = termcmd } }, - { 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} }, + { ClkWinTitle, 0, Button2, zoom, { 0 } }, + { ClkClientWin, MODKEY, Button1, movemouse, { 0 } }, + { ClkClientWin, MODKEY, Button2, defaultgaps, { 0 } }, + { ClkClientWin, MODKEY, Button3, resizemouse, { 0 } }, + { ClkClientWin, MODKEY, Button4, incrgaps, { .i = +1 } }, + { ClkClientWin, MODKEY, Button5, incrgaps, { .i = -1 } }, + { ClkTagBar, 0, Button1, view, { 0 } }, + { ClkTagBar, 0, Button3, toggleview, { 0 } }, + { ClkTagBar, MODKEY, Button1, tag, { 0 } }, + { ClkTagBar, MODKEY, Button3, toggletag, { 0 } }, + { ClkTagBar, 0, Button4, shiftview, { .i = -1 } }, + { ClkTagBar, 0, Button5, shiftview, { .i = 1 } }, + { ClkRootWin, 0, Button2, togglebar, { 0 } }, }; - diff --git a/.repos/dwm/config.mk b/.repos/dwm/config.mk index 6d36cb7..b77641d 100644 --- a/.repos/dwm/config.mk +++ b/.repos/dwm/config.mk @@ -22,10 +22,10 @@ FREETYPEINC = /usr/include/freetype2 # 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 # flags -CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_POSIX_C_SOURCE=2 -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS} +CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_POSIX_C_SOURCE=200809L -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS} #CFLAGS = -g -std=c99 -pedantic -Wall -O0 ${INCS} ${CPPFLAGS} CFLAGS = -std=c99 -pedantic -Wall -Wno-deprecated-declarations -Os ${INCS} ${CPPFLAGS} LDFLAGS = ${LIBS} diff --git a/.repos/dwm/drw.c b/.repos/dwm/drw.c index 8fd1ca4..9617d84 100644 --- a/.repos/dwm/drw.c +++ b/.repos/dwm/drw.c @@ -132,19 +132,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; @@ -202,12 +189,14 @@ 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; } /* Wrapper to create color schemes. The caller has to call free(3) on the * returned color scheme when done using it. */ Clr * -drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount) +drw_scm_create(Drw *drw, char *clrnames[], size_t clrcount) { size_t i; Clr *ret; diff --git a/.repos/dwm/drw.h b/.repos/dwm/drw.h index 4bcd5ad..42b04ce 100644 --- a/.repos/dwm/drw.h +++ b/.repos/dwm/drw.h @@ -39,7 +39,7 @@ void drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned in /* Colorscheme abstraction */ void drw_clr_create(Drw *drw, Clr *dest, const char *clrname); -Clr *drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount); +Clr *drw_scm_create(Drw *drw, char *clrnames[], size_t clrcount); /* Cursor abstraction */ Cur *drw_cur_create(Drw *drw, int shape); diff --git a/.repos/dwm/dwm.1 b/.repos/dwm/dwm.1 index 13b3729..0677f31 100644 --- a/.repos/dwm/dwm.1 +++ b/.repos/dwm/dwm.1 @@ -1,21 +1,16 @@ .TH DWM 1 dwm\-VERSION .SH NAME -dwm \- dynamic window manager +dwm \- dynamic window manager (Luke Smith <https://lukesmith.xyz>'s build) .SH SYNOPSIS .B dwm .RB [ \-v ] .SH DESCRIPTION -dwm is a dynamic window manager for X. It manages windows in tiled, monocle -and floating layouts. Either layout can be applied dynamically, optimising the -environment for the application in use and the task performed. +dwm is a dynamic window manager for X. .P -In tiled layouts windows are managed in a master and stacking area. The master -area on the left contains one window by default, and the stacking area on the -right contains all other windows. The number of master area windows can be -adjusted from zero to an arbitrary number. In monocle layout all windows are -maximised to the screen size. In floating layout windows can be resized and -moved freely. Dialog windows are always managed floating, regardless of the -layout applied. +dwm "orders" windows based on recency and primacy, while dwm layouts may +change, the most recent "master" window is shown in the most prominent +position. There are bindings for cycling through and promoting windows to the +master position. .P Windows are grouped by tags. Each window can be tagged with one or multiple tags. Selecting certain tags displays all windows with these tags. @@ -30,6 +25,15 @@ top left corner. The tags which are applied to one or more windows are indicated with an empty square in the top left corner. .P dwm draws a small border around windows to indicate the focus state. +.P +.I +libxft-bgra +should be installed for this build of dwm. Arch users may install it via the +AUR. Color characters and emoji are enabled, but these will cause crashes +without the fix +.I +libxft-bgra +offers. .SH OPTIONS .TP .B \-v @@ -42,119 +46,120 @@ is read and displayed in the status text area. It can be set with the .BR xsetroot (1) command. .TP -.B Button1 +.B Left click click on a tag label to display all windows with that tag, click on the layout label toggles between tiled and floating layout. .TP -.B Button3 +.B Right click click on a tag label adds/removes all windows with that tag to/from the view. .TP -.B Mod1\-Button1 +.B Super\-Left click click on a tag label applies that tag to the focused window. .TP -.B Mod1\-Button3 +.B Super\-Right click click on a tag label adds/removes that tag to/from the focused window. .SS Keyboard commands .TP -.B Mod1\-Shift\-Return -Start +.B Super\-Return +Start terminal, .BR st(1). .TP -.B Mod1\-p +.B Super\-d Spawn .BR dmenu(1) for launching other programs. .TP -.B Mod1\-, -Focus previous screen, if any. -.TP -.B Mod1\-. -Focus next screen, if any. +.B Super\-b +Toggles bar on and off. .TP -.B Mod1\-Shift\-, -Send focused window to previous screen, if any. +.B Super\-q +Close focused window. .TP -.B Mod1\-Shift\-. -Send focused window to next screen, if any. +.B Super\-t/T +Sets tiled/bstack layouts. .TP -.B Mod1\-b -Toggles bar on and off. +.B Super\-f +Toggle fullscreen window. .TP -.B Mod1\-t -Sets tiled layout. +.B Super\-F +Toggle floating layout. .TP -.B Mod1\-f -Sets floating layout. +.B Super\-y/Y +Sets Fibonacci spiral/dwinde layouts. .TP -.B Mod1\-m -Sets monocle layout. +.B Super\-u/U +Sets centered master layout. .TP -.B Mod1\-space -Toggles between current and previous layout. +.B Super\-i/I +Sets centered master or floating master layouts. .TP -.B Mod1\-j -Focus next window. +.B Super\-space +Zooms/cycles focused window to/from master area. .TP -.B Mod1\-k -Focus previous window. +.B Super\-j/k +Focus next/previous window. .TP -.B Mod1\-i -Increase number of windows in master area. +.B Super\-Shift\-j/k +Move selected window down/up in stack. .TP -.B Mod1\-d -Decrease number of windows in master area. +.B Super\-o/O +Increase/decrease number of windows in master area. .TP -.B Mod1\-l +.B Super\-l Increase master area size. .TP -.B Mod1\-h +.B Super\-h Decrease master area size. .TP -.B Mod1\-Return -Zooms/cycles focused window to/from master area (tiled layouts only). -.TP -.B Mod1\-Shift\-c -Close focused window. -.TP -.B Mod1\-Shift\-space +.B Super\-Shift\-space Toggle focused window between tiled and floating state. .TP -.B Mod1\-Tab +.B Super\-Tab Toggles to the previously selected tags. .TP -.B Mod1\-Shift\-[1..n] +.B Super\-Shift\-[1..n] Apply nth tag to focused window. .TP -.B Mod1\-Shift\-0 +.B Super\-Shift\-0 Apply all tags to focused window. .TP -.B Mod1\-Control\-Shift\-[1..n] +.B Super\-Control\-Shift\-[1..n] Add/remove nth tag to/from focused window. .TP -.B Mod1\-[1..n] +.B Super\-[1..n] View all windows with nth tag. .TP -.B Mod1\-0 +.B Super\-0 View all windows with any tag. .TP -.B Mod1\-Control\-[1..n] +.B Super\-Control\-[1..n] Add/remove all windows with nth tag to/from the view. .TP -.B Mod1\-Shift\-q +.B Super\-Shift\-q Quit dwm. +.TP +.B Mod1\-Control\-Shift\-q +Menu to refresh/quit/reboot/shutdown. .SS Mouse commands .TP -.B Mod1\-Button1 +.B Super\-Left click Move focused window while dragging. Tiled windows will be toggled to the floating state. .TP -.B Mod1\-Button2 +.B Super\-Middle click Toggles focused window between floating and tiled state. .TP -.B Mod1\-Button3 +.B Super\-Right click Resize focused window while dragging. Tiled windows will be toggled to the floating state. .SH CUSTOMIZATION dwm is customized by creating a custom config.h and (re)compiling the source code. This keeps it fast, secure and simple. +.SH SIGNALS +.TP +.B SIGHUP - 1 +Restart the dwm process. +.TP +.B SIGTERM - 15 +Cleanly terminate the dwm process. .SH SEE ALSO .BR dmenu (1), .BR st (1) diff --git a/.repos/dwm/dwm.c b/.repos/dwm/dwm.c index accc70b..f08efb0 100644 --- a/.repos/dwm/dwm.c +++ b/.repos/dwm/dwm.c @@ -35,11 +35,14 @@ #include <X11/Xatom.h> #include <X11/Xlib.h> #include <X11/Xproto.h> +#include <X11/Xresource.h> #include <X11/Xutil.h> #ifdef XINERAMA #include <X11/extensions/Xinerama.h> #endif /* XINERAMA */ #include <X11/Xft/Xft.h> +#include <X11/Xlib-xcb.h> +#include <xcb/res.h> #include "drw.h" #include "util.h" @@ -47,15 +50,24 @@ /* macros */ #define BUTTONMASK (ButtonPressMask|ButtonReleaseMask) #define CLEANMASK(mask) (mask & ~(numlockmask|LockMask) & (ShiftMask|ControlMask|Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask)) +#define GETINC(X) ((X) - 2000) +#define INC(X) ((X) + 2000) #define INTERSECT(x,y,w,h,m) (MAX(0, MIN((x)+(w),(m)->wx+(m)->ww) - MAX((x),(m)->wx)) \ * MAX(0, MIN((y)+(h),(m)->wy+(m)->wh) - MAX((y),(m)->wy))) -#define ISVISIBLE(C) ((C->tags & C->mon->tagset[C->mon->seltags])) +#define ISINC(X) ((X) > 1000 && (X) < 3000) +#define ISVISIBLE(C) ((C->tags & C->mon->tagset[C->mon->seltags]) || C->issticky) +#define PREVSEL 3000 #define LENGTH(X) (sizeof X / sizeof X[0]) #define MOUSEMASK (BUTTONMASK|PointerMotionMask) +#define MOD(N,M) ((N)%(M) < 0 ? (N)%(M) + (M) : (N)%(M)) #define WIDTH(X) ((X)->w + 2 * (X)->bw) #define HEIGHT(X) ((X)->h + 2 * (X)->bw) -#define TAGMASK ((1 << LENGTH(tags)) - 1) +#define NUMTAGS (LENGTH(tags) + LENGTH(scratchpads)) +#define TAGMASK ((1 << NUMTAGS) - 1) +#define SPTAG(i) ((1 << LENGTH(tags)) << (i)) +#define SPTAGMASK (((1 << LENGTH(scratchpads))-1) << LENGTH(tags)) #define TEXTW(X) (drw_fontset_getwidth(drw, (X)) + lrpad) +#define TRUNC(X,A,B) (MAX((A), MIN((X), (B)))) /* enums */ enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */ @@ -92,9 +104,11 @@ 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, isurgent, neverfocus, oldstate, isfullscreen, isterminal, noswallow, issticky; + pid_t pid; Client *next; Client *snext; + Client *swallowing; Monitor *mon; Window win; }; @@ -119,6 +133,10 @@ struct Monitor { int by; /* bar geometry */ int mx, my, mw, mh; /* screen size */ int wx, wy, ww, wh; /* window area */ + int gappih; /* horizontal gap between windows */ + int gappiv; /* vertical gap between windows */ + int gappoh; /* horizontal outer gaps */ + int gappov; /* vertical outer gaps */ unsigned int seltags; unsigned int sellt; unsigned int tagset[2]; @@ -138,6 +156,8 @@ typedef struct { const char *title; unsigned int tags; int isfloating; + int isterminal; + int noswallow; int monitor; } Rule; @@ -156,6 +176,7 @@ static void clientmessage(XEvent *e); static void configure(Client *c); static void configurenotify(XEvent *e); static void configurerequest(XEvent *e); +static void copyvalidchars(char *text, char *rawtext); static Monitor *createmon(void); static void destroynotify(XEvent *e); static void detach(Client *c); @@ -163,14 +184,13 @@ static void detachstack(Client *c); static Monitor *dirtomon(int dir); static void drawbar(Monitor *m); static void drawbars(void); -static void enqueue(Client *c); -static void enqueuestack(Client *c); static void enternotify(XEvent *e); static void expose(XEvent *e); static void focus(Client *c); static void focusin(XEvent *e); static void focusmon(const Arg *arg); static void focusstack(const Arg *arg); +static Atom getatomprop(Client *c, Atom prop); static int getrootptr(int *x, int *y); static long getstate(Window w); static int gettextprop(Window w, Atom atom, char *text, unsigned int size); @@ -188,13 +208,13 @@ static void movemouse(const Arg *arg); static Client *nexttiled(Client *c); static void pop(Client *); static void propertynotify(XEvent *e); +static void pushstack(const Arg *arg); static void quit(const Arg *arg); static Monitor *recttomon(int x, int y, int w, int h); static void resize(Client *c, int x, int y, int w, int h, int interact); static void resizeclient(Client *c, int x, int y, int w, int h); static void resizemouse(const Arg *arg); static void restack(Monitor *m); -static void rotatestack(const Arg *arg); static void run(void); static void scan(void); static int sendevent(Client *c, Atom proto); @@ -208,13 +228,17 @@ static void setup(void); static void seturgent(Client *c, int urg); static void showhide(Client *c); static void sigchld(int unused); +static void sighup(int unused); +static void sigterm(int unused); static void spawn(const Arg *arg); +static int stackpos(const Arg *arg); static void tag(const Arg *arg); static void tagmon(const Arg *arg); -static void tile(Monitor *); static void togglebar(const Arg *arg); static void togglefloating(const Arg *arg); static void togglescratch(const Arg *arg); +static void togglesticky(const Arg *arg); +static void togglefullscr(const Arg *arg); static void toggletag(const Arg *arg); static void toggleview(const Arg *arg); static void unfocus(Client *c, int setfocus); @@ -238,9 +262,17 @@ 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]; +static char rawstext[256]; static int screen; static int sw, sh; /* X display screen geometry width, height */ static int bh, blw = 0; /* bar geometry */ @@ -264,6 +296,7 @@ static void (*handler[LASTEvent]) (XEvent *) = { [UnmapNotify] = unmapnotify }; static Atom wmatom[WMLast], netatom[NetLast]; +static int restart = 0; static int running = 1; static Cur *cursor[CurLast]; static Clr **scheme; @@ -272,11 +305,11 @@ 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" -static unsigned int scratchtag = 1 << LENGTH(tags); - /* compile-time check if all tags fit into an unsigned int bit array. */ struct NumTags { char limitexceeded[LENGTH(tags) > 31 ? -1 : 1]; }; @@ -303,8 +336,15 @@ applyrules(Client *c) && (!r->class || strstr(class, r->class)) && (!r->instance || strstr(instance, r->instance))) { + c->isterminal = r->isterminal; c->isfloating = r->isfloating; + c->noswallow = r->noswallow; c->tags |= r->tags; + if ((r->tags & SPTAGMASK) && r->isfloating) { + c->x = c->mon->wx + (c->mon->ww / 2 - WIDTH(c) / 2); + c->y = c->mon->wy + (c->mon->wh / 2 - HEIGHT(c) / 2); + } + for (m = mons; m && m->num != r->monitor; m = m->next); if (m) c->mon = m; @@ -314,7 +354,7 @@ applyrules(Client *c) XFree(ch.res_class); if (ch.res_name) XFree(ch.res_name); - c->tags = c->tags & TAGMASK ? c->tags & TAGMASK : c->mon->tagset[c->mon->seltags]; + c->tags = c->tags & TAGMASK ? c->tags & TAGMASK : (c->mon->tagset[c->mon->seltags] & ~SPTAGMASK); } int @@ -420,9 +460,55 @@ attachstack(Client *c) } void +swallow(Client *p, Client *c) +{ + if (c->noswallow || c->isterminal) + return; + if (!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; + unsigned int i, x, click, occ = 0; Arg arg = {0}; Client *c; Monitor *m; @@ -437,17 +523,37 @@ buttonpress(XEvent *e) } if (ev->window == selmon->barwin) { i = x = 0; - do + for (c = m->clients; c; c = c->next) + occ |= c->tags == 255 ? 0 : c->tags; + do { + /* do not reserve space for vacant tags */ + if (!(occ & 1 << i || m->tagset[m->seltags] & 1 << i)) + continue; x += TEXTW(tags[i]); - while (ev->x >= x && ++i < LENGTH(tags)); + } while (ev->x >= x && ++i < LENGTH(tags)); if (i < LENGTH(tags)) { click = ClkTagBar; arg.ui = 1 << i; } else if (ev->x < x + blw) click = ClkLtSymbol; - else if (ev->x > selmon->ww - TEXTW(stext)) + else if (ev->x > (x = selmon->ww - TEXTW(stext) + lrpad)) { click = ClkStatusText; - else + + char *text = rawstext; + int i = -1; + char ch; + while (text[++i]) { + if ((unsigned char)text[i] < ' ') { + ch = text[i]; + text[i] = '\0'; + x += TEXTW(text) - lrpad; + text[i] = ch; + text += i+1; + i = -1; + if (x >= ev->x) break; + } + } + } else click = ClkWinTitle; } else if ((c = wintoclient(ev->window))) { focus(c); @@ -633,6 +739,19 @@ configurerequest(XEvent *e) XSync(dpy, False); } +void +copyvalidchars(char *text, char *rawtext) +{ + int i = -1, j = 0; + + while(rawtext[++i]) { + if ((unsigned char)rawtext[i] >= ' ') { + text[j++] = rawtext[i]; + } + } + text[j] = '\0'; +} + Monitor * createmon(void) { @@ -644,6 +763,10 @@ createmon(void) m->nmaster = nmaster; m->showbar = showbar; m->topbar = topbar; + m->gappih = gappih; + m->gappiv = gappiv; + m->gappoh = gappoh; + m->gappov = gappov; m->lt[0] = &layouts[0]; m->lt[1] = &layouts[1 % LENGTH(layouts)]; strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol); @@ -658,6 +781,9 @@ destroynotify(XEvent *e) if ((c = wintoclient(ev->window))) unmanage(c, 1); + + else if ((c = swallowingclient(ev->window))) + unmanage(c->swallowing, 1); } void @@ -701,7 +827,7 @@ dirtomon(int dir) void drawbar(Monitor *m) { - int x, w, sw = 0; + int x, w, tw = 0; int boxs = drw->fonts->h / 9; int boxw = drw->fonts->h / 6 + 2; unsigned int i, occ = 0, urg = 0; @@ -710,31 +836,31 @@ drawbar(Monitor *m) /* draw status first so it can be overdrawn by tags later */ if (m == selmon) { /* status is only drawn on selected monitor */ drw_setscheme(drw, scheme[SchemeNorm]); - sw = TEXTW(stext) - lrpad + 2; /* 2px right padding */ - drw_text(drw, m->ww - sw, 0, sw, bh, 0, stext, 0); + tw = TEXTW(stext) - lrpad + 2; /* 2px right padding */ + drw_text(drw, m->ww - tw, 0, tw, bh, 0, stext, 0); } for (c = m->clients; c; c = c->next) { - occ |= c->tags; + occ |= c->tags == 255 ? 0 : c->tags; if (c->isurgent) urg |= c->tags; } x = 0; for (i = 0; i < LENGTH(tags); i++) { + /* do not draw vacant tags */ + if (!(occ & 1 << i || m->tagset[m->seltags] & 1 << i)) + continue; + w = TEXTW(tags[i]); 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, - m == selmon && selmon->sel && selmon->sel->tags & 1 << i, - urg & 1 << i); x += w; } w = blw = TEXTW(m->ltsymbol); drw_setscheme(drw, scheme[SchemeNorm]); x = drw_text(drw, x, 0, w, bh, lrpad / 2, m->ltsymbol, 0); - if ((w = m->ww - sw - x) > bh) { + 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); @@ -758,28 +884,6 @@ drawbars(void) } void -enqueue(Client *c) -{ - Client *l; - for (l = c->mon->clients; l && l->next; l = l->next); - if (l) { - l->next = c; - c->next = NULL; - } -} - -void -enqueuestack(Client *c) -{ - Client *l; - for (l = c->mon->stack; l && l->snext; l = l->snext); - if (l) { - l->snext = c; - c->snext = NULL; - } -} - -void enternotify(XEvent *e) { Client *c; @@ -811,8 +915,6 @@ expose(XEvent *e) void focus(Client *c) { - XWindowChanges wc; - if (!c || !ISVISIBLE(c)) for (c = selmon->stack; c && !ISVISIBLE(c); c = c->snext); if (selmon->sel && selmon->sel != c) @@ -826,11 +928,6 @@ focus(Client *c) attachstack(c); grabbuttons(c, 1); XSetWindowBorder(dpy, c->win, scheme[SchemeSel][ColBorder].pixel); - if(!c->isfloating) { - wc.sibling = selmon->barwin; - wc.stack_mode = Below; - XConfigureWindow(dpy, c->win, CWSibling | CWStackMode, &wc); - } setfocus(c); } else { XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime); @@ -867,27 +964,16 @@ focusmon(const Arg *arg) void focusstack(const Arg *arg) { - Client *c = NULL, *i; + int i = stackpos(arg); + Client *c, *p; - if (!selmon->sel) + if (i < 0 || !selmon->sel || selmon->sel->isfullscreen) return; - if (arg->i > 0) { - for (c = selmon->sel->next; c && !ISVISIBLE(c); c = c->next); - if (!c) - for (c = selmon->clients; c && !ISVISIBLE(c); c = c->next); - } else { - for (i = selmon->clients; i != selmon->sel; i = i->next) - if (ISVISIBLE(i)) - c = i; - if (!c) - for (; i; i = i->next) - if (ISVISIBLE(i)) - c = i; - } - if (c) { - focus(c); - restack(selmon); - } + + for(p = NULL, c = selmon->clients; c && (i || !ISVISIBLE(c)); + i -= ISVISIBLE(c) ? 1 : 0, p = c, c = c->next); + focus(c ? c : p); + restack(selmon); } Atom @@ -1052,12 +1138,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; @@ -1072,6 +1159,7 @@ 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) @@ -1084,14 +1172,6 @@ manage(Window w, XWindowAttributes *wa) && (c->x + (c->w / 2) < c->mon->wx + c->mon->ww)) ? bh : c->mon->my); c->bw = borderpx; - selmon->tagset[selmon->seltags] &= ~scratchtag; - if (!strcmp(c->name, scratchpadname)) { - c->mon->tagset[c->mon->seltags] |= c->tags = scratchtag; - c->isfloating = True; - c->x = c->mon->wx + (c->mon->ww / 2 - WIDTH(c) / 2); - c->y = c->mon->wy + (c->mon->wh / 2 - HEIGHT(c) / 2); - } - wc.border_width = c->bw; XConfigureWindow(dpy, w, CWBorderWidth, &wc); XSetWindowBorder(dpy, w, scheme[SchemeNorm][ColBorder].pixel); @@ -1116,6 +1196,8 @@ manage(Window w, XWindowAttributes *wa) c->mon->sel = c; arrange(c->mon); XMapWindow(dpy, c->win); + if (term) + swallow(term, c); focus(NULL); } @@ -1146,16 +1228,16 @@ maprequest(XEvent *e) void monocle(Monitor *m) { - unsigned int n = 0; + unsigned int n; + int oh, ov, ih, iv; Client *c; - for (c = m->clients; c; c = c->next) - if (ISVISIBLE(c)) - n++; + getgaps(m, &oh, &ov, &ih, &iv, &n); + if (n > 0) /* override layout symbol */ snprintf(m->ltsymbol, sizeof m->ltsymbol, "[%d]", n); for (c = nexttiled(m->clients); c; c = nexttiled(c->next)) - resize(c, m->wx - c->bw, m->wy, m->ww, m->wh, False); + resize(c, m->wx + ov, m->wy + oh, m->ww - 2 * c->bw - 2 * ov, m->wh - 2 * c->bw - 2 * oh, 0); } void @@ -1252,17 +1334,40 @@ pop(Client *c) } void +pushstack(const Arg *arg) { + int i = stackpos(arg); + Client *sel = selmon->sel, *c, *p; + + if(i < 0 || !sel) + return; + else if(i == 0) { + detach(sel); + attach(sel); + } + else { + for(p = NULL, c = selmon->clients; c; p = c, c = c->next) + if(!(i -= (ISVISIBLE(c) && c != sel))) + break; + c = c ? c : p; + detach(sel); + sel->next = c->next; + c->next = sel; + } + arrange(selmon); +} + +void propertynotify(XEvent *e) { Client *c; Window trans; XPropertyEvent *ev = &e->xproperty; - if ((ev->window == root) && (ev->atom == XA_WM_NAME)) + if ((ev->window == root) && (ev->atom == XA_WM_NAME)) { updatestatus(); - else if (ev->state == PropertyDelete) + } else if (ev->state == PropertyDelete) { return; /* ignore */ - else if ((c = wintoclient(ev->window))) { + } else if ((c = wintoclient(ev->window))) { switch(ev->atom) { default: break; case XA_WM_TRANSIENT_FOR: @@ -1291,6 +1396,7 @@ propertynotify(XEvent *e) void quit(const Arg *arg) { + if(arg->i) restart = 1; running = 0; } @@ -1325,13 +1431,6 @@ 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); @@ -1420,38 +1519,6 @@ restack(Monitor *m) } void -rotatestack(const Arg *arg) -{ - Client *c = NULL, *f; - - if (!selmon->sel) - return; - f = selmon->sel; - if (arg->i > 0) { - for (c = nexttiled(selmon->clients); c && nexttiled(c->next); c = nexttiled(c->next)); - if (c){ - detach(c); - attach(c); - detachstack(c); - attachstack(c); - } - } else { - if ((c = nexttiled(selmon->clients))){ - detach(c); - enqueue(c); - detachstack(c); - enqueuestack(c); - } - } - if (c){ - arrange(selmon); - //unfocus(f, 1); - focus(f); - restack(selmon); - } -} - -void run(void) { XEvent ev; @@ -1579,6 +1646,36 @@ setfullscreen(Client *c, int fullscreen) } } +int +stackpos(const Arg *arg) { + int n, i; + Client *c, *l; + + if(!selmon->clients) + return -1; + + if(arg->i == PREVSEL) { + for(l = selmon->stack; l && (!ISVISIBLE(l) || l == selmon->sel); l = l->snext); + if(!l) + return -1; + for(i = 0, c = selmon->clients; c != l; i += ISVISIBLE(c) ? 1 : 0, c = c->next); + return i; + } + else if(ISINC(arg->i)) { + if(!selmon->sel) + return -1; + for(i = 0, c = selmon->clients; c != selmon->sel; i += ISVISIBLE(c) ? 1 : 0, c = c->next); + for(n = i; c; n += ISVISIBLE(c) ? 1 : 0, c = c->next); + return MOD(i + GETINC(arg->i), n); + } + else if(arg->i < 0) { + for(i = 0, c = selmon->clients; c; i += ISVISIBLE(c) ? 1 : 0, c = c->next); + return MAX(i + arg->i, 0); + } + else + return arg->i; +} + void setlayout(const Arg *arg) { @@ -1602,7 +1699,7 @@ setmfact(const Arg *arg) if (!arg || !selmon->lt[selmon->sellt]->arrange) return; f = arg->f < 1.0 ? arg->f + selmon->mfact : arg->f - 1.0; - if (f < 0.1 || f > 0.9) + if (f < 0.05 || f > 0.95) return; selmon->mfact = f; arrange(selmon); @@ -1618,6 +1715,9 @@ setup(void) /* clean up any zombies immediately */ sigchld(0); + signal(SIGHUP, sighup); + signal(SIGTERM, sigterm); + /* init screen */ screen = DefaultScreen(dpy); sw = DisplayWidth(dpy, screen); @@ -1698,6 +1798,10 @@ showhide(Client *c) if (!c) return; if (ISVISIBLE(c)) { + if ((c->tags & SPTAGMASK) && c->isfloating) { + c->x = c->mon->wx + (c->mon->ww / 2 - WIDTH(c) / 2); + c->y = c->mon->wy + (c->mon->wh / 2 - HEIGHT(c) / 2); + } /* show clients top down */ XMoveWindow(dpy, c->win, c->x, c->y); if ((!c->mon->lt[c->mon->sellt]->arrange || c->isfloating) && !c->isfullscreen) @@ -1719,11 +1823,24 @@ sigchld(int unused) } void +sighup(int unused) +{ + Arg a = {.i = 1}; + quit(&a); +} + +void +sigterm(int unused) +{ + Arg a = {.i = 0}; + quit(&a); +} + +void spawn(const Arg *arg) { if (arg->v == dmenucmd) dmenumon[0] = '0' + selmon->num; - selmon->tagset[selmon->seltags] &= ~scratchtag; if (fork() == 0) { if (dpy) close(ConnectionNumber(dpy)); @@ -1754,35 +1871,6 @@ tagmon(const Arg *arg) } void -tile(Monitor *m) -{ - unsigned int i, n, h, mw, my, ty; - 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; - for (i = my = ty = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) - if (i < m->nmaster) { - h = (m->wh - my) / (MIN(n, m->nmaster) - i); - if (n == 1) - resize(c, m->wx - c->bw, m->wy, m->ww, m->wh, False); - else - resize(c, m->wx - c->bw, m->wy + my, mw - c->bw, h - c->bw, False); - my += HEIGHT(c) - c->bw; - } else { - h = (m->wh - ty) / (n - i); - resize(c, m->wx + mw - c->bw, m->wy + ty, m->ww - mw, h - c->bw, False); - ty += HEIGHT(c) - c->bw; - } -} - -void togglebar(const Arg *arg) { selmon->showbar = !selmon->showbar; @@ -1806,10 +1894,28 @@ togglefloating(const Arg *arg) } void +togglefullscr(const Arg *arg) +{ + if(selmon->sel) + setfullscreen(selmon->sel, !selmon->sel->isfullscreen); +} + +void +togglesticky(const Arg *arg) +{ + if (!selmon->sel) + return; + selmon->sel->issticky = !selmon->sel->issticky; + arrange(selmon); +} + +void togglescratch(const Arg *arg) { Client *c; unsigned int found = 0; + unsigned int scratchtag = SPTAG(arg->ui); + Arg sparg = {.v = scratchpads[arg->ui].cmd}; for (c = selmon->clients; c && !(found = c->tags & scratchtag); c = c->next); if (found) { @@ -1823,8 +1929,10 @@ togglescratch(const Arg *arg) focus(c); restack(selmon); } - } else - spawn(arg); + } else { + selmon->tagset[selmon->seltags] |= scratchtag; + spawn(&sparg); + } } void @@ -1873,6 +1981,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) { @@ -1887,9 +2009,12 @@ unmanage(Client *c, int destroyed) XUngrabServer(dpy); } free(c); - focus(NULL); - updateclientlist(); - arrange(m); + + if (!s) { + arrange(m); + focus(NULL); + updateclientlist(); + } } void @@ -2095,8 +2220,10 @@ updatesizehints(Client *c) void updatestatus(void) { - if (!gettextprop(root, XA_WM_NAME, stext, sizeof(stext))) + if (!gettextprop(root, XA_WM_NAME, rawstext, sizeof(rawstext))) strcpy(stext, "dwm-"VERSION); + else + copyvalidchars(stext, rawstext); drawbar(selmon); } @@ -2152,6 +2279,103 @@ view(const Arg *arg) arrange(selmon); } +pid_t +winpid(Window w) +{ + pid_t result = 0; + + 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; + 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__ */ + + 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) { @@ -2243,7 +2467,10 @@ 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(); + XrmInitialize(); setup(); #ifdef __OpenBSD__ if (pledge("stdio rpath proc exec", NULL) == -1) @@ -2251,6 +2478,7 @@ main(int argc, char *argv[]) #endif /* __OpenBSD__ */ scan(); run(); + if(restart) execvp(argv[0], argv); cleanup(); XCloseDisplay(dpy); return EXIT_SUCCESS; diff --git a/.repos/dwm/patches/attachbottom.diff b/.repos/dwm/patches/attachbottom.diff deleted file mode 100644 index 71d092f..0000000 --- a/.repos/dwm/patches/attachbottom.diff +++ /dev/null @@ -1,60 +0,0 @@ -Binary files dwm/drw.o and dwm.patched/drw.o differ -Binary files dwm/dwm and dwm.patched/dwm differ -diff -ruN dwm/dwm.c dwm.patched/dwm.c ---- dwm/dwm.c 2018-05-22 20:05:47.208417141 -0700 -+++ dwm.patched/dwm.c 2018-06-20 15:08:07.380496725 -0700 -@@ -147,6 +147,7 @@ - static void arrange(Monitor *m); - static void arrangemon(Monitor *m); - static void attach(Client *c); -+static void attachbelow(Client *c); - static void attachstack(Client *c); - static void buttonpress(XEvent *e); - static void checkotherwm(void); -@@ -407,6 +408,17 @@ - } - - void -+attachbelow(Client *c) -+{ -+ Client *below = c->mon->clients; -+ for (; below && below->next; below = below->next); -+ if (below) -+ below->next = c; -+ else -+ c->mon->clients = c; -+} -+ -+void - attachstack(Client *c) - { - c->snext = c->mon->stack; -@@ -1065,7 +1077,7 @@ - c->isfloating = c->oldstate = trans != None || c->isfixed; - if (c->isfloating) - XRaiseWindow(dpy, c->win); -- attach(c); -+ attachbelow(c); - attachstack(c); - XChangeProperty(dpy, root, netatom[NetClientList], XA_WINDOW, 32, PropModeAppend, - (unsigned char *) &(c->win), 1); -@@ -1420,7 +1432,7 @@ - detachstack(c); - c->mon = m; - c->tags = m->tagset[m->seltags]; /* assign tags of target monitor */ -- attach(c); -+ attachbelow(c); - attachstack(c); - focus(NULL); - arrange(NULL); -@@ -1900,7 +1912,7 @@ - m->clients = c->next; - detachstack(c); - c->mon = mons; -- attach(c); -+ attachbelow(c); - attachstack(c); - } - if (m == selmon) -Binary files dwm/dwm.o and dwm.patched/dwm.o differ -Binary files dwm/util.o and dwm.patched/util.o differ diff --git a/.repos/dwm/patches/horizgrid.diff b/.repos/dwm/patches/horizgrid.diff deleted file mode 100644 index 0920cee..0000000 --- a/.repos/dwm/patches/horizgrid.diff +++ /dev/null @@ -1,70 +0,0 @@ -From 064e1d48631cd9b03f32b42d7be79677197ee42f Mon Sep 17 00:00:00 2001 -From: Marshall Mason <marshallmason3@gmail.com> -Date: Mon, 9 Nov 2015 12:38:28 -0800 -Subject: [PATCH] Added horizgrid function - ---- - config.def.h | 2 ++ - horizgrid.c | 32 ++++++++++++++++++++++++++++++++ - 2 files changed, 34 insertions(+) - create mode 100644 horizgrid.c - -diff --git a/config.def.h b/config.def.h -index eaae8f3..c2ad519 100644 ---- a/config.def.h -+++ b/config.def.h -@@ -36,11 +36,13 @@ static const float mfact = 0.55; /* factor of master area size [0.05..0.95] - static const int nmaster = 1; /* number of clients in master area */ - static const Bool resizehints = True; /* True means respect size hints in tiled resizals */ - -+#include "horizgrid.c" - static const Layout layouts[] = { - /* symbol arrange function */ - { "[]=", tile }, /* first entry is default */ - { "><>", NULL }, /* no layout function means floating behavior */ - { "[M]", monocle }, -+ { "###", horizgrid }, - }; - - /* key definitions */ -diff --git a/horizgrid.c b/horizgrid.c -new file mode 100644 -index 0000000..51ce0f8 ---- /dev/null -+++ b/horizgrid.c -@@ -0,0 +1,32 @@ -+void -+horizgrid(Monitor *m) { -+ Client *c; -+ unsigned int n, i; -+ int w = 0; -+ int ntop, nbottom = 0; -+ -+ /* Count windows */ -+ for(n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); -+ -+ if(n == 0) -+ return; -+ else if(n == 1) { /* Just fill the whole screen */ -+ c = nexttiled(m->clients); -+ resize(c, m->wx, m->wy, m->ww - (2*c->bw), m->wh - (2*c->bw), False); -+ } else if(n == 2) { /* Split vertically */ -+ w = m->ww / 2; -+ c = nexttiled(m->clients); -+ resize(c, m->wx, m->wy, w - (2*c->bw), m->wh - (2*c->bw), False); -+ c = nexttiled(c->next); -+ resize(c, m->wx + w, m->wy, w - (2*c->bw), m->wh - (2*c->bw), False); -+ } else { -+ ntop = n / 2; -+ nbottom = n - ntop; -+ for(i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) { -+ if(i < ntop) -+ resize(c, m->wx + i * m->ww / ntop, m->wy, m->ww / ntop - (2*c->bw), m->wh / 2 - (2*c->bw), False); -+ else -+ resize(c, m->wx + (i - ntop) * m->ww / nbottom, m->wy + m->wh / 2, m->ww / nbottom - (2*c->bw), m->wh / 2 - (2*c->bw), False); -+ } -+ } -+} --- -2.1.4 - diff --git a/.repos/dwm/patches/noborder.diff b/.repos/dwm/patches/noborder.diff deleted file mode 100644 index f381eb8..0000000 --- a/.repos/dwm/patches/noborder.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/.repos/dwm/patches/rotate.diff b/.repos/dwm/patches/rotate.diff deleted file mode 100644 index ed74c6d..0000000 --- a/.repos/dwm/patches/rotate.diff +++ /dev/null @@ -1,102 +0,0 @@ -diff --git a/config.def.h b/config.def.h -index fd77a07..09737d7 100644 ---- a/config.def.h -+++ b/config.def.h -@@ -64,6 +64,8 @@ static Key keys[] = { - { MODKEY, XK_p, spawn, {.v = dmenucmd } }, - { MODKEY|ShiftMask, XK_Return, spawn, {.v = termcmd } }, - { MODKEY, XK_b, togglebar, {0} }, -+ { MODKEY|ShiftMask, XK_j, rotatestack, {.i = +1 } }, -+ { MODKEY|ShiftMask, XK_k, rotatestack, {.i = -1 } }, - { MODKEY, XK_j, focusstack, {.i = +1 } }, - { MODKEY, XK_k, focusstack, {.i = -1 } }, - { MODKEY, XK_i, incnmaster, {.i = +1 } }, -diff --git a/dwm.c b/dwm.c -index 421bf27..1ec8b10 100644 ---- a/dwm.c -+++ b/dwm.c -@@ -165,6 +165,8 @@ static void detachstack(Client *c); - static Monitor *dirtomon(int dir); - static void drawbar(Monitor *m); - static void drawbars(void); -+static void enqueue(Client *c); -+static void enqueuestack(Client *c); - static void enternotify(XEvent *e); - static void expose(XEvent *e); - static void focus(Client *c); -@@ -194,6 +196,7 @@ static void resize(Client *c, int x, int y, int w, int h, int interact); - static void resizeclient(Client *c, int x, int y, int w, int h); - static void resizemouse(const Arg *arg); - static void restack(Monitor *m); -+static void rotatestack(const Arg *arg); - static void run(void); - static void scan(void); - static int sendevent(Client *c, Atom proto); -@@ -765,6 +768,28 @@ drawbars(void) - } - - void -+enqueue(Client *c) -+{ -+ Client *l; -+ for (l = c->mon->clients; l && l->next; l = l->next); -+ if (l) { -+ l->next = c; -+ c->next = NULL; -+ } -+} -+ -+void -+enqueuestack(Client *c) -+{ -+ Client *l; -+ for (l = c->mon->stack; l && l->snext; l = l->snext); -+ if (l) { -+ l->snext = c; -+ c->snext = NULL; -+ } -+} -+ -+void - enternotify(XEvent *e) - { - Client *c; -@@ -1390,6 +1415,38 @@ restack(Monitor *m) - } - - void -+rotatestack(const Arg *arg) -+{ -+ Client *c = NULL, *f; -+ -+ if (!selmon->sel) -+ return; -+ f = selmon->sel; -+ if (arg->i > 0) { -+ for (c = nexttiled(selmon->clients); c && nexttiled(c->next); c = nexttiled(c->next)); -+ if (c){ -+ detach(c); -+ attach(c); -+ detachstack(c); -+ attachstack(c); -+ } -+ } else { -+ if ((c = nexttiled(selmon->clients))){ -+ detach(c); -+ enqueue(c); -+ detachstack(c); -+ enqueuestack(c); -+ } -+ } -+ if (c){ -+ arrange(selmon); -+ //unfocus(f, 1); -+ focus(f); -+ restack(selmon); -+ } -+} -+ -+void - run(void) - { - XEvent ev; diff --git a/.repos/dwm/patches/scratchpad.diff b/.repos/dwm/patches/scratchpad.diff deleted file mode 100644 index 2062263..0000000 --- a/.repos/dwm/patches/scratchpad.diff +++ /dev/null @@ -1,90 +0,0 @@ -diff -up a/config.def.h b/config.def.h ---- a/config.def.h 2019-06-06 21:23:27.006661784 +0200 -+++ b/config.def.h 2019-06-20 15:05:59.083102462 +0200 -@@ -58,11 +58,14 @@ static const Layout layouts[] = { - static char dmenumon[2] = "0"; /* component of dmenucmd, manipulated in spawn() */ - static const char *dmenucmd[] = { "dmenu_run", "-m", dmenumon, "-fn", dmenufont, "-nb", col_gray1, "-nf", col_gray3, "-sb", col_cyan, "-sf", col_gray4, NULL }; - static const char *termcmd[] = { "st", NULL }; -+static const char scratchpadname[] = "scratchpad"; -+static const char *scratchpadcmd[] = { "st", "-t", scratchpadname, "-g", "120x34", NULL }; - - static Key keys[] = { - /* modifier key function argument */ - { MODKEY, XK_p, spawn, {.v = dmenucmd } }, - { MODKEY|ShiftMask, XK_Return, spawn, {.v = termcmd } }, -+ { MODKEY, XK_grave, togglescratch, {.v = scratchpadcmd } }, - { MODKEY, XK_b, togglebar, {0} }, - { MODKEY, XK_j, focusstack, {.i = +1 } }, - { MODKEY, XK_k, focusstack, {.i = -1 } }, -diff -up a/dwm.c b/dwm.c ---- a/dwm.c 2019-06-06 21:23:27.023328450 +0200 -+++ b/dwm.c 2019-06-20 15:07:01.089767947 +0200 -@@ -213,6 +213,7 @@ static void tagmon(const Arg *arg); - static void tile(Monitor *); - static void togglebar(const Arg *arg); - static void togglefloating(const Arg *arg); -+static void togglescratch(const Arg *arg); - static void toggletag(const Arg *arg); - static void toggleview(const Arg *arg); - static void unfocus(Client *c, int setfocus); -@@ -273,6 +274,8 @@ static Window root, wmcheckwin; - /* configuration, allows nested code to access above variables */ - #include "config.h" - -+static unsigned int scratchtag = 1 << LENGTH(tags); -+ - /* compile-time check if all tags fit into an unsigned int bit array. */ - struct NumTags { char limitexceeded[LENGTH(tags) > 31 ? -1 : 1]; }; - -@@ -1052,6 +1055,14 @@ manage(Window w, XWindowAttributes *wa) - && (c->x + (c->w / 2) < c->mon->wx + c->mon->ww)) ? bh : c->mon->my); - c->bw = borderpx; - -+ selmon->tagset[selmon->seltags] &= ~scratchtag; -+ if (!strcmp(c->name, scratchpadname)) { -+ c->mon->tagset[c->mon->seltags] |= c->tags = scratchtag; -+ c->isfloating = True; -+ c->x = c->mon->wx + (c->mon->ww / 2 - WIDTH(c) / 2); -+ c->y = c->mon->wy + (c->mon->wh / 2 - HEIGHT(c) / 2); -+ } -+ - wc.border_width = c->bw; - XConfigureWindow(dpy, w, CWBorderWidth, &wc); - XSetWindowBorder(dpy, w, scheme[SchemeNorm][ColBorder].pixel); -@@ -1661,6 +1672,7 @@ spawn(const Arg *arg) - { - if (arg->v == dmenucmd) - dmenumon[0] = '0' + selmon->num; -+ selmon->tagset[selmon->seltags] &= ~scratchtag; - if (fork() == 0) { - if (dpy) - close(ConnectionNumber(dpy)); -@@ -1748,6 +1760,28 @@ togglefloating(const Arg *arg) - } - - void -+togglescratch(const Arg *arg) -+{ -+ Client *c; -+ unsigned int found = 0; -+ -+ for (c = selmon->clients; c && !(found = c->tags & scratchtag); c = c->next); -+ if (found) { -+ unsigned int newtagset = selmon->tagset[selmon->seltags] ^ scratchtag; -+ if (newtagset) { -+ selmon->tagset[selmon->seltags] = newtagset; -+ focus(NULL); -+ arrange(selmon); -+ } -+ if (ISVISIBLE(c)) { -+ focus(c); -+ restack(selmon); -+ } -+ } else -+ spawn(arg); -+} -+ -+void - toggletag(const Arg *arg) - { - unsigned int newtags; diff --git a/.repos/dwm/patches/singularborders.diff b/.repos/dwm/patches/singularborders.diff deleted file mode 100644 index eb94653..0000000 --- a/.repos/dwm/patches/singularborders.diff +++ /dev/null @@ -1,53 +0,0 @@ ---- dwm.c.orig 2013-03-23 15:13:21.709978427 +0100 -+++ dwm.c 2013-03-23 15:13:13.366645236 +0100 -@@ -842,6 +842,8 @@ - - void - focus(Client *c) { -+ XWindowChanges wc; -+ - if(!c || !ISVISIBLE(c)) - for(c = selmon->stack; c && !ISVISIBLE(c); c = c->snext); - /* was if(selmon->sel) */ -@@ -856,6 +858,11 @@ - attachstack(c); - grabbuttons(c, True); - XSetWindowBorder(dpy, c->win, dc.sel[ColBorder]); -+ if(!c->isfloating) { -+ wc.sibling = selmon->barwin; -+ wc.stack_mode = Below; -+ XConfigureWindow(dpy, c->win, CWSibling | CWStackMode, &wc); -+ } - setfocus(c); - } - else -@@ -1200,7 +1207,7 @@ - if(n > 0) /* override layout symbol */ - snprintf(m->ltsymbol, sizeof m->ltsymbol, "[%d]", n); - for(c = nexttiled(m->clients); c; c = nexttiled(c->next)) -- resize(c, m->wx, m->wy, m->ww - 2 * c->bw, m->wh - 2 * c->bw, False); -+ resize(c, m->wx - c->bw, m->wy, m->ww, m->wh, False); - } - - void -@@ -1717,13 +1724,16 @@ - for(i = my = ty = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) - 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), False); -- my += HEIGHT(c); -+ if(n == 1) -+ resize(c, m->wx - c->bw, m->wy, m->ww, m->wh, False); -+ else -+ resize(c, m->wx - c->bw, m->wy + my, mw - c->bw, h - c->bw, False); -+ my += HEIGHT(c) - c->bw; - } - else { - h = (m->wh - ty) / (n - i); -- resize(c, m->wx + mw, m->wy + ty, m->ww - mw - (2*c->bw), h - (2*c->bw), False); -- ty += HEIGHT(c); -+ resize(c, m->wx + mw - c->bw, m->wy + ty, m->ww - mw, h - c->bw, False); -+ ty += HEIGHT(c) - c->bw; - } - } - diff --git a/.repos/dwm/patches/swallow.diff b/.repos/dwm/patches/swallow.diff deleted file mode 100644 index 684735a..0000000 --- a/.repos/dwm/patches/swallow.diff +++ /dev/null @@ -1,388 +0,0 @@ -diff --git a/config.def.h b/config.def.h -index 7054c06..2bfd607 100644 ---- a/config.def.h -+++ b/config.def.h -@@ -24,9 +24,10 @@ 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, 0, -1 }, -+ { "st", NULL, NULL, 0, 0, 1, 1, -1 }, - }; - - /* layout(s) */ -diff --git a/config.mk b/config.mk -index 4eefb71..34ea872 100644 ---- a/config.mk -+++ b/config.mk -@@ -22,7 +22,7 @@ FREETYPEINC = /usr/include/freetype2 - - # 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 - - # flags - CPPFLAGS = -D_BSD_SOURCE -D_POSIX_C_SOURCE=2 -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS} -diff --git a/dwm.c b/dwm.c -index 0362114..1d38293 100644 ---- a/dwm.c -+++ b/dwm.c -@@ -40,6 +40,8 @@ - #include <X11/extensions/Xinerama.h> - #endif /* XINERAMA */ - #include <X11/Xft/Xft.h> -+#include <X11/Xlib-xcb.h> -+#include <xcb/res.h> - - #include "drw.h" - #include "util.h" -@@ -92,9 +94,11 @@ 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, isurgent, neverfocus, oldstate, isfullscreen, isterminal, noswallow; -+ pid_t pid; - Client *next; - Client *snext; -+ Client *swallowing; - Monitor *mon; - Window win; - }; -@@ -138,6 +142,8 @@ typedef struct { - const char *title; - unsigned int tags; - int isfloating; -+ int isterminal; -+ int noswallow; - int monitor; - } Rule; - -@@ -170,12 +176,14 @@ static void focus(Client *c); - static void focusin(XEvent *e); - static void focusmon(const Arg *arg); - static void focusstack(const Arg *arg); -+static pid_t getparentprocess(pid_t p); - static int getrootptr(int *x, int *y); - static long getstate(Window w); - static int gettextprop(Window w, Atom atom, char *text, unsigned int size); - static void grabbuttons(Client *c, int focused); - static void grabkeys(void); - static void incnmaster(const Arg *arg); -+static int isdescprocess(pid_t p, pid_t c); - static void keypress(XEvent *e); - static void killclient(const Arg *arg); - static void manage(Window w, XWindowAttributes *wa); -@@ -206,8 +214,10 @@ static void setup(void); - static void showhide(Client *c); - static void sigchld(int unused); - static void spawn(const Arg *arg); -+static Client *swallowingclient(Window w); - static void tag(const Arg *arg); - static void tagmon(const Arg *arg); -+static Client *termforwin(const Client *c); - static void tile(Monitor *); - static void togglebar(const Arg *arg); - static void togglefloating(const Arg *arg); -@@ -227,6 +237,7 @@ static void updatewindowtype(Client *c); - static void updatetitle(Client *c); - static void updatewmhints(Client *c); - static void view(const Arg *arg); -+static pid_t winpid(Window w); - static Client *wintoclient(Window w); - static Monitor *wintomon(Window w); - static int xerror(Display *dpy, XErrorEvent *ee); -@@ -267,6 +278,8 @@ static Drw *drw; - static Monitor *mons, *selmon; - static Window root; - -+static xcb_connection_t *xcon; -+ - /* configuration, allows nested code to access above variables */ - #include "config.h" - -@@ -296,6 +309,7 @@ applyrules(Client *c) - && (!r->class || strstr(class, r->class)) - && (!r->instance || strstr(instance, r->instance))) - { -+ c->isterminal = r->isterminal; - c->isfloating = r->isfloating; - c->tags |= r->tags; - for (m = mons; m && m->num != r->monitor; m = m->next); -@@ -412,6 +426,48 @@ attachstack(Client *c) - c->mon->stack = c; - } - -+void -+swallow(Client *p, Client *c) -+{ -+ if (c->noswallow || c->isterminal) -+ 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); -+ arrange(p->mon); -+ XMoveResizeWindow(dpy, p->win, p->x, p->y, p->w, p->h); -+ configure(p); -+ updateclientlist(); -+} -+ -+void -+unswallow(Client *c) -+{ -+ c->win = c->swallowing->win; -+ -+ free(c->swallowing); -+ c->swallowing = NULL; -+ -+ updatetitle(c); -+ arrange(c->mon); -+ XMapWindow(dpy, c->win); -+ XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h); -+ configure(c); -+ setclientstate(c, NormalState); -+ focus(c); -+} -+ - void - buttonpress(XEvent *e) - { -@@ -475,7 +531,7 @@ cleanup(void) - selmon->lt[selmon->sellt] = &foo; - for (m = mons; m; m = m->next) - while (m->stack) -- unmanage(m->stack, 0); -+ unmanage(m->stack, 0); // XXX - unmanage swallowing windows too - XUngrabKey(dpy, AnyKey, AnyModifier, root); - while (mons) - cleanupmon(mons); -@@ -661,6 +717,9 @@ destroynotify(XEvent *e) - - if ((c = wintoclient(ev->window))) - unmanage(c, 1); -+ -+ else if ((c = swallowingclient(ev->window))) -+ unmanage(c->swallowing, 1); - } - - void -@@ -1032,12 +1091,13 @@ killclient(const Arg *arg) - void - manage(Window w, XWindowAttributes *wa) - { -- Client *c, *t = NULL; -+ Client *c, *t, *term = NULL; - Window trans = None; - XWindowChanges wc; - - c = ecalloc(1, sizeof(Client)); - c->win = w; -+ c->pid = winpid(w); - updatetitle(c); - if (XGetTransientForHint(dpy, w, &trans) && (t = wintoclient(trans))) { - c->mon = t->mon; -@@ -1045,7 +1105,9 @@ manage(Window w, XWindowAttributes *wa) - } else { - c->mon = selmon; - applyrules(c); -+ term = termforwin(c); - } -+ - /* geometry */ - c->x = c->oldx = wa->x; - c->y = c->oldy = wa->y; -@@ -1085,8 +1147,11 @@ manage(Window w, XWindowAttributes *wa) - if (c->mon == selmon) - unfocus(selmon->sel, 0); - c->mon->sel = c; -- arrange(c->mon); -+ if (!term) -+ arrange(c->mon); - XMapWindow(dpy, c->win); -+ if (term) -+ swallow(term, c); - focus(NULL); - } - -@@ -1758,6 +1823,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; -+ } -+ - /* The server grab construct avoids race conditions. */ - detach(c); - detachstack(c); -@@ -1773,9 +1852,12 @@ unmanage(Client *c, int destroyed) - XUngrabServer(dpy); - } - free(c); -- focus(NULL); -- updateclientlist(); -- arrange(m); -+ -+ if (!s) { -+ arrange(m); -+ focus(NULL); -+ updateclientlist(); -+ } - } - - void -@@ -2040,16 +2122,116 @@ view(const Arg *arg) - arrange(selmon); - } - -+pid_t -+winpid(Window w) -+{ -+ pid_t result = 0; -+ -+ 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; -+ 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__ */ -+ -+ 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) - { - Client *c; - Monitor *m; - -- for (m = mons; m; m = m->next) -- for (c = m->clients; c; c = c->next) -+ for (m = mons; m; m = m->next) { -+ for (c = m->clients; c; c = c->next) { - if (c->win == w) - return c; -+ } -+ } -+ - return NULL; - } - -@@ -2131,6 +2313,8 @@ main(int argc, char *argv[]) - fputs("warning: no locale support\n", stderr); - if (!(dpy = XOpenDisplay(NULL))) - die("dwm: cannot open display\n"); -+ if (!(xcon = XGetXCBConnection(dpy))) -+ die("dwm: cannot get xcb connection\n"); - checkotherwm(); - setup(); - scan(); diff --git a/.repos/dwm/shiftview.c b/.repos/dwm/shiftview.c new file mode 100644 index 0000000..a52ccd7 --- /dev/null +++ b/.repos/dwm/shiftview.c @@ -0,0 +1,68 @@ +/** Function to shift the current view to the left/right + * + * @param: "arg->i" stores the number of tags to shift right (positive value) + * or left (negative value) + */ +void +shiftview(const Arg *arg) +{ + Arg a; + Client *c; + unsigned visible = 0; + int i = arg->i; + int count = 0; + int nextseltags, curseltags = selmon->tagset[selmon->seltags]; + + do { + if(i > 0) // left circular shift + nextseltags = (curseltags << i) | (curseltags >> (LENGTH(tags) - i)); + + else // right circular shift + nextseltags = curseltags >> (- i) | (curseltags << (LENGTH(tags) + i)); + + // Check if tag is visible + for (c = selmon->clients; c && !visible; c = c->next) + if (nextseltags & c->tags) { + visible = 1; + break; + } + i += arg->i; + } while (!visible && ++count < 10); + + if (count < 10) { + a.i = nextseltags; + view(&a); + } +} + +void +shifttag(const Arg *arg) +{ + Arg a; + Client *c; + unsigned visible = 0; + int i = arg->i; + int count = 0; + int nextseltags, curseltags = selmon->tagset[selmon->seltags]; + + do { + if(i > 0) // left circular shift + nextseltags = (curseltags << i) | (curseltags >> (LENGTH(tags) - i)); + + else // right circular shift + nextseltags = curseltags >> (- i) | (curseltags << (LENGTH(tags) + i)); + + // Check if tag is visible + for (c = selmon->clients; c && !visible; c = c->next) + if (nextseltags & c->tags) { + visible = 1; + break; + } + i += arg->i; + } while (!visible && ++count < 10); + + if (count < 10) { + a.i = nextseltags; + tag(&a); + } +} diff --git a/.repos/dwm/vanitygaps.c b/.repos/dwm/vanitygaps.c new file mode 100644 index 0000000..7245e74 --- /dev/null +++ b/.repos/dwm/vanitygaps.c @@ -0,0 +1,542 @@ +/* Key binding functions */ +static void defaultgaps(const Arg *arg); +static void incrgaps(const Arg *arg); +/* static void incrigaps(const Arg *arg); */ +/* static void incrogaps(const Arg *arg); */ +/* static void incrohgaps(const Arg *arg); */ +/* static void incrovgaps(const Arg *arg); */ +/* static void incrihgaps(const Arg *arg); */ +/* static void incrivgaps(const Arg *arg); */ +static void togglegaps(const Arg *arg); + +/* Layouts */ +static void bstack(Monitor *m); +static void centeredmaster(Monitor *m); +static void centeredfloatingmaster(Monitor *m); +static void deck(Monitor *m); +static void dwindle(Monitor *m); +static void fibonacci(Monitor *m, int s); +static void spiral(Monitor *m); +static void tile(Monitor *); + +/* Internals */ +static void getgaps(Monitor *m, int *oh, int *ov, int *ih, int *iv, unsigned int *nc); +static void setgaps(int oh, int ov, int ih, int iv); + +/* Settings */ +static int enablegaps = 1; + +static void +setgaps(int oh, int ov, int ih, int iv) +{ + if (oh < 0) oh = 0; + if (ov < 0) ov = 0; + if (ih < 0) ih = 0; + if (iv < 0) iv = 0; + + selmon->gappoh = oh; + selmon->gappov = ov; + selmon->gappih = ih; + selmon->gappiv = iv; + arrange(selmon); +} + +static void +togglegaps(const Arg *arg) +{ + enablegaps = !enablegaps; + arrange(NULL); +} + +static void +defaultgaps(const Arg *arg) +{ + setgaps(gappoh, gappov, gappih, gappiv); +} + +static void +incrgaps(const Arg *arg) +{ + setgaps( + selmon->gappoh + arg->i, + selmon->gappov + arg->i, + selmon->gappih + arg->i, + selmon->gappiv + arg->i + ); +} + +/* static void */ +/* incrigaps(const Arg *arg) */ +/* { */ +/* setgaps( */ +/* selmon->gappoh, */ +/* selmon->gappov, */ +/* selmon->gappih + arg->i, */ +/* selmon->gappiv + arg->i */ +/* ); */ +/* } */ + +/* static void */ +/* incrogaps(const Arg *arg) */ +/* { */ +/* setgaps( */ +/* selmon->gappoh + arg->i, */ +/* selmon->gappov + arg->i, */ +/* selmon->gappih, */ +/* selmon->gappiv */ +/* ); */ +/* } */ + +/* static void */ +/* incrohgaps(const Arg *arg) */ +/* { */ +/* setgaps( */ +/* selmon->gappoh + arg->i, */ +/* selmon->gappov, */ +/* selmon->gappih, */ +/* selmon->gappiv */ +/* ); */ +/* } */ + +/* static void */ +/* incrovgaps(const Arg *arg) */ +/* { */ +/* setgaps( */ +/* selmon->gappoh, */ +/* selmon->gappov + arg->i, */ +/* selmon->gappih, */ +/* selmon->gappiv */ +/* ); */ +/* } */ + +/* static void */ +/* incrihgaps(const Arg *arg) */ +/* { */ +/* setgaps( */ +/* selmon->gappoh, */ +/* selmon->gappov, */ +/* selmon->gappih + arg->i, */ +/* selmon->gappiv */ +/* ); */ +/* } */ + +/* static void */ +/* incrivgaps(const Arg *arg) */ +/* { */ +/* setgaps( */ +/* selmon->gappoh, */ +/* selmon->gappov, */ +/* selmon->gappih, */ +/* selmon->gappiv + arg->i */ +/* ); */ +/* } */ + +static void +getgaps(Monitor *m, int *oh, int *ov, int *ih, int *iv, unsigned int *nc) +{ + unsigned int n, oe, ie; + oe = ie = enablegaps; + Client *c; + + for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); + if (smartgaps && n == 1) { + oe = 0; // outer gaps disabled when only one client + } + + *oh = m->gappoh*oe; // outer horizontal gap + *ov = m->gappov*oe; // outer vertical gap + *ih = m->gappih*ie; // inner horizontal gap + *iv = m->gappiv*ie; // inner vertical gap + *nc = n; // number of clients +} + +void +getfacts(Monitor *m, int msize, int ssize, float *mf, float *sf, int *mr, int *sr) +{ + unsigned int n; + float mfacts, sfacts; + int mtotal = 0, stotal = 0; + Client *c; + + for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); + mfacts = MIN(n, m->nmaster); + sfacts = n - m->nmaster; + + for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++) + if (n < m->nmaster) + mtotal += msize / mfacts; + else + stotal += ssize / sfacts; + + *mf = mfacts; // total factor of master area + *sf = sfacts; // total factor of stack area + *mr = msize - mtotal; // the remainder (rest) of pixels after an even master split + *sr = ssize - stotal; // the remainder (rest) of pixels after an even stack split +} + +/*** + * Layouts + */ + +/* + * Bottomstack layout + gaps + * https://dwm.suckless.org/patches/bottomstack/ + */ + +static void +bstack(Monitor *m) +{ + unsigned int i, n; + int mx = 0, my = 0, mh = 0, mw = 0; + int sx = 0, sy = 0, sh = 0, sw = 0; + float mfacts, sfacts; + int mrest, srest; + Client *c; + + int oh, ov, ih, iv; + getgaps(m, &oh, &ov, &ih, &iv, &n); + + if (n == 0) + return; + + sx = mx = m->wx + ov; + sy = my = m->wy + oh; + sh = mh = m->wh - 2*oh; + mw = m->ww - 2*ov - iv * (MIN(n, m->nmaster) - 1); + sw = m->ww - 2*ov - iv * (n - m->nmaster - 1); + + if (m->nmaster && n > m->nmaster) { + sh = (mh - ih) * (1 - m->mfact); + mh = (mh - ih) * m->mfact; + sx = mx; + sy = my + mh + ih; + } + + getfacts(m, mw, sw, &mfacts, &sfacts, &mrest, &srest); + + for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) { + if (i < m->nmaster) { + resize(c, mx, my, (mw / mfacts) + (i < mrest ? 1 : 0) - (2*c->bw), mh - (2*c->bw), 0); + mx += WIDTH(c) + iv; + } else { + resize(c, sx, sy, (sw / sfacts) + ((i - m->nmaster) < srest ? 1 : 0) - (2*c->bw), sh - (2*c->bw), 0); + sx += WIDTH(c) + iv; + } + } +} + +/* + * Centred master layout + gaps + * https://dwm.suckless.org/patches/centeredmaster/ + */ + +void +centeredmaster(Monitor *m) +{ + unsigned int i, n; + int mx = 0, my = 0, mh = 0, mw = 0; + int lx = 0, ly = 0, lw = 0, lh = 0; + int rx = 0, ry = 0, rw = 0, rh = 0; + float mfacts = 0, lfacts = 0, rfacts = 0; + int mtotal = 0, ltotal = 0, rtotal = 0; + int mrest = 0, lrest = 0, rrest = 0; + Client *c; + + int oh, ov, ih, iv; + getgaps(m, &oh, &ov, &ih, &iv, &n); + + if (n == 0) + return; + + /* initialize areas */ + mx = m->wx + ov; + my = m->wy + oh; + mh = m->wh - 2*oh - ih * ((!m->nmaster ? n : MIN(n, m->nmaster)) - 1); + mw = m->ww - 2*ov; + lh = m->wh - 2*oh - ih * (((n - m->nmaster) / 2) - 1); + rh = m->wh - 2*oh - ih * (((n - m->nmaster) / 2) - ((n - m->nmaster) % 2 ? 0 : 1)); + + if (m->nmaster && n > m->nmaster) { + /* go mfact box in the center if more than nmaster clients */ + if (n - m->nmaster > 1) { + /* ||<-S->|<---M--->|<-S->|| */ + mw = (m->ww - 2*ov - 2*iv) * m->mfact; + lw = (m->ww - mw - 2*ov - 2*iv) / 2; + mx += lw + iv; + } else { + /* ||<---M--->|<-S->|| */ + mw = (mw - iv) * m->mfact; + lw = m->ww - mw - iv - 2*ov; + } + rw = lw; + lx = m->wx + ov; + ly = m->wy + oh; + rx = mx + mw + iv; + ry = m->wy + oh; + } + + /* calculate facts */ + for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++) { + if (!m->nmaster || n < m->nmaster) + mfacts += 1; + else if ((n - m->nmaster) % 2) + lfacts += 1; // total factor of left hand stack area + else + rfacts += 1; // total factor of right hand stack area + } + + for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++) + if (!m->nmaster || n < m->nmaster) + mtotal += mh / mfacts; + else if ((n - m->nmaster) % 2) + ltotal += lh / lfacts; + else + rtotal += rh / rfacts; + + mrest = mh - mtotal; + lrest = lh - ltotal; + rrest = rh - rtotal; + + for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) { + if (!m->nmaster || i < m->nmaster) { + /* nmaster clients are stacked vertically, in the center of the screen */ + resize(c, mx, my, mw - (2*c->bw), (mh / mfacts) + (i < mrest ? 1 : 0) - (2*c->bw), 0); + my += HEIGHT(c) + ih; + } else { + /* stack clients are stacked vertically */ + if ((i - m->nmaster) % 2 ) { + resize(c, lx, ly, lw - (2*c->bw), (lh / lfacts) + ((i - 2*m->nmaster) < 2*lrest ? 1 : 0) - (2*c->bw), 0); + ly += HEIGHT(c) + ih; + } else { + resize(c, rx, ry, rw - (2*c->bw), (rh / rfacts) + ((i - 2*m->nmaster) < 2*rrest ? 1 : 0) - (2*c->bw), 0); + ry += HEIGHT(c) + ih; + } + } + } +} + +void +centeredfloatingmaster(Monitor *m) +{ + unsigned int i, n; + float mfacts, sfacts; + int mrest, srest; + int mx = 0, my = 0, mh = 0, mw = 0; + int sx = 0, sy = 0, sh = 0, sw = 0; + Client *c; + + float mivf = 1.0; // master inner vertical gap factor + int oh, ov, ih, iv; + getgaps(m, &oh, &ov, &ih, &iv, &n); + + if (n == 0) + return; + + sx = mx = m->wx + ov; + sy = my = m->wy + oh; + sh = mh = m->wh - 2*oh; + mw = m->ww - 2*ov - iv*(n - 1); + sw = m->ww - 2*ov - iv*(n - m->nmaster - 1); + + if (m->nmaster && n > m->nmaster) { + mivf = 0.8; + /* go mfact box in the center if more than nmaster clients */ + if (m->ww > m->wh) { + mw = m->ww * m->mfact - iv*mivf*(MIN(n, m->nmaster) - 1); + mh = m->wh * 0.9 - 2*oh; + } else { + mw = m->ww * 0.9 - iv*mivf*(MIN(n, m->nmaster) - 1); + mh = m->wh * m->mfact; + } + mx = m->wx + (m->ww - mw) / 2; + my = m->wy + (m->wh - mh) / 2; + + sx = m->wx + ov; + sy = m->wy + oh; + sh = m->wh - 2*oh; + } + + getfacts(m, mw, sw, &mfacts, &sfacts, &mrest, &srest); + + for (i = 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 */ + resize(c, mx, my, (mw / mfacts) + (i < mrest ? 1 : 0) - (2*c->bw), mh - (2*c->bw), 0); + mx += WIDTH(c) + iv*mivf; + } else { + /* stack clients are stacked horizontally */ + resize(c, sx, sy, (sw / sfacts) + ((i - m->nmaster) < srest ? 1 : 0) - (2*c->bw), sh - (2*c->bw), 0); + sx += WIDTH(c) + iv; + } +} + +/* + * Deck layout + gaps + * https://dwm.suckless.org/patches/deck/ + */ + +static void +deck(Monitor *m) +{ + unsigned int i, n; + int mx = 0, my = 0, mh = 0, mw = 0; + int sx = 0, sy = 0, sh = 0, sw = 0; + float mfacts, sfacts; + int mrest, srest; + Client *c; + + int oh, ov, ih, iv; + getgaps(m, &oh, &ov, &ih, &iv, &n); + + if (n == 0) + return; + + sx = mx = m->wx + ov; + sy = my = m->wy + oh; + sh = mh = m->wh - 2*oh - ih * (MIN(n, m->nmaster) - 1); + sw = mw = m->ww - 2*ov; + + if (m->nmaster && n > m->nmaster) { + sw = (mw - iv) * (1 - m->mfact); + mw = (mw - iv) * m->mfact; + sx = mx + mw + iv; + sh = m->wh - 2*oh; + } + + getfacts(m, mh, sh, &mfacts, &sfacts, &mrest, &srest); + + if (n - m->nmaster > 0) /* override layout symbol */ + snprintf(m->ltsymbol, sizeof m->ltsymbol, "D %d", n - m->nmaster); + + for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) + if (i < m->nmaster) { + resize(c, mx, my, mw - (2*c->bw), (mh / mfacts) + (i < mrest ? 1 : 0) - (2*c->bw), 0); + my += HEIGHT(c) + ih; + } else { + resize(c, sx, sy, sw - (2*c->bw), sh - (2*c->bw), 0); + } +} + +/* + * Fibonacci layout + gaps + * https://dwm.suckless.org/patches/fibonacci/ + */ + +static void +fibonacci(Monitor *m, int s) +{ + unsigned int i, n; + int nx, ny, nw, nh; + int oh, ov, ih, iv; + Client *c; + + getgaps(m, &oh, &ov, &ih, &iv, &n); + + if (n == 0) + return; + + nx = m->wx + ov; + ny = oh; + nw = m->ww - 2*ov; + nh = m->wh - 2*oh; + + for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next)) { + if ((i % 2 && nh / 2 > 2*c->bw) + || (!(i % 2) && nw / 2 > 2*c->bw)) { + if (i < n - 1) { + if (i % 2) + nh = (nh - ih) / 2; + else + nw = (nw - iv) / 2; + + if ((i % 4) == 2 && !s) + nx += nw + iv; + else if ((i % 4) == 3 && !s) + ny += nh + ih; + } + if ((i % 4) == 0) { + if (s) + ny += nh + ih; + else + ny -= nh + ih; + } + else if ((i % 4) == 1) + nx += nw + iv; + else if ((i % 4) == 2) + ny += nh + ih; + else if ((i % 4) == 3) { + if (s) + nx += nw + iv; + else + nx -= nw + iv; + } + if (i == 0) { + if (n != 1) + nw = (m->ww - 2*ov - iv) * m->mfact; + ny = m->wy + oh; + } + else if (i == 1) + nw = m->ww - nw - iv - 2*ov; + i++; + } + + resize(c, nx, ny, nw - (2*c->bw), nh - (2*c->bw), False); + } +} + +static void +dwindle(Monitor *m) +{ + fibonacci(m, 1); +} + +static void +spiral(Monitor *m) +{ + fibonacci(m, 0); +} + +/* + * Default tile layout + gaps + */ + +static void +tile(Monitor *m) +{ + unsigned int i, n; + int mx = 0, my = 0, mh = 0, mw = 0; + int sx = 0, sy = 0, sh = 0, sw = 0; + float mfacts, sfacts; + int mrest, srest; + Client *c; + + + int oh, ov, ih, iv; + getgaps(m, &oh, &ov, &ih, &iv, &n); + + if (n == 0) + return; + + sx = mx = m->wx + ov; + sy = my = m->wy + oh; + mh = m->wh - 2*oh - ih * (MIN(n, m->nmaster) - 1); + sh = m->wh - 2*oh - ih * (n - m->nmaster - 1); + sw = mw = m->ww - 2*ov; + + if (m->nmaster && n > m->nmaster) { + sw = (mw - iv) * (1 - m->mfact); + mw = (mw - iv) * m->mfact; + sx = mx + mw + iv; + } + + getfacts(m, mh, sh, &mfacts, &sfacts, &mrest, &srest); + + for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) + if (i < m->nmaster) { + resize(c, mx, my, mw - (2*c->bw), (mh / mfacts) + (i < mrest ? 1 : 0) - (2*c->bw), 0); + my += HEIGHT(c) + ih; + } else { + resize(c, sx, sy, sw - (2*c->bw), (sh / sfacts) + ((i - m->nmaster) < srest ? 1 : 0) - (2*c->bw), 0); + sy += HEIGHT(c) + ih; + } +} |