first commit

This commit is contained in:
Luca Bilke 2022-08-22 21:15:37 +02:00
commit 1eb13e5078
29 changed files with 8952 additions and 0 deletions

37
LICENSE Normal file
View File

@ -0,0 +1,37 @@
MIT/X Consortium License
© 2006-2019 Anselm R Garbe <anselm@garbe.ca>
© 2006-2009 Jukka Salmi <jukka at salmi dot ch>
© 2006-2007 Sander van Dijk <a dot h dot vandijk at gmail dot com>
© 2007-2011 Peter Hartlich <sgkkr at hartlich dot com>
© 2007-2009 Szabolcs Nagy <nszabolcs at gmail dot com>
© 2007-2009 Christof Musik <christof at sendfax dot de>
© 2007-2009 Premysl Hruby <dfenze at gmail dot com>
© 2007-2008 Enno Gottox Boland <gottox at s01 dot de>
© 2008 Martin Hurton <martin dot hurton at gmail dot com>
© 2008 Neale Pickett <neale dot woozle dot org>
© 2009 Mate Nagy <mnagy at port70 dot net>
© 2010-2016 Hiltjo Posthuma <hiltjo@codemadness.org>
© 2010-2012 Connor Lane Smith <cls@lubutu.com>
© 2011 Christoph Lohmann <20h@r-36.net>
© 2015-2016 Quentin Rameau <quinq@fifth.space>
© 2015-2016 Eric Pruitt <eric.pruitt@gmail.com>
© 2016-2017 Markus Teich <markus.teich@stusta.mhn.de>
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.

51
Makefile Normal file
View File

@ -0,0 +1,51 @@
# dwm - dynamic window manager
# See LICENSE file for copyright and license details.
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}"
.c.o:
${CC} -c ${CFLAGS} $<
${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
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}
tar -cf dwm-${VERSION}.tar dwm-${VERSION}
gzip dwm-${VERSION}.tar
rm -rf dwm-${VERSION}
install: all
mkdir -p ${DESTDIR}${PREFIX}/bin
cp -f dwm ${DESTDIR}${PREFIX}/bin
chmod 755 ${DESTDIR}${PREFIX}/bin/dwm
mkdir -p ${DESTDIR}${MANPREFIX}/man1
sed "s/VERSION/${VERSION}/g" < dwm.1 > ${DESTDIR}${MANPREFIX}/man1/dwm.1
chmod 644 ${DESTDIR}${MANPREFIX}/man1/dwm.1
uninstall:
rm -f ${DESTDIR}${PREFIX}/bin/dwm\
${DESTDIR}${MANPREFIX}/man1/dwm.1
.PHONY: all options clean dist install uninstall

20
README.md Normal file
View File

