clean slate
This commit is contained in:
parent
b2604d36d1
commit
e639ef6f6d
|
@ -1,8 +0,0 @@
|
||||||
BasedOnStyle: Google
|
|
||||||
IndentWidth: 4
|
|
||||||
InsertBraces: true
|
|
||||||
ColumnLimit: 79
|
|
||||||
AlignConsecutiveMacros: Consecutive
|
|
||||||
AllowShortFunctionsOnASingleLine: None
|
|
||||||
AllowShortLoopsOnASingleLine: false
|
|
||||||
AllowShortIfStatementsOnASingleLine: Never
|
|
30
.clang-tidy
30
.clang-tidy
|
@ -1,30 +0,0 @@
|
||||||
Checks: |
|
|
||||||
-*,
|
|
||||||
abseil-*,
|
|
||||||
bugprone-*,
|
|
||||||
clang-analyzer-*,
|
|
||||||
misc-*,
|
|
||||||
modernize-*,
|
|
||||||
performance-*,
|
|
||||||
portability-*,
|
|
||||||
readability-*,
|
|
||||||
llvm-*,
|
|
||||||
-bugprone-easily-swappable-parameters,
|
|
||||||
-readability-avoid-const-params-in-decls,
|
|
||||||
-readability-identifier-length
|
|
||||||
|
|
||||||
CheckOptions:
|
|
||||||
- key: readability-inconsistent-declaration-parameter-name.Strict
|
|
||||||
value: true
|
|
||||||
- key: readability-identifier-naming.StructCase
|
|
||||||
value: lower_case
|
|
||||||
- key: readability-identifier-naming.FunctionCase
|
|
||||||
value: lower_case
|
|
||||||
- key: readability-identifier-naming.VariableCase
|
|
||||||
value: lower_case
|
|
||||||
- key: readability-identifier-naming.EnumConstantCase
|
|
||||||
value: UPPER_CASE
|
|
||||||
- key: readability-identifier-naming.MacroDefinitionCase
|
|
||||||
value: UPPER_CASE
|
|
||||||
- key: readability-function-cognitive-complexity.Threshold
|
|
||||||
value: 15
|
|
|
@ -1,6 +1,2 @@
|
||||||
compile_commands.json
|
|
||||||
.cache/clangd/index
|
|
||||||
drw.o
|
|
||||||
dwm
|
dwm
|
||||||
dwm.o
|
*.o
|
||||||
util.o
|
|
||||||
|
|
|
@ -1,59 +0,0 @@
|
||||||
when:
|
|
||||||
- event: tag
|
|
||||||
- event: manual
|
|
||||||
|
|
||||||
steps:
|
|
||||||
build:
|
|
||||||
image: gcc
|
|
||||||
environment:
|
|
||||||
- BUILD_DEPS=libx11-dev libx11-xcb-dev libxcb1-dev libxcb-res0-dev libxft-dev libxinerama-dev libfreetype6-dev libfontconfig1-dev
|
|
||||||
commands: |
|
|
||||||
apt-get update
|
|
||||||
apt-get install -y $${BUILD_DEPS}
|
|
||||||
make 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
|
|
||||||
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}" \
|
|
||||||
-c "$${CI_COMMIT_MESSAGE}" \
|
|
||||||
"$${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
|
|
38
LICENSE
38
LICENSE
|
@ -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.
|
|
50
Makefile
50
Makefile
|
@ -1,50 +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}
|
|
||||||
|
|
||||||
all: options dwm
|
|
||||||
|
|
||||||
options:
|
|
||||||
@echo dwm build options:
|
|
||||||
@echo "CFLAGS = ${CFLAGS}"
|
|
||||||
@echo "LDFLAGS = ${LDFLAGS}"
|
|
||||||
@echo "CC = ${CC}"
|
|
||||||
|
|
||||||
.c.o:
|
|
||||||
${CC} -c ${CFLAGS} $<
|
|
||||||
|
|
||||||
${OBJ}: config.h config.mk
|
|
||||||
|
|
||||||
config.h:
|
|
||||||
cp config.def.h $@
|
|
||||||
|
|
||||||
dwm: ${OBJ}
|
|
||||||
${CC} -o $@ ${OBJ} ${LDFLAGS}
|
|
||||||
|
|
||||||
clean:
|
|
||||||
rm -f dwm ${OBJ} dwm-${VERSION}.tar.gz
|
|
||||||
|
|
||||||
dist: clean
|
|
||||||
mkdir -p dwm-${VERSION}
|
|
||||||
cp -R LICENSE Makefile README config.def.h config.mk\
|
|
||||||
drw.h util.h ${SRC} transient.c dwm-${VERSION}
|
|
||||||
tar -cf dwm-${VERSION}.tar dwm-${VERSION}
|
|
||||||
gzip dwm-${VERSION}.tar
|
|
||||||
rm -rf dwm-${VERSION}
|
|
||||||
|
|
||||||
install: all
|
|
||||||
mkdir -p ${DESTDIR}${PREFIX}/bin
|
|
||||||
cp -f dwm ${DESTDIR}${PREFIX}/bin
|
|
||||||
chmod 755 ${DESTDIR}${PREFIX}/bin/dwm
|
|
||||||
mkdir -p ${DESTDIR}${PREFIX}/share/dwm
|
|
||||||
cp -f README.md ${DESTDIR}${PREFIX}/share/dwm/dwm.md
|
|
||||||
chmod 644 ${DESTDIR}${PREFIX}/share/dwm/dwm.md
|
|
||||||
|
|
||||||
uninstall:
|
|
||||||
rm -f ${DESTDIR}${PREFIX}/bin/dwm
|
|
||||||
|
|
||||||
.PHONY: all options clean dist install uninstall
|
|
94
README.md
94
README.md
|
@ -1,94 +0,0 @@
|
||||||
# Client/Tag Control
|
|
||||||
Modifier(s)|Key|Action
|
|
||||||
:--|:--|:--
|
|
||||||
Mod|0|Show all tags
|
|
||||||
Mod Shift|0|Make a client sticky
|
|
||||||
Mod|Tab|Focus last active client
|
|
||||||
Mod Shift|Tab|Move active client to top of stack
|
|
||||||
Mod|,|Focus previous monitor on stack
|
|
||||||
Mod Shift|,|Move active client to previous monitor on stack
|
|
||||||
Mod|.|Focus next monitor on stack
|
|
||||||
Mod Shift|.|Move active client to next monitor on stack
|
|
||||||
Mod|f|Toggle fullscreen on active client
|
|
||||||
Mod|q|Kill active client
|
|
||||||
Mod|j|Focus next client on stack
|
|
||||||
Mod Shift|j|Move active client down stack
|
|
||||||
Mod|k|Focus previous client on stack
|
|
||||||
Mod Shift|k|Move active client up stack
|
|
||||||
Mod|v|Focus first client on stack
|
|
||||||
Mod|space|Move active client to top of stack
|
|
||||||
Mod Shift|space|Make active client float
|
|
||||||
|
|
||||||
# Layout Control
|
|
||||||
Modifier(s)|Key|Action
|
|
||||||
:--|:--|:--
|
|
||||||
Mod|c|Increase number of master clients
|
|
||||||
Mod Shift|c|Reset number of master clients
|
|
||||||
Mod|r|Decrease number of master clients
|
|
||||||
Mod Shift|r|Reset number of master clients
|
|
||||||
Mod|l|Increase master area size
|
|
||||||
Mod|h|Decrease master area size
|
|
||||||
Mod|n|Switch to tile layout
|
|
||||||
Mod Shift|n|Switch to bottom stack layout
|
|
||||||
Mod|s|Switch to centered master layout
|
|
||||||
Mod Shift|s|Switch to grid layout
|
|
||||||
Mod|minus|Switch to monocle layout
|
|
||||||
Mod Shift|minus|Switch to horizontal bottom stack layout
|
|
||||||
|
|
||||||
# Spawn Programs
|
|
||||||
Modifier(s)|Key|Action
|
|
||||||
:--|:--|:--
|
|
||||||
Mod|g|Spawn wiki.vim scratchpad
|
|
||||||
Mod|t|Spawn a browser window
|
|
||||||
Mod Shift|t|Spawn a private browser window
|
|
||||||
Mod|o|Toggle HTOP (Process Manager) scratchpad
|
|
||||||
Mod Shift|o|Spawn an HTOP (Process Manager) window
|
|
||||||
Mod|e|Toggle LF (File Manager) scratchpad
|
|
||||||
Mod Shift|e|Spawn an LF (File Manager) window
|
|
||||||
Mod|u|Spawn launcher menu
|
|
||||||
Mod|backslash|Toggle calculator scratchpad
|
|
||||||
Mod|Return|Spawn a terminal window
|
|
||||||
Mod Shift|Return|Spawn a terminal scratchpad
|
|
||||||
Mod Alt|Return|Spawn a terminal window in working directory of active client
|
|
||||||
Mod|b|Spawn an NMTUI (Network Manager) window
|
|
||||||
Mod|w|Spawn Ferdium
|
|
||||||
|
|
||||||
# System
|
|
||||||
Modifier(s)|Key|Action
|
|
||||||
:--|:--|:--
|
|
||||||
Mod|i|Close the topmost notification
|
|
||||||
Mod Shift|i|Bring back the last closed notification
|
|
||||||
Mod|d|Open the context menu for the topmost notification
|
|
||||||
Mod Shift|d|Run the default action for the topmost notification
|
|
||||||
Mod|F2|Toggle Picom compositor
|
|
||||||
Mod|F3|Spawn volume panel
|
|
||||||
Mod|F5|Toggle Touchpad
|
|
||||||
Mod|F9|Spawn mounting menu
|
|
||||||
Mod|F10|Spawn unmounting menu
|
|
||||||
Mod|F11|Spawn display select menu
|
|
||||||
Mod|F12|Switch keyboard layout
|
|
||||||
Mod|BackSpace|Spawn system menu
|
|
||||||
Mod Shift|End|Kill DWM
|
|
||||||
Mod|Up|Increase volume by 5
|
|
||||||
Mod Shift|Up|Increase volume by 20
|
|
||||||
Mod|Down|Decrease volume by 5
|
|
||||||
Mod Shift|Down|Decrease volume by 20
|
|
||||||
Mod|m|Mute all sound
|
|
||||||
Mod Shift|m|Stop all players
|
|
||||||
Mod|p|Play or pause the last active player
|
|
||||||
|
|
||||||
# Misc.
|
|
||||||
Modifier(s)|Key|Action
|
|
||||||
:--|:--|:--
|
|
||||||
Mod Shift|b|Toggle status bar
|
|
||||||
Mod|F1|Show this help manual
|
|
||||||
Mod|\`|Spawn emoji/fontawesome picker, immediately paste
|
|
||||||
Mod Shift|\`|Spawn emoji/fontawesome picker, copy to clipboard
|
|
||||||
||Print|Make screenshot
|
|
||||||
Shift|Print|Spawn screenshot menu
|
|
||||||
Mod|Print|Spawn recording menu
|
|
||||||
Mod Shift|Print|Kill recording
|
|
||||||
Mod|Delete|Kill recording
|
|
||||||
Mod|Left|Play last track
|
|
||||||
Mod Shift|Left|Seek track to beginning
|
|
||||||
Mod|Right|Play next track
|
|
306
config.h
306
config.h
|
@ -1,306 +0,0 @@
|
||||||
/* See LICENSE file for copyright and license details. */
|
|
||||||
#define BROWSER "brave-browser"
|
|
||||||
#define BROWSER_FLAG "--enable-blink-features=MiddleClickAutoscroll"
|
|
||||||
#define INCOGNITO "--incognito"
|
|
||||||
#define TERMINAL "st"
|
|
||||||
#define PLAYERCTL "brave" /* this is currently only passed to playerctl as the client to control */
|
|
||||||
/* appearance */
|
|
||||||
static const unsigned int borderpx = 2;
|
|
||||||
static const unsigned int snap = 20;
|
|
||||||
static const int showbar = 1;
|
|
||||||
static const int topbar = 1;
|
|
||||||
static const int swallowfloating = 0;
|
|
||||||
static const unsigned int systraypinning = 0;
|
|
||||||
static const unsigned int systrayonleft = 0;
|
|
||||||
static const unsigned int systrayspacing = 2;
|
|
||||||
static const int systraypinningfailfirst = 1;
|
|
||||||
static const int showsystray = 1;
|
|
||||||
static const char *fonts[] = {
|
|
||||||
"FiraCode Nerd Font Mono:pixelsize=14",
|
|
||||||
"FiraCode Nerd Font Mono:pixelsize=20",
|
|
||||||
"FiraCode Nerd Font Mono:pixelsize=30",
|
|
||||||
"Noto Color Emoji:pixelsize=14",
|
|
||||||
"FontAwesome:pixelsize=14"
|
|
||||||
};
|
|
||||||
|
|
||||||
static const char color0[] = "#15161E";
|
|
||||||
static const char color1[] = "#f7768e";
|
|
||||||
static const char color2[] = "#9ece6a";
|
|
||||||
static const char color3[] = "#e0af68";
|
|
||||||
static const char color4[] = "#7aa2f7";
|
|
||||||
static const char color5[] = "#bb9af7";
|
|
||||||
static const char color6[] = "#7dcfff";
|
|
||||||
static const char color7[] = "#a9b1d6";
|
|
||||||
static const char color8[] = "#414868";
|
|
||||||
static const char color9[] = "#f7768e";
|
|
||||||
static const char color10[] = "#9ece6a";
|
|
||||||
static const char color11[] = "#e0af68";
|
|
||||||
static const char color12[] = "#7aa2f7";
|
|
||||||
static const char color13[] = "#bb9af7";
|
|
||||||
static const char color14[] = "#7dcfff";
|
|
||||||
static const char color15[] = "#c0caf5";
|
|
||||||
static const char bordernorm[] = "#383c4a";
|
|
||||||
static const char bordersel[] = "#7aa2f7";
|
|
||||||
|
|
||||||
static const char *barschemes[][3] = {
|
|
||||||
/* fg bg border */
|
|
||||||
[SchemeNorm] = { color15, color0, bordernorm },
|
|
||||||
[SchemeSel] = { color15, color4, bordersel },
|
|
||||||
[SchemeStatus] = { color7, color0, "#000000" }, // Statusbar right
|
|
||||||
[SchemeTagsSel] = { color0, color4, "#000000" }, // Tagbar left selected
|
|
||||||
[SchemeTagsNorm] = { color7, color0, "#000000" }, // Tagbar left unselected
|
|
||||||
[SchemeInfoSel] = { color7, color0, "#000000" }, // infobar middle selected
|
|
||||||
[SchemeInfoNorm] = { color7, color0, "#000000" }, // infobar middle unselected
|
|
||||||
};
|
|
||||||
|
|
||||||
/* tagging */
|
|
||||||
static const char *tags[] = {"1", "2", "3", "4", "5", "6", "7", "8", "9"};
|
|
||||||
|
|
||||||
static const Rule rules[] = {
|
|
||||||
/* xprop(1):
|
|
||||||
* WM_CLASS(STRING) = instance, class
|
|
||||||
* WM_NAME(STRING) = title
|
|
||||||
* If X, Y, W or H are between 0 and 1 (inclusive), their values interpreted as percentages of the current monitor resolution.
|
|
||||||
* If X or Y are negative, they are subtracted from the current monitor resolution and then that value is interpreted.
|
|
||||||
class instance title scratch key tags mask isfloating isterminal noswallow x, y, w, h borderpx */
|
|
||||||
{ NULL, NULL, "Event Tester", 0, 0, 0, 0, 1, 0, 0, 0, 0, -1 },
|
|
||||||
{ "Xournalpp", "xournalpp", NULL, 0, 0, 0, 0, -1, 0, 0, 0, 0, -1 },
|
|
||||||
{ "Zathura", "org.pwmt.zathura", NULL, 0, 0, 0, 0, -1, 0, 0, 0, 0, -1 },
|
|
||||||
{ NULL, "st", NULL, 0, 0, 0, 1, 0, 0, 0, 0, 0, -1 },
|
|
||||||
{ "Brave-browser", NULL, "Bitwarden", 0, 0, 1, 0, 0, .5, .5, .4, .8, -1 },
|
|
||||||
{ "Qalculate-gtk", NULL, NULL, 'q', 0, 1, 0, 0, .5, .5, 722, 512, -1 },
|
|
||||||
{ NULL, "sphelp", NULL, 'n', 0, 1, 0, 0, .5, .5, .4, .8, -1 },
|
|
||||||
{ NULL, "spterm", NULL, 't', 0, 1, 1, 0, .5, .5, .8, .8, -1 },
|
|
||||||
{ NULL, "splf", NULL, 'l', 0, 1, 0, 0, .5, .5, .8, .8, -1 },
|
|
||||||
{ NULL, "sphtop", NULL, 'h', 0, 1, 0, 0, .5, .5, .8, .8, -1 },
|
|
||||||
{ NULL, "spmix", NULL, 'm', 0, 1, 0, 0, -4, -4, 900, 600, -1 },
|
|
||||||
{ NULL, "spnmtui", NULL, 'i', 0, 1, 0, 0, -4, -4, 800, 800, -1 },
|
|
||||||
{ NULL, "spwiki", NULL, 'v', 0, 1, 0, 0, .5, .5, .8, .8, -1 },
|
|
||||||
};
|
|
||||||
|
|
||||||
/* 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 resizehints = 1; /* 1 means respect size hints in tiled resizals */
|
|
||||||
static const int lockfullscreen = 1; /* 1 will force focus on the fullscreen window */
|
|
||||||
|
|
||||||
static const Layout layouts[] = {
|
|
||||||
/* symbol arrange function */
|
|
||||||
{ "[]=", tile },
|
|
||||||
{ "TTT", bstack },
|
|
||||||
{ "|M|", centeredmaster },
|
|
||||||
{ ":::", gaplessgrid },
|
|
||||||
{ "[M]", monocle },
|
|
||||||
{ "===", bstackhoriz },
|
|
||||||
{ ">M>", centeredfloatingmaster },
|
|
||||||
{ "><>", NULL }, /* Floating */
|
|
||||||
};
|
|
||||||
|
|
||||||
/* 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} },
|
|
||||||
|
|
||||||
/* helper for spawning shell commands in the pre dwm-5.0 fashion */
|
|
||||||
#define SHCMD(cmd) { .v = (const char *[]) { "/bin/sh", "-c", cmd, NULL } }
|
|
||||||
|
|
||||||
/* commands */
|
|
||||||
static const char *spqalc[] = { "q", "qalculate-gtk", NULL };
|
|
||||||
static const char *spterm[] = { "t", TERMINAL, "-n", "spterm", "tmux", NULL };
|
|
||||||
static const char *splf[] = { "l", TERMINAL, "-n", "splf", "-e", "lf-sixel", NULL };
|
|
||||||
static const char *sphtop[] = { "h", TERMINAL, "-n", "sphtop", "-e", "htop", NULL };
|
|
||||||
static const char *spmix[] = { "m", TERMINAL, "-n", "spmix", "-e", "pulsemixer", NULL };
|
|
||||||
static const char *sphelp[] = { "n", TERMINAL, "-n", "sphelp", "-e", "/bin/sh", "-c", "mdcat /usr/share/dwm/dwm.md | less", NULL };
|
|
||||||
static const char *spnmtui[] = { "i", TERMINAL, "-n", "spnmtui", "-e", "nmtui", NULL };
|
|
||||||
static const char *spwiki[] = { "v", TERMINAL, "-n", "spwiki", "-e", "zk", "edit", "-i", NULL };
|
|
||||||
|
|
||||||
#include <X11/XF86keysym.h>
|
|
||||||
|
|
||||||
static const Key keys[] = {
|
|
||||||
/* modifier key function argument */
|
|
||||||
{ MODKEY, XK_F1, togglescratch, {.v = sphelp} },
|
|
||||||
{ MODKEY, XK_F2, spawn, {.v = (const char *[]){"togcom", NULL}} },
|
|
||||||
{ MODKEY, XK_F3, togglescratch, {.v = spmix} },
|
|
||||||
// { MODKEY, XK_F4, spawn, {.v = (const char *[]){NULL}} },
|
|
||||||
{ MODKEY, XK_F5, spawn, {.v = (const char *[]){"togtp", NULL}} },
|
|
||||||
// { MODKEY, XK_F6, spawn, {.v = (const char *[]){NULL}} },
|
|
||||||
// { MODKEY, XK_F7, spawn, {.v = (const char *[]){NULL}} },
|
|
||||||
// { MODKEY, XK_F8, spawn, {.v = (const char *[]){NULL}} },
|
|
||||||
{ MODKEY, XK_F9, spawn, {.v = (const char *[]){"dmenumount", NULL}} },
|
|
||||||
{ MODKEY, XK_F10, spawn, {.v = (const char *[]){"dmenuumount", NULL}} },
|
|
||||||
{ MODKEY, XK_F11, spawn, {.v = (const char *[]){"displayselect", NULL}} },
|
|
||||||
{ MODKEY, XK_F12, spawn, {.v = (const char *[]){"remaps", NULL}} },
|
|
||||||
{ MODKEY, XK_grave, spawn, {.v = (const char *[]){"dmenuunicode", "--nocopy", NULL}} },
|
|
||||||
{ MODKEY | ShiftMask, XK_grave, spawn, {.v = (const char *[]){"dmenuunicode", NULL}} },
|
|
||||||
TAGKEYS( XK_1, 0)
|
|
||||||
TAGKEYS( XK_2, 1)
|
|
||||||
TAGKEYS( XK_3, 2)
|
|
||||||
TAGKEYS( XK_4, 3)
|
|
||||||
TAGKEYS( XK_5, 4)
|
|
||||||
TAGKEYS( XK_6, 5)
|
|
||||||
TAGKEYS( XK_7, 6)
|
|
||||||
TAGKEYS( XK_8, 7)
|
|
||||||
TAGKEYS( XK_9, 8)
|
|
||||||
{ MODKEY, XK_0, view, {.ui = ~0} },
|
|
||||||
{ MODKEY | ShiftMask, XK_0, tag, {.ui = ~0} },
|
|
||||||
// { MODKEY, XK_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, {.v = (const char *[]){"sysact", NULL}} },
|
|
||||||
// { MODKEY | ShiftMask, XK_BackSpace, spawn, {.v = (const char *[]){NULL}} },
|
|
||||||
{ MODKEY, XK_Tab, focusstack, {.i = PREVSEL} },
|
|
||||||
// { 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} },
|
|
||||||
{ 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, togglefullscr, {0} },
|
|
||||||
// { MODKEY | ShiftMask, XK_f, setlayout, {.v = (const char *[]){NULL}} },
|
|
||||||
{ MODKEY, XK_g, togglescratch, {.v = spwiki} },
|
|
||||||
// { MODKEY | ShiftMask, XK_g, spawn, {.v = (const char *[]){NULL}} },
|
|
||||||
{ MODKEY, XK_c, incnmaster, {.i = +1} },
|
|
||||||
{ MODKEY | ShiftMask, XK_c, resetnmaster, {0} },
|
|
||||||
{ MODKEY, XK_r, incnmaster, {.i = -1} },
|
|
||||||
{ MODKEY | ShiftMask, XK_r, resetnmaster, {0} },
|
|
||||||
{ MODKEY, XK_l, setmfact, {.f = +0.05} },
|
|
||||||
// { MODKEY | ShiftMask, XK_l, spawn, {.v = (const char *[]){NULL}} },
|
|
||||||
// { 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, spawn, {.v = (const char *[]){NULL}} },
|
|
||||||
// { MODKEY | ShiftMask, XK_a, spawn, {.v = (const char *[]){NULL}} },
|
|
||||||
{ MODKEY, XK_o, togglescratch, {.v = sphtop} },
|
|
||||||
{ MODKEY | ShiftMask, XK_o, spawn, {.v = (const char *[]){TERMINAL, "-e", "htop", NULL}} },
|
|
||||||
{ MODKEY, XK_e, togglescratch, {.v = splf} },
|
|
||||||
// { 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}} },
|
|
||||||
{ 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, spawn, {.v = (const char *[]){NULL}} },
|
|
||||||
{ MODKEY, XK_t, spawn, {.v = (const char *[]){BROWSER, BROWSER_FLAG, NULL}} },
|
|
||||||
{ MODKEY | ShiftMask, XK_t, spawn, {.v = (const char *[]){BROWSER, BROWSER_FLAG, INCOGNITO, NULL}} },
|
|
||||||
{ MODKEY, XK_n, setlayout, {.v = &layouts[0]} },
|
|
||||||
{ MODKEY | ShiftMask, XK_n, setlayout, {.v = &layouts[1]} },
|
|
||||||
{ MODKEY, XK_s, setlayout, {.v = &layouts[2]} },
|
|
||||||
{ MODKEY | ShiftMask, XK_s, setlayout, {.v = &layouts[3]} },
|
|
||||||
{ MODKEY, XK_minus, setlayout, {.v = &layouts[4]} },
|
|
||||||
{ MODKEY | ShiftMask, XK_minus, setlayout, {.v = &layouts[5]} },
|
|
||||||
{ MODKEY, XK_backslash, togglescratch, {.v = spqalc} },
|
|
||||||
// { MODKEY | ShiftMask, XK_backslash, spawn, {.v = (const char *[]){NULL}} },
|
|
||||||
{ MODKEY, XK_Return, spawn, {.v = (const char *[]){TERMINAL, "tmux", NULL}} },
|
|
||||||
{ MODKEY | ShiftMask, XK_Return, togglescratch, {.v = spterm} },
|
|
||||||
{ MODKEY | Mod3Mask, XK_Return, spawn, {.v = (const char *[]){"sd", NULL}} },
|
|
||||||
// { MODKEY, XK_semicolon, spawn, {.v = (const char *[]){NULL}} },
|
|
||||||
// { MODKEY | ShiftMask, XK_semicolon, spawn, {.v = (const char *[]){NULL}} },
|
|
||||||
{ MODKEY, XK_q, killclient, {0} },
|
|
||||||
// { MODKEY | ShiftMask, XK_q, spawn, {.v = (const char *[]){NULL}} },
|
|
||||||
{ 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, spawn, {.v = (const char *[]){NULL}} },
|
|
||||||
// { MODKEY | ShiftMask, XK_x, spawn, {.v = (const char *[]){NULL}} },
|
|
||||||
{ MODKEY, XK_b, togglescratch, {.v = spnmtui} },
|
|
||||||
{ MODKEY | ShiftMask, XK_b, togglebar, {0} },
|
|
||||||
{ MODKEY, XK_m, spawn, {.v = (const char *[]){"pamixer-notify", "-t", NULL}} },
|
|
||||||
{ MODKEY | ShiftMask, XK_m, spawn, {.v = (const char *[]){"playerctl", "-a", "stop"}} },
|
|
||||||
{ MODKEY, XK_w, spawn, {.v = (const char *[]){"ferdium", NULL}} },
|
|
||||||
// { MODKEY | ShiftMask, XK_w, spawn, {.v = (const char *[]){NULL}} },
|
|
||||||
{ MODKEY, XK_v, focusstack, {.i = 0} },
|
|
||||||
{ MODKEY | ShiftMask, XK_v, pushstack, {.i = 0} },
|
|
||||||
// { MODKEY, XK_z, spawn, {.v = (const char *[]){NULL}} },
|
|
||||||
// { MODKEY | ShiftMask, XK_z, spawn, {.v = (const char *[]){NULL}} },
|
|
||||||
{ MODKEY, XK_space, zoom, {0} },
|
|
||||||
{ MODKEY | ShiftMask, XK_space, togglefloating, {0} },
|
|
||||||
{ 0, XK_Print, spawn, {.v = (const char *[]){"dmenumaim", "full", NULL}} },
|
|
||||||
{ ShiftMask, XK_Print, spawn, {.v = (const char *[]){"dmenumaim", NULL}} },
|
|
||||||
{ MODKEY, XK_Print, spawn, {.v = (const char *[]){"dmenurecord", NULL}} },
|
|
||||||
{ MODKEY | ShiftMask, XK_Print, spawn, {.v = (const char *[]){"dmenurecord", "kill", NULL}} },
|
|
||||||
// { MODKEY, XK_Scroll_Lock, spawn, {.v = (const char *[]){NULL}} },
|
|
||||||
// { MODKEY | ShiftMask, XK_Scroll_Lock, spawn, {.v = (const char *[]){NULL}} },
|
|
||||||
// { MODKEY, XK_Pause, spawn, {.v = (const char *[]){NULL}} },
|
|
||||||
// { MODKEY | ShiftMask, XK_Pause, spawn, {.v = (const char *[]){NULL}} },
|
|
||||||
// { MODKEY, XK_Insert, spawn, {.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 *[]){"dmenurecord", "kill", NULL}} },
|
|
||||||
// { MODKEY | ShiftMask, XK_Delete, spawn, {.v = (const char *[]){NULL}} },
|
|
||||||
// { MODKEY, XK_End, spawn, {.v = (const char *[]){NULL}} },
|
|
||||||
{ MODKEY | ShiftMask, XK_End, quit, {0} },
|
|
||||||
// { MODKEY, XK_Page_Down, spawn, {.v = (const char *[]){NULL}} },
|
|
||||||
// { MODKEY | ShiftMask, XK_Page_Down, spawn, {.v = (const char *[]){NULL}} },
|
|
||||||
{ MODKEY, XK_Left, spawn, {.v = (const char *[]){"playerctl", "-p", PLAYERCTL, "previous", NULL}} },
|
|
||||||
{ MODKEY | ShiftMask, XK_Left, spawn, {.v = (const char *[]){"playerctl", "-p", PLAYERCTL, "position", "0", NULL}} },
|
|
||||||
{ MODKEY, XK_Right, spawn, {.v = (const char *[]){"playerctl", "-p", PLAYERCTL, "next", NULL}} },
|
|
||||||
// { MODKEY | ShiftMask, XK_Right, spawn, {.v = (const char *[]){NULL}} },
|
|
||||||
{ MODKEY, XK_Up, spawn, {.v = (const char *[]){"pamixer-notify", "--allow-boost", "-i", "5", NULL}} },
|
|
||||||
{ MODKEY | ShiftMask, XK_Up, spawn, {.v = (const char *[]){"pamixer-notify", "--allow-boost", "-i", "20", NULL}} },
|
|
||||||
{ MODKEY, XK_Down, spawn, {.v = (const char *[]){"pamixer-notify", "--allow-boost", "-d", "5", NULL}} },
|
|
||||||
{ MODKEY | ShiftMask, XK_Down, spawn, {.v = (const char *[]){"pamixer-notify", "--allow-boost", "-d", "20", NULL}} },
|
|
||||||
|
|
||||||
{ 0, XF86XK_AudioMute, spawn, {.v = (const char *[]){"pamixer-notify", "-t", NULL}} },
|
|
||||||
{ 0, XF86XK_AudioRaiseVolume, spawn, {.v = (const char *[]){"pamixer-notify", "--allow-boost", "-i", "5", NULL}} },
|
|
||||||
{ 0, XF86XK_AudioLowerVolume, spawn, {.v = (const char *[]){"pamixer-notify", "--allow-boost", "-d", "5", NULL}} },
|
|
||||||
{ 0, XF86XK_AudioPrev, spawn, {.v = (const char *[]){"playerctl", "-p", PLAYERCTL, "previous", NULL}} },
|
|
||||||
{ 0, XF86XK_AudioNext, spawn, {.v = (const char *[]){"playerctl", "-p", PLAYERCTL, "next", NULL}} },
|
|
||||||
{ 0, XF86XK_AudioPause, spawn, {.v = (const char *[]){"playerctl", "-p", PLAYERCTL, "pause", NULL}} },
|
|
||||||
{ 0, XF86XK_AudioPlay, spawn, {.v = (const char *[]){"playerctl", "-p", PLAYERCTL, "play-pause", NULL}} }, // Most keyboards only have a play button
|
|
||||||
{ 0, XF86XK_AudioStop, spawn, {.v = (const char *[]){"playerctl", "-p", PLAYERCTL, "stop", NULL}} },
|
|
||||||
{ 0, XF86XK_AudioRewind, spawn, {.v = (const char *[]){"playerctl", "-p", PLAYERCTL, "position", "10-", NULL}} },
|
|
||||||
{ 0, XF86XK_AudioForward, spawn, {.v = (const char *[]){"playerctl", "-p", PLAYERCTL, "position", "10+", NULL}} },
|
|
||||||
// { 0, XF86XK_AudioMedia, spawn, {.v = (const char *[]){NULL}} },
|
|
||||||
{ 0, XF86XK_AudioMicMute, spawn, {.v = (const char *[]){"pactl set-source-mute @DEFAULT_SOURCE@ toggle", NULL}} },
|
|
||||||
// { 0, XF86XK_PowerOff, spawn, {.v = (const char *[]){"sysact", NULL}} },
|
|
||||||
{ 0, XF86XK_PowerOff, spawn, {.v = (const char *[]){"alarm-troll", NULL}} },
|
|
||||||
{ 0, XF86XK_Calculator, spawn, {.v = (const char *[]){TERMINAL, "-e", "bc", "-l", NULL}} },
|
|
||||||
{ 0, XF86XK_Sleep, spawn, {.v = (const char *[]){"sudo", "-A", "zzz", NULL}} },
|
|
||||||
{ 0, XF86XK_WWW, spawn, {.v = (const char *[]){BROWSER, BROWSER_FLAG, NULL}} },
|
|
||||||
{ 0, XF86XK_WLAN, spawn, SHCMD("sleep 0.1; pkill -RTMIN+4 dwmblocks") },
|
|
||||||
{ 0, XF86XK_DOS, spawn, {.v = (const char *[]){TERMINAL, NULL}} },
|
|
||||||
{ 0, XF86XK_ScreenSaver, spawn, SHCMD("xset s activate & mpc pause & pauseallmpv") },
|
|
||||||
{ 0, XF86XK_TaskPane, spawn, {.v = (const char *[]){TERMINAL, "-e", "htop", NULL}} },
|
|
||||||
{ 0, XF86XK_Mail, spawn, SHCMD("$TERMINAL -e neomutt; pkill -RTMIN+12 dwmblocks") },
|
|
||||||
{ 0, XF86XK_MyComputer, spawn, {.v = (const char *[]){TERMINAL, "-e", "lfub", "/", NULL}} },
|
|
||||||
// { 0, XF86XK_Battery, spawn, {.v = (const char *[]){NULL}} },
|
|
||||||
{ 0, XF86XK_Launch1, spawn, {.v = (const char *[]){"xset", "dpms", "force", "off", NULL}} },
|
|
||||||
{ 0, XF86XK_TouchpadToggle, spawn, SHCMD("(synclient | grep 'TouchpadOff.*1' && synclient TouchpadOff=0) || " "synclient TouchpadOff=1") },
|
|
||||||
{ 0, XF86XK_TouchpadOff, spawn, {.v = (const char *[]){"synclient", "TouchpadOff=1", NULL}} },
|
|
||||||
{ 0, XF86XK_TouchpadOn, spawn, {.v = (const char *[]){"synclient", "TouchpadOff=0", NULL}} },
|
|
||||||
/* WARN: If you have multiple backlight controllers this will fail */
|
|
||||||
{ 0, XF86XK_MonBrightnessUp, spawn, {.v = (const char *[]){"brightness-notify", "+5", NULL}} },
|
|
||||||
{ 0, XF86XK_MonBrightnessDown, spawn, {.v = (const char *[]){"brightness-notify", "-5", NULL}} },
|
|
||||||
};
|
|
||||||
|
|
||||||
/* button definitions */
|
|
||||||
static Button buttons[] = {
|
|
||||||
/* click event mask button function argument */
|
|
||||||
// { ClkLtSymbol, 0, Button1, setlayout, {0} },
|
|
||||||
// { ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]} },
|
|
||||||
// { ClkWinTitle, 0, Button2, zoom, {0} },
|
|
||||||
{ ClkClientWin, MODKEY, Button1, movemouse, {0} },
|
|
||||||
{ ClkClientWin, MODKEY, Button2, togglefloating, {0} },
|
|
||||||
{ ClkClientWin, MODKEY, Button3, resizemouse, {0} },
|
|
||||||
{ ClkTagBar, 0, Button1, view, {0} },
|
|
||||||
// { ClkTagBar, 0, Button3, toggleview, {0} },
|
|
||||||
// { ClkTagBar, MODKEY, Button1, tag, {0} },
|
|
||||||
// { ClkTagBar, MODKEY, Button3, toggletag, {0} },
|
|
||||||
};
|
|
||||||
/* click can be ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, or ClkRootWin */
|
|
38
config.mk
38
config.mk
|
@ -1,38 +0,0 @@
|
||||||
# dwm version
|
|
||||||
VERSION = 6.4
|
|
||||||
|
|
||||||
# Customize below to fit your system
|
|
||||||
|
|
||||||
# paths
|
|
||||||
PREFIX = /usr/local
|
|
||||||
|
|
||||||
X11INC = /usr/include/X11
|
|
||||||
X11LIB = /usr/lib/X11
|
|
||||||
|
|
||||||
# Xinerama, comment if you don't want it
|
|
||||||
XINERAMALIBS = -lXinerama
|
|
||||||
XINERAMAFLAGS = -DXINERAMA
|
|
||||||
|
|
||||||
# freetype
|
|
||||||
FREETYPELIBS = -lfontconfig -lXft
|
|
||||||
FREETYPEINC = /usr/include/freetype2
|
|
||||||
# OpenBSD (uncomment)
|
|
||||||
#FREETYPEINC = ${X11INC}/freetype2
|
|
||||||
#KVMLIB = -lkvm
|
|
||||||
|
|
||||||
# includes and libs
|
|
||||||
INCS = -I${X11INC} -I${FREETYPEINC}
|
|
||||||
LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} -lX11-xcb -lxcb -lxcb-res ${KVMLIB}
|
|
||||||
|
|
||||||
# flags
|
|
||||||
CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_POSIX_C_SOURCE=200809L -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS}
|
|
||||||
#CFLAGS = -g -std=c99 -pedantic -Wall -O0 ${INCS} ${CPPFLAGS}
|
|
||||||
CFLAGS = -std=c99 -pedantic -Wall -Wno-deprecated-declarations -Os ${INCS} ${CPPFLAGS}
|
|
||||||
LDFLAGS = ${LIBS}
|
|
||||||
|
|
||||||
# Solaris
|
|
||||||
#CFLAGS = -fast ${INCS} -DVERSION=\"${VERSION}\"
|
|
||||||
#LDFLAGS = ${LIBS}
|
|
||||||
|
|
||||||
# compiler and linker
|
|
||||||
CC = cc
|
|
411
drw.c
411
drw.c
|
@ -1,411 +0,0 @@
|
||||||
/* See LICENSE file for copyright and license details. */
|
|
||||||
#include <X11/Xft/Xft.h>
|
|
||||||
#include <X11/Xlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "drw.h"
|
|
||||||
#include "util.h"
|
|
||||||
|
|
||||||
#define UTF_INVALID 0xFFFD
|
|
||||||
#define UTF_SIZ 4
|
|
||||||
|
|
||||||
static const unsigned char utfbyte[UTF_SIZ + 1] = {0x80, 0, 0xC0, 0xE0, 0xF0};
|
|
||||||
static const unsigned char utfmask[UTF_SIZ + 1] = {0xC0, 0x80, 0xE0, 0xF0, 0xF8};
|
|
||||||
static const long utfmin[UTF_SIZ + 1] = {0, 0, 0x80, 0x800, 0x10000};
|
|
||||||
static const long utfmax[UTF_SIZ + 1] = {0x10FFFF, 0x7F, 0x7FF, 0xFFFF, 0x10FFFF};
|
|
||||||
|
|
||||||
static long utf8decodebyte(const char c, size_t *i) {
|
|
||||||
for (*i = 0; *i < (UTF_SIZ + 1); ++(*i))
|
|
||||||
if (((unsigned char)c & utfmask[*i]) == utfbyte[*i])
|
|
||||||
return (unsigned char)c & ~utfmask[*i];
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static size_t utf8validate(long *u, size_t i) {
|
|
||||||
if (!BETWEEN(*u, utfmin[i], utfmax[i]) || BETWEEN(*u, 0xD800, 0xDFFF))
|
|
||||||
*u = UTF_INVALID;
|
|
||||||
for (i = 1; *u > utfmax[i]; ++i)
|
|
||||||
;
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
|
|
||||||
static size_t utf8decode(const char *c, long *u, size_t clen) {
|
|
||||||
size_t i, j, len, type;
|
|
||||||
long udecoded;
|
|
||||||
|
|
||||||
*u = UTF_INVALID;
|
|
||||||
if (!clen)
|
|
||||||
return 0;
|
|
||||||
udecoded = utf8decodebyte(c[0], &len);
|
|
||||||
if (!BETWEEN(len, 1, UTF_SIZ))
|
|
||||||
return 1;
|
|
||||||
for (i = 1, j = 1; i < clen && j < len; ++i, ++j) {
|
|
||||||
udecoded = (udecoded << 6) | utf8decodebyte(c[i], &type);
|
|
||||||
if (type)
|
|
||||||
return j;
|
|
||||||
}
|
|
||||||
if (j < len)
|
|
||||||
return 0;
|
|
||||||
*u = udecoded;
|
|
||||||
utf8validate(u, len);
|
|
||||||
|
|
||||||
return len;
|
|
||||||
}
|
|
||||||
|
|
||||||
Drw *drw_create(Display *dpy, int screen, Window root, unsigned int w, unsigned int h) {
|
|
||||||
Drw *drw = ecalloc(1, sizeof(Drw));
|
|
||||||
|
|
||||||
drw->dpy = dpy;
|
|
||||||
drw->screen = screen;
|
|
||||||
drw->root = root;
|
|
||||||
drw->w = w;
|
|
||||||
drw->h = h;
|
|
||||||
drw->drawable = XCreatePixmap(dpy, root, w, h, DefaultDepth(dpy, screen));
|
|
||||||
drw->gc = XCreateGC(dpy, root, 0, NULL);
|
|
||||||
XSetLineAttributes(dpy, drw->gc, 1, LineSolid, CapButt, JoinMiter);
|
|
||||||
|
|
||||||
return drw;
|
|
||||||
}
|
|
||||||
|
|
||||||
void drw_resize(Drw *drw, unsigned int w, unsigned int h) {
|
|
||||||
if (!drw)
|
|
||||||
return;
|
|
||||||
|
|
||||||
drw->w = w;
|
|
||||||
drw->h = h;
|
|
||||||
if (drw->drawable)
|
|
||||||
XFreePixmap(drw->dpy, drw->drawable);
|
|
||||||
drw->drawable = XCreatePixmap(drw->dpy, drw->root, w, h, DefaultDepth(drw->dpy, drw->screen));
|
|
||||||
}
|
|
||||||
|
|
||||||
void drw_free(Drw *drw) {
|
|
||||||
XFreePixmap(drw->dpy, drw->drawable);
|
|
||||||
XFreeGC(drw->dpy, drw->gc);
|
|
||||||
drw_fontset_free(drw->fonts);
|
|
||||||
free(drw);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* This function is an implementation detail. Library users should use
|
|
||||||
* drw_fontset_create instead.
|
|
||||||
*/
|
|
||||||
static Fnt *xfont_create(Drw *drw, const char *fontname, FcPattern *fontpattern) {
|
|
||||||
Fnt *font;
|
|
||||||
XftFont *xfont = NULL;
|
|
||||||
FcPattern *pattern = NULL;
|
|
||||||
|
|
||||||
if (fontname) {
|
|
||||||
/* Using the pattern found at font->xfont->pattern does not yield the
|
|
||||||
* same substitution results as using the pattern returned by
|
|
||||||
* FcNameParse; using the latter results in the desired fallback
|
|
||||||
* behaviour whereas the former just results in missing-character
|
|
||||||
* rectangles being drawn, at least with some fonts. */
|
|
||||||
if (!(xfont = XftFontOpenName(drw->dpy, drw->screen, fontname))) {
|
|
||||||
fprintf(stderr, "error, cannot load font from name: '%s'\n", fontname);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
if (!(pattern = FcNameParse((FcChar8 *)fontname))) {
|
|
||||||
fprintf(stderr, "error, cannot parse font name to pattern: '%s'\n", fontname);
|
|
||||||
XftFontClose(drw->dpy, xfont);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
} else if (fontpattern) {
|
|
||||||
if (!(xfont = XftFontOpenPattern(drw->dpy, fontpattern))) {
|
|
||||||
fprintf(stderr, "error, cannot load font from pattern.\n");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
die("no font specified.");
|
|
||||||
}
|
|
||||||
|
|
||||||
font = ecalloc(1, sizeof(Fnt));
|
|
||||||
font->xfont = xfont;
|
|
||||||
font->pattern = pattern;
|
|
||||||
font->h = xfont->ascent + xfont->descent;
|
|
||||||
font->dpy = drw->dpy;
|
|
||||||
|
|
||||||
return font;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void xfont_free(Fnt *font) {
|
|
||||||
if (!font)
|
|
||||||
return;
|
|
||||||
if (font->pattern)
|
|
||||||
FcPatternDestroy(font->pattern);
|
|
||||||
XftFontClose(font->dpy, font->xfont);
|
|
||||||
free(font);
|
|
||||||
}
|
|
||||||
|
|
||||||
Fnt *drw_fontset_create(Drw *drw, const char *fonts[], size_t fontcount) {
|
|
||||||
Fnt *cur, *ret = NULL;
|
|
||||||
size_t i;
|
|
||||||
|
|
||||||
if (!drw || !fonts)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
for (i = 1; i <= fontcount; i++) {
|
|
||||||
if ((cur = xfont_create(drw, fonts[fontcount - i], NULL))) {
|
|
||||||
cur->next = ret;
|
|
||||||
ret = cur;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return (drw->fonts = ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
void drw_fontset_free(Fnt *font) {
|
|
||||||
if (font) {
|
|
||||||
drw_fontset_free(font->next);
|
|
||||||
xfont_free(font);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void drw_clr_create(Drw *drw, Clr *dest, const char *clrname) {
|
|
||||||
if (!drw || !dest || !clrname)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!XftColorAllocName(drw->dpy, DefaultVisual(drw->dpy, drw->screen),
|
|
||||||
DefaultColormap(drw->dpy, drw->screen), clrname, dest))
|
|
||||||
die("error, cannot allocate color '%s'", clrname);
|
|
||||||
|
|
||||||
dest->pixel |= 0xff << 24;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Wrapper to create color schemes. The caller has to call free(3) on the
|
|
||||||
* returned color scheme when done using it. */
|
|
||||||
Clr *drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount) {
|
|
||||||
int i;
|
|
||||||
Clr *ret;
|
|
||||||
|
|
||||||
/* need at least two colors for a scheme */
|
|
||||||
if (!drw || !clrnames || clrcount < 2 || !(ret = ecalloc(clrcount, sizeof(XftColor))))
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
for (i = 0; i < clrcount; i++)
|
|
||||||
drw_clr_create(drw, &ret[i], clrnames[i]);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
void drw_setfontset(Drw *drw, Fnt *set) {
|
|
||||||
if (drw)
|
|
||||||
drw->fonts = set;
|
|
||||||
}
|
|
||||||
|
|
||||||
void drw_setscheme(Drw *drw, Clr *scm) {
|
|
||||||
if (drw)
|
|
||||||
drw->scheme = scm;
|
|
||||||
}
|
|
||||||
|
|
||||||
void drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int invert) {
|
|
||||||
if (!drw || !drw->scheme)
|
|
||||||
return;
|
|
||||||
XSetForeground(drw->dpy, drw->gc, invert ? drw->scheme[ColBg].pixel : drw->scheme[ColFg].pixel);
|
|
||||||
if (filled)
|
|
||||||
XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h);
|
|
||||||
else
|
|
||||||
XDrawRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w - 1, h - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
int drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad,
|
|
||||||
const char *text, int invert) {
|
|
||||||
int i, ty, ellipsis_x = 0;
|
|
||||||
unsigned int tmpw, ew, ellipsis_w = 0, ellipsis_len;
|
|
||||||
XftDraw *d = NULL;
|
|
||||||
Fnt *usedfont, *curfont, *nextfont;
|
|
||||||
int utf8strlen, utf8charlen, render = x || y || w || h;
|
|
||||||
long utf8codepoint = 0;
|
|
||||||
const char *utf8str;
|
|
||||||
FcCharSet *fccharset;
|
|
||||||
FcPattern *fcpattern;
|
|
||||||
FcPattern *match;
|
|
||||||
XftResult result;
|
|
||||||
int charexists = 0, overflow = 0;
|
|
||||||
/* keep track of a couple codepoints for which we have no match. */
|
|
||||||
enum { nomatches_len = 64 };
|
|
||||||
static struct {
|
|
||||||
long codepoint[nomatches_len];
|
|
||||||
unsigned int idx;
|
|
||||||
} nomatches;
|
|
||||||
static unsigned int ellipsis_width = 0;
|
|
||||||
|
|
||||||
if (!drw || (render && (!drw->scheme || !w)) || !text || !drw->fonts)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (!render) {
|
|
||||||
w = invert ? invert : ~invert;
|
|
||||||
} else {
|
|
||||||
XSetForeground(drw->dpy, drw->gc, drw->scheme[invert ? ColFg : ColBg].pixel);
|
|
||||||
XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h);
|
|
||||||
d = XftDrawCreate(drw->dpy, drw->drawable, DefaultVisual(drw->dpy, drw->screen),
|
|
||||||
DefaultColormap(drw->dpy, drw->screen));
|
|
||||||
x += lpad;
|
|
||||||
w -= lpad;
|
|
||||||
}
|
|
||||||
|
|
||||||
usedfont = drw->fonts;
|
|
||||||
if (!ellipsis_width && render)
|
|
||||||
ellipsis_width = drw_fontset_getwidth(drw, "...");
|
|
||||||
while (1) {
|
|
||||||
ew = ellipsis_len = utf8strlen = 0;
|
|
||||||
utf8str = text;
|
|
||||||
nextfont = NULL;
|
|
||||||
while (*text) {
|
|
||||||
utf8charlen = utf8decode(text, &utf8codepoint, UTF_SIZ);
|
|
||||||
for (curfont = drw->fonts; curfont; curfont = curfont->next) {
|
|
||||||
charexists = charexists || XftCharExists(drw->dpy, curfont->xfont, utf8codepoint);
|
|
||||||
if (charexists) {
|
|
||||||
drw_font_getexts(curfont, text, utf8charlen, &tmpw, NULL);
|
|
||||||
if (ew + ellipsis_width <= w) {
|
|
||||||
/* keep track where the ellipsis still fits */
|
|
||||||
ellipsis_x = x + ew;
|
|
||||||
ellipsis_w = w - ew;
|
|
||||||
ellipsis_len = utf8strlen;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ew + tmpw > w) {
|
|
||||||
overflow = 1;
|
|
||||||
/* called from drw_fontset_getwidth_clamp():
|
|
||||||
* it wants the width AFTER the overflow
|
|
||||||
*/
|
|
||||||
if (!render)
|
|
||||||
x += tmpw;
|
|
||||||
else
|
|
||||||
utf8strlen = ellipsis_len;
|
|
||||||
} else if (curfont == usedfont) {
|
|
||||||
utf8strlen += utf8charlen;
|
|
||||||
text += utf8charlen;
|
|
||||||
ew += tmpw;
|
|
||||||
} else {
|
|
||||||
nextfont = curfont;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (overflow || !charexists || nextfont)
|
|
||||||
break;
|
|
||||||
else
|
|
||||||
charexists = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (utf8strlen) {
|
|
||||||
if (render) {
|
|
||||||
ty = y + (h - usedfont->h) / 2 + usedfont->xfont->ascent;
|
|
||||||
XftDrawStringUtf8(d, &drw->scheme[invert ? ColBg : ColFg], usedfont->xfont, x, ty,
|
|
||||||
(XftChar8 *)utf8str, utf8strlen);
|
|
||||||
}
|
|
||||||
x += ew;
|
|
||||||
w -= ew;
|
|
||||||
}
|
|
||||||
if (render && overflow)
|
|
||||||
drw_text(drw, ellipsis_x, y, ellipsis_w, h, 0, "...", invert);
|
|
||||||
|
|
||||||
if (!*text || overflow) {
|
|
||||||
break;
|
|
||||||
} else if (nextfont) {
|
|
||||||
charexists = 0;
|
|
||||||
usedfont = nextfont;
|
|
||||||
} else {
|
|
||||||
/* Regardless of whether or not a fallback font is found, the
|
|
||||||
* character must be drawn. */
|
|
||||||
charexists = 1;
|
|
||||||
|
|
||||||
for (i = 0; i < nomatches_len; ++i) {
|
|
||||||
/* avoid calling XftFontMatch if we know we won't find a match */
|
|
||||||
if (utf8codepoint == nomatches.codepoint[i])
|
|
||||||
goto no_match;
|
|
||||||
}
|
|
||||||
|
|
||||||
fccharset = FcCharSetCreate();
|
|
||||||
FcCharSetAddChar(fccharset, utf8codepoint);
|
|
||||||
|
|
||||||
if (!drw->fonts->pattern) {
|
|
||||||
/* Refer to the comment in xfont_create for more information. */
|
|
||||||
die("the first font in the cache must be loaded from a font string.");
|
|
||||||
}
|
|
||||||
|
|
||||||
fcpattern = FcPatternDuplicate(drw->fonts->pattern);
|
|
||||||
FcPatternAddCharSet(fcpattern, FC_CHARSET, fccharset);
|
|
||||||
FcPatternAddBool(fcpattern, FC_SCALABLE, FcTrue);
|
|
||||||
|
|
||||||
FcConfigSubstitute(NULL, fcpattern, FcMatchPattern);
|
|
||||||
FcDefaultSubstitute(fcpattern);
|
|
||||||
match = XftFontMatch(drw->dpy, drw->screen, fcpattern, &result);
|
|
||||||
|
|
||||||
FcCharSetDestroy(fccharset);
|
|
||||||
FcPatternDestroy(fcpattern);
|
|
||||||
|
|
||||||
if (match) {
|
|
||||||
usedfont = xfont_create(drw, NULL, match);
|
|
||||||
if (usedfont && XftCharExists(drw->dpy, usedfont->xfont, utf8codepoint)) {
|
|
||||||
for (curfont = drw->fonts; curfont->next; curfont = curfont->next)
|
|
||||||
; /* NOP */
|
|
||||||
curfont->next = usedfont;
|
|
||||||
} else {
|
|
||||||
xfont_free(usedfont);
|
|
||||||
nomatches.codepoint[++nomatches.idx % nomatches_len] = utf8codepoint;
|
|
||||||
no_match:
|
|
||||||
usedfont = drw->fonts;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (d)
|
|
||||||
XftDrawDestroy(d);
|
|
||||||
|
|
||||||
return x + (render ? w : 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h) {
|
|
||||||
if (!drw)
|
|
||||||
return;
|
|
||||||
|
|
||||||
XCopyArea(drw->dpy, drw->drawable, win, drw->gc, x, y, w, h, x, y);
|
|
||||||
XSync(drw->dpy, False);
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int drw_fontset_getwidth(Drw *drw, const char *text) {
|
|
||||||
if (!drw || !drw->fonts || !text)
|
|
||||||
return 0;
|
|
||||||
return drw_text(drw, 0, 0, 0, 0, 0, text, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int drw_fontset_getwidth_clamp(Drw *drw, const char *text, unsigned int n) {
|
|
||||||
unsigned int tmp = 0;
|
|
||||||
if (drw && drw->fonts && text && n)
|
|
||||||
tmp = drw_text(drw, 0, 0, 0, 0, 0, text, n);
|
|
||||||
return MIN(n, tmp);
|
|
||||||
}
|
|
||||||
|
|
||||||
void drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w,
|
|
||||||
unsigned int *h) {
|
|
||||||
XGlyphInfo ext;
|
|
||||||
|
|
||||||
if (!font || !text)
|
|
||||||
return;
|
|
||||||
|
|
||||||
XftTextExtentsUtf8(font->dpy, font->xfont, (XftChar8 *)text, len, &ext);
|
|
||||||
if (w)
|
|
||||||
*w = ext.xOff;
|
|
||||||
if (h)
|
|
||||||
*h = font->h;
|
|
||||||
}
|
|
||||||
|
|
||||||
Cur *drw_cur_create(Drw *drw, int shape) {
|
|
||||||
Cur *cur;
|
|
||||||
|
|
||||||
if (!drw || !(cur = ecalloc(1, sizeof(Cur))))
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
cur->cursor = XCreateFontCursor(drw->dpy, shape);
|
|
||||||
|
|
||||||
return cur;
|
|
||||||
}
|
|
||||||
|
|
||||||
void drw_cur_free(Drw *drw, Cur *cursor) {
|
|
||||||
if (!cursor)
|
|
||||||
return;
|
|
||||||
|
|
||||||
XFreeCursor(drw->dpy, cursor->cursor);
|
|
||||||
free(cursor);
|
|
||||||
}
|
|
58
drw.h
58
drw.h
|
@ -1,58 +0,0 @@
|
||||||
/* See LICENSE file for copyright and license details. */
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
Cursor cursor;
|
|
||||||
} Cur;
|
|
||||||
|
|
||||||
typedef struct Fnt {
|
|
||||||
Display *dpy;
|
|
||||||
unsigned int h;
|
|
||||||
XftFont *xfont;
|
|
||||||
FcPattern *pattern;
|
|
||||||
struct Fnt *next;
|
|
||||||
} Fnt;
|
|
||||||
|
|
||||||
enum { ColFg, ColBg, ColBorder }; /* Clr scheme index */
|
|
||||||
typedef XftColor Clr;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
unsigned int w, h;
|
|
||||||
Display *dpy;
|
|
||||||
int screen;
|
|
||||||
Window root;
|
|
||||||
Drawable drawable;
|
|
||||||
GC gc;
|
|
||||||
Clr *scheme;
|
|
||||||
Fnt *fonts;
|
|
||||||
} Drw;
|
|
||||||
|
|
||||||
/* Drawable abstraction */
|
|
||||||
Drw *drw_create(Display *dpy, int screen, Window win, unsigned int w, unsigned int h);
|
|
||||||
void drw_resize(Drw *drw, unsigned int w, unsigned int h);
|
|
||||||
void drw_free(Drw *drw);
|
|
||||||
|
|
||||||
/* Fnt abstraction */
|
|
||||||
Fnt *drw_fontset_create(Drw* drw, const char *fonts[], size_t fontcount);
|
|
||||||
void drw_fontset_free(Fnt* set);
|
|
||||||
unsigned int drw_fontset_getwidth(Drw *drw, const char *text);
|
|
||||||
unsigned int drw_fontset_getwidth_clamp(Drw *drw, const char *text, unsigned int n);
|
|
||||||
void drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h);
|
|
||||||
|
|
||||||
/* Colorscheme abstraction */
|
|
||||||
void drw_clr_create(Drw *drw, Clr *dest, const char *clrname);
|
|
||||||
Clr *drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount);
|
|
||||||
|
|
||||||
/* Cursor abstraction */
|
|
||||||
Cur *drw_cur_create(Drw *drw, int shape);
|
|
||||||
void drw_cur_free(Drw *drw, Cur *cursor);
|
|
||||||
|
|
||||||
/* Drawing context manipulation */
|
|
||||||
void drw_setfontset(Drw *drw, Fnt *set);
|
|
||||||
void drw_setscheme(Drw *drw, Clr *scm);
|
|
||||||
|
|
||||||
/* Drawing functions */
|
|
||||||
void drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int invert);
|
|
||||||
int drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert);
|
|
||||||
|
|
||||||
/* Map functions */
|
|
||||||
void drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h);
|
|
|
@ -1,68 +0,0 @@
|
||||||
From eea13010ffc3983392857ee1e3804e3aa1064d7a Mon Sep 17 00:00:00 2001
|
|
||||||
From: Soenke Lambert <s.lambert@mittwald.de>
|
|
||||||
Date: Wed, 13 Oct 2021 18:21:09 +0200
|
|
||||||
Subject: [PATCH] Fullscreen current window with [Alt]+[Shift]+[f]
|
|
||||||
|
|
||||||
This actually fullscreens a window, instead of just hiding the statusbar
|
|
||||||
and applying the monocle layout.
|
|
||||||
---
|
|
||||||
config.def.h | 1 +
|
|
||||||
dwm.1 | 3 +++
|
|
||||||
dwm.c | 8 ++++++++
|
|
||||||
3 files changed, 12 insertions(+)
|
|
||||||
|
|
||||||
diff --git a/config.def.h b/config.def.h
|
|
||||||
index 1c0b587..8cd3204 100644
|
|
||||||
--- a/config.def.h
|
|
||||||
+++ b/config.def.h
|
|
||||||
@@ -78,6 +78,7 @@ static Key keys[] = {
|
|
||||||
{ MODKEY, XK_m, setlayout, {.v = &layouts[2]} },
|
|
||||||
{ MODKEY, XK_space, setlayout, {0} },
|
|
||||||
{ MODKEY|ShiftMask, XK_space, togglefloating, {0} },
|
|
||||||
+ { MODKEY|ShiftMask, XK_f, togglefullscr, {0} },
|
|
||||||
{ MODKEY, XK_0, view, {.ui = ~0 } },
|
|
||||||
{ MODKEY|ShiftMask, XK_0, tag, {.ui = ~0 } },
|
|
||||||
{ MODKEY, XK_comma, focusmon, {.i = -1 } },
|
|
||||||
diff --git a/dwm.1 b/dwm.1
|
|
||||||
index 13b3729..a368d05 100644
|
|
||||||
--- a/dwm.1
|
|
||||||
+++ b/dwm.1
|
|
||||||
@@ -116,6 +116,9 @@ Zooms/cycles focused window to/from master area (tiled layouts only).
|
|
||||||
.B Mod1\-Shift\-c
|
|
||||||
Close focused window.
|
|
||||||
.TP
|
|
||||||
+.B Mod1\-Shift\-f
|
|
||||||
+Toggle fullscreen for focused window.
|
|
||||||
+.TP
|
|
||||||
.B Mod1\-Shift\-space
|
|
||||||
Toggle focused window between tiled and floating state.
|
|
||||||
.TP
|
|
||||||
diff --git a/dwm.c b/dwm.c
|
|
||||||
index 4465af1..c1b899a 100644
|
|
||||||
--- a/dwm.c
|
|
||||||
+++ b/dwm.c
|
|
||||||
@@ -211,6 +211,7 @@ static void tagmon(const Arg *arg);
|
|
||||||
static void tile(Monitor *);
|
|
||||||
static void togglebar(const Arg *arg);
|
|
||||||
static void togglefloating(const Arg *arg);
|
|
||||||
+static void togglefullscr(const Arg *arg);
|
|
||||||
static void toggletag(const Arg *arg);
|
|
||||||
static void toggleview(const Arg *arg);
|
|
||||||
static void unfocus(Client *c, int setfocus);
|
|
||||||
@@ -1719,6 +1720,13 @@ togglefloating(const Arg *arg)
|
|
||||||
arrange(selmon);
|
|
||||||
}
|
|
||||||
|
|
||||||
+void
|
|
||||||
+togglefullscr(const Arg *arg)
|
|
||||||
+{
|
|
||||||
+ if(selmon->sel)
|
|
||||||
+ setfullscreen(selmon->sel, !selmon->sel->isfullscreen);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
void
|
|
||||||
toggletag(const Arg *arg)
|
|
||||||
{
|
|
||||||
--
|
|
||||||
2.30.2
|
|
||||||
|
|
|
@ -1,88 +0,0 @@
|
||||||
From 17acbdcb56d0d2f39507a3f67ef329c14a213ef6 Mon Sep 17 00:00:00 2001
|
|
||||||
From: MLquest8 <miskuzius@gmail.com>
|
|
||||||
Date: Thu, 18 Jun 2020 15:34:18 +0400
|
|
||||||
Subject: [PATCH] attachtop. Attaches new client below the last master/on top
|
|
||||||
of the stack. In case of nmaster = 1 behaves like attachaside.
|
|
||||||
|
|
||||||
---
|
|
||||||
dwm.c | 29 +++++++++++++++++++++++++----
|
|
||||||
1 file changed, 25 insertions(+), 4 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/dwm.c b/dwm.c
|
|
||||||
index 9fd0286..7ced982 100644
|
|
||||||
--- a/dwm.c
|
|
||||||
+++ b/dwm.c
|
|
||||||
@@ -49,7 +49,8 @@
|
|
||||||
#define CLEANMASK(mask) (mask & ~(numlockmask|LockMask) & (ShiftMask|ControlMask|Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask))
|
|
||||||
#define INTERSECT(x,y,w,h,m) (MAX(0, MIN((x)+(w),(m)->wx+(m)->ww) - MAX((x),(m)->wx)) \
|
|
||||||
* MAX(0, MIN((y)+(h),(m)->wy+(m)->wh) - MAX((y),(m)->wy)))
|
|
||||||
-#define ISVISIBLE(C) ((C->tags & C->mon->tagset[C->mon->seltags]))
|
|
||||||
+#define ISVISIBLEONTAG(C, T) ((C->tags & T))
|
|
||||||
+#define ISVISIBLE(C) ISVISIBLEONTAG(C, C->mon->tagset[C->mon->seltags])
|
|
||||||
#define LENGTH(X) (sizeof X / sizeof X[0])
|
|
||||||
#define MOUSEMASK (BUTTONMASK|PointerMotionMask)
|
|
||||||
#define WIDTH(X) ((X)->w + 2 * (X)->bw)
|
|
||||||
@@ -147,6 +148,7 @@ static int applysizehints(Client *c, int *x, int *y, int *w, int *h, int interac
|
|
||||||
static void arrange(Monitor *m);
|
|
||||||
static void arrangemon(Monitor *m);
|
|
||||||
static void attach(Client *c);
|
|
||||||
+static void attachtop(Client *c);
|
|
||||||
static void attachstack(Client *c);
|
|
||||||
static void buttonpress(XEvent *e);
|
|
||||||
static void checkotherwm(void);
|
|
||||||
@@ -407,6 +409,25 @@ attach(Client *c)
|
|
||||||
c->mon->clients = c;
|
|
||||||
}
|
|
||||||
|
|
||||||
+void
|
|
||||||
+attachtop(Client *c)
|
|
||||||
+{
|
|
||||||
+ int n;
|
|
||||||
+ Monitor *m = selmon;
|
|
||||||
+ Client *below;
|
|
||||||
+
|
|
||||||
+ for (n = 1, below = c->mon->clients;
|
|
||||||
+ below && below->next && (below->isfloating || !ISVISIBLEONTAG(below, c->tags) || n != m->nmaster);
|
|
||||||
+ n = below->isfloating || !ISVISIBLEONTAG(below, c->tags) ? n + 0 : n + 1, below = below->next);
|
|
||||||
+ c->next = NULL;
|
|
||||||
+ if (below) {
|
|
||||||
+ c->next = below->next;
|
|
||||||
+ below->next = c;
|
|
||||||
+ }
|
|
||||||
+ else
|
|
||||||
+ c->mon->clients = c;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
void
|
|
||||||
attachstack(Client *c)
|
|
||||||
{
|
|
||||||
@@ -1063,7 +1084,7 @@ manage(Window w, XWindowAttributes *wa)
|
|
||||||
c->isfloating = c->oldstate = trans != None || c->isfixed;
|
|
||||||
if (c->isfloating)
|
|
||||||
XRaiseWindow(dpy, c->win);
|
|
||||||
- attach(c);
|
|
||||||
+ attachtop(c);
|
|
||||||
attachstack(c);
|
|
||||||
XChangeProperty(dpy, root, netatom[NetClientList], XA_WINDOW, 32, PropModeAppend,
|
|
||||||
(unsigned char *) &(c->win), 1);
|
|
||||||
@@ -1418,7 +1439,7 @@ sendmon(Client *c, Monitor *m)
|
|
||||||
detachstack(c);
|
|
||||||
c->mon = m;
|
|
||||||
c->tags = m->tagset[m->seltags]; /* assign tags of target monitor */
|
|
||||||
- attach(c);
|
|
||||||
+ attachtop(c);
|
|
||||||
attachstack(c);
|
|
||||||
focus(NULL);
|
|
||||||
arrange(NULL);
|
|
||||||
@@ -1900,7 +1921,7 @@ updategeom(void)
|
|
||||||
m->clients = c->next;
|
|
||||||
detachstack(c);
|
|
||||||
c->mon = mons;
|
|
||||||
- attach(c);
|
|
||||||
+ attachtop(c);
|
|
||||||
attachstack(c);
|
|
||||||
}
|
|
||||||
if (m == selmon)
|
|
||||||
--
|
|
||||||
2.26.2
|
|
||||||
|
|
|
@ -1,101 +0,0 @@
|
||||||
diff --git a/config.def.h b/config.def.h
|
|
||||||
index 7054c06..554f1db 100644
|
|
||||||
--- a/config.def.h
|
|
||||||
+++ b/config.def.h
|
|
||||||
@@ -39,6 +39,8 @@ static const Layout layouts[] = {
|
|
||||||
{ "[]=", tile }, /* first entry is default */
|
|
||||||
{ "><>", NULL }, /* no layout function means floating behavior */
|
|
||||||
{ "[M]", monocle },
|
|
||||||
+ { "TTT", bstack },
|
|
||||||
+ { "===", bstackhoriz },
|
|
||||||
};
|
|
||||||
|
|
||||||
/* key definitions */
|
|
||||||
@@ -74,6 +76,8 @@ static Key keys[] = {
|
|
||||||
{ MODKEY, XK_t, setlayout, {.v = &layouts[0]} },
|
|
||||||
{ MODKEY, XK_f, setlayout, {.v = &layouts[1]} },
|
|
||||||
{ MODKEY, XK_m, setlayout, {.v = &layouts[2]} },
|
|
||||||
+ { MODKEY, XK_u, setlayout, {.v = &layouts[3]} },
|
|
||||||
+ { MODKEY, XK_o, setlayout, {.v = &layouts[4]} },
|
|
||||||
{ MODKEY, XK_space, setlayout, {0} },
|
|
||||||
{ MODKEY|ShiftMask, XK_space, togglefloating, {0} },
|
|
||||||
{ MODKEY, XK_0, view, {.ui = ~0 } },
|
|
||||||
diff --git a/dwm.c b/dwm.c
|
|
||||||
index 0362114..c313b5e 100644
|
|
||||||
--- a/dwm.c
|
|
||||||
+++ b/dwm.c
|
|
||||||
@@ -233,6 +233,8 @@ static int xerror(Display *dpy, XErrorEvent *ee);
|
|
||||||
static int xerrordummy(Display *dpy, XErrorEvent *ee);
|
|
||||||
static int xerrorstart(Display *dpy, XErrorEvent *ee);
|
|
||||||
static void zoom(const Arg *arg);
|
|
||||||
+static void bstack(Monitor *m);
|
|
||||||
+static void bstackhoriz(Monitor *m);
|
|
||||||
|
|
||||||
/* variables */
|
|
||||||
static const char broken[] = "broken";
|
|
||||||
@@ -2139,3 +2141,65 @@ main(int argc, char *argv[])
|
|
||||||
XCloseDisplay(dpy);
|
|
||||||
return EXIT_SUCCESS;
|
|
||||||
}
|
|
||||||
+
|
|
||||||
+static void
|
|
||||||
+bstack(Monitor *m) {
|
|
||||||
+ int w, h, mh, mx, tx, ty, tw;
|
|
||||||
+ unsigned int i, n;
|
|
||||||
+ Client *c;
|
|
||||||
+
|
|
||||||
+ for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++);
|
|
||||||
+ if (n == 0)
|
|
||||||
+ return;
|
|
||||||
+ if (n > m->nmaster) {
|
|
||||||
+ mh = m->nmaster ? m->mfact * m->wh : 0;
|
|
||||||
+ tw = m->ww / (n - m->nmaster);
|
|
||||||
+ ty = m->wy + mh;
|
|
||||||
+ } else {
|
|
||||||
+ mh = m->wh;
|
|
||||||
+ tw = m->ww;
|
|
||||||
+ ty = m->wy;
|
|
||||||
+ }
|
|
||||||
+ for (i = mx = 0, tx = m->wx, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) {
|
|
||||||
+ if (i < m->nmaster) {
|
|
||||||
+ w = (m->ww - mx) / (MIN(n, m->nmaster) - i);
|
|
||||||
+ resize(c, m->wx + mx, m->wy, w - (2 * c->bw), mh - (2 * c->bw), 0);
|
|
||||||
+ mx += WIDTH(c);
|
|
||||||
+ } else {
|
|
||||||
+ h = m->wh - mh;
|
|
||||||
+ resize(c, tx, ty, tw - (2 * c->bw), h - (2 * c->bw), 0);
|
|
||||||
+ if (tw != m->ww)
|
|
||||||
+ tx += WIDTH(c);
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static void
|
|
||||||
+bstackhoriz(Monitor *m) {
|
|
||||||
+ int w, mh, mx, tx, ty, th;
|
|
||||||
+ unsigned int i, n;
|
|
||||||
+ Client *c;
|
|
||||||
+
|
|
||||||
+ for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++);
|
|
||||||
+ if (n == 0)
|
|
||||||
+ return;
|
|
||||||
+ if (n > m->nmaster) {
|
|
||||||
+ mh = m->nmaster ? m->mfact * m->wh : 0;
|
|
||||||
+ th = (m->wh - mh) / (n - m->nmaster);
|
|
||||||
+ ty = m->wy + mh;
|
|
||||||
+ } else {
|
|
||||||
+ th = mh = m->wh;
|
|
||||||
+ ty = m->wy;
|
|
||||||
+ }
|
|
||||||
+ for (i = mx = 0, tx = m->wx, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) {
|
|
||||||
+ if (i < m->nmaster) {
|
|
||||||
+ w = (m->ww - mx) / (MIN(n, m->nmaster) - i);
|
|
||||||
+ resize(c, m->wx + mx, m->wy, w - (2 * c->bw), mh - (2 * c->bw), 0);
|
|
||||||
+ mx += WIDTH(c);
|
|
||||||
+ } else {
|
|
||||||
+ resize(c, tx, ty, m->ww - (2 * c->bw), th - (2 * c->bw), 0);
|
|
||||||
+ if (th != m->wh)
|
|
||||||
+ ty += HEIGHT(c);
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+}
|
|
|
@ -1,142 +0,0 @@
|
||||||
diff --git a/config.def.h b/config.def.h
|
|
||||||
index 7054c06..527b214 100644
|
|
||||||
--- a/config.def.h
|
|
||||||
+++ b/config.def.h
|
|
||||||
@@ -39,6 +39,8 @@ static const Layout layouts[] = {
|
|
||||||
{ "[]=", tile }, /* first entry is default */
|
|
||||||
{ "><>", NULL }, /* no layout function means floating behavior */
|
|
||||||
{ "[M]", monocle },
|
|
||||||
+ { "|M|", centeredmaster },
|
|
||||||
+ { ">M>", centeredfloatingmaster },
|
|
||||||
};
|
|
||||||
|
|
||||||
/* key definitions */
|
|
||||||
@@ -74,6 +76,8 @@ static Key keys[] = {
|
|
||||||
{ MODKEY, XK_t, setlayout, {.v = &layouts[0]} },
|
|
||||||
{ MODKEY, XK_f, setlayout, {.v = &layouts[1]} },
|
|
||||||
{ MODKEY, XK_m, setlayout, {.v = &layouts[2]} },
|
|
||||||
+ { MODKEY, XK_u, setlayout, {.v = &layouts[3]} },
|
|
||||||
+ { MODKEY, XK_o, setlayout, {.v = &layouts[4]} },
|
|
||||||
{ MODKEY, XK_space, setlayout, {0} },
|
|
||||||
{ MODKEY|ShiftMask, XK_space, togglefloating, {0} },
|
|
||||||
{ MODKEY, XK_0, view, {.ui = ~0 } },
|
|
||||||
diff --git a/dwm.c b/dwm.c
|
|
||||||
index 0362114..1e81412 100644
|
|
||||||
--- a/dwm.c
|
|
||||||
+++ b/dwm.c
|
|
||||||
@@ -233,6 +233,8 @@ static int xerror(Display *dpy, XErrorEvent *ee);
|
|
||||||
static int xerrordummy(Display *dpy, XErrorEvent *ee);
|
|
||||||
static int xerrorstart(Display *dpy, XErrorEvent *ee);
|
|
||||||
static void zoom(const Arg *arg);
|
|
||||||
+static void centeredmaster(Monitor *m);
|
|
||||||
+static void centeredfloatingmaster(Monitor *m);
|
|
||||||
|
|
||||||
/* variables */
|
|
||||||
static const char broken[] = "broken";
|
|
||||||
@@ -2139,3 +2141,106 @@ main(int argc, char *argv[])
|
|
||||||
XCloseDisplay(dpy);
|
|
||||||
return EXIT_SUCCESS;
|
|
||||||
}
|
|
||||||
+
|
|
||||||
+void
|
|
||||||
+centeredmaster(Monitor *m)
|
|
||||||
+{
|
|
||||||
+ unsigned int i, n, h, mw, mx, my, oty, ety, tw;
|
|
||||||
+ Client *c;
|
|
||||||
+
|
|
||||||
+ /* count number of clients in the selected monitor */
|
|
||||||
+ for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++);
|
|
||||||
+ if (n == 0)
|
|
||||||
+ return;
|
|
||||||
+
|
|
||||||
+ /* initialize areas */
|
|
||||||
+ mw = m->ww;
|
|
||||||
+ mx = 0;
|
|
||||||
+ my = 0;
|
|
||||||
+ tw = mw;
|
|
||||||
+
|
|
||||||
+ if (n > m->nmaster) {
|
|
||||||
+ /* go mfact box in the center if more than nmaster clients */
|
|
||||||
+ mw = m->nmaster ? m->ww * m->mfact : 0;
|
|
||||||
+ tw = m->ww - mw;
|
|
||||||
+
|
|
||||||
+ if (n - m->nmaster > 1) {
|
|
||||||
+ /* only one client */
|
|
||||||
+ mx = (m->ww - mw) / 2;
|
|
||||||
+ tw = (m->ww - mw) / 2;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ oty = 0;
|
|
||||||
+ ety = 0;
|
|
||||||
+ for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++)
|
|
||||||
+ if (i < m->nmaster) {
|
|
||||||
+ /* nmaster clients are stacked vertically, in the center
|
|
||||||
+ * of the screen */
|
|
||||||
+ h = (m->wh - my) / (MIN(n, m->nmaster) - i);
|
|
||||||
+ resize(c, m->wx + mx, m->wy + my, mw - (2*c->bw),
|
|
||||||
+ h - (2*c->bw), 0);
|
|
||||||
+ my += HEIGHT(c);
|
|
||||||
+ } else {
|
|
||||||
+ /* stack clients are stacked vertically */
|
|
||||||
+ if ((i - m->nmaster) % 2 ) {
|
|
||||||
+ h = (m->wh - ety) / ( (1 + n - i) / 2);
|
|
||||||
+ resize(c, m->wx, m->wy + ety, tw - (2*c->bw),
|
|
||||||
+ h - (2*c->bw), 0);
|
|
||||||
+ ety += HEIGHT(c);
|
|
||||||
+ } else {
|
|
||||||
+ h = (m->wh - oty) / ((1 + n - i) / 2);
|
|
||||||
+ resize(c, m->wx + mx + mw, m->wy + oty,
|
|
||||||
+ tw - (2*c->bw), h - (2*c->bw), 0);
|
|
||||||
+ oty += HEIGHT(c);
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+void
|
|
||||||
+centeredfloatingmaster(Monitor *m)
|
|
||||||
+{
|
|
||||||
+ unsigned int i, n, w, mh, mw, mx, mxo, my, myo, tx;
|
|
||||||
+ Client *c;
|
|
||||||
+
|
|
||||||
+ /* count number of clients in the selected monitor */
|
|
||||||
+ for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++);
|
|
||||||
+ if (n == 0)
|
|
||||||
+ return;
|
|
||||||
+
|
|
||||||
+ /* initialize nmaster area */
|
|
||||||
+ if (n > m->nmaster) {
|
|
||||||
+ /* go mfact box in the center if more than nmaster clients */
|
|
||||||
+ if (m->ww > m->wh) {
|
|
||||||
+ mw = m->nmaster ? m->ww * m->mfact : 0;
|
|
||||||
+ mh = m->nmaster ? m->wh * 0.9 : 0;
|
|
||||||
+ } else {
|
|
||||||
+ mh = m->nmaster ? m->wh * m->mfact : 0;
|
|
||||||
+ mw = m->nmaster ? m->ww * 0.9 : 0;
|
|
||||||
+ }
|
|
||||||
+ mx = mxo = (m->ww - mw) / 2;
|
|
||||||
+ my = myo = (m->wh - mh) / 2;
|
|
||||||
+ } else {
|
|
||||||
+ /* go fullscreen if all clients are in the master area */
|
|
||||||
+ mh = m->wh;
|
|
||||||
+ mw = m->ww;
|
|
||||||
+ mx = mxo = 0;
|
|
||||||
+ my = myo = 0;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ for(i = tx = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++)
|
|
||||||
+ if (i < m->nmaster) {
|
|
||||||
+ /* nmaster clients are stacked horizontally, in the center
|
|
||||||
+ * of the screen */
|
|
||||||
+ w = (mw + mxo - mx) / (MIN(n, m->nmaster) - i);
|
|
||||||
+ resize(c, m->wx + mx, m->wy + my, w - (2*c->bw),
|
|
||||||
+ mh - (2*c->bw), 0);
|
|
||||||
+ mx += WIDTH(c);
|
|
||||||
+ } else {
|
|
||||||
+ /* stack clients are stacked horizontally */
|
|
||||||
+ w = (m->ww - tx) / (n - i);
|
|
||||||
+ resize(c, m->wx + tx, m->wy, w - (2*c->bw),
|
|
||||||
+ m->wh - (2*c->bw), 0);
|
|
||||||
+ tx += WIDTH(c);
|
|
||||||
+ }
|
|
||||||
+}
|
|
|
@ -1,86 +0,0 @@
|
||||||
From 647a2a56cf7cab6dea868f9800671770940ce3c3 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Alessandro Sisto <alessandro.sisto@studioform.net>
|
|
||||||
Date: Sun, 5 Jun 2022 12:03:43 +0200
|
|
||||||
Subject: [PATCH] colorbar
|
|
||||||
|
|
||||||
---
|
|
||||||
config.def.h | 6 +++++-
|
|
||||||
dwm.c | 12 ++++++------
|
|
||||||
2 files changed, 11 insertions(+), 7 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/config.def.h b/config.def.h
|
|
||||||
index a2ac963..56bc324 100644
|
|
||||||
--- a/config.def.h
|
|
||||||
+++ b/config.def.h
|
|
||||||
@@ -16,6 +16,11 @@ static const char *colors[][3] = {
|
|
||||||
/* fg bg border */
|
|
||||||
[SchemeNorm] = { col_gray3, col_gray1, col_gray2 },
|
|
||||||
[SchemeSel] = { col_gray4, col_cyan, col_cyan },
|
|
||||||
+ [SchemeStatus] = { col_gray3, col_gray1, "#000000" }, // Statusbar right {text,background,not used but cannot be empty}
|
|
||||||
+ [SchemeTagsSel] = { col_gray4, col_cyan, "#000000" }, // Tagbar left selected {text,background,not used but cannot be empty}
|
|
||||||
+ [SchemeTagsNorm] = { col_gray3, col_gray1, "#000000" }, // Tagbar left unselected {text,background,not used but cannot be empty}
|
|
||||||
+ [SchemeInfoSel] = { col_gray4, col_cyan, "#000000" }, // infobar middle selected {text,background,not used but cannot be empty}
|
|
||||||
+ [SchemeInfoNorm] = { col_gray3, col_gray1, "#000000" }, // infobar middle unselected {text,background,not used but cannot be empty}
|
|
||||||
};
|
|
||||||
|
|
||||||
/* tagging */
|
|
||||||
@@ -113,4 +118,3 @@ static Button buttons[] = {
|
|
||||||
{ ClkTagBar, MODKEY, Button1, tag, {0} },
|
|
||||||
{ ClkTagBar, MODKEY, Button3, toggletag, {0} },
|
|
||||||
};
|
|
||||||
-
|
|
||||||
diff --git a/dwm.c b/dwm.c
|
|
||||||
index a96f33c..0eaa4cd 100644
|
|
||||||
--- a/dwm.c
|
|
||||||
+++ b/dwm.c
|
|
||||||
@@ -59,7 +59,7 @@
|
|
||||||
|
|
||||||
/* enums */
|
|
||||||
enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */
|
|
||||||
-enum { SchemeNorm, SchemeSel }; /* color schemes */
|
|
||||||
+enum { SchemeNorm, SchemeSel, SchemeStatus, SchemeTagsSel, SchemeTagsNorm, SchemeInfoSel, SchemeInfoNorm }; /* color schemes */
|
|
||||||
enum { NetSupported, NetWMName, NetWMState, NetWMCheck,
|
|
||||||
NetWMFullscreen, NetActiveWindow, NetWMWindowType,
|
|
||||||
NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH atoms */
|
|
||||||
@@ -707,7 +707,7 @@ drawbar(Monitor *m)
|
|
||||||
|
|
||||||
/* draw status first so it can be overdrawn by tags later */
|
|
||||||
if (m == selmon) { /* status is only drawn on selected monitor */
|
|
||||||
- drw_setscheme(drw, scheme[SchemeNorm]);
|
|
||||||
+ drw_setscheme(drw, scheme[SchemeStatus]);
|
|
||||||
tw = TEXTW(stext) - lrpad + 2; /* 2px right padding */
|
|
||||||
drw_text(drw, m->ww - tw, 0, tw, bh, 0, stext, 0);
|
|
||||||
}
|
|
||||||
@@ -720,7 +720,7 @@ drawbar(Monitor *m)
|
|
||||||
x = 0;
|
|
||||||
for (i = 0; i < LENGTH(tags); i++) {
|
|
||||||
w = TEXTW(tags[i]);
|
|
||||||
- drw_setscheme(drw, scheme[m->tagset[m->seltags] & 1 << i ? SchemeSel : SchemeNorm]);
|
|
||||||
+ drw_setscheme(drw, scheme[m->tagset[m->seltags] & 1 << i ? SchemeTagsSel : SchemeTagsNorm]);
|
|
||||||
drw_text(drw, x, 0, w, bh, lrpad / 2, tags[i], urg & 1 << i);
|
|
||||||
if (occ & 1 << i)
|
|
||||||
drw_rect(drw, x + boxs, boxs, boxw, boxw,
|
|
||||||
@@ -729,17 +729,17 @@ drawbar(Monitor *m)
|
|
||||||
x += w;
|
|
||||||
}
|
|
||||||
w = blw = TEXTW(m->ltsymbol);
|
|
||||||
- drw_setscheme(drw, scheme[SchemeNorm]);
|
|
||||||
+ drw_setscheme(drw, scheme[SchemeTagsNorm]);
|
|
||||||
x = drw_text(drw, x, 0, w, bh, lrpad / 2, m->ltsymbol, 0);
|
|
||||||
|
|
||||||
if ((w = m->ww - tw - x) > bh) {
|
|
||||||
if (m->sel) {
|
|
||||||
- drw_setscheme(drw, scheme[m == selmon ? SchemeSel : SchemeNorm]);
|
|
||||||
+ drw_setscheme(drw, scheme[m == selmon ? SchemeInfoSel : SchemeInfoNorm]);
|
|
||||||
drw_text(drw, x, 0, w, bh, lrpad / 2, m->sel->name, 0);
|
|
||||||
if (m->sel->isfloating)
|
|
||||||
drw_rect(drw, x + boxs, boxs, boxw, boxw, m->sel->isfixed, 0);
|
|
||||||
} else {
|
|
||||||
- drw_setscheme(drw, scheme[SchemeNorm]);
|
|
||||||
+ drw_setscheme(drw, scheme[SchemeInfoNorm]);
|
|
||||||
drw_rect(drw, x, 0, w, bh, 1, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
--
|
|
||||||
2.36.1
|
|
||||||
|
|
|
@ -1,71 +0,0 @@
|
||||||
diff --git a/config.def.h b/config.def.h
|
|
||||||
index a2ac963..e8c0978 100644
|
|
||||||
--- a/config.def.h
|
|
||||||
+++ b/config.def.h
|
|
||||||
@@ -26,9 +26,9 @@ static const Rule rules[] = {
|
|
||||||
* WM_CLASS(STRING) = instance, class
|
|
||||||
* WM_NAME(STRING) = title
|
|
||||||
*/
|
|
||||||
- /* class instance title tags mask isfloating monitor */
|
|
||||||
- { "Gimp", NULL, NULL, 0, 1, -1 },
|
|
||||||
- { "Firefox", NULL, NULL, 1 << 8, 0, -1 },
|
|
||||||
+ /* class instance title tags mask isfloating monitor float x,y,w,h floatborderpx*/
|
|
||||||
+ { "Gimp", NULL, NULL, 0, 1, -1, 50,50,500,500, 5 },
|
|
||||||
+ { "Firefox", NULL, NULL, 1 << 8, 0, -1, 50,50,500,500, 5 },
|
|
||||||
};
|
|
||||||
|
|
||||||
/* layout(s) */
|
|
||||||
diff --git a/dwm.c b/dwm.c
|
|
||||||
index 5e4d494..a03ca15 100644
|
|
||||||
--- a/dwm.c
|
|
||||||
+++ b/dwm.c
|
|
||||||
@@ -93,6 +93,8 @@ struct Client {
|
|
||||||
int bw, oldbw;
|
|
||||||
unsigned int tags;
|
|
||||||
int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen;
|
|
||||||
+ int floatborderpx;
|
|
||||||
+ int hasfloatbw;
|
|
||||||
Client *next;
|
|
||||||
Client *snext;
|
|
||||||
Monitor *mon;
|
|
||||||
@@ -139,6 +141,8 @@ typedef struct {
|
|
||||||
unsigned int tags;
|
|
||||||
int isfloating;
|
|
||||||
int monitor;
|
|
||||||
+ int floatx, floaty, floatw, floath;
|
|
||||||
+ int floatborderpx;
|
|
||||||
} Rule;
|
|
||||||
|
|
||||||
/* function declarations */
|
|
||||||
@@ -300,6 +304,16 @@ applyrules(Client *c)
|
|
||||||
{
|
|
||||||
c->isfloating = r->isfloating;
|
|
||||||
c->tags |= r->tags;
|
|
||||||
+ if (r->floatborderpx >= 0) {
|
|
||||||
+ c->floatborderpx = r->floatborderpx;
|
|
||||||
+ c->hasfloatbw = 1;
|
|
||||||
+ }
|
|
||||||
+ if (r->isfloating) {
|
|
||||||
+ if (r->floatx >= 0) c->x = c->mon->mx + r->floatx;
|
|
||||||
+ if (r->floaty >= 0) c->y = c->mon->my + r->floaty;
|
|
||||||
+ if (r->floatw >= 0) c->w = r->floatw;
|
|
||||||
+ if (r->floath >= 0) c->h = r->floath;
|
|
||||||
+ }
|
|
||||||
for (m = mons; m && m->num != r->monitor; m = m->next);
|
|
||||||
if (m)
|
|
||||||
c->mon = m;
|
|
||||||
@@ -1282,7 +1296,10 @@ resizeclient(Client *c, int x, int y, int w, int h)
|
|
||||||
c->oldy = c->y; c->y = wc.y = y;
|
|
||||||
c->oldw = c->w; c->w = wc.width = w;
|
|
||||||
c->oldh = c->h; c->h = wc.height = h;
|
|
||||||
- wc.border_width = c->bw;
|
|
||||||
+ if (c->isfloating && c->hasfloatbw && !c->isfullscreen)
|
|
||||||
+ wc.border_width = c->floatborderpx;
|
|
||||||
+ else
|
|
||||||
+ wc.border_width = c->bw;
|
|
||||||
XConfigureWindow(dpy, c->win, CWX|CWY|CWWidth|CWHeight|CWBorderWidth, &wc);
|
|
||||||
configure(c);
|
|
||||||
XSync(dpy, False);
|
|
||||||
--
|
|
||||||
2.32.0
|
|
||||||
|
|
|
@ -1,43 +0,0 @@
|
||||||
URL: http://dwm.suckless.org/patches/gapless_grid
|
|
||||||
Add gapless grid layout.
|
|
||||||
|
|
||||||
Index: dwm/gaplessgrid.c
|
|
||||||
===================================================================
|
|
||||||
--- /dev/null
|
|
||||||
+++ dwm/gaplessgrid.c
|
|
||||||
@@ -0,0 +1,35 @@
|
|
||||||
+void
|
|
||||||
+gaplessgrid(Monitor *m) {
|
|
||||||
+ unsigned int n, cols, rows, cn, rn, i, cx, cy, cw, ch;
|
|
||||||
+ 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;
|
|
||||||
+
|
|
||||||
+ /* window geometries */
|
|
||||||
+ cw = cols ? m->ww / cols : m->ww;
|
|
||||||
+ cn = 0; /* current column number */
|
|
||||||
+ rn = 0; /* current row number */
|
|
||||||
+ 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 = rows ? m->wh / rows : m->wh;
|
|
||||||
+ cx = m->wx + cn*cw;
|
|
||||||
+ cy = m->wy + rn*ch;
|
|
||||||
+ resize(c, cx, cy, cw - 2 * c->bw, ch - 2 * c->bw, False);
|
|
||||||
+ rn++;
|
|
||||||
+ if(rn >= rows) {
|
|
||||||
+ rn = 0;
|
|
||||||
+ cn++;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+}
|
|
|
@ -1,39 +0,0 @@
|
||||||
diff --git a/dwm.c b/dwm.c
|
|
||||||
index a96f33c..f2da729 100644
|
|
||||||
--- a/dwm.c
|
|
||||||
+++ b/dwm.c
|
|
||||||
@@ -432,9 +432,15 @@ buttonpress(XEvent *e)
|
|
||||||
}
|
|
||||||
if (ev->window == selmon->barwin) {
|
|
||||||
i = x = 0;
|
|
||||||
- do
|
|
||||||
+ unsigned int occ = 0;
|
|
||||||
+ for(c = m->clients; c; c=c->next)
|
|
||||||
+ occ |= c->tags;
|
|
||||||
+ do {
|
|
||||||
+ /* Do not reserve space for vacant tags */
|
|
||||||
+ if (!(occ & 1 << i || m->tagset[m->seltags] & 1 << i))
|
|
||||||
+ continue;
|
|
||||||
x += TEXTW(tags[i]);
|
|
||||||
- while (ev->x >= x && ++i < LENGTH(tags));
|
|
||||||
+ } while (ev->x >= x && ++i < LENGTH(tags));
|
|
||||||
if (i < LENGTH(tags)) {
|
|
||||||
click = ClkTagBar;
|
|
||||||
arg.ui = 1 << i;
|
|
||||||
@@ -719,13 +725,12 @@ drawbar(Monitor *m)
|
|
||||||
}
|
|
||||||
x = 0;
|
|
||||||
for (i = 0; i < LENGTH(tags); i++) {
|
|
||||||
+ /* Do not draw vacant tags */
|
|
||||||
+ if(!(occ & 1 << i || m->tagset[m->seltags] & 1 << i))
|
|
||||||
+ continue;
|
|
||||||
w = TEXTW(tags[i]);
|
|
||||||
drw_setscheme(drw, scheme[m->tagset[m->seltags] & 1 << i ? SchemeSel : SchemeNorm]);
|
|
||||||
drw_text(drw, x, 0, w, bh, lrpad / 2, tags[i], urg & 1 << i);
|
|
||||||
- if (occ & 1 << i)
|
|
||||||
- drw_rect(drw, x + boxs, boxs, boxw, boxw,
|
|
||||||
- m == selmon && selmon->sel && selmon->sel->tags & 1 << i,
|
|
||||||
- urg & 1 << i);
|
|
||||||
x += w;
|
|
||||||
}
|
|
||||||
w = blw = TEXTW(m->ltsymbol);
|
|
|
@ -1,138 +0,0 @@
|
||||||
diff '--color=auto' -up dwm-6.2/config.def.h dwm-6.2-new/config.def.h
|
|
||||||
--- dwm-6.2/config.def.h 2019-02-02 12:55:28.000000000 +0000
|
|
||||||
+++ dwm-6.2-new/config.def.h 2020-04-26 13:51:06.713332746 +0100
|
|
||||||
@@ -26,9 +26,10 @@ static const Rule rules[] = {
|
|
||||||
* WM_CLASS(STRING) = instance, class
|
|
||||||
* WM_NAME(STRING) = title
|
|
||||||
*/
|
|
||||||
- /* class instance title tags mask isfloating monitor */
|
|
||||||
- { "Gimp", NULL, NULL, 0, 1, -1 },
|
|
||||||
- { "Firefox", NULL, NULL, 1 << 8, 0, -1 },
|
|
||||||
+ /* class instance title tags mask isfloating monitor scratch key */
|
|
||||||
+ { "Gimp", NULL, NULL, 0, 1, -1, 0 },
|
|
||||||
+ { "firefox", NULL, NULL, 1 << 8, 0, -1, 0 },
|
|
||||||
+ { NULL, NULL, "scratchpad", 0, 1, -1, 's' },
|
|
||||||
};
|
|
||||||
|
|
||||||
/* layout(s) */
|
|
||||||
@@ -59,10 +60,14 @@ static char dmenumon[2] = "0"; /* compon
|
|
||||||
static const char *dmenucmd[] = { "dmenu_run", "-m", dmenumon, "-fn", dmenufont, "-nb", col_gray1, "-nf", col_gray3, "-sb", col_cyan, "-sf", col_gray4, NULL };
|
|
||||||
static const char *termcmd[] = { "st", NULL };
|
|
||||||
|
|
||||||
+/*First arg only serves to match against key in rules*/
|
|
||||||
+static const char *scratchpadcmd[] = {"s", "st", "-t", "scratchpad", NULL};
|
|
||||||
+
|
|
||||||
static Key keys[] = {
|
|
||||||
/* modifier key function argument */
|
|
||||||
{ MODKEY, XK_p, spawn, {.v = dmenucmd } },
|
|
||||||
{ MODKEY|ShiftMask, XK_Return, spawn, {.v = termcmd } },
|
|
||||||
+ { MODKEY, XK_grave, togglescratch, {.v = scratchpadcmd } },
|
|
||||||
{ MODKEY, XK_b, togglebar, {0} },
|
|
||||||
{ MODKEY, XK_j, focusstack, {.i = +1 } },
|
|
||||||
{ MODKEY, XK_k, focusstack, {.i = -1 } },
|
|
||||||
diff '--color=auto' -up dwm-6.2/dwm.c dwm-6.2-new/dwm.c
|
|
||||||
--- dwm-6.2/dwm.c 2019-02-02 12:55:28.000000000 +0000
|
|
||||||
+++ dwm-6.2-new/dwm.c 2020-04-26 13:55:56.820584361 +0100
|
|
||||||
@@ -93,6 +93,7 @@ struct Client {
|
|
||||||
int bw, oldbw;
|
|
||||||
unsigned int tags;
|
|
||||||
int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen;
|
|
||||||
+ char scratchkey;
|
|
||||||
Client *next;
|
|
||||||
Client *snext;
|
|
||||||
Monitor *mon;
|
|
||||||
@@ -139,6 +140,7 @@ typedef struct {
|
|
||||||
unsigned int tags;
|
|
||||||
int isfloating;
|
|
||||||
int monitor;
|
|
||||||
+ const char scratchkey;
|
|
||||||
} Rule;
|
|
||||||
|
|
||||||
/* function declarations */
|
|
||||||
@@ -206,11 +208,13 @@ static void seturgent(Client *c, int urg
|
|
||||||
static void showhide(Client *c);
|
|
||||||
static void sigchld(int unused);
|
|
||||||
static void spawn(const Arg *arg);
|
|
||||||
+static void spawnscratch(const Arg *arg);
|
|
||||||
static void tag(const Arg *arg);
|
|
||||||
static void tagmon(const Arg *arg);
|
|
||||||
static void tile(Monitor *);
|
|
||||||
static void togglebar(const Arg *arg);
|
|
||||||
static void togglefloating(const Arg *arg);
|
|
||||||
+static void togglescratch(const Arg *arg);
|
|
||||||
static void toggletag(const Arg *arg);
|
|
||||||
static void toggleview(const Arg *arg);
|
|
||||||
static void unfocus(Client *c, int setfocus);
|
|
||||||
@@ -287,6 +291,7 @@ applyrules(Client *c)
|
|
||||||
/* rule matching */
|
|
||||||
c->isfloating = 0;
|
|
||||||
c->tags = 0;
|
|
||||||
+ c->scratchkey = 0;
|
|
||||||
XGetClassHint(dpy, c->win, &ch);
|
|
||||||
class = ch.res_class ? ch.res_class : broken;
|
|
||||||
instance = ch.res_name ? ch.res_name : broken;
|
|
||||||
@@ -299,6 +304,7 @@ applyrules(Client *c)
|
|
||||||
{
|
|
||||||
c->isfloating = r->isfloating;
|
|
||||||
c->tags |= r->tags;
|
|
||||||
+ c->scratchkey = r->scratchkey;
|
|
||||||
for (m = mons; m && m->num != r->monitor; m = m->next);
|
|
||||||
if (m)
|
|
||||||
c->mon = m;
|
|
||||||
@@ -308,6 +314,7 @@ applyrules(Client *c)
|
|
||||||
XFree(ch.res_class);
|
|
||||||
if (ch.res_name)
|
|
||||||
XFree(ch.res_name);
|
|
||||||
+
|
|
||||||
c->tags = c->tags & TAGMASK ? c->tags & TAGMASK : c->mon->tagset[c->mon->seltags];
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1652,6 +1659,19 @@ spawn(const Arg *arg)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
+void spawnscratch(const Arg *arg)
|
|
||||||
+{
|
|
||||||
+ if (fork() == 0) {
|
|
||||||
+ if (dpy)
|
|
||||||
+ close(ConnectionNumber(dpy));
|
|
||||||
+ setsid();
|
|
||||||
+ execvp(((char **)arg->v)[1], ((char **)arg->v)+1);
|
|
||||||
+ fprintf(stderr, "dwm: execvp %s", ((char **)arg->v)[1]);
|
|
||||||
+ perror(" failed");
|
|
||||||
+ exit(EXIT_SUCCESS);
|
|
||||||
+ }
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
void
|
|
||||||
tag(const Arg *arg)
|
|
||||||
{
|
|
||||||
@@ -1720,6 +1740,28 @@ togglefloating(const Arg *arg)
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
+togglescratch(const Arg *arg)
|
|
||||||
+{
|
|
||||||
+ Client *c;
|
|
||||||
+ unsigned int found = 0;
|
|
||||||
+
|
|
||||||
+ for (c = selmon->clients; c && !(found = c->scratchkey == ((char**)arg->v)[0][0]); c = c->next);
|
|
||||||
+ if (found) {
|
|
||||||
+ c->tags = ISVISIBLE(c) ? 0 : selmon->tagset[selmon->seltags];
|
|
||||||
+ focus(NULL);
|
|
||||||
+ arrange(selmon);
|
|
||||||
+
|
|
||||||
+ if (ISVISIBLE(c)) {
|
|
||||||
+ focus(c);
|
|
||||||
+ restack(selmon);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ } else{
|
|
||||||
+ spawnscratch(arg);
|
|
||||||
+ }
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+void
|
|
||||||
toggletag(const Arg *arg)
|
|
||||||
{
|
|
||||||
unsigned int newtags;
|
|
|
@ -1,177 +0,0 @@
|
||||||
diff --git a/dwm.c b/dwm.c
|
|
||||||
index 664c527..ac8e4ec 100644
|
|
||||||
--- a/dwm.c
|
|
||||||
+++ b/dwm.c
|
|
||||||
@@ -111,6 +111,7 @@ typedef struct {
|
|
||||||
void (*arrange)(Monitor *);
|
|
||||||
} Layout;
|
|
||||||
|
|
||||||
+typedef struct Pertag Pertag;
|
|
||||||
struct Monitor {
|
|
||||||
char ltsymbol[16];
|
|
||||||
float mfact;
|
|
||||||
@@ -130,6 +131,7 @@ struct Monitor {
|
|
||||||
Monitor *next;
|
|
||||||
Window barwin;
|
|
||||||
const Layout *lt[2];
|
|
||||||
+ Pertag *pertag;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
@@ -272,6 +274,15 @@ static Window root, wmcheckwin;
|
|
||||||
/* configuration, allows nested code to access above variables */
|
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
+struct Pertag {
|
|
||||||
+ unsigned int curtag, prevtag; /* current and previous tag */
|
|
||||||
+ int nmasters[LENGTH(tags) + 1]; /* number of windows in master area */
|
|
||||||
+ float mfacts[LENGTH(tags) + 1]; /* mfacts per tag */
|
|
||||||
+ unsigned int sellts[LENGTH(tags) + 1]; /* selected layouts */
|
|
||||||
+ const Layout *ltidxs[LENGTH(tags) + 1][2]; /* matrix of tags and layouts indexes */
|
|
||||||
+ int showbars[LENGTH(tags) + 1]; /* display bar for the current tag */
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
/* compile-time check if all tags fit into an unsigned int bit array. */
|
|
||||||
struct NumTags { char limitexceeded[LENGTH(tags) > 31 ? -1 : 1]; };
|
|
||||||
|
|
||||||
@@ -632,6 +643,7 @@ Monitor *
|
|
||||||
createmon(void)
|
|
||||||
{
|
|
||||||
Monitor *m;
|
|
||||||
+ unsigned int i;
|
|
||||||
|
|
||||||
m = ecalloc(1, sizeof(Monitor));
|
|
||||||
m->tagset[0] = m->tagset[1] = 1;
|
|
||||||
@@ -642,6 +654,20 @@ createmon(void)
|
|
||||||
m->lt[0] = &layouts[0];
|
|
||||||
m->lt[1] = &layouts[1 % LENGTH(layouts)];
|
|
||||||
strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol);
|
|
||||||
+ m->pertag = ecalloc(1, sizeof(Pertag));
|
|
||||||
+ m->pertag->curtag = m->pertag->prevtag = 1;
|
|
||||||
+
|
|
||||||
+ for (i = 0; i <= LENGTH(tags); i++) {
|
|
||||||
+ m->pertag->nmasters[i] = m->nmaster;
|
|
||||||
+ m->pertag->mfacts[i] = m->mfact;
|
|
||||||
+
|
|
||||||
+ m->pertag->ltidxs[i][0] = m->lt[0];
|
|
||||||
+ m->pertag->ltidxs[i][1] = m->lt[1];
|
|
||||||
+ m->pertag->sellts[i] = m->sellt;
|
|
||||||
+
|
|
||||||
+ m->pertag->showbars[i] = m->showbar;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
return m;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -967,7 +993,7 @@ grabkeys(void)
|
|
||||||
void
|
|
||||||
incnmaster(const Arg *arg)
|
|
||||||
{
|
|
||||||
- selmon->nmaster = MAX(selmon->nmaster + arg->i, 0);
|
|
||||||
+ selmon->nmaster = selmon->pertag->nmasters[selmon->pertag->curtag] = MAX(selmon->nmaster + arg->i, 0);
|
|
||||||
arrange(selmon);
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1502,9 +1528,9 @@ void
|
|
||||||
setlayout(const Arg *arg)
|
|
||||||
{
|
|
||||||
if (!arg || !arg->v || arg->v != selmon->lt[selmon->sellt])
|
|
||||||
- selmon->sellt ^= 1;
|
|
||||||
+ selmon->sellt = selmon->pertag->sellts[selmon->pertag->curtag] ^= 1;
|
|
||||||
if (arg && arg->v)
|
|
||||||
- selmon->lt[selmon->sellt] = (Layout *)arg->v;
|
|
||||||
+ selmon->lt[selmon->sellt] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt] = (Layout *)arg->v;
|
|
||||||
strncpy(selmon->ltsymbol, selmon->lt[selmon->sellt]->symbol, sizeof selmon->ltsymbol);
|
|
||||||
if (selmon->sel)
|
|
||||||
arrange(selmon);
|
|
||||||
@@ -1523,7 +1549,7 @@ setmfact(const Arg *arg)
|
|
||||||
f = arg->f < 1.0 ? arg->f + selmon->mfact : arg->f - 1.0;
|
|
||||||
if (f < 0.05 || f > 0.95)
|
|
||||||
return;
|
|
||||||
- selmon->mfact = f;
|
|
||||||
+ selmon->mfact = selmon->pertag->mfacts[selmon->pertag->curtag] = f;
|
|
||||||
arrange(selmon);
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1702,7 +1728,7 @@ tile(Monitor *m)
|
|
||||||
void
|
|
||||||
togglebar(const Arg *arg)
|
|
||||||
{
|
|
||||||
- selmon->showbar = !selmon->showbar;
|
|
||||||
+ selmon->showbar = selmon->pertag->showbars[selmon->pertag->curtag] = !selmon->showbar;
|
|
||||||
updatebarpos(selmon);
|
|
||||||
XMoveResizeWindow(dpy, selmon->barwin, selmon->wx, selmon->by, selmon->ww, bh);
|
|
||||||
arrange(selmon);
|
|
||||||
@@ -1741,9 +1767,33 @@ void
|
|
||||||
toggleview(const Arg *arg)
|
|
||||||
{
|
|
||||||
unsigned int newtagset = selmon->tagset[selmon->seltags] ^ (arg->ui & TAGMASK);
|
|
||||||
+ int i;
|
|
||||||
|
|
||||||
if (newtagset) {
|
|
||||||
selmon->tagset[selmon->seltags] = newtagset;
|
|
||||||
+
|
|
||||||
+ if (newtagset == ~0) {
|
|
||||||
+ selmon->pertag->prevtag = selmon->pertag->curtag;
|
|
||||||
+ selmon->pertag->curtag = 0;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ /* test if the user did not select the same tag */
|
|
||||||
+ if (!(newtagset & 1 << (selmon->pertag->curtag - 1))) {
|
|
||||||
+ selmon->pertag->prevtag = selmon->pertag->curtag;
|
|
||||||
+ for (i = 0; !(newtagset & 1 << i); i++) ;
|
|
||||||
+ selmon->pertag->curtag = i + 1;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ /* apply settings for this view */
|
|
||||||
+ selmon->nmaster = selmon->pertag->nmasters[selmon->pertag->curtag];
|
|
||||||
+ selmon->mfact = selmon->pertag->mfacts[selmon->pertag->curtag];
|
|
||||||
+ selmon->sellt = selmon->pertag->sellts[selmon->pertag->curtag];
|
|
||||||
+ selmon->lt[selmon->sellt] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt];
|
|
||||||
+ selmon->lt[selmon->sellt^1] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt^1];
|
|
||||||
+
|
|
||||||
+ if (selmon->showbar != selmon->pertag->showbars[selmon->pertag->curtag])
|
|
||||||
+ togglebar(NULL);
|
|
||||||
+
|
|
||||||
focus(NULL);
|
|
||||||
arrange(selmon);
|
|
||||||
}
|
|
||||||
@@ -2038,11 +2088,37 @@ updatewmhints(Client *c)
|
|
||||||
void
|
|
||||||
view(const Arg *arg)
|
|
||||||
{
|
|
||||||
+ int i;
|
|
||||||
+ unsigned int tmptag;
|
|
||||||
+
|
|
||||||
if ((arg->ui & TAGMASK) == selmon->tagset[selmon->seltags])
|
|
||||||
return;
|
|
||||||
selmon->seltags ^= 1; /* toggle sel tagset */
|
|
||||||
- if (arg->ui & TAGMASK)
|
|
||||||
+ if (arg->ui & TAGMASK) {
|
|
||||||
selmon->tagset[selmon->seltags] = arg->ui & TAGMASK;
|
|
||||||
+ selmon->pertag->prevtag = selmon->pertag->curtag;
|
|
||||||
+
|
|
||||||
+ if (arg->ui == ~0)
|
|
||||||
+ selmon->pertag->curtag = 0;
|
|
||||||
+ else {
|
|
||||||
+ for (i = 0; !(arg->ui & 1 << i); i++) ;
|
|
||||||
+ selmon->pertag->curtag = i + 1;
|
|
||||||
+ }
|
|
||||||
+ } else {
|
|
||||||
+ tmptag = selmon->pertag->prevtag;
|
|
||||||
+ selmon->pertag->prevtag = selmon->pertag->curtag;
|
|
||||||
+ selmon->pertag->curtag = tmptag;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ selmon->nmaster = selmon->pertag->nmasters[selmon->pertag->curtag];
|
|
||||||
+ selmon->mfact = selmon->pertag->mfacts[selmon->pertag->curtag];
|
|
||||||
+ selmon->sellt = selmon->pertag->sellts[selmon->pertag->curtag];
|
|
||||||
+ selmon->lt[selmon->sellt] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt];
|
|
||||||
+ selmon->lt[selmon->sellt^1] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt^1];
|
|
||||||
+
|
|
||||||
+ if (selmon->showbar != selmon->pertag->showbars[selmon->pertag->curtag])
|
|
||||||
+ togglebar(NULL);
|
|
||||||
+
|
|
||||||
focus(NULL);
|
|
||||||
arrange(selmon);
|
|
||||||
}
|
|
|
@ -1,36 +0,0 @@
|
||||||
diff -r -u a/config.def.h b/config.def.h
|
|
||||||
--- a/config.def.h 2022-01-07 06:42:18.000000000 -0500
|
|
||||||
+++ b/config.def.h 2022-01-23 16:03:42.521951418 -0500
|
|
||||||
@@ -69,6 +69,7 @@
|
|
||||||
{ MODKEY, XK_k, focusstack, {.i = -1 } },
|
|
||||||
{ MODKEY, XK_i, incnmaster, {.i = +1 } },
|
|
||||||
{ MODKEY, XK_d, incnmaster, {.i = -1 } },
|
|
||||||
+ { MODKEY, XK_o, resetnmaster, {0} },
|
|
||||||
{ MODKEY, XK_h, setmfact, {.f = -0.05} },
|
|
||||||
{ MODKEY, XK_l, setmfact, {.f = +0.05} },
|
|
||||||
{ MODKEY, XK_Return, zoom, {0} },
|
|
||||||
diff -r -u a/dwm.c b/dwm.c
|
|
||||||
--- a/dwm.c 2022-01-23 16:06:01.221948285 -0500
|
|
||||||
+++ b/dwm.c 2022-01-23 16:05:35.949948855 -0500
|
|
||||||
@@ -191,6 +191,7 @@
|
|
||||||
static void propertynotify(XEvent *e);
|
|
||||||
static void quit(const Arg *arg);
|
|
||||||
static Monitor *recttomon(int x, int y, int w, int h);
|
|
||||||
+static void resetnmaster(const Arg *arg);
|
|
||||||
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);
|
|
||||||
@@ -1296,6 +1297,13 @@
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
+resetnmaster(const Arg *arg)
|
|
||||||
+{
|
|
||||||
+ selmon->nmaster = selmon->pertag->nmasters[selmon->pertag->curtag] = 1;
|
|
||||||
+ arrange(selmon);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+void
|
|
||||||
resize(Client *c, int x, int y, int w, int h, int interact)
|
|
||||||
{
|
|
||||||
if (applysizehints(c, &x, &y, &w, &h, interact))
|
|
|
@ -1,68 +0,0 @@
|
||||||
diff -r -u a/dwm.c b/dwm.c
|
|
||||||
--- a/dwm.c 2019-02-02 07:55:28.000000000 -0500
|
|
||||||
+++ b/dwm.c 2022-01-17 22:38:33.614493243 -0500
|
|
||||||
@@ -1291,9 +1291,14 @@
|
|
||||||
resizemouse(const Arg *arg)
|
|
||||||
{
|
|
||||||
int ocx, ocy, nw, nh;
|
|
||||||
+ int ocx2, ocy2, nx, ny;
|
|
||||||
Client *c;
|
|
||||||
Monitor *m;
|
|
||||||
XEvent ev;
|
|
||||||
+ int horizcorner, vertcorner;
|
|
||||||
+ int di;
|
|
||||||
+ unsigned int dui;
|
|
||||||
+ Window dummy;
|
|
||||||
Time lasttime = 0;
|
|
||||||
|
|
||||||
if (!(c = selmon->sel))
|
|
||||||
@@ -1303,10 +1308,18 @@
|
|
||||||
restack(selmon);
|
|
||||||
ocx = c->x;
|
|
||||||
ocy = c->y;
|
|
||||||
+ ocx2 = c->x + c->w;
|
|
||||||
+ ocy2 = c->y + c->h;
|
|
||||||
if (XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync,
|
|
||||||
None, cursor[CurResize]->cursor, CurrentTime) != GrabSuccess)
|
|
||||||
return;
|
|
||||||
- XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w + c->bw - 1, c->h + c->bw - 1);
|
|
||||||
+ if (!XQueryPointer (dpy, c->win, &dummy, &dummy, &di, &di, &nx, &ny, &dui))
|
|
||||||
+ return;
|
|
||||||
+ horizcorner = nx < c->w / 2;
|
|
||||||
+ vertcorner = ny < c->h / 2;
|
|
||||||
+ XWarpPointer (dpy, None, c->win, 0, 0, 0, 0,
|
|
||||||
+ horizcorner ? (-c->bw) : (c->w + c->bw -1),
|
|
||||||
+ vertcorner ? (-c->bw) : (c->h + c->bw -1));
|
|
||||||
do {
|
|
||||||
XMaskEvent(dpy, MOUSEMASK|ExposureMask|SubstructureRedirectMask, &ev);
|
|
||||||
switch(ev.type) {
|
|
||||||
@@ -1320,8 +1333,11 @@
|
|
||||||
continue;
|
|
||||||
lasttime = ev.xmotion.time;
|
|
||||||
|
|
||||||
- nw = MAX(ev.xmotion.x - ocx - 2 * c->bw + 1, 1);
|
|
||||||
- nh = MAX(ev.xmotion.y - ocy - 2 * c->bw + 1, 1);
|
|
||||||
+ nx = horizcorner ? ev.xmotion.x : c->x;
|
|
||||||
+ ny = vertcorner ? ev.xmotion.y : c->y;
|
|
||||||
+ nw = MAX(horizcorner ? (ocx2 - nx) : (ev.xmotion.x - ocx - 2 * c->bw + 1), 1);
|
|
||||||
+ nh = MAX(vertcorner ? (ocy2 - ny) : (ev.xmotion.y - ocy - 2 * c->bw + 1), 1);
|
|
||||||
+
|
|
||||||
if (c->mon->wx + nw >= selmon->wx && c->mon->wx + nw <= selmon->wx + selmon->ww
|
|
||||||
&& c->mon->wy + nh >= selmon->wy && c->mon->wy + nh <= selmon->wy + selmon->wh)
|
|
||||||
{
|
|
||||||
@@ -1330,11 +1346,13 @@
|
|
||||||
togglefloating(NULL);
|
|
||||||
}
|
|
||||||
if (!selmon->lt[selmon->sellt]->arrange || c->isfloating)
|
|
||||||
- resize(c, c->x, c->y, nw, nh, 1);
|
|
||||||
+ resize(c, nx, ny, nw, nh, 1);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} while (ev.type != ButtonRelease);
|
|
||||||
- XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w + c->bw - 1, c->h + c->bw - 1);
|
|
||||||
+ XWarpPointer(dpy, None, c->win, 0, 0, 0, 0,
|
|
||||||
+ horizcorner ? (-c->bw) : (c->w + c->bw - 1),
|
|
||||||
+ vertcorner ? (-c->bw) : (c->h + c->bw - 1));
|
|
||||||
XUngrabPointer(dpy, CurrentTime);
|
|
||||||
while (XCheckMaskEvent(dpy, EnterWindowMask, &ev));
|
|
||||||
if ((m = recttomon(c->x, c->y, c->w, c->h)) != selmon) {
|
|
|
@ -1,139 +0,0 @@
|
||||||
From 2991f37f0aaf44b9f9b11e7893ff0af8eb88f649 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Christopher Drelich <cd@cdrakka.com>
|
|
||||||
Date: Wed, 23 May 2018 22:50:38 -0400
|
|
||||||
Subject: [PATCH] Modifies quit to handle restarts and adds SIGHUP and SIGTERM
|
|
||||||
handlers.
|
|
||||||
|
|
||||||
Modified quit() to restart if it receives arg .i = 1
|
|
||||||
MOD+CTRL+SHIFT+Q was added to confid.def.h to do just that.
|
|
||||||
|
|
||||||
Signal handlers were handled for SIGHUP and SIGTERM.
|
|
||||||
If dwm receives these signals it calls quit() with
|
|
||||||
arg .i = to 1 or 0, respectively.
|
|
||||||
|
|
||||||
To restart dwm:
|
|
||||||
MOD+CTRL+SHIFT+Q
|
|
||||||
or
|
|
||||||
kill -HUP dwmpid
|
|
||||||
|
|
||||||
To quit dwm cleanly:
|
|
||||||
MOD+SHIFT+Q
|
|
||||||
or
|
|
||||||
kill -TERM dwmpid
|
|
||||||
---
|
|
||||||
config.def.h | 1 +
|
|
||||||
dwm.1 | 10 ++++++++++
|
|
||||||
dwm.c | 22 ++++++++++++++++++++++
|
|
||||||
3 files changed, 33 insertions(+)
|
|
||||||
|
|
||||||
diff --git a/config.def.h b/config.def.h
|
|
||||||
index a9ac303..e559429 100644
|
|
||||||
--- a/config.def.h
|
|
||||||
+++ b/config.def.h
|
|
||||||
@@ -94,6 +94,7 @@ static Key keys[] = {
|
|
||||||
TAGKEYS( XK_8, 7)
|
|
||||||
TAGKEYS( XK_9, 8)
|
|
||||||
{ MODKEY|ShiftMask, XK_q, quit, {0} },
|
|
||||||
+ { MODKEY|ControlMask|ShiftMask, XK_q, quit, {1} },
|
|
||||||
};
|
|
||||||
|
|
||||||
/* button definitions */
|
|
||||||
diff --git a/dwm.1 b/dwm.1
|
|
||||||
index 13b3729..36a331c 100644
|
|
||||||
--- a/dwm.1
|
|
||||||
+++ b/dwm.1
|
|
||||||
@@ -142,6 +142,9 @@ Add/remove all windows with nth tag to/from the view.
|
|
||||||
.TP
|
|
||||||
.B Mod1\-Shift\-q
|
|
||||||
Quit dwm.
|
|
||||||
+.TP
|
|
||||||
+.B Mod1\-Control\-Shift\-q
|
|
||||||
+Restart dwm.
|
|
||||||
.SS Mouse commands
|
|
||||||
.TP
|
|
||||||
.B Mod1\-Button1
|
|
||||||
@@ -155,6 +158,13 @@ Resize focused window while dragging. Tiled windows will be toggled to the float
|
|
||||||
.SH CUSTOMIZATION
|
|
||||||
dwm is customized by creating a custom config.h and (re)compiling the source
|
|
||||||
code. This keeps it fast, secure and simple.
|
|
||||||
+.SH SIGNALS
|
|
||||||
+.TP
|
|
||||||
+.B SIGHUP - 1
|
|
||||||
+Restart the dwm process.
|
|
||||||
+.TP
|
|
||||||
+.B SIGTERM - 15
|
|
||||||
+Cleanly terminate the dwm process.
|
|
||||||
.SH SEE ALSO
|
|
||||||
.BR dmenu (1),
|
|
||||||
.BR st (1)
|
|
||||||
diff --git a/dwm.c b/dwm.c
|
|
||||||
index bb95e26..286eecd 100644
|
|
||||||
--- a/dwm.c
|
|
||||||
+++ b/dwm.c
|
|
||||||
@@ -205,6 +205,8 @@ static void setup(void);
|
|
||||||
static void seturgent(Client *c, int urg);
|
|
||||||
static void showhide(Client *c);
|
|
||||||
static void sigchld(int unused);
|
|
||||||
+static void sighup(int unused);
|
|
||||||
+static void sigterm(int unused);
|
|
||||||
static void spawn(const Arg *arg);
|
|
||||||
static void tag(const Arg *arg);
|
|
||||||
static void tagmon(const Arg *arg);
|
|
||||||
@@ -260,6 +262,7 @@ static void (*handler[LASTEvent]) (XEvent *) = {
|
|
||||||
[UnmapNotify] = unmapnotify
|
|
||||||
};
|
|
||||||
static Atom wmatom[WMLast], netatom[NetLast];
|
|
||||||
+static int restart = 0;
|
|
||||||
static int running = 1;
|
|
||||||
static Cur *cursor[CurLast];
|
|
||||||
static Clr **scheme;
|
|
||||||
@@ -1248,6 +1251,7 @@ propertynotify(XEvent *e)
|
|
||||||
void
|
|
||||||
quit(const Arg *arg)
|
|
||||||
{
|
|
||||||
+ if(arg->i) restart = 1;
|
|
||||||
running = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1536,6 +1540,9 @@ setup(void)
|
|
||||||
/* clean up any zombies immediately */
|
|
||||||
sigchld(0);
|
|
||||||
|
|
||||||
+ signal(SIGHUP, sighup);
|
|
||||||
+ signal(SIGTERM, sigterm);
|
|
||||||
+
|
|
||||||
/* init screen */
|
|
||||||
screen = DefaultScreen(dpy);
|
|
||||||
sw = DisplayWidth(dpy, screen);
|
|
||||||
@@ -1637,6 +1644,20 @@ sigchld(int unused)
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
+sighup(int unused)
|
|
||||||
+{
|
|
||||||
+ Arg a = {.i = 1};
|
|
||||||
+ quit(&a);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+void
|
|
||||||
+sigterm(int unused)
|
|
||||||
+{
|
|
||||||
+ Arg a = {.i = 0};
|
|
||||||
+ quit(&a);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+void
|
|
||||||
spawn(const Arg *arg)
|
|
||||||
{
|
|
||||||
if (arg->v == dmenucmd)
|
|
||||||
@@ -2139,6 +2160,7 @@ main(int argc, char *argv[])
|
|
||||||
setup();
|
|
||||||
scan();
|
|
||||||
run();
|
|
||||||
+ if(restart) execvp(argv[0], argv);
|
|
||||||
cleanup();
|
|
||||||
XCloseDisplay(dpy);
|
|
||||||
return EXIT_SUCCESS;
|
|
||||||
--
|
|
||||||
2.7.4
|
|
||||||
|
|
|
@ -1,265 +0,0 @@
|
||||||
From dc83e43aad7b8070911e8210b58cc36bdc4214d5 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Santtu Lakkala <inz@inz.fi>
|
|
||||||
Date: Wed, 23 Feb 2022 11:55:19 +0200
|
|
||||||
Subject: [PATCH 1/2] Allow CSI SGR in status bar
|
|
||||||
|
|
||||||
---
|
|
||||||
config.def.h | 19 ++++++
|
|
||||||
dwm.c | 182 ++++++++++++++++++++++++++++++++++++++++++++++++++-
|
|
||||||
2 files changed, 198 insertions(+), 3 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/config.def.h b/config.def.h
|
|
||||||
index a2ac963..3dc34bd 100644
|
|
||||||
--- a/config.def.h
|
|
||||||
+++ b/config.def.h
|
|
||||||
@@ -18,6 +18,25 @@ static const char *colors[][3] = {
|
|
||||||
[SchemeSel] = { col_gray4, col_cyan, col_cyan },
|
|
||||||
};
|
|
||||||
|
|
||||||
+static const char *barcolors[] = {
|
|
||||||
+ "#000000",
|
|
||||||
+ "#7f0000",
|
|
||||||
+ "#007f00",
|
|
||||||
+ "#7f7f00",
|
|
||||||
+ "#00007f",
|
|
||||||
+ "#7f007f",
|
|
||||||
+ "#007f7f",
|
|
||||||
+ "#cccccc",
|
|
||||||
+ "#333333",
|
|
||||||
+ "#ff0000",
|
|
||||||
+ "#00ff00",
|
|
||||||
+ "#ffff00",
|
|
||||||
+ "#0000ff",
|
|
||||||
+ "#ff00ff",
|
|
||||||
+ "#00ffff",
|
|
||||||
+ "#ffffff",
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
/* tagging */
|
|
||||||
static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" };
|
|
||||||
|
|
||||||
diff --git a/dwm.c b/dwm.c
|
|
||||||
index a96f33c..cb9484a 100644
|
|
||||||
--- a/dwm.c
|
|
||||||
+++ b/dwm.c
|
|
||||||
@@ -237,7 +237,7 @@ static void zoom(const Arg *arg);
|
|
||||||
|
|
||||||
/* variables */
|
|
||||||
static const char broken[] = "broken";
|
|
||||||
-static char stext[256];
|
|
||||||
+static char stext[512];
|
|
||||||
static int screen;
|
|
||||||
static int sw, sh; /* X display screen geometry width, height */
|
|
||||||
static int bh, blw = 0; /* bar geometry */
|
|
||||||
@@ -264,6 +264,7 @@ static Atom wmatom[WMLast], netatom[NetLast];
|
|
||||||
static int running = 1;
|
|
||||||
static Cur *cursor[CurLast];
|
|
||||||
static Clr **scheme;
|
|
||||||
+static Clr *barclrs;
|
|
||||||
static Display *dpy;
|
|
||||||
static Drw *drw;
|
|
||||||
static Monitor *mons, *selmon;
|
|
||||||
@@ -693,6 +694,25 @@ dirtomon(int dir)
|
|
||||||
return m;
|
|
||||||
}
|
|
||||||
|
|
||||||
+void
|
|
||||||
+resetfntlist(Fnt *orighead, Fnt *curhead)
|
|
||||||
+{
|
|
||||||
+ if (orighead != curhead) {
|
|
||||||
+ Fnt *f;
|
|
||||||
+ for (f = orighead; f->next; f = f->next);
|
|
||||||
+ f->next = curhead;
|
|
||||||
+ for (f = f->next; f->next != orighead; f = f->next);
|
|
||||||
+ f->next = NULL;
|
|
||||||
+ }
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+enum SgrFlags {
|
|
||||||
+ REVERSE = 1 << 0,
|
|
||||||
+ UNDERLINE = 1 << 1,
|
|
||||||
+ STRIKETHROUGH = 1 << 2,
|
|
||||||
+ OVERLINE = 1 << 3
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
void
|
|
||||||
drawbar(Monitor *m)
|
|
||||||
{
|
|
||||||
@@ -707,9 +727,160 @@ drawbar(Monitor *m)
|
|
||||||
|
|
||||||
/* draw status first so it can be overdrawn by tags later */
|
|
||||||
if (m == selmon) { /* status is only drawn on selected monitor */
|
|
||||||
+ char buffer[sizeof(stext)];
|
|
||||||
+ Clr scm[3];
|
|
||||||
+ int wr, rd;
|
|
||||||
+ int pw;
|
|
||||||
+ int fg = 7;
|
|
||||||
+ int bg = 0;
|
|
||||||
+ int fmt = 0;
|
|
||||||
+ int lp = lrpad / 2 - 2;
|
|
||||||
+ Fnt *fset = drw->fonts;
|
|
||||||
+
|
|
||||||
+ memcpy(scm, scheme[SchemeNorm], sizeof(scm));
|
|
||||||
+
|
|
||||||
+ drw_setscheme(drw, scm);
|
|
||||||
+
|
|
||||||
+ for (tw = 0, wr = 0, rd = 0; stext[rd]; rd++) {
|
|
||||||
+ if (stext[rd] == '' && stext[rd + 1] == '[') {
|
|
||||||
+ size_t alen = strspn(stext + rd + 2,
|
|
||||||
+ "0123456789;");
|
|
||||||
+ if (stext[rd + alen + 2] == 'm') {
|
|
||||||
+ buffer[wr] = '\0';
|
|
||||||
+ tw += TEXTW(buffer) - lrpad;
|
|
||||||
+ wr = 0;
|
|
||||||
+
|
|
||||||
+ char *ep = stext + rd + 1;
|
|
||||||
+ while (*ep != 'm') {
|
|
||||||
+ unsigned v = strtoul(ep + 1, &ep, 10);
|
|
||||||
+ if (v == 0 || (v >= 10 && v <= 19)) {
|
|
||||||
+ int fi = v % 10;
|
|
||||||
+ Fnt *f;
|
|
||||||
+ Fnt *p;
|
|
||||||
+ resetfntlist(fset, drw->fonts);
|
|
||||||
+ for (p = NULL, f = fset; f && fi--; p = f, f = f->next);
|
|
||||||
+ if (f) {
|
|
||||||
+ if (p) {
|
|
||||||
+ p->next = NULL;
|
|
||||||
+ for (p = f; p->next; p = p->next);
|
|
||||||
+ p->next = fset;
|
|
||||||
+ }
|
|
||||||
+ drw_setfontset(drw, f);
|
|
||||||
+ } else {
|
|
||||||
+ drw_setfontset(drw, fset);
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ rd += alen + 2;
|
|
||||||
+ continue;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ buffer[wr++] = stext[rd];
|
|
||||||
+ }
|
|
||||||
+ buffer[wr] = '\0';
|
|
||||||
+
|
|
||||||
+ tw += TEXTW(buffer) - lrpad / 2 + 2;
|
|
||||||
+ x = m->ww - tw;
|
|
||||||
+
|
|
||||||
+ resetfntlist(fset, drw->fonts);
|
|
||||||
+ drw_setfontset(drw, fset);
|
|
||||||
+
|
|
||||||
+ for (wr = 0, rd = 0; stext[rd]; rd++) {
|
|
||||||
+ if (stext[rd] == '' && stext[rd + 1] == '[') {
|
|
||||||
+ size_t alen = strspn(stext + rd + 2,
|
|
||||||
+ "0123456789;");
|
|
||||||
+ if (stext[rd + alen + 2] == 'm') {
|
|
||||||
+ buffer[wr] = '\0';
|
|
||||||
+ pw = TEXTW(buffer) - lrpad;
|
|
||||||
+ drw_text(drw, x, 0, pw + lp, bh, lp, buffer, fmt & REVERSE);
|
|
||||||
+ if (fmt & UNDERLINE)
|
|
||||||
+ drw_rect(drw, x, (bh + drw->fonts->h) / 2, pw, 1, 1, fmt & REVERSE);
|
|
||||||
+ if (fmt & STRIKETHROUGH)
|
|
||||||
+ drw_rect(drw, x, bh / 2, pw, 1, 1, fmt & REVERSE);
|
|
||||||
+ if (fmt & OVERLINE)
|
|
||||||
+ drw_rect(drw, x, (bh - drw->fonts->h) / 2, pw, 1, 1, fmt & REVERSE);
|
|
||||||
+ x += pw + lp;
|
|
||||||
+ lp = 0;
|
|
||||||
+
|
|
||||||
+ char *ep = stext + rd + 1;
|
|
||||||
+ while (*ep != 'm') {
|
|
||||||
+ unsigned v = strtoul(ep + 1, &ep, 10);
|
|
||||||
+ if (v == 0) {
|
|
||||||
+ memcpy(scm, scheme[SchemeNorm], sizeof(scm));
|
|
||||||
+ fg = 7;
|
|
||||||
+ bg = 0;
|
|
||||||
+ fmt = 0;
|
|
||||||
+ resetfntlist(fset, drw->fonts);
|
|
||||||
+ drw_setfontset(drw, fset);
|
|
||||||
+ } else if (v == 1) {
|
|
||||||
+ fg |= 8;
|
|
||||||
+ scm[0] = barclrs[fg];
|
|
||||||
+ } else if (v == 4) {
|
|
||||||
+ fmt |= UNDERLINE;
|
|
||||||
+ } else if (v == 7) {
|
|
||||||
+ fmt |= REVERSE;
|
|
||||||
+ } else if (v == 9) {
|
|
||||||
+ fmt |= STRIKETHROUGH;
|
|
||||||
+ } else if (v >= 10 && v <= 19) {
|
|
||||||
+ int fi = v % 10;
|
|
||||||
+ Fnt *f;
|
|
||||||
+ Fnt *p;
|
|
||||||
+ resetfntlist(fset, drw->fonts);
|
|
||||||
+ for (p = NULL, f = fset; f && fi--; p = f, f = f->next);
|
|
||||||
+ if (f) {
|
|
||||||
+ if (p) {
|
|
||||||
+ p->next = NULL;
|
|
||||||
+ for (p = f; p->next; p = p->next);
|
|
||||||
+ p->next = fset;
|
|
||||||
+ }
|
|
||||||
+ drw_setfontset(drw, f);
|
|
||||||
+ } else {
|
|
||||||
+ drw_setfontset(drw, fset);
|
|
||||||
+ }
|
|
||||||
+ } else if (v == 22) {
|
|
||||||
+ fg &= ~8;
|
|
||||||
+ scm[0] = barclrs[fg];
|
|
||||||
+ } else if (v == 24) {
|
|
||||||
+ fmt &= ~UNDERLINE;
|
|
||||||
+ } else if (v == 27) {
|
|
||||||
+ fmt &= ~REVERSE;
|
|
||||||
+ } else if (v == 29) {
|
|
||||||
+ fmt &= ~STRIKETHROUGH;
|
|
||||||
+ } else if (v >= 30 && v <= 37) {
|
|
||||||
+ fg = v % 10 | (fg & 8);
|
|
||||||
+ scm[0] = barclrs[fg];
|
|
||||||
+ } else if (v >= 40 && v <= 47) {
|
|
||||||
+ bg = v % 10;
|
|
||||||
+ scm[1] = barclrs[bg];
|
|
||||||
+ } else if (v == 53) {
|
|
||||||
+ fmt |= OVERLINE;
|
|
||||||
+ } else if (v == 55) {
|
|
||||||
+ fmt &= ~OVERLINE;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ rd += alen + 2;
|
|
||||||
+ wr = 0;
|
|
||||||
+
|
|
||||||
+ drw_setscheme(drw, scm);
|
|
||||||
+ continue;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ buffer[wr++] = stext[rd];
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ buffer[wr] = '\0';
|
|
||||||
+ pw = TEXTW(buffer) - lrpad;
|
|
||||||
+ drw_text(drw, x, 0, pw + lp, bh, lp, buffer, fmt & REVERSE);
|
|
||||||
+ if (fmt & UNDERLINE)
|
|
||||||
+ drw_rect(drw, x, (bh + drw->fonts->h) / 2, pw, 1, 1, fmt & REVERSE);
|
|
||||||
+ if (fmt & STRIKETHROUGH)
|
|
||||||
+ drw_rect(drw, x, bh / 2, pw, 1, 1, fmt & REVERSE);
|
|
||||||
+ if (fmt & OVERLINE)
|
|
||||||
+ drw_rect(drw, x, (bh - drw->fonts->h) / 2, pw, 1, 1, fmt & REVERSE);
|
|
||||||
+
|
|
||||||
drw_setscheme(drw, scheme[SchemeNorm]);
|
|
||||||
- tw = TEXTW(stext) - lrpad + 2; /* 2px right padding */
|
|
||||||
- drw_text(drw, m->ww - tw, 0, tw, bh, 0, stext, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (c = m->clients; c; c = c->next) {
|
|
||||||
@@ -1574,6 +1745,11 @@ setup(void)
|
|
||||||
scheme = ecalloc(LENGTH(colors), sizeof(Clr *));
|
|
||||||
for (i = 0; i < LENGTH(colors); i++)
|
|
||||||
scheme[i] = drw_scm_create(drw, colors[i], 3);
|
|
||||||
+
|
|
||||||
+ barclrs = ecalloc(LENGTH(barcolors), sizeof(Clr));
|
|
||||||
+ for (i = 0; i < LENGTH(barcolors); i++)
|
|
||||||
+ drw_clr_create(drw, &barclrs[i], barcolors[i]);
|
|
||||||
+
|
|
||||||
/* init bars */
|
|
||||||
updatebars();
|
|
||||||
updatestatus();
|
|
||||||
--
|
|
||||||
2.32.0
|
|
||||||
|
|
|
@ -1,197 +0,0 @@
|
||||||
From d04f2d00688c8b0969d4f10f460c980dd91dac37 Mon Sep 17 00:00:00 2001
|
|
||||||
From: MLquest8 <miskuzius@gmail.com>
|
|
||||||
Date: Fri, 12 Jun 2020 16:04:18 +0400
|
|
||||||
Subject: [PATCH] stacker updated for version 6.2
|
|
||||||
|
|
||||||
---
|
|
||||||
config.def.h | 14 +++++++--
|
|
||||||
dwm.c | 88 ++++++++++++++++++++++++++++++++++++++++------------
|
|
||||||
2 files changed, 80 insertions(+), 22 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/config.def.h b/config.def.h
|
|
||||||
index 1c0b587..d28f8fc 100644
|
|
||||||
--- a/config.def.h
|
|
||||||
+++ b/config.def.h
|
|
||||||
@@ -50,6 +50,14 @@ static const Layout layouts[] = {
|
|
||||||
{ MODKEY|ControlMask, KEY, toggleview, {.ui = 1 << TAG} }, \
|
|
||||||
{ MODKEY|ShiftMask, KEY, tag, {.ui = 1 << TAG} }, \
|
|
||||||
{ MODKEY|ControlMask|ShiftMask, KEY, toggletag, {.ui = 1 << TAG} },
|
|
||||||
+#define STACKKEYS(MOD,ACTION) \
|
|
||||||
+ { MOD, XK_j, ACTION##stack, {.i = INC(+1) } }, \
|
|
||||||
+ { MOD, XK_k, ACTION##stack, {.i = INC(-1) } }, \
|
|
||||||
+ { MOD, XK_grave, ACTION##stack, {.i = PREVSEL } }, \
|
|
||||||
+ { MOD, XK_q, ACTION##stack, {.i = 0 } }, \
|
|
||||||
+ { MOD, XK_a, ACTION##stack, {.i = 1 } }, \
|
|
||||||
+ { MOD, XK_z, ACTION##stack, {.i = 2 } }, \
|
|
||||||
+ { MOD, XK_x, ACTION##stack, {.i = -1 } },
|
|
||||||
|
|
||||||
/* helper for spawning shell commands in the pre dwm-5.0 fashion */
|
|
||||||
#define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } }
|
|
||||||
@@ -64,8 +72,8 @@ static Key keys[] = {
|
|
||||||
{ MODKEY, XK_p, spawn, {.v = dmenucmd } },
|
|
||||||
{ MODKEY|ShiftMask, XK_Return, spawn, {.v = termcmd } },
|
|
||||||
{ MODKEY, XK_b, togglebar, {0} },
|
|
||||||
- { MODKEY, XK_j, focusstack, {.i = +1 } },
|
|
||||||
- { MODKEY, XK_k, focusstack, {.i = -1 } },
|
|
||||||
+ STACKKEYS(MODKEY, focus)
|
|
||||||
+ STACKKEYS(MODKEY|ShiftMask, push)
|
|
||||||
{ MODKEY, XK_i, incnmaster, {.i = +1 } },
|
|
||||||
{ MODKEY, XK_d, incnmaster, {.i = -1 } },
|
|
||||||
{ MODKEY, XK_h, setmfact, {.f = -0.05} },
|
|
||||||
@@ -93,7 +101,7 @@ static Key keys[] = {
|
|
||||||
TAGKEYS( XK_7, 6)
|
|
||||||
TAGKEYS( XK_8, 7)
|
|
||||||
TAGKEYS( XK_9, 8)
|
|
||||||
- { MODKEY|ShiftMask, XK_q, quit, {0} },
|
|
||||||
+ { MODKEY|ShiftMask, XK_BackSpace, quit, {0} },
|
|
||||||
};
|
|
||||||
|
|
||||||
/* button definitions */
|
|
||||||
diff --git a/dwm.c b/dwm.c
|
|
||||||
index 9fd0286..6c302c3 100644
|
|
||||||
--- a/dwm.c
|
|
||||||
+++ b/dwm.c
|
|
||||||
@@ -47,15 +47,21 @@
|
|
||||||
/* macros */
|
|
||||||
#define BUTTONMASK (ButtonPressMask|ButtonReleaseMask)
|
|
||||||
#define CLEANMASK(mask) (mask & ~(numlockmask|LockMask) & (ShiftMask|ControlMask|Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask))
|
|
||||||
+#define GETINC(X) ((X) - 2000)
|
|
||||||
+#define INC(X) ((X) + 2000)
|
|
||||||
#define INTERSECT(x,y,w,h,m) (MAX(0, MIN((x)+(w),(m)->wx+(m)->ww) - MAX((x),(m)->wx)) \
|
|
||||||
* MAX(0, MIN((y)+(h),(m)->wy+(m)->wh) - MAX((y),(m)->wy)))
|
|
||||||
+#define ISINC(X) ((X) > 1000 && (X) < 3000)
|
|
||||||
#define ISVISIBLE(C) ((C->tags & C->mon->tagset[C->mon->seltags]))
|
|
||||||
+#define PREVSEL 3000
|
|
||||||
#define LENGTH(X) (sizeof X / sizeof X[0])
|
|
||||||
+#define MOD(N,M) ((N)%(M) < 0 ? (N)%(M) + (M) : (N)%(M))
|
|
||||||
#define MOUSEMASK (BUTTONMASK|PointerMotionMask)
|
|
||||||
#define WIDTH(X) ((X)->w + 2 * (X)->bw)
|
|
||||||
#define HEIGHT(X) ((X)->h + 2 * (X)->bw)
|
|
||||||
#define TAGMASK ((1 << LENGTH(tags)) - 1)
|
|
||||||
#define TEXTW(X) (drw_fontset_getwidth(drw, (X)) + lrpad)
|
|
||||||
+#define TRUNC(X,A,B) (MAX((A), MIN((X), (B))))
|
|
||||||
|
|
||||||
/* enums */
|
|
||||||
enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */
|
|
||||||
@@ -187,6 +193,7 @@ static void movemouse(const Arg *arg);
|
|
||||||
static Client *nexttiled(Client *c);
|
|
||||||
static void pop(Client *);
|
|
||||||
static void propertynotify(XEvent *e);
|
|
||||||
+static void pushstack(const Arg *arg);
|
|
||||||
static void quit(const Arg *arg);
|
|
||||||
static Monitor *recttomon(int x, int y, int w, int h);
|
|
||||||
static void resize(Client *c, int x, int y, int w, int h, int interact);
|
|
||||||
@@ -207,6 +214,7 @@ static void seturgent(Client *c, int urg);
|
|
||||||
static void showhide(Client *c);
|
|
||||||
static void sigchld(int unused);
|
|
||||||
static void spawn(const Arg *arg);
|
|
||||||
+static int stackpos(const Arg *arg);
|
|
||||||
static void tag(const Arg *arg);
|
|
||||||
static void tagmon(const Arg *arg);
|
|
||||||
static void tile(Monitor *);
|
|
||||||
@@ -833,27 +841,16 @@ focusmon(const Arg *arg)
|
|
||||||
void
|
|
||||||
focusstack(const Arg *arg)
|
|
||||||
{
|
|
||||||
- Client *c = NULL, *i;
|
|
||||||
+ int i = stackpos(arg);
|
|
||||||
+ Client *c, *p;
|
|
||||||
|
|
||||||
- if (!selmon->sel)
|
|
||||||
+ if(i < 0)
|
|
||||||
return;
|
|
||||||
- if (arg->i > 0) {
|
|
||||||
- for (c = selmon->sel->next; c && !ISVISIBLE(c); c = c->next);
|
|
||||||
- if (!c)
|
|
||||||
- for (c = selmon->clients; c && !ISVISIBLE(c); c = c->next);
|
|
||||||
- } else {
|
|
||||||
- for (i = selmon->clients; i != selmon->sel; i = i->next)
|
|
||||||
- if (ISVISIBLE(i))
|
|
||||||
- c = i;
|
|
||||||
- if (!c)
|
|
||||||
- for (; i; i = i->next)
|
|
||||||
- if (ISVISIBLE(i))
|
|
||||||
- c = i;
|
|
||||||
- }
|
|
||||||
- if (c) {
|
|
||||||
- focus(c);
|
|
||||||
- restack(selmon);
|
|
||||||
- }
|
|
||||||
+
|
|
||||||
+ for(p = NULL, c = selmon->clients; c && (i || !ISVISIBLE(c));
|
|
||||||
+ i -= ISVISIBLE(c) ? 1 : 0, p = c, c = c->next);
|
|
||||||
+ focus(c ? c : p);
|
|
||||||
+ restack(selmon);
|
|
||||||
}
|
|
||||||
|
|
||||||
Atom
|
|
||||||
@@ -1246,6 +1243,29 @@ propertynotify(XEvent *e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
+void
|
|
||||||
+pushstack(const Arg *arg) {
|
|
||||||
+ int i = stackpos(arg);
|
|
||||||
+ Client *sel = selmon->sel, *c, *p;
|
|
||||||
+
|
|
||||||
+ if(i < 0)
|
|
||||||
+ return;
|
|
||||||
+ else if(i == 0) {
|
|
||||||
+ detach(sel);
|
|
||||||
+ attach(sel);
|
|
||||||
+ }
|
|
||||||
+ else {
|
|
||||||
+ for(p = NULL, c = selmon->clients; c; p = c, c = c->next)
|
|
||||||
+ if(!(i -= (ISVISIBLE(c) && c != sel)))
|
|
||||||
+ break;
|
|
||||||
+ c = c ? c : p;
|
|
||||||
+ detach(sel);
|
|
||||||
+ sel->next = c->next;
|
|
||||||
+ c->next = sel;
|
|
||||||
+ }
|
|
||||||
+ arrange(selmon);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
void
|
|
||||||
quit(const Arg *arg)
|
|
||||||
{
|
|
||||||
@@ -1653,6 +1673,36 @@ spawn(const Arg *arg)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
+int
|
|
||||||
+stackpos(const Arg *arg) {
|
|
||||||
+ int n, i;
|
|
||||||
+ Client *c, *l;
|
|
||||||
+
|
|
||||||
+ if(!selmon->clients)
|
|
||||||
+ return -1;
|
|
||||||
+
|
|
||||||
+ if(arg->i == PREVSEL) {
|
|
||||||
+ for(l = selmon->stack; l && (!ISVISIBLE(l) || l == selmon->sel); l = l->snext);
|
|
||||||
+ if(!l)
|
|
||||||
+ return -1;
|
|
||||||
+ for(i = 0, c = selmon->clients; c != l; i += ISVISIBLE(c) ? 1 : 0, c = c->next);
|
|
||||||
+ return i;
|
|
||||||
+ }
|
|
||||||
+ else if(ISINC(arg->i)) {
|
|
||||||
+ if(!selmon->sel)
|
|
||||||
+ return -1;
|
|
||||||
+ for(i = 0, c = selmon->clients; c != selmon->sel; i += ISVISIBLE(c) ? 1 : 0, c = c->next);
|
|
||||||
+ for(n = i; c; n += ISVISIBLE(c) ? 1 : 0, c = c->next);
|
|
||||||
+ return MOD(i + GETINC(arg->i), n);
|
|
||||||
+ }
|
|
||||||
+ else if(arg->i < 0) {
|
|
||||||
+ for(i = 0, c = selmon->clients; c; i += ISVISIBLE(c) ? 1 : 0, c = c->next);
|
|
||||||
+ return MAX(i + arg->i, 0);
|
|
||||||
+ }
|
|
||||||
+ else
|
|
||||||
+ return arg->i;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
void
|
|
||||||
tag(const Arg *arg)
|
|
||||||
{
|
|
||||||
--
|
|
||||||
2.26.2
|
|
||||||
|
|
|
@ -1,412 +0,0 @@
|
||||||
From 0cf9a007511f7dfd7dd94171b172562ebac9b6d5 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Tom Schwindl <schwindl@posteo.de>
|
|
||||||
Date: Sat, 10 Sep 2022 12:51:09 +0200
|
|
||||||
Subject: [PATCH] 6.3 swallow patch
|
|
||||||
|
|
||||||
---
|
|
||||||
config.def.h | 9 +-
|
|
||||||
config.mk | 3 +-
|
|
||||||
dwm.c | 235 +++++++++++++++++++++++++++++++++++++++++++++++++--
|
|
||||||
3 files changed, 237 insertions(+), 10 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/config.def.h b/config.def.h
|
|
||||||
index 061ad662f82a..0b2b8ffd30d5 100644
|
|
||||||
--- a/config.def.h
|
|
||||||
+++ b/config.def.h
|
|
||||||
@@ -3,6 +3,7 @@
|
|
||||||
/* appearance */
|
|
||||||
static const unsigned int borderpx = 1; /* border pixel of windows */
|
|
||||||
static const unsigned int snap = 32; /* snap pixel */
|
|
||||||
+static const int swallowfloating = 0; /* 1 means swallow floating windows by default */
|
|
||||||
static const int showbar = 1; /* 0 means no bar */
|
|
||||||
static const int topbar = 1; /* 0 means bottom bar */
|
|
||||||
static const char *fonts[] = { "monospace:size=10" };
|
|
||||||
@@ -26,9 +27,11 @@ static const Rule rules[] = {
|
|
||||||
* WM_CLASS(STRING) = instance, class
|
|
||||||
* WM_NAME(STRING) = title
|
|
||||||
*/
|
|
||||||
- /* class instance title tags mask isfloating monitor */
|
|
||||||
- { "Gimp", NULL, NULL, 0, 1, -1 },
|
|
||||||
- { "Firefox", NULL, NULL, 1 << 8, 0, -1 },
|
|
||||||
+ /* class instance title tags mask isfloating isterminal noswallow monitor */
|
|
||||||
+ { "Gimp", NULL, NULL, 0, 1, 0, 0, -1 },
|
|
||||||
+ { "Firefox", NULL, NULL, 1 << 8, 0, 0, -1, -1 },
|
|
||||||
+ { "St", NULL, NULL, 0, 0, 1, 0, -1 },
|
|
||||||
+ { NULL, NULL, "Event Tester", 0, 0, 0, 1, -1 }, /* xev */
|
|
||||||
};
|
|
||||||
|
|
||||||
/* layout(s) */
|
|
||||||
diff --git a/config.mk b/config.mk
|
|
||||||
index 81c493ef4aff..52d1ebf30bec 100644
|
|
||||||
--- a/config.mk
|
|
||||||
+++ b/config.mk
|
|
||||||
@@ -20,10 +20,11 @@ FREETYPEINC = /usr/include/freetype2
|
|
||||||
# OpenBSD (uncomment)
|
|
||||||
#FREETYPEINC = ${X11INC}/freetype2
|
|
||||||
#MANPREFIX = ${PREFIX}/man
|
|
||||||
+#KVMLIB = -lkvm
|
|
||||||
|
|
||||||
# includes and libs
|
|
||||||
INCS = -I${X11INC} -I${FREETYPEINC}
|
|
||||||
-LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS}
|
|
||||||
+LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} -lX11-xcb -lxcb -lxcb-res ${KVMLIB}
|
|
||||||
|
|
||||||
# flags
|
|
||||||
CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_POSIX_C_SOURCE=200809L -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS}
|
|
||||||
diff --git a/dwm.c b/dwm.c
|
|
||||||
index e5efb6a22806..e68294b6b679 100644
|
|
||||||
--- a/dwm.c
|
|
||||||
+++ b/dwm.c
|
|
||||||
@@ -40,6 +40,12 @@
|
|
||||||
#include <X11/extensions/Xinerama.h>
|
|
||||||
#endif /* XINERAMA */
|
|
||||||
#include <X11/Xft/Xft.h>
|
|
||||||
+#include <X11/Xlib-xcb.h>
|
|
||||||
+#include <xcb/res.h>
|
|
||||||
+#ifdef __OpenBSD__
|
|
||||||
+#include <sys/sysctl.h>
|
|
||||||
+#include <kvm.h>
|
|
||||||
+#endif /* __OpenBSD */
|
|
||||||
|
|
||||||
#include "drw.h"
|
|
||||||
#include "util.h"
|
|
||||||
@@ -92,9 +98,11 @@ struct Client {
|
|
||||||
int basew, baseh, incw, inch, maxw, maxh, minw, minh, hintsvalid;
|
|
||||||
int bw, oldbw;
|
|
||||||
unsigned int tags;
|
|
||||||
- int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen;
|
|
||||||
+ int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen, isterminal, noswallow;
|
|
||||||
+ pid_t pid;
|
|
||||||
Client *next;
|
|
||||||
Client *snext;
|
|
||||||
+ Client *swallowing;
|
|
||||||
Monitor *mon;
|
|
||||||
Window win;
|
|
||||||
};
|
|
||||||
@@ -138,6 +146,8 @@ typedef struct {
|
|
||||||
const char *title;
|
|
||||||
unsigned int tags;
|
|
||||||
int isfloating;
|
|
||||||
+ int isterminal;
|
|
||||||
+ int noswallow;
|
|
||||||
int monitor;
|
|
||||||
} Rule;
|
|
||||||
|
|
||||||
@@ -235,6 +245,12 @@ static int xerrordummy(Display *dpy, XErrorEvent *ee);
|
|
||||||
static int xerrorstart(Display *dpy, XErrorEvent *ee);
|
|
||||||
static void zoom(const Arg *arg);
|
|
||||||
|
|
||||||
+static pid_t getparentprocess(pid_t p);
|
|
||||||
+static int isdescprocess(pid_t p, pid_t c);
|
|
||||||
+static Client *swallowingclient(Window w);
|
|
||||||
+static Client *termforwin(const Client *c);
|
|
||||||
+static pid_t winpid(Window w);
|
|
||||||
+
|
|
||||||
/* variables */
|
|
||||||
static const char broken[] = "broken";
|
|
||||||
static char stext[256];
|
|
||||||
@@ -269,6 +285,8 @@ static Drw *drw;
|
|
||||||
static Monitor *mons, *selmon;
|
|
||||||
static Window root, wmcheckwin;
|
|
||||||
|
|
||||||
+static xcb_connection_t *xcon;
|
|
||||||
+
|
|
||||||
/* configuration, allows nested code to access above variables */
|
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
@@ -298,6 +316,8 @@ applyrules(Client *c)
|
|
||||||
&& (!r->class || strstr(class, r->class))
|
|
||||||
&& (!r->instance || strstr(instance, r->instance)))
|
|
||||||
{
|
|
||||||
+ c->isterminal = r->isterminal;
|
|
||||||
+ c->noswallow = r->noswallow;
|
|
||||||
c->isfloating = r->isfloating;
|
|
||||||
c->tags |= r->tags;
|
|
||||||
for (m = mons; m && m->num != r->monitor; m = m->next);
|
|
||||||
@@ -416,6 +436,53 @@ attachstack(Client *c)
|
|
||||||
c->mon->stack = c;
|
|
||||||
}
|
|
||||||
|
|
||||||
+void
|
|
||||||
+swallow(Client *p, Client *c)
|
|
||||||
+{
|
|
||||||
+
|
|
||||||
+ if (c->noswallow || c->isterminal)
|
|
||||||
+ return;
|
|
||||||
+ if (c->noswallow && !swallowfloating && c->isfloating)
|
|
||||||
+ return;
|
|
||||||
+
|
|
||||||
+ detach(c);
|
|
||||||
+ detachstack(c);
|
|
||||||
+
|
|
||||||
+ setclientstate(c, WithdrawnState);
|
|
||||||
+ XUnmapWindow(dpy, p->win);
|
|
||||||
+
|
|
||||||
+ p->swallowing = c;
|
|
||||||
+ c->mon = p->mon;
|
|
||||||
+
|
|
||||||
+ Window w = p->win;
|
|
||||||
+ p->win = c->win;
|
|
||||||
+ c->win = w;
|
|
||||||
+ updatetitle(p);
|
|
||||||
+ XMoveResizeWindow(dpy, p->win, p->x, p->y, p->w, p->h);
|
|
||||||
+ arrange(p->mon);
|
|
||||||
+ configure(p);
|
|
||||||
+ updateclientlist();
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+void
|
|
||||||
+unswallow(Client *c)
|
|
||||||
+{
|
|
||||||
+ c->win = c->swallowing->win;
|
|
||||||
+
|
|
||||||
+ free(c->swallowing);
|
|
||||||
+ c->swallowing = NULL;
|
|
||||||
+
|
|
||||||
+ /* unfullscreen the client */
|
|
||||||
+ setfullscreen(c, 0);
|
|
||||||
+ updatetitle(c);
|
|
||||||
+ arrange(c->mon);
|
|
||||||
+ XMapWindow(dpy, c->win);
|
|
||||||
+ XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h);
|
|
||||||
+ setclientstate(c, NormalState);
|
|
||||||
+ focus(NULL);
|
|
||||||
+ arrange(c->mon);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
void
|
|
||||||
buttonpress(XEvent *e)
|
|
||||||
{
|
|
||||||
@@ -656,6 +723,9 @@ destroynotify(XEvent *e)
|
|
||||||
|
|
||||||
if ((c = wintoclient(ev->window)))
|
|
||||||
unmanage(c, 1);
|
|
||||||
+
|
|
||||||
+ else if ((c = swallowingclient(ev->window)))
|
|
||||||
+ unmanage(c->swallowing, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
@@ -1022,12 +1092,13 @@ killclient(const Arg *arg)
|
|
||||||
void
|
|
||||||
manage(Window w, XWindowAttributes *wa)
|
|
||||||
{
|
|
||||||
- Client *c, *t = NULL;
|
|
||||||
+ Client *c, *t = NULL, *term = NULL;
|
|
||||||
Window trans = None;
|
|
||||||
XWindowChanges wc;
|
|
||||||
|
|
||||||
c = ecalloc(1, sizeof(Client));
|
|
||||||
c->win = w;
|
|
||||||
+ c->pid = winpid(w);
|
|
||||||
/* geometry */
|
|
||||||
c->x = c->oldx = wa->x;
|
|
||||||
c->y = c->oldy = wa->y;
|
|
||||||
@@ -1042,6 +1113,7 @@ manage(Window w, XWindowAttributes *wa)
|
|
||||||
} else {
|
|
||||||
c->mon = selmon;
|
|
||||||
applyrules(c);
|
|
||||||
+ term = termforwin(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (c->x + WIDTH(c) > c->mon->wx + c->mon->ww)
|
|
||||||
@@ -1076,6 +1148,8 @@ manage(Window w, XWindowAttributes *wa)
|
|
||||||
c->mon->sel = c;
|
|
||||||
arrange(c->mon);
|
|
||||||
XMapWindow(dpy, c->win);
|
|
||||||
+ if (term)
|
|
||||||
+ swallow(term, c);
|
|
||||||
focus(NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1763,6 +1837,20 @@ unmanage(Client *c, int destroyed)
|
|
||||||
Monitor *m = c->mon;
|
|
||||||
XWindowChanges wc;
|
|
||||||
|
|
||||||
+ if (c->swallowing) {
|
|
||||||
+ unswallow(c);
|
|
||||||
+ return;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ Client *s = swallowingclient(c->win);
|
|
||||||
+ if (s) {
|
|
||||||
+ free(s->swallowing);
|
|
||||||
+ s->swallowing = NULL;
|
|
||||||
+ arrange(m);
|
|
||||||
+ focus(NULL);
|
|
||||||
+ return;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
detach(c);
|
|
||||||
detachstack(c);
|
|
||||||
if (!destroyed) {
|
|
||||||
@@ -1778,9 +1866,12 @@ unmanage(Client *c, int destroyed)
|
|
||||||
XUngrabServer(dpy);
|
|
||||||
}
|
|
||||||
free(c);
|
|
||||||
- focus(NULL);
|
|
||||||
- updateclientlist();
|
|
||||||
- arrange(m);
|
|
||||||
+
|
|
||||||
+ if (!s) {
|
|
||||||
+ arrange(m);
|
|
||||||
+ focus(NULL);
|
|
||||||
+ updateclientlist();
|
|
||||||
+ }
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
@@ -2044,6 +2135,136 @@ view(const Arg *arg)
|
|
||||||
arrange(selmon);
|
|
||||||
}
|
|
||||||
|
|
||||||
+pid_t
|
|
||||||
+winpid(Window w)
|
|
||||||
+{
|
|
||||||
+
|
|
||||||
+ pid_t result = 0;
|
|
||||||
+
|
|
||||||
+#ifdef __linux__
|
|
||||||
+ xcb_res_client_id_spec_t spec = {0};
|
|
||||||
+ spec.client = w;
|
|
||||||
+ spec.mask = XCB_RES_CLIENT_ID_MASK_LOCAL_CLIENT_PID;
|
|
||||||
+
|
|
||||||
+ xcb_generic_error_t *e = NULL;
|
|
||||||
+ xcb_res_query_client_ids_cookie_t c = xcb_res_query_client_ids(xcon, 1, &spec);
|
|
||||||
+ xcb_res_query_client_ids_reply_t *r = xcb_res_query_client_ids_reply(xcon, c, &e);
|
|
||||||
+
|
|
||||||
+ if (!r)
|
|
||||||
+ return (pid_t)0;
|
|
||||||
+
|
|
||||||
+ xcb_res_client_id_value_iterator_t i = xcb_res_query_client_ids_ids_iterator(r);
|
|
||||||
+ for (; i.rem; xcb_res_client_id_value_next(&i)) {
|
|
||||||
+ spec = i.data->spec;
|
|
||||||
+ if (spec.mask & XCB_RES_CLIENT_ID_MASK_LOCAL_CLIENT_PID) {
|
|
||||||
+ uint32_t *t = xcb_res_client_id_value_value(i.data);
|
|
||||||
+ result = *t;
|
|
||||||
+ break;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ free(r);
|
|
||||||
+
|
|
||||||
+ if (result == (pid_t)-1)
|
|
||||||
+ result = 0;
|
|
||||||
+
|
|
||||||
+#endif /* __linux__ */
|
|
||||||
+
|
|
||||||
+#ifdef __OpenBSD__
|
|
||||||
+ Atom type;
|
|
||||||
+ int format;
|
|
||||||
+ unsigned long len, bytes;
|
|
||||||
+ unsigned char *prop;
|
|
||||||
+ pid_t ret;
|
|
||||||
+
|
|
||||||
+ if (XGetWindowProperty(dpy, w, XInternAtom(dpy, "_NET_WM_PID", 0), 0, 1, False, AnyPropertyType, &type, &format, &len, &bytes, &prop) != Success || !prop)
|
|
||||||
+ return 0;
|
|
||||||
+
|
|
||||||
+ ret = *(pid_t*)prop;
|
|
||||||
+ XFree(prop);
|
|
||||||
+ result = ret;
|
|
||||||
+
|
|
||||||
+#endif /* __OpenBSD__ */
|
|
||||||
+ return result;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+pid_t
|
|
||||||
+getparentprocess(pid_t p)
|
|
||||||
+{
|
|
||||||
+ unsigned int v = 0;
|
|
||||||
+
|
|
||||||
+#ifdef __linux__
|
|
||||||
+ FILE *f;
|
|
||||||
+ char buf[256];
|
|
||||||
+ snprintf(buf, sizeof(buf) - 1, "/proc/%u/stat", (unsigned)p);
|
|
||||||
+
|
|
||||||
+ if (!(f = fopen(buf, "r")))
|
|
||||||
+ return 0;
|
|
||||||
+
|
|
||||||
+ fscanf(f, "%*u %*s %*c %u", &v);
|
|
||||||
+ fclose(f);
|
|
||||||
+#endif /* __linux__*/
|
|
||||||
+
|
|
||||||
+#ifdef __OpenBSD__
|
|
||||||
+ int n;
|
|
||||||
+ kvm_t *kd;
|
|
||||||
+ struct kinfo_proc *kp;
|
|
||||||
+
|
|
||||||
+ kd = kvm_openfiles(NULL, NULL, NULL, KVM_NO_FILES, NULL);
|
|
||||||
+ if (!kd)
|
|
||||||
+ return 0;
|
|
||||||
+
|
|
||||||
+ kp = kvm_getprocs(kd, KERN_PROC_PID, p, sizeof(*kp), &n);
|
|
||||||
+ v = kp->p_ppid;
|
|
||||||
+#endif /* __OpenBSD__ */
|
|
||||||
+
|
|
||||||
+ return (pid_t)v;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+int
|
|
||||||
+isdescprocess(pid_t p, pid_t c)
|
|
||||||
+{
|
|
||||||
+ while (p != c && c != 0)
|
|
||||||
+ c = getparentprocess(c);
|
|
||||||
+
|
|
||||||
+ return (int)c;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+Client *
|
|
||||||
+termforwin(const Client *w)
|
|
||||||
+{
|
|
||||||
+ Client *c;
|
|
||||||
+ Monitor *m;
|
|
||||||
+
|
|
||||||
+ if (!w->pid || w->isterminal)
|
|
||||||
+ return NULL;
|
|
||||||
+
|
|
||||||
+ for (m = mons; m; m = m->next) {
|
|
||||||
+ for (c = m->clients; c; c = c->next) {
|
|
||||||
+ if (c->isterminal && !c->swallowing && c->pid && isdescprocess(c->pid, w->pid))
|
|
||||||
+ return c;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ return NULL;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+Client *
|
|
||||||
+swallowingclient(Window w)
|
|
||||||
+{
|
|
||||||
+ Client *c;
|
|
||||||
+ Monitor *m;
|
|
||||||
+
|
|
||||||
+ for (m = mons; m; m = m->next) {
|
|
||||||
+ for (c = m->clients; c; c = c->next) {
|
|
||||||
+ if (c->swallowing && c->swallowing->win == w)
|
|
||||||
+ return c;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ return NULL;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
Client *
|
|
||||||
wintoclient(Window w)
|
|
||||||
{
|
|
||||||
@@ -2133,10 +2354,12 @@ main(int argc, char *argv[])
|
|
||||||
fputs("warning: no locale support\n", stderr);
|
|
||||||
if (!(dpy = XOpenDisplay(NULL)))
|
|
||||||
die("dwm: cannot open display");
|
|
||||||
+ if (!(xcon = XGetXCBConnection(dpy)))
|
|
||||||
+ die("dwm: cannot get xcb connection\n");
|
|
||||||
checkotherwm();
|
|
||||||
setup();
|
|
||||||
#ifdef __OpenBSD__
|
|
||||||
- if (pledge("stdio rpath proc exec", NULL) == -1)
|
|
||||||
+ if (pledge("stdio rpath proc exec ps", NULL) == -1)
|
|
||||||
die("pledge");
|
|
||||||
#endif /* __OpenBSD__ */
|
|
||||||
scan();
|
|
||||||
--
|
|
||||||
2.37.2
|
|
||||||
|
|
|
@ -1,746 +0,0 @@
|
||||||
diff --git a/config.def.h b/config.def.h
|
|
||||||
index 9efa774..750529d 100644
|
|
||||||
--- a/config.def.h
|
|
||||||
+++ b/config.def.h
|
|
||||||
@@ -3,6 +3,11 @@
|
|
||||||
/* appearance */
|
|
||||||
static const unsigned int borderpx = 1; /* border pixel of windows */
|
|
||||||
static const unsigned int snap = 32; /* snap pixel */
|
|
||||||
+static const unsigned int systraypinning = 0; /* 0: sloppy systray follows selected monitor, >0: pin systray to monitor X */
|
|
||||||
+static const unsigned int systrayonleft = 0; /* 0: systray in the right corner, >0: systray on left of status text */
|
|
||||||
+static const unsigned int systrayspacing = 2; /* systray spacing */
|
|
||||||
+static const int systraypinningfailfirst = 1; /* 1: if pinning fails, display systray on the first monitor, False: display systray on the last monitor*/
|
|
||||||
+static const int showsystray = 1; /* 0 means no systray */
|
|
||||||
static const int showbar = 1; /* 0 means no bar */
|
|
||||||
static const int topbar = 1; /* 0 means bottom bar */
|
|
||||||
static const char *fonts[] = { "monospace:size=10" };
|
|
||||||
@@ -101,8 +106,8 @@ static const Key keys[] = {
|
|
||||||
/* click can be ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, or ClkRootWin */
|
|
||||||
static const Button buttons[] = {
|
|
||||||
/* click event mask button function argument */
|
|
||||||
- { ClkLtSymbol, 0, Button1, setlayout, {0} },
|
|
||||||
- { ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]} },
|
|
||||||
+ { ClkTagBar, MODKEY, Button1, tag, {0} },
|
|
||||||
+ { ClkTagBar, MODKEY, Button3, toggletag, {0} },
|
|
||||||
{ ClkWinTitle, 0, Button2, zoom, {0} },
|
|
||||||
{ ClkStatusText, 0, Button2, spawn, {.v = termcmd } },
|
|
||||||
{ ClkClientWin, MODKEY, Button1, movemouse, {0} },
|
|
||||||
diff --git a/dwm.c b/dwm.c
|
|
||||||
index 03baf42..4611a03 100644
|
|
||||||
--- a/dwm.c
|
|
||||||
+++ b/dwm.c
|
|
||||||
@@ -57,12 +57,27 @@
|
|
||||||
#define TAGMASK ((1 << LENGTH(tags)) - 1)
|
|
||||||
#define TEXTW(X) (drw_fontset_getwidth(drw, (X)) + lrpad)
|
|
||||||
|
|
||||||
+#define SYSTEM_TRAY_REQUEST_DOCK 0
|
|
||||||
+/* XEMBED messages */
|
|
||||||
+#define XEMBED_EMBEDDED_NOTIFY 0
|
|
||||||
+#define XEMBED_WINDOW_ACTIVATE 1
|
|
||||||
+#define XEMBED_FOCUS_IN 4
|
|
||||||
+#define XEMBED_MODALITY_ON 10
|
|
||||||
+#define XEMBED_MAPPED (1 << 0)
|
|
||||||
+#define XEMBED_WINDOW_ACTIVATE 1
|
|
||||||
+#define XEMBED_WINDOW_DEACTIVATE 2
|
|
||||||
+#define VERSION_MAJOR 0
|
|
||||||
+#define VERSION_MINOR 0
|
|
||||||
+#define XEMBED_EMBEDDED_VERSION (VERSION_MAJOR << 16) | VERSION_MINOR
|
|
||||||
+
|
|
||||||
/* enums */
|
|
||||||
enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */
|
|
||||||
enum { SchemeNorm, SchemeSel }; /* color schemes */
|
|
||||||
enum { NetSupported, NetWMName, NetWMState, NetWMCheck,
|
|
||||||
+ NetSystemTray, NetSystemTrayOP, NetSystemTrayOrientation, NetSystemTrayOrientationHorz,
|
|
||||||
NetWMFullscreen, NetActiveWindow, NetWMWindowType,
|
|
||||||
NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH atoms */
|
|
||||||
+enum { Manager, Xembed, XembedInfo, XLast }; /* Xembed atoms */
|
|
||||||
enum { WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast }; /* default atoms */
|
|
||||||
enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle,
|
|
||||||
ClkClientWin, ClkRootWin, ClkLast }; /* clicks */
|
|
||||||
@@ -141,6 +156,12 @@ typedef struct {
|
|
||||||
int monitor;
|
|
||||||
} Rule;
|
|
||||||
|
|
||||||
+typedef struct Systray Systray;
|
|
||||||
+struct Systray {
|
|
||||||
+ Window win;
|
|
||||||
+ Client *icons;
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
/* function declarations */
|
|
||||||
static void applyrules(Client *c);
|
|
||||||
static int applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact);
|
|
||||||
@@ -172,6 +193,7 @@ static void focusstack(const Arg *arg);
|
|
||||||
static Atom getatomprop(Client *c, Atom prop);
|
|
||||||
static int getrootptr(int *x, int *y);
|
|
||||||
static long getstate(Window w);
|
|
||||||
+static unsigned int getsystraywidth();
|
|
||||||
static int gettextprop(Window w, Atom atom, char *text, unsigned int size);
|
|
||||||
static void grabbuttons(Client *c, int focused);
|
|
||||||
static void grabkeys(void);
|
|
||||||
@@ -189,13 +211,16 @@ static void pop(Client *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 removesystrayicon(Client *i);
|
|
||||||
static void resize(Client *c, int x, int y, int w, int h, int interact);
|
|
||||||
+static void resizebarwin(Monitor *m);
|
|
||||||
static void resizeclient(Client *c, int x, int y, int w, int h);
|
|
||||||
static void resizemouse(const Arg *arg);
|
|
||||||
+static void resizerequest(XEvent *e);
|
|
||||||
static void restack(Monitor *m);
|
|
||||||
static void run(void);
|
|
||||||
static void scan(void);
|
|
||||||
-static int sendevent(Client *c, Atom proto);
|
|
||||||
+static int sendevent(Window w, Atom proto, int m, long d0, long d1, long d2, long d3, long d4);
|
|
||||||
static void sendmon(Client *c, Monitor *m);
|
|
||||||
static void setclientstate(Client *c, long state);
|
|
||||||
static void setfocus(Client *c);
|
|
||||||
@@ -207,6 +232,7 @@ static void seturgent(Client *c, int urg);
|
|
||||||
static void showhide(Client *c);
|
|
||||||
static void sigchld(int unused);
|
|
||||||
static void spawn(const Arg *arg);
|
|
||||||
+static Monitor *systraytomon(Monitor *m);
|
|
||||||
static void tag(const Arg *arg);
|
|
||||||
static void tagmon(const Arg *arg);
|
|
||||||
static void tile(Monitor *m);
|
|
||||||
@@ -224,18 +250,23 @@ static int updategeom(void);
|
|
||||||
static void updatenumlockmask(void);
|
|
||||||
static void updatesizehints(Client *c);
|
|
||||||
static void updatestatus(void);
|
|
||||||
+static void updatesystray(void);
|
|
||||||
+static void updatesystrayicongeom(Client *i, int w, int h);
|
|
||||||
+static void updatesystrayiconstate(Client *i, XPropertyEvent *ev);
|
|
||||||
static void updatetitle(Client *c);
|
|
||||||
static void updatewindowtype(Client *c);
|
|
||||||
static void updatewmhints(Client *c);
|
|
||||||
static void view(const Arg *arg);
|
|
||||||
static Client *wintoclient(Window w);
|
|
||||||
static Monitor *wintomon(Window w);
|
|
||||||
+static Client *wintosystrayicon(Window w);
|
|
||||||
static int xerror(Display *dpy, XErrorEvent *ee);
|
|
||||||
static int xerrordummy(Display *dpy, XErrorEvent *ee);
|
|
||||||
static int xerrorstart(Display *dpy, XErrorEvent *ee);
|
|
||||||
static void zoom(const Arg *arg);
|
|
||||||
|
|
||||||
/* variables */
|
|
||||||
+static Systray *systray = NULL;
|
|
||||||
static const char broken[] = "broken";
|
|
||||||
static char stext[256];
|
|
||||||
static int screen;
|
|
||||||
@@ -258,9 +289,10 @@ static void (*handler[LASTEvent]) (XEvent *) = {
|
|
||||||
[MapRequest] = maprequest,
|
|
||||||
[MotionNotify] = motionnotify,
|
|
||||||
[PropertyNotify] = propertynotify,
|
|
||||||
+ [ResizeRequest] = resizerequest,
|
|
||||||
[UnmapNotify] = unmapnotify
|
|
||||||
};
|
|
||||||
-static Atom wmatom[WMLast], netatom[NetLast];
|
|
||||||
+static Atom wmatom[WMLast], netatom[NetLast], xatom[XLast];
|
|
||||||
static int running = 1;
|
|
||||||
static Cur *cursor[CurLast];
|
|
||||||
static Clr **scheme;
|
|
||||||
@@ -442,7 +474,7 @@ buttonpress(XEvent *e)
|
|
||||||
arg.ui = 1 << i;
|
|
||||||
} else if (ev->x < x + TEXTW(selmon->ltsymbol))
|
|
||||||
click = ClkLtSymbol;
|
|
||||||
- else if (ev->x > selmon->ww - (int)TEXTW(stext))
|
|
||||||
+ else if (ev->x > selmon->ww - (int)TEXTW(stext) - getsystraywidth())
|
|
||||||
click = ClkStatusText;
|
|
||||||
else
|
|
||||||
click = ClkWinTitle;
|
|
||||||
@@ -485,6 +517,13 @@ cleanup(void)
|
|
||||||
XUngrabKey(dpy, AnyKey, AnyModifier, root);
|
|
||||||
while (mons)
|
|
||||||
cleanupmon(mons);
|
|
||||||
+
|
|
||||||
+ if (showsystray) {
|
|
||||||
+ XUnmapWindow(dpy, systray->win);
|
|
||||||
+ XDestroyWindow(dpy, systray->win);
|
|
||||||
+ free(systray);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
for (i = 0; i < CurLast; i++)
|
|
||||||
drw_cur_free(drw, cursor[i]);
|
|
||||||
for (i = 0; i < LENGTH(colors); i++)
|
|
||||||
@@ -516,9 +555,58 @@ cleanupmon(Monitor *mon)
|
|
||||||
void
|
|
||||||
clientmessage(XEvent *e)
|
|
||||||
{
|
|
||||||
+ XWindowAttributes wa;
|
|
||||||
+ XSetWindowAttributes swa;
|
|
||||||
XClientMessageEvent *cme = &e->xclient;
|
|
||||||
Client *c = wintoclient(cme->window);
|
|
||||||
|
|
||||||
+ if (showsystray && cme->window == systray->win && cme->message_type == netatom[NetSystemTrayOP]) {
|
|
||||||
+ /* add systray icons */
|
|
||||||
+ if (cme->data.l[1] == SYSTEM_TRAY_REQUEST_DOCK) {
|
|
||||||
+ if (!(c = (Client *)calloc(1, sizeof(Client))))
|
|
||||||
+ die("fatal: could not malloc() %u bytes\n", sizeof(Client));
|
|
||||||
+ if (!(c->win = cme->data.l[2])) {
|
|
||||||
+ free(c);
|
|
||||||
+ return;
|
|
||||||
+ }
|
|
||||||
+ c->mon = selmon;
|
|
||||||
+ c->next = systray->icons;
|
|
||||||
+ systray->icons = c;
|
|
||||||
+ if (!XGetWindowAttributes(dpy, c->win, &wa)) {
|
|
||||||
+ /* use sane defaults */
|
|
||||||
+ wa.width = bh;
|
|
||||||
+ wa.height = bh;
|
|
||||||
+ wa.border_width = 0;
|
|
||||||
+ }
|
|
||||||
+ c->x = c->oldx = c->y = c->oldy = 0;
|
|
||||||
+ c->w = c->oldw = wa.width;
|
|
||||||
+ c->h = c->oldh = wa.height;
|
|
||||||
+ c->oldbw = wa.border_width;
|
|
||||||
+ c->bw = 0;
|
|
||||||
+ c->isfloating = True;
|
|
||||||
+ /* reuse tags field as mapped status */
|
|
||||||
+ c->tags = 1;
|
|
||||||
+ updatesizehints(c);
|
|
||||||
+ updatesystrayicongeom(c, wa.width, wa.height);
|
|
||||||
+ XAddToSaveSet(dpy, c->win);
|
|
||||||
+ XSelectInput(dpy, c->win, StructureNotifyMask | PropertyChangeMask | ResizeRedirectMask);
|
|
||||||
+ XReparentWindow(dpy, c->win, systray->win, 0, 0);
|
|
||||||
+ /* use parents background color */
|
|
||||||
+ swa.background_pixel = scheme[SchemeNorm][ColBg].pixel;
|
|
||||||
+ XChangeWindowAttributes(dpy, c->win, CWBackPixel, &swa);
|
|
||||||
+ sendevent(c->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_EMBEDDED_NOTIFY, 0 , systray->win, XEMBED_EMBEDDED_VERSION);
|
|
||||||
+ /* FIXME not sure if I have to send these events, too */
|
|
||||||
+ sendevent(c->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_FOCUS_IN, 0 , systray->win, XEMBED_EMBEDDED_VERSION);
|
|
||||||
+ sendevent(c->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_WINDOW_ACTIVATE, 0 , systray->win, XEMBED_EMBEDDED_VERSION);
|
|
||||||
+ sendevent(c->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_MODALITY_ON, 0 , systray->win, XEMBED_EMBEDDED_VERSION);
|
|
||||||
+ XSync(dpy, False);
|
|
||||||
+ resizebarwin(selmon);
|
|
||||||
+ updatesystray();
|
|
||||||
+ setclientstate(c, NormalState);
|
|
||||||
+ }
|
|
||||||
+ return;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
if (!c)
|
|
||||||
return;
|
|
||||||
if (cme->message_type == netatom[NetWMState]) {
|
|
||||||
@@ -571,7 +659,7 @@ configurenotify(XEvent *e)
|
|
||||||
for (c = m->clients; c; c = c->next)
|
|
||||||
if (c->isfullscreen)
|
|
||||||
resizeclient(c, m->mx, m->my, m->mw, m->mh);
|
|
||||||
- XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, bh);
|
|
||||||
+ resizebarwin(m);
|
|
||||||
}
|
|
||||||
focus(NULL);
|
|
||||||
arrange(NULL);
|
|
||||||
@@ -656,6 +744,11 @@ destroynotify(XEvent *e)
|
|
||||||
|
|
||||||
if ((c = wintoclient(ev->window)))
|
|
||||||
unmanage(c, 1);
|
|
||||||
+ else if ((c = wintosystrayicon(ev->window))) {
|
|
||||||
+ removesystrayicon(c);
|
|
||||||
+ resizebarwin(selmon);
|
|
||||||
+ updatesystray();
|
|
||||||
+ }
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
@@ -699,7 +792,7 @@ dirtomon(int dir)
|
|
||||||
void
|
|
||||||
drawbar(Monitor *m)
|
|
||||||
{
|
|
||||||
- int x, w, tw = 0;
|
|
||||||
+ int x, w, tw = 0, stw = 0;
|
|
||||||
int boxs = drw->fonts->h / 9;
|
|
||||||
int boxw = drw->fonts->h / 6 + 2;
|
|
||||||
unsigned int i, occ = 0, urg = 0;
|
|
||||||
@@ -708,13 +801,17 @@ drawbar(Monitor *m)
|
|
||||||
if (!m->showbar)
|
|
||||||
return;
|
|
||||||
|
|
||||||
+ if(showsystray && m == systraytomon(m) && !systrayonleft)
|
|
||||||
+ stw = getsystraywidth();
|
|
||||||
+
|
|
||||||
/* draw status first so it can be overdrawn by tags later */
|
|
||||||
if (m == selmon) { /* status is only drawn on selected monitor */
|
|
||||||
drw_setscheme(drw, scheme[SchemeNorm]);
|
|
||||||
- tw = TEXTW(stext) - lrpad + 2; /* 2px right padding */
|
|
||||||
- drw_text(drw, m->ww - tw, 0, tw, bh, 0, stext, 0);
|
|
||||||
+ tw = TEXTW(stext) - lrpad / 2 + 2; /* 2px extra right padding */
|
|
||||||
+ drw_text(drw, m->ww - tw - stw, 0, tw, bh, lrpad / 2 - 2, stext, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
+ resizebarwin(m);
|
|
||||||
for (c = m->clients; c; c = c->next) {
|
|
||||||
occ |= c->tags;
|
|
||||||
if (c->isurgent)
|
|
||||||
@@ -735,7 +832,7 @@ drawbar(Monitor *m)
|
|
||||||
drw_setscheme(drw, scheme[SchemeNorm]);
|
|
||||||
x = drw_text(drw, x, 0, w, bh, lrpad / 2, m->ltsymbol, 0);
|
|
||||||
|
|
||||||
- if ((w = m->ww - tw - x) > bh) {
|
|
||||||
+ if ((w = m->ww - tw - stw - x) > bh) {
|
|
||||||
if (m->sel) {
|
|
||||||
drw_setscheme(drw, scheme[m == selmon ? SchemeSel : SchemeNorm]);
|
|
||||||
drw_text(drw, x, 0, w, bh, lrpad / 2, m->sel->name, 0);
|
|
||||||
@@ -746,7 +843,7 @@ drawbar(Monitor *m)
|
|
||||||
drw_rect(drw, x, 0, w, bh, 1, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
- drw_map(drw, m->barwin, 0, 0, m->ww, bh);
|
|
||||||
+ drw_map(drw, m->barwin, 0, 0, m->ww - stw, bh);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
@@ -783,8 +880,11 @@ expose(XEvent *e)
|
|
||||||
Monitor *m;
|
|
||||||
XExposeEvent *ev = &e->xexpose;
|
|
||||||
|
|
||||||
- if (ev->count == 0 && (m = wintomon(ev->window)))
|
|
||||||
+ if (ev->count == 0 && (m = wintomon(ev->window))) {
|
|
||||||
drawbar(m);
|
|
||||||
+ if (m == selmon)
|
|
||||||
+ updatesystray();
|
|
||||||
+ }
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
@@ -870,14 +970,32 @@ getatomprop(Client *c, Atom prop)
|
|
||||||
unsigned char *p = NULL;
|
|
||||||
Atom da, atom = None;
|
|
||||||
|
|
||||||
- if (XGetWindowProperty(dpy, c->win, prop, 0L, sizeof atom, False, XA_ATOM,
|
|
||||||
+ /* FIXME getatomprop should return the number of items and a pointer to
|
|
||||||
+ * the stored data instead of this workaround */
|
|
||||||
+ Atom req = XA_ATOM;
|
|
||||||
+ if (prop == xatom[XembedInfo])
|
|
||||||
+ req = xatom[XembedInfo];
|
|
||||||
+
|
|
||||||
+ if (XGetWindowProperty(dpy, c->win, prop, 0L, sizeof atom, False, req,
|
|
||||||
&da, &di, &dl, &dl, &p) == Success && p) {
|
|
||||||
atom = *(Atom *)p;
|
|
||||||
+ if (da == xatom[XembedInfo] && dl == 2)
|
|
||||||
+ atom = ((Atom *)p)[1];
|
|
||||||
XFree(p);
|
|
||||||
}
|
|
||||||
return atom;
|
|
||||||
}
|
|
||||||
|
|
||||||
+unsigned int
|
|
||||||
+getsystraywidth()
|
|
||||||
+{
|
|
||||||
+ unsigned int w = 0;
|
|
||||||
+ Client *i;
|
|
||||||
+ if(showsystray)
|
|
||||||
+ for(i = systray->icons; i; w += i->w + systrayspacing, i = i->next) ;
|
|
||||||
+ return w ? w + systrayspacing : 1;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
int
|
|
||||||
getrootptr(int *x, int *y)
|
|
||||||
{
|
|
||||||
@@ -1018,7 +1136,8 @@ killclient(const Arg *arg)
|
|
||||||
{
|
|
||||||
if (!selmon->sel)
|
|
||||||
return;
|
|
||||||
- if (!sendevent(selmon->sel, wmatom[WMDelete])) {
|
|
||||||
+
|
|
||||||
+ if (!sendevent(selmon->sel->win, wmatom[WMDelete], NoEventMask, wmatom[WMDelete], CurrentTime, 0 , 0, 0)) {
|
|
||||||
XGrabServer(dpy);
|
|
||||||
XSetErrorHandler(xerrordummy);
|
|
||||||
XSetCloseDownMode(dpy, DestroyAll);
|
|
||||||
@@ -1105,6 +1224,13 @@ maprequest(XEvent *e)
|
|
||||||
static XWindowAttributes wa;
|
|
||||||
XMapRequestEvent *ev = &e->xmaprequest;
|
|
||||||
|
|
||||||
+ Client *i;
|
|
||||||
+ if ((i = wintosystrayicon(ev->window))) {
|
|
||||||
+ sendevent(i->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_WINDOW_ACTIVATE, 0, systray->win, XEMBED_EMBEDDED_VERSION);
|
|
||||||
+ resizebarwin(selmon);
|
|
||||||
+ updatesystray();
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
if (!XGetWindowAttributes(dpy, ev->window, &wa) || wa.override_redirect)
|
|
||||||
return;
|
|
||||||
if (!wintoclient(ev->window))
|
|
||||||
@@ -1226,6 +1352,17 @@ propertynotify(XEvent *e)
|
|
||||||
Window trans;
|
|
||||||
XPropertyEvent *ev = &e->xproperty;
|
|
||||||
|
|
||||||
+ if ((c = wintosystrayicon(ev->window))) {
|
|
||||||
+ if (ev->atom == XA_WM_NORMAL_HINTS) {
|
|
||||||
+ updatesizehints(c);
|
|
||||||
+ updatesystrayicongeom(c, c->w, c->h);
|
|
||||||
+ }
|
|
||||||
+ else
|
|
||||||
+ updatesystrayiconstate(c, ev);
|
|
||||||
+ resizebarwin(selmon);
|
|
||||||
+ updatesystray();
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
if ((ev->window == root) && (ev->atom == XA_WM_NAME))
|
|
||||||
updatestatus();
|
|
||||||
else if (ev->state == PropertyDelete)
|
|
||||||
@@ -1276,6 +1413,19 @@ recttomon(int x, int y, int w, int h)
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
+void
|
|
||||||
+removesystrayicon(Client *i)
|
|
||||||
+{
|
|
||||||
+ Client **ii;
|
|
||||||
+
|
|
||||||
+ if (!showsystray || !i)
|
|
||||||
+ return;
|
|
||||||
+ for (ii = &systray->icons; *ii && *ii != i; ii = &(*ii)->next);
|
|
||||||
+ if (ii)
|
|
||||||
+ *ii = i->next;
|
|
||||||
+ free(i);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
void
|
|
||||||
resize(Client *c, int x, int y, int w, int h, int interact)
|
|
||||||
{
|
|
||||||
@@ -1283,6 +1433,14 @@ resize(Client *c, int x, int y, int w, int h, int interact)
|
|
||||||
resizeclient(c, x, y, w, h);
|
|
||||||
}
|
|
||||||
|
|
||||||
+void
|
|
||||||
+resizebarwin(Monitor *m) {
|
|
||||||
+ unsigned int w = m->ww;
|
|
||||||
+ if (showsystray && m == systraytomon(m) && !systrayonleft)
|
|
||||||
+ w -= getsystraywidth();
|
|
||||||
+ XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, w, bh);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
void
|
|
||||||
resizeclient(Client *c, int x, int y, int w, int h)
|
|
||||||
{
|
|
||||||
@@ -1298,6 +1456,19 @@ resizeclient(Client *c, int x, int y, int w, int h)
|
|
||||||
XSync(dpy, False);
|
|
||||||
}
|
|
||||||
|
|
||||||
+void
|
|
||||||
+resizerequest(XEvent *e)
|
|
||||||
+{
|
|
||||||
+ XResizeRequestEvent *ev = &e->xresizerequest;
|
|
||||||
+ Client *i;
|
|
||||||
+
|
|
||||||
+ if ((i = wintosystrayicon(ev->window))) {
|
|
||||||
+ updatesystrayicongeom(i, ev->width, ev->height);
|
|
||||||
+ resizebarwin(selmon);
|
|
||||||
+ updatesystray();
|
|
||||||
+ }
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
void
|
|
||||||
resizemouse(const Arg *arg)
|
|
||||||
{
|
|
||||||
@@ -1444,26 +1615,37 @@ setclientstate(Client *c, long state)
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
-sendevent(Client *c, Atom proto)
|
|
||||||
+sendevent(Window w, Atom proto, int mask, long d0, long d1, long d2, long d3, long d4)
|
|
||||||
{
|
|
||||||
int n;
|
|
||||||
- Atom *protocols;
|
|
||||||
+ Atom *protocols, mt;
|
|
||||||
int exists = 0;
|
|
||||||
XEvent ev;
|
|
||||||
|
|
||||||
- if (XGetWMProtocols(dpy, c->win, &protocols, &n)) {
|
|
||||||
- while (!exists && n--)
|
|
||||||
- exists = protocols[n] == proto;
|
|
||||||
- XFree(protocols);
|
|
||||||
+ if (proto == wmatom[WMTakeFocus] || proto == wmatom[WMDelete]) {
|
|
||||||
+ mt = wmatom[WMProtocols];
|
|
||||||
+ if (XGetWMProtocols(dpy, w, &protocols, &n)) {
|
|
||||||
+ while (!exists && n--)
|
|
||||||
+ exists = protocols[n] == proto;
|
|
||||||
+ XFree(protocols);
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ else {
|
|
||||||
+ exists = True;
|
|
||||||
+ mt = proto;
|
|
||||||
}
|
|
||||||
+
|
|
||||||
if (exists) {
|
|
||||||
ev.type = ClientMessage;
|
|
||||||
- ev.xclient.window = c->win;
|
|
||||||
- ev.xclient.message_type = wmatom[WMProtocols];
|
|
||||||
+ ev.xclient.window = w;
|
|
||||||
+ ev.xclient.message_type = mt;
|
|
||||||
ev.xclient.format = 32;
|
|
||||||
- ev.xclient.data.l[0] = proto;
|
|
||||||
- ev.xclient.data.l[1] = CurrentTime;
|
|
||||||
- XSendEvent(dpy, c->win, False, NoEventMask, &ev);
|
|
||||||
+ ev.xclient.data.l[0] = d0;
|
|
||||||
+ ev.xclient.data.l[1] = d1;
|
|
||||||
+ ev.xclient.data.l[2] = d2;
|
|
||||||
+ ev.xclient.data.l[3] = d3;
|
|
||||||
+ ev.xclient.data.l[4] = d4;
|
|
||||||
+ XSendEvent(dpy, w, False, mask, &ev);
|
|
||||||
}
|
|
||||||
return exists;
|
|
||||||
}
|
|
||||||
@@ -1477,7 +1659,7 @@ setfocus(Client *c)
|
|
||||||
XA_WINDOW, 32, PropModeReplace,
|
|
||||||
(unsigned char *) &(c->win), 1);
|
|
||||||
}
|
|
||||||
- sendevent(c, wmatom[WMTakeFocus]);
|
|
||||||
+ sendevent(c->win, wmatom[WMTakeFocus], NoEventMask, wmatom[WMTakeFocus], CurrentTime, 0, 0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
@@ -1566,6 +1748,10 @@ setup(void)
|
|
||||||
wmatom[WMTakeFocus] = XInternAtom(dpy, "WM_TAKE_FOCUS", False);
|
|
||||||
netatom[NetActiveWindow] = XInternAtom(dpy, "_NET_ACTIVE_WINDOW", False);
|
|
||||||
netatom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False);
|
|
||||||
+ netatom[NetSystemTray] = XInternAtom(dpy, "_NET_SYSTEM_TRAY_S0", False);
|
|
||||||
+ netatom[NetSystemTrayOP] = XInternAtom(dpy, "_NET_SYSTEM_TRAY_OPCODE", False);
|
|
||||||
+ netatom[NetSystemTrayOrientation] = XInternAtom(dpy, "_NET_SYSTEM_TRAY_ORIENTATION", False);
|
|
||||||
+ netatom[NetSystemTrayOrientationHorz] = XInternAtom(dpy, "_NET_SYSTEM_TRAY_ORIENTATION_HORZ", False);
|
|
||||||
netatom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False);
|
|
||||||
netatom[NetWMState] = XInternAtom(dpy, "_NET_WM_STATE", False);
|
|
||||||
netatom[NetWMCheck] = XInternAtom(dpy, "_NET_SUPPORTING_WM_CHECK", False);
|
|
||||||
@@ -1573,6 +1759,9 @@ setup(void)
|
|
||||||
netatom[NetWMWindowType] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE", False);
|
|
||||||
netatom[NetWMWindowTypeDialog] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DIALOG", False);
|
|
||||||
netatom[NetClientList] = XInternAtom(dpy, "_NET_CLIENT_LIST", False);
|
|
||||||
+ xatom[Manager] = XInternAtom(dpy, "MANAGER", False);
|
|
||||||
+ xatom[Xembed] = XInternAtom(dpy, "_XEMBED", False);
|
|
||||||
+ xatom[XembedInfo] = XInternAtom(dpy, "_XEMBED_INFO", False);
|
|
||||||
/* init cursors */
|
|
||||||
cursor[CurNormal] = drw_cur_create(drw, XC_left_ptr);
|
|
||||||
cursor[CurResize] = drw_cur_create(drw, XC_sizing);
|
|
||||||
@@ -1581,6 +1770,8 @@ setup(void)
|
|
||||||
scheme = ecalloc(LENGTH(colors), sizeof(Clr *));
|
|
||||||
for (i = 0; i < LENGTH(colors); i++)
|
|
||||||
scheme[i] = drw_scm_create(drw, colors[i], 3);
|
|
||||||
+ /* init system tray */
|
|
||||||
+ updatesystray();
|
|
||||||
/* init bars */
|
|
||||||
updatebars();
|
|
||||||
updatestatus();
|
|
||||||
@@ -1711,7 +1902,18 @@ togglebar(const Arg *arg)
|
|
||||||
{
|
|
||||||
selmon->showbar = !selmon->showbar;
|
|
||||||
updatebarpos(selmon);
|
|
||||||
- XMoveResizeWindow(dpy, selmon->barwin, selmon->wx, selmon->by, selmon->ww, bh);
|
|
||||||
+ resizebarwin(selmon);
|
|
||||||
+ if (showsystray) {
|
|
||||||
+ XWindowChanges wc;
|
|
||||||
+ if (!selmon->showbar)
|
|
||||||
+ wc.y = -bh;
|
|
||||||
+ else if (selmon->showbar) {
|
|
||||||
+ wc.y = 0;
|
|
||||||
+ if (!selmon->topbar)
|
|
||||||
+ wc.y = selmon->mh - bh;
|
|
||||||
+ }
|
|
||||||
+ XConfigureWindow(dpy, systray->win, CWY, &wc);
|
|
||||||
+ }
|
|
||||||
arrange(selmon);
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1807,11 +2009,18 @@ unmapnotify(XEvent *e)
|
|
||||||
else
|
|
||||||
unmanage(c, 0);
|
|
||||||
}
|
|
||||||
+ else if ((c = wintosystrayicon(ev->window))) {
|
|
||||||
+ /* KLUDGE! sometimes icons occasionally unmap their windows, but do
|
|
||||||
+ * _not_ destroy them. We map those windows back */
|
|
||||||
+ XMapRaised(dpy, c->win);
|
|
||||||
+ updatesystray();
|
|
||||||
+ }
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
updatebars(void)
|
|
||||||
{
|
|
||||||
+ unsigned int w;
|
|
||||||
Monitor *m;
|
|
||||||
XSetWindowAttributes wa = {
|
|
||||||
.override_redirect = True,
|
|
||||||
@@ -1822,10 +2031,15 @@ updatebars(void)
|
|
||||||
for (m = mons; m; m = m->next) {
|
|
||||||
if (m->barwin)
|
|
||||||
continue;
|
|
||||||
- m->barwin = XCreateWindow(dpy, root, m->wx, m->by, m->ww, bh, 0, DefaultDepth(dpy, screen),
|
|
||||||
+ w = m->ww;
|
|
||||||
+ if (showsystray && m == systraytomon(m))
|
|
||||||
+ w -= getsystraywidth();
|
|
||||||
+ m->barwin = XCreateWindow(dpy, root, m->wx, m->by, w, bh, 0, DefaultDepth(dpy, screen),
|
|
||||||
CopyFromParent, DefaultVisual(dpy, screen),
|
|
||||||
CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa);
|
|
||||||
XDefineCursor(dpy, m->barwin, cursor[CurNormal]->cursor);
|
|
||||||
+ if (showsystray && m == systraytomon(m))
|
|
||||||
+ XMapRaised(dpy, systray->win);
|
|
||||||
XMapRaised(dpy, m->barwin);
|
|
||||||
XSetClassHint(dpy, m->barwin, &ch);
|
|
||||||
}
|
|
||||||
@@ -2002,6 +2216,125 @@ updatestatus(void)
|
|
||||||
if (!gettextprop(root, XA_WM_NAME, stext, sizeof(stext)))
|
|
||||||
strcpy(stext, "dwm-"VERSION);
|
|
||||||
drawbar(selmon);
|
|
||||||
+ updatesystray();
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+void
|
|
||||||
+updatesystrayicongeom(Client *i, int w, int h)
|
|
||||||
+{
|
|
||||||
+ if (i) {
|
|
||||||
+ i->h = bh;
|
|
||||||
+ if (w == h)
|
|
||||||
+ i->w = bh;
|
|
||||||
+ else if (h == bh)
|
|
||||||
+ i->w = w;
|
|
||||||
+ else
|
|
||||||
+ i->w = (int) ((float)bh * ((float)w / (float)h));
|
|
||||||
+ applysizehints(i, &(i->x), &(i->y), &(i->w), &(i->h), False);
|
|
||||||
+ /* force icons into the systray dimensions if they don't want to */
|
|
||||||
+ if (i->h > bh) {
|
|
||||||
+ if (i->w == i->h)
|
|
||||||
+ i->w = bh;
|
|
||||||
+ else
|
|
||||||
+ i->w = (int) ((float)bh * ((float)i->w / (float)i->h));
|
|
||||||
+ i->h = bh;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+void
|
|
||||||
+updatesystrayiconstate(Client *i, XPropertyEvent *ev)
|
|
||||||
+{
|
|
||||||
+ long flags;
|
|
||||||
+ int code = 0;
|
|
||||||
+
|
|
||||||
+ if (!showsystray || !i || ev->atom != xatom[XembedInfo] ||
|
|
||||||
+ !(flags = getatomprop(i, xatom[XembedInfo])))
|
|
||||||
+ return;
|
|
||||||
+
|
|
||||||
+ if (flags & XEMBED_MAPPED && !i->tags) {
|
|
||||||
+ i->tags = 1;
|
|
||||||
+ code = XEMBED_WINDOW_ACTIVATE;
|
|
||||||
+ XMapRaised(dpy, i->win);
|
|
||||||
+ setclientstate(i, NormalState);
|
|
||||||
+ }
|
|
||||||
+ else if (!(flags & XEMBED_MAPPED) && i->tags) {
|
|
||||||
+ i->tags = 0;
|
|
||||||
+ code = XEMBED_WINDOW_DEACTIVATE;
|
|
||||||
+ XUnmapWindow(dpy, i->win);
|
|
||||||
+ setclientstate(i, WithdrawnState);
|
|
||||||
+ }
|
|
||||||
+ else
|
|
||||||
+ return;
|
|
||||||
+ sendevent(i->win, xatom[Xembed], StructureNotifyMask, CurrentTime, code, 0,
|
|
||||||
+ systray->win, XEMBED_EMBEDDED_VERSION);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+void
|
|
||||||
+updatesystray(void)
|
|
||||||
+{
|
|
||||||
+ XSetWindowAttributes wa;
|
|
||||||
+ XWindowChanges wc;
|
|
||||||
+ Client *i;
|
|
||||||
+ Monitor *m = systraytomon(NULL);
|
|
||||||
+ unsigned int x = m->mx + m->mw;
|
|
||||||
+ unsigned int sw = TEXTW(stext) - lrpad + systrayspacing;
|
|
||||||
+ unsigned int w = 1;
|
|
||||||
+
|
|
||||||
+ if (!showsystray)
|
|
||||||
+ return;
|
|
||||||
+ if (systrayonleft)
|
|
||||||
+ x -= sw + lrpad / 2;
|
|
||||||
+ if (!systray) {
|
|
||||||
+ /* init systray */
|
|
||||||
+ if (!(systray = (Systray *)calloc(1, sizeof(Systray))))
|
|
||||||
+ die("fatal: could not malloc() %u bytes\n", sizeof(Systray));
|
|
||||||
+ systray->win = XCreateSimpleWindow(dpy, root, x, m->by, w, bh, 0, 0, scheme[SchemeSel][ColBg].pixel);
|
|
||||||
+ wa.event_mask = ButtonPressMask | ExposureMask;
|
|
||||||
+ wa.override_redirect = True;
|
|
||||||
+ wa.background_pixel = scheme[SchemeNorm][ColBg].pixel;
|
|
||||||
+ XSelectInput(dpy, systray->win, SubstructureNotifyMask);
|
|
||||||
+ XChangeProperty(dpy, systray->win, netatom[NetSystemTrayOrientation], XA_CARDINAL, 32,
|
|
||||||
+ PropModeReplace, (unsigned char *)&netatom[NetSystemTrayOrientationHorz], 1);
|
|
||||||
+ XChangeWindowAttributes(dpy, systray->win, CWEventMask|CWOverrideRedirect|CWBackPixel, &wa);
|
|
||||||
+ XMapRaised(dpy, systray->win);
|
|
||||||
+ XSetSelectionOwner(dpy, netatom[NetSystemTray], systray->win, CurrentTime);
|
|
||||||
+ if (XGetSelectionOwner(dpy, netatom[NetSystemTray]) == systray->win) {
|
|
||||||
+ sendevent(root, xatom[Manager], StructureNotifyMask, CurrentTime, netatom[NetSystemTray], systray->win, 0, 0);
|
|
||||||
+ XSync(dpy, False);
|
|
||||||
+ }
|
|
||||||
+ else {
|
|
||||||
+ fprintf(stderr, "dwm: unable to obtain system tray.\n");
|
|
||||||
+ free(systray);
|
|
||||||
+ systray = NULL;
|
|
||||||
+ return;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ for (w = 0, i = systray->icons; i; i = i->next) {
|
|
||||||
+ /* make sure the background color stays the same */
|
|
||||||
+ wa.background_pixel = scheme[SchemeNorm][ColBg].pixel;
|
|
||||||
+ XChangeWindowAttributes(dpy, i->win, CWBackPixel, &wa);
|
|
||||||
+ XMapRaised(dpy, i->win);
|
|
||||||
+ w += systrayspacing;
|
|
||||||
+ i->x = w;
|
|
||||||
+ XMoveResizeWindow(dpy, i->win, i->x, 0, i->w, i->h);
|
|
||||||
+ w += i->w;
|
|
||||||
+ if (i->mon != m)
|
|
||||||
+ i->mon = m;
|
|
||||||
+ }
|
|
||||||
+ w = w ? w + systrayspacing : 1;
|
|
||||||
+ x -= w;
|
|
||||||
+ XMoveResizeWindow(dpy, systray->win, x, m->by, w, bh);
|
|
||||||
+ wc.x = x; wc.y = m->by; wc.width = w; wc.height = bh;
|
|
||||||
+ wc.stack_mode = Above; wc.sibling = m->barwin;
|
|
||||||
+ XConfigureWindow(dpy, systray->win, CWX|CWY|CWWidth|CWHeight|CWSibling|CWStackMode, &wc);
|
|
||||||
+ XMapWindow(dpy, systray->win);
|
|
||||||
+ XMapSubwindows(dpy, systray->win);
|
|
||||||
+ /* redraw background */
|
|
||||||
+ XSetForeground(dpy, drw->gc, scheme[SchemeNorm][ColBg].pixel);
|
|
||||||
+ XFillRectangle(dpy, systray->win, drw->gc, 0, 0, w, bh);
|
|
||||||
+ XSync(dpy, False);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
@@ -2069,6 +2402,16 @@ wintoclient(Window w)
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
+Client *
|
|
||||||
+wintosystrayicon(Window w) {
|
|
||||||
+ Client *i = NULL;
|
|
||||||
+
|
|
||||||
+ if (!showsystray || !w)
|
|
||||||
+ return i;
|
|
||||||
+ for (i = systray->icons; i && i->win != w; i = i->next) ;
|
|
||||||
+ return i;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
Monitor *
|
|
||||||
wintomon(Window w)
|
|
||||||
{
|
|
||||||
@@ -2122,6 +2465,22 @@ xerrorstart(Display *dpy, XErrorEvent *ee)
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
+Monitor *
|
|
||||||
+systraytomon(Monitor *m) {
|
|
||||||
+ Monitor *t;
|
|
||||||
+ int i, n;
|
|
||||||
+ if(!systraypinning) {
|
|
||||||
+ if(!m)
|
|
||||||
+ return selmon;
|
|
||||||
+ return m == selmon ? m : NULL;
|
|
||||||
+ }
|
|
||||||
+ for(n = 1, t = mons; t && t->next; n++, t = t->next) ;
|
|
||||||
+ for(i = 1, t = mons; t && t->next && i < systraypinning; i++, t = t->next) ;
|
|
||||||
+ if(systraypinningfailfirst && n < systraypinning)
|
|
||||||
+ return mons;
|
|
||||||
+ return t;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
void
|
|
||||||
zoom(const Arg *arg)
|
|
||||||
{
|
|
3
todo
3
todo
|
@ -1,3 +0,0 @@
|
||||||
# TODO: consider adding the compiler flags of -O3 and -march=native to enable auto loop vectorize for better performance.
|
|
||||||
# TODO: Picom rule: shadow-exclude = [ "! _IS_FLOATING@:32c = 1" ];
|
|
||||||
# TODO: Rewrite sb-scripts with pango markup
|
|
42
transient.c
42
transient.c
|
@ -1,42 +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);
|
|
||||||
}
|
|
36
util.c
36
util.c
|
@ -1,36 +0,0 @@
|
||||||
/* See LICENSE file for copyright and license details. */
|
|
||||||
#include <stdarg.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "util.h"
|
|
||||||
|
|
||||||
void
|
|
||||||
die(const char *fmt, ...)
|
|
||||||
{
|
|
||||||
va_list ap;
|
|
||||||
|
|
||||||
va_start(ap, fmt);
|
|
||||||
vfprintf(stderr, fmt, ap);
|
|
||||||
va_end(ap);
|
|
||||||
|
|
||||||
if (fmt[0] && fmt[strlen(fmt)-1] == ':') {
|
|
||||||
fputc(' ', stderr);
|
|
||||||
perror(NULL);
|
|
||||||
} else {
|
|
||||||
fputc('\n', stderr);
|
|
||||||
}
|
|
||||||
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void *
|
|
||||||
ecalloc(size_t nmemb, size_t size)
|
|
||||||
{
|
|
||||||
void *p;
|
|
||||||
|
|
||||||
if (!(p = calloc(nmemb, size)))
|
|
||||||
die("calloc:");
|
|
||||||
return p;
|
|
||||||
}
|
|
8
util.h
8
util.h
|
@ -1,8 +0,0 @@
|
||||||
/* See LICENSE file for copyright and license details. */
|
|
||||||
|
|
||||||
#define MAX(A, B) ((A) > (B) ? (A) : (B))
|
|
||||||
#define MIN(A, B) ((A) < (B) ? (A) : (B))
|
|
||||||
#define BETWEEN(X, A, B) ((A) <= (X) && (X) <= (B))
|
|
||||||
|
|
||||||
void die(const char *fmt, ...);
|
|
||||||
void *ecalloc(size_t nmemb, size_t size);
|
|
Loading…
Reference in New Issue