diff --git a/.forgejo/workflows/renovate.yml b/.forgejo/workflows/renovate.yml
deleted file mode 100644
index cc9ea6c..0000000
--- a/.forgejo/workflows/renovate.yml
+++ /dev/null
@@ -1,23 +0,0 @@
-name: Renovate
-
-on:
- schedule:
- - cron: "0 * * * *"
-
-jobs:
- renovate:
- runs-on: docker
- container: renovate/renovate@sha256:5894fa7fae274b30ccb8c9edcd7b8f106cc7da2f4e3eda2c62c2daff32235830
- env:
- RENOVATE_TOKEN: ${{ secrets.RENOVATE_TOKEN }}
- GITHUB_COM_TOKEN: ${{ secrets.GH_NOPRIV_TOKEN }}
- RENOVATE_GIT_PRIVATE_KEY: ${{ secrets.JOHNNY5_GPG_PRIVKEY }}
- RENOVATE_PLATFORM: gitea
- RENOVATE_ENDPOINT: ${{ github.server_url }}
- RENOVATE_GIT_AUTHOR: "Johnny5 <bot@snaile.de>"
-
- steps:
- - uses: https://code.forgejo.org/actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
-
- - name: Renovate
- run: renovate ${{ github.repository }}
diff --git a/.forgejo/workflows/void-packages.yml b/.forgejo/workflows/void-packages.yml
deleted file mode 100644
index 584181b..0000000
--- a/.forgejo/workflows/void-packages.yml
+++ /dev/null
@@ -1,37 +0,0 @@
-# yaml-language-server: $schema=https://json.schemastore.org/github-workflow.json
-name: Update void-packages template
-
-on:
- push:
- tags: ["*"]
-
-jobs:
- update-template:
- name: Update xbps-src template
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v4
- with:
- fetch-depth: 0
- token: ${{ secrets.FORGEJO_PUSH_TOKEN }}
- repository: "snailed/void-custom"
- sparse-checkout: "srcpkgs/dwm-custom/"
- ref: "main"
-
- - name: Modify template
- id: checksum
- run: |
- sed -i '/version=/ c version=${{ github.ref_name }}' srcpkgs/dwm-custom/template
-
- wget https://git.snaile.de/snailed/dwm-custom/archive/${{ github.ref_name }}.tar.gz
- sha256sum="$(sha256sum ${{ github.ref_name }}.tar.gz | cut -d ' ' -f 1)"
- sed -i "/checksum=/ c checksum=${sha256sum}" srcpkgs/dwm-custom/template
- sed -i "/revision=/ c revision=1" srcpkgs/dwm-custom/template
-
- - name: Commit
- uses: https://github.com/stefanzweifel/git-auto-commit-action@3ea6ae190baf489ba007f7c92608f33ce20ef04a # v4.16.0
- with:
- commit_user_name: "Johnny5"
- commit_user_email: "bot@snaile.de"
- commit_author: "Johnny5 <bot@snaile.de>"
- commit_message: "dwm-custom: update to ${{ github.ref_name }}."
diff --git a/.gitignore b/.gitignore
index aaaff05..f6b676c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,3 @@
-drw.o
-dwm
-dwm.o
-util.o
-README.md
+dwm-final
+dwm-dev-1.0.0_1.x86_64.xbps
+pkg/usr
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000..1b17b6d
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,6 @@
+[submodule "dwm-flexipatch"]
+ path = dwm-flexipatch
+ url = https://github.com/bakkeby/dwm-flexipatch
+[submodule "flexipatch-finalizer"]
+ path = flexipatch-finalizer
+ url = https://github.com/bakkeby/flexipatch-finalizer
diff --git a/.renovaterc.json b/.renovaterc.json
deleted file mode 100644
index 468a904..0000000
--- a/.renovaterc.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
- "$schema": "https://docs.renovatebot.com/renovate-schema.json",
- "extends": [
- "local>snailed/renovate-config"
- ]
-}
diff --git a/.woodpecker.yml b/.woodpecker.yml
new file mode 100644
index 0000000..c6150b5
--- /dev/null
+++ b/.woodpecker.yml
@@ -0,0 +1,70 @@
+when:
+ - event: tag
+ - event: manual
+
+steps:
+ build:
+ image: gcc
+ commands: |
+ apt-get update
+ apt-get install -y \
+ libx11-dev libx11-xcb-dev libxcb1-dev \
+ libxcb-res0-dev libxft-dev libxinerama-dev \
+ libfreetype6-dev libfontconfig1-dev \
+ libpango1.0-dev
+ cp -f config.mk patches.h dwm-flexipatch/
+ flexipatch-finalizer/flexipatch-finalizer.sh -r -d dwm-flexipatch -o dwm-final
+ # for patch in patches/*.diff; do
+ # patch -d dwm-final <"$patch"
+ # done
+ cp -f config.h dwm-final/
+ cd dwm-final || exit 1
+ make clean install DESTDIR="$${CI_WORKSPACE}/pkg" PREFIX="/usr"
+
+
+ package-xbps:
+ image: ghcr.io/void-linux/void-musl-busybox
+ environment:
+ - LICENSE=GPL-2.0
+ - SHORT_DESCRIPTION=Customized dwm
+ - DEPENDENCIES="pango"
+ commands: |
+ xbps-create -A x86_64 \
+ -H "$${CI_REPO_URL}" \
+ -l "$${LICENSE}" \
+ -n "$${CI_REPO_NAME}-$${CI_COMMIT_TAG}_1" \
+ -m "$${CI_COMMIT_AUTHOR} <$${CI_COMMIT_AUTHOR_EMAIL}>" \
+ -s "$${SHORT_DESCRIPTION}" \
+ -D "$${DEPENDENCIES}" \
+ "$${CI_WORKSPACE}/pkg"
+
+ package-targz:
+ image: alpine
+ commands: |
+ tar czf $${CI_REPO_NAME}-$${CI_COMMIT_TAG}.tar.gz --directory=$${CI_WORKSPACE}/pkg .
+
+ publish:
+ image: woodpeckerci/plugin-gitea-release
+ settings:
+ base_url: https://git.snaile.de
+ files:
+ - "${CI_REPO_NAME}-${CI_COMMIT_TAG}.tar.gz"
+ api_key:
+ from_secret: gitea_release
+ target: main
+
+ publish-xbps:
+ image: ghcr.io/void-linux/void-musl-busybox
+ environment:
+ - XBPS_TARGET_ARCH=x86_64
+ secrets:
+ - source: xbps_pem_passphrase
+ target: XBPS_PASSPHRASE
+ volumes:
+ - /var/www/xbps:/target
+ - /etc/woodpecker/:/etc/woodpecker:ro
+ commands: |
+ export XBPS_TARGET_ARCH
+ mv $${CI_REPO_NAME}-$${CI_COMMIT_TAG}_1.x86_64.xbps /target
+ xbps-rindex -a /target/$${CI_REPO_NAME}-$${CI_COMMIT_TAG}_1.x86_64.xbps
+ xbps-rindex -S --signedby "$${CI_COMMIT_AUTHOR} <$${CI_COMMIT_AUTHOR_EMAIL}>" --privkey /etc/woodpecker/privkey.pem /target/$${CI_REPO_NAME}-$${CI_COMMIT_TAG}_1.x86_64.xbps
diff --git a/LICENSE b/LICENSE
deleted file mode 100644
index 995172f..0000000
--- a/LICENSE
+++ /dev/null
@@ -1,38 +0,0 @@
-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>
-© 2020-2022 Chris Down <chris@chrisdown.name>
-
-Permission is hereby granted, free of charge, to any person obtaining a
-copy of this software and associated documentation files (the "Software"),
-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.
diff --git a/Makefile b/Makefile
deleted file mode 100644
index 92f52ba..0000000
--- a/Makefile
+++ /dev/null
@@ -1,66 +0,0 @@
-# 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}
-
-# FreeBSD users, prefix all ifdef, else and endif statements with a . for this to work (e.g. .ifdef)
-
-ifdef YAJLLIBS
-all: dwm dwm-msg README.md
-else
-all: dwm README.md
-endif
-
-.c.o:
- ${CC} -c ${CFLAGS} $<
-
-${OBJ}: config.h config.mk
-
-config.h:
- cp config.def.h $@
-
-README.md:
- ./docs.awk config.h >$@
-
-dwm: ${OBJ}
- ${CC} -o $@ ${OBJ} ${LDFLAGS}
-
-ifdef YAJLLIBS
-dwm-msg:
- ${CC} -o $@ patch/ipc/dwm-msg.c ${LDFLAGS}
-endif
-
-clean:
- rm -f dwm ${OBJ} dwm-${VERSION}.tar.gz
- rm -f dwm-msg
- rm -f README.md
-
-dist: clean
- mkdir -p dwm-${VERSION}
- cp -R LICENSE Makefile README.md config.def.h config.mk\
- 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
- mkdir -p ${DESTDIR}${PREFIX}/share/doc/dwm
- cp -f README.md ${DESTDIR}${PREFIX}/share/doc/dwm
-ifdef YAJLLIBS
- cp -f dwm-msg ${DESTDIR}${PREFIX}/bin
-endif
- chmod 755 ${DESTDIR}${PREFIX}/bin/dwm
-ifdef YAJLLIBS
- chmod 755 ${DESTDIR}${PREFIX}/bin/dwm-msg
-endif
-
-uninstall:
- rm -f ${DESTDIR}${PREFIX}/bin/dwm\
- ${DESTDIR}${PREFIX}/share/doc/dwm/README.md
-
-.PHONY: all clean dist install uninstall
diff --git a/build.sh b/build.sh
new file mode 100755
index 0000000..4f1eab0
--- /dev/null
+++ b/build.sh
@@ -0,0 +1,16 @@
+#!/bin/sh
+
+cp config.mk patches.h dwm-flexipatch/
+flexipatch-finalizer/flexipatch-finalizer.sh -r -d dwm-flexipatch -o dwm-final
+for patch in patches/*.diff; do
+ patch -d dwm-final <"$patch"
+done
+cp config.h dwm-final/
+cd dwm-final || exit 1
+make clean install DESTDIR="../pkg" PREFIX="/usr"
+cd - || exit 1
+
+# xbps-create -A x86_64 \
+# -n "dwm-dev-1.0.0_1" \
+# -s "Test build of dwm" \
+# pkg
diff --git a/config.def.h b/config.def.h
deleted file mode 100644
index 80e3821..0000000
--- a/config.def.h
+++ /dev/null
@@ -1,335 +0,0 @@
-/* See LICENSE file for copyright and license details. */
-
-/* Helper macros for spawning commands */
-#define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } }
-#define CMD(...) { .v = (const char*[]){ __VA_ARGS__, NULL } }
-
-/* 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 int focusonwheel = 0;
-static int floatposgrid_x = 5; /* float grid columns */
-static int floatposgrid_y = 5; /* float grid rows */
-/* Status is to be shown on: -1 (all monitors), 0 (a specific monitor by index), 'A' (active monitor) */
-static const int statusmon = 'A';
-
-/* Indicators: see patch/bar_indicators.h for options */
-static int tagindicatortype = INDICATOR_TOP_LEFT_SQUARE;
-static int tiledindicatortype = INDICATOR_NONE;
-static int floatindicatortype = INDICATOR_TOP_LEFT_SQUARE;
-static const char font[] = "monospace 10";
-static const char dmenufont[] = "monospace:size=10";
-
-static char c000000[] = "#000000"; // placeholder value
-
-static char normfgcolor[] = "#bbbbbb";
-static char normbgcolor[] = "#222222";
-static char normbordercolor[] = "#444444";
-static char normfloatcolor[] = "#db8fd9";
-
-static char selfgcolor[] = "#eeeeee";
-static char selbgcolor[] = "#005577";
-static char selbordercolor[] = "#005577";
-static char selfloatcolor[] = "#005577";
-
-static char titlenormfgcolor[] = "#bbbbbb";
-static char titlenormbgcolor[] = "#222222";
-static char titlenormbordercolor[] = "#444444";
-static char titlenormfloatcolor[] = "#db8fd9";
-
-static char titleselfgcolor[] = "#eeeeee";
-static char titleselbgcolor[] = "#005577";
-static char titleselbordercolor[] = "#005577";
-static char titleselfloatcolor[] = "#005577";
-
-static char tagsnormfgcolor[] = "#bbbbbb";
-static char tagsnormbgcolor[] = "#222222";
-static char tagsnormbordercolor[] = "#444444";
-static char tagsnormfloatcolor[] = "#db8fd9";
-
-static char tagsselfgcolor[] = "#eeeeee";
-static char tagsselbgcolor[] = "#005577";
-static char tagsselbordercolor[] = "#005577";
-static char tagsselfloatcolor[] = "#005577";
-
-static char hidnormfgcolor[] = "#005577";
-static char hidselfgcolor[] = "#227799";
-static char hidnormbgcolor[] = "#222222";
-static char hidselbgcolor[] = "#222222";
-
-static char urgfgcolor[] = "#bbbbbb";
-static char urgbgcolor[] = "#222222";
-static char urgbordercolor[] = "#ff0000";
-static char urgfloatcolor[] = "#db8fd9";
-
-static char scratchselfgcolor[] = "#FFF7D4";
-static char scratchselbgcolor[] = "#77547E";
-static char scratchselbordercolor[] = "#894B9F";
-static char scratchselfloatcolor[] = "#894B9F";
-
-static char scratchnormfgcolor[] = "#FFF7D4";
-static char scratchnormbgcolor[] = "#664C67";
-static char scratchnormbordercolor[] = "#77547E";
-static char scratchnormfloatcolor[] = "#77547E";
-
-static char *colors[][ColCount] = {
- /* fg bg border float */
- [SchemeNorm] = { normfgcolor, normbgcolor, normbordercolor, normfloatcolor },
- [SchemeSel] = { selfgcolor, selbgcolor, selbordercolor, selfloatcolor },
- [SchemeTitleNorm] = { titlenormfgcolor, titlenormbgcolor, titlenormbordercolor, titlenormfloatcolor },
- [SchemeTitleSel] = { titleselfgcolor, titleselbgcolor, titleselbordercolor, titleselfloatcolor },
- [SchemeTagsNorm] = { tagsnormfgcolor, tagsnormbgcolor, tagsnormbordercolor, tagsnormfloatcolor },
- [SchemeTagsSel] = { tagsselfgcolor, tagsselbgcolor, tagsselbordercolor, tagsselfloatcolor },
- [SchemeHidNorm] = { hidnormfgcolor, hidnormbgcolor, c000000, c000000 },
- [SchemeHidSel] = { hidselfgcolor, hidselbgcolor, c000000, c000000 },
- [SchemeUrg] = { urgfgcolor, urgbgcolor, urgbordercolor, urgfloatcolor },
- [SchemeScratchSel] = { scratchselfgcolor, scratchselbgcolor, scratchselbordercolor, scratchselfloatcolor },
- [SchemeScratchNorm] = { scratchnormfgcolor, scratchnormbgcolor, scratchnormbordercolor, scratchnormfloatcolor },
-};
-
-static const char *const autostart[] = {
- "st", NULL,
- NULL /* terminate */
-};
-
-static const char *scratchpadcmd[] = {"s", "st", "-n", "spterm", NULL};
-
-/* Tags
- * In a traditional dwm the number of tags in use can be changed simply by changing the number
- * of strings in the tags array. This build does things a bit different which has some added
- * benefits. If you need to change the number of tags here then change the NUMTAGS macro in dwm.c.
- *
- * Examples:
- *
- * 1) static char *tagicons[][NUMTAGS*2] = {
- * [DEFAULT_TAGS] = { "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F", "G", "H", "I" },
- * }
- *
- * 2) static char *tagicons[][1] = {
- * [DEFAULT_TAGS] = { "•" },
- * }
- *
- * The first example would result in the tags on the first monitor to be 1 through 9, while the
- * tags for the second monitor would be named A through I. A third monitor would start again at
- * 1 through 9 while the tags on a fourth monitor would also be named A through I. Note the tags
- * count of NUMTAGS*2 in the array initialiser which defines how many tag text / icon exists in
- * the array. This can be changed to *3 to add separate icons for a third monitor.
- *
- * For the second example each tag would be represented as a bullet point. Both cases work the
- * same from a technical standpoint - the icon index is derived from the tag index and the monitor
- * index. If the icon index is is greater than the number of tag icons then it will wrap around
- * until it an icon matches. Similarly if there are two tag icons then it would alternate between
- * them. This works seamlessly with alternative tags and alttagsdecoration patches.
- */
-static char *tagicons[][NUMTAGS] =
-{
- [DEFAULT_TAGS] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" },
- [ALTERNATIVE_TAGS] = { "A", "B", "C", "D", "E", "F", "G", "H", "I" },
- [ALT_TAGS_DECORATION] = { "<1>", "<2>", "<3>", "<4>", "<5>", "<6>", "<7>", "<8>", "<9>" },
-};
-
-/* There are two options when it comes to per-client rules:
- * - a typical struct table or
- * - using the RULE macro
- *
- * A traditional struct table looks like this:
- * // class instance title wintype tags mask isfloating monitor
- * { "Gimp", NULL, NULL, NULL, 1 << 4, 0, -1 },
- * { "Firefox", NULL, NULL, NULL, 1 << 7, 0, -1 },
- *
- * The RULE macro has the default values set for each field allowing you to only
- * specify the values that are relevant for your rule, e.g.
- *
- * RULE(.class = "Gimp", .tags = 1 << 4)
- * RULE(.class = "Firefox", .tags = 1 << 7)
- *
- * Refer to the Rule struct definition for the list of available fields depending on
- * the patches you enable.
- */
-static const Rule rules[] = {
- /* xprop(1):
- * WM_CLASS(STRING) = instance, class
- * WM_NAME(STRING) = title
- * WM_WINDOW_ROLE(STRING) = role
- * _NET_WM_WINDOW_TYPE(ATOM) = wintype
- */
- RULE(.wintype = WTYPE "DIALOG", .isfloating = 1)
- RULE(.wintype = WTYPE "UTILITY", .isfloating = 1)
- RULE(.wintype = WTYPE "TOOLBAR", .isfloating = 1)
- RULE(.wintype = WTYPE "SPLASH", .isfloating = 1)
- RULE(.class = "Gimp", .tags = 1 << 4)
- RULE(.class = "Firefox", .tags = 1 << 7)
- RULE(.instance = "spterm", .scratchkey = 's', .isfloating = 1)
-};
-
-/* Bar rules allow you to configure what is shown where on the bar, as well as
- * introducing your own bar modules.
- *
- * monitor:
- * -1 show on all monitors
- * 0 show on monitor 0
- * 'A' show on active monitor (i.e. focused / selected) (or just -1 for active?)
- * bar - bar index, 0 is default, 1 is extrabar
- * alignment - how the module is aligned compared to other modules
- * widthfunc, drawfunc, clickfunc - providing bar module width, draw and click functions
- * name - does nothing, intended for visual clue and for logging / debugging
- */
-static const BarRule barrules[] = {
- /* monitor bar alignment widthfunc drawfunc clickfunc hoverfunc name */
- { -1, 0, BAR_ALIGN_LEFT, width_tags, draw_tags, click_tags, hover_tags, "tags" },
- { -1, 0, BAR_ALIGN_LEFT, width_ltsymbol, draw_ltsymbol, click_ltsymbol, NULL, "layout" },
- { statusmon, 0, BAR_ALIGN_RIGHT, width_status, draw_status, click_statuscmd, NULL, "status" },
- { -1, 0, BAR_ALIGN_NONE, width_wintitle, draw_wintitle, click_wintitle, NULL, "wintitle" },
-};
-
-/* layout(s) */
-static const float mfact = 0.55; /* factor of master area size [0.05..0.95] */
-static const int nmaster = 1; /* number of clients in master area */
-static const int resizehints = 0; /* 1 means respect size hints in tiled resizals */
-static const int lockfullscreen = 1; /* 1 will force focus on the fullscreen window */
-
-static const Layout layouts[] = {
- /* symbol arrange function */
- { "[]=", tile }, /* first entry is default */
- { "><>", NULL }, /* no layout function means floating behavior */
- { "TTT", bstack },
- { ":::", gaplessgrid },
-};
-
-/* key definitions */
-#define MODKEY Mod1Mask
-#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_s, ACTION##stack, {.i = PREVSEL } }, \
- { MOD, XK_w, ACTION##stack, {.i = 0 } }, \
- { MOD, XK_e, ACTION##stack, {.i = 1 } }, \
- { MOD, XK_a, ACTION##stack, {.i = 2 } }, \
- { MOD, XK_z, ACTION##stack, {.i = -1 } },
-
-/* commands */
-static const char *dmenucmd[] = {
- "dmenu_run",
- "-fn", dmenufont,
- "-nb", normbgcolor,
- "-nf", normfgcolor,
- "-sb", selbgcolor,
- "-sf", selfgcolor,
- NULL
-};
-static const char *termcmd[] = { "st", NULL };
-
-/* This defines the name of the executable that handles the bar (used for signalling purposes) */
-#define STATUSBAR "dwmblocks"
-
-static const Key keys[] = {
- /* modifier key function argument */
- { MODKEY, XK_p, spawn, {.v = dmenucmd } },
- { MODKEY|ShiftMask, XK_Return, spawn, {.v = termcmd } },
- { MODKEY, XK_b, togglebar, {0} },
- 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} },
- { MODKEY, XK_l, setmfact, {.f = +0.05} },
- { MODKEY, XK_Return, zoom, {0} },
- { MODKEY, XK_Tab, view, {0} },
- { MODKEY|ShiftMask, XK_c, killclient, {0} },
- { MODKEY|ShiftMask, XK_q, quit, {0} },
- { MODKEY|ControlMask|ShiftMask, XK_q, quit, {1} },
- { MODKEY, XK_t, setlayout, {.v = &layouts[0]} },
- { MODKEY, XK_f, setlayout, {.v = &layouts[1]} },
- { MODKEY, XK_m, setlayout, {.v = &layouts[2]} },
- { MODKEY, XK_space, setlayout, {0} },
- { MODKEY|ShiftMask, XK_space, togglefloating, {0} },
- { MODKEY, XK_grave, togglescratch, {.v = scratchpadcmd } },
- { MODKEY|ControlMask, XK_grave, setscratch, {.v = scratchpadcmd } },
- { MODKEY|ShiftMask, XK_grave, removescratch, {.v = scratchpadcmd } },
- { MODKEY|Mod4Mask, XK_space, unfloatvisible, {0} },
- { MODKEY|ShiftMask, XK_t, unfloatvisible, {.v = &layouts[0]} },
- { MODKEY, XK_y, togglefullscreen, {0} },
- { MODKEY, XK_0, view, {.ui = ~0 } },
- { MODKEY|ShiftMask, XK_0, tag, {.ui = ~0 } },
- { MODKEY, XK_comma, focusmon, {.i = -1 } },
- { MODKEY, XK_period, focusmon, {.i = +1 } },
- { MODKEY|ShiftMask, XK_comma, tagmon, {.i = -1 } },
- { MODKEY|ShiftMask, XK_period, tagmon, {.i = +1 } },
- /* Note that due to key limitations the below example kybindings are defined with a Mod3Mask,
- * which is not always readily available. Refer to the patch wiki for more details. */
- /* Client position is limited to monitor window area */
- { Mod3Mask, XK_u, floatpos, {.v = "-26x -26y" } }, // ↖
- { Mod3Mask, XK_i, floatpos, {.v = " 0x -26y" } }, // ↑
- { Mod3Mask, XK_o, floatpos, {.v = " 26x -26y" } }, // ↗
- { Mod3Mask, XK_j, floatpos, {.v = "-26x 0y" } }, // ←
- { Mod3Mask, XK_l, floatpos, {.v = " 26x 0y" } }, // →
- { Mod3Mask, XK_m, floatpos, {.v = "-26x 26y" } }, // ↙
- { Mod3Mask, XK_comma, floatpos, {.v = " 0x 26y" } }, // ↓
- { Mod3Mask, XK_period, floatpos, {.v = " 26x 26y" } }, // ↘
- /* Absolute positioning (allows moving windows between monitors) */
- { Mod3Mask|ControlMask, XK_u, floatpos, {.v = "-26a -26a" } }, // ↖
- { Mod3Mask|ControlMask, XK_i, floatpos, {.v = " 0a -26a" } }, // ↑
- { Mod3Mask|ControlMask, XK_o, floatpos, {.v = " 26a -26a" } }, // ↗
- { Mod3Mask|ControlMask, XK_j, floatpos, {.v = "-26a 0a" } }, // ←
- { Mod3Mask|ControlMask, XK_l, floatpos, {.v = " 26a 0a" } }, // →
- { Mod3Mask|ControlMask, XK_m, floatpos, {.v = "-26a 26a" } }, // ↙
- { Mod3Mask|ControlMask, XK_comma, floatpos, {.v = " 0a 26a" } }, // ↓
- { Mod3Mask|ControlMask, XK_period, floatpos, {.v = " 26a 26a" } }, // ↘
- /* Resize client, client center position is fixed which means that client expands in all directions */
- { Mod3Mask|ShiftMask, XK_u, floatpos, {.v = "-26w -26h" } }, // ↖
- { Mod3Mask|ShiftMask, XK_i, floatpos, {.v = " 0w -26h" } }, // ↑
- { Mod3Mask|ShiftMask, XK_o, floatpos, {.v = " 26w -26h" } }, // ↗
- { Mod3Mask|ShiftMask, XK_j, floatpos, {.v = "-26w 0h" } }, // ←
- { Mod3Mask|ShiftMask, XK_k, floatpos, {.v = "800W 800H" } }, // ·
- { Mod3Mask|ShiftMask, XK_l, floatpos, {.v = " 26w 0h" } }, // →
- { Mod3Mask|ShiftMask, XK_m, floatpos, {.v = "-26w 26h" } }, // ↙
- { Mod3Mask|ShiftMask, XK_comma, floatpos, {.v = " 0w 26h" } }, // ↓
- { Mod3Mask|ShiftMask, XK_period, floatpos, {.v = " 26w 26h" } }, // ↘
- /* Client is positioned in a floating grid, movement is relative to client's current position */
- { Mod3Mask|Mod1Mask, XK_u, floatpos, {.v = "-1p -1p" } }, // ↖
- { Mod3Mask|Mod1Mask, XK_i, floatpos, {.v = " 0p -1p" } }, // ↑
- { Mod3Mask|Mod1Mask, XK_o, floatpos, {.v = " 1p -1p" } }, // ↗
- { Mod3Mask|Mod1Mask, XK_j, floatpos, {.v = "-1p 0p" } }, // ←
- { Mod3Mask|Mod1Mask, XK_k, floatpos, {.v = " 0p 0p" } }, // ·
- { Mod3Mask|Mod1Mask, XK_l, floatpos, {.v = " 1p 0p" } }, // →
- { Mod3Mask|Mod1Mask, XK_m, floatpos, {.v = "-1p 1p" } }, // ↙
- { Mod3Mask|Mod1Mask, XK_comma, floatpos, {.v = " 0p 1p" } }, // ↓
- { Mod3Mask|Mod1Mask, XK_period, floatpos, {.v = " 1p 1p" } }, // ↘
- 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)
-};
-
-/* button definitions */
-/* click can be ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, or ClkRootWin */
-static const Button buttons[] = {
- /* click event mask button function argument */
- { ClkLtSymbol, 0, Button1, setlayout, {0} },
- { ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]} },
- { ClkWinTitle, 0, Button2, zoom, {0} },
- { ClkStatusText, 0, Button1, sigstatusbar, {.i = 1 } },
- { ClkStatusText, 0, Button2, sigstatusbar, {.i = 2 } },
- { ClkStatusText, 0, Button3, sigstatusbar, {.i = 3 } },
- { 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} },
-};
-
diff --git a/config.h b/config.h
index 8c0c92d..063a608 100644
--- a/config.h
+++ b/config.h
@@ -1,138 +1,169 @@
/* See LICENSE file for copyright and license details. */
-
#define TERM "st"
#define TERM_FLAG_NAME "-n"
#define TERM_FLAG_EXEC "-e"
-#define TERM_FLAG_CLASS "-c"
-
-#define BROWSER "floorp"
-#define BROWSER_FLAG_INCOG "--private-window"
-#define BROWSER_FLAG_1 "--disable-pinch"
+#define TERM_START "tmux"
#define STATUSBAR "dwmblocks"
+#define BROWSER "brave-browser"
+#define BROWSER_FLAG_INCOG "--incognito"
+#define BROWSER_FLAG_1 "--enable-blink-features=MiddleClickAutoscroll"
+
/* appearance */
-static const unsigned int borderpx = 2; /* border pixel of windows */
-static const unsigned int snap = 32; /* snap pixel */
-static const int showbar = 1; /* 0 means no bar */
-static const int topbar = 1; /* 0 means bottom bar */
-static const int focusonwheel = 0;
-static int floatposgrid_x = 5; /* float grid columns */
-static int floatposgrid_y = 5; /* float grid rows */
-/* Status is to be shown on: -1 (all monitors), 0 (a specific monitor by index), 'A' (active monitor) */
+static const unsigned int borderpx = 2;
+static const unsigned int snap = 33;
+static const int swallowfloating = 1;
+static const int showbar = 1;
+static const int topbar = 1;
+static const int focusonwheel = 1;
+static int floatposgrid_x = 5;
+static int floatposgrid_y = 3;
+static const unsigned int systrayspacing = 3;
+static const int showsystray = 1;
/* Indicators: see patch/bar_indicators.h for options */
static int tagindicatortype = INDICATOR_NONE;
static int tiledindicatortype = INDICATOR_NONE;
static int floatindicatortype = INDICATOR_NONE;
-static const int quit_empty_window_count = 0; /* only allow dwm to quit if no (<= count) windows are open */
-static const char font[] = "FiraCode Nerd Font 12";
-#define BLACK "#15161E"
-#define RED "#f7768e"
-#define GREEN "#9ece6a"
-#define ORANGE "#e0af68"
-#define BLUE "#7aa2f7"
-#define MAGENTA "#bb9af7"
-#define CYAN "#7dcfff"
-#define LIGHT_GRAY "#a9b1d6"
-#define GRAY "#414868"
-#define WHITE "#c0caf5"
-#define UNDEFINED "#ff0000"
+static const char font[] = "FiraCode Nerd Font 28";
-static char undefined[] = UNDEFINED; // placeholder value
+#define NOCOLOR "#FF0000"
+#define COLOR0 "#15161E"
+#define COLOR1 "#f7768e"
+#define COLOR2 "#9ece6a"
+#define COLOR3 "#e0af68"
+#define COLOR4 "#7aa2f7"
+#define COLOR5 "#bb9af7"
+#define COLOR6 "#7dcfff"
+#define COLOR7 "#a9b1d6"
+#define COLOR8 "#414868"
+#define COLOR9 "#f7768e"
+#define COLOR10 "#9ece6a"
+#define COLOR11 "#e0af68"
+#define COLOR12 "#7aa2f7"
+#define COLOR13 "#bb9af7"
+#define COLOR14 "#7dcfff"
+#define COLOR15 "#c0caf5"
-static char normfgcolor[] = WHITE;
-static char normbgcolor[] = BLACK;
-static char normbordercolor[] = GRAY;
-static char normfloatcolor[] = GRAY;
+#define BORDERNORM "#383c4a"
+#define BORDERSEL COLOR4
-static char selfgcolor[] = UNDEFINED;
-static char selbgcolor[] = UNDEFINED;
-static char selbordercolor[] = BLUE;
-static char selfloatcolor[] = BLUE;
+static char normfgcolor[] = COLOR15;
+static char normbgcolor[] = COLOR0;
+static char normbordercolor[] = BORDERNORM;
+static char normfloatcolor[] = BORDERNORM;
-static char titlenormfgcolor[] = WHITE;
-static char titlenormbgcolor[] = BLACK;
-static char titlenormbordercolor[] = UNDEFINED;
-static char titlenormfloatcolor[] = UNDEFINED;
+static char selfgcolor[] = COLOR15;
+static char selbgcolor[] = COLOR4;
+static char selbordercolor[] = BORDERSEL;
+static char selfloatcolor[] = BORDERSEL;
-static char titleselfgcolor[] = LIGHT_GRAY;
-static char titleselbgcolor[] = BLACK;
-static char titleselbordercolor[] = UNDEFINED;
-static char titleselfloatcolor[] = UNDEFINED;
+static char titlenormfgcolor[] = COLOR7;
+static char titlenormbgcolor[] = COLOR0;
+static char titlenormbordercolor[] = NOCOLOR;
+static char titlenormfloatcolor[] = NOCOLOR;
-static char tagsnormfgcolor[] = LIGHT_GRAY;
-static char tagsnormbgcolor[] = BLACK;
-static char tagsnormbordercolor[] = UNDEFINED;
-static char tagsnormfloatcolor[] = UNDEFINED;
+static char titleselfgcolor[] = COLOR7;
+static char titleselbgcolor[] = COLOR0;
+static char titleselbordercolor[] = NOCOLOR;
+static char titleselfloatcolor[] = NOCOLOR;
-static char tagsselfgcolor[] = BLACK;
-static char tagsselbgcolor[] = BLUE;
-static char tagsselbordercolor[] = UNDEFINED;
-static char tagsselfloatcolor[] = UNDEFINED;
+static char tagsnormfgcolor[] = COLOR7;
+static char tagsnormbgcolor[] = COLOR0;
+static char tagsnormbordercolor[] = NOCOLOR;
+static char tagsnormfloatcolor[] = NOCOLOR;
-static char hidnormfgcolor[] = UNDEFINED;
-static char hidselfgcolor[] = UNDEFINED;
-static char hidnormbgcolor[] = UNDEFINED;
-static char hidselbgcolor[] = UNDEFINED;
+static char tagsselfgcolor[] = COLOR0;
+static char tagsselbgcolor[] = COLOR4;
+static char tagsselbordercolor[] = NOCOLOR;
+static char tagsselfloatcolor[] = NOCOLOR;
-static char urgfgcolor[] = BLACK;
-static char urgbgcolor[] = RED;
-static char urgbordercolor[] = RED;
-static char urgfloatcolor[] = RED;
+static char hidnormfgcolor[] = NOCOLOR;
+static char hidselfgcolor[] = NOCOLOR;
+static char hidnormbgcolor[] = NOCOLOR;
+static char hidselbgcolor[] = NOCOLOR;
-static char scratchselfgcolor[] = UNDEFINED;
-static char scratchselbgcolor[] = UNDEFINED;
-static char scratchselbordercolor[] = BLUE;
-static char scratchselfloatcolor[] = BLUE;
+static char urgfgcolor[] = COLOR0;
+static char urgbgcolor[] = COLOR1;
+static char urgbordercolor[] = COLOR1;
+static char urgfloatcolor[] = COLOR1;
-static char scratchnormfgcolor[] = UNDEFINED;
-static char scratchnormbgcolor[] = UNDEFINED;
-static char scratchnormbordercolor[] = GRAY;
-static char scratchnormfloatcolor[] = GRAY;
+static char scratchselfgcolor[] = COLOR15;
+static char scratchselbgcolor[] = COLOR4;
+static char scratchselbordercolor[] = BORDERSEL;
+static char scratchselfloatcolor[] = BORDERSEL;
+
+static char scratchnormfgcolor[] = COLOR15;
+static char scratchnormbgcolor[] = COLOR0;
+static char scratchnormbordercolor[] = BORDERNORM;
+static char scratchnormfloatcolor[] = BORDERNORM;
+
+static const unsigned int baralpha = 0xcc;
+static const unsigned int borderalpha = OPAQUE;
+static const unsigned int alphas[][3] = {
+ /* fg bg border */
+ [SchemeNorm] = { OPAQUE, baralpha, borderalpha },
+ [SchemeSel] = { OPAQUE, baralpha, borderalpha },
+ [SchemeTitleNorm] = { OPAQUE, baralpha, borderalpha },
+ [SchemeTitleSel] = { OPAQUE, baralpha, borderalpha },
+ [SchemeTagsNorm] = { OPAQUE, baralpha, borderalpha },
+ [SchemeTagsSel] = { OPAQUE, OPAQUE, borderalpha },
+ [SchemeHidNorm] = { OPAQUE, baralpha, borderalpha },
+ [SchemeHidSel] = { OPAQUE, baralpha, borderalpha },
+ [SchemeUrg] = { OPAQUE, OPAQUE, borderalpha },
+ [SchemeScratchSel] = { OPAQUE, baralpha, borderalpha },
+ [SchemeScratchNorm] = { OPAQUE, baralpha, borderalpha },
+};
static char *colors[][ColCount] = {
- /* fg bg border float */
- [SchemeNorm] = { normfgcolor, normbgcolor, normbordercolor, normfloatcolor },
- [SchemeSel] = { selfgcolor, selbgcolor, selbordercolor, selfloatcolor },
- [SchemeTitleNorm] = { titlenormfgcolor, titlenormbgcolor, titlenormbordercolor, titlenormfloatcolor },
- [SchemeTitleSel] = { titleselfgcolor, titleselbgcolor, titleselbordercolor, titleselfloatcolor },
- [SchemeTagsNorm] = { tagsnormfgcolor, tagsnormbgcolor, tagsnormbordercolor, tagsnormfloatcolor },
- [SchemeTagsSel] = { tagsselfgcolor, tagsselbgcolor, tagsselbordercolor, tagsselfloatcolor },
- [SchemeHidNorm] = { hidnormfgcolor, hidnormbgcolor, undefined, undefined },
- [SchemeHidSel] = { hidselfgcolor, hidselbgcolor, undefined, undefined },
- [SchemeUrg] = { urgfgcolor, urgbgcolor, urgbordercolor, urgfloatcolor },
- [SchemeScratchSel] = { scratchselfgcolor, scratchselbgcolor, scratchselbordercolor, scratchselfloatcolor },
- [SchemeScratchNorm] = { scratchnormfgcolor, scratchnormbgcolor, scratchnormbordercolor, scratchnormfloatcolor },
+ /* fg bg border float */
+ [SchemeNorm] = { normfgcolor, normbgcolor, normbordercolor, normfloatcolor },
+ [SchemeSel] = { selfgcolor, selbgcolor, selbordercolor, selfloatcolor },
+ [SchemeTitleNorm] = { titlenormfgcolor, titlenormbgcolor, titlenormbordercolor, titlenormfloatcolor },
+ [SchemeTitleSel] = { titleselfgcolor, titleselbgcolor, titleselbordercolor, titleselfloatcolor },
+ [SchemeTagsNorm] = { tagsnormfgcolor, tagsnormbgcolor, tagsnormbordercolor, tagsnormfloatcolor },
+ [SchemeTagsSel] = { tagsselfgcolor, tagsselbgcolor, tagsselbordercolor, tagsselfloatcolor },
+ [SchemeHidNorm] = { hidnormfgcolor, hidnormbgcolor, NOCOLOR, NOCOLOR },
+ [SchemeHidSel] = { hidselfgcolor, hidselbgcolor, NOCOLOR, NOCOLOR },
+ [SchemeUrg] = { urgfgcolor, urgbgcolor, urgbordercolor, urgfloatcolor },
+ [SchemeScratchSel] = { scratchselfgcolor, scratchselbgcolor, scratchselbordercolor, scratchselfloatcolor },
+ [SchemeScratchNorm] = { scratchnormfgcolor, scratchnormbgcolor, scratchnormbordercolor, scratchnormfloatcolor },
};
-static char *tagicons[][NUMTAGS] =
-{
- [DEFAULT_TAGS] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" },
-};
+static const char *layoutmenu_cmd = "xmenulayout";
+// static const char *layoutxmenu = "$HOME/.local/libexec/dwm/xmenulayout"; // TODO: Patch layoutmenu to accept arguments
+// static const char *layoutdmenu = "$HOME/.local/libexec/dwm/dmenulayout"; // TODO: Patch layoutmenu to accept shell commands
-static const int autostart_kill_signal = SIGHUP;
static const char *const autostart[] = {
- "/bin/sh", "-c", "exec run-parts \"${XDG_CONFIG_HOME}/dwm/autorun.d\"", NULL,
- "/bin/sh", "-c", "exec runsvdir \"${SVDIR}\"", NULL,
+ "sh", "-c", "run-parts $HOME/.local/libexec/dwm/autorun.d", NULL,
+ "pipewire", NULL,
+ "wireplumber", NULL,
+ "pipewire", "-c", "pipewire-pulse.conf", NULL,
+ "dunst", NULL,
+ "picom", NULL,
+ "unclutter", "-noevents", "-idle", "3", NULL,
+ "syncthingtray", NULL,
+ "sh", "-c", "$HOME/.local/libexec/daemons/remapd", NULL,
+ "sh", "-c", "env PATH=\"$HOME/.local/libexec/statusbar:$PATH\" dwmblocks", NULL,
+ "sh", "-c", "$HOME/.local/libexec/dwm/locker", NULL,
NULL
};
-static const char *spterm[] = { "t", TERM, TERM_FLAG_CLASS, "spterm", NULL };
-static const char *spfile[] = { "f", TERM, TERM_FLAG_CLASS, "spfile", TERM_FLAG_EXEC, "lfX", NULL };
-static const char *spchat[] = { "a", TERM, TERM_FLAG_CLASS, "spchat", TERM_FLAG_EXEC, "aichat", "-s", NULL };
-static const char *spproc[] = { "p", TERM, TERM_FLAG_CLASS, "spproc", TERM_FLAG_EXEC, "btm", NULL };
-static const char *spdisk[] = { "d", TERM, TERM_FLAG_CLASS, "spdisk", TERM_FLAG_EXEC, "dua", "i", "/", NULL };
-static const char *spvolm[] = { "v", TERM, TERM_FLAG_CLASS, "spvolm", TERM_FLAG_EXEC, "ncpamixer", NULL };
-static const char *sphelp[] = { "h", TERM, TERM_FLAG_CLASS, "sphelp", TERM_FLAG_EXEC, "glow", "-p", "-s", "tokyo-night", "/usr/share/doc/dwm/README.md", NULL };
-static const char *spnetm[] = { "m", TERM, TERM_FLAG_CLASS, "spnetm", TERM_FLAG_EXEC, "/bin/sh", "-c", "sleep 0.01; nmtui", NULL }; // This sleep is needed to wait for DWM to size the window
-static const char *spblue[] = { "b", TERM, TERM_FLAG_CLASS, "spnetm", TERM_FLAG_EXEC, "bluetuith", NULL };
-static const char *spnetu[] = { "u", TERM, TERM_FLAG_CLASS, "spnetu", TERM_FLAG_EXEC, "bandwhich", NULL };
-static const char *spwiki1[] = { "w", TERM, TERM_FLAG_CLASS, "spwiki", TERM_FLAG_EXEC, "/bin/sh", "-c", "sleep 0.01; zk edit -t index -i", NULL };
-static const char *spwiki2[] = { "w", TERM, TERM_FLAG_CLASS, "spwiki", TERM_FLAG_EXEC, "/bin/sh", "-c", "sleep 0.01; zk edit -i", NULL };
-static const char *sptask[] = { "s", TERM, TERM_FLAG_CLASS, "sptask", TERM_FLAG_EXEC, "taskwarrior-tui", NULL };
-static const char *spcalc[] = { "c", TERM, TERM_FLAG_CLASS, "spcalc", TERM_FLAG_EXEC, "/bin/sh", "-c", "HOME=$XDG_DATA_HOME wcalc -C", NULL };
+static const char *spterm[] = { "t", TERM, "-n", "spterm", TERM_FLAG_EXEC, "tmux", NULL };
+static const char *spfile[] = { "f", TERM, "-n", "spfile", TERM_FLAG_EXEC, "lf-sixel", NULL };
+static const char *spproc[] = { "p", TERM, "-n", "spproc", TERM_FLAG_EXEC, "htop", NULL };
+static const char *spvolm[] = { "v", TERM, "-n", "spvolm", TERM_FLAG_EXEC, "pulsemixer", NULL };
+static const char *sphelp[] = { "h", TERM, "-n", "sphelp", TERM_FLAG_EXEC, "/bin/sh", "-c", "glow -p -s $XDG_CONFIG_HOME/glow/style.json /usr/share/dwm/dwm.md", NULL };
+static const char *spinet[] = { "i", TERM, "-n", "spinet", TERM_FLAG_EXEC, "nmtui", NULL };
+static const char *spwiki[] = { "w", TERM, "-n", "spwiki", TERM_FLAG_EXEC, "zk", "edit", "-i", NULL };
+static const char *spcalc[] = { "c", TERM, "-n", "spcalc", TERM_FLAG_EXEC, "bc", "-li", NULL };
+
+static char *tagicons[][NUMTAGS] =
+{
+ [DEFAULT_TAGS] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" },
+};
static const Rule rules[] = {
/* xprop(1):
@@ -145,93 +176,110 @@ static const Rule rules[] = {
RULE(.wintype = WTYPE "UTILITY", .isfloating = 1)
RULE(.wintype = WTYPE "TOOLBAR", .isfloating = 1)
RULE(.wintype = WTYPE "SPLASH", .isfloating = 1)
- RULE(.role = "pop-up", .isfloating = 1)
- RULE(.class = "Dragon-drop", .isfloating = 1, .iscentered = 1)
- RULE(.class = "St", .isfloating = 0)
- RULE(.class = "mpv", .isfloating = 0)
- RULE(.class = "Element", .monitor = 1, .tags = 1 << 0)
- RULE(.class = "Thunderbird", .monitor = 1, .tags = 1 << 1)
- RULE(.class = "sphelp", .scratchkey = 'h', .isfloating = 1, .iscentered = 1, .floatpos = "50% 50% 50% 90%")
- RULE(.class = "spwiki", .scratchkey = 'w', .isfloating = 1, .iscentered = 1, .floatpos = "50% 50% 50% 90%")
- RULE(.class = "sptask", .scratchkey = 's', .isfloating = 1, .iscentered = 1, .floatpos = "50% 50% 50% 90%")
- RULE(.class = "spterm", .scratchkey = 't', .isfloating = 1, .iscentered = 1, .floatpos = "50% 50% 90% 90%")
- RULE(.class = "spfile", .scratchkey = 'f', .isfloating = 1, .iscentered = 1, .floatpos = "50% 50% 90% 90%")
- RULE(.class = "spchat", .scratchkey = 'a', .isfloating = 1, .iscentered = 1, .floatpos = "50% 50% 90% 90%")
- RULE(.class = "spdisk", .scratchkey = 'd', .isfloating = 1, .iscentered = 1, .floatpos = "50% 50% 90% 90%")
- RULE(.class = "spproc", .scratchkey = 'p', .isfloating = 1, .iscentered = 1, .floatpos = "50% 50% 90% 90%")
- RULE(.class = "spnetu", .scratchkey = 'u', .isfloating = 1, .iscentered = 1, .floatpos = "50% 50% 90% 90%")
- RULE(.class = "spcalc", .scratchkey = 'c', .isfloating = 1, .floatpos = "100% 100% 600W 900H")
- RULE(.class = "spvolm", .scratchkey = 'v', .isfloating = 1, .floatpos = "100% 100% 900W 500H")
- RULE(.class = "spnetm", .scratchkey = 'm', .isfloating = 1, .floatpos = "100% 100% 900W 900H")
- RULE(.class = "spblue", .scratchkey = 'b', .isfloating = 1, .floatpos = "100% 100% 900W 900H")
+ RULE(.title = "Event Tester", .noswallow = 1)
+ RULE(.class = "St", .isterminal = 1)
+ RULE(.instance = "sphelp", .scratchkey = 'h', .isfloating = 1, .floatpos = "50% 50% 40% 80%")
+ RULE(.instance = "spcalc", .scratchkey = 'c', .isfloating = 1, .floatpos = "50% 50% 40% 80%")
+ RULE(.instance = "spterm", .scratchkey = 't', .isfloating = 1, .floatpos = "50% 50% 80% 80%")
+ RULE(.instance = "spfile", .scratchkey = 'f', .isfloating = 1, .floatpos = "50% 50% 80% 80%")
+ RULE(.instance = "spproc", .scratchkey = 'p', .isfloating = 1, .floatpos = "50% 50% 80% 80%")
+ RULE(.instance = "spwiki", .scratchkey = 'w', .isfloating = 1, .floatpos = "50% 50% 80% 80%")
+ RULE(.instance = "spvolm", .scratchkey = 'v', .isfloating = 1, .floatpos = "100% 100% 900W 600H")
+ RULE(.instance = "spinet", .scratchkey = 'i', .isfloating = 1, .floatpos = "100% 100% 800W 800H")
};
+/* Bar rules allow you to configure what is shown where on the bar, as well as
+ * introducing your own bar modules.
+ *
+ * monitor:
+ * -1 show on all monitors
+ * 0 show on monitor 0
+ * 'A' show on active monitor (i.e. focused / selected) (or just -1 for active?)
+ * bar - bar index, 0 is default, 1 is extrabar
+ * alignment - how the module is aligned compared to other modules
+ * widthfunc, drawfunc, clickfunc - providing bar module width, draw and click functions
+ * name - does nothing, intended for visual clue and for logging / debugging
+ */
static const BarRule barrules[] = {
- /* monitor bar alignment widthfunc drawfunc clickfunc hoverfunc name */
- { -1, 0, BAR_ALIGN_LEFT, width_tags, draw_tags, click_tags, hover_tags, "tags" },
- { -1, 0, BAR_ALIGN_LEFT, width_ltsymbol, draw_ltsymbol, click_ltsymbol, NULL, "layout" },
- { 'A', 0, BAR_ALIGN_RIGHT, width_status, draw_status, click_status, NULL, "status" },
- { -1, 0, BAR_ALIGN_NONE, width_wintitle, draw_wintitle, click_wintitle, NULL, "wintitle" },
+ /* monitor bar alignment widthfunc drawfunc clickfunc hoverfunc name */
+ { -1, 0, BAR_ALIGN_LEFT, width_tags, draw_tags, click_tags, hover_tags, "tags" },
+ { 'A', 0, BAR_ALIGN_RIGHT, width_systray, draw_systray, click_systray, NULL, "systray" },
+ { -1, 0, BAR_ALIGN_LEFT, width_ltsymbol, draw_ltsymbol, click_ltsymbol, NULL, "layout" },
+ { 'A', 0, BAR_ALIGN_RIGHT, width_status, draw_status, click_status, NULL, "status" },
+ { -1, 0, BAR_ALIGN_NONE, width_wintitle, draw_wintitle, click_wintitle, NULL, "wintitle" },
};
/* layout(s) */
static const float mfact = 0.50; /* factor of master area size [0.05..0.95] */
static const int nmaster = 1; /* number of clients in master area */
+static const int nstack = 0; /* number of clients in primary stack area */
static const int resizehints = 0; /* 1 means respect size hints in tiled resizals */
static const int lockfullscreen = 1; /* 1 will force focus on the fullscreen window */
+static const int decorhints = 1; /* 1 means respect decoration hints */
+
+
static const Layout layouts[] = {
- /* symbol arrange function */
- { "[]=", tile }, /* first entry is default */
- { "TTT", bstack },
- { ":::", gaplessgrid },
- { "><>", NULL }, /* no layout function means floating behavior */
+ /* symbol arrange function, { nmaster, nstack, layout, master axis, stack axis, secondary stack axis, symbol func } */
+ { "[]=", flextile, { -1, -1, SPLIT_VERTICAL, TOP_TO_BOTTOM, TOP_TO_BOTTOM, 0, NULL } }, // default tile layout
+ { "><>", NULL, {0} }, /* no layout function means floating behavior */
+ { "[M]", flextile, { -1, -1, NO_SPLIT, MONOCLE, MONOCLE, 0, NULL } }, // monocle
+ { "|||", flextile, { -1, -1, SPLIT_VERTICAL, LEFT_TO_RIGHT, TOP_TO_BOTTOM, 0, NULL } }, // columns (col) layout
+ { ">M>", flextile, { -1, -1, FLOATING_MASTER, LEFT_TO_RIGHT, LEFT_TO_RIGHT, 0, NULL } }, // floating master
+ { "[D]", flextile, { -1, -1, SPLIT_VERTICAL, TOP_TO_BOTTOM, MONOCLE, 0, NULL } }, // deck
+ { "TTT", flextile, { -1, -1, SPLIT_HORIZONTAL, LEFT_TO_RIGHT, LEFT_TO_RIGHT, 0, NULL } }, // bstack
+ { "===", flextile, { -1, -1, SPLIT_HORIZONTAL, LEFT_TO_RIGHT, TOP_TO_BOTTOM, 0, NULL } }, // bstackhoriz
+ { "|M|", flextile, { -1, -1, SPLIT_CENTERED_VERTICAL, LEFT_TO_RIGHT, TOP_TO_BOTTOM, TOP_TO_BOTTOM, NULL } }, // centeredmaster
+ { "-M-", flextile, { -1, -1, SPLIT_CENTERED_HORIZONTAL, TOP_TO_BOTTOM, LEFT_TO_RIGHT, LEFT_TO_RIGHT, NULL } }, // centeredmaster horiz
+ { ":::", flextile, { -1, -1, NO_SPLIT, GAPPLESSGRID, GAPPLESSGRID, 0, NULL } }, // gappless grid
+ { "[\\]", flextile, { -1, -1, NO_SPLIT, DWINDLE, DWINDLE, 0, NULL } }, // fibonacci dwindle
+ { "(@)", flextile, { -1, -1, NO_SPLIT, SPIRAL, SPIRAL, 0, NULL } }, // fibonacci spiral
+ { "[T]", flextile, { -1, -1, SPLIT_VERTICAL, LEFT_TO_RIGHT, TATAMI, 0, NULL } }, // tatami mats
+ { "[M]", monocle, {0} },
};
/* 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} }
+ { 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} }
-/* 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 *termcmd[] = { TERM, NULL };
+static const char *termcmd[] = { TERM, TERM_FLAG_EXEC, TERM_START, NULL };
#include <X11/XF86keysym.h>
static const Key keys[] = {
- /* START KEYBINDS */
- { MODKEY, XK_F1, togglescratch, {.v = sphelp} }, // Toggle help
+ /* modifier key function argument */
+ { MODKEY, XK_F1, togglescratch, {.v = sphelp} },
// { MODKEY | ShiftMask, XK_F1, spawn, {.v = (const char *[]){NULL}} },
- // { MODKEY, XK_F2, spawn, SHCMD("$HOME/.local/libexec/dwm/dmenuhandler") },
+ { MODKEY, XK_F2, spawn, SHCMD("$HOME/.local/libexec/dwm/dmenuhandler") },
// { MODKEY | ShiftMask, XK_F2, spawn, {.v = (const char *[]){NULL}} },
- { MODKEY, XK_F3, spawn, SHCMD("$HOME/.local/libexec/dwm/togtouchpad") }, // Toggle touchpad
+ { MODKEY, XK_F3, spawn, SHCMD("$HOME/.local/libexec/dwm/togtouchpad") },
// { MODKEY | ShiftMask, XK_F3, spawn, {.v = (const char *[]){NULL}} },
- { MODKEY, XK_F4, spawn, SHCMD("$HOME/.local/libexec/dwm/togcompositor") }, // Toggle compositor
+ { MODKEY, XK_F4, spawn, SHCMD("$HOME/.local/libexec/dwm/togcompositor") },
// { MODKEY | ShiftMask, XK_F4, spawn, {.v = (const char *[]){NULL}} },
- { MODKEY, XK_F5, spawn, {.v = (const char *[]){"clipmenu", NULL}} }, // Open copy/paste history
- // { MODKEY | ShiftMask, XK_F5, spawn, {.v = (const char *[]){NULL}} },
+ { MODKEY, XK_F5, xrdb, {.v = NULL } },
// { MODKEY, XK_F6, spawn, {.v = (const char *[]){NULL}} },
// { MODKEY | ShiftMask, XK_F6, spawn, {.v = (const char *[]){NULL}} },
// { MODKEY, XK_F7, spawn, {.v = (const char *[]){NULL}} },
// { MODKEY | ShiftMask, XK_F7, spawn, {.v = (const char *[]){NULL}} },
// { MODKEY, XK_F8, spawn, {.v = (const char *[]){NULL}} },
// { MODKEY | ShiftMask, XK_F8, spawn, {.v = (const char *[]){NULL}} },
- // { MODKEY, XK_F9, spawn, SHCMD("$HOME/.local/libexec/dwm/dmenumount") },
+ { MODKEY, XK_F9, spawn, SHCMD("$HOME/.local/libexec/dwm/dmenumount") },
// { MODKEY | ShiftMask, XK_F9, spawn, {.v = (const char *[]){NULL}} },
- // { MODKEY, XK_F10, spawn, SHCMD("$HOME/.local/libexec/dwm/dmenuumount") },
+ { MODKEY, XK_F10, spawn, SHCMD("$HOME/.local/libexec/dwm/dmenuumount") },
// { MODKEY | ShiftMask, XK_F10, spawn, {.v = (const char *[]){NULL}} },
- // { MODKEY, XK_F11, spawn, SHCMD("$HOME/.local/libexec/dwm/displayselect") },
+ { MODKEY, XK_F11, spawn, SHCMD("$HOME/.local/libexec/dwm/displayselect") },
// { MODKEY | ShiftMask, XK_F11, spawn, {.v = (const char *[]){NULL}} },
- { MODKEY, XK_F12, spawn, {.v = (const char *[]){"remaps", NULL}} }, // Rotate keyboard layout
+ { MODKEY, XK_F12, spawn, SHCMD("$HOME/.local/libexec/dwm/remaps") },
// { MODKEY | ShiftMask, XK_F12, spawn, {.v = (const char *[]){NULL}} },
- { MODKEY, XK_grave, spawn, SHCMD("$HOME/.local/libexec/dwm/dmenuunicode --nocopy") }, // Insert an emoji
- { MODKEY | ShiftMask, XK_grave, spawn, SHCMD("$HOME/.local/libexec/dwm/dmenuunicode") }, // Copy an emoji
+ { MODKEY, XK_grave, spawn, SHCMD("$HOME/.local/libexec/dwm/dmenuunicode --nocopy") },
+ { MODKEY | ShiftMask, XK_grave, spawn, SHCMD("$HOME/.local/libexec/dwm/dmenuunicode") },
TAGKEYS( XK_1, 0),
TAGKEYS( XK_2, 1),
TAGKEYS( XK_3, 2),
@@ -241,165 +289,165 @@ static const Key keys[] = {
TAGKEYS( XK_7, 6),
TAGKEYS( XK_8, 7),
TAGKEYS( XK_9, 8),
- { MODKEY, XK_0, view, {.ui = ~0} }, // View all tags
- { MODKEY | ShiftMask, XK_0, tag, {.ui = ~0} }, // Make focused window sticky
- // { MODKEY | ShiftMask, XK_0, spawn, {.v = (const char *[]){NULL}} },
+ { MODKEY, XK_0, view, {.ui = ~0} },
+ { MODKEY | ShiftMask, XK_0, tag, {.ui = ~0} },
+ { MODKEY | Mod1Mask, XK_0, winview, {0} },
// { MODKEY, XK_bracketleft, spawn, {.v = (const char *[]){NULL}} },
// { MODKEY | ShiftMask, XK_bracketleft, spawn, {.v = (const char *[]){NULL}} },
// { MODKEY, XK_bracketright, spawn, {.v = (const char *[]){NULL}} },
// { MODKEY | ShiftMask, XK_bracketright, spawn, {.v = (const char *[]){NULL}} },
- { MODKEY, XK_BackSpace, spawn, SHCMD("$HOME/.local/libexec/dwm/dmenusys") }, // Open shutdown menu
+ { MODKEY, XK_BackSpace, spawn, SHCMD("$HOME/.local/libexec/dwm/dmenusys") },
// { MODKEY | ShiftMask, XK_BackSpace, spawn, {.v = (const char *[]){NULL}} },
- // { MODKEY, XK_Tab, spawn, {.v = (const char *[]){NULL}} },
- // { MODKEY | ShiftMask, XK_Tab, spawn, {.v = (const char *[]){NULL}} },
+ // { MODKEY, XK_Tab, spawn, {.v = (const char *[]){NULL}} },
+ // { MODKEY | ShiftMask, XK_Tab, spawn, {.v = (const char *[]){NULL}} },
// { MODKEY, XK_apostrophe, spawn, {.v = (const char *[]){NULL}} },
// { MODKEY | ShiftMask, XK_apostrophe, spawn, {.v = (const char *[]){NULL}} },
- { MODKEY, XK_comma, focusmon, {.i = +1} }, // Focus next monitor
- { MODKEY | ShiftMask, XK_comma, tagmon, {.i = +1} }, // Move focused window to next monitor
- { MODKEY, XK_period, focusmon, {.i = -1} }, // Focus last monitor
- { MODKEY | ShiftMask, XK_period, tagmon, {.i = -1} }, // Move focused window to last monitor
- { MODKEY, XK_p, spawn, {.v = (const char *[]){"playerctl", "play-pause", NULL}} }, // Pause current player
+ { MODKEY, XK_comma, focusmon, {.i = +1} },
+ { MODKEY | ShiftMask, XK_comma, tagmon, {.i = +1} },
+ { MODKEY, XK_period, focusmon, {.i = -1} },
+ { MODKEY | ShiftMask, XK_period, tagmon, {.i = -1} },
+ { MODKEY, XK_p, spawn, {.v = (const char *[]){"playerctl", "play-pause", NULL}} },
// { MODKEY | ShiftMask, XK_p, spawn, {.v = (const char *[]){NULL}} },
// { MODKEY, XK_y, spawn, {.v = (const char *[]){NULL}} },
// { MODKEY | ShiftMask, XK_y, spawn, {.v = (const char *[]){NULL}} },
- { MODKEY, XK_f, togglefullscreen, {0} }, // Toggle fullscreen for focused window
+ { MODKEY, XK_f, togglefullscreen, {0} },
// { MODKEY | ShiftMask, XK_f, spawn, {.v = (const char *[]){NULL}} },
- { MODKEY, XK_g, setlayout, {.v = &layouts[0]} }, // Select default tile layout
- // { MODKEY | ShiftMask, XK_g, spawn, {.v = (const char *[]){NULL}} },
- { MODKEY, XK_c, setlayout, {.v = &layouts[1]} }, // Select bottom stack layout
- // { MODKEY | ShiftMask, XK_c, spawn, {.v = (const char *[]){NULL}} },
- { MODKEY, XK_r, setlayout, {.v = &layouts[2]} }, // Select grid layout
- // { MODKEY | ShiftMask, XK_r, spawn, {.v = (const char *[]){NULL}} },
- { MODKEY, XK_l, pushstack, {.i = INC(+1)} }, // Move focused window down stack
- { MODKEY | ShiftMask, XK_l, setmfact, {.f = +0.05} }, // Increase size of master stack
+ { MODKEY, XK_g, cyclelayout, {.i = -1} },
+ { MODKEY | ShiftMask, XK_g, rotatelayoutaxis, {.i = -1} },
+ { MODKEY, XK_c, setlayout, {.v = &layouts[0]} },
+ // { MODKEY | ShiftMask, XK_c, spawn, {.v = (const char *[]){NULL}} }, /* TODO: reset axis */
+ { MODKEY, XK_r, cyclelayout, {.i = +1} },
+ { MODKEY | ShiftMask, XK_r, rotatelayoutaxis, {.i = +1} },
+ { MODKEY, XK_l, setmfact, {.f = +0.05} },
+ { MODKEY | ShiftMask, XK_l, setcfact, {.f = +0.1} },
// { MODKEY, XK_slash, spawn, {.v = (const char *[]){NULL}} },
// { MODKEY | ShiftMask, XK_slash, spawn, {.v = (const char *[]){NULL}} },
// { MODKEY, XK_equal, spawn, {.v = (const char *[]){NULL}} },
// { MODKEY | ShiftMask, XK_equal, spawn, {.v = (const char *[]){NULL}} },
- { MODKEY, XK_a, togglescratch, {.v = spchat} }, // Toggle AI chat
+ // { MODKEY, XK_a, spawn, {.v = (const char *[]){NULL}} },
// { MODKEY | ShiftMask, XK_a, spawn, {.v = (const char *[]){NULL}} },
- { MODKEY, XK_o, togglescratch, {.v = spproc} }, // Toggle process manager
- { MODKEY | ShiftMask, XK_o, togglescratch, {.v = spnetu} }, // Toggle network usage analyzer
- { MODKEY, XK_e, togglescratch, {.v = spfile} }, // Toggle file manager
- { MODKEY | ShiftMask, XK_e, togglescratch, {.v = spdisk} }, // Toggle disk usage analyzer
- { MODKEY, XK_u, spawn, {.v = (const char *[]){"dmenu_run", NULL}} }, // Run a program
+ { MODKEY, XK_o, togglescratch, {.v = spproc} },
+ // { MODKEY | ShiftMask, XK_o, spawn, {.v = (const char *[]){NULL}} },
+ { MODKEY, XK_e, togglescratch, {.v = spfile} },
+ // { MODKEY | ShiftMask, XK_e, spawn, {.v = (const char *[]){NULL}} },
+ { MODKEY, XK_u, spawn, {.v = (const char *[]){"dmenu_run", NULL}} },
// { MODKEY | ShiftMask, XK_u, spawn, {.v = (const char *[]){NULL}} },
- { MODKEY, XK_i, spawn, {.v = (const char *[]){"dunstctl", "close", NULL}} }, // Close last notification
- { MODKEY | ShiftMask, XK_i, spawn, {.v = (const char *[]){"dunstctl", "history-pop", NULL}} }, // Reopen last notification
- { MODKEY, XK_d, spawn, {.v = (const char *[]){"dunstctl", "context", NULL}} }, // Select notification option
- { MODKEY | ShiftMask, XK_d, spawn, {.v = (const char *[]){"dunstctl", "action", "0", NULL}} }, // Autoselect first notification option
- { MODKEY, XK_h, pushstack, {.i = INC(-1)} }, // Move focused window up stack
- { MODKEY | ShiftMask, XK_h, setmfact, {.f = -0.05} }, // Decrease size of master stack
- { MODKEY, XK_t, spawn, {.v = (const char *[]){BROWSER, BROWSER_FLAG_1, NULL}} }, // Start a browser window
- { MODKEY | ShiftMask, XK_t, spawn, {.v = (const char *[]){BROWSER, BROWSER_FLAG_1, BROWSER_FLAG_INCOG, NULL}} }, // Start an incognito browser window
- { MODKEY, XK_n, focusstack, {.i = PREVSEL} }, // Focus last focused window
- { MODKEY | ShiftMask, XK_n, focusstack, {.i = 0} }, // Focus master stack
- // { MODKEY, XK_s, spawn, {.v = (const char *[]){NULL}} },
- // { MODKEY | ShiftMask, XK_s, spawn, {.v = (const char *[]){NULL}} },
- // { MODKEY | ShiftMask, XK_s, spawn, {.v = (const char *[]){NULL}} },
- // { MODKEY, XK_minus, spawn, {.v = (const char *[]){NULL}} },
+ { MODKEY, XK_i, spawn, {.v = (const char *[]){"dunstctl", "close", NULL}} },
+ { MODKEY | ShiftMask, XK_i, spawn, {.v = (const char *[]){"dunstctl", "history-pop", NULL}} },
+ { MODKEY, XK_d, spawn, {.v = (const char *[]){"dunstctl", "context", NULL}} },
+ { MODKEY | ShiftMask, XK_d, spawn, {.v = (const char *[]){"dunstctl", "action", "0", NULL}} },
+ { MODKEY, XK_h, setmfact, {.f = -0.05} },
+ { MODKEY | ShiftMask, XK_h, setcfact, {.f = -0.1} },
+ { MODKEY, XK_t, spawn, {.v = (const char *[]){BROWSER, BROWSER_FLAG_1, NULL}} },
+ { MODKEY | ShiftMask, XK_t, spawn, {.v = (const char *[]){BROWSER, BROWSER_FLAG_1, BROWSER_FLAG_INCOG, NULL}} },
+ { MODKEY, XK_n, focusstack, {.i = PREVSEL} },
+ { MODKEY | ShiftMask, XK_n, pushstack, {.i = PREVSEL} },
+ { MODKEY, XK_s, incnmaster, {.i = +1 } },
+ { MODKEY | ShiftMask, XK_s, incnmaster, {.i = -1 } },
+ // { MODKEY, XK_minus, spawn, {.v = (const char *[]){NULL}} }, /* TODO: reset nmaster */
// { MODKEY | ShiftMask, XK_minus, spawn, {.v = (const char *[]){NULL}} },
// { MODKEY, XK_backslash, spawn, {.v = (const char *[]){NULL}} },
// { MODKEY | ShiftMask, XK_backslash, spawn, {.v = (const char *[]){NULL}} },
- { MODKEY, XK_Return, zoom, {0} }, // Move focused window to master stack
- // { MODKEY | ShiftMask, XK_Return, spawn, {.v = (const char *[]){NULL}} },
+ { MODKEY, XK_Return, zoom, {0} },
+ { MODKEY | ShiftMask, XK_Return, mirrorlayout, {0} },
// { MODKEY, XK_semicolon, spawn, {.v = (const char *[]){NULL}} },
// { MODKEY | ShiftMask, XK_semicolon, spawn, {.v = (const char *[]){NULL}} },
- { MODKEY, XK_q, killclient, {0} }, // Close focused window
+ { MODKEY, XK_q, killclient, {0} },
// { MODKEY | ShiftMask, XK_q, spawn, {.v = (const char *[]){NULL}} },
- { MODKEY, XK_j, focusstack, {.i = INC(+1) } }, // Focus next window in stack
- /* { MODKEY | ShiftMask, XK_j, focusstack, {.i = INC(+1) } }, */
- { MODKEY, XK_k, focusstack, {.i = INC(-1) } }, // Focus last window in stack
- /* { MODKEY | ShiftMask, XK_k, focusstack, {.i = INC(-1) } }, */
- { MODKEY, XK_x, togglefloating, {0} }, // Toggle floating for focused window
- { MODKEY | ShiftMask, XK_x, unfloatvisible, {0} }, // Unfloat visible floating windows
- { MODKEY, XK_b, togglescratch, {.v = spnetm} }, // Toggle network manager
- { MODKEY | ShiftMask, XK_b, togglescratch, {.v = spblue} }, // Toggle bluetooth manager
- { MODKEY, XK_m, togglescratch, {.v = spvolm} }, // Toggle volume manager
- { MODKEY | ShiftMask, XK_m, spawn, SHCMD("$HOME/.local/libexec/dwm/pamixer-notify -t") }, // Mute volume
- { MODKEY, XK_w, togglescratch, {.v = spwiki1} }, // Toggle wiki
- { MODKEY | ShiftMask, XK_w, togglescratch, {.v = spwiki2} }, // Toggle full wiki search
- { MODKEY, XK_v, togglescratch, {.v = spcalc} }, // Toggle calculator
+ { MODKEY, XK_j, focusstack, {.i = INC(+1)} },
+ { MODKEY | ShiftMask, XK_j, pushstack, {.i = INC(+1)} },
+ { MODKEY, XK_k, focusstack, {.i = INC(-1)} },
+ { MODKEY | ShiftMask, XK_k, pushstack, {.i = INC(-1)} },
+ { MODKEY, XK_x, togglescratch, {.v = spcalc }},
+ // { MODKEY | ShiftMask, XK_x, spawn, {.v = (const char *[]){NULL}} },
+ { MODKEY, XK_b, togglescratch, {.v = spinet} },
+ // { MODKEY | ShiftMask, XK_b, spawn, {.v = (const char *[]){NULL}} },
+ { MODKEY, XK_m, togglescratch, {.v = spvolm} },
+ // { MODKEY | ShiftMask, XK_m, spawn, {.v = (const char *[]){NULL}} },
+ { MODKEY, XK_w, togglescratch, {.v = spwiki} },
+ // { MODKEY | ShiftMask, XK_w, spawn, {.v = (const char *[]){NULL}} },
+ // { MODKEY, XK_v, spawn, {.v = (const char *[]){NULL}} },
// { MODKEY | ShiftMask, XK_v, spawn, {.v = (const char *[]){NULL}} },
- { MODKEY, XK_z, togglescratch, {.v = sptask} }, // Toggle task manager
+ // { MODKEY, XK_z, spawn, {.v = (const char *[]){NULL}} },
// { MODKEY | ShiftMask, XK_z, spawn, {.v = (const char *[]){NULL}} },
- { MODKEY, XK_space, spawn, {.v = termcmd} }, // Open terminal
- { MODKEY | ShiftMask, XK_space, togglescratch, {.v = spterm} }, // Open scratch terminal
- { MODKEY, XK_Print, spawn, SHCMD("$HOME/.local/libexec/dwm/dmenurecord") }, // Open video recording menu
- { MODKEY | ShiftMask, XK_Print, spawn, SHCMD("$HOME/.local/libexec/dwm/dmenurecord kill") }, // Kill recording
- { 0, XK_Print, spawn, SHCMD("$HOME/.local/libexec/dwm/dmenumaim full") }, // Screenshot full screen
- { ShiftMask, XK_Print, spawn, SHCMD("$HOME/.local/libexec/dwm/dmenumaim") }, // Open screenshot menu
- // { 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, {.v = (const char *[]){NULL}} },
- // { 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_Page_Up, spawn, {.v = (const char *[]){NULL}} },
- // { MODKEY | ShiftMask, XK_Page_Up, spawn, {.v = (const char *[]){NULL}} },
- // { MODKEY, XK_Delete, spawn, {.v = (const char *[]){NULL}} },
- { MODKEY | ShiftMask, XK_Delete, quit, {0} }, // Kill window manager
+ { MODKEY, XK_space, spawn, {.v = termcmd} },
+ { MODKEY | ShiftMask, XK_space, togglescratch, {.v = spterm} },
+ { MODKEY, XK_Print, spawn, SHCMD("$HOME/.local/libexec/dwm/dmenurecord") },
+ { MODKEY | ShiftMask, XK_Print, spawn, SHCMD("$HOME/.local/libexec/dwm/dmenurecord kill") },
+ { 0, XK_Print, spawn, SHCMD("$HOME/.local/libexec/dwm/dmenumaim full") },
+ { ShiftMask, XK_Print, spawn, SHCMD("$HOME/.local/libexec/dwm/dmenumaim") },
+ // { 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, {.v = (const char *[]){NULL}} },
+ // { 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_page_up, spawn, {.v = (const char *[]){NULL}} },
+ // { MODKEY | ShiftMask, XK_page_up, spawn, {.v = (const char *[]){NULL}} },
+ // { MODKEY, XK_delete, spawn, {.v = (const char *[]){NULL}} },
+ // { MODKEY | ShiftMask, XK_delete, spawn, {.v = (const char *[]){NULL}} },
// { MODKEY, XK_End, spawn, {.v = (const char *[]){NULL}} },
- // { MODKEY | ShiftMask, XK_End, 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, spawn, {.v = (const char *[]){"playerctl", "position", "5-", NULL}} }, // Spool current player back 5 seconds
- { MODKEY | ShiftMask, XK_Left, spawn, {.v = (const char *[]){"playerctl", "previous", NULL}} }, // Skip to previous track in current player
- { MODKEY, XK_Right, spawn, {.v = (const char *[]){"playerctl", "position", "5+", NULL}} }, // Spool current player forward 5 seconds
- { MODKEY | ShiftMask, XK_Right, spawn, {.v = (const char *[]){"playerctl", "next", NULL}} }, // Skip to next track in current player
- { MODKEY, XK_Up, spawn, SHCMD("$HOME/.local/libexec/dwm/pamixer-notify --allow-boost -i 5") }, // Increase volume
- { MODKEY | ShiftMask, XK_Up, spawn, {.v = (const char *[]){"playerctl", "volume", "5+", NULL}} }, // Increase volume in player
- { MODKEY, XK_Down, spawn, SHCMD("$HOME/.local/libexec/dwm/pamixer-notify --allow-boost -d 5") }, // Decrease volume
- { MODKEY | ShiftMask, XK_Down, spawn, {.v = (const char *[]){"playerctl", "volume", "5-", NULL}} }, // Decrease volume in player
+ { MODKEY | ShiftMask, XK_End, quit, {0} },
+ // { MODKEY, XK_page_down, spawn, {.v = (const char *[]){NULL}} },
+ // { MODKEY | ShiftMask, XK_page_down, spawn, {.v = (const char *[]){NULL}} },
+ { MODKEY, XK_Left, spawn, {.v = (const char *[]){"playerctl", "position", "5-", NULL}} },
+ { MODKEY | ShiftMask, XK_Left, spawn, {.v = (const char *[]){"playerctl", "previous", NULL}} },
+ { MODKEY, XK_Right, spawn, {.v = (const char *[]){"playerctl", "position", "5+", NULL}} },
+ { MODKEY | ShiftMask, XK_Right, spawn, {.v = (const char *[]){"playerctl", "next", NULL}} },
+ { MODKEY, XK_Up, spawn, SHCMD("$HOME/.local/libexec/dwm/pamixer-notify --allow-boost -i 5") },
+ { MODKEY | ShiftMask, XK_Up, spawn, {.v = (const char *[]){"playerctl", "volume", "5+", NULL}} },
+ { MODKEY, XK_Down, spawn, SHCMD("$HOME/.local/libexec/dwm/pamixer-notify --allow-boost -d 5") },
+ { MODKEY | ShiftMask, XK_Down, spawn, {.v = (const char *[]){"playerctl", "volume", "5-", NULL}} },
- { 0, XF86XK_AudioMute, spawn, SHCMD("$HOME/.local/libexec/dwm/pamixer-notify -t") }, // Mute volume
- { 0, XF86XK_AudioRaiseVolume, spawn, SHCMD("$HOME/.local/libexec/dwm/pamixer-notify --allow-boost -i 5") }, // Increase volume
- { 0, XF86XK_AudioLowerVolume, spawn, SHCMD("$HOME/.local/libexec/dwm/pamixer-notify --allow-boost -d 5") }, // Decrease volume
- { 0, XF86XK_AudioPrev, spawn, {.v = (const char *[]){"playerctl", "previous", NULL}} }, // Skip to previous track in current player
- { 0, XF86XK_AudioNext, spawn, {.v = (const char *[]){"playerctl", "next", NULL}} }, // Skip to next track in current player
- { 0, XF86XK_AudioPause, spawn, {.v = (const char *[]){"playerctl", "pause", NULL}} }, // Pause current player
- { 0, XF86XK_AudioPlay, spawn, {.v = (const char *[]){"playerctl", "play-pause", NULL}} }, // Toggle pause/unpause in current player
- { 0, XF86XK_AudioStop, spawn, {.v = (const char *[]){"playerctl", "stop", NULL}} }, // Stop current player
- { 0, XF86XK_AudioRewind, spawn, {.v = (const char *[]){"playerctl", "position", "5-", NULL}} }, // Spool current player back 5 seconds
- { 0, XF86XK_AudioForward, spawn, {.v = (const char *[]){"playerctl", "position", "5+", NULL}} }, // Spool current player forward 5 seconds
+ { 0, XF86XK_AudioMute, spawn, SHCMD("$HOME/.local/libexec/dwm/pamixer-notify -t") },
+ { 0, XF86XK_AudioRaiseVolume, spawn, SHCMD("$HOME/.local/libexec/dwm/pamixer-notify --allow-boost -i 5") },
+ { 0, XF86XK_AudioLowerVolume, spawn, SHCMD("$HOME/.local/libexec/dwm/pamixer-notify --allow-boost -d 5") },
+ { 0, XF86XK_AudioPrev, spawn, {.v = (const char *[]){"playerctl", "previous", NULL}} },
+ { 0, XF86XK_AudioNext, spawn, {.v = (const char *[]){"playerctl", "next", NULL}} },
+ { 0, XF86XK_AudioPause, spawn, {.v = (const char *[]){"playerctl", "pause", NULL}} },
+ { 0, XF86XK_AudioPlay, spawn, {.v = (const char *[]){"playerctl", "play-pause", NULL}} }, // Most keyboards only have a play button
+ { 0, XF86XK_AudioStop, spawn, {.v = (const char *[]){"playerctl", "stop", NULL}} },
+ { 0, XF86XK_AudioRewind, spawn, {.v = (const char *[]){"playerctl", "position", "5-", NULL}} },
+ { 0, XF86XK_AudioForward, spawn, {.v = (const char *[]){"playerctl", "position", "5+", NULL}} },
// { 0, XF86XK_AudioMedia, spawn, {.v = (const char *[]){NULL}} },
- { 0, XF86XK_AudioMicMute, spawn, SHCMD("$HOME/.local/libexec/dwm/togmic") }, // Toggle microphone mute
- { 0, XF86XK_PowerOff, spawn, {.v = (const char *[]){"dmenusys", NULL}} }, // Open shutdown menu
- { 0, XF86XK_Calculator, togglescratch, {.v = spcalc} }, // Toggle calculator
- { 0, XF86XK_Sleep, spawn, {.v = (const char *[]){"loginctl", "suspend", "-i", NULL}} }, // Sleep system
- { 0, XF86XK_WWW, spawn, {.v = (const char *[]){BROWSER, BROWSER_FLAG_1, NULL}} }, // Open browser
+ { 0, XF86XK_AudioMicMute, spawn, {.v = (const char *[]){"pactl", "set-source-mute", "@DEFAULT_SOURCE@", "toggle", NULL}} }, /* TODO: Test this */
+ { 0, XF86XK_PowerOff, spawn, {.v = (const char *[]){"dmenusys", NULL}} },
+ { 0, XF86XK_Calculator, spawn, {.v = (const char *[]){TERM, "-e", "bc", "-li", NULL}} },
+ { 0, XF86XK_Sleep, spawn, {.v = (const char *[]){"loginctl", "suspend", "-i", NULL}} },
+ { 0, XF86XK_WWW, spawn, {.v = (const char *[]){BROWSER, BROWSER_FLAG_1, NULL}} },
// { 0, XF86XK_WLAN, spawn, {.v = (const char *[]){NULL}} },
- { 0, XF86XK_DOS, spawn, {.v = (const char *[]){TERM, NULL}} }, // Open terminal
- { 0, XF86XK_ScreenSaver, spawn, {.v = (const char *[]){"xset", "s", "activate", NULL}} }, // Lock session
- { 0, XF86XK_TaskPane, togglescratch, {.v = spproc} }, // Toggle process manager
+ { 0, XF86XK_DOS, spawn, {.v = (const char *[]){TERM, NULL}} },
+ { 0, XF86XK_ScreenSaver, spawn, {.v = (const char *[]){"xset", "s", "activate", NULL}} },
+ { 0, XF86XK_TaskPane, spawn, {.v = (const char *[]){TERM, "-e", "htop", NULL}} },
// { 0, XF86XK_Mail, spawn, {.v = (const char *[]){NULL}} },
- { 0, XF86XK_MyComputer, togglescratch, {.v = spfile} }, // Toggle file manager
+ { 0, XF86XK_MyComputer, spawn, {.v = (const char *[]){TERM, "-e", "lfX", "/", NULL}} },
// { 0, XF86XK_Battery, spawn, {.v = (const char *[]){NULL}} },
// { 0, XF86XK_Launch1, spawn, {.v = (const char *[]){NULL}} },
- { 0, XF86XK_TouchpadToggle, spawn, SHCMD("$HOME/.local/libexec/dwm/togtouchpad") }, // Toggle touchpad
- { 0, XF86XK_TouchpadOff, spawn, SHCMD("$HOME/.local/libexec/dwm/togtouchpad -n") }, // Disable touchpad
- { 0, XF86XK_TouchpadOn, spawn, SHCMD("$HOME/.local/libexec/dwm/togtouchpad -y") }, // Enable touchpad
- { 0, XF86XK_MonBrightnessUp, spawn, SHCMD("$HOME/.local/libexec/dwm/brightness-notify +5") }, // Increase monitor brightness
- { 0, XF86XK_MonBrightnessDown, spawn, SHCMD("$HOME/.local/libexec/dwm/brightness-notify -5") }, // Decrease monitor brightness
- /* END KEYBINDS */
+ { 0, XF86XK_TouchpadToggle, spawn, SHCMD("$HOME/.local/libexec/dwm/togtouchpad") },
+ { 0, XF86XK_TouchpadOff, spawn, SHCMD("$HOME/.local/libexec/dwm/togtouchpad -n") },
+ { 0, XF86XK_TouchpadOn, spawn, SHCMD("$HOME/.local/libexec/dwm/togtouchpad -y") },
+ { 0, XF86XK_MonBrightnessUp, spawn, SHCMD("$HOME/.local/libexec/dwm/brightness-notify +5") },
+ { 0, XF86XK_MonBrightnessDown, spawn, SHCMD("$HOME/.local/libexec/dwm/brightness-notify -5") },
+ /* WARN: If you have multiple backlight controllers this will fail */
};
-
/* button definitions */
/* click can be ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, or ClkRootWin */
static const Button buttons[] = {
- /* click event mask button function argument */
- /*{ ClkLtSymbol, 0, Button1, setlayout, {0} },*/
- /*{ ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]} },*/
- /*{ ClkWinTitle, 0, Button2, zoom, {0} },*/
+ /* click event mask button function argument */
+ { ClkLtSymbol, 0, Button1, layoutmenu, {0} },
+ // { ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]} },
+ // { ClkWinTitle, 0, Button2, zoom, {0} },
{ ClkStatusText, 0, Button2, spawn, {.v = termcmd } },
- { ClkClientWin, MODKEY, Button1, movemouse, {0} },
- { ClkClientWin, MODKEY, Button2, togglefloating, {0} },
- { ClkClientWin, MODKEY, Button3, resizemouse, {0} },
- { ClkTagBar, 0, Button1, view, {0} },
- { ClkTagBar, 0, Button3, toggleview, {0} },
- { ClkTagBar, MODKEY, Button1, tag, {0} },
- { ClkTagBar, MODKEY, Button3, toggletag, {0} },
+ { 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} },
};
+
+
diff --git a/config.mk b/config.mk
index c2ba037..a3dd682 100644
--- a/config.mk
+++ b/config.mk
@@ -7,8 +7,8 @@ VERSION = 6.4
PREFIX = /usr/local
MANPREFIX = ${PREFIX}/share/man
-X11INC = /usr/include/X11
-X11LIB = /usr/lib
+X11INC = /usr/X11R6/include
+X11LIB = /usr/X11R6/lib
# FreeBSD (uncomment)
#X11INC = /usr/local/include
@@ -29,7 +29,7 @@ FREETYPEINC = /usr/include/freetype2
#KVMLIB = -lkvm
# Uncomment this for the alpha patch and the winicon patch (BAR_ALPHA_PATCH, BAR_WINICON_PATCH)
-# XRENDER = -lXrender
+XRENDER = -lXrender
# Uncomment this for the mdpcontrol patch / MDPCONTROL_PATCH
#MPDCLIENT = -lmpdclient
@@ -46,7 +46,7 @@ PANGOLIB = `pkg-config --libs xft pango pangoxft`
#XEXTLIB = -lXext
# Uncomment this for the swallow patch / SWALLOW_PATCH
-# XCBLIBS = -lX11-xcb -lxcb -lxcb-res
+XCBLIBS = -lX11-xcb -lxcb -lxcb-res
# This is needed for the winicon and tagpreview patches / BAR_WINICON_PATCH / BAR_TAGPREVIEW_PATCH
#IMLIB2LIBS = -lImlib2
diff --git a/docs.awk b/docs.awk
deleted file mode 100755
index 03c61d4..0000000
--- a/docs.awk
+++ /dev/null
@@ -1,54 +0,0 @@
-#!/bin/awk -f
-
-BEGINFILE {
- printf "# DWM Keybinds\n"
- printf "|Keybind|Function|\n"
- printf "|-|-|\n"
-}
-
-/^#define MODKEY/ {
- modkey = $3
-}
-
-/START KEYBINDS/ {
- in_keybinds = 1
- next
-}
-
-/END KEYBINDS/ {
- in_keybinds = 0
- next
-}
-
-in_keybinds {
- if (/^[[:space:]]*$/ || /^[[:space:]]*\/(\/|\*)/ || /^[[:space:]]*TAGKEYS\(/) {
- next
- }
-
- if (match($0, /\{[[:space:]]*([^,]+)/, modifier_matches)) {
- modifier = modifier_matches[1]
- } else {
- modifier = "0"
- }
-
- gsub(/MODKEY/, modkey, modifier)
- gsub(/\|/, "+", modifier)
- gsub(/Mod1Mask/, "Alt", modifier)
- gsub(/Mod4Mask/, "Super", modifier)
- gsub(/ControlMask/, "Control", modifier)
- gsub(/ShiftMask/, "Shift", modifier)
-
- match($0, /[[:space:]]*XK_([^,]+)/, key_matches)
- key = key_matches[1]
- key = toupper(substr(key,1,1)) substr(key,2)
-
- match($0, /,[[:space:]]*\/\/[[:space:]]*(.+)$/, comment_matches)
- comment = comment_matches[1]
- comment = toupper(substr(comment,1,1)) substr(comment,2)
-
- printf "|"
- if (modifier != "0") {
- printf "%s + ", modifier
- }
- printf "%s|%s|\n", key, comment
-}
diff --git a/drw.c b/drw.c
deleted file mode 100644
index 4f67cb3..0000000
--- a/drw.c
+++ /dev/null
@@ -1,298 +0,0 @@
-/* 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"
-
-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_font_create instead.
- */
-static Fnt *
-xfont_create(Drw *drw, const char *fontname)
-{
- Fnt *font;
- PangoFontMap *fontmap;
- PangoContext *context;
- PangoFontDescription *desc;
- PangoFontMetrics *metrics;
-
- if (!fontname) {
- die("no font specified.");
- }
-
- font = ecalloc(1, sizeof(Fnt));
- font->dpy = drw->dpy;
-
- fontmap = pango_xft_get_font_map(drw->dpy, drw->screen);
- context = pango_font_map_create_context(fontmap);
- desc = pango_font_description_from_string(fontname);
- font->layout = pango_layout_new(context);
- pango_layout_set_font_description(font->layout, desc);
-
- metrics = pango_context_get_metrics(context, desc, pango_language_from_string ("en-us"));
- font->h = pango_font_metrics_get_height(metrics) / PANGO_SCALE;
-
- pango_font_metrics_unref(metrics);
- g_object_unref(context);
-
- return font;
-}
-
-static void
-xfont_free(Fnt *font)
-{
- if (!font)
- return;
- if (font->layout)
- g_object_unref(font->layout);
- free(font);
-}
-
-Fnt*
-drw_font_create(Drw* drw, const char font[])
-{
- Fnt *fnt = NULL;
-
- if (!drw || !font)
- return NULL;
-
- fnt = xfont_create(drw, font);
-
- return (drw->fonts = fnt);
-}
-
-void
-drw_fontset_free(Fnt *font)
-{
- if (font) {
- 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);
-
- dest->pixel |= 0xff << 24;
-}
-
-/* Wrapper to create color schemes. The caller has to call free(3) on the
- * returned color scheme when done using it. */
-Clr *
-drw_scm_create(
- Drw *drw,
- 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_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, Bool markup)
-{
- char buf[1024];
- int i, ty, th;
- unsigned int ew, eh;
- XftDraw *d = NULL;
- size_t len;
- int render = x || y || w || h;
-
- 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);
- if (w < lpad)
- return x + w;
- d = XftDrawCreate(drw->dpy, drw->drawable,
- DefaultVisual(drw->dpy, drw->screen),
- DefaultColormap(drw->dpy, drw->screen));
- x += lpad;
- w -= lpad;
- }
-
- len = strlen(text);
-
- if (len) {
- drw_font_getexts(drw->fonts, text, len, &ew, &eh, markup);
- th = eh;
- /* shorten text if necessary */
- for (len = MIN(len, sizeof(buf) - 1); len && ew > w; len--) {
- drw_font_getexts(drw->fonts, text, len, &ew, &eh, markup);
- if (eh > th)
- th = eh;
- }
-
- if (len) {
- memcpy(buf, text, len);
- buf[len] = '\0';
- if (len < strlen(text))
- for (i = len; i && i > len - 3; buf[--i] = '.')
- ; /* NOP */
-
- if (render) {
- ty = y + (h - th) / 2;
- if (markup)
- pango_layout_set_markup(drw->fonts->layout, buf, len);
- else
- pango_layout_set_text(drw->fonts->layout, buf, len);
- pango_xft_render_layout(d, &drw->scheme[invert ? ColBg : ColFg],
- drw->fonts->layout, x * PANGO_SCALE, ty * PANGO_SCALE);
- if (markup) /* clear markup attributes */
- pango_layout_set_attributes(drw->fonts->layout, NULL);
- }
- x += ew;
- w -= ew;
- }
- }
- 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, Bool markup)
-{
- if (!drw || !drw->fonts || !text)
- return 0;
- return drw_text(drw, 0, 0, 0, 0, 0, text, 0, markup);
-}
-
-void
-drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h, Bool markup)
-{
- if (!font || !text)
- return;
-
- PangoRectangle r;
- if (markup)
- pango_layout_set_markup(font->layout, text, len);
- else
- pango_layout_set_text(font->layout, text, len);
- pango_layout_get_extents(font->layout, 0, &r);
- if (markup) /* clear markup attributes */
- pango_layout_set_attributes(font->layout, NULL);
- if (w)
- *w = r.width / PANGO_SCALE;
- if (h)
- *h = r.height / PANGO_SCALE;
-}
-
-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);
-}
diff --git a/drw.h b/drw.h
deleted file mode 100644
index 701bed3..0000000
--- a/drw.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/* See LICENSE file for copyright and license details. */
-
-#include <pango/pango.h>
-#include <pango/pangoxft.h>
-
-typedef struct {
- Cursor cursor;
-} Cur;
-
-typedef struct Fnt {
- Display *dpy;
- unsigned int h;
- PangoLayout *layout;
-} Fnt;
-
-enum { ColFg, ColBg, ColBorder, ColFloat, ColCount }; /* 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_font_create(Drw* drw, const char font[]);
-void drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h, Bool markup);
-void drw_fontset_free(Fnt* set);
-unsigned int drw_fontset_getwidth(Drw *drw, const char *text, Bool markup);
-
-/* 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_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, Bool markup);
-
-/* Map functions */
-void drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h);
-
diff --git a/dwm-flexipatch b/dwm-flexipatch
new file mode 160000
index 0000000..5e85bc8
--- /dev/null
+++ b/dwm-flexipatch
@@ -0,0 +1 @@
+Subproject commit 5e85bc8b5c784b47cdd3015b53c5bb517500ba9c
diff --git a/dwm.c b/dwm.c
deleted file mode 100644
index 44b9ef0..0000000
--- a/dwm.c
+++ /dev/null
@@ -1,2706 +0,0 @@
-/* See LICENSE file for copyright and license details.
- *
- * dynamic window manager is designed like any other X client as well. It is
- * driven through handling X events. In contrast to other X clients, a window
- * manager selects for SubstructureRedirectMask on the root window, to receive
- * events about window (dis-)appearance. Only one X connection at a time is
- * allowed to select for this event mask.
- *
- * The event handlers of dwm are organized in an array which is accessed
- * whenever a new event has been fetched. This allows event dispatching
- * in O(1) time.
- *
- * Each child of the root window is called a client, except windows which have
- * set the override_redirect flag. Clients are organized in a linked client
- * list on each monitor, the focus history is remembered through a stack list
- * on each monitor. Each client contains a bit array to indicate the tags of a
- * client.
- *
- * Keys and tagging rules are organized as arrays and defined in config.h.
- *
- * To understand everything else, start reading main().
- */
-#include <errno.h>
-#include <locale.h>
-#include <signal.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <X11/cursorfont.h>
-#include <X11/keysym.h>
-#include <X11/Xatom.h>
-#include <X11/Xlib.h>
-#include <X11/Xproto.h>
-#include <X11/Xutil.h>
-#ifdef XINERAMA
-#include <X11/extensions/Xinerama.h>
-#endif /* XINERAMA */
-#include <X11/Xft/Xft.h>
-
-#include "drw.h"
-#include "util.h"
-
-#include <pango/pango.h>
-
-#include <poll.h>
-
-/* macros */
-#define Button6 6
-#define Button7 7
-#define Button8 8
-#define Button9 9
-#define NUMTAGS 9
-#define NUMVIEWHIST NUMTAGS
-#define BARRULES 20
-#define BUTTONMASK (ButtonPressMask|ButtonReleaseMask)
-#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 MOUSEMASK (BUTTONMASK|PointerMotionMask)
-#define WIDTH(X) ((X)->w + 2 * (X)->bw)
-#define HEIGHT(X) ((X)->h + 2 * (X)->bw)
-#define WTYPE "_NET_WM_WINDOW_TYPE_"
-#define TAGMASK ((1 << NUMTAGS) - 1)
-#define TEXTWM(X) (drw_fontset_getwidth(drw, (X), True) + lrpad)
-#define TEXTW(X) (drw_fontset_getwidth(drw, (X), False) + lrpad)
-#define HIDDEN(C) ((getstate(C->win) == IconicState))
-
-/* enums */
-enum {
- CurResizeBR,
- CurResizeBL,
- CurResizeTR,
- CurResizeTL,
- CurNormal,
- CurResize,
- CurMove,
- CurLast
-}; /* cursor */
-
-enum {
- SchemeNorm,
- SchemeSel,
- SchemeTitleNorm,
- SchemeTitleSel,
- SchemeTagsNorm,
- SchemeTagsSel,
- SchemeHidNorm,
- SchemeHidSel,
- SchemeUrg,
- SchemeScratchSel,
- SchemeScratchNorm,
-}; /* color schemes */
-
-enum {
- NetSupported, NetWMName, NetWMState, NetWMCheck,
- NetWMFullscreen, NetActiveWindow, NetWMWindowType,
- NetDesktopNames, NetDesktopViewport, NetNumberOfDesktops, NetCurrentDesktop,
- NetClientList,
- NetClientListStacking,
- NetLast
-}; /* EWMH atoms */
-
-enum {
- WMProtocols,
- WMDelete,
- WMState,
- WMTakeFocus,
- WMWindowRole,
- WMLast
-}; /* default atoms */
-
-enum {
- ClientFields,
- ClientTags,
- ClientLast
-}; /* dwm client atoms */
-
-enum {
- ClkTagBar,
- ClkLtSymbol,
- ClkStatusText,
- ClkWinTitle,
- ClkClientWin,
- ClkRootWin,
- ClkLast
-}; /* clicks */
-
-enum {
- BAR_ALIGN_LEFT,
- BAR_ALIGN_CENTER,
- BAR_ALIGN_RIGHT,
- BAR_ALIGN_LEFT_LEFT,
- BAR_ALIGN_LEFT_RIGHT,
- BAR_ALIGN_LEFT_CENTER,
- BAR_ALIGN_NONE,
- BAR_ALIGN_RIGHT_LEFT,
- BAR_ALIGN_RIGHT_RIGHT,
- BAR_ALIGN_RIGHT_CENTER,
- BAR_ALIGN_LAST
-}; /* bar alignment */
-
-typedef union {
- int i;
- unsigned int ui;
- float f;
- const void *v;
-} Arg;
-
-typedef struct Monitor Monitor;
-typedef struct Bar Bar;
-struct Bar {
- Window win;
- Monitor *mon;
- Bar *next;
- int idx;
- int showbar;
- int topbar;
- int external;
- int borderpx;
- int borderscheme;
- int bx, by, bw, bh; /* bar geometry */
- int w[BARRULES]; // width, array length == barrules, then use r index for lookup purposes
- int x[BARRULES]; // x position, array length == ^
-};
-
-typedef struct {
- int x;
- int y;
- int h;
- int w;
-} BarArg;
-
-typedef struct {
- int monitor;
- int bar;
- int alignment; // see bar alignment enum
- int (*widthfunc)(Bar *bar, BarArg *a);
- int (*drawfunc)(Bar *bar, BarArg *a);
- int (*clickfunc)(Bar *bar, Arg *arg, BarArg *a);
- int (*hoverfunc)(Bar *bar, BarArg *a, XMotionEvent *ev);
- char *name; // for debugging
- int x, w; // position, width for internal use
-} BarRule;
-
-typedef struct {
- unsigned int click;
- unsigned int mask;
- unsigned int button;
- void (*func)(const Arg *arg);
- const Arg arg;
-} Button;
-
-typedef struct Client Client;
-struct Client {
- char name[256];
- float mina, maxa;
- int x, y, w, h;
- int sfx, sfy, sfw, sfh; /* stored float geometry, used on mode revert */
- unsigned int idx;
- int oldx, oldy, oldw, oldh;
- int basew, baseh, incw, inch, maxw, maxh, minw, minh, hintsvalid;
- int bw, oldbw;
- unsigned int tags;
- int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen;
- int iscentered;
- Client *next;
- Client *snext;
- Monitor *mon;
- Window win;
- char scratchkey;
-};
-
-typedef struct {
- unsigned int mod;
- KeySym keysym;
- void (*func)(const Arg *);
- const Arg arg;
-} Key;
-
-typedef struct {
- const char *symbol;
- void (*arrange)(Monitor *);
-} Layout;
-
-typedef struct Pertag Pertag;
-struct Monitor {
- char ltsymbol[16];
- float mfact;
- int nmaster;
- int num;
- int mx, my, mw, mh; /* screen size */
- int wx, wy, ww, wh; /* window area */
- unsigned int seltags;
- unsigned int sellt;
- unsigned int tagset[2];
- int showbar;
- Client *clients;
- Client *sel;
- Client *stack;
- Monitor *next;
- Bar *bar;
- const Layout *lt[2];
- Pertag *pertag;
-};
-
-typedef struct {
- const char *class;
- const char *role;
- const char *instance;
- const char *title;
- const char *wintype;
- unsigned int tags;
- int iscentered;
- int isfloating;
- const char *floatpos;
- int monitor;
- const char scratchkey;
-} Rule;
-
-#define RULE(...) { .monitor = -1, __VA_ARGS__ },
-
-/* Cross patch compatibility rule macro helper macros */
-#define FLOATING , .isfloating = 1
-#define CENTERED , .iscentered = 1
-#define PERMANENT
-#define FAKEFULLSCREEN
-#define NOSWALLOW
-#define TERMINAL
-#define SWITCHTAG
-
-/* function declarations */
-static void applyrules(Client *c);
-static int applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact);
-static void arrange(Monitor *m);
-static void arrangemon(Monitor *m);
-static void attach(Client *c);
-static void attachstack(Client *c);
-static void buttonpress(XEvent *e);
-static void checkotherwm(void);
-static void cleanup(void);
-static void cleanupmon(Monitor *mon);
-static void clientmessage(XEvent *e);
-static void configure(Client *c);
-static void configurenotify(XEvent *e);
-static void configurerequest(XEvent *e);
-static Monitor *createmon(void);
-static void destroynotify(XEvent *e);
-static void detach(Client *c);
-static void detachstack(Client *c);
-static Monitor *dirtomon(int dir);
-static void drawbar(Monitor *m);
-static void drawbars(void);
-static void drawbarwin(Bar *bar);
-static void expose(XEvent *e);
-static void focus(Client *c);
-static void focusin(XEvent *e);
-static void focusmon(const Arg *arg);
-static Atom getatomprop(Client *c, Atom prop, Atom req);
-static int getrootptr(int *x, int *y);
-static long getstate(Window w);
-static int gettextprop(Window w, Atom atom, char *text, unsigned int size);
-static void grabbuttons(Client *c, int focused);
-static void grabkeys(void);
-static void incnmaster(const Arg *arg);
-static void keypress(XEvent *e);
-static void killclient(const Arg *arg);
-static void manage(Window w, XWindowAttributes *wa);
-static void mappingnotify(XEvent *e);
-static void maprequest(XEvent *e);
-static void motionnotify(XEvent *e);
-static void movemouse(const Arg *arg);
-static Client *nexttiled(Client *c);
-static void pop(Client *c);
-static void propertynotify(XEvent *e);
-static void quit(const Arg *arg);
-static Monitor *recttomon(int x, int y, int w, int h);
-static void resize(Client *c, int x, int y, int w, int h, int interact);
-static void resizeclient(Client *c, int x, int y, int w, int h);
-static void resizemouse(const Arg *arg);
-static void restack(Monitor *m);
-static void run(void);
-static void scan(void);
-static int sendevent(Client *c, Atom proto);
-static void sendmon(Client *c, Monitor *m);
-static void setclientstate(Client *c, long state);
-static void setfocus(Client *c);
-static void setfullscreen(Client *c, int fullscreen);
-static void setlayout(const Arg *arg);
-static void setmfact(const Arg *arg);
-static void setup(void);
-static void seturgent(Client *c, int urg);
-static void sigchld(int unused);
-static void showhide(Client *c);
-static void spawn(const Arg *arg);
-static void tag(const Arg *arg);
-static void tagmon(const Arg *arg);
-static void togglebar(const Arg *arg);
-static void togglefloating(const Arg *arg);
-static void toggletag(const Arg *arg);
-static void toggleview(const Arg *arg);
-static void unfocus(Client *c, int setfocus, Client *nextfocus);
-static void unmanage(Client *c, int destroyed);
-static void unmapnotify(XEvent *e);
-static void updatebarpos(Monitor *m);
-static void updatebars(void);
-static void updateclientlist(void);
-static int updategeom(void);
-static void updatenumlockmask(void);
-static void updatesizehints(Client *c);
-static void updatestatus(void);
-static void updatetitle(Client *c);
-static void updatewmhints(Client *c);
-static void view(const Arg *arg);
-static Client *wintoclient(Window w);
-static Monitor *wintomon(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);
-
-/* bar functions */
-
-#include "patch/include.h"
-
-/* variables */
-static const char broken[] = "broken";
-static char stext[8192];
-static char rawstext[8192];
-
-static int screen;
-static int sw, sh; /* X display screen geometry width, height */
-static int bh; /* bar geometry */
-static int lrpad; /* sum of left and right padding for text */
-/* Some clients (e.g. alacritty) helpfully send configure requests with a new size or position
- * when they detect that they have been moved to another monitor. This can cause visual glitches
- * when moving (or resizing) client windows from one monitor to another. This variable is used
- * internally to ignore such configure requests while movemouse or resizemouse are being used. */
-static int ignoreconfigurerequests = 0;
-static int (*xerrorxlib)(Display *, XErrorEvent *);
-static unsigned int numlockmask = 0;
-static void (*handler[LASTEvent]) (XEvent *) = {
- [ButtonPress] = buttonpress,
- [ClientMessage] = clientmessage,
- [ConfigureRequest] = configurerequest,
- [ConfigureNotify] = configurenotify,
- [DestroyNotify] = destroynotify,
- [Expose] = expose,
- [FocusIn] = focusin,
- [KeyPress] = keypress,
- [MappingNotify] = mappingnotify,
- [MapRequest] = maprequest,
- [MotionNotify] = motionnotify,
- [PropertyNotify] = propertynotify,
- [UnmapNotify] = unmapnotify
-};
-static Atom wmatom[WMLast], netatom[NetLast];
-static Atom clientatom[ClientLast];
-static volatile sig_atomic_t running = 1;
-static Cur *cursor[CurLast];
-static Clr **scheme;
-static Display *dpy;
-static Drw *drw;
-static Monitor *mons, *selmon;
-static Window root, wmcheckwin;
-
-/* configuration, allows nested code to access above variables */
-#include "config.h"
-
-#include "patch/include.c"
-
-/* compile-time check if all tags fit into an unsigned int bit array. */
-struct NumTags { char limitexceeded[NUMTAGS > 31 ? -1 : 1]; };
-
-/* function implementations */
-void
-applyrules(Client *c)
-{
- const char *class, *instance;
- Atom wintype;
- char role[64];
- unsigned int i;
- const Rule *r;
- Monitor *m;
- XClassHint ch = { NULL, NULL };
-
- /* 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;
- wintype = getatomprop(c, netatom[NetWMWindowType], XA_ATOM);
- gettextprop(c->win, wmatom[WMWindowRole], role, sizeof(role));
-
- for (i = 0; i < LENGTH(rules); i++) {
- r = &rules[i];
- if ((!r->title || strstr(c->name, r->title))
- && (!r->class || strstr(class, r->class))
- && (!r->role || strstr(role, r->role))
- && (!r->instance || strstr(instance, r->instance))
- && (!r->wintype || wintype == XInternAtom(dpy, r->wintype, False)))
- {
- c->iscentered = r->iscentered;
- 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;
- if (c->isfloating && r->floatpos) {
- c->iscentered = 0;
- setfloatpos(c, r->floatpos);
- }
-
- }
- }
- if (ch.res_class)
- 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];
-}
-
-int
-applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact)
-{
- int baseismin;
- Monitor *m = c->mon;
-
- /* set minimum possible */
- *w = MAX(1, *w);
- *h = MAX(1, *h);
- if (interact) {
- if (*x > sw)
- *x = sw - WIDTH(c);
- if (*y > sh)
- *y = sh - HEIGHT(c);
- if (*x + *w + 2 * c->bw < 0)
- *x = 0;
- if (*y + *h + 2 * c->bw < 0)
- *y = 0;
- } else {
- if (*x >= m->wx + m->ww)
- *x = m->wx + m->ww - WIDTH(c);
- if (*y >= m->wy + m->wh)
- *y = m->wy + m->wh - HEIGHT(c);
- if (*x + *w + 2 * c->bw <= m->wx)
- *x = m->wx;
- if (*y + *h + 2 * c->bw <= m->wy)
- *y = m->wy;
- }
- if (*h < bh)
- *h = bh;
- if (*w < bh)
- *w = bh;
- if (resizehints || c->isfloating || !c->mon->lt[c->mon->sellt]->arrange) {
- if (!c->hintsvalid)
- updatesizehints(c);
- /* see last two sentences in ICCCM 4.1.2.3 */
- baseismin = c->basew == c->minw && c->baseh == c->minh;
- if (!baseismin) { /* temporarily remove base dimensions */
- *w -= c->basew;
- *h -= c->baseh;
- }
- /* adjust for aspect limits */
- if (c->mina > 0 && c->maxa > 0) {
- if (c->maxa < (float)*w / *h)
- *w = *h * c->maxa + 0.5;
- else if (c->mina < (float)*h / *w)
- *h = *w * c->mina + 0.5;
- }
- if (baseismin) { /* increment calculation requires this */
- *w -= c->basew;
- *h -= c->baseh;
- }
- /* adjust for increment value */
- if (c->incw)
- *w -= *w % c->incw;
- if (c->inch)
- *h -= *h % c->inch;
- /* restore base dimensions */
- *w = MAX(*w + c->basew, c->minw);
- *h = MAX(*h + c->baseh, c->minh);
- if (c->maxw)
- *w = MIN(*w, c->maxw);
- if (c->maxh)
- *h = MIN(*h, c->maxh);
- }
- return *x != c->x || *y != c->y || *w != c->w || *h != c->h;
-}
-
-void
-arrange(Monitor *m)
-{
- if (m)
- showhide(m->stack);
- else for (m = mons; m; m = m->next)
- showhide(m->stack);
- if (m) {
- arrangemon(m);
- restack(m);
- } else for (m = mons; m; m = m->next)
- arrangemon(m);
-}
-
-void
-arrangemon(Monitor *m)
-{
- strncpy(m->ltsymbol, m->lt[m->sellt]->symbol, sizeof m->ltsymbol);
- if (m->lt[m->sellt]->arrange)
- m->lt[m->sellt]->arrange(m);
-}
-
-void
-attach(Client *c)
-{
- c->next = c->mon->clients;
- c->mon->clients = c;
-}
-
-void
-attachstack(Client *c)
-{
- c->snext = c->mon->stack;
- c->mon->stack = c;
-}
-
-void
-buttonpress(XEvent *e)
-{
- int click, i, r;
- Arg arg = {0};
- Client *c;
- Monitor *m;
- Bar *bar;
- XButtonPressedEvent *ev = &e->xbutton;
- const BarRule *br;
- BarArg carg = { 0, 0, 0, 0 };
- click = ClkRootWin;
-
- /* focus monitor if necessary */
- if ((m = wintomon(ev->window)) && m != selmon
- && (focusonwheel || (ev->button != Button4 && ev->button != Button5))
- ) {
- unfocus(selmon->sel, 1, NULL);
- selmon = m;
- focus(NULL);
- }
-
- for (bar = selmon->bar; bar; bar = bar->next) {
- if (ev->window == bar->win) {
- for (r = 0; r < LENGTH(barrules); r++) {
- br = &barrules[r];
- if (br->bar != bar->idx || (br->monitor == 'A' && m != selmon) || br->clickfunc == NULL)
- continue;
- if (br->monitor != 'A' && br->monitor != -1 && br->monitor != bar->mon->num)
- continue;
- if (bar->x[r] <= ev->x && ev->x <= bar->x[r] + bar->w[r]) {
- carg.x = ev->x - bar->x[r];
- carg.y = ev->y - bar->borderpx;
- carg.w = bar->w[r];
- carg.h = bar->bh - 2 * bar->borderpx;
- click = br->clickfunc(bar, &arg, &carg);
- if (click < 0)
- return;
- break;
- }
- }
- break;
- }
- }
-
- if (click == ClkRootWin && (c = wintoclient(ev->window))) {
- if (focusonwheel || (ev->button != Button4 && ev->button != Button5))
- focus(c);
- XAllowEvents(dpy, ReplayPointer, CurrentTime);
- click = ClkClientWin;
- }
-
- for (i = 0; i < LENGTH(buttons); i++) {
- if (click == buttons[i].click && buttons[i].func && buttons[i].button == ev->button
- && CLEANMASK(buttons[i].mask) == CLEANMASK(ev->state)) {
- buttons[i].func(
- (
- click == ClkTagBar
- ) && buttons[i].arg.i == 0 ? &arg : &buttons[i].arg
- );
- }
- }
-}
-
-void
-checkotherwm(void)
-{
- xerrorxlib = XSetErrorHandler(xerrorstart);
- /* this causes an error if some other window manager is running */
- XSelectInput(dpy, DefaultRootWindow(dpy), SubstructureRedirectMask);
- XSync(dpy, False);
- XSetErrorHandler(xerror);
- XSync(dpy, False);
-}
-
-void
-cleanup(void)
-{
- Monitor *m;
- Layout foo = { "", NULL };
- size_t i;
-
- for (m = mons; m; m = m->next)
- persistmonitorstate(m);
-
- /* kill child processes */
- for (i = 0; i < autostart_len; i++) {
- if (0 < autostart_pids[i]) {
- kill(autostart_pids[i], autostart_kill_signal);
- waitpid(autostart_pids[i], NULL, 0);
- }
- }
-
- selmon->lt[selmon->sellt] = &foo;
- for (m = mons; m; m = m->next)
- while (m->stack)
- unmanage(m->stack, 0);
- XUngrabKey(dpy, AnyKey, AnyModifier, root);
- while (mons)
- cleanupmon(mons);
- for (i = 0; i < CurLast; i++)
- drw_cur_free(drw, cursor[i]);
- for (i = 0; i < LENGTH(colors); i++)
- free(scheme[i]);
- free(scheme);
- XDestroyWindow(dpy, wmcheckwin);
- drw_free(drw);
- XSync(dpy, False);
- XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime);
- XDeleteProperty(dpy, root, netatom[NetActiveWindow]);
-
-}
-
-void
-cleanupmon(Monitor *mon)
-{
- Monitor *m;
- Bar *bar;
-
- if (mon == mons)
- mons = mons->next;
- else {
- for (m = mons; m && m->next != mon; m = m->next);
- m->next = mon->next;
- }
- for (bar = mon->bar; bar; bar = mon->bar) {
- if (!bar->external) {
- XUnmapWindow(dpy, bar->win);
- XDestroyWindow(dpy, bar->win);
- }
- mon->bar = bar->next;
- free(bar);
- }
- free(mon->pertag);
- free(mon);
-}
-
-void
-clientmessage(XEvent *e)
-{
- XClientMessageEvent *cme = &e->xclient;
- Client *c = wintoclient(cme->window);
-
- if (!c)
- return;
- if (cme->message_type == netatom[NetWMState]) {
- if (cme->data.l[1] == netatom[NetWMFullscreen]
- || cme->data.l[2] == netatom[NetWMFullscreen]) {
- setfullscreen(c, (cme->data.l[0] == 1 /* _NET_WM_STATE_ADD */
- || (cme->data.l[0] == 2 /* _NET_WM_STATE_TOGGLE */
- && !c->isfullscreen
- )));
- }
- } else if (cme->message_type == netatom[NetActiveWindow]) {
- if (c != selmon->sel && !c->isurgent)
- seturgent(c, 1);
- }
-}
-
-void
-configure(Client *c)
-{
- XConfigureEvent ce;
-
- ce.type = ConfigureNotify;
- ce.display = dpy;
- ce.event = c->win;
- ce.window = c->win;
- ce.x = c->x;
- ce.y = c->y;
- ce.width = c->w;
- ce.height = c->h;
- ce.border_width = c->bw;
-
- ce.above = None;
- ce.override_redirect = False;
- XSendEvent(dpy, c->win, False, StructureNotifyMask, (XEvent *)&ce);
-}
-
-void
-configurenotify(XEvent *e)
-{
- Monitor *m;
- Bar *bar;
- Client *c;
- XConfigureEvent *ev = &e->xconfigure;
- int dirty;
- /* TODO: updategeom handling sucks, needs to be simplified */
- if (ev->window == root) {
- dirty = (sw != ev->width || sh != ev->height);
- sw = ev->width;
- sh = ev->height;
- if (updategeom() || dirty) {
- drw_resize(drw, sw, sh);
- updatebars();
- for (m = mons; m; m = m->next) {
- for (c = m->clients; c; c = c->next)
- if (c->isfullscreen)
- resizeclient(c, m->mx, m->my, m->mw, m->mh);
- for (bar = m->bar; bar; bar = bar->next)
- XMoveResizeWindow(dpy, bar->win, bar->bx, bar->by, bar->bw, bar->bh);
- }
- arrange(NULL);
- focus(NULL);
- }
- }
-}
-
-void
-configurerequest(XEvent *e)
-{
- Client *c;
- Monitor *m;
- XConfigureRequestEvent *ev = &e->xconfigurerequest;
- XWindowChanges wc;
-
- if (ignoreconfigurerequests)
- return;
-
- if ((c = wintoclient(ev->window))) {
- if (ev->value_mask & CWBorderWidth)
- c->bw = ev->border_width;
- else if (c->isfloating || !selmon->lt[selmon->sellt]->arrange) {
- m = c->mon;
- if (ev->value_mask & CWX) {
- c->oldx = c->x;
- c->x = m->mx + ev->x;
- }
- if (ev->value_mask & CWY) {
- c->oldy = c->y;
- c->y = m->my + ev->y;
- }
- if (ev->value_mask & CWWidth) {
- c->oldw = c->w;
- c->w = ev->width;
- }
- if (ev->value_mask & CWHeight) {
- c->oldh = c->h;
- c->h = ev->height;
- }
- if ((c->x + c->w) > m->mx + m->mw && c->isfloating)
- c->x = m->mx + (m->mw / 2 - WIDTH(c) / 2); /* center in x direction */
- if ((c->y + c->h) > m->my + m->mh && c->isfloating)
- c->y = m->my + (m->mh / 2 - HEIGHT(c) / 2); /* center in y direction */
- if ((ev->value_mask & (CWX|CWY)) && !(ev->value_mask & (CWWidth|CWHeight)))
- configure(c);
- if (ISVISIBLE(c))
- XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h);
- } else
- configure(c);
- } else {
- wc.x = ev->x;
- wc.y = ev->y;
- wc.width = ev->width;
- wc.height = ev->height;
- wc.border_width = ev->border_width;
- wc.sibling = ev->above;
- wc.stack_mode = ev->detail;
- XConfigureWindow(dpy, ev->window, ev->value_mask, &wc);
- }
- XSync(dpy, False);
-}
-
-Monitor *
-createmon(void)
-{
- Monitor *m, *mon;
- int i, n, mi, max_bars = 2, istopbar = topbar;
-
- const BarRule *br;
- Bar *bar;
-
- m = ecalloc(1, sizeof(Monitor));
- m->tagset[0] = m->tagset[1] = 1;
- m->mfact = mfact;
- m->nmaster = nmaster;
- m->showbar = showbar;
- for (mi = 0, mon = mons; mon; mon = mon->next, mi++); // monitor index
- m->num = mi;
- m->lt[0] = &layouts[0];
- m->lt[1] = &layouts[1 % LENGTH(layouts)];
- strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol);
-
- /* Derive the number of bars for this monitor based on bar rules */
- for (n = -1, i = 0; i < LENGTH(barrules); i++) {
- br = &barrules[i];
- if (br->monitor == 'A' || br->monitor == -1 || br->monitor == m->num)
- n = MAX(br->bar, n);
- }
-
- m->bar = NULL;
- for (i = 0; i <= n && i < max_bars; i++) {
- bar = ecalloc(1, sizeof(Bar));
- bar->mon = m;
- bar->idx = i;
- bar->next = m->bar;
- bar->topbar = istopbar;
- m->bar = bar;
- istopbar = !istopbar;
- bar->showbar = 1;
- bar->external = 0;
- bar->borderpx = 0;
- bar->bh = bh + bar->borderpx * 2;
- bar->borderscheme = SchemeNorm;
- }
-
- if (!(m->pertag = (Pertag *)calloc(1, sizeof(Pertag))))
- die("fatal: could not malloc() %u bytes\n", sizeof(Pertag));
- m->pertag->curtag = 1;
- for (i = 0; i <= NUMTAGS; i++) {
-
- /* init nmaster */
- m->pertag->nmasters[i] = m->nmaster;
-
- /* init mfacts */
- m->pertag->mfacts[i] = m->mfact;
-
- /* init layouts */
- m->pertag->ltidxs[i][0] = m->lt[0];
- m->pertag->ltidxs[i][1] = m->lt[1];
- m->pertag->sellts[i] = m->sellt;
-
- }
-
- restoremonitorstate(m);
-
- return m;
-}
-
-void
-destroynotify(XEvent *e)
-{
- Client *c;
- XDestroyWindowEvent *ev = &e->xdestroywindow;
-
- if ((c = wintoclient(ev->window)))
- unmanage(c, 1);
-}
-
-void
-detach(Client *c)
-{
- Client **tc;
- c->idx = 0;
-
- for (tc = &c->mon->clients; *tc && *tc != c; tc = &(*tc)->next);
- *tc = c->next;
- c->next = NULL;
-}
-
-void
-detachstack(Client *c)
-{
- Client **tc, *t;
-
- for (tc = &c->mon->stack; *tc && *tc != c; tc = &(*tc)->snext);
- *tc = c->snext;
-
- if (c == c->mon->sel) {
- for (t = c->mon->stack; t && !ISVISIBLE(t); t = t->snext);
- c->mon->sel = t;
- }
- c->snext = NULL;
-}
-
-Monitor *
-dirtomon(int dir)
-{
- Monitor *m = NULL;
-
- if (dir > 0) {
- if (!(m = selmon->next))
- m = mons;
- } else if (selmon == mons)
- for (m = mons; m->next; m = m->next);
- else
- for (m = mons; m->next != selmon; m = m->next);
- return m;
-}
-
-void
-drawbar(Monitor *m)
-{
- Bar *bar;
-
- if (m->showbar)
- for (bar = m->bar; bar; bar = bar->next)
- drawbarwin(bar);
-}
-
-void
-drawbars(void)
-{
- Monitor *m;
- for (m = mons; m; m = m->next)
- drawbar(m);
-}
-
-void
-drawbarwin(Bar *bar)
-{
- if (!bar || !bar->win || bar->external)
- return;
- int r, w, total_drawn = 0;
- int rx, lx, rw, lw; // bar size, split between left and right if a center module is added
- const BarRule *br;
-
- if (bar->borderpx) {
- XSetForeground(drw->dpy, drw->gc, scheme[bar->borderscheme][ColBorder].pixel);
- XFillRectangle(drw->dpy, drw->drawable, drw->gc, 0, 0, bar->bw, bar->bh);
- }
-
- BarArg warg = { 0 };
- BarArg darg = { 0 };
- warg.h = bar->bh - 2 * bar->borderpx;
-
- rw = lw = bar->bw - 2 * bar->borderpx;
- rx = lx = bar->borderpx;
-
- drw_setscheme(drw, scheme[SchemeNorm]);
- drw_rect(drw, lx, bar->borderpx, lw, bar->bh - 2 * bar->borderpx, 1, 1);
- for (r = 0; r < LENGTH(barrules); r++) {
- br = &barrules[r];
- if (br->bar != bar->idx || !br->widthfunc || (br->monitor == 'A' && bar->mon != selmon))
- continue;
- if (br->monitor != 'A' && br->monitor != -1 && br->monitor != bar->mon->num)
- continue;
- drw_setscheme(drw, scheme[SchemeNorm]);
- warg.w = (br->alignment < BAR_ALIGN_RIGHT_LEFT ? lw : rw);
-
- w = br->widthfunc(bar, &warg);
- w = MIN(warg.w, w);
-
- if (lw <= 0) { // if left is exhausted then switch to right side, and vice versa
- lw = rw;
- lx = rx;
- } else if (rw <= 0) {
- rw = lw;
- rx = lx;
- }
-
- switch(br->alignment) {
- default:
- case BAR_ALIGN_NONE:
- case BAR_ALIGN_LEFT_LEFT:
- case BAR_ALIGN_LEFT:
- bar->x[r] = lx;
- if (lx == rx) {
- rx += w;
- rw -= w;
- }
- lx += w;
- lw -= w;
- break;
- case BAR_ALIGN_LEFT_RIGHT:
- case BAR_ALIGN_RIGHT:
- bar->x[r] = lx + lw - w;
- if (lx == rx)
- rw -= w;
- lw -= w;
- break;
- case BAR_ALIGN_LEFT_CENTER:
- case BAR_ALIGN_CENTER:
- bar->x[r] = lx + lw / 2 - w / 2;
- if (lx == rx) {
- rw = rx + rw - bar->x[r] - w;
- rx = bar->x[r] + w;
- }
- lw = bar->x[r] - lx;
- break;
- case BAR_ALIGN_RIGHT_LEFT:
- bar->x[r] = rx;
- if (lx == rx) {
- lx += w;
- lw -= w;
- }
- rx += w;
- rw -= w;
- break;
- case BAR_ALIGN_RIGHT_RIGHT:
- bar->x[r] = rx + rw - w;
- if (lx == rx)
- lw -= w;
- rw -= w;
- break;
- case BAR_ALIGN_RIGHT_CENTER:
- bar->x[r] = rx + rw / 2 - w / 2;
- if (lx == rx) {
- lw = lx + lw - bar->x[r] + w;
- lx = bar->x[r] + w;
- }
- rw = bar->x[r] - rx;
- break;
- }
- bar->w[r] = w;
- darg.x = bar->x[r];
- darg.y = bar->borderpx;
- darg.h = bar->bh - 2 * bar->borderpx;
- darg.w = bar->w[r];
- if (br->drawfunc)
- total_drawn += br->drawfunc(bar, &darg);
- }
-
- if (total_drawn == 0 && bar->showbar) {
- bar->showbar = 0;
- updatebarpos(bar->mon);
- XMoveResizeWindow(dpy, bar->win, bar->bx, bar->by, bar->bw, bar->bh);
- arrange(bar->mon);
- }
- else if (total_drawn > 0 && !bar->showbar) {
- bar->showbar = 1;
- updatebarpos(bar->mon);
- XMoveResizeWindow(dpy, bar->win, bar->bx, bar->by, bar->bw, bar->bh);
- drw_map(drw, bar->win, 0, 0, bar->bw, bar->bh);
- arrange(bar->mon);
- } else
- drw_map(drw, bar->win, 0, 0, bar->bw, bar->bh);
-}
-
-void
-expose(XEvent *e)
-{
- Monitor *m;
- XExposeEvent *ev = &e->xexpose;
-
- if (ev->count == 0 && (m = wintomon(ev->window))) {
- drawbar(m);
- }
-}
-
-void
-focus(Client *c)
-{
- if (!c || !ISVISIBLE(c))
- for (c = selmon->stack; c && !ISVISIBLE(c); c = c->snext);
- if (selmon->sel && selmon->sel != c)
- unfocus(selmon->sel, 0, c);
- if (c) {
- if (c->mon != selmon)
- selmon = c->mon;
- if (c->isurgent)
- seturgent(c, 0);
- detachstack(c);
- attachstack(c);
- grabbuttons(c, 1);
- if (c->scratchkey != 0 && c->isfloating)
- XSetWindowBorder(dpy, c->win, scheme[SchemeScratchSel][ColFloat].pixel);
- else if (c->scratchkey != 0)
- XSetWindowBorder(dpy, c->win, scheme[SchemeScratchSel][ColBorder].pixel);
- else if (c->isfloating)
- XSetWindowBorder(dpy, c->win, scheme[SchemeSel][ColFloat].pixel);
- else
- XSetWindowBorder(dpy, c->win, scheme[SchemeSel][ColBorder].pixel);
- setfocus(c);
- } else {
- XSetInputFocus(dpy, selmon->bar && selmon->bar->win ? selmon->bar->win : root, RevertToPointerRoot, CurrentTime);
- XDeleteProperty(dpy, root, netatom[NetActiveWindow]);
- }
- selmon->sel = c;
- drawbars();
-
-}
-
-/* there are some broken focus acquiring clients needing extra handling */
-void
-focusin(XEvent *e)
-{
- XFocusChangeEvent *ev = &e->xfocus;
-
- if (selmon->sel && ev->window != selmon->sel->win)
- setfocus(selmon->sel);
-}
-
-void
-focusmon(const Arg *arg)
-{
- Monitor *m;
- Client *sel;
-
- if (!mons->next)
- return;
- if ((m = dirtomon(arg->i)) == selmon)
- return;
- sel = selmon->sel;
- selmon = m;
- unfocus(sel, 0, NULL);
- focus(NULL);
-}
-
-Atom
-getatomprop(Client *c, Atom prop, Atom req)
-{
- int di;
- unsigned long dl;
- unsigned char *p = NULL;
- Atom da, atom = None;
-
- /* FIXME getatomprop should return the number of items and a pointer to
- * the stored data instead of this workaround */
- if (XGetWindowProperty(dpy, c->win, prop, 0L, sizeof atom, False, req,
- &da, &di, &dl, &dl, &p) == Success && p) {
- atom = *(Atom *)p;
- XFree(p);
- }
- return atom;
-}
-
-int
-getrootptr(int *x, int *y)
-{
- int di;
- unsigned int dui;
- Window dummy;
-
- return XQueryPointer(dpy, root, &dummy, &dummy, x, y, &di, &di, &dui);
-}
-
-long
-getstate(Window w)
-{
- int format;
- long result = -1;
- unsigned char *p = NULL;
- unsigned long n, extra;
- Atom real;
-
- if (XGetWindowProperty(dpy, w, wmatom[WMState], 0L, 2L, False, wmatom[WMState],
- &real, &format, &n, &extra, (unsigned char **)&p) != Success)
- return -1;
- if (n != 0)
- result = *p;
- XFree(p);
- return result;
-}
-
-int
-gettextprop(Window w, Atom atom, char *text, unsigned int size)
-{
- char **list = NULL;
- int n;
- XTextProperty name;
-
- if (!text || size == 0)
- return 0;
- text[0] = '\0';
- if (!XGetTextProperty(dpy, w, &name, atom) || !name.nitems)
- return 0;
- if (name.encoding == XA_STRING) {
- strncpy(text, (char *)name.value, size - 1);
- } else if (XmbTextPropertyToTextList(dpy, &name, &list, &n) >= Success && n > 0 && *list) {
- strncpy(text, *list, size - 1);
- XFreeStringList(list);
- }
- text[size - 1] = '\0';
- XFree(name.value);
- return 1;
-}
-
-void
-grabbuttons(Client *c, int focused)
-{
- updatenumlockmask();
- {
- unsigned int i, j;
- unsigned int modifiers[] = { 0, LockMask, numlockmask, numlockmask|LockMask };
- XUngrabButton(dpy, AnyButton, AnyModifier, c->win);
- if (!focused)
- XGrabButton(dpy, AnyButton, AnyModifier, c->win, False,
- BUTTONMASK, GrabModeSync, GrabModeSync, None, None);
- for (i = 0; i < LENGTH(buttons); i++)
- if (buttons[i].click == ClkClientWin
- )
- for (j = 0; j < LENGTH(modifiers); j++)
- XGrabButton(dpy, buttons[i].button,
- buttons[i].mask | modifiers[j],
- c->win, False, BUTTONMASK,
- GrabModeAsync, GrabModeSync, None, None);
- }
-}
-
-void
-grabkeys(void)
-{
- updatenumlockmask();
- {
- unsigned int i, j, k;
- unsigned int modifiers[] = { 0, LockMask, numlockmask, numlockmask|LockMask };
- int start, end, skip;
- KeySym *syms;
-
- XUngrabKey(dpy, AnyKey, AnyModifier, root);
- XDisplayKeycodes(dpy, &start, &end);
- syms = XGetKeyboardMapping(dpy, start, end - start + 1, &skip);
- if (!syms)
- return;
- for (k = start; k <= end; k++)
- for (i = 0; i < LENGTH(keys); i++)
- /* skip modifier codes, we do that ourselves */
- if (keys[i].keysym == syms[(k - start) * skip])
- for (j = 0; j < LENGTH(modifiers); j++)
- XGrabKey(dpy, k,
- keys[i].mod | modifiers[j],
- root, True,
- GrabModeAsync, GrabModeAsync);
- XFree(syms);
- }
-}
-
-void
-incnmaster(const Arg *arg)
-{
- selmon->nmaster = selmon->pertag->nmasters[selmon->pertag->curtag] = MAX(selmon->nmaster + arg->i, 0);
- arrange(selmon);
-}
-
-#ifdef XINERAMA
-static int
-isuniquegeom(XineramaScreenInfo *unique, size_t n, XineramaScreenInfo *info)
-{
- while (n--)
- if (unique[n].x_org == info->x_org && unique[n].y_org == info->y_org
- && unique[n].width == info->width && unique[n].height == info->height)
- return 0;
- return 1;
-}
-#endif /* XINERAMA */
-
-void
-keypress(XEvent *e)
-{
- unsigned int i;
- int keysyms_return;
- KeySym* keysym;
- XKeyEvent *ev;
-
- ev = &e->xkey;
- keysym = XGetKeyboardMapping(dpy, (KeyCode)ev->keycode, 1, &keysyms_return);
- for (i = 0; i < LENGTH(keys); i++)
- if (*keysym == keys[i].keysym
- && CLEANMASK(keys[i].mod) == CLEANMASK(ev->state)
- && keys[i].func)
- keys[i].func(&(keys[i].arg));
- XFree(keysym);
-}
-
-void
-killclient(const Arg *arg)
-{
- if (!selmon->sel)
- return;
- if (!sendevent(selmon->sel, wmatom[WMDelete]))
- {
- XGrabServer(dpy);
- XSetErrorHandler(xerrordummy);
- XSetCloseDownMode(dpy, DestroyAll);
- XKillClient(dpy, selmon->sel->win);
- XSync(dpy, False);
- XSetErrorHandler(xerror);
- XUngrabServer(dpy);
- }
-}
-
-void
-manage(Window w, XWindowAttributes *wa)
-{
- Client *c, *t = NULL;
- int settings_restored;
- Window trans = None;
- XWindowChanges wc;
-
- c = ecalloc(1, sizeof(Client));
- c->win = w;
- /* geometry */
- c->sfx = c->sfy = c->sfw = c->sfh = -9999;
- c->x = c->oldx = wa->x;
- c->y = c->oldy = wa->y;
- c->w = c->oldw = wa->width;
- c->h = c->oldh = wa->height;
- c->oldbw = wa->border_width;
- settings_restored = restoreclientstate(c);
- updatetitle(c);
-
- if (XGetTransientForHint(dpy, w, &trans) && (t = wintoclient(trans))) {
- c->mon = t->mon;
- c->tags = t->tags;
- c->bw = borderpx;
- c->x = t->x + WIDTH(t) / 2 - WIDTH(c) / 2;
- c->y = t->y + HEIGHT(t) / 2 - HEIGHT(c) / 2;
- } else {
- if (!settings_restored || c->mon == NULL) {
- c->mon = selmon;
- settings_restored = 0;
- }
- if (c->x == c->mon->wx && c->y == c->mon->wy)
- c->iscentered = 1;
- c->bw = borderpx;
- if (!settings_restored)
- applyrules(c);
- }
-
- if (c->x + WIDTH(c) > c->mon->wx + c->mon->ww)
- c->x = c->mon->wx + c->mon->ww - WIDTH(c);
- if (c->y + HEIGHT(c) > c->mon->wy + c->mon->wh)
- c->y = c->mon->wy + c->mon->wh - HEIGHT(c);
- c->x = MAX(c->x, c->mon->wx);
- c->y = MAX(c->y, c->mon->wy);
-
- wc.border_width = c->bw;
- XConfigureWindow(dpy, w, CWBorderWidth, &wc);
- if (c->isfloating)
- XSetWindowBorder(dpy, w, scheme[SchemeNorm][ColFloat].pixel);
- else
- XSetWindowBorder(dpy, w, scheme[SchemeNorm][ColBorder].pixel);
- configure(c); /* propagates border_width, if size doesn't change */
- updatesizehints(c);
- updatewmhints(c);
-
- if (c->iscentered) {
- c->sfx = c->x = c->mon->wx + (c->mon->ww - WIDTH(c)) / 2;
- c->sfy = c->y = c->mon->wy + (c->mon->wh - HEIGHT(c)) / 2;
- }
- if (c->sfw == -9999) {
- c->sfw = c->w;
- c->sfh = c->h;
- }
-
- if (getatomprop(c, netatom[NetWMState], XA_ATOM) == netatom[NetWMFullscreen])
- setfullscreen(c, 1);
-
- XSelectInput(dpy, w, EnterWindowMask|FocusChangeMask|PropertyChangeMask|StructureNotifyMask);
- grabbuttons(c, 0);
-
- if (!c->isfloating)
- c->isfloating = c->oldstate = trans != None || c->isfixed;
- if (c->isfloating) {
- XRaiseWindow(dpy, c->win);
- XSetWindowBorder(dpy, w, scheme[SchemeNorm][ColFloat].pixel);
- }
- attachx(c);
- attachstack(c);
- XChangeProperty(dpy, root, netatom[NetClientList], XA_WINDOW, 32, PropModeAppend,
- (unsigned char *) &(c->win), 1);
- XChangeProperty(dpy, root, netatom[NetClientListStacking], XA_WINDOW, 32, PropModePrepend,
- (unsigned char *) &(c->win), 1);
- XMoveResizeWindow(dpy, c->win, c->x + 2 * sw, c->y, c->w, c->h); /* some windows require this */
-
- setclientstate(c, NormalState);
- if (c->mon == selmon)
- unfocus(selmon->sel, 0, c);
- c->mon->sel = c;
- arrange(c->mon);
- XMapWindow(dpy, c->win);
- focus(NULL);
-
- setfloatinghint(c);
-}
-
-void
-mappingnotify(XEvent *e)
-{
- XMappingEvent *ev = &e->xmapping;
-
- XRefreshKeyboardMapping(ev);
- if (ev->request == MappingKeyboard)
- grabkeys();
-}
-
-void
-maprequest(XEvent *e)
-{
- static XWindowAttributes wa;
- XMapRequestEvent *ev = &e->xmaprequest;
-
- if (!XGetWindowAttributes(dpy, ev->window, &wa) || wa.override_redirect)
- return;
- if (!wintoclient(ev->window))
- manage(ev->window, &wa);
-}
-
-void
-motionnotify(XEvent *e)
-{
- Bar *bar;
- XMotionEvent *ev = &e->xmotion;
-
- if ((bar = wintobar(ev->window))) {
- barhover(e, bar);
- return;
- }
-
-}
-
-void
-movemouse(const Arg *arg)
-{
- int x, y, ocx, ocy, nx, ny;
- Client *c;
- Monitor *m;
- XEvent ev;
- Time lasttime = 0;
-
- if (!(c = selmon->sel))
- return;
- if (c->isfullscreen) /* no support moving fullscreen windows by mouse */
- return;
- restack(selmon);
- nx = ocx = c->x;
- ny = ocy = c->y;
- if (XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync,
- None, cursor[CurMove]->cursor, CurrentTime) != GrabSuccess)
- return;
- if (!getrootptr(&x, &y))
- return;
- ignoreconfigurerequests = 1;
- do {
- XMaskEvent(dpy, MOUSEMASK|ExposureMask|SubstructureRedirectMask, &ev);
- switch(ev.type) {
- case ConfigureRequest:
- case Expose:
- case MapRequest:
- handler[ev.type](&ev);
- break;
- case MotionNotify:
- if ((ev.xmotion.time - lasttime) <= (1000 / 60))
- continue;
- lasttime = ev.xmotion.time;
-
- nx = ocx + (ev.xmotion.x - x);
- ny = ocy + (ev.xmotion.y - y);
- if (abs(selmon->wx - nx) < snap)
- nx = selmon->wx;
- else if (abs((selmon->wx + selmon->ww) - (nx + WIDTH(c))) < snap)
- nx = selmon->wx + selmon->ww - WIDTH(c);
- if (abs(selmon->wy - ny) < snap)
- ny = selmon->wy;
- else if (abs((selmon->wy + selmon->wh) - (ny + HEIGHT(c))) < snap)
- ny = selmon->wy + selmon->wh - HEIGHT(c);
- if (!c->isfloating && selmon->lt[selmon->sellt]->arrange
- && (abs(nx - c->x) > snap || abs(ny - c->y) > snap)) {
- c->sfx = -9999; // disable savefloats when using movemouse
- togglefloating(NULL);
- }
- if (!selmon->lt[selmon->sellt]->arrange || c->isfloating) {
- resize(c, nx, ny, c->w, c->h, 1);
- }
- break;
- }
- } while (ev.type != ButtonRelease);
-
- XUngrabPointer(dpy, CurrentTime);
- if ((m = recttomon(c->x, c->y, c->w, c->h)) != selmon) {
- sendmon(c, m);
- selmon = m;
- focus(NULL);
- }
- /* save last known float coordinates */
- if (!selmon->lt[selmon->sellt]->arrange || c->isfloating) {
- c->sfx = nx;
- c->sfy = ny;
- }
- ignoreconfigurerequests = 0;
-}
-
-Client *
-nexttiled(Client *c)
-{
- for (; c && (c->isfloating || !ISVISIBLE(c)); c = c->next);
- return c;
-}
-
-void
-pop(Client *c)
-{
- detach(c);
- attach(c);
- focus(c);
- arrange(c->mon);
-}
-
-void
-propertynotify(XEvent *e)
-{
- Client *c;
- Window trans;
- XPropertyEvent *ev = &e->xproperty;
-
- if ((ev->window == root) && (ev->atom == XA_WM_NAME)) {
- updatestatus();
- } else if (ev->state == PropertyDelete) {
- return; /* ignore */
- } else if ((c = wintoclient(ev->window))) {
- switch(ev->atom) {
- default: break;
- case XA_WM_TRANSIENT_FOR:
- if (!c->isfloating && (XGetTransientForHint(dpy, c->win, &trans)) &&
- (c->isfloating = (wintoclient(trans)) != NULL))
- arrange(c->mon);
- break;
- case XA_WM_NORMAL_HINTS:
- c->hintsvalid = 0;
- break;
- case XA_WM_HINTS:
- updatewmhints(c);
- if (c->isurgent)
- drawbars();
- break;
- }
- if (ev->atom == XA_WM_NAME || ev->atom == netatom[NetWMName]) {
- updatetitle(c);
- if (c == c->mon->sel)
- drawbar(c->mon);
- }
- }
-}
-
-void
-quit(const Arg *arg)
-{
- restart = arg->i;
- running = 0;
-}
-
-Monitor *
-recttomon(int x, int y, int w, int h)
-{
- Monitor *m, *r = selmon;
- int a, area = 0;
-
- for (m = mons; m; m = m->next)
- if ((a = INTERSECT(x, y, w, h, m)) > area) {
- area = a;
- r = m;
- }
- return r;
-}
-
-void
-resize(Client *c, int x, int y, int w, int h, int interact)
-{
- if (applysizehints(c, &x, &y, &w, &h, interact))
- resizeclient(c, x, y, w, h);
-}
-
-void
-resizeclient(Client *c, int x, int y, int w, int h)
-{
- XWindowChanges wc;
-
- c->oldx = c->x; c->x = wc.x = x;
- 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;
- XConfigureWindow(dpy, c->win, CWX|CWY|CWWidth|CWHeight|CWBorderWidth, &wc);
- configure(c);
- XSync(dpy, False);
-}
-
-void
-resizemouse(const Arg *arg)
-{
- int ocx, ocy, nw, nh, nx, ny;
- int opx, opy, och, ocw;
- int horizcorner, vertcorner;
- unsigned int dui;
- Window dummy;
- Client *c;
- Monitor *m;
- XEvent ev;
- Time lasttime = 0;
-
- if (!(c = selmon->sel))
- return;
- if (c->isfullscreen) /* no support resizing fullscreen windows by mouse */
- return;
- restack(selmon);
- nx = ocx = c->x;
- ny = ocy = c->y;
- nh = c->h;
- nw = c->w;
- och = c->h;
- ocw = c->w;
- if (!XQueryPointer(dpy, c->win, &dummy, &dummy, &opx, &opy, &nx, &ny, &dui))
- return;
- horizcorner = nx < c->w / 2;
- vertcorner = ny < c->h / 2;
- if (XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync,
- None, cursor[horizcorner | (vertcorner << 1)]->cursor, CurrentTime) != GrabSuccess)
- return;
- ignoreconfigurerequests = 1;
- do {
- XMaskEvent(dpy, MOUSEMASK|ExposureMask|SubstructureRedirectMask, &ev);
- switch(ev.type) {
- case ConfigureRequest:
- case Expose:
- case MapRequest:
- handler[ev.type](&ev);
- break;
- case MotionNotify:
- if ((ev.xmotion.time - lasttime) <= (1000 / 60))
- continue;
- lasttime = ev.xmotion.time;
-
- nx = horizcorner ? (ocx + ev.xmotion.x - opx) : c->x;
- ny = vertcorner ? (ocy + ev.xmotion.y - opy) : c->y;
- nw = MAX(horizcorner ? (ocx + ocw - nx) : (ocw + (ev.xmotion.x - opx)), 1);
- nh = MAX(vertcorner ? (ocy + och - ny) : (och + (ev.xmotion.y - opy)), 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)
- {
- if (!c->isfloating && selmon->lt[selmon->sellt]->arrange
- && (abs(nw - c->w) > snap || abs(nh - c->h) > snap)) {
- c->sfx = -9999; // disable savefloats when using resizemouse
- togglefloating(NULL);
- }
- }
- if (!selmon->lt[selmon->sellt]->arrange || c->isfloating) {
- resize(c, nx, ny, nw, nh, 1);
- }
- break;
- }
- } while (ev.type != ButtonRelease);
-
- XUngrabPointer(dpy, CurrentTime);
- while (XCheckMaskEvent(dpy, EnterWindowMask, &ev));
- if ((m = recttomon(c->x, c->y, c->w, c->h)) != selmon) {
- sendmon(c, m);
- selmon = m;
- focus(NULL);
- }
- /* save last known float dimensions */
- if (!selmon->lt[selmon->sellt]->arrange || c->isfloating) {
- c->sfx = nx;
- c->sfy = ny;
- c->sfw = nw;
- c->sfh = nh;
- }
- ignoreconfigurerequests = 0;
-}
-
-void
-restack(Monitor *m)
-{
- Client *c, *f = NULL;
- XEvent ev;
- XWindowChanges wc;
-
- drawbar(m);
- if (!m->sel)
- return;
- if (m->sel->isfloating || !m->lt[m->sellt]->arrange)
- XRaiseWindow(dpy, m->sel->win);
- if (m->lt[m->sellt]->arrange) {
- wc.stack_mode = Below;
- if (m->bar) {
- wc.sibling = m->bar->win;
- } else {
- for (f = m->stack; f && (f->isfloating || !ISVISIBLE(f)); f = f->snext); // find first tiled stack client
- if (f)
- wc.sibling = f->win;
- }
- for (c = m->stack; c; c = c->snext)
- if (!c->isfloating && ISVISIBLE(c) && c != f) {
- XConfigureWindow(dpy, c->win, CWSibling|CWStackMode, &wc);
- wc.sibling = c->win;
- }
- }
- XSync(dpy, False);
- while (XCheckMaskEvent(dpy, EnterWindowMask, &ev));
-}
-
-void
-run(void)
-{
- XEvent ev;
- XSync(dpy, False);
- /* main event loop */
- while (running) {
- struct pollfd pfd = {
- .fd = ConnectionNumber(dpy),
- .events = POLLIN,
- };
- int pending = XPending(dpy) > 0 || poll(&pfd, 1, -1) > 0;
-
- if (!running)
- break;
- if (!pending)
- continue;
-
- XNextEvent(dpy, &ev);
- if (handler[ev.type])
- handler[ev.type](&ev); /* call handler */
- }
-}
-
-void
-scan(void)
-{
- unsigned int i, num;
- Window d1, d2, *wins = NULL;
- XWindowAttributes wa;
-
- if (XQueryTree(dpy, root, &d1, &d2, &wins, &num)) {
- for (i = 0; i < num; i++) {
- if (!XGetWindowAttributes(dpy, wins[i], &wa)
- || wa.override_redirect || XGetTransientForHint(dpy, wins[i], &d1))
- continue;
- if (wa.map_state == IsViewable || getstate(wins[i]) == IconicState)
- manage(wins[i], &wa);
- }
- for (i = 0; i < num; i++) { /* now the transients */
- if (!XGetWindowAttributes(dpy, wins[i], &wa))
- continue;
- if (XGetTransientForHint(dpy, wins[i], &d1)
- && (wa.map_state == IsViewable || getstate(wins[i]) == IconicState))
- manage(wins[i], &wa);
- }
- XFree(wins);
- }
-}
-
-void
-sendmon(Client *c, Monitor *m)
-{
- if (c->mon == m)
- return;
- int hadfocus = (c == selmon->sel);
- unfocus(c, 1, NULL);
- detach(c);
- detachstack(c);
- arrange(c->mon);
- c->mon = m;
- c->tags = m->tagset[m->seltags]; /* assign tags of target monitor */
- attachx(c);
- attachstack(c);
- arrange(m);
- if (hadfocus) {
- focus(c);
- restack(m);
- } else {
- focus(NULL);
- }
-}
-
-void
-setclientstate(Client *c, long state)
-{
- long data[] = { state, None };
-
- XChangeProperty(dpy, c->win, wmatom[WMState], wmatom[WMState], 32,
- PropModeReplace, (unsigned char *)data, 2);
-}
-
-int
-sendevent(Client *c, Atom proto)
-{
- int n;
- Atom *protocols;
- int exists = 0;
- XEvent ev;
-
- if (XGetWMProtocols(dpy, c->win, &protocols, &n)) {
- while (!exists && n--)
- exists = protocols[n] == proto;
- XFree(protocols);
- }
-
- if (exists) {
- ev.type = ClientMessage;
- ev.xclient.window = c->win;
- ev.xclient.message_type = wmatom[WMProtocols];
- ev.xclient.format = 32;
- ev.xclient.data.l[0] = proto;
- ev.xclient.data.l[1] = CurrentTime;
- XSendEvent(dpy, c->win, False, NoEventMask, &ev);
- }
- return exists;
-}
-
-void
-setfocus(Client *c)
-{
- if (!c->neverfocus) {
- XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime);
- XChangeProperty(dpy, root, netatom[NetActiveWindow],
- XA_WINDOW, 32, PropModeReplace,
- (unsigned char *) &(c->win), 1);
- }
- sendevent(c, wmatom[WMTakeFocus]);
-}
-
-void
-setfullscreen(Client *c, int fullscreen)
-{
- if (fullscreen && !c->isfullscreen) {
- XChangeProperty(dpy, c->win, netatom[NetWMState], XA_ATOM, 32,
- PropModeReplace, (unsigned char*)&netatom[NetWMFullscreen], 1);
- c->isfullscreen = 1;
- c->oldbw = c->bw;
- c->oldstate = c->isfloating;
- c->bw = 0;
- c->isfloating = 1;
- resizeclient(c, c->mon->mx, c->mon->my, c->mon->mw, c->mon->mh);
- XRaiseWindow(dpy, c->win);
- } else if (!fullscreen && c->isfullscreen){
- XChangeProperty(dpy, c->win, netatom[NetWMState], XA_ATOM, 32,
- PropModeReplace, (unsigned char*)0, 0);
- c->isfullscreen = 0;
- c->bw = c->oldbw;
- c->isfloating = c->oldstate;
- c->x = c->oldx;
- c->y = c->oldy;
- c->w = c->oldw;
- c->h = c->oldh;
- resizeclient(c, c->x, c->y, c->w, c->h);
- arrange(c->mon);
- }
-}
-
-void
-setlayout(const Arg *arg)
-{
- if (!arg || !arg->v || arg->v != selmon->lt[selmon->sellt]) {
- selmon->pertag->sellts[selmon->pertag->curtag] ^= 1;
- selmon->sellt = selmon->pertag->sellts[selmon->pertag->curtag];
- }
- if (arg && arg->v)
- selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt] = (Layout *)arg->v;
- selmon->lt[selmon->sellt] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt];
-
- strncpy(selmon->ltsymbol, selmon->lt[selmon->sellt]->symbol, sizeof selmon->ltsymbol);
- if (selmon->sel)
- arrange(selmon);
- else
- drawbar(selmon);
-}
-
-/* arg > 1.0 will set mfact absolutely */
-void
-setmfact(const Arg *arg)
-{
- float f;
-
- if (!arg || !selmon->lt[selmon->sellt]->arrange)
- return;
- f = arg->f < 1.0 ? arg->f + selmon->mfact : arg->f - 1.0;
- if (f < 0.05 || f > 0.95)
- return;
- selmon->mfact = selmon->pertag->mfacts[selmon->pertag->curtag] = f;
- arrange(selmon);
-}
-
-void
-setup(void)
-{
- int i;
- XSetWindowAttributes wa;
- Atom utf8string;
- /* clean up any zombies immediately */
- sigchld(0);
-
- signal(SIGHUP, sighup);
- signal(SIGTERM, sigterm);
-
- /* the one line of bloat that would have saved a lot of time for a lot of people */
- putenv("_JAVA_AWT_WM_NONREPARENTING=1");
-
- /* init screen */
- screen = DefaultScreen(dpy);
- sw = DisplayWidth(dpy, screen);
- sh = DisplayHeight(dpy, screen);
- root = RootWindow(dpy, screen);
- drw = drw_create(dpy, screen, root, sw, sh);
- if (!drw_font_create(drw, font))
- die("no fonts could be loaded.");
- lrpad = drw->fonts->h;
- bh = drw->fonts->h + 2;
- updategeom();
- /* init atoms */
- utf8string = XInternAtom(dpy, "UTF8_STRING", False);
- wmatom[WMProtocols] = XInternAtom(dpy, "WM_PROTOCOLS", False);
- wmatom[WMDelete] = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
- wmatom[WMState] = XInternAtom(dpy, "WM_STATE", False);
- wmatom[WMTakeFocus] = XInternAtom(dpy, "WM_TAKE_FOCUS", False);
- wmatom[WMWindowRole] = XInternAtom(dpy, "WM_WINDOW_ROLE", False);
- clientatom[ClientFields] = XInternAtom(dpy, "_DWM_CLIENT_FIELDS", False);
- clientatom[ClientTags] = XInternAtom(dpy, "_DWM_CLIENT_TAGS", False);
- netatom[NetActiveWindow] = XInternAtom(dpy, "_NET_ACTIVE_WINDOW", False);
- netatom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False);
- netatom[NetDesktopViewport] = XInternAtom(dpy, "_NET_DESKTOP_VIEWPORT", False);
- netatom[NetNumberOfDesktops] = XInternAtom(dpy, "_NET_NUMBER_OF_DESKTOPS", False);
- netatom[NetCurrentDesktop] = XInternAtom(dpy, "_NET_CURRENT_DESKTOP", False);
- netatom[NetDesktopNames] = XInternAtom(dpy, "_NET_DESKTOP_NAMES", 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[NetClientList] = XInternAtom(dpy, "_NET_CLIENT_LIST", False);
- netatom[NetClientListStacking] = XInternAtom(dpy, "_NET_CLIENT_LIST_STACKING", False);
- /* init cursors */
- cursor[CurNormal] = drw_cur_create(drw, XC_left_ptr);
- cursor[CurResize] = drw_cur_create(drw, XC_sizing);
- cursor[CurResizeBR] = drw_cur_create(drw, XC_bottom_right_corner);
- cursor[CurResizeBL] = drw_cur_create(drw, XC_bottom_left_corner);
- cursor[CurResizeTR] = drw_cur_create(drw, XC_top_right_corner);
- cursor[CurResizeTL] = drw_cur_create(drw, XC_top_left_corner);
- cursor[CurMove] = drw_cur_create(drw, XC_fleur);
- /* init appearance */
- scheme = ecalloc(LENGTH(colors), sizeof(Clr *));
- for (i = 0; i < LENGTH(colors); i++)
- scheme[i] = drw_scm_create(drw, colors[i], ColCount);
-
- updatebars();
- updatestatus();
-
- /* supporting window for NetWMCheck */
- wmcheckwin = XCreateSimpleWindow(dpy, root, 0, 0, 1, 1, 0, 0, 0);
- XChangeProperty(dpy, wmcheckwin, netatom[NetWMCheck], XA_WINDOW, 32,
- PropModeReplace, (unsigned char *) &wmcheckwin, 1);
- XChangeProperty(dpy, wmcheckwin, netatom[NetWMName], utf8string, 8,
- PropModeReplace, (unsigned char *) "dwm", 3);
- XChangeProperty(dpy, root, netatom[NetWMCheck], XA_WINDOW, 32,
- PropModeReplace, (unsigned char *) &wmcheckwin, 1);
- /* EWMH support per view */
- XChangeProperty(dpy, root, netatom[NetSupported], XA_ATOM, 32,
- PropModeReplace, (unsigned char *) netatom, NetLast);
- setnumdesktops();
- setcurrentdesktop();
- setdesktopnames();
- setviewport();
- XDeleteProperty(dpy, root, netatom[NetClientList]);
- XDeleteProperty(dpy, root, netatom[NetClientListStacking]);
- /* select events */
- wa.cursor = cursor[CurNormal]->cursor;
- wa.event_mask = SubstructureRedirectMask|SubstructureNotifyMask
- |ButtonPressMask|PointerMotionMask|EnterWindowMask
- |LeaveWindowMask|StructureNotifyMask|PropertyChangeMask;
- XChangeWindowAttributes(dpy, root, CWEventMask|CWCursor, &wa);
- XSelectInput(dpy, root, wa.event_mask);
-
- grabkeys();
- focus(NULL);
-}
-
-void
-seturgent(Client *c, int urg)
-{
- XWMHints *wmh;
-
- c->isurgent = urg;
- if (!(wmh = XGetWMHints(dpy, c->win)))
- return;
- wmh->flags = urg ? (wmh->flags | XUrgencyHint) : (wmh->flags & ~XUrgencyHint);
- XSetWMHints(dpy, c->win, wmh);
- XFree(wmh);
-}
-
-void
-showhide(Client *c)
-{
- if (!c)
- return;
- if (ISVISIBLE(c)) {
- /* show clients top down */
- if (!c->mon->lt[c->mon->sellt]->arrange && c->sfx != -9999 && !c->isfullscreen) {
- XMoveResizeWindow(dpy, c->win, c->sfx, c->sfy, c->sfw, c->sfh);
- resize(c, c->sfx, c->sfy, c->sfw, c->sfh, 0);
- showhide(c->snext);
- return;
- }
- XMoveWindow(dpy, c->win, c->x, c->y);
- if ((!c->mon->lt[c->mon->sellt]->arrange || c->isfloating)
- && !c->isfullscreen
- )
- resize(c, c->x, c->y, c->w, c->h, 0);
- showhide(c->snext);
- } else {
- /* hide clients bottom up */
- showhide(c->snext);
- XMoveWindow(dpy, c->win, WIDTH(c) * -2, c->y);
- }
-}
-
-void
-sigchld(int unused)
-{
- pid_t pid;
-
- if (signal(SIGCHLD, sigchld) == SIG_ERR)
- die("can't install SIGCHLD handler:");
-
- while (0 < (pid = waitpid(-1, NULL, WNOHANG))) {
- pid_t *p, *lim;
-
- if (!(p = autostart_pids))
- continue;
- lim = &p[autostart_len];
-
- for (; p < lim; p++) {
- if (*p == pid) {
- *p = -1;
- break;
- }
- }
- }
-}
-
-void
-spawn(const Arg *arg)
-{
- struct sigaction sa;
-
- if (fork() == 0)
- {
- if (dpy)
- close(ConnectionNumber(dpy));
-
- setsid();
-
- sigemptyset(&sa.sa_mask);
- sa.sa_flags = 0;
- sa.sa_handler = SIG_DFL;
- sigaction(SIGCHLD, &sa, NULL);
-
- execvp(((char **)arg->v)[0], (char **)arg->v);
- die("dwm: execvp '%s' failed:", ((char **)arg->v)[0]);
- }
-}
-
-void
-tag(const Arg *arg)
-{
-
- if (selmon->sel && arg->ui & TAGMASK) {
- selmon->sel->tags = arg->ui & TAGMASK;
- arrange(selmon);
- focus(NULL);
- }
-}
-
-void
-tagmon(const Arg *arg)
-{
- Client *c = selmon->sel;
- Monitor *dest;
- int restored;
- if (!c || !mons->next)
- return;
- dest = dirtomon(arg->i);
- savewindowfloatposition(c, c->mon);
- restored = restorewindowfloatposition(c, dest);
- if (restored && (!dest->lt[dest->sellt]->arrange || c->isfloating)) {
- XMoveResizeWindow(dpy, c->win, c->sfx, c->sfy, c->sfw, c->sfh);
- resize(c, c->sfx, c->sfy, c->sfw, c->sfh, 1);
- }
- if (c->isfullscreen) {
- c->isfullscreen = 0;
- sendmon(c, dest);
- c->isfullscreen = 1;
- resizeclient(c, c->mon->mx, c->mon->my, c->mon->mw, c->mon->mh);
- XRaiseWindow(dpy, c->win);
- } else if (c->isfloating && c->scratchkey != 0) {
- sendmon(c, dest);
- applyrules(c);
- XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h);
- } else
- sendmon(c, dest);
-}
-
-void
-togglebar(const Arg *arg)
-{
- Bar *bar;
- selmon->showbar = !selmon->showbar;
- updatebarpos(selmon);
- for (bar = selmon->bar; bar; bar = bar->next)
- XMoveResizeWindow(dpy, bar->win, bar->bx, bar->by, bar->bw, bar->bh);
- arrange(selmon);
-}
-
-void
-togglefloating(const Arg *arg)
-{
- Client *c = selmon->sel;
- if (arg && arg->v)
- c = (Client*)arg->v;
- if (!c)
- return;
- if (c->isfullscreen) /* no support for fullscreen windows */
- return;
- c->isfloating = !c->isfloating || c->isfixed;
- if (c->scratchkey != 0 && c->isfloating)
- XSetWindowBorder(dpy, c->win, scheme[SchemeScratchSel][ColFloat].pixel);
- else if (c->scratchkey != 0)
- XSetWindowBorder(dpy, c->win, scheme[SchemeScratchSel][ColBorder].pixel);
- else if (c->isfloating)
- XSetWindowBorder(dpy, c->win, scheme[SchemeSel][ColFloat].pixel);
- else
- XSetWindowBorder(dpy, c->win, scheme[SchemeSel][ColBorder].pixel);
- if (c->isfloating) {
- if (c->sfx != -9999) {
- /* restore last known float dimensions */
- resize(c, c->sfx, c->sfy, c->sfw, c->sfh, 0);
- } else
- resize(c, c->x, c->y, c->w, c->h, 0);
- } else {
- /* save last known float dimensions */
- c->sfx = c->x;
- c->sfy = c->y;
- c->sfw = c->w;
- c->sfh = c->h;
- }
- arrange(c->mon);
-
- setfloatinghint(c);
-}
-
-void
-toggletag(const Arg *arg)
-{
- unsigned int newtags;
-
- if (!selmon->sel)
- return;
- newtags = selmon->sel->tags ^ (arg->ui & TAGMASK);
- if (newtags) {
- selmon->sel->tags = newtags;
- arrange(selmon);
- focus(NULL);
- }
- updatecurrentdesktop();
-}
-
-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->curtag = 0;
- }
- /* test if the user did not select the same tag */
- if (!(newtagset & 1 << (selmon->pertag->curtag - 1))) {
- 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];
- arrange(selmon);
- focus(NULL);
- }
- updatecurrentdesktop();
-}
-
-void
-unfocus(Client *c, int setfocus, Client *nextfocus)
-{
- if (!c)
- return;
- if (c->isfullscreen && ISVISIBLE(c) && c->mon == selmon && nextfocus && !nextfocus->isfloating) {
- setfullscreen(c, 0);
- }
- grabbuttons(c, 0);
- if (c->scratchkey != 0 && c->isfloating)
- XSetWindowBorder(dpy, c->win, scheme[SchemeScratchNorm][ColFloat].pixel);
- else if (c->scratchkey != 0)
- XSetWindowBorder(dpy, c->win, scheme[SchemeScratchNorm][ColBorder].pixel);
- else if (c->isfloating)
- XSetWindowBorder(dpy, c->win, scheme[SchemeNorm][ColFloat].pixel);
- else
- XSetWindowBorder(dpy, c->win, scheme[SchemeNorm][ColBorder].pixel);
- if (setfocus) {
- XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime);
- XDeleteProperty(dpy, root, netatom[NetActiveWindow]);
- }
-}
-
-void
-unmanage(Client *c, int destroyed)
-{
- Monitor *m;
- XWindowChanges wc;
-
- m = c->mon;
-
- detach(c);
- detachstack(c);
- if (!destroyed) {
- wc.border_width = c->oldbw;
- XGrabServer(dpy); /* avoid race conditions */
- XSetErrorHandler(xerrordummy);
- XSelectInput(dpy, c->win, NoEventMask);
- XConfigureWindow(dpy, c->win, CWBorderWidth, &wc); /* restore border */
- XUngrabButton(dpy, AnyButton, AnyModifier, c->win);
- if (!HIDDEN(c))
- setclientstate(c, WithdrawnState);
- XSync(dpy, False);
- XSetErrorHandler(xerror);
- XUngrabServer(dpy);
- }
-
- free(c);
- arrange(m);
- focus(NULL);
- updateclientlist();
-}
-
-void
-unmapnotify(XEvent *e)
-{
- Client *c;
- XUnmapEvent *ev = &e->xunmap;
-
- if ((c = wintoclient(ev->window))) {
- if (ev->send_event)
- setclientstate(c, WithdrawnState);
- else
- unmanage(c, 0);
- }
-}
-
-void
-updatebars(void)
-{
- Bar *bar;
- Monitor *m;
- XSetWindowAttributes wa = {
- .override_redirect = True,
- .background_pixmap = ParentRelative,
- .event_mask = ButtonPressMask|ExposureMask
- };
- XClassHint ch = {"dwm", "dwm"};
- for (m = mons; m; m = m->next) {
- for (bar = m->bar; bar; bar = bar->next) {
- if (bar->external)
- continue;
- if (!bar->win) {
- bar->win = XCreateWindow(dpy, root, bar->bx, bar->by, bar->bw, bar->bh, 0, DefaultDepth(dpy, screen),
- CopyFromParent, DefaultVisual(dpy, screen),
- CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa);
- XDefineCursor(dpy, bar->win, cursor[CurNormal]->cursor);
- XMapRaised(dpy, bar->win);
- XSetClassHint(dpy, bar->win, &ch);
- }
- }
- }
-}
-
-void
-updatebarpos(Monitor *m)
-{
-
- m->wx = m->mx;
- m->wy = m->my;
- m->ww = m->mw;
- m->wh = m->mh;
- Bar *bar;
- int y_pad = 0;
- int x_pad = 0;
-
- for (bar = m->bar; bar; bar = bar->next) {
- bar->bx = m->wx + x_pad;
- bar->bw = m->ww - 2 * x_pad;
- }
-
- for (bar = m->bar; bar; bar = bar->next)
- if (!m->showbar || !bar->showbar)
- bar->by = -bar->bh - y_pad;
-
- if (!m->showbar)
- return;
- for (bar = m->bar; bar; bar = bar->next) {
- if (!bar->showbar)
- continue;
- if (bar->topbar)
- m->wy = m->wy + bar->bh + y_pad;
- m->wh -= y_pad + bar->bh;
- bar->by = (bar->topbar ? m->wy - bar->bh : m->wy + m->wh);
- }
-}
-
-void
-updateclientlist(void)
-{
- Client *c;
- Monitor *m;
-
- XDeleteProperty(dpy, root, netatom[NetClientList]);
- for (m = mons; m; m = m->next)
- for (c = m->clients; c; c = c->next)
- XChangeProperty(dpy, root, netatom[NetClientList],
- XA_WINDOW, 32, PropModeAppend,
- (unsigned char *) &(c->win), 1);
-
- XDeleteProperty(dpy, root, netatom[NetClientListStacking]);
- for (m = mons; m; m = m->next)
- for (c = m->stack; c; c = c->snext)
- XChangeProperty(dpy, root, netatom[NetClientListStacking],
- XA_WINDOW, 32, PropModeAppend,
- (unsigned char *) &(c->win), 1);
-}
-
-int
-updategeom(void)
-{
- int dirty = 0;
-
-#ifdef XINERAMA
- if (XineramaIsActive(dpy)) {
- int i, j, n, nn;
- Client *c;
- Monitor *m;
- XineramaScreenInfo *info = XineramaQueryScreens(dpy, &nn);
- XineramaScreenInfo *unique = NULL;
-
- for (n = 0, m = mons; m; m = m->next, n++);
- /* only consider unique geometries as separate screens */
- unique = ecalloc(nn, sizeof(XineramaScreenInfo));
- for (i = 0, j = 0; i < nn; i++)
- if (isuniquegeom(unique, j, &info[i]))
- memcpy(&unique[j++], &info[i], sizeof(XineramaScreenInfo));
- XFree(info);
- nn = j;
- /* new monitors if nn > n */
- for (i = n; i < nn; i++) {
- for (m = mons; m && m->next; m = m->next);
- if (m)
- m->next = createmon();
- else
- mons = createmon();
- }
- for (i = 0, m = mons; i < nn && m; m = m->next, i++)
- if (i >= n
- || unique[i].x_org != m->mx || unique[i].y_org != m->my
- || unique[i].width != m->mw || unique[i].height != m->mh)
- {
- dirty = 1;
- m->num = i;
- m->mx = m->wx = unique[i].x_org;
- m->my = m->wy = unique[i].y_org;
- m->mw = m->ww = unique[i].width;
- m->mh = m->wh = unique[i].height;
- updatebarpos(m);
- }
- /* removed monitors if n > nn */
- for (i = nn; i < n; i++) {
- for (m = mons; m && m->next; m = m->next);
- while ((c = m->clients)) {
- dirty = 1;
- m->clients = c->next;
- detachstack(c);
- c->mon = mons;
- attach(c);
- attachstack(c);
- }
- if (m == selmon)
- selmon = mons;
- cleanupmon(m);
- }
- free(unique);
- } else
-#endif /* XINERAMA */
- { /* default monitor setup */
- if (!mons)
- mons = createmon();
- if (mons->mw != sw || mons->mh != sh) {
- dirty = 1;
- mons->mw = mons->ww = sw;
- mons->mh = mons->wh = sh;
- updatebarpos(mons);
- }
- }
- if (dirty) {
- selmon = mons;
- selmon = wintomon(root);
- }
- return dirty;
-}
-
-void
-updatenumlockmask(void)
-{
- unsigned int i, j;
- XModifierKeymap *modmap;
-
- numlockmask = 0;
- modmap = XGetModifierMapping(dpy);
- for (i = 0; i < 8; i++)
- for (j = 0; j < modmap->max_keypermod; j++)
- if (modmap->modifiermap[i * modmap->max_keypermod + j]
- == XKeysymToKeycode(dpy, XK_Num_Lock))
- numlockmask = (1 << i);
- XFreeModifiermap(modmap);
-}
-
-void
-updatesizehints(Client *c)
-{
- long msize;
- XSizeHints size;
-
- if (!XGetWMNormalHints(dpy, c->win, &size, &msize))
- /* size is uninitialized, ensure that size.flags aren't used */
- size.flags = 0;
- if (size.flags & PBaseSize) {
- c->basew = size.base_width;
- c->baseh = size.base_height;
- } else if (size.flags & PMinSize) {
- c->basew = size.min_width;
- c->baseh = size.min_height;
- } else
- c->basew = c->baseh = 0;
- if (size.flags & PResizeInc) {
- c->incw = size.width_inc;
- c->inch = size.height_inc;
- } else
- c->incw = c->inch = 0;
- if (size.flags & PMaxSize) {
- c->maxw = size.max_width;
- c->maxh = size.max_height;
- } else
- c->maxw = c->maxh = 0;
- if (size.flags & PMinSize) {
- c->minw = size.min_width;
- c->minh = size.min_height;
- } else if (size.flags & PBaseSize) {
- c->minw = size.base_width;
- c->minh = size.base_height;
- } else
- c->minw = c->minh = 0;
- if (size.flags & PAspect) {
- c->mina = (float)size.min_aspect.y / size.min_aspect.x;
- c->maxa = (float)size.max_aspect.x / size.max_aspect.y;
- } else
- c->maxa = c->mina = 0.0;
- if (size.flags & PSize)
- {
- c->basew = size.base_width;
- c->baseh = size.base_height;
- c->isfloating = 1;
- }
- checkfloatingrules(c);
- c->isfixed = (c->maxw && c->maxh && c->maxw == c->minw && c->maxh == c->minh);
- c->hintsvalid = 1;
-}
-
-void
-updatestatus(void)
-{
- Monitor *m;
- if (!gettextprop(root, XA_WM_NAME, rawstext, sizeof(rawstext)))
- strcpy(stext, "dwm-"VERSION);
- else
- copyvalidchars(stext, rawstext);
- for (m = mons; m; m = m->next)
- drawbar(m);
-}
-
-void
-updatetitle(Client *c)
-{
-
- if (!gettextprop(c->win, netatom[NetWMName], c->name, sizeof c->name))
- gettextprop(c->win, XA_WM_NAME, c->name, sizeof c->name);
- if (c->name[0] == '\0') /* hack to mark broken clients */
- strcpy(c->name, broken);
-
-}
-
-void
-updatewmhints(Client *c)
-{
- XWMHints *wmh;
-
- if ((wmh = XGetWMHints(dpy, c->win))) {
- if (c == selmon->sel && wmh->flags & XUrgencyHint) {
- wmh->flags &= ~XUrgencyHint;
- XSetWMHints(dpy, c->win, wmh);
- } else
- c->isurgent = (wmh->flags & XUrgencyHint) ? 1 : 0;
- if (c->isurgent) {
- if (c->isfloating)
- XSetWindowBorder(dpy, c->win, scheme[SchemeUrg][ColFloat].pixel);
- else
- XSetWindowBorder(dpy, c->win, scheme[SchemeUrg][ColBorder].pixel);
- }
- if (wmh->flags & InputHint)
- c->neverfocus = !wmh->input;
- else
- c->neverfocus = 0;
- XFree(wmh);
- }
-}
-
-void
-view(const Arg *arg)
-{
- if ((arg->ui & TAGMASK) == selmon->tagset[selmon->seltags])
- {
- return;
- }
- selmon->seltags ^= 1; /* toggle sel tagset */
- if (arg->ui & TAGMASK)
- selmon->tagset[selmon->seltags] = arg->ui & TAGMASK;
- pertagview(arg);
- arrange(selmon);
- focus(NULL);
- updatecurrentdesktop();
-}
-
-Client *
-wintoclient(Window w)
-{
- Client *c;
- Monitor *m;
-
- for (m = mons; m; m = m->next)
- for (c = m->clients; c; c = c->next)
- if (c->win == w)
- return c;
- return NULL;
-}
-
-Monitor *
-wintomon(Window w)
-{
- int x, y;
- Client *c;
- Monitor *m;
- Bar *bar;
-
- if (w == root && getrootptr(&x, &y))
- return recttomon(x, y, 1, 1);
- for (m = mons; m; m = m->next)
- for (bar = m->bar; bar; bar = bar->next)
- if (w == bar->win)
- return m;
- if ((c = wintoclient(w)))
- return c->mon;
- return selmon;
-}
-
-/* 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. */
-int
-xerror(Display *dpy, XErrorEvent *ee)
-{
- if (ee->error_code == BadWindow
- || (ee->request_code == X_SetInputFocus && ee->error_code == BadMatch)
- || (ee->request_code == X_PolyText8 && ee->error_code == BadDrawable)
- || (ee->request_code == X_PolyFillRectangle && ee->error_code == BadDrawable)
- || (ee->request_code == X_PolySegment && ee->error_code == BadDrawable)
- || (ee->request_code == X_ConfigureWindow && ee->error_code == BadMatch)
- || (ee->request_code == X_GrabButton && ee->error_code == BadAccess)
- || (ee->request_code == X_GrabKey && ee->error_code == BadAccess)
- || (ee->request_code == X_CopyArea && ee->error_code == BadDrawable))
- return 0;
- fprintf(stderr, "dwm: fatal error: request code=%d, error code=%d\n",
- ee->request_code, ee->error_code);
- return xerrorxlib(dpy, ee); /* may call exit */
-}
-
-int
-xerrordummy(Display *dpy, XErrorEvent *ee)
-{
- return 0;
-}
-
-/* Startup Error handler to check if another window manager
- * is already running. */
-int
-xerrorstart(Display *dpy, XErrorEvent *ee)
-{
- die("dwm: another window manager is already running");
- return -1;
-}
-
-void
-zoom(const Arg *arg)
-{
- Client *c = selmon->sel;
- if (arg && arg->v)
- c = (Client*)arg->v;
- if (!c)
- return;
-
- if (!c->mon->lt[c->mon->sellt]->arrange || !c || c->isfloating)
- return;
-
- if (c == nexttiled(selmon->clients) && !(c = nexttiled(c->next)))
- return;
- pop(c);
-}
-
-int
-main(int argc, char *argv[])
-{
- if (argc == 2 && !strcmp("-v", argv[1]))
- die("dwm-"VERSION);
- else if (argc != 1)
- die("usage: dwm [-v]");
- if (!setlocale(LC_CTYPE, "") || !XSupportsLocale())
- fputs("warning: no locale support\n", stderr);
- if (!(dpy = XOpenDisplay(NULL)))
- die("dwm: cannot open display");
- checkotherwm();
- autostart_exec();
- setup();
-#ifdef __OpenBSD__
- if (pledge("stdio rpath proc exec", NULL) == -1)
- die("pledge");
-#endif /* __OpenBSD__ */
- scan();
- run();
- cleanup();
- XCloseDisplay(dpy);
- if (restart)
- execvp(argv[0], argv);
- return EXIT_SUCCESS;
-}
-
diff --git a/flexipatch-finalizer b/flexipatch-finalizer
new file mode 160000
index 0000000..7c66a3d
--- /dev/null
+++ b/flexipatch-finalizer
@@ -0,0 +1 @@
+Subproject commit 7c66a3d0560d33d9d49b3e856859ef8a0af1fd6a
diff --git a/patch/attachx.c b/patch/attachx.c
deleted file mode 100644
index 5b9f7d9..0000000
--- a/patch/attachx.c
+++ /dev/null
@@ -1,27 +0,0 @@
-void
-attachx(Client *c)
-{
- Client *at;
-
- if (c->idx > 0) { /* then the client has a designated position in the client list */
- for (at = c->mon->clients; at; at = at->next) {
- if (c->idx < at->idx) {
- c->next = at;
- c->mon->clients = c;
- return;
- } else if (at->idx <= c->idx && (!at->next || c->idx <= at->next->idx)) {
- c->next = at->next;
- at->next = c;
- return;
- }
- }
- }
-
- if (!(c->mon->sel == NULL || c->mon->sel == c || c->mon->sel->isfloating)) {
- c->next = c->mon->sel->next;
- c->mon->sel->next = c;
- return;
- }
- attach(c); // master (default)
-}
-
diff --git a/patch/attachx.h b/patch/attachx.h
deleted file mode 100644
index e522d27..0000000
--- a/patch/attachx.h
+++ /dev/null
@@ -1,2 +0,0 @@
-static void attachx(Client *c);
-
diff --git a/patch/bar.c b/patch/bar.c
deleted file mode 100644
index 65e1a69..0000000
--- a/patch/bar.c
+++ /dev/null
@@ -1,39 +0,0 @@
-void
-barhover(XEvent *e, Bar *bar)
-{
- const BarRule *br;
- Monitor *m = bar->mon;
- XMotionEvent *ev = &e->xmotion;
- BarArg barg = { 0, 0, 0, 0 };
- int r;
-
- for (r = 0; r < LENGTH(barrules); r++) {
- br = &barrules[r];
- if (br->bar != bar->idx || (br->monitor == 'A' && m != selmon) || br->hoverfunc == NULL)
- continue;
- if (br->monitor != 'A' && br->monitor != -1 && br->monitor != bar->mon->num)
- continue;
- if (bar->x[r] > ev->x || ev->x > bar->x[r] + bar->w[r])
- continue;
-
- barg.x = ev->x - bar->x[r];
- barg.y = ev->y - bar->borderpx;
- barg.w = bar->w[r];
- barg.h = bar->bh - 2 * bar->borderpx;
-
- br->hoverfunc(bar, &barg, ev);
- break;
- }
-}
-
-Bar *
-wintobar(Window win)
-{
- Monitor *m;
- Bar *bar;
- for (m = mons; m; m = m->next)
- for (bar = m->bar; bar; bar = bar->next)
- if (bar->win == win)
- return bar;
- return NULL;
-}
diff --git a/patch/bar.h b/patch/bar.h
deleted file mode 100644
index 3e006dc..0000000
--- a/patch/bar.h
+++ /dev/null
@@ -1,2 +0,0 @@
-static void barhover(XEvent *e, Bar *bar);
-static Bar *wintobar(Window win);
diff --git a/patch/bar_dwmblocks.c b/patch/bar_dwmblocks.c
deleted file mode 100644
index 0a4b097..0000000
--- a/patch/bar_dwmblocks.c
+++ /dev/null
@@ -1,41 +0,0 @@
-static int statussig;
-pid_t statuspid = -1;
-
-pid_t
-getstatusbarpid()
-{
- char buf[32], *str = buf, *c;
- FILE *fp;
-
- if (statuspid > 0) {
- snprintf(buf, sizeof(buf), "/proc/%u/cmdline", statuspid);
- if ((fp = fopen(buf, "r"))) {
- fgets(buf, sizeof(buf), fp);
- while ((c = strchr(str, '/')))
- str = c + 1;
- fclose(fp);
- if (!strcmp(str, STATUSBAR))
- return statuspid;
- }
- }
- if (!(fp = popen("pgrep -o "STATUSBAR, "r")))
- return -1;
- fgets(buf, sizeof(buf), fp);
- pclose(fp);
- return strtol(buf, NULL, 10);
-}
-
-void
-sigstatusbar(const Arg *arg)
-{
- union sigval sv;
-
- if (!statussig)
- return;
- if ((statuspid = getstatusbarpid()) <= 0)
- return;
-
- sv.sival_int = arg->i;
- sigqueue(statuspid, SIGRTMIN+statussig, sv);
-}
-
diff --git a/patch/bar_dwmblocks.h b/patch/bar_dwmblocks.h
deleted file mode 100644
index 4db9467..0000000
--- a/patch/bar_dwmblocks.h
+++ /dev/null
@@ -1,3 +0,0 @@
-static int getstatusbarpid();
-static void sigstatusbar(const Arg *arg);
-
diff --git a/patch/bar_ewmhtags.c b/patch/bar_ewmhtags.c
deleted file mode 100644
index 46ee5e4..0000000
--- a/patch/bar_ewmhtags.c
+++ /dev/null
@@ -1,52 +0,0 @@
-void
-setcurrentdesktop(void)
-{
- long data[] = { 0 };
- XChangeProperty(dpy, root, netatom[NetCurrentDesktop], XA_CARDINAL, 32, PropModeReplace, (unsigned char *)data, 1);
-}
-
-void
-setdesktopnames(void)
-{
- int i;
- XTextProperty text;
- char *tags[NUMTAGS];
- for (i = 0; i < NUMTAGS; i++)
- tags[i] = tagicon(selmon, i);
- Xutf8TextListToTextProperty(dpy, tags, NUMTAGS, XUTF8StringStyle, &text);
- XSetTextProperty(dpy, root, &text, netatom[NetDesktopNames]);
-}
-
-void
-setfloatinghint(Client *c)
-{
- Atom target = XInternAtom(dpy, "_IS_FLOATING", 0);
- unsigned int floating[1] = {c->isfloating};
- XChangeProperty(dpy, c->win, target, XA_CARDINAL, 32, PropModeReplace, (unsigned char *)floating, 1);
-}
-
-void
-setnumdesktops(void)
-{
- long data[] = { NUMTAGS };
- XChangeProperty(dpy, root, netatom[NetNumberOfDesktops], XA_CARDINAL, 32, PropModeReplace, (unsigned char *)data, 1);
-}
-
-void
-setviewport(void)
-{
- long data[] = { 0, 0 };
- XChangeProperty(dpy, root, netatom[NetDesktopViewport], XA_CARDINAL, 32, PropModeReplace, (unsigned char *)data, 2);
-}
-
-void
-updatecurrentdesktop(void)
-{
- long rawdata[] = { selmon->tagset[selmon->seltags] };
- int i = 0;
- while (*rawdata >> (i + 1)) {
- i++;
- }
- long data[] = { i };
- XChangeProperty(dpy, root, netatom[NetCurrentDesktop], XA_CARDINAL, 32, PropModeReplace, (unsigned char *)data, 1);
-}
diff --git a/patch/bar_ewmhtags.h b/patch/bar_ewmhtags.h
deleted file mode 100644
index 4d6a74b..0000000
--- a/patch/bar_ewmhtags.h
+++ /dev/null
@@ -1,7 +0,0 @@
-static void setcurrentdesktop(void);
-static void setdesktopnames(void);
-static void setfloatinghint(Client *c);
-static void setnumdesktops(void);
-static void setviewport(void);
-static void updatecurrentdesktop(void);
-
diff --git a/patch/bar_indicators.c b/patch/bar_indicators.c
deleted file mode 100644
index b003fc8..0000000
--- a/patch/bar_indicators.c
+++ /dev/null
@@ -1,104 +0,0 @@
-/* Indicator properties, you can override these in your config.h if you want. */
-#ifndef TAGSINDICATOR
-#define TAGSINDICATOR 1 // 0 = off, 1 = on if >1 client/view tag, 2 = always on
-#endif
-#ifndef TAGSPX
-#define TAGSPX 5 // # pixels for tag grid boxes
-#endif
-#ifndef TAGSROWS
-#define TAGSROWS 3 // # rows in tag grid (9 tags, e.g. 3x3)
-#endif
-
-void
-drawindicator(Monitor *m, Client *c, unsigned int occ, int x, int y, int w, int h, unsigned int tag, int filled, int invert, int type)
-{
- int i, boxw, boxs, indn = 0;
- if (!(occ & 1 << tag) || type == INDICATOR_NONE)
- return;
-
- boxs = drw->fonts->h / 9;
- boxw = drw->fonts->h / 6 + 2;
- if (filled == -1)
- filled = m == selmon && m->sel && m->sel->tags & 1 << tag;
-
- switch (type) {
- default:
- case INDICATOR_TOP_LEFT_SQUARE:
- drw_rect(drw, x + boxs, y + boxs, boxw, boxw, filled, invert);
- break;
- case INDICATOR_TOP_LEFT_LARGER_SQUARE:
- drw_rect(drw, x + boxs + 2, y + boxs+1, boxw+1, boxw+1, filled, invert);
- break;
- case INDICATOR_TOP_BAR:
- drw_rect(drw, x + boxw, y, w - ( 2 * boxw + 1), boxw/2, filled, invert);
- break;
- case INDICATOR_TOP_BAR_SLIM:
- drw_rect(drw, x + boxw, y, w - ( 2 * boxw + 1), 1, 0, invert);
- break;
- case INDICATOR_BOTTOM_BAR:
- drw_rect(drw, x + boxw, y + h - boxw/2, w - ( 2 * boxw + 1), boxw/2, filled, invert);
- break;
- case INDICATOR_BOTTOM_BAR_SLIM:
- drw_rect(drw, x + boxw, y + h - 1, w - ( 2 * boxw + 1), 1, 0, invert);
- break;
- case INDICATOR_BOX:
- drw_rect(drw, x + boxw, y, w - 2 * boxw, h, 0, invert);
- break;
- case INDICATOR_BOX_WIDER:
- drw_rect(drw, x + boxw/2, y, w - boxw, h, 0, invert);
- break;
- case INDICATOR_BOX_FULL:
- drw_rect(drw, x, y, w - 2, h, 0, invert);
- break;
- case INDICATOR_CLIENT_DOTS:
- for (c = m->clients; c; c = c->next) {
- if (c->tags & (1 << tag)) {
- drw_rect(drw, x, 1 + (indn * 2), m->sel == c ? 6 : 1, 1, 1, invert);
- indn++;
- }
- if (h <= 1 + (indn * 2)) {
- indn = 0;
- x += 2;
- }
- }
- break;
- case INDICATOR_RIGHT_TAGS:
- if (!c)
- break;
- for (i = 0; i < NUMTAGS; i++) {
- drw_rect(drw,
- ( x + w - 2 - ((NUMTAGS / TAGSROWS) * TAGSPX)
- - (i % (NUMTAGS/TAGSROWS)) + ((i % (NUMTAGS / TAGSROWS)) * TAGSPX)
- ),
- ( y + 2 + ((i / (NUMTAGS/TAGSROWS)) * TAGSPX)
- - ((i / (NUMTAGS/TAGSROWS)))
- ),
- TAGSPX, TAGSPX, (c->tags >> i) & 1, 0
- );
- }
- break;
- case INDICATOR_PLUS_AND_LARGER_SQUARE:
- boxs += 2;
- boxw += 2;
- /* falls through */
- case INDICATOR_PLUS_AND_SQUARE:
- drw_rect(drw, x + boxs, y + boxs, boxw % 2 ? boxw : boxw + 1, boxw % 2 ? boxw : boxw + 1, filled, invert);
- /* falls through */
- case INDICATOR_PLUS:
- if (!(boxw % 2))
- boxw += 1;
- drw_rect(drw, x + boxs + boxw / 2, y + boxs, 1, boxw, filled, invert); // |
- drw_rect(drw, x + boxs, y + boxs + boxw / 2, boxw + 1, 1, filled, invert); // ‒
- break;
- }
-}
-
-void
-drawstateindicator(Monitor *m, Client *c, unsigned int occ, int x, int y, int w, int h, unsigned int tag, int filled, int invert)
-{
- if (c->isfloating)
- drawindicator(m, c, occ, x, y, w, h, tag, filled, invert, floatindicatortype);
- else
- drawindicator(m, c, occ, x, y, w, h, tag, filled, invert, tiledindicatortype);
-}
-
diff --git a/patch/bar_indicators.h b/patch/bar_indicators.h
deleted file mode 100644
index c66e4f0..0000000
--- a/patch/bar_indicators.h
+++ /dev/null
@@ -1,21 +0,0 @@
-enum {
- INDICATOR_NONE,
- INDICATOR_TOP_LEFT_SQUARE,
- INDICATOR_TOP_LEFT_LARGER_SQUARE,
- INDICATOR_TOP_BAR,
- INDICATOR_TOP_BAR_SLIM,
- INDICATOR_BOTTOM_BAR,
- INDICATOR_BOTTOM_BAR_SLIM,
- INDICATOR_BOX,
- INDICATOR_BOX_WIDER,
- INDICATOR_BOX_FULL,
- INDICATOR_CLIENT_DOTS,
- INDICATOR_RIGHT_TAGS,
- INDICATOR_PLUS,
- INDICATOR_PLUS_AND_SQUARE,
- INDICATOR_PLUS_AND_LARGER_SQUARE,
-};
-
-static void drawindicator(Monitor *m, Client *c, unsigned int occ, int x, int y, int w, int h, unsigned int tag, int filled, int invert, int type);
-static void drawstateindicator(Monitor *m, Client *c, unsigned int occ, int x, int y, int w, int h, unsigned int tag, int filled, int invert);
-
diff --git a/patch/bar_ltsymbol.c b/patch/bar_ltsymbol.c
deleted file mode 100644
index 1004378..0000000
--- a/patch/bar_ltsymbol.c
+++ /dev/null
@@ -1,17 +0,0 @@
-int
-width_ltsymbol(Bar *bar, BarArg *a)
-{
- return TEXTW(bar->mon->ltsymbol);
-}
-
-int
-draw_ltsymbol(Bar *bar, BarArg *a)
-{
- return drw_text(drw, a->x, a->y, a->w, a->h, lrpad / 2, bar->mon->ltsymbol, 0, False);
-}
-
-int
-click_ltsymbol(Bar *bar, Arg *arg, BarArg *a)
-{
- return ClkLtSymbol;
-}
diff --git a/patch/bar_ltsymbol.h b/patch/bar_ltsymbol.h
deleted file mode 100644
index 4188584..0000000
--- a/patch/bar_ltsymbol.h
+++ /dev/null
@@ -1,3 +0,0 @@
-static int width_ltsymbol(Bar *bar, BarArg *a);
-static int draw_ltsymbol(Bar *bar, BarArg *a);
-static int click_ltsymbol(Bar *bar, Arg *arg, BarArg *a);
diff --git a/patch/bar_status.c b/patch/bar_status.c
deleted file mode 100644
index 19ff219..0000000
--- a/patch/bar_status.c
+++ /dev/null
@@ -1,18 +0,0 @@
-int
-width_status(Bar *bar, BarArg *a)
-{
- return TEXTWM(stext);
-}
-
-int
-draw_status(Bar *bar, BarArg *a)
-{
- return drw_text(drw, a->x, a->y, a->w, a->h, lrpad / 2, stext, 0, True);
-}
-
-int
-click_status(Bar *bar, Arg *arg, BarArg *a)
-{
- return ClkStatusText;
-}
-
diff --git a/patch/bar_status.h b/patch/bar_status.h
deleted file mode 100644
index c580597..0000000
--- a/patch/bar_status.h
+++ /dev/null
@@ -1,4 +0,0 @@
-static int width_status(Bar *bar, BarArg *a);
-static int draw_status(Bar *bar, BarArg *a);
-static int click_status(Bar *bar, Arg *arg, BarArg *a);
-
diff --git a/patch/bar_statuscmd.c b/patch/bar_statuscmd.c
deleted file mode 100644
index 2e74f9f..0000000
--- a/patch/bar_statuscmd.c
+++ /dev/null
@@ -1,44 +0,0 @@
-int
-click_statuscmd(Bar *bar, Arg *arg, BarArg *a)
-{
- return click_statuscmd_text(arg, a->x, rawstext);
-}
-
-int
-click_statuscmd_text(Arg *arg, int rel_x, char *text)
-{
- int i = -1;
- int x = 0;
- char ch;
- statussig = -1;
- while (text[++i]) {
- if ((unsigned char)text[i] < ' ') {
- ch = text[i];
- text[i] = '\0';
- x += TEXTWM(text) - lrpad;
- text[i] = ch;
- text += i+1;
- i = -1;
- if (x >= rel_x && statussig != -1)
- break;
- statussig = ch;
- }
- }
- if (statussig == -1)
- statussig = 0;
- return ClkStatusText;
-}
-
-void
-copyvalidchars(char *text, char *rawtext)
-{
- int i = -1, j = 0;
-
- while (rawtext[++i]) {
- if ((unsigned char)rawtext[i] >= ' ') {
- text[j++] = rawtext[i];
- }
- }
- text[j] = '\0';
-}
-
diff --git a/patch/bar_statuscmd.h b/patch/bar_statuscmd.h
deleted file mode 100644
index 1ec24a6..0000000
--- a/patch/bar_statuscmd.h
+++ /dev/null
@@ -1,9 +0,0 @@
-static int click_statuscmd(Bar *bar, Arg *arg, BarArg *a);
-static int click_statuscmd_text(Arg *arg, int rel_x, char *text);
-static void copyvalidchars(char *text, char *rawtext);
-
-typedef struct {
- const char *cmd;
- int id;
-} StatusCmd;
-
diff --git a/patch/bar_tagicons.c b/patch/bar_tagicons.c
deleted file mode 100644
index 57d1629..0000000
--- a/patch/bar_tagicons.c
+++ /dev/null
@@ -1,9 +0,0 @@
-char *
-tagicon(Monitor *m, int tag)
-{
- int tagindex = tag + NUMTAGS * m->num;
- if (tagindex >= LENGTH(tagicons[DEFAULT_TAGS]))
- tagindex = tagindex % LENGTH(tagicons[DEFAULT_TAGS]);
- return tagicons[DEFAULT_TAGS][tagindex];
-}
-
diff --git a/patch/bar_tagicons.h b/patch/bar_tagicons.h
deleted file mode 100644
index 16fad2a..0000000
--- a/patch/bar_tagicons.h
+++ /dev/null
@@ -1,8 +0,0 @@
-enum {
- DEFAULT_TAGS,
- ALTERNATIVE_TAGS,
- ALT_TAGS_DECORATION,
-};
-
-static char * tagicon(Monitor *m, int tag);
-
diff --git a/patch/bar_tags.c b/patch/bar_tags.c
deleted file mode 100644
index 8aa37b2..0000000
--- a/patch/bar_tags.c
+++ /dev/null
@@ -1,81 +0,0 @@
-int
-width_tags(Bar *bar, BarArg *a)
-{
- int w, i;
- Client *c;
- unsigned int occ = 0;
- for (c = bar->mon->clients; c; c = c->next)
- occ |= c->tags == 255 ? 0 : c->tags;
-
- for (w = 0, i = 0; i < NUMTAGS; i++) {
- if (!(occ & 1 << i || bar->mon->tagset[bar->mon->seltags] & 1 << i))
- continue;
- w += TEXTW(tagicon(bar->mon, i));
- }
- return w;
-}
-
-int
-draw_tags(Bar *bar, BarArg *a)
-{
- int invert;
- int w, x = a->x;
- unsigned int i, occ = 0, urg = 0;
- char *icon;
- Client *c;
- Monitor *m = bar->mon;
-
- for (c = m->clients; c; c = c->next) {
- occ |= c->tags == 255 ? 0 : c->tags;
- if (c->isurgent)
- urg |= c->tags;
- }
- for (i = 0; i < NUMTAGS; i++) {
- /* do not draw vacant tags */
- if (!(occ & 1 << i || m->tagset[m->seltags] & 1 << i))
- continue;
-
- icon = tagicon(bar->mon, i);
- invert = 0;
- w = TEXTW(icon);
- drw_setscheme(drw, scheme[
- m->tagset[m->seltags] & 1 << i
- ? SchemeTagsSel
- : urg & 1 << i
- ? SchemeUrg
- : SchemeTagsNorm
- ]);
- drw_text(drw, x, a->y, w, a->h, lrpad / 2, icon, invert, False);
- drawindicator(m, NULL, occ, x, a->y, w, a->h, i, -1, invert, tagindicatortype);
- x += w;
- }
-
- return 1;
-}
-
-int
-click_tags(Bar *bar, Arg *arg, BarArg *a)
-{
- int i = 0, x = 0;
- Client *c;
- unsigned int occ = 0;
- for (c = bar->mon->clients; c; c = c->next)
- occ |= c->tags == 255 ? 0 : c->tags;
-
- do {
- if (!(occ & 1 << i || bar->mon->tagset[bar->mon->seltags] & 1 << i))
- continue;
- x += TEXTW(tagicon(bar->mon, i));
- } while (a->x >= x && ++i < NUMTAGS);
- if (i < NUMTAGS) {
- arg->ui = 1 << i;
- }
- return ClkTagBar;
-}
-
-int
-hover_tags(Bar *bar, BarArg *a, XMotionEvent *ev)
-{
-
- return 1;
-}
diff --git a/patch/bar_tags.h b/patch/bar_tags.h
deleted file mode 100644
index 70040d2..0000000
--- a/patch/bar_tags.h
+++ /dev/null
@@ -1,4 +0,0 @@
-static int width_tags(Bar *bar, BarArg *a);
-static int draw_tags(Bar *bar, BarArg *a);
-static int click_tags(Bar *bar, Arg *arg, BarArg *a);
-static int hover_tags(Bar *bar, BarArg *a, XMotionEvent *ev);
diff --git a/patch/bar_wintitle.c b/patch/bar_wintitle.c
deleted file mode 100644
index 4468f93..0000000
--- a/patch/bar_wintitle.c
+++ /dev/null
@@ -1,49 +0,0 @@
-int
-width_wintitle(Bar *bar, BarArg *a)
-{
- return a->w;
-}
-
-int
-draw_wintitle(Bar *bar, BarArg *a)
-{
- int x = a->x, w = a->w;
- Monitor *m = bar->mon;
- Client *c = m->sel;
-
- if (!c) {
- drw_setscheme(drw, scheme[SchemeTitleNorm]);
- drw_rect(drw, x, a->y, w, a->h, 1, 1);
- return 0;
- }
-
- int tpad = lrpad / 2;
- int tx = x;
- int tw = w;
-
- drw_setscheme(drw, scheme[m == selmon ? SchemeTitleSel : SchemeTitleNorm]);
- XSetErrorHandler(xerrordummy);
-
- if (w <= TEXTW("A") - lrpad + tpad) // reduce text padding if wintitle is too small
- tpad = (w - TEXTW("A") + lrpad < 0 ? 0 : (w - TEXTW("A") + lrpad) / 2);
-
- XSetForeground(drw->dpy, drw->gc, drw->scheme[ColBg].pixel);
- XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, a->y, w, a->h);
-
- tx += tpad;
- tw -= lrpad;
-
- drw_text(drw, tx, a->y, tw, a->h, 0, c->name, 0, False);
-
- XSync(dpy, False);
- XSetErrorHandler(xerror);
- drawstateindicator(m, c, 1, x, a->y, w, a->h, 0, 0, c->isfixed);
- return 1;
-}
-
-int
-click_wintitle(Bar *bar, Arg *arg, BarArg *a)
-{
- return ClkWinTitle;
-}
-
diff --git a/patch/bar_wintitle.h b/patch/bar_wintitle.h
deleted file mode 100644
index 7e8cce5..0000000
--- a/patch/bar_wintitle.h
+++ /dev/null
@@ -1,4 +0,0 @@
-static int width_wintitle(Bar *bar, BarArg *a);
-static int draw_wintitle(Bar *bar, BarArg *a);
-static int click_wintitle(Bar *bar, Arg *arg, BarArg *a);
-
diff --git a/patch/cool_autostart.c b/patch/cool_autostart.c
deleted file mode 100644
index 848f5ab..0000000
--- a/patch/cool_autostart.c
+++ /dev/null
@@ -1,37 +0,0 @@
-/* dwm will keep pid's of processes from autostart array and kill them at quit */
-static pid_t *autostart_pids;
-static size_t autostart_len;
-
-/* execute command from autostart array */
-static void
-autostart_exec()
-{
- const char *const *p;
- struct sigaction sa;
- size_t i = 0;
-
- /* count entries */
- for (p = autostart; *p; autostart_len++, p++)
- while (*++p);
-
- autostart_pids = malloc(autostart_len * sizeof(pid_t));
- for (p = autostart; *p; i++, p++) {
- if ((autostart_pids[i] = fork()) == 0) {
- setsid();
-
- /* Restore SIGCHLD sighandler to default before spawning a program */
- sigemptyset(&sa.sa_mask);
- sa.sa_flags = 0;
- sa.sa_handler = SIG_DFL;
- sigaction(SIGCHLD, &sa, NULL);
-
- execvp(*p, (char *const *)p);
- fprintf(stderr, "dwm: execvp %s\n", *p);
- perror(" failed");
- _exit(EXIT_FAILURE);
- }
- /* skip arguments */
- while (*++p);
- }
-}
-
diff --git a/patch/cool_autostart.h b/patch/cool_autostart.h
deleted file mode 100644
index 5534d99..0000000
--- a/patch/cool_autostart.h
+++ /dev/null
@@ -1,2 +0,0 @@
-static void autostart_exec(void);
-
diff --git a/patch/floatpos.c b/patch/floatpos.c
deleted file mode 100644
index d935d23..0000000
--- a/patch/floatpos.c
+++ /dev/null
@@ -1,179 +0,0 @@
-void
-floatpos(const Arg *arg)
-{
- Client *c = selmon->sel;
-
- if (!c || (selmon->lt[selmon->sellt]->arrange && !c->isfloating))
- return;
-
- setfloatpos(c, (char *)arg->v);
- resizeclient(c, c->x, c->y, c->w, c->h);
-
-}
-
-void
-setfloatpos(Client *c, const char *floatpos)
-{
- char xCh, yCh, wCh, hCh;
- int x, y, w, h, wx, ww, wy, wh;
-
- if (!c || !floatpos)
- return;
- if (selmon->lt[selmon->sellt]->arrange && !c->isfloating)
- return;
-
- switch(sscanf(floatpos, "%d%c %d%c %d%c %d%c", &x, &xCh, &y, &yCh, &w, &wCh, &h, &hCh)) {
- case 4:
- if (xCh == 'w' || xCh == 'W') {
- w = x; wCh = xCh;
- h = y; hCh = yCh;
- x = -1; xCh = 'C';
- y = -1; yCh = 'C';
- } else if (xCh == 'p' || xCh == 'P') {
- w = x; wCh = xCh;
- h = y; hCh = yCh;
- x = 0; xCh = 'G';
- y = 0; yCh = 'G';
- } else if (xCh == 'm' || xCh == 'M') {
- getrootptr(&x, &y);
- } else {
- w = 0; wCh = 0;
- h = 0; hCh = 0;
- }
- break;
- case 8:
- if (xCh == 'm' || xCh == 'M')
- getrootptr(&x, &y);
- break;
- default:
- return;
- }
-
- wx = c->mon->wx;
- wy = c->mon->wy;
- ww = c->mon->ww;
- wh = c->mon->wh;
-
- getfloatpos(x, xCh, w, wCh, wx, ww, c->x, c->w, c->bw, floatposgrid_x, &c->x, &c->w);
- getfloatpos(y, yCh, h, hCh, wy, wh, c->y, c->h, c->bw, floatposgrid_y, &c->y, &c->h);
-}
-
-/* p - position, s - size, cp and cs represents current position and size */
-void
-getfloatpos(int pos, char pCh, int size, char sCh, int min_p, int max_s, int cp, int cs, int cbw, int defgrid, int *out_p, int *out_s)
-{
- int abs_p, abs_s, i, delta, rest;
-
- abs_p = pCh == 'A' || pCh == 'a';
- abs_s = sCh == 'A' || sCh == 'a';
-
- cs += 2*cbw;
-
- switch(pCh) {
- case 'A': // absolute position
- cp = pos;
- break;
- case 'a': // absolute relative position
- cp += pos;
- break;
- case 'y':
- case 'x': // client relative position
- cp = MIN(cp + pos, min_p + max_s);
- break;
- case 'Y':
- case 'X': // client position relative to monitor
- cp = min_p + MIN(pos, max_s);
- break;
- case 'S': // fixed client position (sticky)
- case 'C': // fixed client position (center)
- case 'Z': // fixed client right-hand position (position + size)
- if (pos == -1)
- break;
- pos = MAX(MIN(pos, max_s), 0);
- if (pCh == 'Z')
- cs = abs((cp + cs) - (min_p + pos));
- else if (pCh == 'C')
- cs = abs((cp + cs / 2) - (min_p + pos));
- else
- cs = abs(cp - (min_p + pos));
- cp = min_p + pos;
- sCh = 0; // size determined by position, override defined size
- break;
- case 'G': // grid
- if (pos <= 0)
- pos = defgrid; // default configurable
- if (size == 0 || pos < 2 || (sCh != 'p' && sCh != 'P'))
- break;
- delta = (max_s - cs) / (pos - 1);
- rest = max_s - cs - delta * (pos - 1);
- if (sCh == 'P') {
- if (size < 1 || size > pos)
- break;
- cp = min_p + delta * (size - 1);
- } else {
- for (i = 0; i < pos && cp >= min_p + delta * i + (i > pos - rest ? i + rest - pos + 1 : 0); i++);
- cp = min_p + delta * (MAX(MIN(i + size, pos), 1) - 1) + (i > pos - rest ? i + rest - pos + 1 : 0);
- }
- break;
- }
-
- switch(sCh) {
- case 'A': // absolute size
- cs = size;
- break;
- case 'a': // absolute relative size
- cs = MAX(1, cs + size);
- break;
- case '%': // client size percentage in relation to monitor window area size
- if (size <= 0)
- break;
- size = max_s * MIN(size, 100) / 100;
- /* falls through */
- case 'h':
- case 'w': // size relative to client
- if (sCh == 'w' || sCh == 'h') {
- if (size == 0)
- break;
- size += cs;
- }
- /* falls through */
- case 'H':
- case 'W': // normal size, position takes precedence
- if (pCh == 'S' && cp + size > min_p + max_s)
- size = min_p + max_s - cp;
- else if (size > max_s)
- size = max_s;
-
- if (pCh == 'C') { // fixed client center, expand or contract client
- delta = size - cs;
- if (delta < 0 || (cp - delta / 2 + size <= min_p + max_s))
- cp -= delta / 2;
- else if (cp - delta / 2 < min_p)
- cp = min_p;
- else if (delta)
- cp = min_p + max_s;
- } else if (pCh == 'Z')
- cp -= size - cs;
-
- cs = size;
- break;
- }
-
- if (pCh == '%') // client mid-point position in relation to monitor window area size
- cp = min_p + max_s * MAX(MIN(pos, 100), 0) / 100 - (cs) / 2;
- if (pCh == 'm' || pCh == 'M')
- cp = pos - cs / 2;
-
- if (!abs_p && cp < min_p)
- cp = min_p;
- if (cp + cs > min_p + max_s && !(abs_p && abs_s)) {
- if (abs_p || cp == min_p)
- cs = min_p + max_s - cp;
- else
- cp = min_p + max_s - cs;
- }
-
- *out_p = cp;
- *out_s = MAX(cs - 2*cbw, 1);
-}
-
diff --git a/patch/floatpos.h b/patch/floatpos.h
deleted file mode 100644
index ecdcf0b..0000000
--- a/patch/floatpos.h
+++ /dev/null
@@ -1,4 +0,0 @@
-static void floatpos(const Arg *arg);
-static void setfloatpos(Client *c, const char *floatpos);
-static void getfloatpos(int pos, char pCh, int size, char sCh, int min_p, int max_s, int cp, int cs, int cbw, int defgrid, int *out_p, int *out_s);
-
diff --git a/patch/include.c b/patch/include.c
deleted file mode 100644
index f376a05..0000000
--- a/patch/include.c
+++ /dev/null
@@ -1,31 +0,0 @@
-/* Bar functionality */
-#include "bar_indicators.c"
-#include "bar_tagicons.c"
-#include "bar.c"
-
-#include "bar_dwmblocks.c"
-#include "bar_ewmhtags.c"
-#include "bar_ltsymbol.c"
-#include "bar_status.c"
-#include "bar_statuscmd.c"
-#include "bar_tags.c"
-#include "bar_wintitle.c"
-
-/* Other patches */
-#include "attachx.c"
-#include "cool_autostart.c"
-#include "floatpos.c"
-#include "pertag.c"
-#include "restartsig.c"
-#include "renamed_scratchpads.c"
-#include "sizehints_ruled.c"
-#include "stacker.c"
-#include "togglefullscreen.c"
-#include "unfloatvisible.c"
-#include "seamless_restart.c"
-/* Layouts */
-#include "layout_facts.c"
-#include "layout_bstack.c"
-#include "layout_gapplessgrid.c"
-#include "layout_tile.c"
-
diff --git a/patch/include.h b/patch/include.h
deleted file mode 100644
index f9dbd4d..0000000
--- a/patch/include.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/* Bar functionality */
-#include "bar_indicators.h"
-#include "bar_tagicons.h"
-#include "bar.h"
-
-#include "bar_dwmblocks.h"
-#include "bar_ewmhtags.h"
-#include "bar_ltsymbol.h"
-#include "bar_status.h"
-#include "bar_statuscmd.h"
-#include "bar_tags.h"
-#include "bar_wintitle.h"
-
-/* Other patches */
-#include "attachx.h"
-#include "cool_autostart.h"
-#include "floatpos.h"
-#include "pertag.h"
-#include "restartsig.h"
-#include "renamed_scratchpads.h"
-#include "seamless_restart.h"
-#include "sizehints_ruled.h"
-#include "stacker.h"
-#include "togglefullscreen.h"
-#include "unfloatvisible.h"
-/* Layouts */
-#include "layout_bstack.h"
-#include "layout_gapplessgrid.h"
-#include "layout_tile.h"
-
diff --git a/patch/ipc/IPCClient.h b/patch/ipc/IPCClient.h
deleted file mode 100644
index ee93030..0000000
--- a/patch/ipc/IPCClient.h
+++ /dev/null
@@ -1,62 +0,0 @@
-#ifndef IPC_CLIENT_H_
-#define IPC_CLIENT_H_
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/epoll.h>
-
-typedef struct IPCClient IPCClient;
-/**
- * This structure contains the details of an IPC Client and pointers for a
- * linked list
- */
-struct IPCClient {
- int fd;
- int subscriptions;
-
- char *buffer;
- uint32_t buffer_size;
-
- struct epoll_event event;
- IPCClient *next;
- IPCClient *prev;
-};
-
-typedef IPCClient *IPCClientList;
-
-/**
- * Allocate memory for new IPCClient with the specified file descriptor and
- * initialize struct.
- *
- * @param fd File descriptor of IPC client
- *
- * @return Address to allocated IPCClient struct
- */
-IPCClient *ipc_client_new(int fd);
-
-/**
- * Add an IPC Client to the specified list
- *
- * @param list Address of the list to add the client to
- * @param nc Address of the IPCClient
- */
-void ipc_list_add_client(IPCClientList *list, IPCClient *nc);
-
-/**
- * Remove an IPCClient from the specified list
- *
- * @param list Address of the list to remove the client from
- * @param c Address of the IPCClient
- */
-void ipc_list_remove_client(IPCClientList *list, IPCClient *c);
-
-/**
- * Get an IPCClient from the specified IPCClient list
- *
- * @param list List to remove the client from
- * @param fd File descriptor of the IPCClient
- */
-IPCClient *ipc_list_get_client(IPCClientList list, int fd);
-
-#endif // IPC_CLIENT_H_
-
diff --git a/patch/ipc/dwm-msg.c b/patch/ipc/dwm-msg.c
deleted file mode 100644
index ca1e1a4..0000000
--- a/patch/ipc/dwm-msg.c
+++ /dev/null
@@ -1,549 +0,0 @@
-#include <ctype.h>
-#include <errno.h>
-#include <inttypes.h>
-#include <stdarg.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <unistd.h>
-#include <yajl/yajl_gen.h>
-
-#define IPC_MAGIC "DWM-IPC"
-// clang-format off
-#define IPC_MAGIC_ARR { 'D', 'W', 'M', '-', 'I', 'P', 'C' }
-// clang-format on
-#define IPC_MAGIC_LEN 7 // Not including null char
-
-#define IPC_EVENT_TAG_CHANGE "tag_change_event"
-#define IPC_EVENT_CLIENT_FOCUS_CHANGE "client_focus_change_event"
-#define IPC_EVENT_LAYOUT_CHANGE "layout_change_event"
-#define IPC_EVENT_MONITOR_FOCUS_CHANGE "monitor_focus_change_event"
-#define IPC_EVENT_FOCUSED_TITLE_CHANGE "focused_title_change_event"
-#define IPC_EVENT_FOCUSED_STATE_CHANGE "focused_state_change_event"
-
-#define YSTR(str) yajl_gen_string(gen, (unsigned char *)str, strlen(str))
-#define YINT(num) yajl_gen_integer(gen, num)
-#define YDOUBLE(num) yajl_gen_double(gen, num)
-#define YBOOL(v) yajl_gen_bool(gen, v)
-#define YNULL() yajl_gen_null(gen)
-#define YARR(body) \
- { \
- yajl_gen_array_open(gen); \
- body; \
- yajl_gen_array_close(gen); \
- }
-#define YMAP(body) \
- { \
- yajl_gen_map_open(gen); \
- body; \
- yajl_gen_map_close(gen); \
- }
-
-typedef unsigned long Window;
-
-const char *DEFAULT_SOCKET_PATH = "/tmp/dwm.sock";
-static int sock_fd = -1;
-static unsigned int ignore_reply = 0;
-
-typedef enum IPCMessageType {
- IPC_TYPE_RUN_COMMAND = 0,
- IPC_TYPE_GET_MONITORS = 1,
- IPC_TYPE_GET_TAGS = 2,
- IPC_TYPE_GET_LAYOUTS = 3,
- IPC_TYPE_GET_DWM_CLIENT = 4,
- IPC_TYPE_SUBSCRIBE = 5,
- IPC_TYPE_EVENT = 6
-} IPCMessageType;
-
-// Every IPC message must begin with this
-typedef struct dwm_ipc_header {
- uint8_t magic[IPC_MAGIC_LEN];
- uint32_t size;
- uint8_t type;
-} __attribute((packed)) dwm_ipc_header_t;
-
-static int
-recv_message(uint8_t *msg_type, uint32_t *reply_size, uint8_t **reply)
-{
- uint32_t read_bytes = 0;
- const int32_t to_read = sizeof(dwm_ipc_header_t);
- char header[to_read];
- char *walk = header;
-
- // Try to read header
- while (read_bytes < to_read) {
- ssize_t n = read(sock_fd, header + read_bytes, to_read - read_bytes);
-
- if (n == 0) {
- if (read_bytes == 0) {
- fprintf(stderr, "Unexpectedly reached EOF while reading header.");
- fprintf(stderr,
- "Read %" PRIu32 " bytes, expected %" PRIu32 " total bytes.\n",
- read_bytes, to_read);
- return -2;
- } else {
- fprintf(stderr, "Unexpectedly reached EOF while reading header.");
- fprintf(stderr,
- "Read %" PRIu32 " bytes, expected %" PRIu32 " total bytes.\n",
- read_bytes, to_read);
- return -3;
- }
- } else if (n == -1) {
- return -1;
- }
-
- read_bytes += n;
- }
-
- // Check if magic string in header matches
- if (memcmp(walk, IPC_MAGIC, IPC_MAGIC_LEN) != 0) {
- fprintf(stderr, "Invalid magic string. Got '%.*s', expected '%s'\n",
- IPC_MAGIC_LEN, walk, IPC_MAGIC);
- return -3;
- }
-
- walk += IPC_MAGIC_LEN;
-
- // Extract reply size
- memcpy(reply_size, walk, sizeof(uint32_t));
- walk += sizeof(uint32_t);
-
- // Extract message type
- memcpy(msg_type, walk, sizeof(uint8_t));
- walk += sizeof(uint8_t);
-
- (*reply) = malloc(*reply_size);
-
- // Extract payload
- read_bytes = 0;
- while (read_bytes < *reply_size) {
- ssize_t n = read(sock_fd, *reply + read_bytes, *reply_size - read_bytes);
-
- if (n == 0) {
- fprintf(stderr, "Unexpectedly reached EOF while reading payload.");
- fprintf(stderr, "Read %" PRIu32 " bytes, expected %" PRIu32 " bytes.\n",
- read_bytes, *reply_size);
- free(*reply);
- return -2;
- } else if (n == -1) {
- if (errno == EINTR || errno == EAGAIN) continue;
- free(*reply);
- return -1;
- }
-
- read_bytes += n;
- }
-
- return 0;
-}
-
-static int
-read_socket(IPCMessageType *msg_type, uint32_t *msg_size, char **msg)
-{
- int ret = -1;
-
- while (ret != 0) {
- ret = recv_message((uint8_t *)msg_type, msg_size, (uint8_t **)msg);
-
- if (ret < 0) {
- // Try again (non-fatal error)
- if (ret == -1 && (errno == EINTR || errno == EAGAIN)) continue;
-
- fprintf(stderr, "Error receiving response from socket. ");
- fprintf(stderr, "The connection might have been lost.\n");
- exit(2);
- }
- }
-
- return 0;
-}
-
-static ssize_t
-write_socket(const void *buf, size_t count)
-{
- size_t written = 0;
-
- while (written < count) {
- const ssize_t n =
- write(sock_fd, ((uint8_t *)buf) + written, count - written);
-
- if (n == -1) {
- if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR)
- continue;
- else
- return n;
- }
- written += n;
- }
- return written;
-}
-
-static void
-connect_to_socket()
-{
- struct sockaddr_un addr;
-
- int sock = socket(AF_UNIX, SOCK_STREAM, 0);
-
- // Initialize struct to 0
- memset(&addr, 0, sizeof(struct sockaddr_un));
-
- addr.sun_family = AF_UNIX;
- strcpy(addr.sun_path, DEFAULT_SOCKET_PATH);
-
- connect(sock, (const struct sockaddr *)&addr, sizeof(struct sockaddr_un));
-
- sock_fd = sock;
-}
-
-static int
-send_message(IPCMessageType msg_type, uint32_t msg_size, uint8_t *msg)
-{
- dwm_ipc_header_t header = {
- .magic = IPC_MAGIC_ARR, .size = msg_size, .type = msg_type};
-
- size_t header_size = sizeof(dwm_ipc_header_t);
- size_t total_size = header_size + msg_size;
-
- uint8_t buffer[total_size];
-
- // Copy header to buffer
- memcpy(buffer, &header, header_size);
- // Copy message to buffer
- memcpy(buffer + header_size, msg, header.size);
-
- write_socket(buffer, total_size);
-
- return 0;
-}
-
-static int
-is_float(const char *s)
-{
- size_t len = strlen(s);
- int is_dot_used = 0;
- int is_minus_used = 0;
-
- // Floats can only have one decimal point in between or digits
- // Optionally, floats can also be below zero (negative)
- for (int i = 0; i < len; i++) {
- if (isdigit(s[i]))
- continue;
- else if (!is_dot_used && s[i] == '.' && i != 0 && i != len - 1) {
- is_dot_used = 1;
- continue;
- } else if (!is_minus_used && s[i] == '-' && i == 0) {
- is_minus_used = 1;
- continue;
- } else
- return 0;
- }
-
- return 1;
-}
-
-static int
-is_unsigned_int(const char *s)
-{
- size_t len = strlen(s);
-
- // Unsigned int can only have digits
- for (int i = 0; i < len; i++) {
- if (isdigit(s[i]))
- continue;
- else
- return 0;
- }
-
- return 1;
-}
-
-static int
-is_signed_int(const char *s)
-{
- size_t len = strlen(s);
-
- // Signed int can only have digits and a negative sign at the start
- for (int i = 0; i < len; i++) {
- if (isdigit(s[i]))
- continue;
- else if (i == 0 && s[i] == '-') {
- continue;
- } else
- return 0;
- }
-
- return 1;
-}
-
-static void
-flush_socket_reply()
-{
- IPCMessageType reply_type;
- uint32_t reply_size;
- char *reply;
-
- read_socket(&reply_type, &reply_size, &reply);
-
- free(reply);
-}
-
-static void
-print_socket_reply()
-{
- IPCMessageType reply_type;
- uint32_t reply_size;
- char *reply;
-
- read_socket(&reply_type, &reply_size, &reply);
-
- printf("%.*s\n", reply_size, reply);
- fflush(stdout);
- free(reply);
-}
-
-static int
-run_command(const char *name, char *args[], int argc)
-{
- const unsigned char *msg;
- size_t msg_size;
-
- yajl_gen gen = yajl_gen_alloc(NULL);
-
- // Message format:
- // {
- // "command": "<name>",
- // "args": [ ... ]
- // }
- // clang-format off
- YMAP(
- YSTR("command"); YSTR(name);
- YSTR("args"); YARR(
- for (int i = 0; i < argc; i++) {
- if (is_signed_int(args[i])) {
- long long num = atoll(args[i]);
- YINT(num);
- } else if (is_float(args[i])) {
- float num = atof(args[i]);
- YDOUBLE(num);
- } else {
- YSTR(args[i]);
- }
- }
- )
- )
- // clang-format on
-
- yajl_gen_get_buf(gen, &msg, &msg_size);
-
- send_message(IPC_TYPE_RUN_COMMAND, msg_size, (uint8_t *)msg);
-
- if (!ignore_reply)
- print_socket_reply();
- else
- flush_socket_reply();
-
- yajl_gen_free(gen);
-
- return 0;
-}
-
-static int
-get_monitors()
-{
- send_message(IPC_TYPE_GET_MONITORS, 1, (uint8_t *)"");
- print_socket_reply();
- return 0;
-}
-
-static int
-get_tags()
-{
- send_message(IPC_TYPE_GET_TAGS, 1, (uint8_t *)"");
- print_socket_reply();
-
- return 0;
-}
-
-static int
-get_layouts()
-{
- send_message(IPC_TYPE_GET_LAYOUTS, 1, (uint8_t *)"");
- print_socket_reply();
-
- return 0;
-}
-
-static int
-get_dwm_client(Window win)
-{
- const unsigned char *msg;
- size_t msg_size;
-
- yajl_gen gen = yajl_gen_alloc(NULL);
-
- // Message format:
- // {
- // "client_window_id": "<win>"
- // }
- // clang-format off
- YMAP(
- YSTR("client_window_id"); YINT(win);
- )
- // clang-format on
-
- yajl_gen_get_buf(gen, &msg, &msg_size);
-
- send_message(IPC_TYPE_GET_DWM_CLIENT, msg_size, (uint8_t *)msg);
-
- print_socket_reply();
-
- yajl_gen_free(gen);
-
- return 0;
-}
-
-static int
-subscribe(const char *event)
-{
- const unsigned char *msg;
- size_t msg_size;
-
- yajl_gen gen = yajl_gen_alloc(NULL);
-
- // Message format:
- // {
- // "event": "<event>",
- // "action": "subscribe"
- // }
- // clang-format off
- YMAP(
- YSTR("event"); YSTR(event);
- YSTR("action"); YSTR("subscribe");
- )
- // clang-format on
-
- yajl_gen_get_buf(gen, &msg, &msg_size);
-
- send_message(IPC_TYPE_SUBSCRIBE, msg_size, (uint8_t *)msg);
-
- if (!ignore_reply)
- print_socket_reply();
- else
- flush_socket_reply();
-
- yajl_gen_free(gen);
-
- return 0;
-}
-
-static void
-usage_error(const char *prog_name, const char *format, ...)
-{
- va_list args;
- va_start(args, format);
-
- fprintf(stderr, "Error: ");
- vfprintf(stderr, format, args);
- fprintf(stderr, "\nusage: %s <command> [...]\n", prog_name);
- fprintf(stderr, "Try '%s help'\n", prog_name);
-
- va_end(args);
- exit(1);
-}
-
-static void
-print_usage(const char *name)
-{
- printf("usage: %s [options] <command> [...]\n", name);
- puts("");
- puts("Commands:");
- puts(" run_command <name> [args...] Run an IPC command");
- puts("");
- puts(" get_monitors Get monitor properties");
- puts("");
- puts(" get_tags Get list of tags");
- puts("");
- puts(" get_layouts Get list of layouts");
- puts("");
- puts(" get_dwm_client <window_id> Get dwm client proprties");
- puts("");
- puts(" subscribe [events...] Subscribe to specified events");
- puts(" Options: " IPC_EVENT_TAG_CHANGE ",");
- puts(" " IPC_EVENT_LAYOUT_CHANGE ",");
- puts(" " IPC_EVENT_CLIENT_FOCUS_CHANGE ",");
- puts(" " IPC_EVENT_MONITOR_FOCUS_CHANGE ",");
- puts(" " IPC_EVENT_FOCUSED_TITLE_CHANGE ",");
- puts(" " IPC_EVENT_FOCUSED_STATE_CHANGE);
- puts("");
- puts(" help Display this message");
- puts("");
- puts("Options:");
- puts(" --ignore-reply Don't print reply messages from");
- puts(" run_command and subscribe.");
- puts("");
-}
-
-int
-main(int argc, char *argv[])
-{
- const char *prog_name = argv[0];
-
- connect_to_socket();
- if (sock_fd == -1) {
- fprintf(stderr, "Failed to connect to socket\n");
- return 1;
- }
-
- int i = 1;
- if (i < argc && strcmp(argv[i], "--ignore-reply") == 0) {
- ignore_reply = 1;
- i++;
- }
-
- if (i >= argc) usage_error(prog_name, "Expected an argument, got none");
-
- if (!argc || strcmp(argv[i], "help") == 0)
- print_usage(prog_name);
- else if (strcmp(argv[i], "run_command") == 0) {
- if (++i >= argc) usage_error(prog_name, "No command specified");
- // Command name
- char *command = argv[i];
- // Command arguments are everything after command name
- char **command_args = argv + ++i;
- // Number of command arguments
- int command_argc = argc - i;
- run_command(command, command_args, command_argc);
- } else if (strcmp(argv[i], "get_monitors") == 0) {
- get_monitors();
- } else if (strcmp(argv[i], "get_tags") == 0) {
- get_tags();
- } else if (strcmp(argv[i], "get_layouts") == 0) {
- get_layouts();
- } else if (strcmp(argv[i], "get_dwm_client") == 0) {
- if (++i < argc) {
- if (is_unsigned_int(argv[i])) {
- Window win = atol(argv[i]);
- get_dwm_client(win);
- } else
- usage_error(prog_name, "Expected unsigned integer argument");
- } else
- usage_error(prog_name, "Expected the window id");
- } else if (strcmp(argv[i], "subscribe") == 0) {
- if (++i < argc) {
- for (int j = i; j < argc; j++) subscribe(argv[j]);
- } else
- usage_error(prog_name, "Expected event name");
- // Keep listening for events forever
- while (1) {
- print_socket_reply();
- }
- } else
- usage_error(prog_name, "Invalid argument '%s'", argv[i]);
-
- return 0;
-}
-
diff --git a/patch/ipc/yajl_dumps.h b/patch/ipc/yajl_dumps.h
deleted file mode 100644
index bb57a17..0000000
--- a/patch/ipc/yajl_dumps.h
+++ /dev/null
@@ -1,66 +0,0 @@
-#ifndef YAJL_DUMPS_H_
-#define YAJL_DUMPS_H_
-
-#include <string.h>
-#include <yajl/yajl_gen.h>
-
-#define YSTR(str) yajl_gen_string(gen, (unsigned char *)str, strlen(str))
-#define YINT(num) yajl_gen_integer(gen, num)
-#define YDOUBLE(num) yajl_gen_double(gen, num)
-#define YBOOL(v) yajl_gen_bool(gen, v)
-#define YNULL() yajl_gen_null(gen)
-#define YARR(body) \
- { \
- yajl_gen_array_open(gen); \
- body; \
- yajl_gen_array_close(gen); \
- }
-#define YMAP(body) \
- { \
- yajl_gen_map_open(gen); \
- body; \
- yajl_gen_map_close(gen); \
- }
-
-int dump_tag(yajl_gen gen, const char *name, const int tag_mask);
-
-int dump_tags(yajl_gen gen, int tags_len);
-
-int dump_client(yajl_gen gen, Client *c);
-
-int dump_monitor(yajl_gen gen, Monitor *mon, int is_selected);
-
-int dump_monitors(yajl_gen gen, Monitor *mons, Monitor *selmon);
-
-int dump_layouts(yajl_gen gen, const Layout layouts[], const int layouts_len);
-
-int dump_tag_state(yajl_gen gen, TagState state);
-
-int dump_tag_event(yajl_gen gen, int mon_num, TagState old_state,
- TagState new_state);
-
-int dump_client_focus_change_event(yajl_gen gen, Client *old_client,
- Client *new_client, int mon_num);
-
-int dump_layout_change_event(yajl_gen gen, const int mon_num,
- const char *old_symbol, const Layout *old_layout,
- const char *new_symbol, const Layout *new_layout);
-
-int dump_monitor_focus_change_event(yajl_gen gen, const int last_mon_num,
- const int new_mon_num);
-
-int dump_focused_title_change_event(yajl_gen gen, const int mon_num,
- const Window client_id,
- const char *old_name, const char *new_name);
-
-int dump_client_state(yajl_gen gen, const ClientState *state);
-
-int dump_focused_state_change_event(yajl_gen gen, const int mon_num,
- const Window client_id,
- const ClientState *old_state,
- const ClientState *new_state);
-
-int dump_error_message(yajl_gen gen, const char *reason);
-
-#endif // YAJL_DUMPS_H_
-
diff --git a/patch/layout_bstack.c b/patch/layout_bstack.c
deleted file mode 100644
index e72c57c..0000000
--- a/patch/layout_bstack.c
+++ /dev/null
@@ -1,39 +0,0 @@
-static void
-bstack(Monitor *m)
-{
- unsigned int i, n;
- int mx = 0, my = 0, mh = 0, mw = 0;
- int sx = 0, sy = 0, sh = 0, sw = 0;
- float mfacts, sfacts;
- int mrest, srest;
- Client *c;
-
- for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++);
-
- if (n == 0)
- return;
-
- sx = mx = m->wx;
- sy = my = m->wy;
- sh = mh = m->wh;
- sw = mw = m->ww;
-
- if (m->nmaster && n > m->nmaster) {
- sh = mh * (1 - m->mfact);
- mh = mh * m->mfact;
- sy = my + mh;
- }
-
- 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);
- } else {
- resize(c, sx, sy, (sw / sfacts) + ((i - m->nmaster) < srest ? 1 : 0) - (2*c->bw), sh - (2*c->bw), 0);
- sx += WIDTH(c);
- }
- }
-}
-
diff --git a/patch/layout_bstack.h b/patch/layout_bstack.h
deleted file mode 100644
index 07e8c0a..0000000
--- a/patch/layout_bstack.h
+++ /dev/null
@@ -1,2 +0,0 @@
-static void bstack(Monitor *m);
-
diff --git a/patch/layout_facts.c b/patch/layout_facts.c
deleted file mode 100644
index 241d344..0000000
--- a/patch/layout_facts.c
+++ /dev/null
@@ -1,24 +0,0 @@
-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
-}
-
diff --git a/patch/layout_gapplessgrid.c b/patch/layout_gapplessgrid.c
deleted file mode 100644
index ce23d5a..0000000
--- a/patch/layout_gapplessgrid.c
+++ /dev/null
@@ -1,48 +0,0 @@
-void
-gaplessgrid(Monitor *m)
-{
- unsigned int i, n;
- int x, y, cols, rows, ch, cw, cn, rn, rrest, crest; // counters
- Client *c;
-
- for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), 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 / rows;
- cw = m->ww / cols;
- rrest = m->wh - ch * rows;
- crest = m->ww - cw * cols;
- x = m->wx;
- y = m->wy;
-
- 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 / rows;
- rrest = m->wh - ch * rows;
- }
- resize(c,
- x,
- y + rn*ch + 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 + (cn < crest ? 1 : 0);
- cn++;
- }
- }
-}
-
diff --git a/patch/layout_gapplessgrid.h b/patch/layout_gapplessgrid.h
deleted file mode 100644
index 1a4ffc2..0000000
--- a/patch/layout_gapplessgrid.h
+++ /dev/null
@@ -1,2 +0,0 @@
-static void gaplessgrid(Monitor *m);
-
diff --git a/patch/layout_tile.c b/patch/layout_tile.c
deleted file mode 100644
index 76b0078..0000000
--- a/patch/layout_tile.c
+++ /dev/null
@@ -1,38 +0,0 @@
-static void
-tile(Monitor *m)
-{
- unsigned int i, n;
- int mx = 0, my = 0, mh = 0, mw = 0;
- int sx = 0, sy = 0, sh = 0, sw = 0;
- float mfacts, sfacts;
- int mrest, srest;
- Client *c;
-
- for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++);
-
- if (n == 0)
- return;
-
- sx = mx = m->wx;
- sy = my = m->wy;
- sh = mh = m->wh;
- sw = mw = m->ww;
-
- if (m->nmaster && n > m->nmaster) {
- sw = mw * (1 - m->mfact);
- mw = mw * m->mfact;
- sx = mx + mw;
- }
-
- 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);
- } else {
- resize(c, sx, sy, sw - (2*c->bw), (sh / sfacts) + ((i - m->nmaster) < srest ? 1 : 0) - (2*c->bw), 0);
- sy += HEIGHT(c);
- }
-}
-
diff --git a/patch/layout_tile.h b/patch/layout_tile.h
deleted file mode 100644
index 4aff634..0000000
--- a/patch/layout_tile.h
+++ /dev/null
@@ -1,2 +0,0 @@
-static void tile(Monitor *m);
-
diff --git a/patch/pertag.c b/patch/pertag.c
deleted file mode 100644
index c5f7f92..0000000
--- a/patch/pertag.c
+++ /dev/null
@@ -1,28 +0,0 @@
-struct Pertag {
- unsigned int curtag; /* current tag index */
- int nmasters[NUMTAGS + 1]; /* number of windows in master area */
- const Layout *ltidxs[NUMTAGS + 1][2]; /* matrix of tags and layouts indexes */
- float mfacts[NUMTAGS + 1]; /* mfacts per tag */
- unsigned int sellts[NUMTAGS + 1]; /* selected layouts */
-};
-
-void
-pertagview(const Arg *arg)
-{
- int i;
-
- if (arg->ui == ~0)
- selmon->pertag->curtag = 0;
- else {
- for (i = 0; !(selmon->tagset[selmon->seltags] & 1 << i); i++);
- selmon->pertag->curtag = i + 1;
- }
-
- 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];
-
-}
-
diff --git a/patch/pertag.h b/patch/pertag.h
deleted file mode 100644
index 5c53ac9..0000000
--- a/patch/pertag.h
+++ /dev/null
@@ -1,2 +0,0 @@
-static void pertagview(const Arg *arg);
-
diff --git a/patch/renamed_scratchpads.c b/patch/renamed_scratchpads.c
deleted file mode 100644
index 1a41e22..0000000
--- a/patch/renamed_scratchpads.c
+++ /dev/null
@@ -1,144 +0,0 @@
-void
-removescratch(const Arg *arg)
-{
- Client *c = selmon->sel;
- if (!c)
- return;
- c->scratchkey = 0;
-}
-
-void
-setscratch(const Arg *arg)
-{
- Client *c = selmon->sel;
- if (!c)
- return;
-
- c->scratchkey = ((char**)arg->v)[0][0];
-}
-
-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
-togglescratch(const Arg *arg)
-{
- Client *c, *next, *last = NULL, *found = NULL, *monclients = NULL;
- Monitor *mon;
- int scratchvisible = 0; // whether the scratchpads are currently visible or not
- int multimonscratch = 0; // whether we have scratchpads that are placed on multiple monitors
- int scratchmon = -1; // the monitor where the scratchpads exist
- int numscratchpads = 0; // count of scratchpads
-
- /* Looping through monitors and client's twice, the first time to work out whether we need
- to move clients across from one monitor to another or not */
- for (mon = mons; mon; mon = mon->next)
- for (c = mon->clients; c; c = c->next) {
- if (c->scratchkey != ((char**)arg->v)[0][0])
- continue;
- if (scratchmon != -1 && scratchmon != mon->num)
- multimonscratch = 1;
- if (c->mon->tagset[c->mon->seltags] & c->tags) // && !HIDDEN(c)
- ++scratchvisible;
- scratchmon = mon->num;
- ++numscratchpads;
- }
-
- /* Now for the real deal. The logic should go like:
- - hidden scratchpads will be shown
- - shown scratchpads will be hidden, unless they are being moved to the current monitor
- - the scratchpads will be moved to the current monitor if they all reside on the same monitor
- - multiple scratchpads residing on separate monitors will be left in place
- */
- for (mon = mons; mon; mon = mon->next) {
- for (c = mon->stack; c; c = next) {
- next = c->snext;
- if (c->scratchkey != ((char**)arg->v)[0][0])
- continue;
-
- /* Record the first found scratchpad client for focus purposes, but prioritise the
- scratchpad on the current monitor if one exists */
- if (!found || (mon == selmon && found->mon != selmon))
- found = c;
-
- /* If scratchpad clients reside on another monitor and we are moving them across then
- as we are looping through monitors we could be moving a client to a monitor that has
- not been processed yet, hence we could be processing a scratchpad twice. To avoid
- this we detach them and add them to a temporary list (monclients) which is to be
- processed later. */
- if (!multimonscratch && c->mon != selmon) {
- detach(c);
- detachstack(c);
- c->next = NULL;
- /* Note that we are adding clients at the end of the list, this is to preserve the
- order of clients as they were on the adjacent monitor (relevant when tiled) */
- if (last)
- last = last->next = c;
- else
- last = monclients = c;
- } else if (scratchvisible == numscratchpads) {
- c->tags = 0;
- } else {
- XSetWindowBorder(dpy, c->win, scheme[SchemeScratchNorm][ColBorder].pixel);
- c->tags = c->mon->tagset[c->mon->seltags];
- if (c->isfloating)
- XRaiseWindow(dpy, c->win);
- }
- }
- }
-
- /* Attach moved scratchpad clients on the selected monitor */
- for (c = monclients; c; c = next) {
- next = c->next;
- mon = c->mon;
- c->mon = selmon;
- c->tags = selmon->tagset[selmon->seltags];
- /* Attach scratchpad clients from other monitors at the bottom of the stack */
- if (selmon->clients) {
- for (last = selmon->clients; last && last->next; last = last->next);
- last->next = c;
- } else
- selmon->clients = c;
- c->next = NULL;
- attachstack(c);
-
- /* Center floating scratchpad windows when moved from one monitor to another */
- if (c->isfloating) {
- if (c->w > selmon->ww)
- c->w = selmon->ww - c->bw * 2;
- if (c->h > selmon->wh)
- c->h = selmon->wh - c->bw * 2;
-
- if (numscratchpads > 1) {
- c->x = c->mon->wx + (c->x - mon->wx) * ((double)(abs(c->mon->ww - WIDTH(c))) / MAX(abs(mon->ww - WIDTH(c)), 1));
- c->y = c->mon->wy + (c->y - mon->wy) * ((double)(abs(c->mon->wh - HEIGHT(c))) / MAX(abs(mon->wh - HEIGHT(c)), 1));
- } else if (c->x < c->mon->mx || c->x > c->mon->mx + c->mon->mw ||
- c->y < c->mon->my || c->y > c->mon->my + c->mon->mh) {
- c->x = c->mon->wx + (c->mon->ww / 2 - WIDTH(c) / 2);
- c->y = c->mon->wy + (c->mon->wh / 2 - HEIGHT(c) / 2);
- }
- resizeclient(c, c->x, c->y, c->w, c->h);
- XRaiseWindow(dpy, c->win);
- }
- }
-
- if (found) {
- focus(ISVISIBLE(found) ? found : NULL);
- arrange(NULL);
- if (found->isfloating)
- XRaiseWindow(dpy, found->win);
- } else {
- spawnscratch(arg);
- }
-}
-
diff --git a/patch/renamed_scratchpads.h b/patch/renamed_scratchpads.h
deleted file mode 100644
index 3260462..0000000
--- a/patch/renamed_scratchpads.h
+++ /dev/null
@@ -1,4 +0,0 @@
-static void removescratch(const Arg *arg);
-static void setscratch(const Arg *arg);
-static void spawnscratch(const Arg *arg);
-static void togglescratch(const Arg *arg);
diff --git a/patch/restartsig.c b/patch/restartsig.c
deleted file mode 100644
index adb61b5..0000000
--- a/patch/restartsig.c
+++ /dev/null
@@ -1,16 +0,0 @@
-static int restart = 0;
-
-void
-sighup(int unused)
-{
- Arg a = {.i = 1};
- quit(&a);
-}
-
-void
-sigterm(int unused)
-{
- Arg a = {.i = 0};
- quit(&a);
-}
-
diff --git a/patch/restartsig.h b/patch/restartsig.h
deleted file mode 100644
index b16975b..0000000
--- a/patch/restartsig.h
+++ /dev/null
@@ -1,3 +0,0 @@
-static void sighup(int unused);
-static void sigterm(int unused);
-
diff --git a/patch/seamless_restart.c b/patch/seamless_restart.c
deleted file mode 100644
index dd3c157..0000000
--- a/patch/seamless_restart.c
+++ /dev/null
@@ -1,314 +0,0 @@
-void
-persistmonitorstate(Monitor *m)
-{
- Client *c;
- unsigned int i;
-
- setmonitortags(m);
- setmonitorfields(m);
-
- /* Set client atoms */
- for (i = 1, c = m->clients; c; c = c->next, ++i) {
- c->idx = i;
- persistclientstate(c);
- }
-}
-
-int
-restoremonitorstate(Monitor *m)
-{
- return getmonitortags(m) | getmonitorfields(m);
-}
-
-void
-persistclientstate(Client *c)
-{
- setclienttags(c);
- setclientfields(c);
- savewindowfloatposition(c, c->mon);
-}
-
-int
-restoreclientstate(Client *c)
-{
- int restored = getclientfields(c);
- getclienttags(c);
- restorewindowfloatposition(c, c->mon ? c->mon : selmon);
- return restored;
-}
-
-void setmonitorfields(Monitor *m)
-{
- unsigned int i;
- char atom[22] = {0};
- Atom monitor_fields;
-
- sprintf(atom, "_DWM_MONITOR_FIELDS_%u", m->num);
- monitor_fields = XInternAtom(dpy, atom, False);
-
- /* Perists workspace information in 32 bits laid out like this:
- *
- * |0|0000|0|0000|0000|0000|0000|0000|000|000
- * | | | | | | | | | |-- nmaster
- * | | | | | | | | |-- nstack
- * | | | | | | | |-- layout
- * | | | | | | |-- flextile LAYOUT (split)
- * | | | | | |-- flextile MASTER
- * | | | | |-- flextile STACK1
- * | | | |-- flextile STACK2
- * | | |-- flextile mirror layout (indicated by negative layout)
- * | |
- * | |-- reserved
- * |-- showbar
- */
- for (i = 0; i <= NUMTAGS; i++) {
- uint32_t data[] = {
- (m->pertag->nmasters[i] & 0x7) |
- (getlayoutindex(m->pertag->ltidxs[i][m->pertag->sellts[i]]) & 0xF) << 6 |
- m->showbar << 31
- };
-
- XChangeProperty(dpy, root, monitor_fields, XA_CARDINAL, 32,
- i ? PropModeAppend : PropModeReplace, (unsigned char *)data, 1);
- }
-}
-
-int
-getlayoutindex(const Layout *layout)
-{
- int i;
-
- for (i = 0; i < LENGTH(layouts) && &layouts[i] != layout; i++);
- if (i == LENGTH(layouts))
- i = 0;
- return i;
-}
-
-int
-getmonitorfields(Monitor *m)
-{
- int di, layout_index;
- unsigned int i, restored = 0;
- unsigned int tags = m->tagset[m->seltags] << 1;
- unsigned long dl, nitems;
- unsigned char *p = NULL;
- char atom[22] = {0};
- Atom da, state = None;
-
- sprintf(atom, "_DWM_MONITOR_FIELDS_%u", m->num);
- Atom dwm_monitor = XInternAtom(dpy, atom, False);
- if (!dwm_monitor)
- return 0;
-
- for (i = 0; i <= NUMTAGS; i++) {
- if (!(XGetWindowProperty(dpy, root, dwm_monitor, i, (NUMTAGS + 1) * sizeof dl,
- False, AnyPropertyType, &da, &di, &nitems, &dl, &p) == Success && p)) {
- break;
- }
-
- if (!nitems) {
- XFree(p);
- break;
- }
-
- /* See bit layout in the persistmonitorstate function */
- state = *(Atom *)p;
-
- m->pertag->nmasters[i] = state & 0x7;
- layout_index = (state >> 6) & 0xF;
- if (layout_index < LENGTH(layouts))
- m->pertag->ltidxs[i][m->pertag->sellts[i]] = &layouts[layout_index];
-
- if (!restored && i && (tags & (1 << i))) {
- m->nmaster = m->pertag->nmasters[i];
- m->sellt = m->pertag->sellts[i];
- m->lt[m->sellt] = m->pertag->ltidxs[i][m->sellt];
- m->showbar = (state >> 31) & 0x1;
- restored = 1;
- }
-
- XFree(p);
- }
-
- return restored;
-}
-
-void
-setmonitortags(Monitor *m)
-{
- char atom[22] = {0};
- Atom monitor_tags;
-
- sprintf(atom, "_DWM_MONITOR_TAGS_%u", m->num);
- monitor_tags = XInternAtom(dpy, atom, False);
-
- uint32_t data[] = { m->tagset[m->seltags] };
- XChangeProperty(dpy, root, monitor_tags, XA_CARDINAL, 32, PropModeReplace, (unsigned char *)data, 1);
-}
-
-int
-getmonitortags(Monitor *m)
-{
- int di;
- unsigned long dl, nitems;
- unsigned char *p = NULL;
- char atom[22] = {0};
- Atom da, monitor_tags = None, tags;
-
- sprintf(atom, "_DWM_MONITOR_TAGS_%u", m->num);
- monitor_tags = XInternAtom(dpy, atom, False);
-
- if (!(XGetWindowProperty(dpy, root, monitor_tags, 0L, sizeof dl,
- False, AnyPropertyType, &da, &di, &nitems, &dl, &p) == Success && p)) {
- return 0;
- }
-
- if (nitems) {
- tags = *(Atom *)p;
- m->tagset[m->seltags] = tags & TAGMASK;
- }
-
- XFree(p);
- return 1;
-}
-
-void
-setclientfields(Client *c)
-{
- /* Perists client information in 32 bits laid out like this:
- *
- * |00000000|00000|0|0|0|0|0|0|0|0|00000000|000
- * | | | | | | | | | | | |-- monitor index
- * | | | | | | | | | | |-- client index
- * | | | | | | | | | |-- isfloating
- * | | | | | | | | |-- ispermanent
- * | | | | | | | |-- isterminal
- * | | | | | | |-- noswallow
- * | | | | | |-- issteam
- * | | | | |-- issticky
- * | | | |-- fakefullscreen
- * | | |-- isfreesize
- * | |
- * | |-- reserved
- * |-- scratchkey (for scratchpads)
- */
- uint32_t data[] = {
- (c->mon->num & 0x7)
- | (c->idx & 0xFF) << 3
- | (c->isfloating & 0x1) << 11
- | (c->scratchkey & 0xFF) << 24
- };
- XChangeProperty(dpy, c->win, clientatom[ClientFields], XA_CARDINAL, 32, PropModeReplace, (unsigned char *)data, 1);
-}
-
-int
-getclientfields(Client *c)
-{
- Monitor *m;
- Atom fields = getatomprop(c, clientatom[ClientFields], AnyPropertyType);
- if (fields == None)
- return 0;
-
- /* See bit layout in the setclientfields function */
- for (m = mons; m; m = m->next)
- if (m->num == (fields & 0x7)) {
- c->mon = m;
- break;
- }
- c->idx = (fields >> 3) & 0xFF;
- c->isfloating = (fields >> 11) & 0x1;
- c->scratchkey = (fields >> 24) & 0xFF;
- return 1;
-}
-
-void
-setclienttags(Client *c)
-{
- uint32_t data[] = { c->tags };
- XChangeProperty(dpy, c->win, clientatom[ClientTags], XA_CARDINAL, 32, PropModeReplace, (unsigned char *)data, 1);
-}
-
-int
-getclienttags(Client *c)
-{
- Atom tags = getatomprop(c, clientatom[ClientTags], AnyPropertyType);
- if (tags == None)
- return 0;
-
- c->tags = tags & TAGMASK;
- return 1;
-}
-
-void
-savewindowfloatposition(Client *c, Monitor *m)
-{
- char atom[22] = {0};
- if (c->sfx == -9999)
- return;
-
- sprintf(atom, "_DWM_FLOATPOS_%u", m->num);
- uint32_t pos[] = { (MAX(c->sfx - m->mx, 0) & 0xffff) | ((MAX(c->sfy - m->my, 0) & 0xffff) << 16) };
- XChangeProperty(dpy, c->win, XInternAtom(dpy, atom, False), XA_CARDINAL, 32, PropModeReplace, (unsigned char *)pos, 1);
-
- sprintf(atom, "_DWM_FLOATSIZE_%u", m->num);
- uint32_t size[] = { (c->sfw & 0xffff) | ((c->sfh & 0xffff) << 16) };
- XChangeProperty(dpy, c->win, XInternAtom(dpy, atom, False), XA_CARDINAL, 32, PropModeReplace, (unsigned char *)size, 1);
-
- XSync(dpy, False);
-}
-
-int
-restorewindowfloatposition(Client *c, Monitor *m)
-{
- char atom[22] = {0};
- Atom key, value;
- int x, y, w, h;
-
- if (m == NULL)
- return 0;
-
- sprintf(atom, "_DWM_FLOATPOS_%u", m->num);
-
- key = XInternAtom(dpy, atom, False);
- if (!key)
- return 0;
-
- value = getatomprop(c, key, AnyPropertyType);
- if (!value)
- return 0;
-
- x = value & 0xffff;
- y = value >> 16;
-
- sprintf(atom, "_DWM_FLOATSIZE_%u", m->num);
-
- key = XInternAtom(dpy, atom, False);
- if (!key)
- return 0;
-
- value = getatomprop(c, key, AnyPropertyType);
- if (!value)
- return 0;
-
- w = value & 0xffff;
- h = value >> 16;
-
- if (w <= 0 || h <= 0) {
- fprintf(stderr, "restorewindowfloatposition: bad float values x = %d, y = %d, w = %d, h = %d for client = %s\n", x, y, w, h, c->name);
- return 0;
- }
-
- c->sfx = m->mx + x;
- c->sfy = m->my + y;
- c->sfw = w;
- c->sfh = h;
-
- if (c->isfloating) {
- c->x = c->sfx;
- c->y = c->sfy;
- c->w = c->sfw;
- c->h = c->sfh;
- }
-
- return 1;
-}
diff --git a/patch/seamless_restart.h b/patch/seamless_restart.h
deleted file mode 100644
index 4d95b6a..0000000
--- a/patch/seamless_restart.h
+++ /dev/null
@@ -1,17 +0,0 @@
-#include <stdint.h>
-
-static void persistmonitorstate(Monitor *m);
-static int restoremonitorstate(Monitor *m);
-static void persistclientstate(Client *c);
-static int restoreclientstate(Client *c);
-static void setmonitorfields(Monitor *m);
-static int getmonitorfields(Monitor *m);
-static void setmonitortags(Monitor *m);
-static int getmonitortags(Monitor *m);
-static void setclientfields(Client *c);
-static int getclientfields(Client *c);
-static void setclienttags(Client *c);
-static int getclienttags(Client *c);
-static int getlayoutindex(const Layout *layout);
-static void savewindowfloatposition(Client *c, Monitor *m);
-static int restorewindowfloatposition(Client *c, Monitor *m);
diff --git a/patch/sizehints_ruled.c b/patch/sizehints_ruled.c
deleted file mode 100644
index 32de43b..0000000
--- a/patch/sizehints_ruled.c
+++ /dev/null
@@ -1,33 +0,0 @@
-void
-checkfloatingrules(Client *c)
-{
- const char *class, *instance;
- Atom wintype;
- char role[64];
- unsigned int i;
- const Rule *r;
- XClassHint ch = { NULL, NULL };
-
- XGetClassHint(dpy, c->win, &ch);
- class = ch.res_class ? ch.res_class : broken;
- instance = ch.res_name ? ch.res_name : broken;
- wintype = getatomprop(c, netatom[NetWMWindowType], XA_ATOM);
- gettextprop(c->win, wmatom[WMWindowRole], role, sizeof(role));
-
- for (i = 0; i < LENGTH(rules); i++) {
- r = &rules[i];
- if ((!r->title || strstr(c->name, r->title))
- && (!r->class || strstr(class, r->class))
- && (!r->role || strstr(role, r->role))
- && (!r->instance || strstr(instance, r->instance))
- && (!r->wintype || wintype == XInternAtom(dpy, r->wintype, False)))
- {
- c->isfloating = r->isfloating;
- }
- }
- if (ch.res_class)
- XFree(ch.res_class);
- if (ch.res_name)
- XFree(ch.res_name);
-}
-
diff --git a/patch/sizehints_ruled.h b/patch/sizehints_ruled.h
deleted file mode 100644
index 14c6719..0000000
--- a/patch/sizehints_ruled.h
+++ /dev/null
@@ -1,2 +0,0 @@
-static void checkfloatingrules(Client *c);
-
diff --git a/patch/stacker.c b/patch/stacker.c
deleted file mode 100644
index 0ed1344..0000000
--- a/patch/stacker.c
+++ /dev/null
@@ -1,73 +0,0 @@
-void
-focusstack(const Arg *arg)
-{
- int i = stackpos(arg);
- Client *c, *p;
-
- if (i < 0)
- return;
-
- if (!selmon->sel)
- return;
-
- 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);
-}
-
-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);
-}
-
-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;
-}
-
diff --git a/patch/stacker.h b/patch/stacker.h
deleted file mode 100644
index ee420bd..0000000
--- a/patch/stacker.h
+++ /dev/null
@@ -1,11 +0,0 @@
-#define GETINC(X) ((X) - 2000)
-#define INC(X) ((X) + 2000)
-#define ISINC(X) ((X) > 1000 && (X) < 3000)
-#define PREVSEL 3000
-#define MOD(N,M) ((N)%(M) < 0 ? (N)%(M) + (M) : (N)%(M))
-#define TRUNC(X,A,B) (MAX((A), MIN((X), (B))))
-
-static void focusstack(const Arg *arg);
-static void pushstack(const Arg *arg);
-static int stackpos(const Arg *arg);
-
diff --git a/patch/togglefullscreen.c b/patch/togglefullscreen.c
deleted file mode 100644
index a62edef..0000000
--- a/patch/togglefullscreen.c
+++ /dev/null
@@ -1,10 +0,0 @@
-void
-togglefullscreen(const Arg *arg)
-{
- Client *c = selmon->sel;
- if (!c)
- return;
-
- setfullscreen(c, !c->isfullscreen);
-}
-
diff --git a/patch/togglefullscreen.h b/patch/togglefullscreen.h
deleted file mode 100644
index 96a6770..0000000
--- a/patch/togglefullscreen.h
+++ /dev/null
@@ -1,2 +0,0 @@
-static void togglefullscreen(const Arg *arg);
-
diff --git a/patch/unfloatvisible.c b/patch/unfloatvisible.c
deleted file mode 100644
index fb8888f..0000000
--- a/patch/unfloatvisible.c
+++ /dev/null
@@ -1,15 +0,0 @@
-void
-unfloatvisible(const Arg *arg)
-{
- Client *c;
-
- for (c = selmon->clients; c; c = c->next)
- if (ISVISIBLE(c) && c->isfloating)
- c->isfloating = c->isfixed;
-
- if (arg && arg->v)
- setlayout(arg);
- else
- arrange(selmon);
-}
-
diff --git a/patch/unfloatvisible.h b/patch/unfloatvisible.h
deleted file mode 100644
index f15bc66..0000000
--- a/patch/unfloatvisible.h
+++ /dev/null
@@ -1,2 +0,0 @@
-static void unfloatvisible(const Arg *arg);
-
diff --git a/patches.h b/patches.h
new file mode 100644
index 0000000..a633a2c
--- /dev/null
+++ b/patches.h
@@ -0,0 +1,1494 @@
+/*
+ * This file contains patch control flags.
+ *
+ * In principle you should be able to mix and match any patches
+ * you may want. In cases where patches are logically incompatible
+ * one patch may take precedence over the other as noted in the
+ * relevant descriptions.
+ *
+ * Although layouts typically come as patches they are differentiated
+ * here for grouping purposes.
+ */
+
+/**
+ * Bar modules
+ */
+
+/* Enhanced taskbar that shows the titles of all visible windows in the status bar
+ * and allows focus / hiding / unhiding of windows by clicking on the status bar.
+ * Awesomebar takes precedence over fancybar.
+ * https://dwm.suckless.org/patches/awesomebar/
+ */
+#define BAR_AWESOMEBAR_PATCH 0
+
+/* This patch depends on statuscmd patch and adds integration with a (patched)
+ * dwmblocks instance to give a clickable status bar. One must not necessarily
+ * have to use dwmblocks for this feature, any status updater that has support
+ * for real-time signals (SIGRTMIN) can be used.
+ *
+ * dwmblocks: https://github.com/torrinfail/dwmblocks
+ * https://dwm.suckless.org/patches/statuscmd/
+ */
+#define BAR_DWMBLOCKS_PATCH 0
+
+/* Originally the dwmblocks + statuscmd patch used a user defined signal (SIGUSR1)
+ * for communicating with dwmblocks to indicate update signal and what button was
+ * pressed. The signalling was later changed to SIGRTMIN instead.
+ *
+ * Ultimately this makes dwmblocks instances that were patched with the old patch
+ * are incompatible with the new dwm patch and vice versa.
+ *
+ * This is a compatibility patch that makes dwm use SIGUSR1 instead of SIGRTMIN so
+ * if button clicks are not working then you may want to try enabling this.
+ *
+ * If dwmblocks happen to die like this when clicking on a status
+ *
+ * [1] 54355 user-defined signal 1 dwmblocks
+ *
+ * then it suggests that dwmblocks does not support user defined signals and this
+ * patch should be left disabled.
+ *
+ * Patch: https://gist.github.com/danbyl/54f7c1d57fc6507242a95b71c3d8fdea
+ * https://dwm.suckless.org/patches/statuscmd/
+ */
+#define BAR_DWMBLOCKS_SIGUSR1_PATCH 0
+
+/* This patch shows the titles of all visible windows in the status bar
+ * (as opposed to showing only the selected one).
+ * Awesomebar takes precedence over fancybar. Fancybar takes precedence over
+ * the centeredwindowname patch.
+ * https://dwm.suckless.org/patches/fancybar/
+ */
+#define BAR_FANCYBAR_PATCH 0
+
+/* Being an evolution of the bartabgroups patch the flexwintitle patch specifically
+ * taps into the many layout options that flextile-deluxe offers to produce a window
+ * title section in the bar that is representative of what is shown on screen.
+ */
+#define BAR_FLEXWINTITLE_PATCH 0
+
+/* This patch adds a context menu for layout switching.
+ * - xmenu needs to be installed.
+ * - Edit layoutmenu.sh with the installed layouts and with correct indexes.
+ * - Place layoutmenu.sh in PATH.
+ * - The text of the menu items is for display only. Name them however you want.
+ * https://dwm.suckless.org/patches/layoutmenu/
+ */
+#define BAR_LAYOUTMENU_PATCH 1
+
+/* Show layout symbol in bar */
+#define BAR_LTSYMBOL_PATCH 1
+
+/* Adds powerline arrows for the status.
+ * This uses statuscolors logic for choosing colors for the powerline. As these markers
+ * are also control characters there is no explicit statuscmd support for this patch.
+ *
+ * Powerline separators are defined as:
+ * |\xXX (creates a hard edge)
+ * <\xXX (creates a less than arrow)
+ * /\xXX (creates a diagonal line)
+ *
+ * Examples:
+ * xsetroot -name "$(echo -e '<\x01a<\x02b<\x03c')"
+ * xsetroot -name "$(echo -e '/\x01d/\x02e/\x03f')"
+ *
+ * https://gitlab.com/udiboy1209-suckless/dwm/-/commit/071f5063e8ac4280666828179f92788d893eea40#4b1a539194be7467cefbda22f675a3b7c19ceca7
+ * https://dwm.suckless.org/patches/statuscolors/
+ */
+#define BAR_POWERLINE_STATUS_PATCH 0
+
+/* Adds powerline arrows for the tags.
+ * https://gitlab.com/udiboy1209-suckless/dwm/-/commit/071f5063e8ac4280666828179f92788d893eea40#4b1a539194be7467cefbda22f675a3b7c19ceca7
+ */
+#define BAR_POWERLINE_TAGS_PATCH 0
+
+/* Alters the tags powerline to use forward slash instead of arrows */
+#define BAR_POWERLINE_TAGS_SLASH_PATCH 0
+
+/* This patch turns the titlebar area into a mfact-respecting tabbar showing each client's title.
+ * https://dwm.suckless.org/patches/bartabgroups/
+ */
+#define BAR_TABGROUPS_PATCH 0
+
+/* This patch adds an option to place tags in rows like in many other window managers.
+ * https://dwm.suckless.org/patches/taggrid/
+ */
+#define BAR_TAGGRID_PATCH 0
+
+/* Hover tag icons to see a preview of the windows on that tag.
+ *
+ * The patch depends on Imlib2 for icon scaling.
+ * You need to uncomment the corresponding line in config.mk to use the -lImlib2 library
+ *
+ * Arch Linux:
+ * sudo pacman -S imlib2
+ * Debian:
+ * sudo apt install libimlib2-dev
+ *
+ * As with the winicon patch you may want to consider adding the compiler flags of -O3 and
+ * -march=native to enable auto loop vectorize for better performance.
+ *
+ * https://dwm.suckless.org/patches/tag-previews/
+ */
+#define BAR_TAGPREVIEW_PATCH 0
+
+/* Show status in bar */
+#define BAR_STATUS_PATCH 1
+
+/* This patch adds a clickable button to the left hand side of the statusbar.
+ * https://dwm.suckless.org/patches/statusbutton/
+ */
+#define BAR_STATUSBUTTON_PATCH 0
+
+/* This patch adds the ability to execute shell commands based on the mouse button and position
+ * when clicking the status bar. Refer to the website for usage.
+ * https://dwm.suckless.org/patches/statuscmd/
+ */
+#define BAR_STATUSCMD_PATCH 0
+
+/* Status2d allows colors and rectangle drawing in your dwm status bar.
+ * This patch is incompatible with the statuscolors patch which takes precedence.
+ * This patch is incompatible with the extrabar patch.
+ * https://dwm.suckless.org/patches/status2d/
+ */
+#define BAR_STATUS2D_PATCH 0
+
+/* Supplementary patch should you want to disable alpha for the status2d section */
+#define BAR_STATUS2D_NO_ALPHA_PATCH 0
+
+/* Addition to the status2d patch that allows the use of terminal colors (color0 through color15)
+ * from xrdb in the status, allowing programs like pywal to change statusbar colors.
+ * This adds the C and B codes to use terminal foreground and background colors respectively.
+ * E.g. ^B5^ would use color5 as the background color.
+ * https://dwm.suckless.org/patches/status2d/
+ */
+#define BAR_STATUS2D_XRDB_TERMCOLORS_PATCH 0
+
+/* The systray patch adds systray for the status bar.
+ * https://dwm.suckless.org/patches/systray/
+ */
+#define BAR_SYSTRAY_PATCH 1
+
+/* Show tag symbols in the bar. */
+#define BAR_TAGS_PATCH 1
+
+/* Show tag symbols + class of master window in the bar.
+ * https://dwm.suckless.org/patches/taglabels/
+ */
+#define BAR_TAGLABELS_PATCH 0
+
+/* This patch underlines the selected tag, or optionally all tags.
+ * https://dwm.suckless.org/patches/underlinetags/
+ */
+#define BAR_UNDERLINETAGS_PATCH 0
+
+/* This patch adds the window icon next to the window title in the bar.
+ *
+ * The patch depends on Imlib2 for icon scaling.
+ * You need to uncomment the corresponding line in config.mk to use the -lImlib2 library
+ *
+ * Arch Linux:
+ * sudo pacman -S imlib2
+ * Debian:
+ * sudo apt install libimlib2-dev
+ *
+ * The author recommends adding the compiler flags of -O3 and -march=native to enable auto loop
+ * vectorize for better performance.
+ *
+ * https://github.com/AdamYuan/dwm-winicon
+ * https://dwm.suckless.org/patches/winicon
+ */
+#define BAR_WINICON_PATCH 0
+
+/* Show window title in bar */
+#define BAR_WINTITLE_PATCH 1
+
+/* Shows window titles in the bar, but only for floating clients.
+ * This depends on code from the flexwintitle patch.
+ * Note that the configuration in config.def.h for this is merely an example. If combined
+ * with the corresponding hidden patch then these two will overlap unless the width of the
+ * modules are controlled.
+ */
+#define BAR_WINTITLE_FLOATING_PATCH 0
+
+/* Shows window titles in the bar, but only for floating clients.
+ * This depends on code from the flexwintitle patch.
+ * Note that the configuration in config.def.h for this is merely an example. If combined
+ * with the corresponding floating patch then these two will overlap unless the width of the
+ * modules are controlled.
+ */
+#define BAR_WINTITLE_HIDDEN_PATCH 0
+
+/* Title bar modules such as wintitle (default), fancybar and awesomebar
+ * do not by default add left and/or right padding as they take up the
+ * remaining space. These options allow you explicitly add padding should
+ * you need it.
+ */
+#define BAR_TITLE_RIGHT_PAD_PATCH 0
+#define BAR_TITLE_LEFT_PAD_PATCH 0
+
+/**
+ * Bar options
+ */
+
+/* This patch changes the rectangle indicating if a tag is used by a client into a bar
+ * above the tag name for better visibility.
+ * Set the tagindicatortype variable in config.h to INDICATOR_TOP_BAR to enable this.
+ * https://dwm.suckless.org/patches/activetagindicatorbar/
+ */
+#define BAR_ACTIVETAGINDICATORBAR_PATCH N/A
+
+/* Alternative patch to the activetagindicatorbar patch, adds the bar below the tag
+ * icon rather than above.
+ * Set the tagindicatortype variable in config.h to INDICATOR_BOTTOM_BAR to enable this.
+ */
+#define BAR_ACTIVETAGINDICATORBAR_ALT1_PATCH N/A
+
+/* The alpha patch adds transparency for the status bar.
+ * You need to uncomment the corresponding line in config.mk to use the -lXrender library
+ * when including this patch.
+ * https://dwm.suckless.org/patches/alpha/
+ */
+#define BAR_ALPHA_PATCH 1
+
+/* This patch introduces alternative tags which can be switched on the fly for the
+ * sole purpose of providing visual aid.
+ * https://dwm.suckless.org/patches/alternativetags/
+ */
+#define BAR_ALTERNATIVE_TAGS_PATCH 0
+
+/* This patches provides the ability to use alternative text for tags which contain at
+ * least one window.
+ * https://dwm.suckless.org/patches/alttagsdecoration/
+ */
+#define BAR_ALTTAGSDECORATION_PATCH 0
+
+/* This patch enables dwm to manage external status bars such as lemonbar and polybar.
+ * dwm treats the external bar as it would its own, so all regular dwm commands such as
+ * togglebar affect the external bar in the same way.
+ *
+ * NB: Unless you want both anybar + dwm bar(s) then the recommendation is to disable all
+ * bar modules and have { -2 } in the barrules.
+ *
+ * https://dwm.suckless.org/patches/anybar/
+ */
+#define BAR_ANYBAR_PATCH 0
+
+/* Anybar option to place the next bar depending on previous bar's position (top or bottom) */
+#define BAR_ANYBAR_TOP_AND_BOTTOM_BARS_PATCH 0
+
+/* Anybar option to let dwm manage the width of the bar */
+#define BAR_ANYBAR_MANAGE_WIDTH_PATCH 0
+
+/* This patch adds a border around the status bar(s) just like the border of client windows.
+ * https://codemadness.org/paste/dwm-border-bar.patch
+ */
+#define BAR_BORDER_PATCH 0
+
+/* This patch centers the WM_NAME of the currently selected window on the status bar.
+ * This is compatible with the wintitle, bartabgroups, flexwintitle and awesomebar bar
+ * modules.
+ * https://dwm.suckless.org/patches/centeredwindowname/
+ */
+#define BAR_CENTEREDWINDOWNAME_PATCH 0
+
+/* Draws a dot indicator overlayed on each tag icon for each client. The selected client
+ * is drawn as a larger horizontal line.
+ * Set the tagindicatortype variable in config.h to INDICATOR_CLIENT_DOTS to enable this.
+ * https://dwm.suckless.org/patches/clientindicators/
+ */
+#define BAR_CLIENTINDICATOR_PATCH N/A
+
+/* Updates the position of dmenu to match that of the bar. I.e. if topbar is 0 then dmenu
+ * will appear at the bottom and if 1 then dmenu will appear at the top.
+ * https://dwm.suckless.org/patches/dmenumatchtop
+ */
+#define BAR_DMENUMATCHTOP_PATCH 0
+
+/* Originally this was the extrabar patch, but as the handling of extra bars is now built-in
+ * only the splitting of the status by a designated separator remains. As such this has been
+ * renamed to more accurately reflect what it does - creating an extra status.
+ * https://dwm.suckless.org/patches/extrabar/
+ */
+#define BAR_EXTRASTATUS_PATCH 0
+
+/* Adds EWMH support for _NET_NUMBER_OF_DESKTOPS, _NET_CURRENT_DESKTOP, _NET_DESKTOP_NAMES
+ * and _NET_DESKTOP_VIEWPORT, which allows for compatibility with other bars and programs
+ * that request workspace information. For example polybar's xworkspaces module.
+ *
+ * This patch also includes support for adding the _IS_FLOATING property for floating windows
+ * allowing for compositors to treat floating windows differently to tiled windows.
+ *
+ * E.g. this setting makes picom only render shadows for floating windows:
+ *
+ * shadow-exclude = [ "! _IS_FLOATING@:32c = 1" ];
+ *
+ * https://github.com/bakkeby/dwm-flexipatch/issues/50 (_IS_FLOATING patch)
+ * https://dwm.suckless.org/patches/ewmhtags/
+ */
+#define BAR_EWMHTAGS_PATCH 1
+
+/* Allows the bar height to be explicitly set rather than being derived from font.
+ * https://dwm.suckless.org/patches/bar_height/
+ */
+#define BAR_HEIGHT_PATCH 0
+
+/* This patch prevents dwm from drawing tags with no clients (i.e. vacant) on the bar.
+ * https://dwm.suckless.org/patches/hide_vacant_tags/
+ */
+#define BAR_HIDEVACANTTAGS_PATCH 1
+
+/* With this patch dwm's built-in status bar is only shown when HOLDKEY is pressed
+ * and the bar will now overlay the display.
+ * http://dwm.suckless.org/patches/holdbar/
+ */
+#define BAR_HOLDBAR_PATCH 0
+
+/* Sometimes dwm crashes when it cannot render some glyphs in window titles (usually emoji).
+ * This patch is essentially a hack to ignore any errors when drawing text on the status bar.
+ * https://groups.google.com/forum/m/#!topic/wmii/7bncCahYIww
+ * https://docs.google.com/viewer?a=v&pid=forums&srcid=MDAwODA2MTg0MDQyMjE0OTgzMzMBMDQ3ODQzODkyMTU3NTAyMTMxNTYBX2RUMVNtOUtDQUFKATAuMQEBdjI&authuser=0
+ */
+#define BAR_IGNORE_XFT_ERRORS_WHEN_DRAWING_TEXT_PATCH 0
+
+/* This patch adds back in the workaround for a BadLength error in the Xft library when color
+ * glyphs are used. This is for systems that do not have an updated version of the Xft library
+ * (or generally prefer monochrome fonts).
+ */
+#define BAR_NO_COLOR_EMOJI_PATCH 0
+
+/* This patch adds vertical and horizontal space between the statusbar and the edge of the screen.
+ * https://dwm.suckless.org/patches/barpadding/
+ */
+#define BAR_PADDING_PATCH 0
+
+/* Same as barpadding patch but specifically tailored for the vanitygaps patch in that the outer
+ * bar padding is derived from the vanitygaps settings. In addition to this the bar padding is
+ * toggled in unison when vanitygaps are toggled. Increasing or decreasing gaps during runtime
+ * will not affect the bar padding.
+ */
+#define BAR_PADDING_VANITYGAPS_PATCH 0
+
+/* This patch adds simple markup for status messages using pango markup.
+ * This depends on the pango library v1.44 or greater.
+ * You need to uncomment the corresponding lines in config.mk to use the pango libraries
+ * when including this patch.
+ *
+ * Note that the pango patch does not protect against the BadLength error from Xft
+ * when color glyphs are used, which means that dwm will crash if color emoji is used.
+ *
+ * If you need color emoji then you may want to install this patched library from the AUR:
+ * https://aur.archlinux.org/packages/libxft-bgra/
+ *
+ * A long term fix for the libXft library is pending approval of this pull request:
+ * https://gitlab.freedesktop.org/xorg/lib/libxft/-/merge_requests/1
+ *
+ * Also see:
+ * https://developer.gnome.org/pygtk/stable/pango-markup-language.html
+ * https://lists.suckless.org/hackers/2004/17285.html
+ * https://dwm.suckless.org/patches/pango/
+ */
+#define BAR_PANGO_PATCH 1
+
+/* This patch allows the status text to be fixed to the bar on a specific
+ * monitor rather than being drawn on the focused monitor.
+ * The statusallmons patch takes precedence over this patch.
+ * https://dwm.suckless.org/patches/staticstatus/
+ */
+#define BAR_STATICSTATUS_PATCH 0
+
+/* This patch draws and updates the statusbar on all monitors.
+ * https://dwm.suckless.org/patches/statusallmons/
+ */
+#define BAR_STATUSALLMONS_PATCH 0
+
+/* This patch enables colored text in the status bar. It changes the way colors are defined
+ * in config.h allowing multiple color combinations for use in the status script.
+ * This patch is incompatible with and takes precedence over the status2d patch.
+ *
+ * This patch is compatible with the statuscmd patch with the caveat that the first 16 markers
+ * are reserved for status colors restricting block signals to 17 through 31.
+ *
+ * https://dwm.suckless.org/patches/statuscolors/
+ */
+#define BAR_STATUSCOLORS_PATCH 0
+
+/* This patch adds configuration options for horizontal and vertical padding in the status bar.
+ * https://dwm.suckless.org/patches/statuspadding/
+ */
+#define BAR_STATUSPADDING_PATCH 0
+
+/* This patch adds the ability for dwm to read colors from the linux virtual console.
+ * /sys/module/vt/parameters/default_{red,grn,blu}
+ * Essentially this way the colors you use in your regular tty is "mirrored" to dwm.
+ * https://dwm.suckless.org/patches/vtcolors/
+ */
+#define BAR_VTCOLORS_PATCH 0
+
+/* This patch allows client windows to be hidden. This code was originally part of awesomebar,
+ * but has been separated out so that other bar modules can take advantage of it.
+ * Both awesomebar and bartabgroups patches depend on this patch and it will be auto-enabled
+ * during compile time if it is needed. Note that if using flexipatch-finalizer this must be
+ * explicitly enabled.
+ * https://github.com/bakkeby/patches/blob/master/dwm/dwm-barmodules-wintitleactions-6.2.diff
+ */
+#define BAR_WINTITLEACTIONS_PATCH BAR_AWESOMEBAR_PATCH || BAR_TABGROUPS_PATCH || BAR_FLEXWINTITLE_PATCH
+
+/***
+ * Other patches
+ */
+
+/* Adds a window task switcher toggled using alt-tab.
+ * https://dwm.suckless.org/patches/alt-tab/
+ */
+#define ALT_TAB_PATCH 0
+
+/* All floating windows are centered, like the center patch, but without a rule.
+ * The center patch takes precedence over this patch.
+ * This patch interferes with the center transient windows patches.
+ * https://dwm.suckless.org/patches/alwayscenter/
+ */
+#define ALWAYSCENTER_PATCH 0
+
+/* This patch allows windows to be resized with its aspect ratio remaining constant.
+ * https://dwm.suckless.org/patches/aspectresize/
+ */
+#define ASPECTRESIZE_PATCH 0
+
+/* This patch adds new clients above the selected client, instead of always
+ * becoming the new master. This behaviour is known from Xmonad.
+ * This patch takes precedence over ATTACHASIDE_PATCH.
+ * https://dwm.suckless.org/patches/attachabove/
+ */
+#define ATTACHABOVE_PATCH 0
+
+/* This patch adds new clients on top of the stack.
+ * This patch takes precedence over ATTACHBELOW_PATCH.
+ * https://dwm.suckless.org/patches/attachaside/
+ */
+#define ATTACHASIDE_PATCH 0
+
+/* This patch adds new clients below the selected client.
+ * This patch takes precedence over ATTACHBOTTOM_PATCH.
+ * https://dwm.suckless.org/patches/attachbelow/
+ */
+#define ATTACHBELOW_PATCH 1
+
+/* This patch adds new clients at the bottom of the stack.
+ * https://dwm.suckless.org/patches/attachbottom/
+ */
+#define ATTACHBOTTOM_PATCH 0
+
+/* This patch will make dwm run "~/.local/share/dwm/autostart_blocking.sh" and
+ * "~/.local/share/dwm/autostart.sh &" before entering the handler loop. One or
+ * both of these files can be ommited. Note the path inside .local/share rather
+ * than the original ~/.dwm folder.
+ * https://dwm.suckless.org/patches/autostart/
+ */
+#define AUTOSTART_PATCH 0
+
+/* By default, windows that are not visible when requesting a resize/move will not
+ * get resized/moved. With this patch, they will.
+ * https://dwm.suckless.org/patches/autoresize/
+ */
+#define AUTORESIZE_PATCH 0
+
+/* This patch adds proper support for Right-To-Left languages. (such as Farsi, Arabic or Hebrew).
+ *
+ * You need to uncomment the corresponding lines in config.mk to use the -lfribidi library
+ * when including this patch.
+ *
+ * This patch depends on the following additional library:
+ * - fribidi
+ *
+ * https://dwm.suckless.org/patches/bidi/
+ */
+#define BIDI_PATCH 0
+
+/* This patch adds an iscentered rule to automatically center clients on the current monitor.
+ * This patch takes precedence over centeredwindowname, alwayscenter and fancybar patches.
+ * https://dwm.suckless.org/patches/center/
+ */
+#define CENTER_PATCH 0
+
+/* A transient window is one that is meant to be short lived and is usually raised by a
+ * parent window. Such windows are typically dialog boxes and the like.
+ * It should be noted that in dwm transient windows are not subject to normal client rules
+ * and they are always floating by default.
+ * This patch centers transient windows on the screen like the center patch does. Note that
+ * the 6.2 center patch piggy-backed on the updatewindowtype function to ensure that all
+ * dialog boxes were centered, transient or not. This function was removed in relation to
+ * adding wintype as a client rule filter, hence this no longer works out of the box. This
+ * patch restores previous behaviour with the center patch.
+ */
+#define CENTER_TRANSIENT_WINDOWS_PATCH 1
+
+/* As above, except that the transient window is centered within the position of the parent
+ * window, rather than at the center of the screen. This takes precedence over the above patch.
+ */
+#define CENTER_TRANSIENT_WINDOWS_BY_PARENT_PATCH 1
+
+/* This patch provides the ability to assign different weights to clients in their
+ * respective stack in tiled layout.
+ * https://dwm.suckless.org/patches/cfacts/
+ */
+#define CFACTS_PATCH 1
+
+/* This patch allows color attributes to be set through the command line.
+ * https://dwm.suckless.org/patches/cmdcustomize/
+ */
+#define CMDCUSTOMIZE_PATCH 0
+
+/* This patch tweaks the tagging interface so that you can select multiple tags for tag
+ * or view by pressing all the right keys as a combo. For example to view tags 1 and 3,
+ * hold MOD and then press and hold 1 and 3 together.
+ * https://dwm.suckless.org/patches/combo/
+ */
+#define COMBO_PATCH 0
+
+/* Allow dwm to execute commands from autostart array in your config.h file. When dwm exits
+ * then all processes from autostart array will be killed.
+ * https://dwm.suckless.org/patches/cool_autostart/
+ */
+#define COOL_AUTOSTART_PATCH 1
+
+/* The cyclelayouts patch lets you cycle through all your layouts.
+ * https://dwm.suckless.org/patches/cyclelayouts/
+ */
+#define CYCLELAYOUTS_PATCH 1
+
+/* Make dwm respect _MOTIF_WM_HINTS property, and not draw borders around windows requesting
+ * for it. Some applications use this property to notify window managers to not draw window
+ * decorations.
+ * Not respecting this property leads to issues with applications that draw their own borders,
+ * like chromium (with "Use system title bar and borders" turned off) or vlc in fullscreen mode.
+ * https://dwm.suckless.org/patches/decoration_hints/
+ */
+#define DECORATION_HINTS_PATCH 1
+
+/* This feature distributes all clients on the current monitor evenly across all tags.
+ * It is a variant of the reorganizetags patch.
+ * https://dwm.suckless.org/patches/reorganizetags/
+ */
+#define DISTRIBUTETAGS_PATCH 0
+
+/* By default dwm will terminate on color allocation failure and the behaviour is intended to
+ * catch and inform the user of color configuration issues.
+ *
+ * Some patches like status2d and xresources / xrdb can change colours during runtime, which
+ * means that if a color can't be allocated at this time then the window manager will abruptly
+ * terminate.
+ *
+ * This patch will ignore color allocation failures and continue on as normal. The effect of
+ * this is that the existing color, that was supposed to be replaced, will remain as-is.
+ */
+#define DO_NOT_DIE_ON_COLOR_ALLOCATION_FAILURE_PATCH 1
+
+/* Similarly to the dragmfact patch this allows you to click and drag clients to change the
+ * cfact to adjust the client's size in the stack. This patch depends on the cfacts patch.
+ */
+#define DRAGCFACT_PATCH 0
+
+/* This patch lets you resize the split in the tile layout (i.e. modify mfact) by holding
+ * the modkey and dragging the mouse.
+ * This patch can be a bit wonky with other layouts, but generally works.
+ * https://dwm.suckless.org/patches/dragmfact/
+ */
+#define DRAGMFACT_PATCH 0
+
+/* Simple dwmc client using a fork of fsignal to communicate with dwm.
+ * To use this either copy the patch/dwmc shell script to somewhere in your path or
+ * uncomment the following line in Makefile:
+ * #cp -f patch/dwmc ${DESTDIR}${PREFIX}/bin
+ * http://dwm.suckless.org/patches/dwmc/
+ */
+#define DWMC_PATCH 0
+
+/* This patch allows no tag at all to be selected. The result is that dwm will start with
+ * no tag selected and when you start a client with no tag rule and no tag selected then
+ * it will be opened on the first tag.
+ * https://dwm.suckless.org/patches/emptyview/
+ */
+#define EMPTYVIEW_PATCH 0
+
+/* This patch allows the user to change size and placement of floating windows using only the
+ * keyboard. It also allows for temporary vertical and horizontal extension of windows similar
+ * to other WMs fill command.
+ * https://dwm.suckless.org/patches/exresize/
+ */
+#define EXRESIZE_PATCH 0
+
+/* Only allow clients to "fullscreen" into the space currently given to them.
+ * As an example, this will allow you to view a fullscreen video in your browser on
+ * one half of the screen, while having the other half available for other tasks.
+ * This patch takes precedence over the fakefullscreen client patch below.
+ * https://dwm.suckless.org/patches/fakefullscreen/
+ */
+#define FAKEFULLSCREEN_PATCH 0
+
+/* Similarly to the fakefullscreen patch this patch only allows clients to "fullscreen" into
+ * the space currently given to them.
+ * The "twist" with this patch is that fake fullscreen can be toggled on a per client basis
+ * rather than applying to all clients globally.
+ * Also see the selectivefakefullscreen option that adds a rule option to enabled this on client
+ * startup.
+ */
+#define FAKEFULLSCREEN_CLIENT_PATCH 0
+
+/* This patch adds a float rule allowing the size and position of floating windows to be specified
+ * It also allows the size and position of floating windows to be controlled similar to the
+ * exresize, moveresize, and moveplace patches.
+ * The size and position can be specified using absolute, relative or fixed co-ordinates and
+ * https://github.com/bakkeby/patches/wiki/floatpos/
+ */
+#define FLOATPOS_PATCH 1
+
+/* Add-on functionality for the above: make the float positions respect outer (vanity)gaps. */
+#define FLOATPOS_RESPECT_GAPS_PATCH 0
+
+/* This patch provides the ability to focus the tag on the immediate left or right of the
+ * currently focused tag. It also allows to send the focused window either on the left or
+ * the right tag.
+ * http://dwm.suckless.org/patches/focusadjacenttag/
+ */
+#define FOCUSADJACENTTAG_PATCH 0
+
+/* Allows focusing on clients based on direction (up, down, left, right) instead of client order.
+ * https://github.com/bakkeby/patches/wiki/focusdir/
+ */
+#define FOCUSDIR_PATCH 0
+
+/* When changing tags, closing windows or moving clients out of view then focus will revert to the
+ * client window that remains under the mouse cursor rather than the most recently focused window.
+ * https://github.com/bakkeby/patches/wiki/focusfollowmouse
+ */
+#define FOCUSFOLLOWMOUSE_PATCH 0
+
+/* A simple patch that just puts focus back to the master client.
+ * https://dwm.suckless.org/patches/focusmaster/
+ */
+#define FOCUSMASTER_PATCH 0
+
+/* A variant of the focusmaster patch that additionally allows the focus to be returned to the
+ * previously focused client
+ * https://dwm.suckless.org/patches/focusmaster/
+ */
+#define FOCUSMASTER_RETURN_PATCH 0
+
+/* Switch focus only by mouse click and not sloppy (focus follows mouse pointer).
+ * https://dwm.suckless.org/patches/focusonclick/
+ */
+#define FOCUSONCLICK_PATCH 1
+
+/* Selects the next window having the urgent flag regardless of the tag it is on.
+ * The urgent flag can be artificially set with the following xdotool command on any window:
+ * xdotool selectwindow -- set_window --urgency 1
+ * https://dwm.suckless.org/patches/focusurgent/
+ */
+#define FOCUSURGENT_PATCH 0
+
+/* By default, dwm responds to _NET_ACTIVE_WINDOW client messages by setting
+ * the urgency bit on the named window. This patch activates the window instead.
+ * https://dwm.suckless.org/patches/focusonnetactive/
+ */
+#define FOCUSONNETACTIVE_PATCH 0
+
+/* Send "fake signals" to dwm for handling, using xsetroot. This will not conflict with the
+ * status bar, which also is managed using xsetroot.
+ * Also see the dwmc patch, which takes precedence over this patch.
+ * https://dwm.suckless.org/patches/fsignal/
+ */
+#define FSIGNAL_PATCH 0
+
+/* Applies the monocle layout with the focused client on top and hides the bar. When pressed
+ * again it shows the bar and restores the layout that was active before going fullscreen.
+ * https://dwm.suckless.org/patches/fullscreen/
+ */
+#define FULLSCREEN_PATCH 0
+
+/* This patch provides a keybinding to rotate all clients in the currently selected
+ * area (master or stack) without affecting the other area.
+ * https://dwm.suckless.org/patches/inplacerotate/
+ */
+#define INPLACEROTATE_PATCH 0
+
+/* This patch lets you define custom insets from each edge of the screen. One use case would be
+ * to arrange space for an external bar.
+ * https://dwm.suckless.org/patches/insets/
+ */
+#define INSETS_PATCH 0
+
+/* This patch (v1.5.7) implements inter-process communication through a UNIX socket for dwm. This
+ * allows for the window manager to be queried for information, e.g. listen for events such as tag
+ * or layout changes, as well as send commands to control the window manager via other programs.
+ *
+ * You need to uncomment the corresponding lines in config.mk to use the -lyajl library
+ * when including this patch.
+ * This patch depends on the following additional library:
+ * - yajl
+ *
+ * https://github.com/mihirlad55/dwm-ipc
+ * https://dwm.suckless.org/patches/ipc/
+ */
+#define IPC_PATCH 0
+
+/* Adds rule option for clients to avoid accidental termination by killclient for sticky windows.
+ * https://dwm.suckless.org/patches/ispermanent/
+ */
+#define ISPERMANENT_PATCH 0
+
+/* This patch adds key modes (like in vim or emacs) where chains of keyboard shortcuts
+ * can be performed.
+ * https://dwm.suckless.org/patches/keymodes/
+ */
+#define KEYMODES_PATCH 0
+
+/* This patch adds a keybinding to kills all visible clients that are not selected.
+ * https://dwm.suckless.org/patches/killunsel/
+ */
+#define KILLUNSEL_PATCH 0
+
+/* This changes the window manager name to LG3d instead of dwm as a workaround for Java
+ * applications that assume that the window manager is using window reparenting.
+ * Refer to the ISSUES secton of the dwm man page for more details.
+ */
+#define LG3D_PATCH 0
+
+/* By default in dwm it is possible to make an application fullscreen, then use
+ * the focusstack keybindings to focus on other windows beneath the current window.
+ * It is also possible to spawn new windows (e.g. a terminal) that end up getting
+ * focus while the previous window remains in fullscreen. This patch ensures that
+ * in such scenarios the previous window loses fullscreen.
+ * https://github.com/bakkeby/patches/blob/master/dwm/dwm-losefullscreen-6.2.diff
+ */
+#define LOSEFULLSCREEN_PATCH 1
+
+/* This patch adds helper functions for maximizing, horizontally and vertically, floating
+ * windows using keybindings.
+ * https://dwm.suckless.org/patches/maximize/
+ */
+#define MAXIMIZE_PATCH 0
+
+/* Control Music Player Daemon via keybinds.
+ * You need to uncomment the corresponding line in config.mk to use the -lmpdclient library
+ * when including this patch.
+ * This patch depends on the following additional library:
+ * - libmpdclient
+ * https://dwm.suckless.org/patches/mpdcontrol/
+ */
+#define MPDCONTROL_PATCH 0
+
+/* Adds rules per monitor, e.g. have default layouts per monitor.
+ * The use case for this is if the second monitor is vertical (i.e. rotated) then
+ * you may want to use a different default layout for this monitor than what is
+ * used for the main monitor. E.g. normal vertical split for main monitor and
+ * horizontal split for the second.
+ */
+#define MONITOR_RULES_PATCH 0
+
+/* Always display the the monocle-symbol as defined in config.h if the monocle-layout
+ * is activated. Do not display the number of open clients in the current tag.
+ * https://dwm.suckless.org/patches/monoclesymbol/
+ */
+#define MONOCLESYMBOL_PATCH 0
+
+/* Makes a window floating and 1/3rd the height and 1/3rd the width of the screen and is
+ * positioned in either the center or one of the 8 cardinal directions depending on which
+ * key is pressed.
+ * https://dwm.suckless.org/patches/moveplace/
+ */
+#define MOVEPLACE_PATCH 0
+
+/* This patch allows you to move and resize dwm's clients using keyboard bindings.
+ * https://dwm.suckless.org/patches/moveresize/
+ */
+#define MOVERESIZE_PATCH 0
+
+/* This patch allows you to move clients around in the stack and swap them with the master.
+ * https://dwm.suckless.org/patches/movestack/
+ */
+#define MOVESTACK_PATCH 0
+
+/* This patch allows you to change the names of tags during runtime.
+ *
+ * This is a bespoke version implemented specifically in relation to tagicons, which is integrated
+ * into dwm-flexipatch. By default it uses dmenu to retrieve the new name, but this can be
+ * customised via config along with the maximum text length and the format string.
+ *
+ * Special behaviour:
+ * - if more than one tag is selected then the name change applies to all selected tags
+ * - if tagicons is configured to have unique tags per monitor then the change only applies
+ * for the current monitor
+ * - the name change applies to the tag set that is active for the current tag:
+ * * if used in combination with BAR_ALTTAGSDECORATION_PATCH and there are clients on the
+ * given tag then the name change only applies to the ALT_TAGS_DECORATION tag set
+ * * if used in combination with the BAR_ALTERNATIVE_TAGS_PATCH and alternative tags are
+ * shown then the name change only applies to the ALTERNATIVE_TAGS tag set
+ * * if used in combination with both then BAR_ALTTAGSDECORATION_PATCH takes precedence
+ * * otherwise the name change applies to the DEFAULT_TAGS tag set
+ *
+ * https://dwm.suckless.org/patches/nametag/
+ */
+#define NAMETAG_PATCH 0
+
+/* Variant of the above which prepends the tag number to the given string.
+ * The toggle does nothing on its own and need to be enabled in combination with the above. */
+#define NAMETAG_PREPEND_PATCH 0
+
+/* Adds support for the _NET_CLIENT_LIST_STACKING atom, needed by certain applications like the
+ * Zoom video conferencing application.
+ * https://github.com/bakkeby/patches/wiki/netclientliststacking/
+ */
+#define NET_CLIENT_LIST_STACKING_PATCH 1
+
+/* Removes the border when there is only one window visible.
+ * https://dwm.suckless.org/patches/noborder/
+ */
+#define NOBORDER_PATCH 0
+
+/* Enable modifying or removing dmenu in config.def.h which resulted previously in a
+ * compilation error because two lines of code hardcode dmenu into dwm.
+ * https://dwm.suckless.org/patches/nodmenu/
+ */
+#define NODMENU_PATCH 1
+
+/* This patch allows for toggleable client button bindings that have no modifiers.
+ * This can, for example, allow you to move or resize using the mouse alone without holding
+ * down a modifier key. This can be practical if you have extra buttons on your mouse.
+ * While you can use button bindings with no modifiers without this patch in a bare dwm,
+ * those buttons are then unavailable for use within the application itself so being able to
+ * toggle these on and off can be necessary in certain situations (e.g. being able to use
+ * back and forward buttons in a browser).
+
+ * Example bindings:
+ * { ClkClientWin, 0, Button8, movemouse, {0} },
+ * { ClkClientWin, 0, Button9, resizemouse, {0} },
+ */
+#define NO_MOD_BUTTONS_PATCH 0
+
+/* When terminals have transparency then their borders also become transparent.
+ * This patch ensures that borders have no transparency. Note that this patch is
+ * only relevant if you are not using the alpha patch.
+ * https://github.com/szatanjl/dwm/commit/1529909466206016f2101457bbf37c67195714c8
+ * https://dwm.suckless.org/patches/alpha/dwm-fixborders-6.2.diff
+ */
+#define NO_TRANSPARENT_BORDERS_PATCH 0
+
+/* Port of InstantWM's on_empty_keys functionality allowing keybindings that apply only when
+ * a tag is empty. An example use case is being able to launch applications with first hand
+ * keys like "f" to launch firefox.
+ *
+ * https://github.com/instantOS/instantWM/
+ * https://github.com/bakkeby/dwm-flexipatch/issues/51
+ */
+#define ON_EMPTY_KEYS_PATCH 0
+
+/* Minor patch that prevents more than one rule being matched for a given client. */
+#define ONLY_ONE_RULE_MATCH_PATCH 0
+
+/* This patch makes it so dwm will only exit via quit() if no windows are open.
+ * This is to prevent you accidentally losing all your work.
+ * https://dwm.suckless.org/patches/onlyquitonempty/
+ */
+#define ONLYQUITONEMPTY_PATCH 0
+
+/* The pertag patch adds nmaster, mfacts and layouts per tag rather than per
+ * monitor (default).
+ * https://dwm.suckless.org/patches/pertag/
+ */
+#define PERTAG_PATCH 1
+
+/* Option to enable gaps on a per tag basis rather than globally.
+ * Depends on both pertag and vanitygaps patches being enabled.
+ */
+#define PERTAG_VANITYGAPS_PATCH 0
+
+/* This controls whether or not to also store bar position on a per
+ * tag basis, or leave it as one bar per monitor.
+ */
+#define PERTAGBAR_PATCH 0
+
+/* This patch lets you change the position of a client in the stack using the mouse.
+ * https://github.com/bakkeby/patches/wiki/placemouse
+ */
+#define PLACEMOUSE_PATCH 0
+
+/* This patch provides a way to move clients up and down inside the client list.
+ * https://dwm.suckless.org/patches/push/
+ */
+#define PUSH_PATCH 0
+
+/* This patch provides a way to move clients up and down inside the client list,
+ * but does not push up or down into the master area (except that it does not take
+ * nmaster into account).
+ * This takes precedence over the push patch above.
+ * https://dwm.suckless.org/patches/push/
+ */
+#define PUSH_NO_MASTER_PATCH 0
+
+/* Variant of the named scratchpads patch allowing scratch keys to be added or removed
+ * on demand, allowing multiple scratchpad windows to be toggled into and out of view
+ * in unison, as well as including multi-monitor support.
+ *
+ * https://github.com/bakkeby/patches/wiki/renamedscratchpads
+ */
+#define RENAMED_SCRATCHPADS_PATCH 1
+
+/* Renamed scratchpads option to auto-hide scratchpads when moving to a different tag.
+ * This behaviour is similar to that of the (multiple) scratchpads patch. */
+#define RENAMED_SCRATCHPADS_AUTO_HIDE_PATCH 1
+
+/* Shifts all clients per tag to leftmost unoccupied tags.
+ *
+ * For example, if clients A, B, C are tagged on tags 1, 5, 9 respectively, when
+ * this function is called, they will now be on 1, 2, and 3. The focused client
+ * will also remain focused.
+ *
+ * Clients on multiple tags will be treated as if they only were only on their
+ * leftmost tag, and will be reduced to one tag after the operation is complete.
+ * https://dwm.suckless.org/patches/reorganizetags/
+ */
+#define REORGANIZETAGS_PATCH 0
+
+/* By default, windows only resize from the bottom right corner. With this
+ * patch the mouse is warped to the nearest corner and you resize from there.
+ * https://dwm.suckless.org/patches/resizecorners/
+ */
+#define RESIZECORNERS_PATCH 0
+
+/* Practically the same as resizecorners, but the cursor does not warp to corners.
+ * This takes precedence over the resizecorners patch.
+ * https://github.com/bakkeby/patches/blob/master/dwm/dwm-resizepoint-6.2.diff
+ */
+#define RESIZEPOINT_PATCH 1
+
+/* Adds a keyboard shortcut to restart dwm or alternatively by using kill -HUP dwmpid.
+ * Additionally dwm can quit cleanly by using kill -TERM dwmpid.
+ * https://dwm.suckless.org/patches/restartsig/
+ */
+#define RESTARTSIG_PATCH 1
+
+/* Adds rio-like drawing to resize the selected client.
+ * This depends on an external tool slop being installed.
+ * This patch was backported from instantWM.
+ * https://github.com/bakkeby/patches/blob/master/dwm/dwm-riodraw-6.2.diff
+ */
+#define RIODRAW_PATCH 0
+
+/* This patch let's you rotate through the stack using keyboard shortcuts.
+ * https://dwm.suckless.org/patches/rotatestack/
+ */
+#define ROTATESTACK_PATCH 0
+
+/* This patch adds rounded corners to client windows in dwm.
+ * You need to uncomment the corresponding line in config.mk to use the -lXext library
+ * when including this patch. You will also want to set "borderpx = 0;" in your config.h.
+ * https://github.com/mitchweaver/suckless/blob/master/dwm/patches/mitch-06-rounded_corners-f04cac6d6e39cd9e3fc4fae526e3d1e8df5e34b2.patch
+ */
+#define ROUNDED_CORNERS_PATCH 0
+
+/* This patch saves size and position of every floating window before it is forced
+ * into tiled mode. If the window is made floating again then the old dimensions
+ * will be restored.
+ * https://dwm.suckless.org/patches/save_floats/
+ */
+#define SAVEFLOATS_PATCH 1
+
+/* The scratchpad patch allows you to spawn or restore floating terminal windows.
+ * It is typically useful when one need to do some short typing.
+ *
+ * Note that this patch changes TAGMASK to make room for special scratchpad tags,
+ * so ~0 does more than select all tags with this patch. Code that relies on ~0 to
+ * represent all tags should use ~SPTAGMASK instead.
+ *
+ * Upgraded to Christian Tenllado's multiple scratchpad version.
+ * https://lists.suckless.org/hackers/2004/17205.html
+ * https://dwm.suckless.org/patches/scratchpads/
+ */
+#define SCRATCHPADS_PATCH 0
+
+/* Minor alteration of the above allowing clients to keep their size and position when shown */
+#define SCRATCHPADS_KEEP_POSITION_AND_SIZE_PATCH 0
+
+/* This alternative patch enables a scratchpad feature in dwm similar to the scratchpad
+ * feature in i3wm.
+ * https://github.com/GasparVardanyan/dwm-scratchpad
+ */
+#define SCRATCHPAD_ALT_1_PATCH 0
+
+/* This patch persists some settings across window manager restarts. These include but are not
+ * limited to:
+ * - client's assigned tag(s) on which monitor
+ * - the order of clients
+ * - nmaster
+ * - selected layout
+ * - plus various additions depending on what other patches are used
+ *
+ * The above is not persisted across reboots, however.
+ */
+#define SEAMLESS_RESTART_PATCH 1
+
+/* As opposed to the original patch this only adds a rule option allowing fake fullscreen
+ * to be enabled for applications when they start. This is intended to be used in combination
+ * with the fakefullscreenclient patch and offers no practical functionality without it.
+ * https://dwm.suckless.org/patches/selectivefakefullscreen/
+ */
+#define SELECTIVEFAKEFULLSCREEN_PATCH 0
+
+/* Allows restarting dwm without the dependency of an external script.
+ * https://dwm.suckless.org/patches/selfrestart/
+ */
+#define SELFRESTART_PATCH 0
+
+/* Floating windows being sent to another monitor will be centered.
+ * https://dwm.suckless.org/patches/sendmoncenter/
+ */
+#define SENDMON_CENTER_PATCH 0
+
+/* This patch allow clients to keep focus when being sent to another monitor.
+ * https://github.com/bakkeby/patches/blob/master/dwm/dwm-sendmon_keepfocus-6.2.diff
+ */
+#define SENDMON_KEEPFOCUS_PATCH 1
+
+/* This patch allows border pixels to be changed during runtime.
+ * https://dwm.suckless.org/patches/setborderpx/
+ */
+#define SETBORDERPX_PATCH 0
+
+/* Combines shifttag and shiftview. Basically moves the window to the next/prev tag and follows it.
+ * Also see the focusadjacenttag patch.
+ * https://dwm.suckless.org/patches/shift-tools/
+ */
+#define SHIFTBOTH_PATCH 0
+
+/* Swaps all the clients on the current tag with all the client on the next/prev tag.
+ * Depends on the swaptags patch.
+ * https://dwm.suckless.org/patches/shift-tools/
+ */
+#define SHIFTSWAPTAGS_PATCH 0
+
+/* Moves the current selected client to the adjacent tag.
+ * Also see the focusadjacenttag patch.
+ * https://dwm.suckless.org/patches/shift-tools/
+ */
+#define SHIFTTAG_PATCH 0
+
+/* Moves the current selected client to the adjacent tag that has at least one client, if none
+ * then it acts as shifttag.
+ * https://dwm.suckless.org/patches/shift-tools/
+ */
+#define SHIFTTAGCLIENTS_PATCH 0
+
+/* This patch adds keybindings for left and right circular shift through tags.
+ * https://github.com/chau-bao-long/dotfiles/blob/master/suckless/dwm/shiftview.diff
+ */
+#define SHIFTVIEW_PATCH 0
+
+/* This variant of the shiftview patch adds left and right circular shift through tags,
+ * but skips tags where there are no clients.
+ */
+#define SHIFTVIEW_CLIENTS_PATCH 0
+
+/* This patch makes dwm obey even "soft" sizehints for new clients. Any window
+ * that requests a specific initial size will be floated and set to that size.
+ * Unlike with "fixed size" windows, you are able to resize and/or unfloat these
+ * windows freely - only the initial state is affected.
+ * This version of the patch is honestly of limited utility since there are many
+ * clients that will abuse it.
+ * https://dwm.suckless.org/patches/sizehints/
+ */
+#define SIZEHINTS_PATCH 0
+
+/* This patch makes dwm obey even "soft" sizehints for new clients. This ruled
+ * version is essentially the same patch except it obeys the "isfloating" rule
+ * if it is available in config.h for the given client.
+ * https://dwm.suckless.org/patches/sizehints/
+ */
+#define SIZEHINTS_RULED_PATCH 0
+
+/* This patch makes dwm obey even "soft" sizehints for new clients. The isfreesize
+ * version is similar to the sizehints ruled patch except it allows you to specify
+ * via client rules which clients this should apply to. Soft sizehints applies by
+ * default to clients that are not ruled, and will be disabled by default for clients
+ * that are.
+ *
+ * Example client rule enabling soft sizehints:
+ * - RULE(.wintype = WTYPE "DIALOG", .isfloating = 1, .isfreesize = 1)
+ *
+ * https://dwm.suckless.org/patches/sizehints/
+ */
+#define SIZEHINTS_ISFREESIZE_PATCH 1
+
+/* In a multi-head setup monitor 0 is by default the primary screen, with the left and right
+ * screen being monitor 1 and 2 respectively. This patch sorts screens left to right (or
+ * top to bottom in a vertical layout) which aims to address some inconsistencies when it
+ * comes to focusmon, tagmon and similar functionality.
+ * https://www.mail-archive.com/hackers@suckless.org/msg09400.html
+ */
+#define SORTSCREENS_PATCH 0
+
+/* Spawns programs from currently focused client's working directory.
+ * https://dwm.suckless.org/patches/spawn_cwd/
+ */
+#define SPAWNCMD_PATCH 0
+
+/* This patch provides comprehensive utilities for managing the client stack, providing
+ * keyboard shortcuts for focusing or placing a client at specific positions in the stack.
+ * Note that the default keybindings for this patch have been changed in dwm-flexipatch
+ * due to the many conflicts with other patches. As it provides similar functionality to the
+ * swapfocus patch it also uses the MOD+s shortcut to focus the previously selected client,
+ * thus note a conflict between these two patches.
+ * https://dwm.suckless.org/patches/stacker/
+ */
+#define STACKER_PATCH 1
+
+/* Steam, and steam windows (games), trigger a ConfigureNotify request every time the window
+ * gets focus. More so, the configure event passed along from Steam tends to have the wrong
+ * x and y co-ordinates which can make the window, if floating, jump around the screen.
+ *
+ * This patch works around this age-old issue by ignoring the x and y co-ordinates for
+ * ConfigureNotify requests relating to Steam windows.
+ *
+ * https://github.com/bakkeby/patches/wiki/steam
+ */
+#define STEAM_PATCH 0
+
+/* Adds toggleable keyboard shortcut to make a client 'sticky', i.e. visible on all tags.
+ * https://dwm.suckless.org/patches/sticky/
+ */
+#define STICKY_PATCH 0
+
+/* This patch adds "window swallowing" to dwm as known from Plan 9's windowing system rio.
+ * Clients marked with isterminal in config.h swallow a window opened by any child process,
+ * e.g. running xclock in a terminal. Closing the xclock window restores the terminal window
+ * in the current position.
+ *
+ * This patch depends on the following additional libraries:
+ * - libxcb
+ * - Xlib-libxcb
+ * - xcb-res
+ *
+ * You need to uncomment the corresponding line in config.mk to use the above libraries when
+ * including this patch.
+ *
+ * https://dwm.suckless.org/patches/swallow/
+ */
+#define SWALLOW_PATCH 1
+
+/* This patch depends on the pertag patch and makes it possible to switch focus with a single
+ * shortcut (MOD+s) instead of having to think if you should use mod-j or mod-k for reaching
+ * the previously used window.
+ * https://dwm.suckless.org/patches/swapfocus/
+ */
+#define SWAPFOCUS_PATCH 0
+
+/* This patch allows swapping the contents of the currently selected tag with another tag using
+ * keyboard shortcuts.
+ * https://dwm.suckless.org/patches/swaptags/
+ */
+#define SWAPTAGS_PATCH 0
+
+/* Switch focus between the master and stack columns using a single keybinding.
+ * https://dwm.suckless.org/patches/switchcol/
+ */
+#define SWITCHCOL_PATCH 0
+
+/* By default dwm allow you to set application specific rules so that you can have your browser,
+ * for example, start up on tag 9 optionally on a given monitor when you open your browser it is
+ * then automatically moved to the configured tag, but you have to manually enable the tag to see
+ * the newly opened application.
+ * This patch adds an extra configuration option for individual rules where:
+ * 0 is default behaviour
+ * 1 automatically moves you to the tag of the newly opened application and
+ * 2 enables the tag of the newly opened application in addition to your existing enabled tags
+ * 3 as 1, but closing that window reverts the view back to what it was previously (*)
+ * 4 as 2, but closing that window reverts the view back to what it was previously (*)
+ *
+ * (*) except if the client has been moved between tags or to another monitor
+ *
+ * https://github.com/bakkeby/patches/blob/master/dwm/dwm-switchtag-6.2.diff
+ * Also see https://dwm.suckless.org/patches/switchtotag
+ */
+#define SWITCHTAG_PATCH 0
+
+/* This patch transforms the monocle layout into a "tabbed" layout if more than one window is
+ * present on the monocle view. This patch has been added for demonstration purposes only and has
+ * limited compatibility with other patches. It will conflict space-wise with a second bar.
+ * Note that fancybar, awesomebar, bartabgroups and similar patches make the tab patch redundant.
+ * https://dwm.suckless.org/patches/tab/
+ */
+#define TAB_PATCH 0
+
+/* Adds keyboard shortcuts to move all (or only floating) windows from one tag to another.
+ * https://dwm.suckless.org/patches/tagall/
+ */
+#define TAGALL_PATCH 0
+
+/* This patch allows you to move all visible windows on a monitor to an adjacent monitor.
+ * https://github.com/bakkeby/patches/blob/master/dwm/dwm-tagallmon-6.2.diff
+ */
+#define TAGALLMON_PATCH 0
+
+/* This patch makes new clients attach into the stack area when you toggle a new tag into
+ * view. This means your master area will remain unchanged when toggling views.
+ * The allmaster patch will cause all clients in the master area to be left alone. This patch
+ * takes precedence over the onemaster tagintostack patch.
+ * https://dwm.suckless.org/patches/tagintostack/
+ */
+#define TAGINTOSTACK_ALLMASTER_PATCH 0
+
+/* This patch makes new clients attach into the stack area when you toggle a new tag into
+ * view. This means your master area will remain unchanged when toggling views.
+ * The onemaster patch will cause the first client in the master area to be left alone.
+ * https://dwm.suckless.org/patches/tagintostack/
+ */
+#define TAGINTOSTACK_ONEMASTER_PATCH 0
+
+/* If you try to send a fullscreen window to an adjacent monitor using tagmon then
+ * the window is moved behind the scenes, but it remains in fullscreen on the original
+ * monitor until you exit fullscreen view (at which point it will appear on the adjacent
+ * monitor). This patch allows a fullscreen window to be moved to an adjacent monitor
+ * while remaining in fullscreen.
+ * https://github.com/bakkeby/patches/blob/master/dwm/dwm-tagmonfixfs-6.2.diff
+ */
+#define TAGMONFIXFS_PATCH 1
+
+/* Add functions and keybindings to tag a window to a desired tag on the next (right)
+ * or previous (left) monitor from the currently selected monitor.
+ * https://dwm.suckless.org/patches/tagothermonitor/
+ */
+#define TAGOTHERMONITOR_PATCH 0
+
+/* This patch allows you to swap all visible windows on one monitor with those of an
+ * adjacent monitor.
+ * https://github.com/bakkeby/patches/blob/master/dwm/dwm-tagswapmon-6.2.diff
+ */
+#define TAGSWAPMON_PATCH 0
+
+/* Sync tag actions across all monitors.
+ * This is comparable to a sort of pseudo-desktop environment.
+ * Also refer to the desktop patch:
+ * https://github.com/bakkeby/patches/blob/master/dwm/dwm-desktop-6.3.diff
+ */
+#define TAGSYNC_PATCH 0
+
+/* This patch can be useful to the touchpad users because it allows to
+ * resize windows using Mod + two-finger scroll. It is useful when
+ * two-finger scrolling is configured in libinput.
+ * https://dwm.suckless.org/patches/tapresize/
+ */
+#define TAPRESIZE_PATCH 0
+
+/* This patch allows you to toggle fullscreen on and off using a single shortcut key.
+ * https://github.com/bakkeby/patches/blob/master/dwm/dwm-togglefullscreen-6.2.diff
+ */
+#define TOGGLEFULLSCREEN_PATCH 1
+
+/* This patch allows for the bar position (top or bottom) to be toggled during runtime.
+ * https://dwm.suckless.org/patches/toggletopbar/
+ */
+#define TOGGLETOPBAR_PATCH 0
+
+/* Minor patch that lets you use the same keyboard shortcut to toggle to the previous layout if the
+ * designated layout is already active.
+ *
+ * This allows you to use e.g. MOD+m to change to the monocle layout and use the same keybinding to
+ * toggle back to what it was previously. The default behaviour in dwm forces you to use either
+ * MOD+space or MOD+t to change back to tiled layout.
+ *
+ * https://github.com/bakkeby/patches/wiki/togglelayout
+ */
+
+#define TOGGLELAYOUT_PATCH 1
+
+/* Minor patch that lets you use the same keyboard shortcut to toggle to the previous tag if the
+ * designated tag is already active.
+ *
+ * This allows you to use e.g. MOD+4 to quickly view the 4th tag and use the same keybinding to
+ * toggle back to what it was previously. The default behaviour in dwm forces you to use either
+ * MOD+tab or MOD+1 to change back to the previous tag.
+ *
+ * Idea ref.
+ * https://www.reddit.com/r/suckless/comments/ik27vd/key_toggle_between_next_and_previous_tag_dwm/
+ * https://github.com/bakkeby/patches/wiki/toggletag
+ */
+#define TOGGLETAG_PATCH 1
+
+/* Lets you transfer the currently focused client between the master and stack area
+ * while increasing or decreasing the master area (nmaster) accordingly.
+ * https://dwm.suckless.org/patches/transfer/
+ */
+#define TRANSFER_PATCH 0
+
+/* Lets you transfer all clients between the master and stack area
+ * while increasing or decreasing the master area (nmaster) accordingly.
+ * https://dwm.suckless.org/patches/transfer/
+ */
+#define TRANSFER_ALL_PATCH 0
+
+/* This patch resets isfloating on any visible windows that have it set.
+ * Optionally also applies a layout.
+ * https://dwm.suckless.org/patches/unfloatvisible/
+ */
+#define UNFLOATVISIBLE_PATCH 0
+
+/* This patch adds a client rule that allows for windows that do not specify the override-redirect
+ * to not be managed by the window manager. This can be useful for external bars, widgets,
+ * launchers, docks, desktop icons and more.
+ * https://github.com/bakkeby/patches/wiki/unmanaged
+ */
+#define UNMANAGED_PATCH 0
+
+/* This patch adds configurable gaps between windows differentiating between outer, inner,
+ * horizontal and vertical gaps.
+ * https://github.com/bakkeby/patches/blob/master/dwm/dwm-vanitygaps-6.2.diff
+ * https://github.com/bakkeby/patches/blob/master/dwm/dwm-cfacts-vanitygaps-6.2.diff
+ */
+#define VANITYGAPS_PATCH 0
+
+/* This patch adds outer gaps for the monocle layout.
+ * Most gaps patches tries to avoid gaps on the monocle layout, as it is often used as a
+ * fullscreen mode, hence this is enabled separately from the main vanitygaps patch.
+ */
+#define VANITYGAPS_MONOCLE_PATCH 0
+
+/* By default MOD+Tab will take the user back to the previous tag only. If the user keeps
+ * using MOD+Tab then the view will switch back and forth between the current and previous tag.
+ * This patch allows dwm to keep a longer history of previous tag changes such that MOD+Tab can
+ * be pressed multiple times to go further back to earlier tag selections.
+ *
+ * The number of history elements is defined by the NUMVIEWHIST macro in dwm.c and defaults to
+ * the number of tags in the system.
+ */
+#define VIEW_HISTORY_PATCH 0
+
+/* Follow a window to the tag it is being moved to.
+ * https://dwm.suckless.org/patches/viewontag/
+ */
+#define VIEWONTAG_PATCH 0
+
+/* This patch warps the mouse cursor to the center of the currently focused window or screen
+ * when the mouse cursor is (a) on a different screen or (b) on top of a different window.
+ * https://dwm.suckless.org/patches/warp/
+ */
+#define WARP_PATCH 1
+
+/* Sometimes a single application opens different windows depending on the task
+ * at hand and this is often reflected in the WM_WINDOW_ROLE(STRING) x property.
+ * This patch adds the role field to the rule configuration so that one can
+ * differentiate between, say, Firefox "browser" vs "Preferences" vs "Manager"
+ * or Google-chrome "browser" vs "pop-up".
+ * https://github.com/bakkeby/patches/blob/master/dwm/dwm-windowrolerule-6.2.diff
+ */
+#define WINDOWROLERULE_PATCH 1
+
+/* The winview patch allows switching the view to that of a given client from the all-window
+ * view (Mod-0) using a keyboard shortcut.
+ * http://dwm.suckless.org/patches/winview/
+ */
+#define WINVIEW_PATCH 1
+
+/* Remember keyboard layout per client.
+ * It is recommended that you configure xkb before using this patch as described in
+ * https://www.x.org/archive/X11R7.5/doc/input/XKB-Config.html
+ * https://dwm.suckless.org/patches/xkb/
+ */
+#define XKB_PATCH 0
+
+/* Allows dwm to read colors from xrdb (.Xresources) during runtime. Compatible with
+ * the float border color, awesomebar, urgentborder and titlecolor patches.
+ * https://dwm.suckless.org/patches/xrdb/
+ */
+#define XRDB_PATCH 1
+
+/* Simple patch that allows floating windows to be zoomed into the master stack position.
+ * https://www.reddit.com/r/suckless/comments/ie5fe3/zoomfloating_my_own_simple_original_patch/
+ */
+#define ZOOMFLOATING_PATCH 0
+
+/* The zoomswap patch allows a master and a stack window to swap places
+ * rather than every window on the screen changing position.
+ * https://dwm.suckless.org/patches/zoomswap/
+ */
+#define ZOOMSWAP_PATCH 0
+
+/**
+ * Layouts
+ */
+
+/* Bottomstack layout.
+ * https://dwm.suckless.org/patches/bottomstack/
+ */
+#define BSTACK_LAYOUT 0
+
+/* Bottomstack horizontal layout.
+ * https://dwm.suckless.org/patches/bottomstack/
+ */
+#define BSTACKHORIZ_LAYOUT 0
+
+/* Centered master layout.
+ * https://dwm.suckless.org/patches/centeredmaster/
+ */
+#define CENTEREDMASTER_LAYOUT 0
+
+/* Centered floating master layout.
+ * https://dwm.suckless.org/patches/centeredmaster/
+ */
+#define CENTEREDFLOATINGMASTER_LAYOUT 0
+
+/* Same as the default tile layout except clients in the master area are arranged in
+ * columns (i.e. left to right).
+ * https://dwm.suckless.org/patches/columns/
+ */
+#define COLUMNS_LAYOUT 0
+
+/* Deck layout.
+ * https://dwm.suckless.org/patches/deck/
+ */
+#define DECK_LAYOUT 0
+
+/* Fibonacci dwindle layout.
+ * https://dwm.suckless.org/patches/fibonacci/
+ */
+#define FIBONACCI_DWINDLE_LAYOUT 0
+
+/* Fibonacci spiral layout.
+ * https://dwm.suckless.org/patches/fibonacci/
+ */
+#define FIBONACCI_SPIRAL_LAYOUT 0
+
+/* Flextile deluxe layout.
+ * A revamped, more flexible, and over-the-top version of the original flextile layout.
+ * https://dwm.suckless.org/patches/flextile/ (original)
+ */
+#define FLEXTILE_DELUXE_LAYOUT 1
+
+/* Gappless grid layout.
+ * https://dwm.suckless.org/patches/gaplessgrid/
+ */
+#define GAPPLESSGRID_LAYOUT 0
+
+/* Gridmode (grid) layout.
+ * https://dwm.suckless.org/patches/gridmode/
+ */
+#define GRIDMODE_LAYOUT 0
+
+/* Horizontal grid (horizgrid) layout.
+ * https://dwm.suckless.org/patches/horizgrid/
+ */
+#define HORIZGRID_LAYOUT 0
+
+/* Grid layout where nmaster controls the number of rows.
+ * https://dwm.suckless.org/patches/nrowgrid/
+ */
+#define NROWGRID_LAYOUT 0
+
+/* The default tile layout.
+ * This can be optionally disabled in favour of other layouts.
+ */
+#define TILE_LAYOUT 0
+
+/* Monocle layout (default).
+ * This can be optionally disabled in favour of other layouts.
+ */
+#define MONOCLE_LAYOUT 1
diff --git a/todo b/todo
new file mode 100644
index 0000000..59e3862
--- /dev/null
+++ b/todo
@@ -0,0 +1 @@
+# TODO: customize layoutmenu patch
diff --git a/transient.c b/transient.c
deleted file mode 100644
index 158460f..0000000
--- a/transient.c
+++ /dev/null
@@ -1,43 +0,0 @@
-/* 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);
-}
-
diff --git a/util.c b/util.c
deleted file mode 100644
index 0cdc035..0000000
--- a/util.c
+++ /dev/null
@@ -1,36 +0,0 @@
-/* See LICENSE file for copyright and license details. */
-#include <errno.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "util.h"
-
-void
-die(const char *fmt, ...)
-{
- va_list ap;
- int saved_errno;
-
- saved_errno = errno;
- va_start(ap, fmt);
- vfprintf(stderr, fmt, ap);
- va_end(ap);
-
- if (fmt[0] && fmt[strlen(fmt)-1] == ':')
- fprintf(stderr, " %s", strerror(saved_errno));
- fputc('\n', stderr);
-
- exit(1);
-}
-
-void *
-ecalloc(size_t nmemb, size_t size)
-{
- void *p;
-
- if (!(p = calloc(nmemb, size)))
- die("calloc:");
- return p;
-}
diff --git a/util.h b/util.h
deleted file mode 100644
index 72ba202..0000000
--- a/util.h
+++ /dev/null
@@ -1,20 +0,0 @@
-/* See LICENSE file for copyright and license details. */
-
-#ifndef MAX
-#define MAX(A, B) ((A) > (B) ? (A) : (B))
-#endif
-#ifndef MIN
-#define MIN(A, B) ((A) < (B) ? (A) : (B))
-#endif
-#define BETWEEN(X, A, B) ((A) <= (X) && (X) <= (B))
-#define LENGTH(X) (sizeof (X) / sizeof (X)[0])
-
-#ifdef _DEBUG
-#define DEBUG(...) fprintf(stderr, __VA_ARGS__)
-#else
-#define DEBUG(...)
-#endif
-
-void die(const char *fmt, ...);
-void *ecalloc(size_t nmemb, size_t size);
-