@ -0,0 +1,20 @@
# My build of DWM
I use a modified floatrules patch that allows setting floats for X, Y, W and H values that are interpreted as percentages of screen space.
The SGR patch allows my sb-status scripts to use colors and show larger NerdFonts icons.
## Patches
- [Actual Fullscreen](https://dwm.suckless.org/patches/actualfullscreen/dwm-actualfullscreen-20211013-cb3f58a.diff)
- [Attach Top](https://dwm.suckless.org/patches/attachtop/)
- [Color Bar](https://dwm.suckless.org/patches/colorbar/)
- [Floatrules](https://dwm.suckless.org/patches/floatrules/)
- [Hide Vacant Tags](https://dwm.suckless.org/patches/hide_vacant_tags/)
- [Named Scratchpads](https://dwm.suckless.org/patches/namedscratchpads/)
- [Per Tag](https://dwm.suckless.org/patches/pertag/)
- [Resize Corners](https://dwm.suckless.org/patches/resizecorners/)
- [Restart Sig](https://dwm.suckless.org/patches/restartsig/)
- [SGR Status](https://dwm.suckless.org/patches/sgrstatus/)
- [SSH Aware Spawn](https://dwm.suckless.org/patches/sshawarespawn/)
- [Stacker](https://dwm.suckless.org/patches/stacker/)
- [Swallow](https://dwm.suckless.org/patches/swallow/)
- [Vanity Gaps](https://dwm.suckless.org/patches/vanitygaps/)
- [XResources](https://dwm.suckless.org/patches/xresources/)

65
compile_commands.json Normal file
View File

@ -0,0 +1,65 @@
[
{
"arguments": [
"/usr/bin/cc",
"-c",
"-std=c99",
"-pedantic",
"-Wall",
"-Wno-deprecated-declarations",
"-Os",
"-I/usr/X11R6/include",
"-I/usr/include/freetype2",
"-D_DEFAULT_SOURCE",
"-D_BSD_SOURCE",
"-D_POSIX_C_SOURCE=200809L",
"-DVERSION=\"6.3\"",
"-DXINERAMA",
"drw.c"
],
"directory": "/home/luca/.local/src/dwm",
"file": "/home/luca/.local/src/dwm/drw.c"
},
{
"arguments": [
"/usr/bin/cc",
"-c",
"-std=c99",
"-pedantic",
"-Wall",
"-Wno-deprecated-declarations",
"-Os",
"-I/usr/X11R6/include",
"-I/usr/include/freetype2",
"-D_DEFAULT_SOURCE",
"-D_BSD_SOURCE",
"-D_POSIX_C_SOURCE=200809L",
"-DVERSION=\"6.3\"",
"-DXINERAMA",
"dwm.c"
],
"directory": "/home/luca/.local/src/dwm",
"file": "/home/luca/.local/src/dwm/dwm.c"
},
{
"arguments": [
"/usr/bin/cc",
"-c",
"-std=c99",
"-pedantic",
"-Wall",
"-Wno-deprecated-declarations",
"-Os",
"-I/usr/X11R6/include",
"-I/usr/include/freetype2",
"-D_DEFAULT_SOURCE",
"-D_BSD_SOURCE",
"-D_POSIX_C_SOURCE=200809L",
"-DVERSION=\"6.3\"",
"-DXINERAMA",
"util.c"
],
"directory": "/home/luca/.local/src/dwm",
"file": "/home/luca/.local/src/dwm/util.c"
}
]

342
config.h Normal file
View File

@ -0,0 +1,342 @@
/* See LICENSE file for copyright and license details. */
#define BROWSER "librewolf"
#define TERMINAL "kitty"
/* appearance */
static unsigned int borderpx = 2; /* border pixel of windows */
static unsigned int snap = 20; /* snap pixel */
static unsigned int gappih = 10; /* horiz inner gap between windows */
static unsigned int gappiv = 10; /* vert inner gap between windows */
static unsigned int gappoh = 10; /* horiz outer gap between windows and screen edge */
static unsigned int gappov = 10; /* vert outer gap between windows and screen edge */
static int smartgaps = 0; /* 1 means no outer gap when there is only one window */
static int swallowfloating = 0; /* 1 means swallow floating windows by default */
static int showbar = 1; /* 0 means no bar */
static int topbar = 1; /* 0 means bottom bar */
static const char *fonts[] = { "monospace:size=10", "monospace:size=14", "monospace:size=20", "NotoColorEmoji:pixelsize=10:antialias=true:autohint=true" };
static char color0[] = "#000000";
static char color1[] = "#7f0000";
static char color2[] = "#007f00";
static char color3[] = "#7f7f00";
static char color4[] = "#00007f";
static char color5[] = "#7f007f";
static char color6[] = "#007f7f";
static char color7[] = "#cccccc";
static char color8[] = "#333333";
static char color9[] = "#ff0000";
static char color10[] = "#00ff00";
static char color11[] = "#ffff00";
static char color12[] = "#0000ff";
static char color13[] = "#ff00ff";
static char color14[] = "#00ffff";
static char color15[] = "#ffffff";
static char bordernorm[] = "#222222";
static char bordersel[] = "#444444";
static char *colors[][3] = {
/* fg bg border */
[SchemeNorm] = { color15, color0, bordernorm },
[SchemeSel] = { color15, color4, bordersel },
[SchemeStatus] = { color7, color0, "#000000" }, // Statusbar right
[SchemeTagsSel] = { color0, color4, "#000000" }, // Tagbar left selected
[SchemeTagsNorm] = { color7, color0, "#000000" }, // Tagbar left unselected
[SchemeInfoSel] = { color7, color0, "#000000" }, // infobar middle selected
[SchemeInfoNorm] = { color7, color0, "#000000" }, // infobar middle unselected
};
/* Colors for SGR escapes */
static const char *barcolors[] = {
color0,
color1,
color2,
color3,
color4,
color5,
color6,
color7,
color8,
color9,
color10,
color11,
color12,
color13,
color14,
color15,
};
/* tagging */
static char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" };
static const Rule rules[] = {
/* xprop(1):
* WM_CLASS(STRING) = instance, class
* WM_NAME(STRING) = title
*/
/* class instance title scratch key tags mask isfloating isterminal noswallow x, y, w, h floatborderpx monitor */
{ "Gimp", NULL, NULL, 0, 0, 1, 0, 0, -1, -1, -1, -1, -1, -1},
{ "Qalculate-gtk", NULL, NULL, 'q', 0, 1, 0, 0, .5, .5, 722, 512, -1, -1},
{ NULL, "dropterm", NULL, 'd', 0, 1, 0, 0, 0, 0, 1, 1, 0, 1},
{ NULL, "splf", NULL, 'l', 0, 1, 0, 0, .5, .5, .5, .5, -1, -1},
{ NULL, "sphtop", NULL, 'h', 0, 1, 0, 0, .5, .5, .5, .5, -1, -1},
{ NULL, NULL, "Event Tester", 0, 0, 0, 0, 1, -1, -1, -1, -1, -1, -1},
};
/* layout(s) */
static float mfact = 0.55; /* factor of master area size [0.05..0.95] */
static int nmaster = 1; /* number of clients in master area */
static int resizehints = 1; /* 1 means respect size hints in tiled resizals */
static int lockfullscreen = 1; /* 1 will force focus on the fullscreen window */
#define FORCE_VSPLIT 1 /* nrowgrid layout: force two clients to always split vertically */
#include "vanitygaps.c"
static const Layout layouts[] = {
/* symbol arrange function */
{ "[]=", tile }, /* first entry is default */
{ "[M]", monocle },
{ "[@]", spiral },
{ "[\\]", dwindle },
{ "H[]", deck },
{ "TTT", bstack },
{ "===", bstackhoriz },
{ "HHH", grid },
{ "###", nrowgrid },
{ "---", horizgrid },
{ ":::", gaplessgrid },
{ "|M|", centeredmaster },
{ ">M>", centeredfloatingmaster },
{ "><>", 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 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} }
/* commands */
static const char *spqalc[] = { "q", "qalculate-gtk", NULL };
static const char *splf[] = { "l", "kitty", "--name", "splf", "-d", "~", "-e", "lf", NULL };
static const char *sphtop[] = { "h", "kitty", "--name", "sphtop", "-e", "htop", NULL };
/*
* Xresources preferences to load at startup
*/
ResourcePref resources[] = {
{ "color0", STRING, &color0 },
{ "color1", STRING, &color1 },
{ "color2", STRING, &color2 },
{ "color3", STRING, &color3 },
{ "color4", STRING, &color4 },
{ "color5", STRING, &color5 },
{ "color6", STRING, &color6 },
{ "color7", STRING, &color7 },
{ "color8", STRING, &color8 },
{ "color9", STRING, &color9 },
{ "color10", STRING, &color10 },
{ "color11", STRING, &color11 },
{ "color12", STRING, &color12 },
{ "color13", STRING, &color13 },
{ "color14", STRING, &color14 },
{ "color15", STRING, &color15 },
{ "bordernorm", STRING, &bordernorm },
{ "bordersel", STRING, &bordersel },
};
#include <X11/XF86keysym.h>
static Key keys[] = {
STACKKEYS(MODKEY, focus) STACKKEYS(MODKEY | ShiftMask, push)
/* modifier key function argument */
{ MODKEY, XK_F1, spawn, SHCMD("groff -mom /usr/local/share/dwm/keybinds.mom -Tpdf | zathura -") },
{ MODKEY, XK_F2, spawn, {.v = (const char *[]){TERMINAL, "-e", "deluge-console"}} },
{ MODKEY, XK_F3, spawn, SHCMD(TERMINAL "-e pulsemixer; kill -44 $(pidof dwmblocks)") },
/*{ MODKEY, XK_F4, spawn, {.v = (const char *[]){NULL}} },*/
/*{ MODKEY, XK_F5, spawn, {.v = (const char *[]){NULL}} },*/
/*{ MODKEY, XK_F6, spawn, {.v = (const char *[]){NULL}} },*/
/*{ MODKEY, XK_F7, spawn, {.v = (const char *[]){NULL}} },*/
/*{ MODKEY, XK_F8, spawn, {.v = (const char *[]){NULL}} },*/
{ MODKEY, XK_F9, spawn, {.v = (const char *[]){"dmenumount", NULL}} },
{ MODKEY, XK_F10, spawn, {.v = (const char *[]){"dmenuumount", NULL}} },
/*{ MODKEY, XK_F11, spawn, {.v = (const char *[]){NULL}} },*/
{ MODKEY, XK_F12, spawn, {.v = (const char *[]){"remaps", NULL}} },
{ MODKEY, XK_asciicircum, spawn, {.v = (const char *[]){"dmenuunicode", NULL}} },
/*{ MODKEY | ShiftMask, XK_asciicircum, spawn, {.v = (const char *[]){NULL}} },*/
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_ssharp, spawn, SHCMD("pamixer --allow-boost -d 5; kill -44 $(pidof dwmblocks)") },
{ MODKEY | ShiftMask, XK_ssharp, spawn, SHCMD("pamixer --allow-boost -d 15; kill -44 $(pidof dwmblocks)") },
{ MODKEY, XK_acute, spawn, SHCMD("pamixer --allow-boost -i 5; kill -44 $(pidof dwmblocks)") },
{ MODKEY | ShiftMask, XK_acute, spawn, SHCMD("pamixer --allow-boost -i 15; kill -44 $(pidof dwmblocks)") },
{ MODKEY, XK_BackSpace, spawn, {.v = (const char *[]){"sysact", NULL}} },
{ MODKEY | ShiftMask, XK_BackSpace, spawn, {.v = (const char *[]){"sysact", NULL}} },
{ MODKEY, XK_Tab, view, {0} },
/*{ MODKEY|ShiftMask, XK_Tab, spawn, {.v = (const char *[]){NULL}}},*/
{ MODKEY, XK_q, killclient, {0} },
{ MODKEY | ShiftMask, XK_q, spawn, {.v = (const char *[]){"sysact", NULL}} },
{ MODKEY, XK_w, spawn, {.v = (const char *[]){BROWSER, NULL}} },
{ MODKEY | ShiftMask, XK_w, spawn, {.v = (const char *[]){TERMINAL, "-e", "sudo", "nmtui", NULL}} },
{ MODKEY, XK_e, togglescratch, {.v = splf} },
/*{ MODKEY | ShiftMask, XK_e, spawn, {.v = (const char *[]){NULL}} },*/
{ MODKEY, XK_r, togglescratch, {.v = sphtop} },
{ MODKEY | ShiftMask, XK_r, spawn, {.v = (const char *[]){TERMINAL, "-e", "htop", NULL}} },
{ MODKEY, XK_t, setlayout, {.v = &layouts[0]} }, /* tile */
{ MODKEY | ShiftMask, XK_t, setlayout, {.v = &layouts[1]} }, /* bstack */
{ MODKEY, XK_z, setlayout, {.v = &layouts[2]} }, /* spiral */
{ MODKEY | ShiftMask, XK_z, 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_p, spawn, {.v = (const char *[]){"mpc", "toggle", NULL}} },
{ MODKEY | ShiftMask, XK_p, spawn, SHCMD("mpc pause ; pauseallmpv") },
{ MODKEY, XK_udiaeresis, spawn, {.v = (const char *[]){"mpc", "seek", "-10", NULL}} },
{ MODKEY | ShiftMask, XK_udiaeresis, spawn, {.v = (const char *[]){"mpc", "seek", "-60", NULL}} },
{ MODKEY, XK_plus, spawn, {.v = (const char *[]){"mpc", "seek", "+10", NULL}} },
{ MODKEY | ShiftMask, XK_plus, spawn, {.v = (const char *[]){"mpc", "seek", "+60", NULL}} },
{ MODKEY, XK_a, togglegaps, {0} },
{ MODKEY | ShiftMask, XK_a, defaultgaps, {0} },
/*{ MODKEY, XK_s, spawn, {.v = (const char *[]){NULL}} },*/
/*{ MODKEY | ShiftMask, XK_s, spawn, {.v = (const char *[]){NULL}} },*/
{ MODKEY, XK_d, spawn, {.v = (const char *[]){"dmenu_run", NULL}} },
{ MODKEY | ShiftMask, XK_d, spawn, {.v = (const char *[]){"passmenu", NULL}} },
{ MODKEY, XK_f, togglefullscr, {0} },
{ MODKEY | ShiftMask, XK_f, setlayout, {.v = &layouts[8]} }, /* floating */
/*{ MODKEY, XK_g, spawn, {.v = (const char *[]){NULL}} },*/
/*{ MODKEY | ShiftMask, XK_g, spawn, {.v = (const char *[]){NULL}} },*/
{ MODKEY, XK_h, setmfact, {.f = -0.05} },
/*{ MODKEY | ShiftMask, XK_h, spawn, {.v = (const char *[]){NULL}} },*/
/* J and K are automatically bound above in STACKEYS */
{ MODKEY, XK_l, setmfact, {.f = +0.05} },
/*{ MODKEY | ShiftMask, XK_l, spawn, {.v = (const char *[]){NULL}} },*/
/*{ MODKEY, XK_odiaeresis, spawn, {.v = (const char *[]){NULL}} },*/
/*{ MODKEY | ShiftMask, XK_odiaeresis, spawn, {.v = (const char *[]){NULL}} },*/
/*{ MODKEY, XK_adiaeresis, spawn, {.v = (const char *[]){NULL}} },*/
/*{ MODKEY | ShiftMask, XK_adiaeresis, spawn, {.v = (const char *[]){NULL}} },*/
{ MODKEY, XK_numbersign, togglescratch, {.v = spqalc} },
/*{ MODKEY | ShiftMask, XK_numbersign, spawn, {.v = (const char *[]){NULL}} },*/
{ MODKEY, XK_Return, spawn, {.v = (const char *[]){TERMINAL, "-d", "~", NULL}} },
{ MODKEY | ShiftMask, XK_Return, spawnsshaware, {.v = (const char *[]){TERMINAL, "-d", "~", NULL}} },
/*{ MODKEY, XK_y, spawn, {.v = (const char *[]){NULL}} },*/
/*{ MODKEY | ShiftMask, XK_y, spawn, {.v = (const char *[]){NULL}} },*/
/*{ MODKEY, XK_x, spawn, {.v = (const char *[]){NULL}} },*/
/*{ MODKEY | ShiftMask, XK_x, spawn, {.v = (const char *[]){NULL}} },*/
/*{ MODKEY, XK_c, spawn, {.v = (const char *[]){NULL}} },*/
/*{ MODKEY | ShiftMask, XK_c, spawn, {.v = (const char *[]){NULL}} },*/
/* V is automatically bound above in STACKKEYS */
{ MODKEY, XK_b, togglebar, {0} },
/*{ MODKEY | ShiftMask, XK_b, spawn, {.v = (const char *[]){NULL}} },*/
{ MODKEY, XK_n, spawn, {.v = (const char *[]){TERMINAL, "-e", "nvim", "-c", "VimwikiIndex", NULL}} },
/*{ MODKEY | ShiftMask, XK_n, spawn, {.v = (const char *[]){NULL}} },*/
{ MODKEY, XK_m, spawn, {.v = (const char *[]){TERMINAL, "-e", "ncmpcpp", NULL}} },
{ MODKEY | ShiftMask, XK_m, spawn, SHCMD("pamixer -t; kill -44 $(pidof dwmblocks)") },
{ MODKEY, XK_comma, spawn, {.v = (const char *[]){"mpc", "prev", NULL}} },
{ MODKEY | ShiftMask, XK_comma, spawn, {.v = (const char *[]){"mpc", "seek", "0%", NULL}} },
{ MODKEY, XK_period, spawn, {.v = (const char *[]){"mpc", "next", NULL}} },
{ MODKEY | ShiftMask, XK_period, spawn, {.v = (const char *[]){"mpc", "repeat", NULL}} },
/*{ MODKEY, XK_minus, spawn, {.v = (const char *[]){NULL}} },*/
/*{ MODKEY | ShiftMask, XK_minus, spawn, {.v = (const char *[]){NULL}} },*/
{ MODKEY, XK_space, zoom, {0} },
{ MODKEY | ShiftMask, XK_space, togglefloating, {0} },
{ 0, XK_Print, spawn, SHCMD("maim pic-full-$(date '+%y%m%d-%H%M-%S').png") },
{ ShiftMask, XK_Print, spawn, {.v = (const char *[]){"maimpick", NULL}} },
{ MODKEY, XK_Print, spawn, {.v = (const char *[]){"dmenurecord", NULL}} },
{ MODKEY | ShiftMask, XK_Print, spawn, {.v = (const char *[]){"dmenurecord", "kill", NULL}} },
/*{ MODKEY, XK_Scroll_Lock, spawn, {.v = (const char *[]){NULL}} },*/
/*{ MODKEY | ShiftMask, XK_Scroll_Lock, spawn, {.v = (const char *[]){NULL}} },*/
/*{ MODKEY, XK_Pause, spawn, {.v = (const char *[]){NULL}} },*/
/*{ MODKEY | ShiftMask, XK_Pause, spawn, {.v = (const char *[]){NULL}} },*/
{ MODKEY, XK_Insert, spawn, SHCMD("xdotool type $(grep -v '^#' ~/.local/share/snippets | dmenu -i -l " "50 | cut -d' ' -f1)") },
/*{ MODKEY | ShiftMask, XK_Insert, spawn, {.v = (const char *[]){NULL}} },*/
/*{ MODKEY, XK_Home, spawn, {.v = (const char *[]){NULL}} },*/
/*{ MODKEY | ShiftMask, XK_Home, spawn, {.v = (const char *[]){NULL}} },*/
{ MODKEY, XK_Delete, spawn, {.v = (const char *[]){"dmenurecord", "kill", NULL}} },
/*{ MODKEY | ShiftMask, XK_Delete, spawn, {.v = (const char *[]){NULL}} },*/
/*{ MODKEY, XK_End, spawn, {.v = (const char *[]){NULL}} },*/
{ MODKEY | ShiftMask, XK_End, quit, {0} },
/*{ MODKEY, XK_Page_Up, spawn, {.v = (const char *[]){NULL}} },*/
/*{ MODKEY | ShiftMask, XK_Page_Up, spawn, {.v = (const char *[]){NULL}} },*/
/*{ MODKEY, XK_Page_Down, spawn, {.v = (const char *[]){NULL}} },*/
/*{ MODKEY | ShiftMask, XK_Page_Down, spawn, {.v = (const char *[]){NULL}} },*/
{ MODKEY, XK_Left, focusmon, {.i = -1} },
{ MODKEY | ShiftMask, XK_Left, tagmon, {.i = -1} },
{ MODKEY, XK_Right, focusmon, {.i = +1} },
{ MODKEY | ShiftMask, XK_Right, tagmon, {.i = +1} },
/*{ MODKEY, XK_Up, spawn, {.v = (const char *[]){NULL}} },*/
/*{ MODKEY | ShiftMask, XK_Up, spawn, {.v = (const char *[]){NULL}} },*/
/*{ MODKEY, XK_Down, spawn, {.v = (const char *[]){NULL}} },*/
/*{ MODKEY | ShiftMask, XK_Down, spawn, {.v = (const char *[]){NULL}} },*/
{ 0, XF86XK_AudioMute, spawn, SHCMD("pamixer -t; kill -44 $(pidof dwmblocks)") },
{ 0, XF86XK_AudioRaiseVolume, spawn, SHCMD("pamixer --allow-boost -i 3; kill -44 $(pidof dwmblocks)") },
{ 0, XF86XK_AudioLowerVolume, spawn, SHCMD("pamixer --allow-boost -d 3; kill -44 $(pidof dwmblocks)") },
{ 0, XF86XK_AudioPrev, spawn, {.v = (const char *[]){"mpc", "prev", NULL}} },
{ 0, XF86XK_AudioNext, spawn, {.v = (const char *[]){"mpc", "next", NULL}} },
{ 0, XF86XK_AudioPause, spawn, {.v = (const char *[]){"mpc", "pause", NULL}} },
{ 0, XF86XK_AudioPlay, spawn, {.v = (const char *[]){"mpc", "play", NULL}} },
{ 0, XF86XK_AudioStop, spawn, {.v = (const char *[]){"mpc", "stop", NULL}} },
{ 0, XF86XK_AudioRewind, spawn, {.v = (const char *[]){"mpc", "seek", "-10", NULL}} },
{ 0, XF86XK_AudioForward, spawn, {.v = (const char *[]){"mpc", "seek", "+10", NULL}} },
{ 0, XF86XK_AudioMedia, spawn, {.v = (const char *[]){TERMINAL, "-e", "ncmpcpp", NULL}} },
{ 0, XF86XK_AudioMicMute, spawn, SHCMD("pactl set-source-mute @DEFAULT_SOURCE@ toggle") },
{ 0, XF86XK_PowerOff, spawn, {.v = (const char *[]){"sysact", NULL}} },
{ 0, XF86XK_Calculator, spawn, {.v = (const char *[]){TERMINAL, "-e", "bc", "-l", NULL}} },
{ 0, XF86XK_Sleep, spawn, {.v = (const char *[]){"sudo", "-A", "zzz", NULL}} },
{ 0, XF86XK_WWW, spawn, {.v = (const char *[]){BROWSER, NULL}} },
{ 0, XF86XK_DOS, spawn, {.v = (const char *[]){TERMINAL, NULL}} },
{ 0, XF86XK_ScreenSaver, spawn, SHCMD("xset s activate & mpc pause & pauseallmpv") },
{ 0, XF86XK_TaskPane, spawn, {.v = (const char *[]){TERMINAL, "-e", "htop", NULL}} },
{ 0, XF86XK_Mail, spawn, SHCMD("kitty -e neomutt; pkill -RTMIN+12 dwmblocks") },
{ 0, XF86XK_MyComputer, spawn, {.v = (const char *[]){TERMINAL, "-e", "lfub", "/", NULL}} },
/*{ 0, XF86XK_Battery, spawn, {.v = (const char *[]){NULL}} }, */
{ 0, XF86XK_Launch1, spawn, {.v = (const char *[]){"xset", "dpms", "force", "off", NULL}} },
{ 0, XF86XK_TouchpadToggle, spawn, SHCMD("(synclient | grep 'TouchpadOff.*1' && synclient TouchpadOff=0) || " "synclient TouchpadOff=1") },
{ 0, XF86XK_TouchpadOff, spawn, {.v = (const char *[]){"synclient", "TouchpadOff=1", NULL}} },
{ 0, XF86XK_TouchpadOn, spawn, {.v = (const char *[]){"synclient", "TouchpadOff=0", NULL}} },
{ 0, XF86XK_MonBrightnessUp, spawn, {.v = (const char *[]){"xbacklight", "-inc", "15", NULL}} },
{ 0, XF86XK_MonBrightnessDown, spawn, {.v = (const char *[]){"xbacklight", "-dec", "15", NULL}} },
};
/* 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} },
{ 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} },
};

39
config.mk Normal file
View File

@ -0,0 +1,39 @@
# dwm version
VERSION = 6.3
# Customize below to fit your system
# paths
PREFIX = /usr/local
MANPREFIX = ${PREFIX}/share/man
X11INC = /usr/X11R6/include
X11LIB = /usr/X11R6/lib
# Xinerama, comment if you don't want it
XINERAMALIBS = -lXinerama
XINERAMAFLAGS = -DXINERAMA
# freetype
FREETYPELIBS = -lfontconfig -lXft
FREETYPEINC = /usr/include/freetype2
# OpenBSD (uncomment)
#FREETYPEINC = ${X11INC}/freetype2
#KVMLIB = -lkvm
# includes and libs
INCS = -I${X11INC} -I${FREETYPEINC}
LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} -lX11-xcb -lxcb -lxcb-res ${KVMLIB} -lprocps
# flags
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}
# Solaris
#CFLAGS = -fast ${INCS} -DVERSION=\"${VERSION}\"
#LDFLAGS = ${LIBS}
# compiler and linker
CC = cc

436
drw.c Normal file
View File

@ -0,0 +1,436 @@
/* See LICENSE file for copyright and license details. */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <X11/Xlib.h>
#include <X11/Xft/Xft.h>
#include "drw.h"
#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)
{
size_t i, j, len, type;
long udecoded;
*u = UTF_INVALID;
if (!clen)
return 0;
udecoded = utf8decodebyte(c[0], &len);
if (!BETWEEN(len, 1, UTF_SIZ))
return 1;
for (i = 1, j = 1; i < clen && j < len; ++i, ++j) {
udecoded = (udecoded << 6) | utf8decodebyte(c[i], &type);
if (type)
return j;
}
if (j < len)
return 0;
*u = udecoded;
utf8validate(u, len);
return len;
}
Drw *
drw_create(Display *dpy, int screen, Window root, unsigned int w, unsigned int h)
{
Drw *drw = ecalloc(1, sizeof(Drw));
drw->dpy = dpy;
drw->screen = screen;
drw->root = root;
drw->w = w;
drw->h = h;
drw->drawable = XCreatePixmap(dpy, root, w, h, DefaultDepth(dpy, screen));
drw->gc = XCreateGC(dpy, root, 0, NULL);
XSetLineAttributes(dpy, drw->gc, 1, LineSolid, CapButt, JoinMiter);
return drw;
}
void
drw_resize(Drw *drw, unsigned int w, unsigned int h)
{
if (!drw)
return;
drw->w = w;
drw->h = h;
if (drw->drawable)
XFreePixmap(drw->dpy, drw->drawable);
drw->drawable = XCreatePixmap(drw->dpy, drw->root, w, h, DefaultDepth(drw->dpy, drw->screen));
}
void
drw_free(Drw *drw)
{
XFreePixmap(drw->dpy, drw->drawable);
XFreeGC(drw->dpy, drw->gc);
drw_fontset_free(drw->fonts);
free(drw);
}
/* This function is an implementation detail. Library users should use
* drw_fontset_create instead.
*/
static Fnt *
xfont_create(Drw *drw, const char *fontname, FcPattern *fontpattern)
{
Fnt *font;
XftFont *xfont = NULL;
FcPattern *pattern = NULL;
if (fontname) {
/* Using the pattern found at font->xfont->pattern does not yield the
* same substitution results as using the pattern returned by
* FcNameParse; using the latter results in the desired fallback
* behaviour whereas the former just results in missing-character
* rectangles being drawn, at least with some fonts. */
if (!(xfont = XftFontOpenName(drw->dpy, drw->screen, fontname))) {
fprintf(stderr, "error, cannot load font from name: '%s'\n", fontname);
return NULL;
}
if (!(pattern = FcNameParse((FcChar8 *) fontname))) {
fprintf(stderr, "error, cannot parse font name to pattern: '%s'\n", fontname);
XftFontClose(drw->dpy, xfont);
return NULL;
}
} else if (fontpattern) {
if (!(xfont = XftFontOpenPattern(drw->dpy, fontpattern))) {
fprintf(stderr, "error, cannot load font from pattern.\n");
return NULL;
}
} else {
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;
font->h = xfont->ascent + xfont->descent;
font->dpy = drw->dpy;
return font;
}
static void
xfont_free(Fnt *font)
{
if (!font)
return;
if (font->pattern)
FcPatternDestroy(font->pattern);
XftFontClose(font->dpy, font->xfont);
free(font);
}
Fnt*
drw_fontset_create(Drw* drw, const char *fonts[], size_t fontcount)
{
Fnt *cur, *ret = NULL;
size_t i;
if (!drw || !fonts)
return NULL;
for (i = 1; i <= fontcount; i++) {
if ((cur = xfont_create(drw, fonts[fontcount - i], NULL))) {
cur->next = ret;
ret = cur;
}
}
return (drw->fonts = ret);
}
void
drw_fontset_free(Fnt *font)
{
if (font) {
drw_fontset_free(font->next);
xfont_free(font);
}
}
void
drw_clr_create(Drw *drw, Clr *dest, const char *clrname)
{
if (!drw || !dest || !clrname)
return;
if (!XftColorAllocName(drw->dpy, DefaultVisual(drw->dpy, drw->screen),
DefaultColormap(drw->dpy, drw->screen),
clrname, dest))
die("error, cannot allocate color '%s'", clrname);
}
/* 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, char *clrnames[], size_t clrcount)
{
size_t i;
Clr *ret;
/* need at least two colors for a scheme */
if (!drw || !clrnames || clrcount < 2 || !(ret = ecalloc(clrcount, sizeof(XftColor))))
return NULL;
for (i = 0; i < clrcount; i++)
drw_clr_create(drw, &ret[i], clrnames[i]);
return ret;
}
void
drw_setfontset(Drw *drw, Fnt *set)
{
if (drw)
drw->fonts = set;
}
void
drw_setscheme(Drw *drw, Clr *scm)
{
if (drw)
drw->scheme = scm;
}
void
drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int invert)
{
if (!drw || !drw->scheme)
return;
XSetForeground(drw->dpy, drw->gc, invert ? drw->scheme[ColBg].pixel : drw->scheme[ColFg].pixel);
if (filled)
XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h);
else
XDrawRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w - 1, h - 1);
}
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;
XftDraw *d = NULL;
Fnt *usedfont, *curfont, *nextfont;
size_t i, len;
int utf8strlen, utf8charlen, render = x || y || w || h;
long utf8codepoint = 0;
const char *utf8str;
FcCharSet *fccharset;
FcPattern *fcpattern;
FcPattern *match;
XftResult result;
int charexists = 0;
if (!drw || (render && !drw->scheme) || !text || !drw->fonts)
return 0;
if (!render) {
w = ~w;
} else {
XSetForeground(drw->dpy, drw->gc, drw->scheme[invert ? ColFg : ColBg].pixel);
XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h);
d = XftDrawCreate(drw->dpy, drw->drawable,
DefaultVisual(drw->dpy, drw->screen),
DefaultColormap(drw->dpy, drw->screen));
x += lpad;
w -= lpad;
}
usedfont = drw->fonts;
while (1) {
utf8strlen = 0;
utf8str = text;
nextfont = NULL;
while (*text) {
utf8charlen = utf8decode(text, &utf8codepoint, UTF_SIZ);
for (curfont = drw->fonts; curfont; curfont = curfont->next) {
charexists = charexists || XftCharExists(drw->dpy, curfont->xfont, utf8codepoint);
if (charexists) {
if (curfont == usedfont) {
utf8strlen += utf8charlen;
text += utf8charlen;
} else {
nextfont = curfont;
}
break;
}
}
if (!charexists || nextfont)
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 (!*text) {
break;
} else if (nextfont) {
charexists = 0;
usedfont = nextfont;
} else {
/* Regardless of whether or not a fallback font is found, the
* character must be drawn. */
charexists = 1;
fccharset = FcCharSetCreate();
FcCharSetAddChar(fccharset, utf8codepoint);
if (!drw->fonts->pattern) {
/* Refer to the comment in xfont_create for more information. */
die("the first font in the cache must be loaded from a font string.");
}
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);
match = XftFontMatch(drw->dpy, drw->screen, fcpattern, &result);
FcCharSetDestroy(fccharset);
FcPatternDestroy(fcpattern);
if (match) {
usedfont = xfont_create(drw, NULL, match);
if (usedfont && XftCharExists(drw->dpy, usedfont->xfont, utf8codepoint)) {
for (curfont = drw->fonts; curfont->next; curfont = curfont->next)
; /* NOP */
curfont->next = usedfont;
} else {
xfont_free(usedfont);
usedfont = drw->fonts;
}
}
}
}
if (d)
XftDrawDestroy(d);
return x + (render ? w : 0);
}
void
drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h)
{
if (!drw)
return;
XCopyArea(drw->dpy, drw->drawable, win, drw->gc, x, y, w, h, x, y);
XSync(drw->dpy, False);
}
unsigned int
drw_fontset_getwidth(Drw *drw, const char *text)
{
if (!drw || !drw->fonts || !text)
return 0;
return drw_text(drw, 0, 0, 0, 0, 0, text, 0);
}
void
drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h)
{
XGlyphInfo ext;
if (!font || !text)
return;
XftTextExtentsUtf8(font->dpy, font->xfont, (XftChar8 *)text, len, &ext);
if (w)
*w = ext.xOff;
if (h)
*h = font->h;
}
Cur *
drw_cur_create(Drw *drw, int shape)
{
Cur *cur;
if (!drw || !(cur = ecalloc(1, sizeof(Cur))))
return NULL;
cur->cursor = XCreateFontCursor(drw->dpy, shape);
return cur;
}
void
drw_cur_free(Drw *drw, Cur *cursor)
{
if (!cursor)
return;
XFreeCursor(drw->dpy, cursor->cursor);
free(cursor);
}

57
drw.h Normal file
View File

@ -0,0 +1,57 @@
/* See LICENSE file for copyright and license details. */
typedef struct {
Cursor cursor;
} Cur;
typedef struct Fnt {
Display *dpy;
unsigned int h;
XftFont *xfont;
FcPattern *pattern;
struct Fnt *next;
} Fnt;
enum { ColFg, ColBg, ColBorder }; /* Clr scheme index */
typedef XftColor Clr;
typedef struct {
unsigned int w, h;
Display *dpy;
int screen;
Window root;
Drawable drawable;
GC gc;
Clr *scheme;
Fnt *fonts;
} Drw;
/* Drawable abstraction */
Drw *drw_create(Display *dpy, int screen, Window win, unsigned int w, unsigned int h);
void drw_resize(Drw *drw, unsigned int w, unsigned int h);
void drw_free(Drw *drw);
/* Fnt abstraction */
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);
void drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h);
/* Colorscheme abstraction */
void drw_clr_create(Drw *drw, Clr *dest, const char *clrname);
Clr *drw_scm_create(Drw *drw, char *clrnames[], size_t clrcount);
/* Cursor abstraction */
Cur *drw_cur_create(Drw *drw, int shape);
void drw_cur_free(Drw *drw, Cur *cursor);
/* Drawing context manipulation */
void drw_setfontset(Drw *drw, Fnt *set);
void drw_setscheme(Drw *drw, Clr *scm);
/* Drawing functions */
void drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int invert);
int drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert);
/* Map functions */
void drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h);

2974
dwm.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,68 @@
From eea13010ffc3983392857ee1e3804e3aa1064d7a Mon Sep 17 00:00:00 2001
From: Soenke Lambert <s.lambert@mittwald.de>
Date: Wed, 13 Oct 2021 18:21:09 +0200
Subject: [PATCH] Fullscreen current window with [Alt]+[Shift]+[f]
This actually fullscreens a window, instead of just hiding the statusbar
and applying the monocle layout.
---
config.def.h | 1 +
dwm.1 | 3 +++
dwm.c | 8 ++++++++
3 files changed, 12 insertions(+)
diff --git a/config.def.h b/config.def.h
index 1c0b587..8cd3204 100644
--- a/config.def.h
+++ b/config.def.h
@@ -78,6 +78,7 @@ static Key keys[] = {
{ MODKEY, XK_m, setlayout, {.v = &layouts[2]} },
{ MODKEY, XK_space, setlayout, {0} },
{ MODKEY|ShiftMask, XK_space, togglefloating, {0} },
+ { MODKEY|ShiftMask, XK_f, togglefullscr, {0} },
{ MODKEY, XK_0, view, {.ui = ~0 } },
{ MODKEY|ShiftMask, XK_0, tag, {.ui = ~0 } },
{ MODKEY, XK_comma, focusmon, {.i = -1 } },
diff --git a/dwm.1 b/dwm.1
index 13b3729..a368d05 100644
--- a/dwm.1
+++ b/dwm.1
@@ -116,6 +116,9 @@ Zooms/cycles focused window to/from master area (tiled layouts only).
.B Mod1\-Shift\-c
Close focused window.
.TP
+.B Mod1\-Shift\-f
+Toggle fullscreen for focused window.
+.TP
.B Mod1\-Shift\-space
Toggle focused window between tiled and floating state.
.TP
diff --git a/dwm.c b/dwm.c
index 4465af1..c1b899a 100644
--- a/dwm.c
+++ b/dwm.c
@@ -211,6 +211,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 togglefullscr(const Arg *arg);
static void toggletag(const Arg *arg);
static void toggleview(const Arg *arg);
static void unfocus(Client *c, int setfocus);
@@ -1719,6 +1720,13 @@ togglefloating(const Arg *arg)
arrange(selmon);
}
+void
+togglefullscr(const Arg *arg)
+{
+ if(selmon->sel)
+ setfullscreen(selmon->sel, !selmon->sel->isfullscreen);
+}
+
void
toggletag(const Arg *arg)
{
--
2.30.2

View File

@ -0,0 +1,88 @@
From 17acbdcb56d0d2f39507a3f67ef329c14a213ef6 Mon Sep 17 00:00:00 2001
From: MLquest8 <miskuzius@gmail.com>
Date: Thu, 18 Jun 2020 15:34:18 +0400
Subject: [PATCH] attachtop. Attaches new client below the last master/on top
of the stack. In case of nmaster = 1 behaves like attachaside.
---
dwm.c | 29 +++++++++++++++++++++++++----
1 file changed, 25 insertions(+), 4 deletions(-)
diff --git a/dwm.c b/dwm.c
index 9fd0286..7ced982 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)) \
* 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 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)
@@ -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);
+static void attachtop(Client *c);
static void attachstack(Client *c);
static void buttonpress(XEvent *e);
static void checkotherwm(void);
@@ -407,6 +409,25 @@ attach(Client *c)
c->mon->clients = c;
}
+void
+attachtop(Client *c)
+{
+ int n;
+ Monitor *m = selmon;
+ Client *below;
+
+ for (n = 1, below = c->mon->clients;
+ below && below->next && (below->isfloating || !ISVISIBLEONTAG(below, c->tags) || n != m->nmaster);
+ n = below->isfloating || !ISVISIBLEONTAG(below, c->tags) ? n + 0 : n + 1, below = below->next);
+ c->next = NULL;
+ if (below) {
+ c->next = below->next;
+ below->next = c;
+ }
+ else
+ c->mon->clients = c;
+}
+
void
attachstack(Client *c)
{
@@ -1063,7 +1084,7 @@ manage(Window w, XWindowAttributes *wa)
c->isfloating = c->oldstate = trans != None || c->isfixed;
if (c->isfloating)
XRaiseWindow(dpy, c->win);
- attach(c);
+ attachtop(c);
attachstack(c);
XChangeProperty(dpy, root, netatom[NetClientList], XA_WINDOW, 32, PropModeAppend,
(unsigned char *) &(c->win), 1);
@@ -1418,7 +1439,7 @@ sendmon(Client *c, Monitor *m)
detachstack(c);
c->mon = m;
c->tags = m->tagset[m->seltags]; /* assign tags of target monitor */
- attach(c);
+ attachtop(c);
attachstack(c);
focus(NULL);
arrange(NULL);
@@ -1900,7 +1921,7 @@ updategeom(void)
m->clients = c->next;
detachstack(c);
c->mon = mons;
- attach(c);
+ attachtop(c);
attachstack(c);
}
if (m == selmon)
--
2.26.2

View File

@ -0,0 +1,86 @@
From 647a2a56cf7cab6dea868f9800671770940ce3c3 Mon Sep 17 00:00:00 2001
From: Alessandro Sisto <alessandro.sisto@studioform.net>
Date: Sun, 5 Jun 2022 12:03:43 +0200
Subject: [PATCH] colorbar
---
config.def.h | 6 +++++-
dwm.c | 12 ++++++------
2 files changed, 11 insertions(+), 7 deletions(-)
diff --git a/config.def.h b/config.def.h
index a2ac963..56bc324 100644
--- a/config.def.h
+++ b/config.def.h
@@ -16,6 +16,11 @@ static const char *colors[][3] = {
/* fg bg border */
[SchemeNorm] = { col_gray3, col_gray1, col_gray2 },
[SchemeSel] = { col_gray4, col_cyan, col_cyan },
+ [SchemeStatus] = { col_gray3, col_gray1, "#000000" }, // Statusbar right {text,background,not used but cannot be empty}
+ [SchemeTagsSel] = { col_gray4, col_cyan, "#000000" }, // Tagbar left selected {text,background,not used but cannot be empty}
+ [SchemeTagsNorm] = { col_gray3, col_gray1, "#000000" }, // Tagbar left unselected {text,background,not used but cannot be empty}
+ [SchemeInfoSel] = { col_gray4, col_cyan, "#000000" }, // infobar middle selected {text,background,not used but cannot be empty}
+ [SchemeInfoNorm] = { col_gray3, col_gray1, "#000000" }, // infobar middle unselected {text,background,not used but cannot be empty}
};
/* tagging */
@@ -113,4 +118,3 @@ static Button buttons[] = {
{ ClkTagBar, MODKEY, Button1, tag, {0} },
{ ClkTagBar, MODKEY, Button3, toggletag, {0} },
};
-
diff --git a/dwm.c b/dwm.c
index a96f33c..0eaa4cd 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, SchemeStatus, SchemeTagsSel, SchemeTagsNorm, SchemeInfoSel, SchemeInfoNorm }; /* color schemes */
enum { NetSupported, NetWMName, NetWMState, NetWMCheck,
NetWMFullscreen, NetActiveWindow, NetWMWindowType,
NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH atoms */
@@ -707,7 +707,7 @@ 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]);
+ drw_setscheme(drw, scheme[SchemeStatus]);
tw = TEXTW(stext) - lrpad + 2; /* 2px right padding */
drw_text(drw, m->ww - tw, 0, tw, bh, 0, stext, 0);
}
@@ -720,7 +720,7 @@ 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]);
+ drw_setscheme(drw, scheme[m->tagset[m->seltags] & 1 << i ? SchemeTagsSel : SchemeTagsNorm]);
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,
@@ -729,17 +729,17 @@ drawbar(Monitor *m)
x += w;
}
w = blw = TEXTW(m->ltsymbol);
- drw_setscheme(drw, scheme[SchemeNorm]);
+ drw_setscheme(drw, scheme[SchemeTagsNorm]);
x = drw_text(drw, x, 0, w, bh, lrpad / 2, m->ltsymbol, 0);
if ((w = m->ww - tw - x) > bh) {
if (m->sel) {
- drw_setscheme(drw, scheme[m == selmon ? SchemeSel : SchemeNorm]);
+ drw_setscheme(drw, scheme[m == selmon ? SchemeInfoSel : SchemeInfoNorm]);
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_setscheme(drw, scheme[SchemeInfoNorm]);
drw_rect(drw, x, 0, w, bh, 1, 1);
}
}
--
2.36.1

View File

@ -0,0 +1,71 @@
diff --git a/config.def.h b/config.def.h
index a2ac963..e8c0978 100644
--- a/config.def.h
+++ b/config.def.h
@@ -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 isfloating monitor float x,y,w,h floatborderpx*/
+ { "Gimp", NULL, NULL, 0, 1, -1, 50,50,500,500, 5 },
+ { "Firefox", NULL, NULL, 1 << 8, 0, -1, 50,50,500,500, 5 },
};
/* layout(s) */
diff --git a/dwm.c b/dwm.c
index 5e4d494..a03ca15 100644
--- a/dwm.c
+++ b/dwm.c
@@ -93,6 +93,8 @@ struct Client {
int bw, oldbw;
unsigned int tags;
int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen;
+ int floatborderpx;
+ int hasfloatbw;
Client *next;
Client *snext;
Monitor *mon;
@@ -139,6 +141,8 @@ typedef struct {
unsigned int tags;
int isfloating;
int monitor;
+ int floatx, floaty, floatw, floath;
+ int floatborderpx;
} Rule;
/* function declarations */
@@ -300,6 +304,16 @@ applyrules(Client *c)
{
c->isfloating = r->isfloating;
c->tags |= r->tags;
+ if (r->floatborderpx >= 0) {
+ c->floatborderpx = r->floatborderpx;
+ c->hasfloatbw = 1;
+ }
+ if (r->isfloating) {
+ if (r->floatx >= 0) c->x = c->mon->mx + r->floatx;
+ if (r->floaty >= 0) c->y = c->mon->my + r->floaty;
+ if (r->floatw >= 0) c->w = r->floatw;
+ if (r->floath >= 0) c->h = r->floath;
+ }
for (m = mons; m && m->num != r->monitor; m = m->next);
if (m)
c->mon = m;
@@ -1282,7 +1296,10 @@ resizeclient(Client *c, int x, int y, int w, int h)
c->oldy = c->y; c->y = wc.y = y;
c->oldw = c->w; c->w = wc.width = w;
c->oldh = c->h; c->h = wc.height = h;
- wc.border_width = c->bw;
+ if (c->isfloating && c->hasfloatbw && !c->isfullscreen)
+ wc.border_width = c->floatborderpx;
+ else
+ wc.border_width = c->bw;
XConfigureWindow(dpy, c->win, CWX|CWY|CWWidth|CWHeight|CWBorderWidth, &wc);
configure(c);
XSync(dpy, False);
--
2.32.0

View File

@ -0,0 +1,39 @@
diff --git a/dwm.c b/dwm.c
index a96f33c..f2da729 100644
--- a/dwm.c
+++ b/dwm.c
@@ -432,9 +432,15 @@ buttonpress(XEvent *e)
}
if (ev->window == selmon->barwin) {
i = x = 0;
- do
+ unsigned int occ = 0;
+ for(c = m->clients; c; c=c->next)
+ occ |= 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;
@@ -719,13 +725,12 @@ drawbar(Monitor *m)
}
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);

View File

@ -0,0 +1,138 @@
diff '--color=auto' -up dwm-6.2/config.def.h dwm-6.2-new/config.def.h
--- dwm-6.2/config.def.h 2019-02-02 12:55:28.000000000 +0000
+++ dwm-6.2-new/config.def.h 2020-04-26 13:51:06.713332746 +0100
@@ -26,9 +26,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 monitor scratch key */
+ { "Gimp", NULL, NULL, 0, 1, -1, 0 },
+ { "firefox", NULL, NULL, 1 << 8, 0, -1, 0 },
+ { NULL, NULL, "scratchpad", 0, 1, -1, 's' },
};
/* layout(s) */
@@ -59,10 +60,14 @@ static char dmenumon[2] = "0"; /* compon
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 };
+/*First arg only serves to match against key in rules*/
+static const char *scratchpadcmd[] = {"s", "st", "-t", "scratchpad", 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 '--color=auto' -up dwm-6.2/dwm.c dwm-6.2-new/dwm.c
--- dwm-6.2/dwm.c 2019-02-02 12:55:28.000000000 +0000
+++ dwm-6.2-new/dwm.c 2020-04-26 13:55:56.820584361 +0100
@@ -93,6 +93,7 @@ struct Client {
int bw, oldbw;
unsigned int tags;
int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen;
+ char scratchkey;
Client *next;
Client *snext;
Monitor *mon;
@@ -139,6 +140,7 @@ typedef struct {
unsigned int tags;
int isfloating;
int monitor;
+ const char scratchkey;
} Rule;
/* function declarations */
@@ -206,11 +208,13 @@ 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 spawnscratch(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 toggletag(const Arg *arg);
static void toggleview(const Arg *arg);
static void unfocus(Client *c, int setfocus);
@@ -287,6 +291,7 @@ applyrules(Client *c)
/* rule matching */
c->isfloating = 0;
c->tags = 0;
+ c->scratchkey = 0;
XGetClassHint(dpy, c->win, &ch);
class = ch.res_class ? ch.res_class : broken;
instance = ch.res_name ? ch.res_name : broken;
@@ -299,6 +304,7 @@ applyrules(Client *c)
{
c->isfloating = r->isfloating;
c->tags |= r->tags;
+ c->scratchkey = r->scratchkey;
for (m = mons; m && m->num != r->monitor; m = m->next);
if (m)
c->mon = m;
@@ -308,6 +314,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];
}
@@ -1652,6 +1659,19 @@ spawn(const Arg *arg)
}
}
+void spawnscratch(const Arg *arg)
+{
+ if (fork() == 0) {
+ if (dpy)
+ close(ConnectionNumber(dpy));
+ setsid();
+ execvp(((char **)arg->v)[1], ((char **)arg->v)+1);
+ fprintf(stderr, "dwm: execvp %s", ((char **)arg->v)[1]);
+ perror(" failed");
+ exit(EXIT_SUCCESS);
+ }
+}
+
void
tag(const Arg *arg)
{
@@ -1720,6 +1740,28 @@ togglefloating(const Arg *arg)
}
void
+togglescratch(const Arg *arg)
+{
+ Client *c;
+ unsigned int found = 0;
+
+ for (c = selmon->clients; c && !(found = c->scratchkey == ((char**)arg->v)[0][0]); c = c->next);
+ if (found) {
+ c->tags = ISVISIBLE(c) ? 0 : selmon->tagset[selmon->seltags];
+ focus(NULL);
+ arrange(selmon);
+
+ if (ISVISIBLE(c)) {
+ focus(c);
+ restack(selmon);
+ }
+
+ } else{
+ spawnscratch(arg);
+ }
+}
+
+void
toggletag(const Arg *arg)
{
unsigned int newtags;

View File

@ -0,0 +1,177 @@
diff --git a/dwm.c b/dwm.c
index 664c527..ac8e4ec 100644
--- a/dwm.c
+++ b/dwm.c
@@ -111,6 +111,7 @@ typedef struct {
void (*arrange)(Monitor *);
} Layout;
+typedef struct Pertag Pertag;
struct Monitor {
char ltsymbol[16];
float mfact;
@@ -130,6 +131,7 @@ struct Monitor {
Monitor *next;
Window barwin;
const Layout *lt[2];
+ Pertag *pertag;
};
typedef struct {
@@ -272,6 +274,15 @@ static Window root, wmcheckwin;
/* configuration, allows nested code to access above variables */
#include "config.h"
+struct Pertag {
+ unsigned int curtag, prevtag; /* current and previous tag */
+ int nmasters[LENGTH(tags) + 1]; /* number of windows in master area */
+ float mfacts[LENGTH(tags) + 1]; /* mfacts per tag */
+ unsigned int sellts[LENGTH(tags) + 1]; /* selected layouts */
+ const Layout *ltidxs[LENGTH(tags) + 1][2]; /* matrix of tags and layouts indexes */
+ int showbars[LENGTH(tags) + 1]; /* display bar for the current tag */
+};
+
/* compile-time check if all tags fit into an unsigned int bit array. */
struct NumTags { char limitexceeded[LENGTH(tags) > 31 ? -1 : 1]; };
@@ -632,6 +643,7 @@ Monitor *
createmon(void)
{
Monitor *m;
+ unsigned int i;
m = ecalloc(1, sizeof(Monitor));
m->tagset[0] = m->tagset[1] = 1;
@@ -642,6 +654,20 @@ createmon(void)
m->lt[0] = &layouts[0];
m->lt[1] = &layouts[1 % LENGTH(layouts)];
strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol);
+ m->pertag = ecalloc(1, sizeof(Pertag));
+ m->pertag->curtag = m->pertag->prevtag = 1;
+
+ for (i = 0; i <= LENGTH(tags); i++) {
+ m->pertag->nmasters[i] = m->nmaster;
+ m->pertag->mfacts[i] = m->mfact;
+
+ m->pertag->ltidxs[i][0] = m->lt[0];
+ m->pertag->ltidxs[i][1] = m->lt[1];
+ m->pertag->sellts[i] = m->sellt;
+
+ m->pertag->showbars[i] = m->showbar;
+ }
+
return m;
}
@@ -967,7 +993,7 @@ grabkeys(void)
void
incnmaster(const Arg *arg)
{
- selmon->nmaster = MAX(selmon->nmaster + arg->i, 0);
+ selmon->nmaster = selmon->pertag->nmasters[selmon->pertag->curtag] = MAX(selmon->nmaster + arg->i, 0);
arrange(selmon);
}
@@ -1502,9 +1528,9 @@ void
setlayout(const Arg *arg)
{
if (!arg || !arg->v || arg->v != selmon->lt[selmon->sellt])
- selmon->sellt ^= 1;
+ selmon->sellt = selmon->pertag->sellts[selmon->pertag->curtag] ^= 1;
if (arg && arg->v)
- selmon->lt[selmon->sellt] = (Layout *)arg->v;
+ selmon->lt[selmon->sellt] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt] = (Layout *)arg->v;
strncpy(selmon->ltsymbol, selmon->lt[selmon->sellt]->symbol, sizeof selmon->ltsymbol);
if (selmon->sel)
arrange(selmon);
@@ -1523,7 +1549,7 @@ setmfact(const Arg *arg)
f = arg->f < 1.0 ? arg->f + selmon->mfact : arg->f - 1.0;
if (f < 0.05 || f > 0.95)
return;
- selmon->mfact = f;
+ selmon->mfact = selmon->pertag->mfacts[selmon->pertag->curtag] = f;
arrange(selmon);
}
@@ -1702,7 +1728,7 @@ tile(Monitor *m)
void
togglebar(const Arg *arg)
{
- selmon->showbar = !selmon->showbar;
+ selmon->showbar = selmon->pertag->showbars[selmon->pertag->curtag] = !selmon->showbar;
updatebarpos(selmon);
XMoveResizeWindow(dpy, selmon->barwin, selmon->wx, selmon->by, selmon->ww, bh);
arrange(selmon);
@@ -1741,9 +1767,33 @@ void
toggleview(const Arg *arg)
{
unsigned int newtagset = selmon->tagset[selmon->seltags] ^ (arg->ui & TAGMASK);
+ int i;
if (newtagset) {
selmon->tagset[selmon->seltags] = newtagset;
+
+ if (newtagset == ~0) {
+ selmon->pertag->prevtag = selmon->pertag->curtag;
+ selmon->pertag->curtag = 0;
+ }
+
+ /* test if the user did not select the same tag */
+ if (!(newtagset & 1 << (selmon->pertag->curtag - 1))) {
+ selmon->pertag->prevtag = selmon->pertag->curtag;
+ for (i = 0; !(newtagset & 1 << i); i++) ;
+ selmon->pertag->curtag = i + 1;
+ }
+
+ /* apply settings for this view */
+ selmon->nmaster = selmon->pertag->nmasters[selmon->pertag->curtag];
+ selmon->mfact = selmon->pertag->mfacts[selmon->pertag->curtag];
+ selmon->sellt = selmon->pertag->sellts[selmon->pertag->curtag];
+ selmon->lt[selmon->sellt] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt];
+ selmon->lt[selmon->sellt^1] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt^1];
+
+ if (selmon->showbar != selmon->pertag->showbars[selmon->pertag->curtag])
+ togglebar(NULL);
+
focus(NULL);
arrange(selmon);
}
@@ -2038,11 +2088,37 @@ updatewmhints(Client *c)
void
view(const Arg *arg)
{
+ int i;
+ unsigned int tmptag;
+
if ((arg->ui & TAGMASK) == selmon->tagset[selmon->seltags])
return;
selmon->seltags ^= 1; /* toggle sel tagset */
- if (arg->ui & TAGMASK)
+ if (arg->ui & TAGMASK) {
selmon->tagset[selmon->seltags] = arg->ui & TAGMASK;
+ selmon->pertag->prevtag = selmon->pertag->curtag;
+
+ if (arg->ui == ~0)
+ selmon->pertag->curtag = 0;
+ else {
+ for (i = 0; !(arg->ui & 1 << i); i++) ;
+ selmon->pertag->curtag = i + 1;
+ }
+ } else {
+ tmptag = selmon->pertag->prevtag;
+ selmon->pertag->prevtag = selmon->pertag->curtag;
+ selmon->pertag->curtag = tmptag;
+ }
+
+ selmon->nmaster = selmon->pertag->nmasters[selmon->pertag->curtag];
+ selmon->mfact = selmon->pertag->mfacts[selmon->pertag->curtag];
+ selmon->sellt = selmon->pertag->sellts[selmon->pertag->curtag];
+ selmon->lt[selmon->sellt] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt];
+ selmon->lt[selmon->sellt^1] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt^1];
+
+ if (selmon->showbar != selmon->pertag->showbars[selmon->pertag->curtag])
+ togglebar(NULL);
+
focus(NULL);
arrange(selmon);
}

View File

@ -0,0 +1,68 @@
diff -r -u a/dwm.c b/dwm.c
--- a/dwm.c 2019-02-02 07:55:28.000000000 -0500
+++ b/dwm.c 2022-01-17 22:38:33.614493243 -0500
@@ -1291,9 +1291,14 @@
resizemouse(const Arg *arg)
{
int ocx, ocy, nw, nh;
+ int ocx2, ocy2, nx, ny;
Client *c;
Monitor *m;
XEvent ev;
+ int horizcorner, vertcorner;
+ int di;
+ unsigned int dui;
+ Window dummy;
Time lasttime = 0;
if (!(c = selmon->sel))
@@ -1303,10 +1308,18 @@
restack(selmon);
ocx = c->x;
ocy = c->y;
+ ocx2 = c->x + c->w;
+ ocy2 = c->y + c->h;
if (XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync,
None, cursor[CurResize]->cursor, CurrentTime) != GrabSuccess)
return;
- XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w + c->bw - 1, c->h + c->bw - 1);
+ if (!XQueryPointer (dpy, c->win, &dummy, &dummy, &di, &di, &nx, &ny, &dui))
+ return;
+ horizcorner = nx < c->w / 2;
+ vertcorner = ny < c->h / 2;
+ XWarpPointer (dpy, None, c->win, 0, 0, 0, 0,
+ horizcorner ? (-c->bw) : (c->w + c->bw -1),
+ vertcorner ? (-c->bw) : (c->h + c->bw -1));
do {
XMaskEvent(dpy, MOUSEMASK|ExposureMask|SubstructureRedirectMask, &ev);
switch(ev.type) {
@@ -1320,8 +1333,11 @@
continue;
lasttime = ev.xmotion.time;
- nw = MAX(ev.xmotion.x - ocx - 2 * c->bw + 1, 1);
- nh = MAX(ev.xmotion.y - ocy - 2 * c->bw + 1, 1);
+ nx = horizcorner ? ev.xmotion.x : c->x;
+ ny = vertcorner ? ev.xmotion.y : c->y;
+ nw = MAX(horizcorner ? (ocx2 - nx) : (ev.xmotion.x - ocx - 2 * c->bw + 1), 1);
+ nh = MAX(vertcorner ? (ocy2 - ny) : (ev.xmotion.y - ocy - 2 * c->bw + 1), 1);
+
if (c->mon->wx + nw >= selmon->wx && c->mon->wx + nw <= selmon->wx + selmon->ww
&& c->mon->wy + nh >= selmon->wy && c->mon->wy + nh <= selmon->wy + selmon->wh)
{
@@ -1330,11 +1346,13 @@
togglefloating(NULL);
}
if (!selmon->lt[selmon->sellt]->arrange || c->isfloating)
- resize(c, c->x, c->y, nw, nh, 1);
+ resize(c, nx, ny, nw, nh, 1);
break;
}
} while (ev.type != ButtonRelease);
- XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w + c->bw - 1, c->h + c->bw - 1);
+ XWarpPointer(dpy, None, c->win, 0, 0, 0, 0,
+ horizcorner ? (-c->bw) : (c->w + c->bw - 1),
+ vertcorner ? (-c->bw) : (c->h + c->bw - 1));
XUngrabPointer(dpy, CurrentTime);
while (XCheckMaskEvent(dpy, EnterWindowMask, &ev));
if ((m = recttomon(c->x, c->y, c->w, c->h)) != selmon) {

View File

@ -0,0 +1,139 @@
From 2991f37f0aaf44b9f9b11e7893ff0af8eb88f649 Mon Sep 17 00:00:00 2001
From: Christopher Drelich <cd@cdrakka.com>
Date: Wed, 23 May 2018 22:50:38 -0400
Subject: [PATCH] Modifies quit to handle restarts and adds SIGHUP and SIGTERM
handlers.
Modified quit() to restart if it receives arg .i = 1
MOD+CTRL+SHIFT+Q was added to confid.def.h to do just that.
Signal handlers were handled for SIGHUP and SIGTERM.
If dwm receives these signals it calls quit() with
arg .i = to 1 or 0, respectively.
To restart dwm:
MOD+CTRL+SHIFT+Q
or
kill -HUP dwmpid
To quit dwm cleanly:
MOD+SHIFT+Q
or
kill -TERM dwmpid
---
config.def.h | 1 +
dwm.1 | 10 ++++++++++
dwm.c | 22 ++++++++++++++++++++++
3 files changed, 33 insertions(+)
diff --git a/config.def.h b/config.def.h
index a9ac303..e559429 100644
--- a/config.def.h
+++ b/config.def.h
@@ -94,6 +94,7 @@ static Key keys[] = {
TAGKEYS( XK_8, 7)
TAGKEYS( XK_9, 8)
{ MODKEY|ShiftMask, XK_q, quit, {0} },
+ { MODKEY|ControlMask|ShiftMask, XK_q, quit, {1} },
};
/* button definitions */
diff --git a/dwm.1 b/dwm.1
index 13b3729..36a331c 100644
--- a/dwm.1
+++ b/dwm.1
@@ -142,6 +142,9 @@ Add/remove all windows with nth tag to/from the view.
.TP
.B Mod1\-Shift\-q
Quit dwm.
+.TP
+.B Mod1\-Control\-Shift\-q
+Restart dwm.
.SS Mouse commands
.TP
.B Mod1\-Button1
@@ -155,6 +158,13 @@ Resize focused window while dragging. Tiled windows will be toggled to the float
.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/dwm.c b/dwm.c
index bb95e26..286eecd 100644
--- a/dwm.c
+++ b/dwm.c
@@ -205,6 +205,8 @@ 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 void tag(const Arg *arg);
static void tagmon(const Arg *arg);
@@ -260,6 +262,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;
@@ -1248,6 +1251,7 @@ propertynotify(XEvent *e)
void
quit(const Arg *arg)
{
+ if(arg->i) restart = 1;
running = 0;
}
@@ -1536,6 +1540,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);
@@ -1637,6 +1644,20 @@ 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)
@@ -2139,6 +2160,7 @@ main(int argc, char *argv[])
setup();
scan();
run();
+ if(restart) execvp(argv[0], argv);
cleanup();
XCloseDisplay(dpy);
return EXIT_SUCCESS;
--
2.7.4

View File

@ -0,0 +1,265 @@
From dc83e43aad7b8070911e8210b58cc36bdc4214d5 Mon Sep 17 00:00:00 2001
From: Santtu Lakkala <inz@inz.fi>
Date: Wed, 23 Feb 2022 11:55:19 +0200
Subject: [PATCH 1/2] Allow CSI SGR in status bar
---
config.def.h | 19 ++++++
dwm.c | 182 ++++++++++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 198 insertions(+), 3 deletions(-)
diff --git a/config.def.h b/config.def.h
index a2ac963..3dc34bd 100644
--- a/config.def.h
+++ b/config.def.h
@@ -18,6 +18,25 @@ static const char *colors[][3] = {
[SchemeSel] = { col_gray4, col_cyan, col_cyan },
};
+static const char *barcolors[] = {
+ "#000000",
+ "#7f0000",
+ "#007f00",
+ "#7f7f00",
+ "#00007f",
+ "#7f007f",
+ "#007f7f",
+ "#cccccc",
+ "#333333",
+ "#ff0000",
+ "#00ff00",
+ "#ffff00",
+ "#0000ff",
+ "#ff00ff",
+ "#00ffff",
+ "#ffffff",
+};
+
/* tagging */
static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" };
diff --git a/dwm.c b/dwm.c
index a96f33c..cb9484a 100644
--- a/dwm.c
+++ b/dwm.c
@@ -237,7 +237,7 @@ static void zoom(const Arg *arg);
/* variables */
static const char broken[] = "broken";
-static char stext[256];
+static char stext[512];
static int screen;
static int sw, sh; /* X display screen geometry width, height */
static int bh, blw = 0; /* bar geometry */
@@ -264,6 +264,7 @@ static Atom wmatom[WMLast], netatom[NetLast];
static int running = 1;
static Cur *cursor[CurLast];
static Clr **scheme;
+static Clr *barclrs;
static Display *dpy;
static Drw *drw;
static Monitor *mons, *selmon;
@@ -693,6 +694,25 @@ dirtomon(int dir)
return m;
}
+void
+resetfntlist(Fnt *orighead, Fnt *curhead)
+{
+ if (orighead != curhead) {
+ Fnt *f;
+ for (f = orighead; f->next; f = f->next);
+ f->next = curhead;
+ for (f = f->next; f->next != orighead; f = f->next);
+ f->next = NULL;
+ }
+}
+
+enum SgrFlags {
+ REVERSE = 1 << 0,
+ UNDERLINE = 1 << 1,
+ STRIKETHROUGH = 1 << 2,
+ OVERLINE = 1 << 3
+};
+
void
drawbar(Monitor *m)
{
@@ -707,9 +727,160 @@ drawbar(Monitor *m)
/* draw status first so it can be overdrawn by tags later */
if (m == selmon) { /* status is only drawn on selected monitor */
+ char buffer[sizeof(stext)];
+ Clr scm[3];
+ int wr, rd;
+ int pw;
+ int fg = 7;
+ int bg = 0;
+ int fmt = 0;
+ int lp = lrpad / 2 - 2;
+ Fnt *fset = drw->fonts;
+
+ memcpy(scm, scheme[SchemeNorm], sizeof(scm));
+
+ drw_setscheme(drw, scm);
+
+ for (tw = 0, wr = 0, rd = 0; stext[rd]; rd++) {
+ if (stext[rd] == '' && stext[rd + 1] == '[') {
+ size_t alen = strspn(stext + rd + 2,
+ "0123456789;");
+ if (stext[rd + alen + 2] == 'm') {
+ buffer[wr] = '\0';
+ tw += TEXTW(buffer) - lrpad;
+ wr = 0;
+
+ char *ep = stext + rd + 1;
+ while (*ep != 'm') {
+ unsigned v = strtoul(ep + 1, &ep, 10);
+ if (v == 0 || (v >= 10 && v <= 19)) {
+ int fi = v % 10;
+ Fnt *f;
+ Fnt *p;
+ resetfntlist(fset, drw->fonts);
+ for (p = NULL, f = fset; f && fi--; p = f, f = f->next);
+ if (f) {
+ if (p) {
+ p->next = NULL;
+ for (p = f; p->next; p = p->next);
+ p->next = fset;
+ }
+ drw_setfontset(drw, f);
+ } else {
+ drw_setfontset(drw, fset);
+ }
+ }
+ }
+
+ rd += alen + 2;
+ continue;
+ }
+ }
+ buffer[wr++] = stext[rd];
+ }
+ buffer[wr] = '\0';
+
+ tw += TEXTW(buffer) - lrpad / 2 + 2;
+ x = m->ww - tw;
+
+ resetfntlist(fset, drw->fonts);
+ drw_setfontset(drw, fset);
+
+ for (wr = 0, rd = 0; stext[rd]; rd++) {
+ if (stext[rd] == '' && stext[rd + 1] == '[') {
+ size_t alen = strspn(stext + rd + 2,
+ "0123456789;");
+ if (stext[rd + alen + 2] == 'm') {
+ buffer[wr] = '\0';
+ pw = TEXTW(buffer) - lrpad;
+ drw_text(drw, x, 0, pw + lp, bh, lp, buffer, fmt & REVERSE);
+ if (fmt & UNDERLINE)
+ drw_rect(drw, x, (bh + drw->fonts->h) / 2, pw, 1, 1, fmt & REVERSE);
+ if (fmt & STRIKETHROUGH)
+ drw_rect(drw, x, bh / 2, pw, 1, 1, fmt & REVERSE);
+ if (fmt & OVERLINE)
+ drw_rect(drw, x, (bh - drw->fonts->h) / 2, pw, 1, 1, fmt & REVERSE);
+ x += pw + lp;
+ lp = 0;
+
+ char *ep = stext + rd + 1;
+ while (*ep != 'm') {
+ unsigned v = strtoul(ep + 1, &ep, 10);
+ if (v == 0) {
+ memcpy(scm, scheme[SchemeNorm], sizeof(scm));
+ fg = 7;
+ bg = 0;
+ fmt = 0;
+ resetfntlist(fset, drw->fonts);
+ drw_setfontset(drw, fset);
+ } else if (v == 1) {
+ fg |= 8;
+ scm[0] = barclrs[fg];
+ } else if (v == 4) {
+ fmt |= UNDERLINE;
+ } else if (v == 7) {
+ fmt |= REVERSE;
+ } else if (v == 9) {
+ fmt |= STRIKETHROUGH;
+ } else if (v >= 10 && v <= 19) {
+ int fi = v % 10;
+ Fnt *f;
+ Fnt *p;
+ resetfntlist(fset, drw->fonts);
+ for (p = NULL, f = fset; f && fi--; p = f, f = f->next);
+ if (f) {
+ if (p) {
+ p->next = NULL;
+ for (p = f; p->next; p = p->next);
+ p->next = fset;
+ }
+ drw_setfontset(drw, f);
+ } else {
+ drw_setfontset(drw, fset);
+ }
+ } else if (v == 22) {
+ fg &= ~8;
+ scm[0] = barclrs[fg];
+ } else if (v == 24) {
+ fmt &= ~UNDERLINE;
+ } else if (v == 27) {
+ fmt &= ~REVERSE;
+ } else if (v == 29) {
+ fmt &= ~STRIKETHROUGH;
+ } else if (v >= 30 && v <= 37) {
+ fg = v % 10 | (fg & 8);
+ scm[0] = barclrs[fg];
+ } else if (v >= 40 && v <= 47) {
+ bg = v % 10;
+ scm[1] = barclrs[bg];
+ } else if (v == 53) {
+ fmt |= OVERLINE;
+ } else if (v == 55) {
+ fmt &= ~OVERLINE;
+ }
+ }
+
+ rd += alen + 2;
+ wr = 0;
+
+ drw_setscheme(drw, scm);
+ continue;
+ }
+ }
+ buffer[wr++] = stext[rd];
+ }
+
+ buffer[wr] = '\0';
+ pw = TEXTW(buffer) - lrpad;
+ drw_text(drw, x, 0, pw + lp, bh, lp, buffer, fmt & REVERSE);
+ if (fmt & UNDERLINE)
+ drw_rect(drw, x, (bh + drw->fonts->h) / 2, pw, 1, 1, fmt & REVERSE);
+ if (fmt & STRIKETHROUGH)
+ drw_rect(drw, x, bh / 2, pw, 1, 1, fmt & REVERSE);
+ if (fmt & OVERLINE)
+ drw_rect(drw, x, (bh - drw->fonts->h) / 2, pw, 1, 1, fmt & REVERSE);
+
drw_setscheme(drw, scheme[SchemeNorm]);
- 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) {
@@ -1574,6 +1745,11 @@ setup(void)
scheme = ecalloc(LENGTH(colors), sizeof(Clr *));
for (i = 0; i < LENGTH(colors); i++)
scheme[i] = drw_scm_create(drw, colors[i], 3);
+
+ barclrs = ecalloc(LENGTH(barcolors), sizeof(Clr));
+ for (i = 0; i < LENGTH(barcolors); i++)
+ drw_clr_create(drw, &barclrs[i], barcolors[i]);
+
/* init bars */
updatebars();
updatestatus();
--
2.32.0

View File

@ -0,0 +1,320 @@
From fc232a3075835e01c1dab6b199ec8817d911d0be Mon Sep 17 00:00:00 2001
From: blatzfab <fabian.blatz@gmail.com>
Date: Fri, 16 Oct 2020 09:44:24 +0000
Subject: [PATCH] Adds ssh aware spawn command
---
config.def.h | 2 +-
config.mk | 3 +-
dwm.c | 174 +++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 177 insertions(+), 2 deletions(-)
diff --git a/config.def.h b/config.def.h
index 1c0b587..1121d4d 100644
--- a/config.def.h
+++ b/config.def.h
@@ -62,7 +62,7 @@ static const char *termcmd[] = { "st", NULL };
static Key keys[] = {
/* modifier key function argument */
{ MODKEY, XK_p, spawn, {.v = dmenucmd } },
- { MODKEY|ShiftMask, XK_Return, spawn, {.v = termcmd } },
+ { MODKEY|ShiftMask, XK_Return, spawnsshaware, {.v = termcmd } },
{ MODKEY, XK_b, togglebar, {0} },
{ MODKEY, XK_j, focusstack, {.i = +1 } },
{ MODKEY, XK_k, focusstack, {.i = -1 } },
diff --git a/config.mk b/config.mk
index 6d36cb7..5272bdc 100644
--- a/config.mk
+++ b/config.mk
@@ -19,10 +19,11 @@ FREETYPELIBS = -lfontconfig -lXft
FREETYPEINC = /usr/include/freetype2
# OpenBSD (uncomment)
#FREETYPEINC = ${X11INC}/freetype2
+#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} -lprocps
# flags
CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_POSIX_C_SOURCE=2 -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS}
diff --git a/dwm.c b/dwm.c
index 4465af1..bd35817 100644
--- a/dwm.c
+++ b/dwm.c
@@ -28,6 +28,8 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
+#include <proc/readproc.h>
+#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <X11/cursorfont.h>
@@ -40,6 +42,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"
@@ -93,6 +101,7 @@ struct Client {
int bw, oldbw;
unsigned int tags;
int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen;
+ pid_t pid;
Client *next;
Client *snext;
Monitor *mon;
@@ -156,6 +165,8 @@ static void clientmessage(XEvent *e);
static void configure(Client *c);
static void configurenotify(XEvent *e);
static void configurerequest(XEvent *e);
+static char* checksshsession(pid_t process);
+static int checkparents(pid_t pid, pid_t target);
static Monitor *createmon(void);
static void destroynotify(XEvent *e);
static void detach(Client *c);
@@ -171,6 +182,7 @@ static void focusmon(const Arg *arg);
static void focusstack(const Arg *arg);
static int getrootptr(int *x, int *y);
static long getstate(Window w);
+static int getprocinfo(pid_t pid, proc_t *procinfo);
static int gettextprop(Window w, Atom atom, char *text, unsigned int size);
static void grabbuttons(Client *c, int focused);
static void grabkeys(void);
@@ -206,6 +218,8 @@ 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 spawnsshaware(const Arg *arg);
+static int strtopid(char *s, pid_t *pid);
static void tag(const Arg *arg);
static void tagmon(const Arg *arg);
static void tile(Monitor *);
@@ -229,6 +243,7 @@ static void updatewmhints(Client *c);
static void view(const Arg *arg);
static Client *wintoclient(Window w);
static Monitor *wintomon(Window w);
+static pid_t winpid(Window w);
static int xerror(Display *dpy, XErrorEvent *ee);
static int xerrordummy(Display *dpy, XErrorEvent *ee);
static int xerrorstart(Display *dpy, XErrorEvent *ee);
@@ -267,6 +282,7 @@ 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"
@@ -575,6 +591,63 @@ configurenotify(XEvent *e)
}
}
+int
+checkparents(pid_t pid, pid_t target)
+{
+ proc_t *pinf = calloc(1, sizeof(proc_t));
+ pid_t current = pid;
+
+ while(current!=(pid_t)0 && current!=(pid_t)1 && current!=target){
+ getprocinfo(current, pinf);
+ current = pinf->ppid;
+ }
+ freeproc(pinf);
+ if(current==target)
+ return 1;
+ return 0;
+}
+
+char*
+checksshsession(pid_t process)
+{
+ struct dirent *dp;
+ DIR *dfd;
+ const char *dir = "/proc";
+ char filename_qfd[100] ;
+ pid_t pid;
+ proc_t* process_info = calloc(1, sizeof(proc_t));
+ struct stat stbuf;
+ char* res = 0;
+
+ if ((dfd = opendir(dir)) == NULL) {
+ fprintf(stderr, "Can't open %s\n", dir);
+ freeproc(process_info);
+ return 0;
+ }
+
+ while ((dp = readdir(dfd)) != NULL && res == 0) {
+ sprintf( filename_qfd , "%s/%s",dir,dp->d_name);
+ if(stat(filename_qfd,&stbuf ) == -1) {
+ fprintf(stderr, "Unable to stat file: %s\n",filename_qfd);
+ continue;
+ }
+ if (((stbuf.st_mode & S_IFMT) == S_IFDIR) && strtopid(dp->d_name, &pid)) {
+ getprocinfo(pid, process_info);
+ if(!process_info->cmdline)
+ continue;
+ char* cmdline = *process_info->cmdline;
+ if(strncmp("ssh ", cmdline, 4) == 0 && checkparents(pid, process)){
+ res = calloc(strlen(cmdline)+1, sizeof(char));
+ strcpy(res, cmdline);
+ }
+ }
+ }
+ freeproc(process_info);
+ free(dfd);
+ return res;
+}
+
+
void
configurerequest(XEvent *e)
{
@@ -899,6 +972,19 @@ getstate(Window w)
return result;
}
+int
+getprocinfo(pid_t pid, proc_t *procinfo)
+{
+ int res = 1;
+ if(!procinfo)
+ return 0;
+ PROCTAB *pt_ptr = openproc(PROC_FILLARG | PROC_EDITCMDLCVT | PROC_FILLSTATUS | PROC_PID, &pid);
+ if(readproc(pt_ptr, procinfo))
+ res = 0;
+ closeproc(pt_ptr);
+ return res;
+}
+
int
gettextprop(Window w, Atom atom, char *text, unsigned int size)
{
@@ -1023,6 +1109,7 @@ manage(Window w, XWindowAttributes *wa)
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;
@@ -1636,6 +1723,38 @@ sigchld(int unused)
while (0 < waitpid(-1, NULL, WNOHANG));
}
+void
+spawnsshaware(const Arg *arg)
+{
+ if(selmon->sel) {
+ char* sshcmdline = checksshsession(selmon->sel->pid);
+ if(sshcmdline){
+ const char* sshcmd[] = {"st", "-e", "/bin/bash", "-c", sshcmdline, NULL};
+ Arg a = {.v=sshcmd};
+ spawn(&a);
+ free(sshcmdline);
+ }else{
+ spawn(arg);
+ }
+ }else{
+ spawn(arg);
+ }
+}
+
+int
+strtopid(char *s, pid_t *pid)
+{
+ long result = 0;
+ char *eptr;
+ if(!pid)
+ return 0;
+ result = strtol(s, &eptr, 10);
+ if((eptr && *eptr!='\0') || errno == ERANGE)
+ return 0;
+ *pid=(pid_t) result;
+ return 1;
+}
+
void
spawn(const Arg *arg)
{
@@ -2074,6 +2193,59 @@ wintomon(Window w)
return 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", 1), 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;
+}
+
/* 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. */
@@ -2135,6 +2307,8 @@ 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__
--
2.28.0

View File

@ -0,0 +1,197 @@
From d04f2d00688c8b0969d4f10f460c980dd91dac37 Mon Sep 17 00:00:00 2001
From: MLquest8 <miskuzius@gmail.com>
Date: Fri, 12 Jun 2020 16:04:18 +0400
Subject: [PATCH] stacker updated for version 6.2
---
config.def.h | 14 +++++++--
dwm.c | 88 ++++++++++++++++++++++++++++++++++++++++------------
2 files changed, 80 insertions(+), 22 deletions(-)
diff --git a/config.def.h b/config.def.h
index 1c0b587..d28f8fc 100644
--- a/config.def.h
+++ b/config.def.h
@@ -50,6 +50,14 @@ static const Layout layouts[] = {
{ 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_grave, ACTION##stack, {.i = PREVSEL } }, \
+ { MOD, XK_q, ACTION##stack, {.i = 0 } }, \
+ { 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 } }
@@ -64,8 +72,8 @@ static Key keys[] = {
{ MODKEY, XK_p, spawn, {.v = dmenucmd } },
{ MODKEY|ShiftMask, XK_Return, spawn, {.v = termcmd } },
{ MODKEY, XK_b, togglebar, {0} },
- { MODKEY, XK_j, focusstack, {.i = +1 } },
- { MODKEY, XK_k, focusstack, {.i = -1 } },
+ STACKKEYS(MODKEY, focus)
+ STACKKEYS(MODKEY|ShiftMask, push)
{ MODKEY, XK_i, incnmaster, {.i = +1 } },
{ MODKEY, XK_d, incnmaster, {.i = -1 } },
{ MODKEY, XK_h, setmfact, {.f = -0.05} },
@@ -93,7 +101,7 @@ static Key keys[] = {
TAGKEYS( XK_7, 6)
TAGKEYS( XK_8, 7)
TAGKEYS( XK_9, 8)
- { MODKEY|ShiftMask, XK_q, quit, {0} },
+ { MODKEY|ShiftMask, XK_BackSpace, quit, {0} },
};
/* button definitions */
diff --git a/dwm.c b/dwm.c
index 9fd0286..6c302c3 100644
--- a/dwm.c
+++ b/dwm.c
@@ -47,15 +47,21 @@
/* 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 ISINC(X) ((X) > 1000 && (X) < 3000)
#define ISVISIBLE(C) ((C->tags & C->mon->tagset[C->mon->seltags]))
+#define PREVSEL 3000
#define LENGTH(X) (sizeof X / sizeof X[0])
+#define MOD(N,M) ((N)%(M) < 0 ? (N)%(M) + (M) : (N)%(M))
#define MOUSEMASK (BUTTONMASK|PointerMotionMask)
#define WIDTH(X) ((X)->w + 2 * (X)->bw)
#define HEIGHT(X) ((X)->h + 2 * (X)->bw)
#define TAGMASK ((1 << LENGTH(tags)) - 1)
#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 */
@@ -187,6 +193,7 @@ 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);
@@ -207,6 +214,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 int stackpos(const Arg *arg);
static void tag(const Arg *arg);
static void tagmon(const Arg *arg);
static void tile(Monitor *);
@@ -833,27 +841,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)
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
@@ -1246,6 +1243,29 @@ propertynotify(XEvent *e)
}
}
+void
+pushstack(const Arg *arg) {
+ int i = stackpos(arg);
+ Client *sel = selmon->sel, *c, *p;
+
+ if(i < 0)
+ 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
quit(const Arg *arg)
{
@@ -1653,6 +1673,36 @@ spawn(const Arg *arg)
}
}
+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
tag(const Arg *arg)
{
--
2.26.2

View File

@ -0,0 +1,412 @@
From f0cdf40e0a7126838d051eb84d84b91421b771d6 Mon Sep 17 00:00:00 2001
From: 0x1bi <ben@0x1bi.net>
Date: Fri, 11 Dec 2020 10:16:25 -0500
Subject: [PATCH] fix swallow for openbsd
---
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 1c0b587..fe51476 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 7084c33..ff9e508 100644
--- a/config.mk
+++ b/config.mk
@@ -19,10 +19,11 @@ FREETYPELIBS = -lfontconfig -lXft
FREETYPEINC = /usr/include/freetype2
# OpenBSD (uncomment)
#FREETYPEINC = ${X11INC}/freetype2
+#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 664c527..0b20086 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;
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);
@@ -414,6 +434,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)
{
@@ -653,6 +720,9 @@ destroynotify(XEvent *e)
if ((c = wintoclient(ev->window)))
unmanage(c, 1);
+
+ else if ((c = swallowingclient(ev->window)))
+ unmanage(c->swallowing, 1);
}
void
@@ -1018,12 +1088,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;
@@ -1038,6 +1109,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)
@@ -1074,6 +1146,8 @@ manage(Window w, XWindowAttributes *wa)
c->mon->sel = c;
arrange(c->mon);
XMapWindow(dpy, c->win);
+ if (term)
+ swallow(term, c);
focus(NULL);
}
@@ -1768,6 +1842,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) {
@@ -1782,9 +1870,12 @@ unmanage(Client *c, int destroyed)
XUngrabServer(dpy);
}
free(c);
- focus(NULL);
- updateclientlist();
- arrange(m);
+
+ if (!s) {
+ arrange(m);
+ focus(NULL);
+ updateclientlist();
+ }
}
void
@@ -2047,6 +2138,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)
{
@@ -2138,10 +2359,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.28.0

View File

@ -0,0 +1,763 @@
diff --git a/config.def.h b/config.def.h
index a2ac963..4be4c06 100644
--- a/config.def.h
+++ b/config.def.h
@@ -2,9 +2,14 @@
/* appearance */
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 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 = 1; /* 0 means no bar */
+static const int topbar = 1; /* 0 means bottom bar */
static const char *fonts[] = { "monospace:size=10" };
static const char dmenufont[] = "monospace:size=10";
static const char col_gray1[] = "#222222";
@@ -101,8 +106,8 @@ static Key keys[] = {
/* 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]} },
+ { 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 a96f33c..941c1c0 100644
--- a/dwm.c
+++ b/dwm.c
@@ -57,12 +57,27 @@
#define TAGMASK ((1 << LENGTH(tags)) - 1)
#define TEXTW(X) (drw_fontset_getwidth(drw, (X)) + lrpad)
+#define SYSTEM_TRAY_REQUEST_DOCK 0
+/* XEMBED messages */
+#define XEMBED_EMBEDDED_NOTIFY 0
+#define XEMBED_WINDOW_ACTIVATE 1
+#define XEMBED_FOCUS_IN 4
+#define XEMBED_MODALITY_ON 10
+#define XEMBED_MAPPED (1 << 0)
+#define XEMBED_WINDOW_ACTIVATE 1
+#define XEMBED_WINDOW_DEACTIVATE 2
+#define VERSION_MAJOR 0
+#define VERSION_MINOR 0
+#define XEMBED_EMBEDDED_VERSION (VERSION_MAJOR << 16) | VERSION_MINOR
+
/* enums */
enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */
enum { SchemeNorm, SchemeSel }; /* color schemes */
enum { NetSupported, NetWMName, NetWMState, NetWMCheck,
+ NetSystemTray, NetSystemTrayOP, NetSystemTrayOrientation, NetSystemTrayOrientationHorz,
NetWMFullscreen, NetActiveWindow, NetWMWindowType,
NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH atoms */
+enum { Manager, Xembed, XembedInfo, XLast }; /* Xembed atoms */
enum { WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast }; /* default atoms */
enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle,
ClkClientWin, ClkRootWin, ClkLast }; /* clicks */
@@ -141,6 +156,12 @@ typedef struct {
int monitor;
} Rule;
+typedef struct Systray Systray;
+struct Systray {
+ Window win;
+ Client *icons;
+};
+
/* function declarations */
static void applyrules(Client *c);
static int applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact);
@@ -172,6 +193,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 int gettextprop(Window w, Atom atom, char *text, unsigned int size);
static void grabbuttons(Client *c, int focused);
static void grabkeys(void);
@@ -189,13 +211,16 @@ static void pop(Client *);
static void propertynotify(XEvent *e);
static void quit(const Arg *arg);
static Monitor *recttomon(int x, int y, int w, int h);
+static void removesystrayicon(Client *i);
static void resize(Client *c, int x, int y, int w, int h, int interact);
+static void resizebarwin(Monitor *m);
static void resizeclient(Client *c, int x, int y, int w, int h);
static void resizemouse(const Arg *arg);
+static void resizerequest(XEvent *e);
static void restack(Monitor *m);
static void run(void);
static void scan(void);
-static int sendevent(Client *c, Atom proto);
+static int sendevent(Window w, Atom proto, int m, long d0, long d1, long d2, long d3, long d4);
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);
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 *);
@@ -224,18 +250,23 @@ static int updategeom(void);
static void updatenumlockmask(void);
static void updatesizehints(Client *c);
static void updatestatus(void);
+static void updatesystray(void);
+static void updatesystrayicongeom(Client *i, int w, int h);
+static void updatesystrayiconstate(Client *i, XPropertyEvent *ev);
static void updatetitle(Client *c);
static void updatewindowtype(Client *c);
static void updatewmhints(Client *c);
static void view(const Arg *arg);
static Client *wintoclient(Window w);
static Monitor *wintomon(Window w);
+static Client *wintosystrayicon(Window w);
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);
/* variables */
+static Systray *systray = NULL;
static const char broken[] = "broken";
static char stext[256];
static int screen;
@@ -258,9 +289,10 @@ static void (*handler[LASTEvent]) (XEvent *) = {
[MapRequest] = maprequest,
[MotionNotify] = motionnotify,
[PropertyNotify] = propertynotify,
+ [ResizeRequest] = resizerequest,
[UnmapNotify] = unmapnotify
};
-static Atom wmatom[WMLast], netatom[NetLast];
+static Atom wmatom[WMLast], netatom[NetLast], xatom[XLast];
static int running = 1;
static Cur *cursor[CurLast];
static Clr **scheme;
@@ -440,7 +472,7 @@ buttonpress(XEvent *e)
arg.ui = 1 << i;
} else if (ev->x < x + blw)
click = ClkLtSymbol;
- else if (ev->x > selmon->ww - (int)TEXTW(stext))
+ else if (ev->x > selmon->ww - (int)TEXTW(stext) - getsystraywidth())
click = ClkStatusText;
else
click = ClkWinTitle;
@@ -483,7 +515,14 @@ cleanup(void)
XUngrabKey(dpy, AnyKey, AnyModifier, root);
while (mons)
cleanupmon(mons);
- for (i = 0; i < CurLast; i++)
+
+ if (showsystray) {
+ XUnmapWindow(dpy, systray->win);
+ XDestroyWindow(dpy, systray->win);
+ free(systray);
+ }
+
+ for (i = 0; i < CurLast; i++)
drw_cur_free(drw, cursor[i]);
for (i = 0; i < LENGTH(colors); i++)
free(scheme[i]);
@@ -513,9 +552,58 @@ cleanupmon(Monitor *mon)
void
clientmessage(XEvent *e)
{
+ XWindowAttributes wa;
+ XSetWindowAttributes swa;
XClientMessageEvent *cme = &e->xclient;
Client *c = wintoclient(cme->window);
+ if (showsystray && cme->window == systray->win && cme->message_type == netatom[NetSystemTrayOP]) {
+ /* add systray icons */
+ if (cme->data.l[1] == SYSTEM_TRAY_REQUEST_DOCK) {
+ if (!(c = (Client *)calloc(1, sizeof(Client))))
+ die("fatal: could not malloc() %u bytes\n", sizeof(Client));
+ if (!(c->win = cme->data.l[2])) {
+ free(c);
+ return;
+ }
+ c->mon = selmon;
+ c->next = systray->icons;
+ systray->icons = c;
+ if (!XGetWindowAttributes(dpy, c->win, &wa)) {
+ /* use sane defaults */
+ wa.width = bh;
+ wa.height = bh;
+ wa.border_width = 0;
+ }
+ c->x = c->oldx = c->y = c->oldy = 0;
+ c->w = c->oldw = wa.width;
+ c->h = c->oldh = wa.height;
+ c->oldbw = wa.border_width;
+ c->bw = 0;
+ c->isfloating = True;
+ /* reuse tags field as mapped status */
+ c->tags = 1;
+ updatesizehints(c);
+ updatesystrayicongeom(c, wa.width, wa.height);
+ XAddToSaveSet(dpy, c->win);
+ XSelectInput(dpy, c->win, StructureNotifyMask | PropertyChangeMask | ResizeRedirectMask);
+ XReparentWindow(dpy, c->win, systray->win, 0, 0);
+ /* use parents background color */
+ swa.background_pixel = scheme[SchemeNorm][ColBg].pixel;
+ XChangeWindowAttributes(dpy, c->win, CWBackPixel, &swa);
+ sendevent(c->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_EMBEDDED_NOTIFY, 0 , systray->win, XEMBED_EMBEDDED_VERSION);
+ /* FIXME not sure if I have to send these events, too */
+ sendevent(c->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_FOCUS_IN, 0 , systray->win, XEMBED_EMBEDDED_VERSION);
+ sendevent(c->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_WINDOW_ACTIVATE, 0 , systray->win, XEMBED_EMBEDDED_VERSION);
+ sendevent(c->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_MODALITY_ON, 0 , systray->win, XEMBED_EMBEDDED_VERSION);
+ XSync(dpy, False);
+ resizebarwin(selmon);
+ updatesystray();
+ setclientstate(c, NormalState);
+ }
+ return;
+ }
+
if (!c)
return;
if (cme->message_type == netatom[NetWMState]) {
@@ -568,7 +656,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);
- XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, bh);
+ resizebarwin(m);
}
focus(NULL);
arrange(NULL);
@@ -653,6 +741,11 @@ destroynotify(XEvent *e)
if ((c = wintoclient(ev->window)))
unmanage(c, 1);
+ else if ((c = wintosystrayicon(ev->window))) {
+ removesystrayicon(c);
+ resizebarwin(selmon);
+ updatesystray();
+ }
}
void
@@ -696,7 +789,7 @@ dirtomon(int dir)
void
drawbar(Monitor *m)
{
- int x, w, tw = 0;
+ int x, w, tw = 0, stw = 0;
int boxs = drw->fonts->h / 9;
int boxw = drw->fonts->h / 6 + 2;
unsigned int i, occ = 0, urg = 0;
@@ -705,13 +798,17 @@ drawbar(Monitor *m)
if (!m->showbar)
return;
+ if(showsystray && m == systraytomon(m) && !systrayonleft)
+ stw = getsystraywidth();
+
/* 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]);
- tw = TEXTW(stext) - lrpad + 2; /* 2px right padding */
- drw_text(drw, m->ww - tw, 0, tw, bh, 0, stext, 0);
+ tw = TEXTW(stext) - lrpad / 2 + 2; /* 2px extra right padding */
+ drw_text(drw, m->ww - tw - stw, 0, tw, bh, lrpad / 2 - 2, stext, 0);
}
+ resizebarwin(m);
for (c = m->clients; c; c = c->next) {
occ |= c->tags;
if (c->isurgent)
@@ -732,7 +829,7 @@ drawbar(Monitor *m)
drw_setscheme(drw, scheme[SchemeNorm]);
x = drw_text(drw, x, 0, w, bh, lrpad / 2, m->ltsymbol, 0);
- if ((w = m->ww - tw - x) > bh) {
+ if ((w = m->ww - tw - stw - 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);
@@ -743,7 +840,7 @@ drawbar(Monitor *m)
drw_rect(drw, x, 0, w, bh, 1, 1);
}
}
- drw_map(drw, m->barwin, 0, 0, m->ww, bh);
+ drw_map(drw, m->barwin, 0, 0, m->ww - stw, bh);
}
void
@@ -780,8 +877,11 @@ expose(XEvent *e)
Monitor *m;
XExposeEvent *ev = &e->xexpose;
- if (ev->count == 0 && (m = wintomon(ev->window)))
+ if (ev->count == 0 && (m = wintomon(ev->window))) {
drawbar(m);
+ if (m == selmon)
+ updatesystray();
+ }
}
void
@@ -867,9 +967,17 @@ getatomprop(Client *c, Atom prop)
unsigned char *p = NULL;
Atom da, atom = None;
- if (XGetWindowProperty(dpy, c->win, prop, 0L, sizeof atom, False, XA_ATOM,
+ /* FIXME getatomprop should return the number of items and a pointer to
+ * the stored data instead of this workaround */
+ Atom req = XA_ATOM;
+ if (prop == xatom[XembedInfo])
+ req = xatom[XembedInfo];
+
+ if (XGetWindowProperty(dpy, c->win, prop, 0L, sizeof atom, False, req,
&da, &di, &dl, &dl, &p) == Success && p) {
atom = *(Atom *)p;
+ if (da == xatom[XembedInfo] && dl == 2)
+ atom = ((Atom *)p)[1];
XFree(p);
}
return atom;
@@ -903,6 +1011,16 @@ getstate(Window w)
return result;
}
+unsigned int
+getsystraywidth()
+{
+ unsigned int w = 0;
+ Client *i;
+ if(showsystray)
+ for(i = systray->icons; i; w += i->w + systrayspacing, i = i->next) ;
+ return w ? w + systrayspacing : 1;
+}
+
int
gettextprop(Window w, Atom atom, char *text, unsigned int size)
{
@@ -1007,7 +1125,8 @@ killclient(const Arg *arg)
{
if (!selmon->sel)
return;
- if (!sendevent(selmon->sel, wmatom[WMDelete])) {
+
+ if (!sendevent(selmon->sel->win, wmatom[WMDelete], NoEventMask, wmatom[WMDelete], CurrentTime, 0 , 0, 0)) {
XGrabServer(dpy);
XSetErrorHandler(xerrordummy);
XSetCloseDownMode(dpy, DestroyAll);
@@ -1096,6 +1215,13 @@ maprequest(XEvent *e)
static XWindowAttributes wa;
XMapRequestEvent *ev = &e->xmaprequest;
+ Client *i;
+ if ((i = wintosystrayicon(ev->window))) {
+ sendevent(i->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_WINDOW_ACTIVATE, 0, systray->win, XEMBED_EMBEDDED_VERSION);
+ resizebarwin(selmon);
+ updatesystray();
+ }
+
if (!XGetWindowAttributes(dpy, ev->window, &wa))
return;
if (wa.override_redirect)
@@ -1219,7 +1345,18 @@ propertynotify(XEvent *e)
Window trans;
XPropertyEvent *ev = &e->xproperty;
- if ((ev->window == root) && (ev->atom == XA_WM_NAME))
+ if ((c = wintosystrayicon(ev->window))) {
+ if (ev->atom == XA_WM_NORMAL_HINTS) {
+ updatesizehints(c);
+ updatesystrayicongeom(c, c->w, c->h);
+ }
+ else
+ updatesystrayiconstate(c, ev);
+ resizebarwin(selmon);
+ updatesystray();
+ }
+
+ if ((ev->window == root) && (ev->atom == XA_WM_NAME))
updatestatus();
else if (ev->state == PropertyDelete)
return; /* ignore */
@@ -1269,6 +1406,19 @@ recttomon(int x, int y, int w, int h)
return r;
}
+void
+removesystrayicon(Client *i)
+{
+ Client **ii;
+
+ if (!showsystray || !i)
+ return;
+ for (ii = &systray->icons; *ii && *ii != i; ii = &(*ii)->next);
+ if (ii)
+ *ii = i->next;
+ free(i);
+}
+
void
resize(Client *c, int x, int y, int w, int h, int interact)
{
@@ -1276,6 +1426,14 @@ resize(Client *c, int x, int y, int w, int h, int interact)
resizeclient(c, x, y, w, h);
}
+void
+resizebarwin(Monitor *m) {
+ unsigned int w = m->ww;
+ if (showsystray && m == systraytomon(m) && !systrayonleft)
+ w -= getsystraywidth();
+ XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, w, bh);
+}
+
void
resizeclient(Client *c, int x, int y, int w, int h)
{
@@ -1348,6 +1506,19 @@ resizemouse(const Arg *arg)
}
}
+void
+resizerequest(XEvent *e)
+{
+ XResizeRequestEvent *ev = &e->xresizerequest;
+ Client *i;
+
+ if ((i = wintosystrayicon(ev->window))) {
+ updatesystrayicongeom(i, ev->width, ev->height);
+ resizebarwin(selmon);
+ updatesystray();
+ }
+}
+
void
restack(Monitor *m)
{
@@ -1437,26 +1608,37 @@ setclientstate(Client *c, long state)
}
int
-sendevent(Client *c, Atom proto)
+sendevent(Window w, Atom proto, int mask, long d0, long d1, long d2, long d3, long d4)
{
int n;
- Atom *protocols;
+ Atom *protocols, mt;
int exists = 0;
XEvent ev;
- if (XGetWMProtocols(dpy, c->win, &protocols, &n)) {
- while (!exists && n--)
- exists = protocols[n] == proto;
- XFree(protocols);
+ if (proto == wmatom[WMTakeFocus] || proto == wmatom[WMDelete]) {
+ mt = wmatom[WMProtocols];
+ if (XGetWMProtocols(dpy, w, &protocols, &n)) {
+ while (!exists && n--)
+ exists = protocols[n] == proto;
+ XFree(protocols);
+ }
}
+ else {
+ exists = True;
+ mt = proto;
+ }
+
if (exists) {
ev.type = ClientMessage;
- ev.xclient.window = c->win;
- ev.xclient.message_type = wmatom[WMProtocols];
+ ev.xclient.window = w;
+ ev.xclient.message_type = mt;
ev.xclient.format = 32;
- ev.xclient.data.l[0] = proto;
- ev.xclient.data.l[1] = CurrentTime;
- XSendEvent(dpy, c->win, False, NoEventMask, &ev);
+ ev.xclient.data.l[0] = d0;
+ ev.xclient.data.l[1] = d1;
+ ev.xclient.data.l[2] = d2;
+ ev.xclient.data.l[3] = d3;
+ ev.xclient.data.l[4] = d4;
+ XSendEvent(dpy, w, False, mask, &ev);
}
return exists;
}
@@ -1470,7 +1652,7 @@ setfocus(Client *c)
XA_WINDOW, 32, PropModeReplace,
(unsigned char *) &(c->win), 1);
}
- sendevent(c, wmatom[WMTakeFocus]);
+ sendevent(c->win, wmatom[WMTakeFocus], NoEventMask, wmatom[WMTakeFocus], CurrentTime, 0, 0, 0);
}
void
@@ -1558,15 +1740,22 @@ setup(void)
wmatom[WMState] = XInternAtom(dpy, "WM_STATE", False);
wmatom[WMTakeFocus] = XInternAtom(dpy, "WM_TAKE_FOCUS", False);
netatom[NetActiveWindow] = XInternAtom(dpy, "_NET_ACTIVE_WINDOW", False);
- netatom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False);
- netatom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False);
+ netatom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False);
+ netatom[NetSystemTray] = XInternAtom(dpy, "_NET_SYSTEM_TRAY_S0", False);
+ netatom[NetSystemTrayOP] = XInternAtom(dpy, "_NET_SYSTEM_TRAY_OPCODE", False);
+ netatom[NetSystemTrayOrientation] = XInternAtom(dpy, "_NET_SYSTEM_TRAY_ORIENTATION", False);
+ netatom[NetSystemTrayOrientationHorz] = XInternAtom(dpy, "_NET_SYSTEM_TRAY_ORIENTATION_HORZ", False);
+ 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);
netatom[NetWMFullscreen] = XInternAtom(dpy, "_NET_WM_STATE_FULLSCREEN", False);
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);
- /* init cursors */
+ xatom[Manager] = XInternAtom(dpy, "MANAGER", False);
+ xatom[Xembed] = XInternAtom(dpy, "_XEMBED", False);
+ xatom[XembedInfo] = XInternAtom(dpy, "_XEMBED_INFO", False);
+ /* init cursors */
cursor[CurNormal] = drw_cur_create(drw, XC_left_ptr);
cursor[CurResize] = drw_cur_create(drw, XC_sizing);
cursor[CurMove] = drw_cur_create(drw, XC_fleur);
@@ -1574,6 +1763,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);
+ /* init system tray */
+ updatesystray();
/* init bars */
updatebars();
updatestatus();
@@ -1707,7 +1898,18 @@ togglebar(const Arg *arg)
{
selmon->showbar = !selmon->showbar;
updatebarpos(selmon);
- XMoveResizeWindow(dpy, selmon->barwin, selmon->wx, selmon->by, selmon->ww, bh);
+ resizebarwin(selmon);
+ if (showsystray) {
+ XWindowChanges wc;
+ if (!selmon->showbar)
+ wc.y = -bh;
+ else if (selmon->showbar) {
+ wc.y = 0;
+ if (!selmon->topbar)
+ wc.y = selmon->mh - bh;
+ }
+ XConfigureWindow(dpy, systray->win, CWY, &wc);
+ }
arrange(selmon);
}
@@ -1802,11 +2004,18 @@ unmapnotify(XEvent *e)
else
unmanage(c, 0);
}
+ else if ((c = wintosystrayicon(ev->window))) {
+ /* KLUDGE! sometimes icons occasionally unmap their windows, but do
+ * _not_ destroy them. We map those windows back */
+ XMapRaised(dpy, c->win);
+ updatesystray();
+ }
}
void
updatebars(void)
{
+ unsigned int w;
Monitor *m;
XSetWindowAttributes wa = {
.override_redirect = True,
@@ -1817,10 +2026,15 @@ updatebars(void)
for (m = mons; m; m = m->next) {
if (m->barwin)
continue;
- m->barwin = XCreateWindow(dpy, root, m->wx, m->by, m->ww, bh, 0, DefaultDepth(dpy, screen),
+ w = m->ww;
+ if (showsystray && m == systraytomon(m))
+ w -= getsystraywidth();
+ m->barwin = XCreateWindow(dpy, root, m->wx, m->by, w, bh, 0, DefaultDepth(dpy, screen),
CopyFromParent, DefaultVisual(dpy, screen),
CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa);
XDefineCursor(dpy, m->barwin, cursor[CurNormal]->cursor);
+ if (showsystray && m == systraytomon(m))
+ XMapRaised(dpy, systray->win);
XMapRaised(dpy, m->barwin);
XSetClassHint(dpy, m->barwin, &ch);
}
@@ -1996,6 +2210,125 @@ updatestatus(void)
if (!gettextprop(root, XA_WM_NAME, stext, sizeof(stext)))
strcpy(stext, "dwm-"VERSION);
drawbar(selmon);
+ updatesystray();
+}
+
+
+void
+updatesystrayicongeom(Client *i, int w, int h)
+{
+ if (i) {
+ i->h = bh;
+ if (w == h)
+ i->w = bh;
+ else if (h == bh)
+ i->w = w;
+ else
+ i->w = (int) ((float)bh * ((float)w / (float)h));
+ applysizehints(i, &(i->x), &(i->y), &(i->w), &(i->h), False);
+ /* force icons into the systray dimensions if they don't want to */
+ if (i->h > bh) {
+ if (i->w == i->h)
+ i->w = bh;
+ else
+ i->w = (int) ((float)bh * ((float)i->w / (float)i->h));
+ i->h = bh;
+ }
+ }
+}
+
+void
+updatesystrayiconstate(Client *i, XPropertyEvent *ev)
+{
+ long flags;
+ int code = 0;
+
+ if (!showsystray || !i || ev->atom != xatom[XembedInfo] ||
+ !(flags = getatomprop(i, xatom[XembedInfo])))
+ return;
+
+ if (flags & XEMBED_MAPPED && !i->tags) {
+ i->tags = 1;
+ code = XEMBED_WINDOW_ACTIVATE;
+ XMapRaised(dpy, i->win);
+ setclientstate(i, NormalState);
+ }
+ else if (!(flags & XEMBED_MAPPED) && i->tags) {
+ i->tags = 0;
+ code = XEMBED_WINDOW_DEACTIVATE;
+ XUnmapWindow(dpy, i->win);
+ setclientstate(i, WithdrawnState);
+ }
+ else
+ return;
+ sendevent(i->win, xatom[Xembed], StructureNotifyMask, CurrentTime, code, 0,
+ systray->win, XEMBED_EMBEDDED_VERSION);
+}
+
+void
+updatesystray(void)
+{
+ XSetWindowAttributes wa;
+ XWindowChanges wc;
+ Client *i;
+ Monitor *m = systraytomon(NULL);
+ unsigned int x = m->mx + m->mw;
+ unsigned int sw = TEXTW(stext) - lrpad + systrayspacing;
+ unsigned int w = 1;
+
+ if (!showsystray)
+ return;
+ if (systrayonleft)
+ x -= sw + lrpad / 2;
+ if (!systray) {
+ /* init systray */
+ if (!(systray = (Systray *)calloc(1, sizeof(Systray))))
+ die("fatal: could not malloc() %u bytes\n", sizeof(Systray));
+ systray->win = XCreateSimpleWindow(dpy, root, x, m->by, w, bh, 0, 0, scheme[SchemeSel][ColBg].pixel);
+ wa.event_mask = ButtonPressMask | ExposureMask;
+ wa.override_redirect = True;
+ wa.background_pixel = scheme[SchemeNorm][ColBg].pixel;
+ XSelectInput(dpy, systray->win, SubstructureNotifyMask);
+ XChangeProperty(dpy, systray->win, netatom[NetSystemTrayOrientation], XA_CARDINAL, 32,
+ PropModeReplace, (unsigned char *)&netatom[NetSystemTrayOrientationHorz], 1);
+ XChangeWindowAttributes(dpy, systray->win, CWEventMask|CWOverrideRedirect|CWBackPixel, &wa);
+ XMapRaised(dpy, systray->win);
+ XSetSelectionOwner(dpy, netatom[NetSystemTray], systray->win, CurrentTime);
+ if (XGetSelectionOwner(dpy, netatom[NetSystemTray]) == systray->win) {
+ sendevent(root, xatom[Manager], StructureNotifyMask, CurrentTime, netatom[NetSystemTray], systray->win, 0, 0);
+ XSync(dpy, False);
+ }
+ else {
+ fprintf(stderr, "dwm: unable to obtain system tray.\n");
+ free(systray);
+ systray = NULL;
+ return;
+ }
+ }
+ for (w = 0, i = systray->icons; i; i = i->next) {
+ /* make sure the background color stays the same */
+ wa.background_pixel = scheme[SchemeNorm][ColBg].pixel;
+ XChangeWindowAttributes(dpy, i->win, CWBackPixel, &wa);
+ XMapRaised(dpy, i->win);
+ w += systrayspacing;
+ i->x = w;
+ XMoveResizeWindow(dpy, i->win, i->x, 0, i->w, i->h);
+ w += i->w;
+ if (i->mon != m)
+ i->mon = m;
+ }
+ w = w ? w + systrayspacing : 1;
+ x -= w;
+ XMoveResizeWindow(dpy, systray->win, x, m->by, w, bh);
+ wc.x = x; wc.y = m->by; wc.width = w; wc.height = bh;
+ wc.stack_mode = Above; wc.sibling = m->barwin;
+ XConfigureWindow(dpy, systray->win, CWX|CWY|CWWidth|CWHeight|CWSibling|CWStackMode, &wc);
+ XMapWindow(dpy, systray->win);
+ XMapSubwindows(dpy, systray->win);
+ /* redraw background */
+ XSetForeground(dpy, drw->gc, scheme[SchemeNorm][ColBg].pixel);
+ XFillRectangle(dpy, systray->win, drw->gc, 0, 0, w, bh);
+ XSync(dpy, False);
}
void
@@ -2063,6 +2396,16 @@ wintoclient(Window w)
return NULL;
}
+Client *
+wintosystrayicon(Window w) {
+ Client *i = NULL;
+
+ if (!showsystray || !w)
+ return i;
+ for (i = systray->icons; i && i->win != w; i = i->next) ;
+ return i;
+}
+
Monitor *
wintomon(Window w)
{
@@ -2116,6 +2459,22 @@ xerrorstart(Display *dpy, XErrorEvent *ee)
return -1;
}
+Monitor *
+systraytomon(Monitor *m) {
+ Monitor *t;
+ int i, n;
+ if(!systraypinning) {
+ if(!m)
+ return selmon;
+ return m == selmon ? m : NULL;
+ }
+ for(n = 1, t = mons; t && t->next; n++, t = t->next) ;
+ for(i = 1, t = mons; t && t->next && i < systraypinning; i++, t = t->next) ;
+ if(systraypinningfailfirst && n < systraypinning)
+ return mons;
+ return t;
+}
+
void
zoom(const Arg *arg)
{

View File

@ -0,0 +1,971 @@
From 9709d08daa290c8c7319571cd9e6ef4ec40e7683 Mon Sep 17 00:00:00 2001
From: bakkeby <bakkeby@gmail.com>
Date: Wed, 6 May 2020 17:21:25 +0200
Subject: [PATCH] vanitygaps - adds gaps to layouts
This patch differentiates between inner and outer gaps as well as
horizontal and vertical gaps.
The logic of these layouts also aims to be pixel perfect by ensuring
an even split of the available space and re-distributing the remainder
among the available clients.
---
config.def.h | 38 ++-
dwm.c | 35 +--
vanitygaps.c | 809 +++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 854 insertions(+), 28 deletions(-)
create mode 100644 vanitygaps.c
diff --git a/config.def.h b/config.def.h
index 1c0b587..a886863 100644
--- a/config.def.h
+++ b/config.def.h
@@ -3,6 +3,11 @@
/* appearance */
static const unsigned int borderpx = 1; /* 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 int smartgaps = 0; /* 1 means no outer gap when there is only one window */
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" };
@@ -36,11 +41,26 @@ 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 = 1; /* 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 */
{ "[]=", tile }, /* first entry is default */
- { "><>", NULL }, /* no layout function means floating behavior */
{ "[M]", monocle },
+ { "[@]", spiral },
+ { "[\\]", dwindle },
+ { "H[]", deck },
+ { "TTT", bstack },
+ { "===", bstackhoriz },
+ { "HHH", grid },
+ { "###", nrowgrid },
+ { "---", horizgrid },
+ { ":::", gaplessgrid },
+ { "|M|", centeredmaster },
+ { ">M>", centeredfloatingmaster },
+ { "><>", NULL }, /* no layout function means floating behavior */
+ { NULL, NULL },
};
/* key definitions */
@@ -71,6 +91,22 @@ static Key keys[] = {
{ MODKEY, XK_h, setmfact, {.f = -0.05} },
{ MODKEY, XK_l, setmfact, {.f = +0.05} },
{ MODKEY, XK_Return, zoom, {0} },
+ { MODKEY|Mod4Mask, XK_u, incrgaps, {.i = +1 } },
+ { MODKEY|Mod4Mask|ShiftMask, XK_u, incrgaps, {.i = -1 } },
+ { MODKEY|Mod4Mask, XK_i, incrigaps, {.i = +1 } },
+ { MODKEY|Mod4Mask|ShiftMask, XK_i, incrigaps, {.i = -1 } },
+ { MODKEY|Mod4Mask, XK_o, incrogaps, {.i = +1 } },
+ { MODKEY|Mod4Mask|ShiftMask, XK_o, incrogaps, {.i = -1 } },
+ { MODKEY|Mod4Mask, XK_6, incrihgaps, {.i = +1 } },
+ { MODKEY|Mod4Mask|ShiftMask, XK_6, incrihgaps, {.i = -1 } },
+ { MODKEY|Mod4Mask, XK_7, incrivgaps, {.i = +1 } },
+ { MODKEY|Mod4Mask|ShiftMask, XK_7, incrivgaps, {.i = -1 } },
+ { MODKEY|Mod4Mask, XK_8, incrohgaps, {.i = +1 } },
+ { MODKEY|Mod4Mask|ShiftMask, XK_8, incrohgaps, {.i = -1 } },
+ { MODKEY|Mod4Mask, XK_9, incrovgaps, {.i = +1 } },
+ { MODKEY|Mod4Mask|ShiftMask, XK_9, incrovgaps, {.i = -1 } },
+ { MODKEY|Mod4Mask, XK_0, togglegaps, {0} },
+ { MODKEY|Mod4Mask|ShiftMask, XK_0, defaultgaps, {0} },
{ MODKEY, XK_Tab, view, {0} },
{ MODKEY|ShiftMask, XK_c, killclient, {0} },
{ MODKEY, XK_t, setlayout, {.v = &layouts[0]} },
diff --git a/dwm.c b/dwm.c
index 4465af1..c3b2d82 100644
--- a/dwm.c
+++ b/dwm.c
@@ -119,6 +119,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];
@@ -208,7 +212,6 @@ static void sigchld(int unused);
static void spawn(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 toggletag(const Arg *arg);
@@ -638,6 +641,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);
@@ -1670,32 +1677,6 @@ tagmon(const Arg *arg)
sendmon(selmon->sel, dirtomon(arg->i));
}
-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);
- resize(c, m->wx, m->wy + my, mw - (2*c->bw), h - (2*c->bw), 0);
- my += HEIGHT(c);
- } 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), 0);
- ty += HEIGHT(c);
- }
-}
-
void
togglebar(const Arg *arg)
{
diff --git a/vanitygaps.c b/vanitygaps.c
new file mode 100644
index 0000000..3f31593
--- /dev/null
+++ b/vanitygaps.c
@@ -0,0 +1,809 @@
+/* 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 (delete the ones you do not need) */
+static void bstack(Monitor *m);
+static void bstackhoriz(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 grid(Monitor *m);
+static void nrowgrid(Monitor *m);
+static void spiral(Monitor *m);
+static void tile(Monitor *m);
+/* Internals */
+static void getgaps(Monitor *m, int *oh, int *ov, int *ih, int *iv, unsigned int *nc);
+static void getfacts(Monitor *m, int msize, int ssize, float *mf, float *sf, int *mr, int *sr);
+static void setgaps(int oh, int ov, int ih, int iv);
+
+/* Settings */
+#if !PERTAG_PATCH
+static int enablegaps = 1;
+#endif // PERTAG_PATCH
+
+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);
+}
+
+void
+togglegaps(const Arg *arg)
+{
+ #if PERTAG_PATCH
+ selmon->pertag->enablegaps[selmon->pertag->curtag] = !selmon->pertag->enablegaps[selmon->pertag->curtag];
+ #else
+ enablegaps = !enablegaps;
+ #endif // PERTAG_PATCH
+ arrange(NULL);
+}
+
+void
+defaultgaps(const Arg *arg)
+{
+ setgaps(gappoh, gappov, gappih, gappiv);
+}
+
+void
+incrgaps(const Arg *arg)
+{
+ setgaps(
+ selmon->gappoh + arg->i,
+ selmon->gappov + arg->i,
+ selmon->gappih + arg->i,
+ selmon->gappiv + arg->i
+ );
+}
+
+void
+incrigaps(const Arg *arg)
+{
+ setgaps(
+ selmon->gappoh,
+ selmon->gappov,
+ selmon->gappih + arg->i,
+ selmon->gappiv + arg->i
+ );
+}
+
+void
+incrogaps(const Arg *arg)
+{
+ setgaps(
+ selmon->gappoh + arg->i,
+ selmon->gappov + arg->i,
+ selmon->gappih,
+ selmon->gappiv
+ );
+}
+
+void
+incrohgaps(const Arg *arg)
+{
+ setgaps(
+ selmon->gappoh + arg->i,
+ selmon->gappov,
+ selmon->gappih,
+ selmon->gappiv
+ );
+}
+
+void
+incrovgaps(const Arg *arg)
+{
+ setgaps(
+ selmon->gappoh,
+ selmon->gappov + arg->i,
+ selmon->gappih,
+ selmon->gappiv
+ );
+}
+
+void
+incrihgaps(const Arg *arg)
+{
+ setgaps(
+ selmon->gappoh,
+ selmon->gappov,
+ selmon->gappih + arg->i,
+ selmon->gappiv
+ );
+}
+
+void
+incrivgaps(const Arg *arg)
+{
+ setgaps(
+ selmon->gappoh,
+ selmon->gappov,
+ selmon->gappih,
+ selmon->gappiv + arg->i
+ );
+}
+
+void
+getgaps(Monitor *m, int *oh, int *ov, int *ih, int *iv, unsigned int *nc)
+{
+ unsigned int n, oe, ie;
+ #if PERTAG_PATCH
+ oe = ie = selmon->pertag->enablegaps[selmon->pertag->curtag];
+ #else
+ oe = ie = enablegaps;
+ #endif // PERTAG_PATCH
+ 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 oh, ov, ih, iv;
+ 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;
+
+ 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 - sh;
+ 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;
+ }
+ }
+}
+
+static void
+bstackhoriz(Monitor *m)
+{
+ unsigned int i, n;
+ int oh, ov, ih, iv;
+ 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;
+
+ 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;
+ sh = m->wh - 2*oh - ih * (n - m->nmaster - 1);
+ mw = m->ww - 2*ov - iv * (MIN(n, m->nmaster) - 1);
+ sw = m->ww - 2*ov;
+
+ if (m->nmaster && n > m->nmaster) {
+ sh = (mh - ih) * (1 - m->mfact);
+ mh = mh - ih - sh;
+ sy = my + mh + ih;
+ sh = m->wh - mh - 2*oh - ih * (n - m->nmaster);
+ }
+
+ getfacts(m, mw, 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 / mfacts) + (i < mrest ? 1 : 0) - (2*c->bw), mh - (2*c->bw), 0);
+ mx += WIDTH(c) + iv;
+ } 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;
+ }
+ }
+}
+
+/*
+ * Centred master layout + gaps
+ * https://dwm.suckless.org/patches/centeredmaster/
+ */
+void
+centeredmaster(Monitor *m)
+{
+ unsigned int i, n;
+ int oh, ov, ih, iv;
+ 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;
+
+ 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;
+ rw = (m->ww - mw - 2*ov - 2*iv) - lw;
+ mx += lw + iv;
+ } else {
+ /* ||<---M--->|<-S->|| */
+ mw = (mw - iv) * m->mfact;
+ lw = 0;
+ rw = m->ww - mw - iv - 2*ov;
+ }
+ 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;
+ float mivf = 1.0; // master inner vertical gap factor
+ int oh, ov, ih, iv, mrest, srest;
+ int mx = 0, my = 0, mh = 0, mw = 0;
+ int sx = 0, sy = 0, sh = 0, sw = 0;
+ Client *c;
+
+ 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;
+ } 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*oh) / 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/
+ */
+void
+deck(Monitor *m)
+{
+ unsigned int i, n;
+ int oh, ov, ih, iv;
+ 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;
+
+ 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 - sw;
+ 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/
+ */
+void
+fibonacci(Monitor *m, int s)
+{
+ unsigned int i, n;
+ int nx, ny, nw, nh;
+ int oh, ov, ih, iv;
+ int nv, hrest = 0, wrest = 0, r = 1;
+ Client *c;
+
+ getgaps(m, &oh, &ov, &ih, &iv, &n);
+ if (n == 0)
+ return;
+
+ nx = m->wx + ov;
+ ny = m->wy + oh;
+ nw = m->ww - 2*ov;
+ nh = m->wh - 2*oh;
+
+ for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next)) {
+ if (r) {
+ if ((i % 2 && (nh - ih) / 2 <= (bh + 2*c->bw))
+ || (!(i % 2) && (nw - iv) / 2 <= (bh + 2*c->bw))) {
+ r = 0;
+ }
+ if (r && i < n - 1) {
+ if (i % 2) {
+ nv = (nh - ih) / 2;
+ hrest = nh - 2*nv - ih;
+ nh = nv;
+ } else {
+ nv = (nw - iv) / 2;
+ wrest = nw - 2*nv - iv;
+ nw = nv;
+ }
+
+ 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;
+ nh += hrest;
+ }
+ else {
+ nh -= hrest;
+ ny -= nh + ih;
+ }
+ }
+ else if ((i % 4) == 1) {
+ nx += nw + iv;
+ nw += wrest;
+ }
+ else if ((i % 4) == 2) {
+ ny += nh + ih;
+ nh += hrest;
+ if (i < n - 1)
+ nw += wrest;
+ }
+ else if ((i % 4) == 3) {
+ if (s) {
+ nx += nw + iv;
+ nw -= wrest;
+ } else {
+ nw -= wrest;
+ nx -= nw + iv;
+ nh += hrest;
+ }
+ }
+ if (i == 0) {
+ if (n != 1) {
+ nw = (m->ww - iv - 2*ov) - (m->ww - iv - 2*ov) * (1 - m->mfact);
+ wrest = 0;
+ }
+ 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);
+ }
+}
+
+void
+dwindle(Monitor *m)
+{
+ fibonacci(m, 1);
+}
+
+void
+spiral(Monitor *m)
+{
+ fibonacci(m, 0);
+}
+
+/*
+ * Gappless grid layout + gaps (ironically)
+ * https://dwm.suckless.org/patches/gaplessgrid/
+ */
+void
+gaplessgrid(Monitor *m)
+{
+ unsigned int i, n;
+ int x, y, cols, rows, ch, cw, cn, rn, rrest, crest; // counters
+ int oh, ov, ih, iv;
+ Client *c;
+
+ getgaps(m, &oh, &ov, &ih, &iv, &n);
+ if (n == 0)
+ return;
+
+ /* grid dimensions */
+ for (cols = 0; cols <= n/2; cols++)
+ if (cols*cols >= n)
+ break;
+ if (n == 5) /* set layout against the general calculation: not 1:2:2, but 2:3 */
+ cols = 2;
+ rows = n/cols;
+ cn = rn = 0; // reset column no, row no, client count
+
+ ch = (m->wh - 2*oh - ih * (rows - 1)) / rows;
+ cw = (m->ww - 2*ov - iv * (cols - 1)) / cols;
+ rrest = (m->wh - 2*oh - ih * (rows - 1)) - ch * rows;
+ crest = (m->ww - 2*ov - iv * (cols - 1)) - cw * cols;
+ x = m->wx + ov;
+ y = m->wy + oh;
+
+ for (i = 0, c = nexttiled(m->clients); c; i++, c = nexttiled(c->next)) {
+ if (i/rows + 1 > cols - n%cols) {
+ rows = n/cols + 1;
+ ch = (m->wh - 2*oh - ih * (rows - 1)) / rows;
+ rrest = (m->wh - 2*oh - ih * (rows - 1)) - ch * rows;
+ }
+ resize(c,
+ x,
+ y + rn*(ch + ih) + MIN(rn, rrest),
+ cw + (cn < crest ? 1 : 0) - 2*c->bw,
+ ch + (rn < rrest ? 1 : 0) - 2*c->bw,
+ 0);
+ rn++;
+ if (rn >= rows) {
+ rn = 0;
+ x += cw + ih + (cn < crest ? 1 : 0);
+ cn++;
+ }
+ }
+}
+
+/*
+ * Gridmode layout + gaps
+ * https://dwm.suckless.org/patches/gridmode/
+ */
+void
+grid(Monitor *m)
+{
+ unsigned int i, n;
+ int cx, cy, cw, ch, cc, cr, chrest, cwrest, cols, rows;
+ int oh, ov, ih, iv;
+ Client *c;
+
+ getgaps(m, &oh, &ov, &ih, &iv, &n);
+
+ /* grid dimensions */
+ for (rows = 0; rows <= n/2; rows++)
+ if (rows*rows >= n)
+ break;
+ cols = (rows && (rows - 1) * rows >= n) ? rows - 1 : rows;
+
+ /* window geoms (cell height/width) */
+ ch = (m->wh - 2*oh - ih * (rows - 1)) / (rows ? rows : 1);
+ cw = (m->ww - 2*ov - iv * (cols - 1)) / (cols ? cols : 1);
+ chrest = (m->wh - 2*oh - ih * (rows - 1)) - ch * rows;
+ cwrest = (m->ww - 2*ov - iv * (cols - 1)) - cw * cols;
+ for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) {
+ cc = i / rows;
+ cr = i % rows;
+ cx = m->wx + ov + cc * (cw + iv) + MIN(cc, cwrest);
+ cy = m->wy + oh + cr * (ch + ih) + MIN(cr, chrest);
+ resize(c, cx, cy, cw + (cc < cwrest ? 1 : 0) - 2*c->bw, ch + (cr < chrest ? 1 : 0) - 2*c->bw, False);
+ }
+}
+
+/*
+ * Horizontal grid layout + gaps
+ * https://dwm.suckless.org/patches/horizgrid/
+ */
+void
+horizgrid(Monitor *m) {
+ Client *c;
+ unsigned int n, i;
+ int oh, ov, ih, iv;
+ int mx = 0, my = 0, mh = 0, mw = 0;
+ int sx = 0, sy = 0, sh = 0, sw = 0;
+ int ntop, nbottom = 1;
+ float mfacts, sfacts;
+ int mrest, srest;
+
+ /* Count windows */
+ getgaps(m, &oh, &ov, &ih, &iv, &n);
+ if (n == 0)
+ return;
+
+ if (n <= 2)
+ ntop = n;
+ else {
+ ntop = n / 2;
+ nbottom = n - ntop;
+ }
+ sx = mx = m->wx + ov;
+ sy = my = m->wy + oh;
+ sh = mh = m->wh - 2*oh;
+ sw = mw = m->ww - 2*ov;
+
+ if (n > ntop) {
+ sh = (mh - ih) / 2;
+ mh = mh - ih - sh;
+ sy = my + mh + ih;
+ mw = m->ww - 2*ov - iv * (ntop - 1);
+ sw = m->ww - 2*ov - iv * (nbottom - 1);
+ }
+
+ mfacts = ntop;
+ sfacts = nbottom;
+ mrest = mw - (mw / ntop) * ntop;
+ srest = sw - (sw / nbottom) * nbottom;
+
+ for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++)
+ if (i < ntop) {
+ 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 - ntop) < srest ? 1 : 0) - (2*c->bw), sh - (2*c->bw), 0);
+ sx += WIDTH(c) + iv;
+ }
+}
+
+/*
+ * nrowgrid layout + gaps
+ * https://dwm.suckless.org/patches/nrowgrid/
+ */
+void
+nrowgrid(Monitor *m)
+{
+ unsigned int n;
+ int ri = 0, ci = 0; /* counters */
+ int oh, ov, ih, iv; /* vanitygap settings */
+ 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 */
+ getgaps(m, &oh, &ov, &ih, &iv, &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 + oh;
+ ch = (m->wh - 2*oh - ih*(rows - 1)) / rows;
+ uh = ch;
+
+ for (c = nexttiled(m->clients); c; c = nexttiled(c->next), ci++) {
+ if (ci == cols) {
+ uw = 0;
+ ci = 0;
+ ri++;
+
+ /* next row */
+ cols = (n - uc) / (rows - ri);
+ uc += cols;
+ cy = m->wy + oh + uh + ih;
+ uh += ch + ih;
+ }
+
+ cx = m->wx + ov + uw;
+ cw = (m->ww - 2*ov - uw) / (cols - ci);
+ uw += cw + iv;
+
+ resize(c, cx, cy, cw - (2*c->bw), ch - (2*c->bw), 0);
+ }
+}
+
+/*
+ * Default tile layout + gaps
+ */
+static void
+tile(Monitor *m)
+{
+ unsigned int i, n;
+ int oh, ov, ih, iv;
+ 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;
+
+ 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 - sw;
+ 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;
+ }
+}
\ No newline at end of file
--
2.19.1

View File

@ -0,0 +1,235 @@
From 2832bd78a690606a48a7e1d370cd60fd92ee4988 Mon Sep 17 00:00:00 2001
From: MLquest8 <miskuzius@gmail.com>
Date: Fri, 12 Jun 2020 15:43:31 +0400
Subject: [PATCH] handle various setting of various types from Xresources
---
config.def.h | 54 ++++++++++++++++++++++++++-------------
drw.c | 2 +-
drw.h | 2 +-
dwm.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 111 insertions(+), 19 deletions(-)
diff --git a/config.def.h b/config.def.h
index 1c0b587..e69f288 100644
--- a/config.def.h
+++ b/config.def.h
@@ -1,21 +1,22 @@
/* See LICENSE file for copyright and license details. */
/* appearance */
-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 unsigned int borderpx = 1; /* border pixel of windows */
+static unsigned int snap = 32; /* snap pixel */
+static int showbar = 1; /* 0 means no bar */
+static int topbar = 1; /* 0 means bottom bar */
static const char *fonts[] = { "monospace:size=10" };
static const char dmenufont[] = "monospace:size=10";
-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[] = "#005577";
-static const char *colors[][3] = {
- /* fg bg border */
- [SchemeNorm] = { col_gray3, col_gray1, col_gray2 },
- [SchemeSel] = { col_gray4, col_cyan, col_cyan },
+static char normbgcolor[] = "#222222";
+static char normbordercolor[] = "#444444";
+static char normfgcolor[] = "#bbbbbb";
+static char selfgcolor[] = "#eeeeee";
+static char selbordercolor[] = "#005577";
+static char selbgcolor[] = "#005577";
+static char *colors[][3] = {
+ /* fg bg border */
+ [SchemeNorm] = { normfgcolor, normbgcolor, normbordercolor },
+ [SchemeSel] = { selfgcolor, selbgcolor, selbordercolor },
};
/* tagging */
@@ -32,9 +33,9 @@ static const Rule rules[] = {
};
/* 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 = 1; /* 1 means respect size hints in tiled resizals */
+static float mfact = 0.55; /* factor of master area size [0.05..0.95] */
+static int nmaster = 1; /* number of clients in master area */
+static int resizehints = 1; /* 1 means respect size hints in tiled resizals */
static const Layout layouts[] = {
/* symbol arrange function */
@@ -56,9 +57,28 @@ static const Layout layouts[] = {
/* commands */
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 *dmenucmd[] = { "dmenu_run", "-m", dmenumon, "-fn", dmenufont, "-nb", normbgcolor, "-nf", normfgcolor, "-sb", selbordercolor, "-sf", selfgcolor, NULL };
static const char *termcmd[] = { "st", NULL };
+/*
+ * Xresources preferences to load at startup
+ */
+ResourcePref resources[] = {
+ { "normbgcolor", STRING, &normbgcolor },
+ { "normbordercolor", STRING, &normbordercolor },
+ { "normfgcolor", STRING, &normfgcolor },
+ { "selbgcolor", STRING, &selbgcolor },
+ { "selbordercolor", STRING, &selbordercolor },
+ { "selfgcolor", STRING, &selfgcolor },
+ { "borderpx", INTEGER, &borderpx },
+ { "snap", INTEGER, &snap },
+ { "showbar", INTEGER, &showbar },
+ { "topbar", INTEGER, &topbar },
+ { "nmaster", INTEGER, &nmaster },
+ { "resizehints", INTEGER, &resizehints },
+ { "mfact", FLOAT, &mfact },
+};
+
static Key keys[] = {
/* modifier key function argument */
{ MODKEY, XK_p, spawn, {.v = dmenucmd } },
diff --git a/drw.c b/drw.c
index 4cdbcbe..8f1059e 100644
--- a/drw.c
+++ b/drw.c
@@ -208,7 +208,7 @@ drw_clr_create(Drw *drw, Clr *dest, const char *clrname)
/* 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/drw.h b/drw.h
index 4bcd5ad..42b04ce 100644
--- a/drw.h
+++ b/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/dwm.c b/dwm.c
index 9fd0286..dc0d219 100644
--- a/dwm.c
+++ b/dwm.c
@@ -36,6 +36,7 @@
#include <X11/Xlib.h>
#include <X11/Xproto.h>
#include <X11/Xutil.h>
+#include <X11/Xresource.h>
#ifdef XINERAMA
#include <X11/extensions/Xinerama.h>
#endif /* XINERAMA */
@@ -141,6 +142,19 @@ typedef struct {
int monitor;
} Rule;
+/* Xresources preferences */
+enum resource_type {
+ STRING = 0,
+ INTEGER = 1,
+ FLOAT = 2
+};
+
+typedef struct {
+ char *name;
+ enum resource_type type;
+ void *dst;
+} ResourcePref;
+
/* function declarations */
static void applyrules(Client *c);
static int applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact);
@@ -234,6 +248,8 @@ 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 load_xresources(void);
+static void resource_load(XrmDatabase db, char *name, enum resource_type rtype, void *dst);
/* variables */
static const char broken[] = "broken";
@@ -2127,6 +2143,60 @@ zoom(const Arg *arg)
pop(c);
}
+void
+resource_load(XrmDatabase db, char *name, enum resource_type rtype, void *dst)
+{
+ char *sdst = NULL;
+ int *idst = NULL;
+ float *fdst = NULL;
+
+ sdst = dst;
+ idst = dst;
+ fdst = dst;
+
+ char fullname[256];
+ char *type;
+ XrmValue ret;
+
+ snprintf(fullname, sizeof(fullname), "%s.%s", "dwm", name);
+ fullname[sizeof(fullname) - 1] = '\0';
+
+ XrmGetResource(db, fullname, "*", &type, &ret);
+ if (!(ret.addr == NULL || strncmp("String", type, 64)))
+ {
+ switch (rtype) {
+ case STRING:
+ strcpy(sdst, ret.addr);
+ break;
+ case INTEGER:
+ *idst = strtoul(ret.addr, NULL, 10);
+ break;
+ case FLOAT:
+ *fdst = strtof(ret.addr, NULL);
+ break;
+ }
+ }
+}
+
+void
+load_xresources(void)
+{
+ Display *display;
+ char *resm;
+ XrmDatabase db;
+ ResourcePref *p;
+
+ display = XOpenDisplay(NULL);
+ resm = XResourceManagerString(display);
+ if (!resm)
+ return;
+
+ db = XrmGetStringDatabase(resm);
+ for (p = resources; p < resources + LENGTH(resources); p++)
+ resource_load(db, p->name, p->type, p->dst);
+ XCloseDisplay(display);
+}
+
int
main(int argc, char *argv[])
{
@@ -2139,6 +2209,8 @@ main(int argc, char *argv[])
if (!(dpy = XOpenDisplay(NULL)))
die("dwm: cannot open display");
checkotherwm();
+ XrmInitialize();
+ load_xresources();
setup();
#ifdef __OpenBSD__
if (pledge("stdio rpath proc exec", NULL) == -1)
--
2.26.2

42
transient.c Normal file
View File

@ -0,0 +1,42 @@
/* cc transient.c -o transient -lX11 */
#include <stdlib.h>
#include <unistd.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
int main(void) {
Display *d;
Window r, f, t = None;
XSizeHints h;
XEvent e;
d = XOpenDisplay(NULL);
if (!d)
exit(1);
r = DefaultRootWindow(d);
f = XCreateSimpleWindow(d, r, 100, 100, 400, 400, 0, 0, 0);
h.min_width = h.max_width = h.min_height = h.max_height = 400;
h.flags = PMinSize | PMaxSize;
XSetWMNormalHints(d, f, &h);
XStoreName(d, f, "floating");
XMapWindow(d, f);
XSelectInput(d, f, ExposureMask);
while (1) {
XNextEvent(d, &e);
if (t == None) {
sleep(5);
t = XCreateSimpleWindow(d, r, 50, 50, 100, 100, 0, 0, 0);
XSetTransientForHint(d, t, f);
XStoreName(d, t, "transient");
XMapWindow(d, t);
XSelectInput(d, t, ExposureMask);
}
}
XCloseDisplay(d);
exit(0);
}

35
util.c Normal file
View File

@ -0,0 +1,35 @@
/* See LICENSE file for copyright and license details. */
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#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, ...) {
va_list ap;
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);
}
exit(1);
}

8
util.h Normal file
View File

@ -0,0 +1,8 @@
/* See LICENSE file for copyright and license details. */
#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))
void die(const char *fmt, ...);
void *ecalloc(size_t nmemb, size_t size);

809
vanitygaps.c Normal file
View File

@ -0,0 +1,809 @@
/* 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 (delete the ones you do not need) */
static void bstack(Monitor *m);
static void bstackhoriz(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 grid(Monitor *m);
static void nrowgrid(Monitor *m);
static void spiral(Monitor *m);
static void tile(Monitor *m);
/* Internals */
static void getgaps(Monitor *m, int *oh, int *ov, int *ih, int *iv, unsigned int *nc);
static void getfacts(Monitor *m, int msize, int ssize, float *mf, float *sf, int *mr, int *sr);
static void setgaps(int oh, int ov, int ih, int iv);
/* Settings */
#if !PERTAG_PATCH
static int enablegaps = 1;
#endif // PERTAG_PATCH
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);
}
void
togglegaps(const Arg *arg)
{
#if PERTAG_PATCH
selmon->pertag->enablegaps[selmon->pertag->curtag] = !selmon->pertag->enablegaps[selmon->pertag->curtag];
#else
enablegaps = !enablegaps;
#endif // PERTAG_PATCH
arrange(NULL);
}
void
defaultgaps(const Arg *arg)
{
setgaps(gappoh, gappov, gappih, gappiv);
}
void
incrgaps(const Arg *arg)
{
setgaps(
selmon->gappoh + arg->i,
selmon->gappov + arg->i,
selmon->gappih + arg->i,
selmon->gappiv + arg->i
);
}
void
incrigaps(const Arg *arg)
{
setgaps(
selmon->gappoh,
selmon->gappov,
selmon->gappih + arg->i,
selmon->gappiv + arg->i
);
}
void
incrogaps(const Arg *arg)
{
setgaps(
selmon->gappoh + arg->i,
selmon->gappov + arg->i,
selmon->gappih,
selmon->gappiv
);
}
void
incrohgaps(const Arg *arg)
{
setgaps(
selmon->gappoh + arg->i,
selmon->gappov,
selmon->gappih,
selmon->gappiv
);
}
void
incrovgaps(const Arg *arg)
{
setgaps(
selmon->gappoh,
selmon->gappov + arg->i,
selmon->gappih,
selmon->gappiv
);
}
void
incrihgaps(const Arg *arg)
{
setgaps(
selmon->gappoh,
selmon->gappov,
selmon->gappih + arg->i,
selmon->gappiv
);
}
void
incrivgaps(const Arg *arg)
{
setgaps(
selmon->gappoh,
selmon->gappov,
selmon->gappih,
selmon->gappiv + arg->i
);
}
void
getgaps(Monitor *m, int *oh, int *ov, int *ih, int *iv, unsigned int *nc)
{
unsigned int n, oe, ie;
#if PERTAG_PATCH
oe = ie = selmon->pertag->enablegaps[selmon->pertag->curtag];
#else
oe = ie = enablegaps;
#endif // PERTAG_PATCH
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 oh, ov, ih, iv;
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;
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 - sh;
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;
}
}
}
static void
bstackhoriz(Monitor *m)
{
unsigned int i, n;
int oh, ov, ih, iv;
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;
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;
sh = m->wh - 2*oh - ih * (n - m->nmaster - 1);
mw = m->ww - 2*ov - iv * (MIN(n, m->nmaster) - 1);
sw = m->ww - 2*ov;
if (m->nmaster && n > m->nmaster) {
sh = (mh - ih) * (1 - m->mfact);
mh = mh - ih - sh;
sy = my + mh + ih;
sh = m->wh - mh - 2*oh - ih * (n - m->nmaster);
}
getfacts(m, mw, 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 / mfacts) + (i < mrest ? 1 : 0) - (2*c->bw), mh - (2*c->bw), 0);
mx += WIDTH(c) + iv;
} 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;
}
}
}
/*
* Centred master layout + gaps
* https://dwm.suckless.org/patches/centeredmaster/
*/
void
centeredmaster(Monitor *m)
{
unsigned int i, n;
int oh, ov, ih, iv;
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;
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;
rw = (m->ww - mw - 2*ov - 2*iv) - lw;
mx += lw + iv;
} else {
/* ||<---M--->|<-S->|| */
mw = (mw - iv) * m->mfact;
lw = 0;
rw = m->ww - mw - iv - 2*ov;
}
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;
float mivf = 1.0; // master inner vertical gap factor
int oh, ov, ih, iv, mrest, srest;
int mx = 0, my = 0, mh = 0, mw = 0;
int sx = 0, sy = 0, sh = 0, sw = 0;
Client *c;
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;
} 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*oh) / 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/
*/
void
deck(Monitor *m)
{
unsigned int i, n;
int oh, ov, ih, iv;
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;
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 - sw;
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/
*/
void
fibonacci(Monitor *m, int s)
{
unsigned int i, n;
int nx, ny, nw, nh;
int oh, ov, ih, iv;
int nv, hrest = 0, wrest = 0, r = 1;
Client *c;
getgaps(m, &oh, &ov, &ih, &iv, &n);
if (n == 0)
return;
nx = m->wx + ov;
ny = m->wy + oh;
nw = m->ww - 2*ov;
nh = m->wh - 2*oh;
for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next)) {
if (r) {
if ((i % 2 && (nh - ih) / 2 <= (bh + 2*c->bw))
|| (!(i % 2) && (nw - iv) / 2 <= (bh + 2*c->bw))) {
r = 0;
}
if (r && i < n - 1) {
if (i % 2) {
nv = (nh - ih) / 2;
hrest = nh - 2*nv - ih;
nh = nv;
} else {
nv = (nw - iv) / 2;
wrest = nw - 2*nv - iv;
nw = nv;
}
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;
nh += hrest;
}
else {
nh -= hrest;
ny -= nh + ih;
}
}
else if ((i % 4) == 1) {
nx += nw + iv;
nw += wrest;
}
else if ((i % 4) == 2) {
ny += nh + ih;
nh += hrest;
if (i < n - 1)
nw += wrest;
}
else if ((i % 4) == 3) {
if (s) {
nx += nw + iv;
nw -= wrest;
} else {
nw -= wrest;
nx -= nw + iv;
nh += hrest;
}
}
if (i == 0) {
if (n != 1) {
nw = (m->ww - iv - 2*ov) - (m->ww - iv - 2*ov) * (1 - m->mfact);
wrest = 0;
}
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);
}
}
void
dwindle(Monitor *m)
{
fibonacci(m, 1);
}
void
spiral(Monitor *m)
{
fibonacci(m, 0);
}
/*
* Gappless grid layout + gaps (ironically)
* https://dwm.suckless.org/patches/gaplessgrid/
*/
void
gaplessgrid(Monitor *m)
{
unsigned int i, n;
int x, y, cols, rows, ch, cw, cn, rn, rrest, crest; // counters
int oh, ov, ih, iv;
Client *c;
getgaps(m, &oh, &ov, &ih, &iv, &n);
if (n == 0)
return;
/* grid dimensions */
for (cols = 0; cols <= n/2; cols++)
if (cols*cols >= n)
break;
if (n == 5) /* set layout against the general calculation: not 1:2:2, but 2:3 */
cols = 2;
rows = n/cols;
cn = rn = 0; // reset column no, row no, client count
ch = (m->wh - 2*oh - ih * (rows - 1)) / rows;
cw = (m->ww - 2*ov - iv * (cols - 1)) / cols;
rrest = (m->wh - 2*oh - ih * (rows - 1)) - ch * rows;
crest = (m->ww - 2*ov - iv * (cols - 1)) - cw * cols;
x = m->wx + ov;
y = m->wy + oh;
for (i = 0, c = nexttiled(m->clients); c; i++, c = nexttiled(c->next)) {
if (i/rows + 1 > cols - n%cols) {
rows = n/cols + 1;
ch = (m->wh - 2*oh - ih * (rows - 1)) / rows;
rrest = (m->wh - 2*oh - ih * (rows - 1)) - ch * rows;
}
resize(c,
x,
y + rn*(ch + ih) + MIN(rn, rrest),
cw + (cn < crest ? 1 : 0) - 2*c->bw,
ch + (rn < rrest ? 1 : 0) - 2*c->bw,
0);
rn++;
if (rn >= rows) {
rn = 0;
x += cw + ih + (cn < crest ? 1 : 0);
cn++;
}
}
}
/*
* Gridmode layout + gaps
* https://dwm.suckless.org/patches/gridmode/
*/
void
grid(Monitor *m)
{
unsigned int i, n;
int cx, cy, cw, ch, cc, cr, chrest, cwrest, cols, rows;
int oh, ov, ih, iv;
Client *c;
getgaps(m, &oh, &ov, &ih, &iv, &n);
/* grid dimensions */
for (rows = 0; rows <= n/2; rows++)
if (rows*rows >= n)
break;
cols = (rows && (rows - 1) * rows >= n) ? rows - 1 : rows;
/* window geoms (cell height/width) */
ch = (m->wh - 2*oh - ih * (rows - 1)) / (rows ? rows : 1);
cw = (m->ww - 2*ov - iv * (cols - 1)) / (cols ? cols : 1);
chrest = (m->wh - 2*oh - ih * (rows - 1)) - ch * rows;
cwrest = (m->ww - 2*ov - iv * (cols - 1)) - cw * cols;
for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) {
cc = i / rows;
cr = i % rows;
cx = m->wx + ov + cc * (cw + iv) + MIN(cc, cwrest);
cy = m->wy + oh + cr * (ch + ih) + MIN(cr, chrest);
resize(c, cx, cy, cw + (cc < cwrest ? 1 : 0) - 2*c->bw, ch + (cr < chrest ? 1 : 0) - 2*c->bw, False);
}
}
/*
* Horizontal grid layout + gaps
* https://dwm.suckless.org/patches/horizgrid/
*/
void
horizgrid(Monitor *m) {
Client *c;
unsigned int n, i;
int oh, ov, ih, iv;
int mx = 0, my = 0, mh = 0, mw = 0;
int sx = 0, sy = 0, sh = 0, sw = 0;
int ntop, nbottom = 1;
float mfacts, sfacts;
int mrest, srest;
/* Count windows */
getgaps(m, &oh, &ov, &ih, &iv, &n);
if (n == 0)
return;
if (n <= 2)
ntop = n;
else {
ntop = n / 2;
nbottom = n - ntop;
}
sx = mx = m->wx + ov;
sy = my = m->wy + oh;
sh = mh = m->wh - 2*oh;
sw = mw = m->ww - 2*ov;
if (n > ntop) {
sh = (mh - ih) / 2;
mh = mh - ih - sh;
sy = my + mh + ih;
mw = m->ww - 2*ov - iv * (ntop - 1);
sw = m->ww - 2*ov - iv * (nbottom - 1);
}
mfacts = ntop;
sfacts = nbottom;
mrest = mw - (mw / ntop) * ntop;
srest = sw - (sw / nbottom) * nbottom;
for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++)
if (i < ntop) {
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 - ntop) < srest ? 1 : 0) - (2*c->bw), sh - (2*c->bw), 0);
sx += WIDTH(c) + iv;
}
}
/*
* nrowgrid layout + gaps
* https://dwm.suckless.org/patches/nrowgrid/
*/
void
nrowgrid(Monitor *m)
{
unsigned int n;
int ri = 0, ci = 0; /* counters */
int oh, ov, ih, iv; /* vanitygap settings */
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 */
getgaps(m, &oh, &ov, &ih, &iv, &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 + oh;
ch = (m->wh - 2*oh - ih*(rows - 1)) / rows;
uh = ch;
for (c = nexttiled(m->clients); c; c = nexttiled(c->next), ci++) {
if (ci == cols) {
uw = 0;
ci = 0;
ri++;
/* next row */
cols = (n - uc) / (rows - ri);
uc += cols;
cy = m->wy + oh + uh + ih;
uh += ch + ih;
}
cx = m->wx + ov + uw;
cw = (m->ww - 2*ov - uw) / (cols - ci);
uw += cw + iv;
resize(c, cx, cy, cw - (2*c->bw), ch - (2*c->bw), 0);
}
}
/*
* Default tile layout + gaps
*/
static void
tile(Monitor *m)
{
unsigned int i, n;
int oh, ov, ih, iv;
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;
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 - sw;
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;
}
}