diff --git a/.bashrc b/.bashrc index 936bb53..55b554b 100644 --- a/.bashrc +++ b/.bashrc @@ -6,6 +6,7 @@ # # My bash config. Not much to see here. Some pretty standard stuff. +PATH="$HOME/.local/bin${PATH:+:${PATH}}" EDITOR="emacsclient -c" export TERM="xterm-256color" diff --git a/.config/qtile/config.py b/.config/qtile/config.py index eac673d..f3b1eda 100644 --- a/.config/qtile/config.py +++ b/.config/qtile/config.py @@ -339,8 +339,7 @@ def init_widgets_list(): foreground = colors[2], background = colors[0] ), - widget.WindowName(font="Ubuntu", - fontsize = 11, + widget.WindowName( foreground = colors[4], background = colors[0], padding = 5 @@ -353,7 +352,6 @@ def init_widgets_list(): fontsize=37 ), widget.TextBox( - font="Ubuntu Bold", text=" ⟳", padding = 5, foreground=colors[2], @@ -419,7 +417,6 @@ def init_widgets_list(): fontsize=37 ), widget.TextBox( - font="Ubuntu Bold", text=" ♫", padding = 5, foreground=colors[2], @@ -460,7 +457,6 @@ def init_widgets_list(): fontsize=37 ), widget.TextBox( - font="Ubuntu Bold", text=" ☵", padding = 5, foreground=colors[2], @@ -480,7 +476,6 @@ def init_widgets_list(): fontsize=37 ), widget.TextBox( - font="Ubuntu Bold", text=" 🕒", foreground=colors[2], background=colors[4], diff --git a/.dwm/autostart.sh b/.dwm/autostart.sh index 2304144..afc4ed4 100755 --- a/.dwm/autostart.sh +++ b/.dwm/autostart.sh @@ -1,45 +1,4 @@ #! /bin/bash -compton --config ~/.config/compton/compton.conf & +compton & nitrogen --restore & -urxvtd -q -o -f & - -dte(){ - dte="$(date +"%A, %B %d %l:%M%p")" - echo -e "🕒 $dte" -} - -hdd() { - hdd="$(df -h | awk 'NR==4{print $3, $5}')" - echo -e "💿 $hdd" -} - -mem(){ - mem=`free | awk '/Mem/ {printf "%d MiB/%d MiB\n", $3 / 1024.0, $2 / 1024.0 }'` - echo -e "🖪 $mem" -} - -cpu(){ - read cpu a b c previdle rest < /proc/stat - prevtotal=$((a+b+c+previdle)) - sleep 0.5 - read cpu a b c idle rest < /proc/stat - total=$((a+b+c+idle)) - cpu=$((100*( (total-prevtotal) - (idle-previdle) ) / (total-prevtotal) )) - echo -e "💻 $cpu% cpu" -} - -pulse () { - volume=$(pactl list sinks | grep '^[[:space:]]Volume:' | head -n $(( $SINK + 1 )) | tail -n 1 | sed -e 's,.* \([0-9][0-9]*\)%.*,\1,') - status=$(pacmd list-sinks | awk '/muted/ { print $2 }') - - if [ "$status" = "yes" ]; then - echo -e "🔈 muted" - else - echo -e "🔈 $volume%" - fi -} - -while true; do - xsetroot -name "$(cpu) | $(mem) | $(hdd) | $(pulse) | $(dte)" - sleep 1s # Update time every one second(s) -done & +dwmblocks & diff --git a/.local/bin/clock b/.local/bin/clock new file mode 100755 index 0000000..44ee7a4 --- /dev/null +++ b/.local/bin/clock @@ -0,0 +1,4 @@ +#! /bin/bash + +dte="$(date +"%a, %B %d %l:%M%p"| sed 's/ / /g')" +echo -e "$dte" diff --git a/.local/bin/kernel b/.local/bin/kernel new file mode 100755 index 0000000..605621d --- /dev/null +++ b/.local/bin/kernel @@ -0,0 +1,4 @@ +#! /bin/bash + +kern="$(uname -r)" +echo -e "$kern " diff --git a/.local/bin/memory b/.local/bin/memory new file mode 100755 index 0000000..6cda383 --- /dev/null +++ b/.local/bin/memory @@ -0,0 +1,4 @@ +#! /bin/bash + +mem="$(free -h | awk '/^Mem:/ {print $3 "/" $2}')" +echo -e "$mem ram " diff --git a/.local/bin/pacupdate b/.local/bin/pacupdate new file mode 100755 index 0000000..559ae49 --- /dev/null +++ b/.local/bin/pacupdate @@ -0,0 +1,4 @@ +#!/bin/bash + +cupd=$(checkupdates | wc -l) +printf "$cupd udpates \n" diff --git a/.local/bin/upt b/.local/bin/upt new file mode 100755 index 0000000..8bcb1ed --- /dev/null +++ b/.local/bin/upt @@ -0,0 +1,4 @@ +#! /bin/bash + +upt="$(uptime --pretty | sed -e 's/up //g' -e 's/ hours/h/g' -e 's/ hour/h/g' -e 's/ minutes/m/g' -e 's/, //g')" +echo -e "$upt uptime " diff --git a/.local/bin/volume b/.local/bin/volume new file mode 100755 index 0000000..d3bca2f --- /dev/null +++ b/.local/bin/volume @@ -0,0 +1,4 @@ +#!/bin/bash + +vol="$(amixer get Master | tail -n1 | sed -r 's/.*\[(.*)%\].*/\1/')" +echo "${vol}% " diff --git a/.surf/styles/suckless.css b/.surf/styles/suckless.css index 3d41c35..4b41535 100644 --- a/.surf/styles/suckless.css +++ b/.surf/styles/suckless.css @@ -1,32 +1,41 @@ body { - background-color: #292d3e !important; - color: #eee !important; + font-size: 13px; + background-color: #282a36 !important; + color: #d0d0d0 !important; } #header { - - background-color: #292d3e !important; + background-color: #282a36 !important; clear: both; - color: #BD93F9 !important; - + color: #c3e88d !important; } + +a { + color: #82aaff !important; +} + +#header a { + color: #e1acff !important; +} + #menu { - clear: both; - color: #069; + clear: both; + color: #c792ea; + font-weight: bold; overflow: hidden; - background-color: #17a; padding: 0.7ex; border: 0px !important; } -a { - color: #BD93F9 !important; -} - -#header a { - color: #BD93F9 !important; -} - #menu a { - color: #F8F8F2 !important; + color: #d0d0d0 !important; } + +#nav li a:hover { + background-color: #282a36 !important; +} + +h1, h2 { + color: #f07178 !important; +} + diff --git a/dwm/LICENSE b/dwm/LICENSE deleted file mode 100755 index d221f09..0000000 --- a/dwm/LICENSE +++ /dev/null @@ -1,37 +0,0 @@ -MIT/X Consortium License - -© 2006-2019 Anselm R Garbe -© 2006-2009 Jukka Salmi -© 2006-2007 Sander van Dijk -© 2007-2011 Peter Hartlich -© 2007-2009 Szabolcs Nagy -© 2007-2009 Christof Musik -© 2007-2009 Premysl Hruby -© 2007-2008 Enno Gottox Boland -© 2008 Martin Hurton -© 2008 Neale Pickett -© 2009 Mate Nagy -© 2010-2016 Hiltjo Posthuma -© 2010-2012 Connor Lane Smith -© 2011 Christoph Lohmann <20h@r-36.net> -© 2015-2016 Quentin Rameau -© 2015-2016 Eric Pruitt -© 2016-2017 Markus Teich - -Permission is hereby granted, free of charge, to any person obtaining a -copy of this software and associated documentation files (the "Software"), -to deal in the Software without restriction, including without limitation -the rights to use, copy, modify, merge, publish, distribute, sublicense, -and/or sell copies of the Software, and to permit persons to whom the -Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. diff --git a/dwm/Makefile b/dwm/Makefile deleted file mode 100755 index 77bcbc0..0000000 --- a/dwm/Makefile +++ /dev/null @@ -1,51 +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\ - dwm.1 drw.h util.h ${SRC} dwm.png transient.c dwm-${VERSION} - tar -cf dwm-${VERSION}.tar dwm-${VERSION} - gzip dwm-${VERSION}.tar - rm -rf dwm-${VERSION} - -install: all - mkdir -p ${DESTDIR}${PREFIX}/bin - cp -f dwm ${DESTDIR}${PREFIX}/bin - chmod 755 ${DESTDIR}${PREFIX}/bin/dwm - mkdir -p ${DESTDIR}${MANPREFIX}/man1 - sed "s/VERSION/${VERSION}/g" < dwm.1 > ${DESTDIR}${MANPREFIX}/man1/dwm.1 - chmod 644 ${DESTDIR}${MANPREFIX}/man1/dwm.1 - -uninstall: - rm -f ${DESTDIR}${PREFIX}/bin/dwm\ - ${DESTDIR}${MANPREFIX}/man1/dwm.1 - -.PHONY: all options clean dist install uninstall diff --git a/dwm/README.md b/dwm/README.md deleted file mode 100755 index 083dc3d..0000000 --- a/dwm/README.md +++ /dev/null @@ -1,61 +0,0 @@ -# My dwm (Dynamic Window Manager) build - -![Screenshot of my desktop](https://gitlab.com/dwt1/dotfiles/raw/master/.screenshots/dotfiles04.png) -Dwm is an extremely fast, small, and dynamic window manager for X. This is my personal build of dwm. I used a number of patches in this build to make dwm more "sensible" rather than "suckless." - -# My Keybindings - -The MODKEY is set to the Super key (aka the Windows key). I try to keep the -keybindings consistent with all of my window managers. - -| Keybinding | Action | -| :--- | :--- | -| `MODKEY + RETURN` | opens terminal (alacritty is the terminal but can be easily changed) | -| `MODKEY + SHIFT + RETURN` | opens run launcher (dmenu is the run launcher but can be easily changed) | -| `MODKEY + SHIFT + c` | closes window with focus | -| `MODKEY + SHIFT + r` | restarts dwm | -| `MODKEY + SHIFT + q` | quits dwm | -| `MODKEY + 1-9` | switch focus to workspace (1-9) | -| `MODKEY + SHIFT + 1-9` | send focused window to workspace (1-9) | -| `MODKEY + j` | focus stack +1 (switches focus between windows in the stack) | -| `MODKEY + k` | focus stack -1 (switches focus between windows in the stack) | -| `MODKEY + SHIFT + j` | rotate stack +1 (rotates the windows in the stack) | -| `MODKEY + SHIFT + k` | rotate stack -1 (rotates the windows in the stack) | -| `MODKEY + h` | setmfact -0.05 (expands size of window) | -| `MODKEY + l` | setmfact +0.05 (shrinks size of window) | -| `MODKEY + .` | focusmon +1 (switches focus next monitors) | -| `MODKEY + ,` | focusmon -1 (switches focus to prev monitors) | - -Afterwards enter the following command to build and install dwm (if -necessary as root): - - make clean install - - -# Running dwm - -Add the following line to your .xinitrc to start dwm using startx: - - exec dwm - -In order to connect dwm to a specific display, make sure that -the DISPLAY environment variable is set correctly, e.g.: - - DISPLAY=foo.bar:1 exec dwm - -(This will start dwm on display :1 of the host foo.bar.) - -In order to display status info in the bar, you can do something -like this in your .xinitrc: - - while xsetroot -name "`date` `uptime | sed 's/.*,//'`" - do - sleep 1 - done & - exec dwm - - -# Configuration - -The configuration of dwm is done by creating a custom config.h -and (re)compiling the source code. diff --git a/dwm/config.def.h b/dwm/config.def.h deleted file mode 100755 index 704979f..0000000 --- a/dwm/config.def.h +++ /dev/null @@ -1,132 +0,0 @@ -/* See LICENSE file for copyright and license details. */ - -/* appearance */ -static const unsigned int borderpx = 1; /* border pixel of windows */ -static const unsigned int snap = 32; /* snap pixel */ -static const int showbar = 1; /* 0 means no bar */ -static const int topbar = 1; /* 0 means bottom bar */ -static const int horizpadbar = 4; /* horizontal padding for statusbar */ -static const int vertpadbar = 2; /* vertical padding for statusbar */ -static const char *fonts[] = { "monospace:size=10" }; -static const char dmenufont[] = "monospace:size=10"; -static const char col_gray1[] = "#222222"; -static const char col_gray2[] = "#444444"; -static const char col_gray3[] = "#bbbbbb"; -static const char col_gray4[] = "#eeeeee"; -static const char col_cyan[] = "#005577"; -static const unsigned int baralpha = 0xd0; -static const unsigned int borderalpha = OPAQUE; -static const char *colors[][3] = { - /* fg bg border */ - [SchemeNorm] = { col_gray3, col_gray1, col_gray2 }, - [SchemeSel] = { col_gray4, col_cyan, col_cyan }, -}; -static const unsigned int alphas[][3] = { - /* fg bg border */ - [SchemeNorm] = { OPAQUE, baralpha, borderalpha }, - [SchemeSel] = { OPAQUE, baralpha, borderalpha }, -}; - -/* 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 - */ - /* class instance title tags mask isfloating monitor */ - { "Gimp", NULL, NULL, 0, 1, -1 }, - { "Firefox", NULL, NULL, 1 << 8, 0, -1 }, -}; - -/* layout(s) */ -static const float mfact = 0.55; /* factor of master area size [0.05..0.95] */ -static const int nmaster = 1; /* number of clients in master area */ -static const int resizehints = 1; /* 1 means respect size hints in tiled resizals */ - -static const Layout layouts[] = { - /* symbol arrange function */ - { "[]=", tile }, /* first entry is default */ - { "><>", NULL }, /* no layout function means floating behavior */ - { "[M]", monocle }, - { NULL, NULL }, -}; - -/* key definitions */ -#define MODKEY Mod1Mask -#define TAGKEYS(KEY,TAG) \ - { MODKEY, KEY, view, {.ui = 1 << TAG} }, \ - { MODKEY|ControlMask, KEY, toggleview, {.ui = 1 << TAG} }, \ - { MODKEY|ShiftMask, KEY, tag, {.ui = 1 << TAG} }, \ - { MODKEY|ControlMask|ShiftMask, KEY, toggletag, {.ui = 1 << TAG} }, - -/* helper for spawning shell commands in the pre dwm-5.0 fashion */ -#define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } } - -/* commands */ -static char dmenumon[2] = "0"; /* component of dmenucmd, manipulated in spawn() */ -static const char *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 }; - -#include "selfrestart.c" - -static Key keys[] = { - /* modifier key function argument */ - { MODKEY, XK_p, spawn, {.v = dmenucmd } }, - { MODKEY|ShiftMask, XK_Return, spawn, {.v = termcmd } }, - { MODKEY, XK_b, togglebar, {0} }, - { MODKEY|ShiftMask, XK_j, rotatestack, {.i = +1 } }, - { MODKEY|ShiftMask, XK_k, rotatestack, {.i = -1 } }, - { MODKEY, XK_j, focusstack, {.i = +1 } }, - { MODKEY, XK_k, focusstack, {.i = -1 } }, - { MODKEY, XK_i, incnmaster, {.i = +1 } }, - { MODKEY, XK_d, incnmaster, {.i = -1 } }, - { MODKEY, XK_h, setmfact, {.f = -0.05} }, - { MODKEY, XK_l, setmfact, {.f = +0.05} }, - { MODKEY, XK_Return, zoom, {0} }, - { MODKEY, XK_Tab, view, {0} }, - { MODKEY|ShiftMask, XK_c, killclient, {0} }, - { MODKEY, XK_t, setlayout, {.v = &layouts[0]} }, - { MODKEY, XK_f, setlayout, {.v = &layouts[1]} }, - { MODKEY, XK_m, setlayout, {.v = &layouts[2]} }, - { MODKEY|ControlMask, XK_comma, cyclelayout, {.i = -1 } }, - { MODKEY|ControlMask, XK_period, cyclelayout, {.i = +1 } }, - { MODKEY, XK_space, setlayout, {0} }, - { MODKEY|ShiftMask, XK_space, togglefloating, {0} }, - { MODKEY, XK_0, view, {.ui = ~0 } }, - { MODKEY|ShiftMask, XK_0, tag, {.ui = ~0 } }, - { MODKEY, XK_comma, focusmon, {.i = -1 } }, - { MODKEY, XK_period, focusmon, {.i = +1 } }, - { MODKEY|ShiftMask, XK_comma, tagmon, {.i = -1 } }, - { MODKEY|ShiftMask, XK_period, tagmon, {.i = +1 } }, - TAGKEYS( XK_1, 0) - TAGKEYS( XK_2, 1) - TAGKEYS( XK_3, 2) - TAGKEYS( XK_4, 3) - TAGKEYS( XK_5, 4) - TAGKEYS( XK_6, 5) - TAGKEYS( XK_7, 6) - TAGKEYS( XK_8, 7) - TAGKEYS( XK_9, 8) - { MODKEY|ShiftMask, XK_r, self_restart, {0} }, - { MODKEY|ShiftMask, XK_q, quit, {0} }, - { MODKEY|ControlMask|ShiftMask, XK_q, quit, {1} }, -}; - -/* button definitions */ -/* click can be ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, or ClkRootWin */ -static Button buttons[] = { - /* click event mask button function argument */ - { ClkLtSymbol, 0, Button1, setlayout, {0} }, - { ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]} }, - { ClkWinTitle, 0, Button2, zoom, {0} }, - { ClkStatusText, 0, Button2, spawn, {.v = termcmd } }, - { ClkClientWin, MODKEY, Button1, movemouse, {0} }, - { ClkClientWin, MODKEY, Button2, togglefloating, {0} }, - { ClkClientWin, MODKEY, Button3, resizemouse, {0} }, - { ClkTagBar, 0, Button1, view, {0} }, - { ClkTagBar, 0, Button3, toggleview, {0} }, - { ClkTagBar, MODKEY, Button1, tag, {0} }, - { ClkTagBar, MODKEY, Button3, toggletag, {0} }, -}; diff --git a/dwm/config.def.h.orig b/dwm/config.def.h.orig deleted file mode 100755 index 2d5f9e8..0000000 --- a/dwm/config.def.h.orig +++ /dev/null @@ -1,131 +0,0 @@ -/* See LICENSE file for copyright and license details. */ - -/* appearance */ -static const unsigned int borderpx = 1; /* border pixel of windows */ -static const unsigned int snap = 32; /* snap pixel */ -static const int showbar = 1; /* 0 means no bar */ -static const int topbar = 1; /* 0 means bottom bar */ -static const int horizpadbar = 4; /* horizontal padding for statusbar */ -static const int vertpadbar = 2; /* vertical padding for statusbar */ -static const char *fonts[] = { "monospace:size=10" }; -static const char dmenufont[] = "monospace:size=10"; -static const char col_gray1[] = "#222222"; -static const char col_gray2[] = "#444444"; -static const char col_gray3[] = "#bbbbbb"; -static const char col_gray4[] = "#eeeeee"; -static const char col_cyan[] = "#005577"; -static const unsigned int baralpha = 0xd0; -static const unsigned int borderalpha = OPAQUE; -static const char *colors[][3] = { - /* fg bg border */ - [SchemeNorm] = { col_gray3, col_gray1, col_gray2 }, - [SchemeSel] = { col_gray4, col_cyan, col_cyan }, -}; -static const unsigned int alphas[][3] = { - /* fg bg border */ - [SchemeNorm] = { OPAQUE, baralpha, borderalpha }, - [SchemeSel] = { OPAQUE, baralpha, borderalpha }, -}; - -/* 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 - */ - /* class instance title tags mask isfloating monitor */ - { "Gimp", NULL, NULL, 0, 1, -1 }, - { "Firefox", NULL, NULL, 1 << 8, 0, -1 }, -}; - -/* layout(s) */ -static const float mfact = 0.55; /* factor of master area size [0.05..0.95] */ -static const int nmaster = 1; /* number of clients in master area */ -static const int resizehints = 1; /* 1 means respect size hints in tiled resizals */ - -static const Layout layouts[] = { - /* symbol arrange function */ - { "[]=", tile }, /* first entry is default */ - { "><>", NULL }, /* no layout function means floating behavior */ - { "[M]", monocle }, - { NULL, NULL }, -}; - -/* key definitions */ -#define MODKEY Mod1Mask -#define TAGKEYS(KEY,TAG) \ - { MODKEY, KEY, view, {.ui = 1 << TAG} }, \ - { MODKEY|ControlMask, KEY, toggleview, {.ui = 1 << TAG} }, \ - { MODKEY|ShiftMask, KEY, tag, {.ui = 1 << TAG} }, \ - { MODKEY|ControlMask|ShiftMask, KEY, toggletag, {.ui = 1 << TAG} }, - -/* helper for spawning shell commands in the pre dwm-5.0 fashion */ -#define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } } - -/* commands */ -static char dmenumon[2] = "0"; /* component of dmenucmd, manipulated in spawn() */ -static const char *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 }; - -#include "selfrestart.c" - -static Key keys[] = { - /* modifier key function argument */ - { MODKEY, XK_p, spawn, {.v = dmenucmd } }, - { MODKEY|ShiftMask, XK_Return, spawn, {.v = termcmd } }, - { MODKEY, XK_b, togglebar, {0} }, - { MODKEY|ShiftMask, XK_j, rotatestack, {.i = +1 } }, - { MODKEY|ShiftMask, XK_k, rotatestack, {.i = -1 } }, - { MODKEY, XK_j, focusstack, {.i = +1 } }, - { MODKEY, XK_k, focusstack, {.i = -1 } }, - { MODKEY, XK_i, incnmaster, {.i = +1 } }, - { MODKEY, XK_d, incnmaster, {.i = -1 } }, - { MODKEY, XK_h, setmfact, {.f = -0.05} }, - { MODKEY, XK_l, setmfact, {.f = +0.05} }, - { MODKEY, XK_Return, zoom, {0} }, - { MODKEY, XK_Tab, view, {0} }, - { MODKEY|ShiftMask, XK_c, killclient, {0} }, - { MODKEY, XK_t, setlayout, {.v = &layouts[0]} }, - { MODKEY, XK_f, setlayout, {.v = &layouts[1]} }, - { MODKEY, XK_m, setlayout, {.v = &layouts[2]} }, - { MODKEY|ControlMask, XK_comma, cyclelayout, {.i = -1 } }, - { MODKEY|ControlMask, XK_period, cyclelayout, {.i = +1 } }, - { MODKEY, XK_space, setlayout, {0} }, - { MODKEY|ShiftMask, XK_space, togglefloating, {0} }, - { MODKEY, XK_0, view, {.ui = ~0 } }, - { MODKEY|ShiftMask, XK_0, tag, {.ui = ~0 } }, - { MODKEY, XK_comma, focusmon, {.i = -1 } }, - { MODKEY, XK_period, focusmon, {.i = +1 } }, - { MODKEY|ShiftMask, XK_comma, tagmon, {.i = -1 } }, - { MODKEY|ShiftMask, XK_period, tagmon, {.i = +1 } }, - TAGKEYS( XK_1, 0) - TAGKEYS( XK_2, 1) - TAGKEYS( XK_3, 2) - TAGKEYS( XK_4, 3) - TAGKEYS( XK_5, 4) - TAGKEYS( XK_6, 5) - TAGKEYS( XK_7, 6) - TAGKEYS( XK_8, 7) - TAGKEYS( XK_9, 8) - { MODKEY|ShiftMask, XK_r, self_restart, {0} }, - { MODKEY|ShiftMask, XK_q, quit, {0} }, -}; - -/* button definitions */ -/* click can be ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, or ClkRootWin */ -static Button buttons[] = { - /* click event mask button function argument */ - { ClkLtSymbol, 0, Button1, setlayout, {0} }, - { ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]} }, - { ClkWinTitle, 0, Button2, zoom, {0} }, - { ClkStatusText, 0, Button2, spawn, {.v = termcmd } }, - { ClkClientWin, MODKEY, Button1, movemouse, {0} }, - { ClkClientWin, MODKEY, Button2, togglefloating, {0} }, - { ClkClientWin, MODKEY, Button3, resizemouse, {0} }, - { ClkTagBar, 0, Button1, view, {0} }, - { ClkTagBar, 0, Button3, toggleview, {0} }, - { ClkTagBar, MODKEY, Button1, tag, {0} }, - { ClkTagBar, MODKEY, Button3, toggletag, {0} }, -}; diff --git a/dwm/config.def.h.rej b/dwm/config.def.h.rej deleted file mode 100755 index 881ca1c..0000000 --- a/dwm/config.def.h.rej +++ /dev/null @@ -1,19 +0,0 @@ ---- config.def.h -+++ config.def.h -@@ -41,6 +41,7 @@ static const Layout layouts[] = { - { "[]=", tile }, /* first entry is default */ - { "><>", NULL }, /* no layout function means floating behavior */ - { "[M]", monocle }, -+ { NULL, NULL }, - }; - - /* key definitions */ -@@ -76,6 +77,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|ControlMask, XK_comma, cyclelayout, {.i = -1 } }, -+ { MODKEY|ControlMask, XK_period, cyclelayout, {.i = +1 } }, - { MODKEY, XK_space, setlayout, {0} }, - { MODKEY|ShiftMask, XK_space, togglefloating, {0} }, - { MODKEY, XK_0, view, {.ui = ~0 } }, diff --git a/dwm/config.h b/dwm/config.h deleted file mode 100755 index c031cef..0000000 --- a/dwm/config.h +++ /dev/null @@ -1,165 +0,0 @@ -/* ____ _____ */ -/* | _ \_ _| Derek Taylor (DistroTube) */ -/* | | | || | http://www.youtube.com/c/DistroTube */ -/* | |_| || | http://www.gitlab.com/dwt1/ */ -/* |____/ |_| */ - -/* See LICENSE file for copyright and license details. */ -/* appearance */ -static const unsigned int borderpx = 2; /* border pixel of windows */ -static const unsigned int snap = 32; /* snap pixel */ -static const unsigned int gappx = 6; /* pixel gap between clients */ -static const int showbar = 1; /* 0 means no bar */ -static const int topbar = 1; /* 0 means bottom bar */ -static const int horizpadbar = 6; /* horizontal padding for statusbar */ -static const int vertpadbar = 7; /* vertical padding for statusbar */ -static const char *fonts[] = { "Mononoki Nerd Font:size=9" }; -static const char dmenufont[] = "Mononoki Nerd Font:size=9"; -static const char col_gray1[] = "#282a36"; -static const char col_gray2[] = "#282a36"; /* border color unfocused windows */ -static const char col_gray3[] = "#96b5b4"; -static const char col_gray4[] = "#d7d7d7"; -static const char col_cyan[] = "#924441"; /* border color focused windows and tags */ -static const unsigned int baralpha = 0xff; /* 0xee adds a wee bit transparency */ -static const unsigned int borderalpha = OPAQUE; -static const char *colors[][3] = { - /* fg bg border */ - [SchemeNorm] = { col_gray4, col_gray1, col_gray2 }, - [SchemeSel] = { col_gray4, col_cyan, col_cyan }, -}; -static const unsigned int alphas[][3] = { - /* fg bg border */ - [SchemeNorm] = { OPAQUE, baralpha, borderalpha }, - [SchemeSel] = { OPAQUE, baralpha, borderalpha }, -}; - -/* tagging */ -/* static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" }; */ -static const char *tags[] = { "", "", "", "", "", "", "", "", "" }; - - -static const Rule rules[] = { - /* xprop(1): - * 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 }, -}; - -/* 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 = 0; /* 1 means respect size hints in tiled resizals */ - -#include "layouts.c" -static const Layout layouts[] = { - /* symbol arrange function */ - { "[]=", tile }, /* first entry is default */ - { "><>", NULL }, /* no layout function means floating behavior */ - { "[M]", monocle }, - { "HHH", grid }, - { NULL, NULL }, -}; - -/* key definitions */ -#define MODKEY Mod4Mask -#define TAGKEYS(KEY,TAG) \ - { MODKEY, KEY, view, {.ui = 1 << TAG} }, \ - { MODKEY|ControlMask, KEY, toggleview, {.ui = 1 << TAG} }, \ - { MODKEY|ShiftMask, KEY, tag, {.ui = 1 << TAG} }, \ - { MODKEY|ControlMask|ShiftMask, KEY, toggletag, {.ui = 1 << TAG} }, -#define CMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } } - -/* helper for spawning shell commands in the pre dwm-5.0 fashion */ -#define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } } - -/* commands */ -static char dmenumon[2] = "0"; /* component of dmenucmd, manipulated in spawn() */ -static const char *dmenucmd[] = { "dmenu_run", "-m", dmenumon, "-fn", dmenufont, "-nb", col_gray1, "-nf", col_gray3, "-sb", col_cyan, "-sf", col_gray4, NULL }; -static const char *termcmd[] = { "alacritty", NULL }; - -static Key keys[] = { - /* modifier key function argument */ - { MODKEY|ShiftMask, XK_Return, spawn, {.v = dmenucmd } }, - { MODKEY, XK_Return, spawn, {.v = termcmd } }, - { MODKEY, XK_b, togglebar, {0} }, - { MODKEY|ShiftMask, XK_j, rotatestack, {.i = +1 } }, - { MODKEY|ShiftMask, XK_k, rotatestack, {.i = -1 } }, - { MODKEY, XK_j, focusstack, {.i = +1 } }, - { MODKEY, XK_k, focusstack, {.i = -1 } }, - { MODKEY, XK_i, incnmaster, {.i = +1 } }, - { MODKEY, XK_d, incnmaster, {.i = -1 } }, - { MODKEY, XK_h, setmfact, {.f = -0.05} }, - { MODKEY, XK_l, setmfact, {.f = +0.05} }, - { MODKEY|ControlMask, XK_Return, zoom, {0} }, - { MODKEY, XK_Tab, view, {0} }, - { MODKEY|ShiftMask, XK_c, killclient, {0} }, - - /* Layouts and layout manipulation */ - { MODKEY, XK_t, setlayout, {.v = &layouts[0]} }, - { MODKEY, XK_f, setlayout, {.v = &layouts[1]} }, - { MODKEY, XK_m, setlayout, {.v = &layouts[2]} }, - { MODKEY, XK_g, setlayout, {.v = &layouts[3]} }, - { MODKEY|ControlMask, XK_comma, cyclelayout, {.i = -1 } }, - { MODKEY|ControlMask, XK_period, cyclelayout, {.i = +1 } }, - { MODKEY, XK_space, setlayout, {0} }, - { MODKEY|ShiftMask, XK_space, togglefloating, {0} }, - - { MODKEY, XK_0, view, {.ui = ~0 } }, - { MODKEY|ShiftMask, XK_0, tag, {.ui = ~0 } }, - - /* Switching between monitors */ - { MODKEY, XK_comma, focusmon, {.i = -1 } }, - { MODKEY, XK_period, focusmon, {.i = +1 } }, - { MODKEY|ShiftMask, XK_comma, tagmon, {.i = -1 } }, - { MODKEY|ShiftMask, XK_period, tagmon, {.i = +1 } }, - - /* Dmenu scripts launched with ALT + CTRL + KEY */ - { Mod1Mask|ControlMask, XK_e, spawn, CMD("./.dmenu/dmenu-edit-configs.sh") }, - { Mod1Mask|ControlMask, XK_m, spawn, CMD("./.dmenu/dmenu-sysmon.sh") }, - { Mod1Mask|ControlMask, XK_p, spawn, CMD("passmenu") }, - { Mod1Mask|ControlMask, XK_r, spawn, CMD("./.dmenu/dmenu-reddio.sh") }, - { Mod1Mask|ControlMask, XK_s, spawn, CMD("./.dmenu/dmenu-surfraw.sh") }, - { Mod1Mask|ControlMask, XK_t, spawn, CMD("./.dmenu/dmenu-trading.sh") }, - { Mod1Mask|ControlMask, XK_i, spawn, CMD("./.dmenu/dmenu-scrot.sh") }, - - /* Apps Launched with SUPER + ALT + KEY */ - { MODKEY|Mod1Mask, XK_l, spawn, CMD("alacritty -e lynx gopher://distro.tube") }, - { MODKEY|Mod1Mask, XK_f, spawn, CMD("alacritty -e sh ./.config/vifm/scripts/vifmrun") }, - { MODKEY|Mod1Mask, XK_i, spawn, CMD("alacritty -e irssi") }, - { MODKEY|Mod1Mask, XK_n, spawn, CMD("alacritty -e newsboat") }, - { MODKEY|Mod1Mask, XK_r, spawn, CMD("alacritty -e rtv") }, - { MODKEY|Mod1Mask, XK_e, spawn, CMD("alacritty -e neomutt") }, - - TAGKEYS( XK_1, 0) - TAGKEYS( XK_2, 1) - TAGKEYS( XK_3, 2) - TAGKEYS( XK_4, 3) - TAGKEYS( XK_5, 4) - TAGKEYS( XK_6, 5) - TAGKEYS( XK_7, 6) - TAGKEYS( XK_8, 7) - TAGKEYS( XK_9, 8) - { MODKEY|ShiftMask, XK_q, quit, {0} }, - { MODKEY|ShiftMask, XK_r, quit, {1} }, -}; - -/* button definitions */ -/* click can be ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, or ClkRootWin */ -static Button buttons[] = { - /* click event mask button function argument */ - { ClkLtSymbol, 0, Button1, setlayout, {0} }, - { ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]} }, - { ClkWinTitle, 0, Button2, zoom, {0} }, - { ClkStatusText, 0, Button2, spawn, {.v = termcmd } }, - { ClkClientWin, MODKEY, Button1, movemouse, {0} }, - { ClkClientWin, MODKEY, Button2, togglefloating, {0} }, - { ClkClientWin, MODKEY, Button3, resizemouse, {0} }, - { ClkTagBar, 0, Button1, view, {0} }, - { ClkTagBar, 0, Button3, toggleview, {0} }, - { ClkTagBar, MODKEY, Button1, tag, {0} }, - { ClkTagBar, MODKEY, Button3, toggletag, {0} }, -}; - diff --git a/dwm/config.mk b/dwm/config.mk deleted file mode 100755 index 3cb1518..0000000 --- a/dwm/config.mk +++ /dev/null @@ -1,38 +0,0 @@ -# dwm version -VERSION = 6.2 - -# Customize below to fit your system - -# paths -PREFIX = /usr/local -MANPREFIX = ${PREFIX}/share/man - -X11INC = /usr/X11R6/include -X11LIB = /usr/X11R6/lib - -# Xinerama, comment if you don't want it -XINERAMALIBS = -lXinerama -XINERAMAFLAGS = -DXINERAMA - -# freetype -FREETYPELIBS = -lfontconfig -lXft -FREETYPEINC = /usr/include/freetype2 -# OpenBSD (uncomment) -#FREETYPEINC = ${X11INC}/freetype2 - -# includes and libs -INCS = -I${X11INC} -I${FREETYPEINC} -LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} -lXrender - -# flags -CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_POSIX_C_SOURCE=2 -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 diff --git a/dwm/drw.c b/dwm/drw.c deleted file mode 100755 index c202cb3..0000000 --- a/dwm/drw.c +++ /dev/null @@ -1,437 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include -#include -#include -#include -#include - -#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, Visual *visual, unsigned int depth, Colormap cmap) -{ - Drw *drw = ecalloc(1, sizeof(Drw)); - - drw->dpy = dpy; - drw->screen = screen; - drw->root = root; - drw->w = w; - drw->h = h; - drw->visual = visual; - drw->depth = depth; - drw->cmap = cmap; - drw->drawable = XCreatePixmap(dpy, root, w, h, depth); - drw->gc = XCreateGC(dpy, drw->drawable, 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, drw->depth); -} - -void -drw_free(Drw *drw) -{ - XFreePixmap(drw->dpy, drw->drawable); - XFreeGC(drw->dpy, drw->gc); - free(drw); -} - -/* This function is an implementation detail. Library users should use - * drw_fontset_create instead. - */ -static Fnt * -xfont_create(Drw *drw, const char *fontname, FcPattern *fontpattern) -{ - Fnt *font; - XftFont *xfont = NULL; - FcPattern *pattern = NULL; - - if (fontname) { - /* Using the pattern found at font->xfont->pattern does not yield the - * same substitution results as using the pattern returned by - * FcNameParse; using the latter results in the desired fallback - * behaviour whereas the former just results in missing-character - * rectangles being drawn, at least with some fonts. */ - if (!(xfont = XftFontOpenName(drw->dpy, drw->screen, fontname))) { - fprintf(stderr, "error, cannot load font from name: '%s'\n", fontname); - return NULL; - } - if (!(pattern = FcNameParse((FcChar8 *) fontname))) { - fprintf(stderr, "error, cannot parse font name to pattern: '%s'\n", fontname); - XftFontClose(drw->dpy, xfont); - return NULL; - } - } else if (fontpattern) { - if (!(xfont = XftFontOpenPattern(drw->dpy, fontpattern))) { - fprintf(stderr, "error, cannot load font from pattern.\n"); - return NULL; - } - } else { - die("no font specified."); - } - - /* Do not allow using color fonts. This is a workaround for a BadLength - * error from Xft with color glyphs. Modelled on the Xterm workaround. See - * https://bugzilla.redhat.com/show_bug.cgi?id=1498269 - * https://lists.suckless.org/dev/1701/30932.html - * https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=916349 - * and lots more all over the internet. - */ - FcBool iscol; - if(FcPatternGetBool(xfont->pattern, FC_COLOR, 0, &iscol) == FcResultMatch && iscol) { - XftFontClose(drw->dpy, xfont); - return NULL; - } - - font = ecalloc(1, sizeof(Fnt)); - font->xfont = xfont; - font->pattern = pattern; - font->h = xfont->ascent + xfont->descent; - font->dpy = drw->dpy; - - return font; -} - -static void -xfont_free(Fnt *font) -{ - if (!font) - return; - if (font->pattern) - FcPatternDestroy(font->pattern); - XftFontClose(font->dpy, font->xfont); - free(font); -} - -Fnt* -drw_fontset_create(Drw* drw, const char *fonts[], size_t fontcount) -{ - Fnt *cur, *ret = NULL; - size_t i; - - if (!drw || !fonts) - return NULL; - - for (i = 1; i <= fontcount; i++) { - if ((cur = xfont_create(drw, fonts[fontcount - i], NULL))) { - cur->next = ret; - ret = cur; - } - } - return (drw->fonts = ret); -} - -void -drw_fontset_free(Fnt *font) -{ - if (font) { - drw_fontset_free(font->next); - xfont_free(font); - } -} - -void -drw_clr_create(Drw *drw, Clr *dest, const char *clrname, unsigned int alpha) -{ - if (!drw || !dest || !clrname) - return; - - if (!XftColorAllocName(drw->dpy, drw->visual, drw->cmap, - clrname, dest)) - die("error, cannot allocate color '%s'", clrname); - - dest->pixel = (dest->pixel & 0x00ffffffU) | (alpha << 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[], const unsigned int alphas[], size_t clrcount) -{ - size_t i; - Clr *ret; - - /* need at least two colors for a scheme */ - if (!drw || !clrnames || clrcount < 2 || !(ret = ecalloc(clrcount, sizeof(XftColor)))) - return NULL; - - for (i = 0; i < clrcount; i++) - drw_clr_create(drw, &ret[i], clrnames[i], alphas[i]); - return ret; -} - -void -drw_setfontset(Drw *drw, Fnt *set) -{ - if (drw) - drw->fonts = set; -} - -void -drw_setscheme(Drw *drw, Clr *scm) -{ - if (drw) - drw->scheme = scm; -} - -void -drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int invert) -{ - if (!drw || !drw->scheme) - return; - XSetForeground(drw->dpy, drw->gc, invert ? drw->scheme[ColBg].pixel : drw->scheme[ColFg].pixel); - if (filled) - XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h); - else - XDrawRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w - 1, h - 1); -} - -int -drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert) -{ - char buf[1024]; - int ty; - unsigned int ew; - XftDraw *d = NULL; - Fnt *usedfont, *curfont, *nextfont; - size_t i, len; - int utf8strlen, utf8charlen, render = x || y || w || h; - long utf8codepoint = 0; - const char *utf8str; - FcCharSet *fccharset; - FcPattern *fcpattern; - FcPattern *match; - XftResult result; - int charexists = 0; - - if (!drw || (render && !drw->scheme) || !text || !drw->fonts) - return 0; - - if (!render) { - w = ~w; - } else { - XSetForeground(drw->dpy, drw->gc, drw->scheme[invert ? ColFg : ColBg].pixel); - XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h); - d = XftDrawCreate(drw->dpy, drw->drawable, drw->visual, drw->cmap); - x += lpad; - w -= lpad; - } - - usedfont = drw->fonts; - while (1) { - utf8strlen = 0; - utf8str = text; - nextfont = NULL; - while (*text) { - utf8charlen = utf8decode(text, &utf8codepoint, UTF_SIZ); - for (curfont = drw->fonts; curfont; curfont = curfont->next) { - charexists = charexists || XftCharExists(drw->dpy, curfont->xfont, utf8codepoint); - if (charexists) { - if (curfont == usedfont) { - utf8strlen += utf8charlen; - text += utf8charlen; - } else { - nextfont = curfont; - } - break; - } - } - - if (!charexists || nextfont) - break; - else - charexists = 0; - } - - if (utf8strlen) { - drw_font_getexts(usedfont, utf8str, utf8strlen, &ew, NULL); - /* shorten text if necessary */ - for (len = MIN(utf8strlen, sizeof(buf) - 1); len && ew > w; len--) - drw_font_getexts(usedfont, utf8str, len, &ew, NULL); - - if (len) { - memcpy(buf, utf8str, len); - buf[len] = '\0'; - if (len < utf8strlen) - for (i = len; i && i > len - 3; buf[--i] = '.') - ; /* NOP */ - - if (render) { - ty = y + (h - usedfont->h) / 2 + usedfont->xfont->ascent; - XftDrawStringUtf8(d, &drw->scheme[invert ? ColBg : ColFg], - usedfont->xfont, x, ty, (XftChar8 *)buf, len); - } - x += ew; - w -= ew; - } - } - - if (!*text) { - break; - } else if (nextfont) { - charexists = 0; - usedfont = nextfont; - } else { - /* Regardless of whether or not a fallback font is found, the - * character must be drawn. */ - charexists = 1; - - fccharset = FcCharSetCreate(); - FcCharSetAddChar(fccharset, utf8codepoint); - - if (!drw->fonts->pattern) { - /* Refer to the comment in xfont_create for more information. */ - die("the first font in the cache must be loaded from a font string."); - } - - fcpattern = FcPatternDuplicate(drw->fonts->pattern); - FcPatternAddCharSet(fcpattern, FC_CHARSET, fccharset); - FcPatternAddBool(fcpattern, FC_SCALABLE, FcTrue); - FcPatternAddBool(fcpattern, FC_COLOR, FcFalse); - - FcConfigSubstitute(NULL, fcpattern, FcMatchPattern); - FcDefaultSubstitute(fcpattern); - match = XftFontMatch(drw->dpy, drw->screen, fcpattern, &result); - - FcCharSetDestroy(fccharset); - FcPatternDestroy(fcpattern); - - if (match) { - usedfont = xfont_create(drw, NULL, match); - if (usedfont && XftCharExists(drw->dpy, usedfont->xfont, utf8codepoint)) { - for (curfont = drw->fonts; curfont->next; curfont = curfont->next) - ; /* NOP */ - curfont->next = usedfont; - } else { - xfont_free(usedfont); - usedfont = drw->fonts; - } - } - } - } - if (d) - XftDrawDestroy(d); - - return x + (render ? w : 0); -} - -void -drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h) -{ - if (!drw) - return; - - XCopyArea(drw->dpy, drw->drawable, win, drw->gc, x, y, w, h, x, y); - XSync(drw->dpy, False); -} - -unsigned int -drw_fontset_getwidth(Drw *drw, const char *text) -{ - if (!drw || !drw->fonts || !text) - return 0; - return drw_text(drw, 0, 0, 0, 0, 0, text, 0); -} - -void -drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h) -{ - XGlyphInfo ext; - - if (!font || !text) - return; - - XftTextExtentsUtf8(font->dpy, font->xfont, (XftChar8 *)text, len, &ext); - if (w) - *w = ext.xOff; - if (h) - *h = font->h; -} - -Cur * -drw_cur_create(Drw *drw, int shape) -{ - Cur *cur; - - if (!drw || !(cur = ecalloc(1, sizeof(Cur)))) - return NULL; - - cur->cursor = XCreateFontCursor(drw->dpy, shape); - - return cur; -} - -void -drw_cur_free(Drw *drw, Cur *cursor) -{ - if (!cursor) - return; - - XFreeCursor(drw->dpy, cursor->cursor); - free(cursor); -} diff --git a/dwm/drw.h b/dwm/drw.h deleted file mode 100755 index a56f523..0000000 --- a/dwm/drw.h +++ /dev/null @@ -1,60 +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; - Visual *visual; - unsigned int depth; - Colormap cmap; - 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, Visual *visual, unsigned int depth, Colormap cmap); -void drw_resize(Drw *drw, unsigned int w, unsigned int h); -void drw_free(Drw *drw); - -/* Fnt abstraction */ -Fnt *drw_fontset_create(Drw* drw, const char *fonts[], size_t fontcount); -void drw_fontset_free(Fnt* set); -unsigned int drw_fontset_getwidth(Drw *drw, const char *text); -void drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h); - -/* Colorscheme abstraction */ -void drw_clr_create(Drw *drw, Clr *dest, const char *clrname, unsigned int alpha); -Clr *drw_scm_create(Drw *drw, const char *clrnames[], const unsigned int alphas[], 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); diff --git a/dwm/dwm-alpha-20180613-b69c870.diff b/dwm/dwm-alpha-20180613-b69c870.diff deleted file mode 100755 index 558b2f3..0000000 --- a/dwm/dwm-alpha-20180613-b69c870.diff +++ /dev/null @@ -1,289 +0,0 @@ -From f699934b8c8a9c15988ad359bf8fedd6c55abd53 Mon Sep 17 00:00:00 2001 -From: Thomas Oltmann -Date: Wed, 13 Jun 2018 19:46:26 +0200 -Subject: [PATCH] Allow dwm to have translucent bars, while keeping all the - text on it opaque, just like the alpha-patch for st. Updated for b69c870. - ---- - config.def.h | 7 ++++++ - config.mk | 2 +- - drw.c | 26 ++++++++++++----------- - drw.h | 9 +++++--- - dwm.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++------ - 5 files changed, 82 insertions(+), 22 deletions(-) - -diff --git a/config.def.h b/config.def.h -index 1c0b587..4f68fe8 100644 ---- a/config.def.h -+++ b/config.def.h -@@ -12,11 +12,18 @@ static const char col_gray2[] = "#444444"; - static const char col_gray3[] = "#bbbbbb"; - static const char col_gray4[] = "#eeeeee"; - static const char col_cyan[] = "#005577"; -+static const unsigned int baralpha = 0xd0; -+static const unsigned int borderalpha = OPAQUE; - static const char *colors[][3] = { - /* fg bg border */ - [SchemeNorm] = { col_gray3, col_gray1, col_gray2 }, - [SchemeSel] = { col_gray4, col_cyan, col_cyan }, - }; -+static const unsigned int alphas[][3] = { -+ /* fg bg border */ -+ [SchemeNorm] = { OPAQUE, baralpha, borderalpha }, -+ [SchemeSel] = { OPAQUE, baralpha, borderalpha }, -+}; - - /* tagging */ - static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" }; -diff --git a/config.mk b/config.mk -index 25e2685..bef8de0 100644 ---- a/config.mk -+++ b/config.mk -@@ -22,7 +22,7 @@ FREETYPEINC = /usr/include/freetype2 - - # includes and libs - INCS = -I${X11INC} -I${FREETYPEINC} --LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} -+LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} -lXrender - - # flags - CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_POSIX_C_SOURCE=2 -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS} -diff --git a/drw.c b/drw.c -index c638323..77fc113 100644 ---- a/drw.c -+++ b/drw.c -@@ -61,7 +61,7 @@ utf8decode(const char *c, long *u, size_t clen) - } - - Drw * --drw_create(Display *dpy, int screen, Window root, unsigned int w, unsigned int h) -+drw_create(Display *dpy, int screen, Window root, unsigned int w, unsigned int h, Visual *visual, unsigned int depth, Colormap cmap) - { - Drw *drw = ecalloc(1, sizeof(Drw)); - -@@ -70,8 +70,11 @@ drw_create(Display *dpy, int screen, Window root, unsigned int w, unsigned int h - 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); -+ drw->visual = visual; -+ drw->depth = depth; -+ drw->cmap = cmap; -+ drw->drawable = XCreatePixmap(dpy, root, w, h, depth); -+ drw->gc = XCreateGC(dpy, drw->drawable, 0, NULL); - XSetLineAttributes(dpy, drw->gc, 1, LineSolid, CapButt, JoinMiter); - - return drw; -@@ -87,7 +90,7 @@ drw_resize(Drw *drw, unsigned int w, unsigned int h) - 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)); -+ drw->drawable = XCreatePixmap(drw->dpy, drw->root, w, h, drw->depth); - } - - void -@@ -180,21 +183,22 @@ drw_fontset_free(Fnt *font) - } - - void --drw_clr_create(Drw *drw, Clr *dest, const char *clrname) -+drw_clr_create(Drw *drw, Clr *dest, const char *clrname, unsigned int alpha) - { - if (!drw || !dest || !clrname) - return; - -- if (!XftColorAllocName(drw->dpy, DefaultVisual(drw->dpy, drw->screen), -- DefaultColormap(drw->dpy, drw->screen), -+ if (!XftColorAllocName(drw->dpy, drw->visual, drw->cmap, - clrname, dest)) - die("error, cannot allocate color '%s'", clrname); -+ -+ dest->pixel = (dest->pixel & 0x00ffffffU) | (alpha << 24); - } - - /* Wrapper to create color schemes. The caller has to call free(3) on the - * returned color scheme when done using it. */ - Clr * --drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount) -+drw_scm_create(Drw *drw, const char *clrnames[], const unsigned int alphas[], size_t clrcount) - { - size_t i; - Clr *ret; -@@ -204,7 +208,7 @@ drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount) - return NULL; - - for (i = 0; i < clrcount; i++) -- drw_clr_create(drw, &ret[i], clrnames[i]); -+ drw_clr_create(drw, &ret[i], clrnames[i], alphas[i]); - return ret; - } - -@@ -260,9 +264,7 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp - } 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)); -+ d = XftDrawCreate(drw->dpy, drw->drawable, drw->visual, drw->cmap); - x += lpad; - w -= lpad; - } -diff --git a/drw.h b/drw.h -index 4bcd5ad..a56f523 100644 ---- a/drw.h -+++ b/drw.h -@@ -20,6 +20,9 @@ typedef struct { - Display *dpy; - int screen; - Window root; -+ Visual *visual; -+ unsigned int depth; -+ Colormap cmap; - Drawable drawable; - GC gc; - Clr *scheme; -@@ -27,7 +30,7 @@ typedef struct { - } Drw; - - /* Drawable abstraction */ --Drw *drw_create(Display *dpy, int screen, Window win, unsigned int w, unsigned int h); -+Drw *drw_create(Display *dpy, int screen, Window win, unsigned int w, unsigned int h, Visual *visual, unsigned int depth, Colormap cmap); - void drw_resize(Drw *drw, unsigned int w, unsigned int h); - void drw_free(Drw *drw); - -@@ -38,8 +41,8 @@ unsigned int drw_fontset_getwidth(Drw *drw, const char *text); - void drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h); - - /* Colorscheme abstraction */ --void drw_clr_create(Drw *drw, Clr *dest, const char *clrname); --Clr *drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount); -+void drw_clr_create(Drw *drw, Clr *dest, const char *clrname, unsigned int alpha); -+Clr *drw_scm_create(Drw *drw, const char *clrnames[], const unsigned int alphas[], size_t clrcount); - - /* Cursor abstraction */ - Cur *drw_cur_create(Drw *drw, int shape); -diff --git a/dwm.c b/dwm.c -index 4465af1..20f8309 100644 ---- a/dwm.c -+++ b/dwm.c -@@ -57,6 +57,8 @@ - #define TAGMASK ((1 << LENGTH(tags)) - 1) - #define TEXTW(X) (drw_fontset_getwidth(drw, (X)) + lrpad) - -+#define OPAQUE 0xffU -+ - /* enums */ - enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */ - enum { SchemeNorm, SchemeSel }; /* color schemes */ -@@ -232,6 +234,7 @@ static Monitor *wintomon(Window w); - static int xerror(Display *dpy, XErrorEvent *ee); - static int xerrordummy(Display *dpy, XErrorEvent *ee); - static int xerrorstart(Display *dpy, XErrorEvent *ee); -+static void xinitvisual(); - static void zoom(const Arg *arg); - - /* variables */ -@@ -268,6 +271,11 @@ static Drw *drw; - static Monitor *mons, *selmon; - static Window root, wmcheckwin; - -+static int useargb = 0; -+static Visual *visual; -+static int depth; -+static Colormap cmap; -+ - /* configuration, allows nested code to access above variables */ - #include "config.h" - -@@ -1541,7 +1549,8 @@ setup(void) - sw = DisplayWidth(dpy, screen); - sh = DisplayHeight(dpy, screen); - root = RootWindow(dpy, screen); -- drw = drw_create(dpy, screen, root, sw, sh); -+ xinitvisual(); -+ drw = drw_create(dpy, screen, root, sw, sh, visual, depth, cmap); - if (!drw_fontset_create(drw, fonts, LENGTH(fonts))) - die("no fonts could be loaded."); - lrpad = drw->fonts->h; -@@ -1569,7 +1578,7 @@ setup(void) - /* init appearance */ - scheme = ecalloc(LENGTH(colors), sizeof(Clr *)); - for (i = 0; i < LENGTH(colors); i++) -- scheme[i] = drw_scm_create(drw, colors[i], 3); -+ scheme[i] = drw_scm_create(drw, colors[i], alphas[i], 3); - /* init bars */ - updatebars(); - updatestatus(); -@@ -1804,16 +1813,18 @@ updatebars(void) - Monitor *m; - XSetWindowAttributes wa = { - .override_redirect = True, -- .background_pixmap = ParentRelative, -+ .background_pixel = 0, -+ .border_pixel = 0, -+ .colormap = cmap, - .event_mask = ButtonPressMask|ExposureMask - }; - XClassHint ch = {"dwm", "dwm"}; - 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), -- CopyFromParent, DefaultVisual(dpy, screen), -- CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa); -+ m->barwin = XCreateWindow(dpy, root, m->wx, m->by, m->ww, bh, 0, depth, -+ InputOutput, visual, -+ CWOverrideRedirect|CWBackPixel|CWBorderPixel|CWColormap|CWEventMask, &wa); - XDefineCursor(dpy, m->barwin, cursor[CurNormal]->cursor); - XMapRaised(dpy, m->barwin); - XSetClassHint(dpy, m->barwin, &ch); -@@ -2110,6 +2121,43 @@ xerrorstart(Display *dpy, XErrorEvent *ee) - return -1; - } - -+void -+xinitvisual() -+{ -+ XVisualInfo *infos; -+ XRenderPictFormat *fmt; -+ int nitems; -+ int i; -+ -+ XVisualInfo tpl = { -+ .screen = screen, -+ .depth = 32, -+ .class = TrueColor -+ }; -+ long masks = VisualScreenMask | VisualDepthMask | VisualClassMask; -+ -+ infos = XGetVisualInfo(dpy, masks, &tpl, &nitems); -+ visual = NULL; -+ for(i = 0; i < nitems; i ++) { -+ fmt = XRenderFindVisualFormat(dpy, infos[i].visual); -+ if (fmt->type == PictTypeDirect && fmt->direct.alphaMask) { -+ visual = infos[i].visual; -+ depth = infos[i].depth; -+ cmap = XCreateColormap(dpy, root, visual, AllocNone); -+ useargb = 1; -+ break; -+ } -+ } -+ -+ XFree(infos); -+ -+ if (! visual) { -+ visual = DefaultVisual(dpy, screen); -+ depth = DefaultDepth(dpy, screen); -+ cmap = DefaultColormap(dpy, screen); -+ } -+} -+ - void - zoom(const Arg *arg) - { --- -2.17.0 - diff --git a/dwm/dwm-attachaside-20180126-db22360.diff b/dwm/dwm-attachaside-20180126-db22360.diff deleted file mode 100755 index ae43713..0000000 --- a/dwm/dwm-attachaside-20180126-db22360.diff +++ /dev/null @@ -1,92 +0,0 @@ -diff --git a/dwm.c b/dwm.c -index ec6a27c..7b6ce67 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) -@@ -148,6 +149,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 attachaside(Client *c); - static void attachstack(Client *c); - static void buttonpress(XEvent *e); - static void checkotherwm(void); -@@ -184,6 +186,7 @@ static void maprequest(XEvent *e); - static void monocle(Monitor *m); - static void motionnotify(XEvent *e); - static void movemouse(const Arg *arg); -+static Client *nexttagged(Client *c); - static Client *nexttiled(Client *c); - static void pop(Client *); - static void propertynotify(XEvent *e); -@@ -407,6 +410,18 @@ attach(Client *c) - c->mon->clients = c; - } - -+void -+attachaside(Client *c) { -+ Client *at = nexttagged(c); -+ if(!at) { -+ attach(c); -+ return; -+ } -+ c->next = at->next; -+ at->next = c; -+} -+ -+ - void - attachstack(Client *c) - { -@@ -1063,7 +1078,7 @@ manage(Window w, XWindowAttributes *wa) - c->isfloating = c->oldstate = trans != None || c->isfixed; - if (c->isfloating) - XRaiseWindow(dpy, c->win); -- attach(c); -+ attachaside(c); - attachstack(c); - XChangeProperty(dpy, root, netatom[NetClientList], XA_WINDOW, 32, PropModeAppend, - (unsigned char *) &(c->win), 1); -@@ -1193,6 +1208,16 @@ movemouse(const Arg *arg) - } - } - -+ Client * -+nexttagged(Client *c) { -+ Client *walked = c->mon->clients; -+ for(; -+ walked && (walked->isfloating || !ISVISIBLEONTAG(walked, c->tags)); -+ walked = walked->next -+ ); -+ return walked; -+} -+ - Client * - nexttiled(Client *c) - { -@@ -1418,7 +1443,7 @@ sendmon(Client *c, Monitor *m) - detachstack(c); - c->mon = m; - c->tags = m->tagset[m->seltags]; /* assign tags of target monitor */ -- attach(c); -+ attachaside(c); - attachstack(c); - focus(NULL); - arrange(NULL); -@@ -1899,6 +1924,7 @@ updategeom(void) - detachstack(c); - c->mon = mons; - attach(c); -+ attachaside(c); - attachstack(c); - } - if (m == selmon) diff --git a/dwm/dwm-autostart-20161205-bb3bd6f.diff b/dwm/dwm-autostart-20161205-bb3bd6f.diff deleted file mode 100755 index 6f11eaf..0000000 --- a/dwm/dwm-autostart-20161205-bb3bd6f.diff +++ /dev/null @@ -1,39 +0,0 @@ -commit 5918623c5bd7fda155bf9dc3d33890c4ae1722d0 -Author: Simon Bremer -Date: Thu Dec 22 17:31:07 2016 +0100 - - Applied and fixed autostart patch for previous version; - -diff --git a/dwm.c b/dwm.c -index d27cb67..066ed71 100644 ---- a/dwm.c -+++ b/dwm.c -@@ -194,6 +194,7 @@ static void resizeclient(Client *c, int x, int y, int w, int h); - static void resizemouse(const Arg *arg); - static void restack(Monitor *m); - static void run(void); -+static void runAutostart(void); - static void scan(void); - static int sendevent(Client *c, Atom proto); - static void sendmon(Client *c, Monitor *m); -@@ -1386,6 +1387,12 @@ run(void) - } - - void -+runAutostart(void) { -+ system("cd ~/.dwm; ./autostart_blocking.sh"); -+ system("cd ~/.dwm; ./autostart.sh &"); -+} -+ -+void - scan(void) - { - unsigned int i, num; -@@ -2145,6 +2152,7 @@ main(int argc, char *argv[]) - checkotherwm(); - setup(); - scan(); -+ runAutostart(); - run(); - cleanup(); - XCloseDisplay(dpy); diff --git a/dwm/dwm-cyclelayouts-20180524-a09e766.diff b/dwm/dwm-cyclelayouts-20180524-a09e766.diff deleted file mode 100755 index 8079028..0000000 --- a/dwm/dwm-cyclelayouts-20180524-a09e766.diff +++ /dev/null @@ -1,93 +0,0 @@ -From a09e766a4342f580582082a92b2de65f33208eb4 Mon Sep 17 00:00:00 2001 -From: Christopher Drelich -Date: Thu, 24 May 2018 00:56:56 -0400 -Subject: [PATCH] Function to cycle through available layouts. - -MOD-CTRL-, and MOD-CTRL-. -cycle backwards and forwards through available layouts. -Probably only useful if you have a lot of additional layouts. -The NULL, NULL layout should always be the last layout in your list, -in order to guarantee consistent behavior. ---- - config.def.h | 3 +++ - dwm.1 | 6 ++++++ - dwm.c | 18 ++++++++++++++++++ - 3 files changed, 27 insertions(+) - -diff --git a/config.def.h b/config.def.h -index a9ac303..153b880 100644 ---- a/config.def.h -+++ b/config.def.h -@@ -41,6 +41,7 @@ static const Layout layouts[] = { - { "[]=", tile }, /* first entry is default */ - { "><>", NULL }, /* no layout function means floating behavior */ - { "[M]", monocle }, -+ { NULL, NULL }, - }; - - /* key definitions */ -@@ -76,6 +77,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|ControlMask, XK_comma, cyclelayout, {.i = -1 } }, -+ { MODKEY|ControlMask, XK_period, cyclelayout, {.i = +1 } }, - { MODKEY, XK_space, setlayout, {0} }, - { MODKEY|ShiftMask, XK_space, togglefloating, {0} }, - { MODKEY, XK_0, view, {.ui = ~0 } }, -diff --git a/dwm.1 b/dwm.1 -index 13b3729..165891b 100644 ---- a/dwm.1 -+++ b/dwm.1 -@@ -92,6 +92,12 @@ Sets monocle layout. - .B Mod1\-space - Toggles between current and previous layout. - .TP -+.B Mod1\-Control\-, -+Cycles backwards in layout list. -+.TP -+.B Mod1\-Control\-. -+Cycles forwards in layout list. -+.TP - .B Mod1\-j - Focus next window. - .TP -diff --git a/dwm.c b/dwm.c -index bb95e26..db73000 100644 ---- a/dwm.c -+++ b/dwm.c -@@ -157,6 +157,7 @@ static void configure(Client *c); - static void configurenotify(XEvent *e); - static void configurerequest(XEvent *e); - static Monitor *createmon(void); -+static void cyclelayout(const Arg *arg); - static void destroynotify(XEvent *e); - static void detach(Client *c); - static void detachstack(Client *c); -@@ -645,6 +646,23 @@ createmon(void) - } - - void -+cyclelayout(const Arg *arg) { -+ Layout *l; -+ for(l = (Layout *)layouts; l != selmon->lt[selmon->sellt]; l++); -+ if(arg->i > 0) { -+ if(l->symbol && (l + 1)->symbol) -+ setlayout(&((Arg) { .v = (l + 1) })); -+ else -+ setlayout(&((Arg) { .v = layouts })); -+ } else { -+ if(l != layouts && (l - 1)->symbol) -+ setlayout(&((Arg) { .v = (l - 1) })); -+ else -+ setlayout(&((Arg) { .v = &layouts[LENGTH(layouts) - 2] })); -+ } -+} -+ -+void - destroynotify(XEvent *e) - { - Client *c; --- -2.7.4 - diff --git a/dwm/dwm-fancybar-2019018-b69c870.diff b/dwm/dwm-fancybar-2019018-b69c870.diff deleted file mode 100644 index 7d14e3a..0000000 --- a/dwm/dwm-fancybar-2019018-b69c870.diff +++ /dev/null @@ -1,74 +0,0 @@ -diff --git a/dwm.c b/dwm.c -index 4465af1..eff2da6 100644 ---- a/dwm.c -+++ b/dwm.c -@@ -695,10 +695,10 @@ dirtomon(int dir) - void - drawbar(Monitor *m) - { -- int x, w, sw = 0; -+ int x, w, sw = 0, tw, mw, ew = 0; - int boxs = drw->fonts->h / 9; - int boxw = drw->fonts->h / 6 + 2; -- unsigned int i, occ = 0, urg = 0; -+ unsigned int i, occ = 0, urg = 0, n = 0; - Client *c; - - /* draw status first so it can be overdrawn by tags later */ -@@ -709,6 +709,8 @@ drawbar(Monitor *m) - } - - for (c = m->clients; c; c = c->next) { -+ if (ISVISIBLE(c)) -+ n++; - occ |= c->tags; - if (c->isurgent) - urg |= c->tags; -@@ -729,15 +731,39 @@ drawbar(Monitor *m) - x = drw_text(drw, x, 0, w, bh, lrpad / 2, m->ltsymbol, 0); - - if ((w = m->ww - sw - x) > bh) { -- if (m->sel) { -- drw_setscheme(drw, scheme[m == selmon ? SchemeSel : SchemeNorm]); -- drw_text(drw, x, 0, w, bh, lrpad / 2, m->sel->name, 0); -- if (m->sel->isfloating) -- drw_rect(drw, x + boxs, boxs, boxw, boxw, m->sel->isfixed, 0); -- } else { -- drw_setscheme(drw, scheme[SchemeNorm]); -- drw_rect(drw, x, 0, w, bh, 1, 1); -+ if (n > 0) { -+ tw = TEXTW(m->sel->name) + lrpad; -+ mw = (tw >= w || n == 1) ? 0 : (w - tw) / (n - 1); -+ -+ i = 0; -+ for (c = m->clients; c; c = c->next) { -+ if (!ISVISIBLE(c) || c == m->sel) -+ continue; -+ tw = TEXTW(c->name); -+ if(tw < mw) -+ ew += (mw - tw); -+ else -+ i++; -+ } -+ if (i > 0) -+ mw += ew / i; -+ -+ for (c = m->clients; c; c = c->next) { -+ if (!ISVISIBLE(c)) -+ continue; -+ tw = MIN(m->sel == c ? w : mw, TEXTW(c->name)); -+ -+ drw_setscheme(drw, scheme[m->sel == c ? SchemeSel : SchemeNorm]); -+ if (tw > 0) /* trap special handling of 0 in drw_text */ -+ drw_text(drw, x, 0, tw, bh, lrpad / 2, c->name, 0); -+ if (c->isfloating) -+ drw_rect(drw, x + boxs, boxs, boxw, boxw, c->isfixed, 0); -+ x += tw; -+ w -= tw; -+ } - } -+ drw_setscheme(drw, scheme[SchemeNorm]); -+ drw_rect(drw, x, 0, w, bh, 1, 1); - } - drw_map(drw, m->barwin, 0, 0, m->ww, bh); - } diff --git a/dwm/dwm-gridmode-20170909-ceac8c9.diff b/dwm/dwm-gridmode-20170909-ceac8c9.diff deleted file mode 100755 index feec67b..0000000 --- a/dwm/dwm-gridmode-20170909-ceac8c9.diff +++ /dev/null @@ -1,73 +0,0 @@ -From b04bb473cf9818277d33a591f7fe2dfae96afaaf Mon Sep 17 00:00:00 2001 -From: Joshua Haase -Date: Mon, 15 Aug 2016 17:06:18 -0500 -Subject: [PATCH] Apply modified gridmode patch. - ---- - config.def.h | 3 +++ - layouts.c | 27 +++++++++++++++++++++++++++ - 2 files changed, 30 insertions(+) - create mode 100644 layouts.c - -diff --git a/config.def.h b/config.def.h -index a9ac303..30b7c4a 100644 ---- a/config.def.h -+++ b/config.def.h -@@ -36,11 +36,13 @@ static const float mfact = 0.55; /* factor of master area size [0.05..0.95] - static const int nmaster = 1; /* number of clients in master area */ - static const int resizehints = 1; /* 1 means respect size hints in tiled resizals */ - -+#include "layouts.c" - static const Layout layouts[] = { - /* symbol arrange function */ - { "[]=", tile }, /* first entry is default */ - { "><>", NULL }, /* no layout function means floating behavior */ - { "[M]", monocle }, -+ { "HHH", grid }, - }; - - /* key definitions */ -@@ -76,6 +78,7 @@ static Key keys[] = { - { MODKEY, XK_t, setlayout, {.v = &layouts[0]} }, - { MODKEY, XK_f, setlayout, {.v = &layouts[1]} }, - { MODKEY, XK_m, setlayout, {.v = &layouts[2]} }, -+ { MODKEY, XK_g, setlayout, {.v = &layouts[3]} }, - { MODKEY, XK_space, setlayout, {0} }, - { MODKEY|ShiftMask, XK_space, togglefloating, {0} }, - { MODKEY, XK_0, view, {.ui = ~0 } }, -diff --git a/layouts.c b/layouts.c -new file mode 100644 -index 0000000..d26acf3 ---- /dev/null -+++ b/layouts.c -@@ -0,0 +1,27 @@ -+void -+grid(Monitor *m) { -+ unsigned int i, n, cx, cy, cw, ch, aw, ah, cols, rows; -+ Client *c; -+ -+ for(n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next)) -+ n++; -+ -+ /* grid dimensions */ -+ for(rows = 0; rows <= n/2; rows++) -+ if(rows*rows >= n) -+ break; -+ cols = (rows && (rows - 1) * rows >= n) ? rows - 1 : rows; -+ -+ /* window geoms (cell height/width) */ -+ ch = m->wh / (rows ? rows : 1); -+ cw = m->ww / (cols ? cols : 1); -+ for(i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next)) { -+ cx = m->wx + (i / rows) * cw; -+ cy = m->wy + (i % rows) * ch; -+ /* adjust height/width of last row/column's windows */ -+ ah = ((i + 1) % rows == 0) ? m->wh - ch * rows : 0; -+ aw = (i >= rows * (cols - 1)) ? m->ww - cw * cols : 0; -+ resize(c, cx, cy, cw - 2 * c->bw + aw, ch - 2 * c->bw + ah, False); -+ i++; -+ } -+} --- -2.14.1 - diff --git a/dwm/dwm-restartsig-20180523-6.2.diff b/dwm/dwm-restartsig-20180523-6.2.diff deleted file mode 100644 index f1f8680..0000000 --- a/dwm/dwm-restartsig-20180523-6.2.diff +++ /dev/null @@ -1,139 +0,0 @@ -From 2991f37f0aaf44b9f9b11e7893ff0af8eb88f649 Mon Sep 17 00:00:00 2001 -From: Christopher Drelich -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 - diff --git a/dwm/dwm-rotatestack-20161021-ab9571b.diff b/dwm/dwm-rotatestack-20161021-ab9571b.diff deleted file mode 100755 index ed74c6d..0000000 --- a/dwm/dwm-rotatestack-20161021-ab9571b.diff +++ /dev/null @@ -1,102 +0,0 @@ -diff --git a/config.def.h b/config.def.h -index fd77a07..09737d7 100644 ---- a/config.def.h -+++ b/config.def.h -@@ -64,6 +64,8 @@ static Key keys[] = { - { MODKEY, XK_p, spawn, {.v = dmenucmd } }, - { MODKEY|ShiftMask, XK_Return, spawn, {.v = termcmd } }, - { MODKEY, XK_b, togglebar, {0} }, -+ { MODKEY|ShiftMask, XK_j, rotatestack, {.i = +1 } }, -+ { MODKEY|ShiftMask, XK_k, rotatestack, {.i = -1 } }, - { MODKEY, XK_j, focusstack, {.i = +1 } }, - { MODKEY, XK_k, focusstack, {.i = -1 } }, - { MODKEY, XK_i, incnmaster, {.i = +1 } }, -diff --git a/dwm.c b/dwm.c -index 421bf27..1ec8b10 100644 ---- a/dwm.c -+++ b/dwm.c -@@ -165,6 +165,8 @@ static void detachstack(Client *c); - static Monitor *dirtomon(int dir); - static void drawbar(Monitor *m); - static void drawbars(void); -+static void enqueue(Client *c); -+static void enqueuestack(Client *c); - static void enternotify(XEvent *e); - static void expose(XEvent *e); - static void focus(Client *c); -@@ -194,6 +196,7 @@ static void resize(Client *c, int x, int y, int w, int h, int interact); - static void resizeclient(Client *c, int x, int y, int w, int h); - static void resizemouse(const Arg *arg); - static void restack(Monitor *m); -+static void rotatestack(const Arg *arg); - static void run(void); - static void scan(void); - static int sendevent(Client *c, Atom proto); -@@ -765,6 +768,28 @@ drawbars(void) - } - - void -+enqueue(Client *c) -+{ -+ Client *l; -+ for (l = c->mon->clients; l && l->next; l = l->next); -+ if (l) { -+ l->next = c; -+ c->next = NULL; -+ } -+} -+ -+void -+enqueuestack(Client *c) -+{ -+ Client *l; -+ for (l = c->mon->stack; l && l->snext; l = l->snext); -+ if (l) { -+ l->snext = c; -+ c->snext = NULL; -+ } -+} -+ -+void - enternotify(XEvent *e) - { - Client *c; -@@ -1390,6 +1415,38 @@ restack(Monitor *m) - } - - void -+rotatestack(const Arg *arg) -+{ -+ Client *c = NULL, *f; -+ -+ if (!selmon->sel) -+ return; -+ f = selmon->sel; -+ if (arg->i > 0) { -+ for (c = nexttiled(selmon->clients); c && nexttiled(c->next); c = nexttiled(c->next)); -+ if (c){ -+ detach(c); -+ attach(c); -+ detachstack(c); -+ attachstack(c); -+ } -+ } else { -+ if ((c = nexttiled(selmon->clients))){ -+ detach(c); -+ enqueue(c); -+ detachstack(c); -+ enqueuestack(c); -+ } -+ } -+ if (c){ -+ arrange(selmon); -+ //unfocus(f, 1); -+ focus(f); -+ restack(selmon); -+ } -+} -+ -+void - run(void) - { - XEvent ev; diff --git a/dwm/dwm-statuspadding-20150524-c8e9479.diff b/dwm/dwm-statuspadding-20150524-c8e9479.diff deleted file mode 100755 index eab4bf9..0000000 --- a/dwm/dwm-statuspadding-20150524-c8e9479.diff +++ /dev/null @@ -1,62 +0,0 @@ -From 75d5edbe16ee2fc060ff8b05eea17791d6334a59 Mon Sep 17 00:00:00 2001 -From: Christopher Drelich -Date: Thu, 24 May 2018 23:24:12 -0400 -Subject: [PATCH] Replaces magic numbers in statusbar with configurable - variables. - -horizpadbar for horizontal statusbar padding -vertpadbar for vertical statusbar padding - -StatusText now has both left and right padding, -as well as the vertical padding that all of the statusbar shares. - -Other than the addition of left padding to StatusText, appearance -of the statusbar is identical to pre-patch when using the defaults -in config.def.h ---- - config.def.h | 2 ++ - dwm.c | 8 ++++---- - 2 files changed, 6 insertions(+), 4 deletions(-) - -diff --git a/config.def.h b/config.def.h -index a9ac303..5819399 100644 ---- a/config.def.h -+++ b/config.def.h -@@ -5,6 +5,8 @@ static const unsigned int borderpx = 1; /* border pixel of windows */ - static const unsigned int snap = 32; /* snap pixel */ - static const int showbar = 1; /* 0 means no bar */ - static const int topbar = 1; /* 0 means bottom bar */ -+static const int horizpadbar = 2; /* horizontal padding for statusbar */ -+static const int vertpadbar = 0; /* vertical padding for statusbar */ - static const char *fonts[] = { "monospace:size=10" }; - static const char dmenufont[] = "monospace:size=10"; - static const char col_gray1[] = "#222222"; -diff --git a/dwm.c b/dwm.c -index bb95e26..7b9ed42 100644 ---- a/dwm.c -+++ b/dwm.c -@@ -704,8 +704,8 @@ drawbar(Monitor *m) - /* draw status first so it can be overdrawn by tags later */ - if (m == selmon) { /* status is only drawn on selected monitor */ - drw_setscheme(drw, scheme[SchemeNorm]); -- sw = TEXTW(stext) - lrpad + 2; /* 2px right padding */ -- drw_text(drw, m->ww - sw, 0, sw, bh, 0, stext, 0); -+ sw = TEXTW(stext); -+ drw_text(drw, m->ww - sw, 0, sw, bh, lrpad / 2, stext, 0); - } - - for (c = m->clients; c; c = c->next) { -@@ -1544,8 +1544,8 @@ setup(void) - drw = drw_create(dpy, screen, root, sw, sh); - if (!drw_fontset_create(drw, fonts, LENGTH(fonts))) - die("no fonts could be loaded."); -- lrpad = drw->fonts->h; -- bh = drw->fonts->h + 2; -+ lrpad = drw->fonts->h + horizpadbar; -+ bh = drw->fonts->h + vertpadbar; - updategeom(); - /* init atoms */ - utf8string = XInternAtom(dpy, "UTF8_STRING", False); --- -2.7.4 - diff --git a/dwm/dwm-uselessgap-6.1.diff b/dwm/dwm-uselessgap-6.1.diff deleted file mode 100755 index 28cb369..0000000 --- a/dwm/dwm-uselessgap-6.1.diff +++ /dev/null @@ -1,54 +0,0 @@ ---- dwm/dwm.c.orig 2015-11-22 13:26:16.664650238 -0700 -+++ dwm/dwm.c 2015-11-22 13:25:57.407984351 -0700 -@@ -52,8 +52,8 @@ - #define ISVISIBLE(C) ((C->tags & C->mon->tagset[C->mon->seltags])) - #define LENGTH(X) (sizeof X / sizeof X[0]) - #define MOUSEMASK (BUTTONMASK|PointerMotionMask) --#define WIDTH(X) ((X)->w + 2 * (X)->bw) --#define HEIGHT(X) ((X)->h + 2 * (X)->bw) -+#define WIDTH(X) ((X)->w + 2 * (X)->bw + gappx) -+#define HEIGHT(X) ((X)->h + 2 * (X)->bw + gappx) - #define TAGMASK ((1 << LENGTH(tags)) - 1) - #define TEXTW(X) (drw_text(drw, 0, 0, 0, 0, (X), 0) + drw->fonts[0]->h) - -@@ -1293,12 +1293,36 @@ void - resizeclient(Client *c, int x, int y, int w, int h) - { - XWindowChanges wc; -+ unsigned int n; -+ unsigned int gapoffset; -+ unsigned int gapincr; -+ Client *nbc; - -- c->oldx = c->x; c->x = wc.x = x; -- c->oldy = c->y; c->y = wc.y = y; -- c->oldw = c->w; c->w = wc.width = w; -- c->oldh = c->h; c->h = wc.height = h; - wc.border_width = c->bw; -+ -+ /* Get number of clients for the selected monitor */ -+ for (n = 0, nbc = nexttiled(selmon->clients); nbc; nbc = nexttiled(nbc->next), n++); -+ -+ /* Do nothing if layout is floating */ -+ if (c->isfloating || selmon->lt[selmon->sellt]->arrange == NULL) { -+ gapincr = gapoffset = 0; -+ } else { -+ /* Remove border and gap if layout is monocle or only one client */ -+ if (selmon->lt[selmon->sellt]->arrange == monocle || n == 1) { -+ gapoffset = 0; -+ gapincr = -2 * borderpx; -+ wc.border_width = 0; -+ } else { -+ gapoffset = gappx; -+ gapincr = 2 * gappx; -+ } -+ } -+ -+ c->oldx = c->x; c->x = wc.x = x + gapoffset; -+ c->oldy = c->y; c->y = wc.y = y + gapoffset; -+ c->oldw = c->w; c->w = wc.width = w - gapincr; -+ c->oldh = c->h; c->h = wc.height = h - gapincr; -+ - XConfigureWindow(dpy, c->win, CWX|CWY|CWWidth|CWHeight|CWBorderWidth, &wc); - configure(c); - XSync(dpy, False); diff --git a/dwm/dwm.1 b/dwm/dwm.1 deleted file mode 100755 index 85d1cdc..0000000 --- a/dwm/dwm.1 +++ /dev/null @@ -1,192 +0,0 @@ -.TH DWM 1 dwm\-VERSION -.SH NAME -dwm \- dynamic window manager -.SH SYNOPSIS -.B dwm -.RB [ \-v ] -.SH DESCRIPTION -dwm is a dynamic window manager for X. It manages windows in tiled, monocle -and floating layouts. Either layout can be applied dynamically, optimising the -environment for the application in use and the task performed. -.P -In tiled layouts windows are managed in a master and stacking area. The master -area on the left contains one window by default, and the stacking area on the -right contains all other windows. The number of master area windows can be -adjusted from zero to an arbitrary number. In monocle layout all windows are -maximised to the screen size. In floating layout windows can be resized and -moved freely. Dialog windows are always managed floating, regardless of the -layout applied. -.P -Windows are grouped by tags. Each window can be tagged with one or multiple -tags. Selecting certain tags displays all windows with these tags. -.P -Each screen contains a small status bar which displays all available tags, the -layout, the title of the focused window, and the text read from the root window -name property, if the screen is focused. A floating window is indicated with an -empty square and a maximised floating window is indicated with a filled square -before the windows title. The selected tags are indicated with a different -color. The tags of the focused window are indicated with a filled square in the -top left corner. The tags which are applied to one or more windows are -indicated with an empty square in the top left corner. -.P -dwm draws a small border around windows to indicate the focus state. -.SH OPTIONS -.TP -.B \-v -prints version information to standard output, then exits. -.SH USAGE -.SS Status bar -.TP -.B X root window name -is read and displayed in the status text area. It can be set with the -.BR xsetroot (1) -command. -.TP -.B Button1 -click on a tag label to display all windows with that tag, click on the layout -label toggles between tiled and floating layout. -.TP -.B Button3 -click on a tag label adds/removes all windows with that tag to/from the view. -.TP -.B Mod1\-Button1 -click on a tag label applies that tag to the focused window. -.TP -.B Mod1\-Button3 -click on a tag label adds/removes that tag to/from the focused window. -.SS Keyboard commands -.TP -.B Mod1\-Shift\-Return -Start -.BR st(1). -.TP -.B Mod1\-p -Spawn -.BR dmenu(1) -for launching other programs. -.TP -.B Mod1\-, -Focus previous screen, if any. -.TP -.B Mod1\-. -Focus next screen, if any. -.TP -.B Mod1\-Shift\-, -Send focused window to previous screen, if any. -.TP -.B Mod1\-Shift\-. -Send focused window to next screen, if any. -.TP -.B Mod1\-b -Toggles bar on and off. -.TP -.B Mod1\-t -Sets tiled layout. -.TP -.B Mod1\-f -Sets floating layout. -.TP -.B Mod1\-m -Sets monocle layout. -.TP -.B Mod1\-space -Toggles between current and previous layout. -.TP -.B Mod1\-Control\-, -Cycles backwards in layout list. -.TP -.B Mod1\-Control\-. -Cycles forwards in layout list. -.TP -.B Mod1\-j -Focus next window. -.TP -.B Mod1\-k -Focus previous window. -.TP -.B Mod1\-i -Increase number of windows in master area. -.TP -.B Mod1\-d -Decrease number of windows in master area. -.TP -.B Mod1\-l -Increase master area size. -.TP -.B Mod1\-h -Decrease master area size. -.TP -.B Mod1\-Return -Zooms/cycles focused window to/from master area (tiled layouts only). -.TP -.B Mod1\-Shift\-c -Close focused window. -.TP -.B Mod1\-Shift\-space -Toggle focused window between tiled and floating state. -.TP -.B Mod1\-Tab -Toggles to the previously selected tags. -.TP -.B Mod1\-Shift\-[1..n] -Apply nth tag to focused window. -.TP -.B Mod1\-Shift\-0 -Apply all tags to focused window. -.TP -.B Mod1\-Control\-Shift\-[1..n] -Add/remove nth tag to/from focused window. -.TP -.B Mod1\-[1..n] -View all windows with nth tag. -.TP -.B Mod1\-0 -View all windows with any tag. -.TP -.B Mod1\-Control\-[1..n] -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 -Move focused window while dragging. Tiled windows will be toggled to the floating state. -.TP -.B Mod1\-Button2 -Toggles focused window between floating and tiled state. -.TP -.B Mod1\-Button3 -Resize focused window while dragging. Tiled windows will be toggled to the floating state. -.SH CUSTOMIZATION -dwm is customized by creating a custom config.h and (re)compiling the source -code. This keeps it fast, secure and simple. -.SH SIGNALS -.TP -.B SIGHUP - 1 -Restart the dwm process. -.TP -.B SIGTERM - 15 -Cleanly terminate the dwm process. -.SH SEE ALSO -.BR dmenu (1), -.BR st (1) -.SH ISSUES -Java applications which use the XToolkit/XAWT backend may draw grey windows -only. The XToolkit/XAWT backend breaks ICCCM-compliance in recent JDK 1.5 and early -JDK 1.6 versions, because it assumes a reparenting window manager. Possible workarounds -are using JDK 1.4 (which doesn't contain the XToolkit/XAWT backend) or setting the -environment variable -.BR AWT_TOOLKIT=MToolkit -(to use the older Motif backend instead) or running -.B xprop -root -f _NET_WM_NAME 32a -set _NET_WM_NAME LG3D -or -.B wmname LG3D -(to pretend that a non-reparenting window manager is running that the -XToolkit/XAWT backend can recognize) or when using OpenJDK setting the environment variable -.BR _JAVA_AWT_WM_NONREPARENTING=1 . -.SH BUGS -Send all bug reports with a patch to hackers@suckless.org. diff --git a/dwm/dwm.c b/dwm/dwm.c deleted file mode 100755 index b49b919..0000000 --- a/dwm/dwm.c +++ /dev/null @@ -1,2371 +0,0 @@ -/* See LICENSE file for copyright and license details. - * - * dynamic window manager is designed like any other X client as well. It is - * driven through handling X events. In contrast to other X clients, a window - * manager selects for SubstructureRedirectMask on the root window, to receive - * events about window (dis-)appearance. Only one X connection at a time is - * allowed to select for this event mask. - * - * The event handlers of dwm are organized in an array which is accessed - * whenever a new event has been fetched. This allows event dispatching - * in O(1) time. - * - * Each child of the root window is called a client, except windows which have - * set the override_redirect flag. Clients are organized in a linked client - * list on each monitor, the focus history is remembered through a stack list - * on each monitor. Each client contains a bit array to indicate the tags of a - * client. - * - * Keys and tagging rules are organized as arrays and defined in config.h. - * - * To understand everything else, start reading main(). - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef XINERAMA -#include -#endif /* XINERAMA */ -#include - -#include "drw.h" -#include "util.h" - -/* macros */ -#define BUTTONMASK (ButtonPressMask|ButtonReleaseMask) -#define CLEANMASK(mask) (mask & ~(numlockmask|LockMask) & (ShiftMask|ControlMask|Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask)) -#define INTERSECT(x,y,w,h,m) (MAX(0, MIN((x)+(w),(m)->wx+(m)->ww) - MAX((x),(m)->wx)) \ - * MAX(0, MIN((y)+(h),(m)->wy+(m)->wh) - MAX((y),(m)->wy))) -#define 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 + gappx) -#define HEIGHT(X) ((X)->h + 2 * (X)->bw + gappx) -#define TAGMASK ((1 << LENGTH(tags)) - 1) -#define TEXTW(X) (drw_fontset_getwidth(drw, (X)) + lrpad) - -#define OPAQUE 0xffU - -/* enums */ -enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */ -enum { SchemeNorm, SchemeSel }; /* color schemes */ -enum { NetSupported, NetWMName, NetWMState, NetWMCheck, - NetWMFullscreen, NetActiveWindow, NetWMWindowType, - NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH atoms */ -enum { WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast }; /* default atoms */ -enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, - ClkClientWin, ClkRootWin, ClkLast }; /* clicks */ - -typedef union { - int i; - unsigned int ui; - float f; - const void *v; -} Arg; - -typedef struct { - unsigned int click; - unsigned int mask; - unsigned int button; - void (*func)(const Arg *arg); - const Arg arg; -} Button; - -typedef struct Monitor Monitor; -typedef struct Client Client; -struct Client { - char name[256]; - float mina, maxa; - int x, y, w, h; - int oldx, oldy, oldw, oldh; - int basew, baseh, incw, inch, maxw, maxh, minw, minh; - int bw, oldbw; - unsigned int tags; - int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen; - Client *next; - Client *snext; - Monitor *mon; - Window win; -}; - -typedef struct { - unsigned int mod; - KeySym keysym; - void (*func)(const Arg *); - const Arg arg; -} Key; - -typedef struct { - const char *symbol; - void (*arrange)(Monitor *); -} Layout; - -struct Monitor { - char ltsymbol[16]; - float mfact; - int nmaster; - int num; - int by; /* bar geometry */ - int mx, my, mw, mh; /* screen size */ - int wx, wy, ww, wh; /* window area */ - unsigned int seltags; - unsigned int sellt; - unsigned int tagset[2]; - int showbar; - int topbar; - Client *clients; - Client *sel; - Client *stack; - Monitor *next; - Window barwin; - const Layout *lt[2]; -}; - -typedef struct { - const char *class; - const char *instance; - const char *title; - unsigned int tags; - int isfloating; - int monitor; -} Rule; - -/* function declarations */ -static void applyrules(Client *c); -static int applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact); -static void arrange(Monitor *m); -static void arrangemon(Monitor *m); -static void attach(Client *c); -static void attachaside(Client *c); -static void attachstack(Client *c); -static void buttonpress(XEvent *e); -static void checkotherwm(void); -static void cleanup(void); -static void cleanupmon(Monitor *mon); -static void clientmessage(XEvent *e); -static void configure(Client *c); -static void configurenotify(XEvent *e); -static void configurerequest(XEvent *e); -static Monitor *createmon(void); -static void cyclelayout(const Arg *arg); -static void destroynotify(XEvent *e); -static void detach(Client *c); -static void detachstack(Client *c); -static Monitor *dirtomon(int dir); -static void drawbar(Monitor *m); -static void drawbars(void); -static void enqueue(Client *c); -static void enqueuestack(Client *c); -static void enternotify(XEvent *e); -static void expose(XEvent *e); -static void focus(Client *c); -static void focusin(XEvent *e); -static void focusmon(const Arg *arg); -static void focusstack(const Arg *arg); -static int getrootptr(int *x, int *y); -static long getstate(Window w); -static int gettextprop(Window w, Atom atom, char *text, unsigned int size); -static void grabbuttons(Client *c, int focused); -static void grabkeys(void); -static void incnmaster(const Arg *arg); -static void keypress(XEvent *e); -static void killclient(const Arg *arg); -static void manage(Window w, XWindowAttributes *wa); -static void mappingnotify(XEvent *e); -static void maprequest(XEvent *e); -static void monocle(Monitor *m); -static void motionnotify(XEvent *e); -static void movemouse(const Arg *arg); -static Client *nexttagged(Client *c); -static Client *nexttiled(Client *c); -static void pop(Client *); -static void propertynotify(XEvent *e); -static void quit(const Arg *arg); -static Monitor *recttomon(int x, int y, int w, int h); -static void resize(Client *c, int x, int y, int w, int h, int interact); -static void resizeclient(Client *c, int x, int y, int w, int h); -static void resizemouse(const Arg *arg); -static void restack(Monitor *m); -static void rotatestack(const Arg *arg); -static void run(void); -static void runAutostart(void); -static void scan(void); -static int sendevent(Client *c, Atom proto); -static void sendmon(Client *c, Monitor *m); -static void setclientstate(Client *c, long state); -static void setfocus(Client *c); -static void setfullscreen(Client *c, int fullscreen); -static void setlayout(const Arg *arg); -static void setmfact(const Arg *arg); -static void setup(void); -static void seturgent(Client *c, int urg); -static void 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); -static void tile(Monitor *); -static void togglebar(const Arg *arg); -static void togglefloating(const Arg *arg); -static void toggletag(const Arg *arg); -static void toggleview(const Arg *arg); -static void unfocus(Client *c, int setfocus); -static void unmanage(Client *c, int destroyed); -static void unmapnotify(XEvent *e); -static void updatebarpos(Monitor *m); -static void updatebars(void); -static void updateclientlist(void); -static int updategeom(void); -static void updatenumlockmask(void); -static void updatesizehints(Client *c); -static void updatestatus(void); -static void updatetitle(Client *c); -static void 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 int xerror(Display *dpy, XErrorEvent *ee); -static int xerrordummy(Display *dpy, XErrorEvent *ee); -static int xerrorstart(Display *dpy, XErrorEvent *ee); -static void xinitvisual(); -static void zoom(const Arg *arg); - -/* variables */ -static const char broken[] = "broken"; -static char stext[256]; -static int screen; -static int sw, sh; /* X display screen geometry width, height */ -static int bh, blw = 0; /* bar geometry */ -static int lrpad; /* sum of left and right padding for text */ -static int (*xerrorxlib)(Display *, XErrorEvent *); -static unsigned int numlockmask = 0; -static void (*handler[LASTEvent]) (XEvent *) = { - [ButtonPress] = buttonpress, - [ClientMessage] = clientmessage, - [ConfigureRequest] = configurerequest, - [ConfigureNotify] = configurenotify, - [DestroyNotify] = destroynotify, - [EnterNotify] = enternotify, - [Expose] = expose, - [FocusIn] = focusin, - [KeyPress] = keypress, - [MappingNotify] = mappingnotify, - [MapRequest] = maprequest, - [MotionNotify] = motionnotify, - [PropertyNotify] = propertynotify, - [UnmapNotify] = unmapnotify -}; -static Atom wmatom[WMLast], netatom[NetLast]; -static int restart = 0; -static int running = 1; -static Cur *cursor[CurLast]; -static Clr **scheme; -static Display *dpy; -static Drw *drw; -static Monitor *mons, *selmon; -static Window root, wmcheckwin; - -static int useargb = 0; -static Visual *visual; -static int depth; -static Colormap cmap; - -/* configuration, allows nested code to access above variables */ -#include "config.h" - -/* compile-time check if all tags fit into an unsigned int bit array. */ -struct NumTags { char limitexceeded[LENGTH(tags) > 31 ? -1 : 1]; }; - -/* function implementations */ -void -applyrules(Client *c) -{ - const char *class, *instance; - unsigned int i; - const Rule *r; - Monitor *m; - XClassHint ch = { NULL, NULL }; - - /* rule matching */ - c->isfloating = 0; - c->tags = 0; - XGetClassHint(dpy, c->win, &ch); - class = ch.res_class ? ch.res_class : broken; - instance = ch.res_name ? ch.res_name : broken; - - for (i = 0; i < LENGTH(rules); i++) { - r = &rules[i]; - if ((!r->title || strstr(c->name, r->title)) - && (!r->class || strstr(class, r->class)) - && (!r->instance || strstr(instance, r->instance))) - { - c->isfloating = r->isfloating; - c->tags |= r->tags; - for (m = mons; m && m->num != r->monitor; m = m->next); - if (m) - c->mon = m; - } - } - if (ch.res_class) - XFree(ch.res_class); - if (ch.res_name) - XFree(ch.res_name); - c->tags = c->tags & TAGMASK ? c->tags & TAGMASK : c->mon->tagset[c->mon->seltags]; -} - -int -applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact) -{ - int baseismin; - Monitor *m = c->mon; - - /* set minimum possible */ - *w = MAX(1, *w); - *h = MAX(1, *h); - if (interact) { - if (*x > sw) - *x = sw - WIDTH(c); - if (*y > sh) - *y = sh - HEIGHT(c); - if (*x + *w + 2 * c->bw < 0) - *x = 0; - if (*y + *h + 2 * c->bw < 0) - *y = 0; - } else { - if (*x >= m->wx + m->ww) - *x = m->wx + m->ww - WIDTH(c); - if (*y >= m->wy + m->wh) - *y = m->wy + m->wh - HEIGHT(c); - if (*x + *w + 2 * c->bw <= m->wx) - *x = m->wx; - if (*y + *h + 2 * c->bw <= m->wy) - *y = m->wy; - } - if (*h < bh) - *h = bh; - if (*w < bh) - *w = bh; - if (resizehints || c->isfloating || !c->mon->lt[c->mon->sellt]->arrange) { - /* see last two sentences in ICCCM 4.1.2.3 */ - baseismin = c->basew == c->minw && c->baseh == c->minh; - if (!baseismin) { /* temporarily remove base dimensions */ - *w -= c->basew; - *h -= c->baseh; - } - /* adjust for aspect limits */ - if (c->mina > 0 && c->maxa > 0) { - if (c->maxa < (float)*w / *h) - *w = *h * c->maxa + 0.5; - else if (c->mina < (float)*h / *w) - *h = *w * c->mina + 0.5; - } - if (baseismin) { /* increment calculation requires this */ - *w -= c->basew; - *h -= c->baseh; - } - /* adjust for increment value */ - if (c->incw) - *w -= *w % c->incw; - if (c->inch) - *h -= *h % c->inch; - /* restore base dimensions */ - *w = MAX(*w + c->basew, c->minw); - *h = MAX(*h + c->baseh, c->minh); - if (c->maxw) - *w = MIN(*w, c->maxw); - if (c->maxh) - *h = MIN(*h, c->maxh); - } - return *x != c->x || *y != c->y || *w != c->w || *h != c->h; -} - -void -arrange(Monitor *m) -{ - if (m) - showhide(m->stack); - else for (m = mons; m; m = m->next) - showhide(m->stack); - if (m) { - arrangemon(m); - restack(m); - } else for (m = mons; m; m = m->next) - arrangemon(m); -} - -void -arrangemon(Monitor *m) -{ - strncpy(m->ltsymbol, m->lt[m->sellt]->symbol, sizeof m->ltsymbol); - if (m->lt[m->sellt]->arrange) - m->lt[m->sellt]->arrange(m); -} - -void -attach(Client *c) -{ - c->next = c->mon->clients; - c->mon->clients = c; -} - -void -attachaside(Client *c) { - Client *at = nexttagged(c); - if(!at) { - attach(c); - return; - } - c->next = at->next; - at->next = c; -} - - -void -attachstack(Client *c) -{ - c->snext = c->mon->stack; - c->mon->stack = c; -} - -void -buttonpress(XEvent *e) -{ - unsigned int i, x, click; - Arg arg = {0}; - Client *c; - Monitor *m; - XButtonPressedEvent *ev = &e->xbutton; - - click = ClkRootWin; - /* focus monitor if necessary */ - if ((m = wintomon(ev->window)) && m != selmon) { - unfocus(selmon->sel, 1); - selmon = m; - focus(NULL); - } - if (ev->window == selmon->barwin) { - i = x = 0; - do - x += TEXTW(tags[i]); - while (ev->x >= x && ++i < LENGTH(tags)); - if (i < LENGTH(tags)) { - click = ClkTagBar; - arg.ui = 1 << i; - } else if (ev->x < x + blw) - click = ClkLtSymbol; - else if (ev->x > selmon->ww - TEXTW(stext)) - click = ClkStatusText; - else - click = ClkWinTitle; - } else if ((c = wintoclient(ev->window))) { - focus(c); - restack(selmon); - XAllowEvents(dpy, ReplayPointer, CurrentTime); - click = ClkClientWin; - } - for (i = 0; i < LENGTH(buttons); i++) - if (click == buttons[i].click && buttons[i].func && buttons[i].button == ev->button - && CLEANMASK(buttons[i].mask) == CLEANMASK(ev->state)) - buttons[i].func(click == ClkTagBar && buttons[i].arg.i == 0 ? &arg : &buttons[i].arg); -} - -void -checkotherwm(void) -{ - xerrorxlib = XSetErrorHandler(xerrorstart); - /* this causes an error if some other window manager is running */ - XSelectInput(dpy, DefaultRootWindow(dpy), SubstructureRedirectMask); - XSync(dpy, False); - XSetErrorHandler(xerror); - XSync(dpy, False); -} - -void -cleanup(void) -{ - Arg a = {.ui = ~0}; - Layout foo = { "", NULL }; - Monitor *m; - size_t i; - - view(&a); - selmon->lt[selmon->sellt] = &foo; - for (m = mons; m; m = m->next) - while (m->stack) - unmanage(m->stack, 0); - XUngrabKey(dpy, AnyKey, AnyModifier, root); - while (mons) - cleanupmon(mons); - for (i = 0; i < CurLast; i++) - drw_cur_free(drw, cursor[i]); - for (i = 0; i < LENGTH(colors); i++) - free(scheme[i]); - XDestroyWindow(dpy, wmcheckwin); - drw_free(drw); - XSync(dpy, False); - XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime); - XDeleteProperty(dpy, root, netatom[NetActiveWindow]); -} - -void -cleanupmon(Monitor *mon) -{ - Monitor *m; - - if (mon == mons) - mons = mons->next; - else { - for (m = mons; m && m->next != mon; m = m->next); - m->next = mon->next; - } - XUnmapWindow(dpy, mon->barwin); - XDestroyWindow(dpy, mon->barwin); - free(mon); -} - -void -clientmessage(XEvent *e) -{ - XClientMessageEvent *cme = &e->xclient; - Client *c = wintoclient(cme->window); - - if (!c) - return; - if (cme->message_type == netatom[NetWMState]) { - if (cme->data.l[1] == netatom[NetWMFullscreen] - || cme->data.l[2] == netatom[NetWMFullscreen]) - setfullscreen(c, (cme->data.l[0] == 1 /* _NET_WM_STATE_ADD */ - || (cme->data.l[0] == 2 /* _NET_WM_STATE_TOGGLE */ && !c->isfullscreen))); - } else if (cme->message_type == netatom[NetActiveWindow]) { - if (c != selmon->sel && !c->isurgent) - seturgent(c, 1); - } -} - -void -configure(Client *c) -{ - XConfigureEvent ce; - - ce.type = ConfigureNotify; - ce.display = dpy; - ce.event = c->win; - ce.window = c->win; - ce.x = c->x; - ce.y = c->y; - ce.width = c->w; - ce.height = c->h; - ce.border_width = c->bw; - ce.above = None; - ce.override_redirect = False; - XSendEvent(dpy, c->win, False, StructureNotifyMask, (XEvent *)&ce); -} - -void -configurenotify(XEvent *e) -{ - Monitor *m; - Client *c; - XConfigureEvent *ev = &e->xconfigure; - int dirty; - - /* TODO: updategeom handling sucks, needs to be simplified */ - if (ev->window == root) { - dirty = (sw != ev->width || sh != ev->height); - sw = ev->width; - sh = ev->height; - if (updategeom() || dirty) { - drw_resize(drw, sw, bh); - updatebars(); - for (m = mons; m; m = m->next) { - for (c = m->clients; c; c = c->next) - if (c->isfullscreen) - resizeclient(c, m->mx, m->my, m->mw, m->mh); - XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, bh); - } - focus(NULL); - arrange(NULL); - } - } -} - -void -configurerequest(XEvent *e) -{ - Client *c; - Monitor *m; - XConfigureRequestEvent *ev = &e->xconfigurerequest; - XWindowChanges wc; - - if ((c = wintoclient(ev->window))) { - if (ev->value_mask & CWBorderWidth) - c->bw = ev->border_width; - else if (c->isfloating || !selmon->lt[selmon->sellt]->arrange) { - m = c->mon; - if (ev->value_mask & CWX) { - c->oldx = c->x; - c->x = m->mx + ev->x; - } - if (ev->value_mask & CWY) { - c->oldy = c->y; - c->y = m->my + ev->y; - } - if (ev->value_mask & CWWidth) { - c->oldw = c->w; - c->w = ev->width; - } - if (ev->value_mask & CWHeight) { - c->oldh = c->h; - c->h = ev->height; - } - if ((c->x + c->w) > m->mx + m->mw && c->isfloating) - c->x = m->mx + (m->mw / 2 - WIDTH(c) / 2); /* center in x direction */ - if ((c->y + c->h) > m->my + m->mh && c->isfloating) - c->y = m->my + (m->mh / 2 - HEIGHT(c) / 2); /* center in y direction */ - if ((ev->value_mask & (CWX|CWY)) && !(ev->value_mask & (CWWidth|CWHeight))) - configure(c); - if (ISVISIBLE(c)) - XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h); - } else - configure(c); - } else { - wc.x = ev->x; - wc.y = ev->y; - wc.width = ev->width; - wc.height = ev->height; - wc.border_width = ev->border_width; - wc.sibling = ev->above; - wc.stack_mode = ev->detail; - XConfigureWindow(dpy, ev->window, ev->value_mask, &wc); - } - XSync(dpy, False); -} - -Monitor * -createmon(void) -{ - Monitor *m; - - m = ecalloc(1, sizeof(Monitor)); - m->tagset[0] = m->tagset[1] = 1; - m->mfact = mfact; - m->nmaster = nmaster; - m->showbar = showbar; - m->topbar = topbar; - m->lt[0] = &layouts[0]; - m->lt[1] = &layouts[1 % LENGTH(layouts)]; - strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol); - return m; -} - -void -cyclelayout(const Arg *arg) { - Layout *l; - for(l = (Layout *)layouts; l != selmon->lt[selmon->sellt]; l++); - if(arg->i > 0) { - if(l->symbol && (l + 1)->symbol) - setlayout(&((Arg) { .v = (l + 1) })); - else - setlayout(&((Arg) { .v = layouts })); - } else { - if(l != layouts && (l - 1)->symbol) - setlayout(&((Arg) { .v = (l - 1) })); - else - setlayout(&((Arg) { .v = &layouts[LENGTH(layouts) - 2] })); - } -} - -void -destroynotify(XEvent *e) -{ - Client *c; - XDestroyWindowEvent *ev = &e->xdestroywindow; - - if ((c = wintoclient(ev->window))) - unmanage(c, 1); -} - -void -detach(Client *c) -{ - Client **tc; - - for (tc = &c->mon->clients; *tc && *tc != c; tc = &(*tc)->next); - *tc = c->next; -} - -void -detachstack(Client *c) -{ - Client **tc, *t; - - for (tc = &c->mon->stack; *tc && *tc != c; tc = &(*tc)->snext); - *tc = c->snext; - - if (c == c->mon->sel) { - for (t = c->mon->stack; t && !ISVISIBLE(t); t = t->snext); - c->mon->sel = t; - } -} - -Monitor * -dirtomon(int dir) -{ - Monitor *m = NULL; - - if (dir > 0) { - if (!(m = selmon->next)) - m = mons; - } else if (selmon == mons) - for (m = mons; m->next; m = m->next); - else - for (m = mons; m->next != selmon; m = m->next); - return m; -} - -void -drawbar(Monitor *m) -{ - int x, w, sw = 0, tw, mw, ew = 0; - int boxs = drw->fonts->h / 9; - int boxw = drw->fonts->h / 6 + 2; - unsigned int i, occ = 0, urg = 0, n = 0; - Client *c; - - /* draw status first so it can be overdrawn by tags later */ - if (m == selmon) { /* status is only drawn on selected monitor */ - drw_setscheme(drw, scheme[SchemeNorm]); - sw = TEXTW(stext); - drw_text(drw, m->ww - sw, 0, sw, bh, lrpad / 2, stext, 0); - } - - for (c = m->clients; c; c = c->next) { - if (ISVISIBLE(c)) - n++; - occ |= c->tags; - if (c->isurgent) - urg |= c->tags; - } - 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_text(drw, x, 0, w, bh, lrpad / 2, tags[i], urg & 1 << i); - if (occ & 1 << i) - drw_rect(drw, x + boxs, boxs, boxw, boxw, - m == selmon && selmon->sel && selmon->sel->tags & 1 << i, - urg & 1 << i); - x += w; - } - w = blw = TEXTW(m->ltsymbol); - drw_setscheme(drw, scheme[SchemeNorm]); - x = drw_text(drw, x, 0, w, bh, lrpad / 2, m->ltsymbol, 0); - - if ((w = m->ww - sw - x) > bh) { - if (n > 0) { - tw = TEXTW(m->sel->name) + lrpad; - mw = (tw >= w || n == 1) ? 0 : (w - tw) / (n - 1); - - i = 0; - for (c = m->clients; c; c = c->next) { - if (!ISVISIBLE(c) || c == m->sel) - continue; - tw = TEXTW(c->name); - if(tw < mw) - ew += (mw - tw); - else - i++; - } - if (i > 0) - mw += ew / i; - - for (c = m->clients; c; c = c->next) { - if (!ISVISIBLE(c)) - continue; - tw = MIN(m->sel == c ? w : mw, TEXTW(c->name)); - - drw_setscheme(drw, scheme[m->sel == c ? SchemeSel : SchemeNorm]); - if (tw > 0) /* trap special handling of 0 in drw_text */ - drw_text(drw, x, 0, tw, bh, lrpad / 2, c->name, 0); - if (c->isfloating) - drw_rect(drw, x + boxs, boxs, boxw, boxw, c->isfixed, 0); - x += tw; - w -= tw; - } - } - drw_setscheme(drw, scheme[SchemeNorm]); - drw_rect(drw, x, 0, w, bh, 1, 1); - } - drw_map(drw, m->barwin, 0, 0, m->ww, bh); -} - -void -drawbars(void) -{ - Monitor *m; - - for (m = mons; m; m = m->next) - drawbar(m); -} - -void -enqueue(Client *c) -{ - Client *l; - for (l = c->mon->clients; l && l->next; l = l->next); - if (l) { - l->next = c; - c->next = NULL; - } -} - -void -enqueuestack(Client *c) -{ - Client *l; - for (l = c->mon->stack; l && l->snext; l = l->snext); - if (l) { - l->snext = c; - c->snext = NULL; - } -} - -void -enternotify(XEvent *e) -{ - Client *c; - Monitor *m; - XCrossingEvent *ev = &e->xcrossing; - - if ((ev->mode != NotifyNormal || ev->detail == NotifyInferior) && ev->window != root) - return; - c = wintoclient(ev->window); - m = c ? c->mon : wintomon(ev->window); - if (m != selmon) { - unfocus(selmon->sel, 1); - selmon = m; - } else if (!c || c == selmon->sel) - return; - focus(c); -} - -void -expose(XEvent *e) -{ - Monitor *m; - XExposeEvent *ev = &e->xexpose; - - if (ev->count == 0 && (m = wintomon(ev->window))) - drawbar(m); -} - -void -focus(Client *c) -{ - if (!c || !ISVISIBLE(c)) - for (c = selmon->stack; c && !ISVISIBLE(c); c = c->snext); - if (selmon->sel && selmon->sel != c) - unfocus(selmon->sel, 0); - if (c) { - if (c->mon != selmon) - selmon = c->mon; - if (c->isurgent) - seturgent(c, 0); - detachstack(c); - attachstack(c); - grabbuttons(c, 1); - XSetWindowBorder(dpy, c->win, scheme[SchemeSel][ColBorder].pixel); - setfocus(c); - } else { - XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime); - XDeleteProperty(dpy, root, netatom[NetActiveWindow]); - } - selmon->sel = c; - drawbars(); -} - -/* there are some broken focus acquiring clients needing extra handling */ -void -focusin(XEvent *e) -{ - XFocusChangeEvent *ev = &e->xfocus; - - if (selmon->sel && ev->window != selmon->sel->win) - setfocus(selmon->sel); -} - -void -focusmon(const Arg *arg) -{ - Monitor *m; - - if (!mons->next) - return; - if ((m = dirtomon(arg->i)) == selmon) - return; - unfocus(selmon->sel, 0); - selmon = m; - focus(NULL); -} - -void -focusstack(const Arg *arg) -{ - Client *c = NULL, *i; - - if (!selmon->sel) - 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); - } -} - -Atom -getatomprop(Client *c, Atom prop) -{ - int di; - unsigned long dl; - unsigned char *p = NULL; - Atom da, atom = None; - - if (XGetWindowProperty(dpy, c->win, prop, 0L, sizeof atom, False, XA_ATOM, - &da, &di, &dl, &dl, &p) == Success && p) { - atom = *(Atom *)p; - XFree(p); - } - return atom; -} - -int -getrootptr(int *x, int *y) -{ - int di; - unsigned int dui; - Window dummy; - - return XQueryPointer(dpy, root, &dummy, &dummy, x, y, &di, &di, &dui); -} - -long -getstate(Window w) -{ - int format; - long result = -1; - unsigned char *p = NULL; - unsigned long n, extra; - Atom real; - - if (XGetWindowProperty(dpy, w, wmatom[WMState], 0L, 2L, False, wmatom[WMState], - &real, &format, &n, &extra, (unsigned char **)&p) != Success) - return -1; - if (n != 0) - result = *p; - XFree(p); - return result; -} - -int -gettextprop(Window w, Atom atom, char *text, unsigned int size) -{ - char **list = NULL; - int n; - XTextProperty name; - - if (!text || size == 0) - return 0; - text[0] = '\0'; - if (!XGetTextProperty(dpy, w, &name, atom) || !name.nitems) - return 0; - if (name.encoding == XA_STRING) - strncpy(text, (char *)name.value, size - 1); - else { - if (XmbTextPropertyToTextList(dpy, &name, &list, &n) >= Success && n > 0 && *list) { - strncpy(text, *list, size - 1); - XFreeStringList(list); - } - } - text[size - 1] = '\0'; - XFree(name.value); - return 1; -} - -void -grabbuttons(Client *c, int focused) -{ - updatenumlockmask(); - { - unsigned int i, j; - unsigned int modifiers[] = { 0, LockMask, numlockmask, numlockmask|LockMask }; - XUngrabButton(dpy, AnyButton, AnyModifier, c->win); - if (!focused) - XGrabButton(dpy, AnyButton, AnyModifier, c->win, False, - BUTTONMASK, GrabModeSync, GrabModeSync, None, None); - for (i = 0; i < LENGTH(buttons); i++) - if (buttons[i].click == ClkClientWin) - for (j = 0; j < LENGTH(modifiers); j++) - XGrabButton(dpy, buttons[i].button, - buttons[i].mask | modifiers[j], - c->win, False, BUTTONMASK, - GrabModeAsync, GrabModeSync, None, None); - } -} - -void -grabkeys(void) -{ - updatenumlockmask(); - { - unsigned int i, j; - unsigned int modifiers[] = { 0, LockMask, numlockmask, numlockmask|LockMask }; - KeyCode code; - - XUngrabKey(dpy, AnyKey, AnyModifier, root); - for (i = 0; i < LENGTH(keys); i++) - if ((code = XKeysymToKeycode(dpy, keys[i].keysym))) - for (j = 0; j < LENGTH(modifiers); j++) - XGrabKey(dpy, code, keys[i].mod | modifiers[j], root, - True, GrabModeAsync, GrabModeAsync); - } -} - -void -incnmaster(const Arg *arg) -{ - selmon->nmaster = MAX(selmon->nmaster + arg->i, 0); - arrange(selmon); -} - -#ifdef XINERAMA -static int -isuniquegeom(XineramaScreenInfo *unique, size_t n, XineramaScreenInfo *info) -{ - while (n--) - if (unique[n].x_org == info->x_org && unique[n].y_org == info->y_org - && unique[n].width == info->width && unique[n].height == info->height) - return 0; - return 1; -} -#endif /* XINERAMA */ - -void -keypress(XEvent *e) -{ - unsigned int i; - KeySym keysym; - XKeyEvent *ev; - - ev = &e->xkey; - keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0); - for (i = 0; i < LENGTH(keys); i++) - if (keysym == keys[i].keysym - && CLEANMASK(keys[i].mod) == CLEANMASK(ev->state) - && keys[i].func) - keys[i].func(&(keys[i].arg)); -} - -void -killclient(const Arg *arg) -{ - if (!selmon->sel) - return; - if (!sendevent(selmon->sel, wmatom[WMDelete])) { - XGrabServer(dpy); - XSetErrorHandler(xerrordummy); - XSetCloseDownMode(dpy, DestroyAll); - XKillClient(dpy, selmon->sel->win); - XSync(dpy, False); - XSetErrorHandler(xerror); - XUngrabServer(dpy); - } -} - -void -manage(Window w, XWindowAttributes *wa) -{ - Client *c, *t = NULL; - Window trans = None; - XWindowChanges wc; - - c = ecalloc(1, sizeof(Client)); - c->win = w; - /* geometry */ - c->x = c->oldx = wa->x; - c->y = c->oldy = wa->y; - c->w = c->oldw = wa->width; - c->h = c->oldh = wa->height; - c->oldbw = wa->border_width; - - updatetitle(c); - if (XGetTransientForHint(dpy, w, &trans) && (t = wintoclient(trans))) { - c->mon = t->mon; - c->tags = t->tags; - } else { - c->mon = selmon; - applyrules(c); - } - - if (c->x + WIDTH(c) > c->mon->mx + c->mon->mw) - c->x = c->mon->mx + c->mon->mw - WIDTH(c); - if (c->y + HEIGHT(c) > c->mon->my + c->mon->mh) - c->y = c->mon->my + c->mon->mh - HEIGHT(c); - c->x = MAX(c->x, c->mon->mx); - /* only fix client y-offset, if the client center might cover the bar */ - c->y = MAX(c->y, ((c->mon->by == c->mon->my) && (c->x + (c->w / 2) >= c->mon->wx) - && (c->x + (c->w / 2) < c->mon->wx + c->mon->ww)) ? bh : c->mon->my); - c->bw = borderpx; - - wc.border_width = c->bw; - XConfigureWindow(dpy, w, CWBorderWidth, &wc); - XSetWindowBorder(dpy, w, scheme[SchemeNorm][ColBorder].pixel); - configure(c); /* propagates border_width, if size doesn't change */ - updatewindowtype(c); - updatesizehints(c); - updatewmhints(c); - XSelectInput(dpy, w, EnterWindowMask|FocusChangeMask|PropertyChangeMask|StructureNotifyMask); - grabbuttons(c, 0); - if (!c->isfloating) - c->isfloating = c->oldstate = trans != None || c->isfixed; - if (c->isfloating) - XRaiseWindow(dpy, c->win); - attachaside(c); - attachstack(c); - XChangeProperty(dpy, root, netatom[NetClientList], XA_WINDOW, 32, PropModeAppend, - (unsigned char *) &(c->win), 1); - XMoveResizeWindow(dpy, c->win, c->x + 2 * sw, c->y, c->w, c->h); /* some windows require this */ - setclientstate(c, NormalState); - if (c->mon == selmon) - unfocus(selmon->sel, 0); - c->mon->sel = c; - arrange(c->mon); - XMapWindow(dpy, c->win); - focus(NULL); -} - -void -mappingnotify(XEvent *e) -{ - XMappingEvent *ev = &e->xmapping; - - XRefreshKeyboardMapping(ev); - if (ev->request == MappingKeyboard) - grabkeys(); -} - -void -maprequest(XEvent *e) -{ - static XWindowAttributes wa; - XMapRequestEvent *ev = &e->xmaprequest; - - if (!XGetWindowAttributes(dpy, ev->window, &wa)) - return; - if (wa.override_redirect) - return; - if (!wintoclient(ev->window)) - manage(ev->window, &wa); -} - -void -monocle(Monitor *m) -{ - unsigned int n = 0; - Client *c; - - for (c = m->clients; c; c = c->next) - if (ISVISIBLE(c)) - n++; - if (n > 0) /* override layout symbol */ - snprintf(m->ltsymbol, sizeof m->ltsymbol, "[%d]", n); - for (c = nexttiled(m->clients); c; c = nexttiled(c->next)) - resize(c, m->wx, m->wy, m->ww - 2 * c->bw, m->wh - 2 * c->bw, 0); -} - -void -motionnotify(XEvent *e) -{ - static Monitor *mon = NULL; - Monitor *m; - XMotionEvent *ev = &e->xmotion; - - if (ev->window != root) - return; - if ((m = recttomon(ev->x_root, ev->y_root, 1, 1)) != mon && mon) { - unfocus(selmon->sel, 1); - selmon = m; - focus(NULL); - } - mon = m; -} - -void -movemouse(const Arg *arg) -{ - int x, y, ocx, ocy, nx, ny; - Client *c; - Monitor *m; - XEvent ev; - Time lasttime = 0; - - if (!(c = selmon->sel)) - return; - if (c->isfullscreen) /* no support moving fullscreen windows by mouse */ - return; - restack(selmon); - ocx = c->x; - ocy = c->y; - if (XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, - None, cursor[CurMove]->cursor, CurrentTime) != GrabSuccess) - return; - if (!getrootptr(&x, &y)) - return; - do { - XMaskEvent(dpy, MOUSEMASK|ExposureMask|SubstructureRedirectMask, &ev); - switch(ev.type) { - case ConfigureRequest: - case Expose: - case MapRequest: - handler[ev.type](&ev); - break; - case MotionNotify: - if ((ev.xmotion.time - lasttime) <= (1000 / 60)) - continue; - lasttime = ev.xmotion.time; - - nx = ocx + (ev.xmotion.x - x); - ny = ocy + (ev.xmotion.y - y); - if (abs(selmon->wx - nx) < snap) - nx = selmon->wx; - else if (abs((selmon->wx + selmon->ww) - (nx + WIDTH(c))) < snap) - nx = selmon->wx + selmon->ww - WIDTH(c); - if (abs(selmon->wy - ny) < snap) - ny = selmon->wy; - else if (abs((selmon->wy + selmon->wh) - (ny + HEIGHT(c))) < snap) - ny = selmon->wy + selmon->wh - HEIGHT(c); - if (!c->isfloating && selmon->lt[selmon->sellt]->arrange - && (abs(nx - c->x) > snap || abs(ny - c->y) > snap)) - togglefloating(NULL); - if (!selmon->lt[selmon->sellt]->arrange || c->isfloating) - resize(c, nx, ny, c->w, c->h, 1); - break; - } - } while (ev.type != ButtonRelease); - XUngrabPointer(dpy, CurrentTime); - if ((m = recttomon(c->x, c->y, c->w, c->h)) != selmon) { - sendmon(c, m); - selmon = m; - focus(NULL); - } -} - - Client * -nexttagged(Client *c) { - Client *walked = c->mon->clients; - for(; - walked && (walked->isfloating || !ISVISIBLEONTAG(walked, c->tags)); - walked = walked->next - ); - return walked; -} - -Client * -nexttiled(Client *c) -{ - for (; c && (c->isfloating || !ISVISIBLE(c)); c = c->next); - return c; -} - -void -pop(Client *c) -{ - detach(c); - attach(c); - focus(c); - arrange(c->mon); -} - -void -propertynotify(XEvent *e) -{ - Client *c; - Window trans; - XPropertyEvent *ev = &e->xproperty; - - if ((ev->window == root) && (ev->atom == XA_WM_NAME)) - updatestatus(); - else if (ev->state == PropertyDelete) - return; /* ignore */ - else if ((c = wintoclient(ev->window))) { - switch(ev->atom) { - default: break; - case XA_WM_TRANSIENT_FOR: - if (!c->isfloating && (XGetTransientForHint(dpy, c->win, &trans)) && - (c->isfloating = (wintoclient(trans)) != NULL)) - arrange(c->mon); - break; - case XA_WM_NORMAL_HINTS: - updatesizehints(c); - break; - case XA_WM_HINTS: - updatewmhints(c); - drawbars(); - break; - } - if (ev->atom == XA_WM_NAME || ev->atom == netatom[NetWMName]) { - updatetitle(c); - if (c == c->mon->sel) - drawbar(c->mon); - } - if (ev->atom == netatom[NetWMWindowType]) - updatewindowtype(c); - } -} - -void -quit(const Arg *arg) -{ - if(arg->i) restart = 1; - running = 0; -} - -Monitor * -recttomon(int x, int y, int w, int h) -{ - Monitor *m, *r = selmon; - int a, area = 0; - - for (m = mons; m; m = m->next) - if ((a = INTERSECT(x, y, w, h, m)) > area) { - area = a; - r = m; - } - return r; -} - -void -resize(Client *c, int x, int y, int w, int h, int interact) -{ - if (applysizehints(c, &x, &y, &w, &h, interact)) - resizeclient(c, x, y, w, h); -} - -void -resizeclient(Client *c, int x, int y, int w, int h) -{ - XWindowChanges wc; - unsigned int n; - unsigned int gapoffset; - unsigned int gapincr; - Client *nbc; - - wc.border_width = c->bw; - - /* Get number of clients for the selected monitor */ - for (n = 0, nbc = nexttiled(selmon->clients); nbc; nbc = nexttiled(nbc->next), n++); - - /* Do nothing if layout is floating */ - if (c->isfloating || selmon->lt[selmon->sellt]->arrange == NULL) { - gapincr = gapoffset = 0; - } else { - gapoffset = gappx; - gapincr = 2 * gappx; - } - - c->oldx = c->x; c->x = wc.x = x + gapoffset; - c->oldy = c->y; c->y = wc.y = y + gapoffset; - c->oldw = c->w; c->w = wc.width = w - gapincr; - c->oldh = c->h; c->h = wc.height = h - gapincr; - - XConfigureWindow(dpy, c->win, CWX|CWY|CWWidth|CWHeight|CWBorderWidth, &wc); - configure(c); - XSync(dpy, False); -} - -void -resizemouse(const Arg *arg) -{ - int ocx, ocy, nw, nh; - Client *c; - Monitor *m; - XEvent ev; - Time lasttime = 0; - - if (!(c = selmon->sel)) - return; - if (c->isfullscreen) /* no support resizing fullscreen windows by mouse */ - return; - restack(selmon); - ocx = c->x; - ocy = c->y; - 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); - do { - XMaskEvent(dpy, MOUSEMASK|ExposureMask|SubstructureRedirectMask, &ev); - switch(ev.type) { - case ConfigureRequest: - case Expose: - case MapRequest: - handler[ev.type](&ev); - break; - case MotionNotify: - if ((ev.xmotion.time - lasttime) <= (1000 / 60)) - continue; - lasttime = ev.xmotion.time; - - nw = MAX(ev.xmotion.x - ocx - 2 * c->bw + 1, 1); - nh = MAX(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) - { - if (!c->isfloating && selmon->lt[selmon->sellt]->arrange - && (abs(nw - c->w) > snap || abs(nh - c->h) > snap)) - togglefloating(NULL); - } - if (!selmon->lt[selmon->sellt]->arrange || c->isfloating) - resize(c, c->x, c->y, 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); - XUngrabPointer(dpy, CurrentTime); - while (XCheckMaskEvent(dpy, EnterWindowMask, &ev)); - if ((m = recttomon(c->x, c->y, c->w, c->h)) != selmon) { - sendmon(c, m); - selmon = m; - focus(NULL); - } -} - -void -restack(Monitor *m) -{ - Client *c; - XEvent ev; - XWindowChanges wc; - - drawbar(m); - if (!m->sel) - return; - if (m->sel->isfloating || !m->lt[m->sellt]->arrange) - XRaiseWindow(dpy, m->sel->win); - if (m->lt[m->sellt]->arrange) { - wc.stack_mode = Below; - wc.sibling = m->barwin; - for (c = m->stack; c; c = c->snext) - if (!c->isfloating && ISVISIBLE(c)) { - XConfigureWindow(dpy, c->win, CWSibling|CWStackMode, &wc); - wc.sibling = c->win; - } - } - XSync(dpy, False); - while (XCheckMaskEvent(dpy, EnterWindowMask, &ev)); -} - -void -rotatestack(const Arg *arg) -{ - Client *c = NULL, *f; - - if (!selmon->sel) - return; - f = selmon->sel; - if (arg->i > 0) { - for (c = nexttiled(selmon->clients); c && nexttiled(c->next); c = nexttiled(c->next)); - if (c){ - detach(c); - attach(c); - detachstack(c); - attachstack(c); - } - } else { - if ((c = nexttiled(selmon->clients))){ - detach(c); - enqueue(c); - detachstack(c); - enqueuestack(c); - } - } - if (c){ - arrange(selmon); - //unfocus(f, 1); - focus(f); - restack(selmon); - } -} - -void -run(void) -{ - XEvent ev; - /* main event loop */ - XSync(dpy, False); - while (running && !XNextEvent(dpy, &ev)) - if (handler[ev.type]) - handler[ev.type](&ev); /* call handler */ -} - -void -runAutostart(void) { - system("cd ~/.dwm; ./autostart_blocking.sh"); - system("cd ~/.dwm; ./autostart.sh &"); -} - -void -scan(void) -{ - unsigned int i, num; - Window d1, d2, *wins = NULL; - XWindowAttributes wa; - - if (XQueryTree(dpy, root, &d1, &d2, &wins, &num)) { - for (i = 0; i < num; i++) { - if (!XGetWindowAttributes(dpy, wins[i], &wa) - || wa.override_redirect || XGetTransientForHint(dpy, wins[i], &d1)) - continue; - if (wa.map_state == IsViewable || getstate(wins[i]) == IconicState) - manage(wins[i], &wa); - } - for (i = 0; i < num; i++) { /* now the transients */ - if (!XGetWindowAttributes(dpy, wins[i], &wa)) - continue; - if (XGetTransientForHint(dpy, wins[i], &d1) - && (wa.map_state == IsViewable || getstate(wins[i]) == IconicState)) - manage(wins[i], &wa); - } - if (wins) - XFree(wins); - } -} - -void -sendmon(Client *c, Monitor *m) -{ - if (c->mon == m) - return; - unfocus(c, 1); - detach(c); - detachstack(c); - c->mon = m; - c->tags = m->tagset[m->seltags]; /* assign tags of target monitor */ - attachaside(c); - attachstack(c); - focus(NULL); - arrange(NULL); -} - -void -setclientstate(Client *c, long state) -{ - long data[] = { state, None }; - - XChangeProperty(dpy, c->win, wmatom[WMState], wmatom[WMState], 32, - PropModeReplace, (unsigned char *)data, 2); -} - -int -sendevent(Client *c, Atom proto) -{ - int n; - Atom *protocols; - int exists = 0; - XEvent ev; - - if (XGetWMProtocols(dpy, c->win, &protocols, &n)) { - while (!exists && n--) - exists = protocols[n] == proto; - XFree(protocols); - } - if (exists) { - ev.type = ClientMessage; - ev.xclient.window = c->win; - ev.xclient.message_type = wmatom[WMProtocols]; - ev.xclient.format = 32; - ev.xclient.data.l[0] = proto; - ev.xclient.data.l[1] = CurrentTime; - XSendEvent(dpy, c->win, False, NoEventMask, &ev); - } - return exists; -} - -void -setfocus(Client *c) -{ - if (!c->neverfocus) { - XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime); - XChangeProperty(dpy, root, netatom[NetActiveWindow], - XA_WINDOW, 32, PropModeReplace, - (unsigned char *) &(c->win), 1); - } - sendevent(c, wmatom[WMTakeFocus]); -} - -void -setfullscreen(Client *c, int fullscreen) -{ - if (fullscreen && !c->isfullscreen) { - XChangeProperty(dpy, c->win, netatom[NetWMState], XA_ATOM, 32, - PropModeReplace, (unsigned char*)&netatom[NetWMFullscreen], 1); - c->isfullscreen = 1; - c->oldstate = c->isfloating; - c->oldbw = c->bw; - c->bw = 0; - c->isfloating = 1; - resizeclient(c, c->mon->mx, c->mon->my, c->mon->mw, c->mon->mh); - XRaiseWindow(dpy, c->win); - } else if (!fullscreen && c->isfullscreen){ - XChangeProperty(dpy, c->win, netatom[NetWMState], XA_ATOM, 32, - PropModeReplace, (unsigned char*)0, 0); - c->isfullscreen = 0; - c->isfloating = c->oldstate; - c->bw = c->oldbw; - c->x = c->oldx; - c->y = c->oldy; - c->w = c->oldw; - c->h = c->oldh; - resizeclient(c, c->x, c->y, c->w, c->h); - arrange(c->mon); - } -} - -void -setlayout(const Arg *arg) -{ - if (!arg || !arg->v || arg->v != selmon->lt[selmon->sellt]) - selmon->sellt ^= 1; - if (arg && arg->v) - selmon->lt[selmon->sellt] = (Layout *)arg->v; - strncpy(selmon->ltsymbol, selmon->lt[selmon->sellt]->symbol, sizeof selmon->ltsymbol); - if (selmon->sel) - arrange(selmon); - else - drawbar(selmon); -} - -/* arg > 1.0 will set mfact absolutely */ -void -setmfact(const Arg *arg) -{ - float f; - - if (!arg || !selmon->lt[selmon->sellt]->arrange) - return; - f = arg->f < 1.0 ? arg->f + selmon->mfact : arg->f - 1.0; - if (f < 0.1 || f > 0.9) - return; - selmon->mfact = f; - arrange(selmon); -} - -void -setup(void) -{ - int i; - XSetWindowAttributes wa; - Atom utf8string; - - /* clean up any zombies immediately */ - sigchld(0); - - signal(SIGHUP, sighup); - signal(SIGTERM, sigterm); - - /* init screen */ - screen = DefaultScreen(dpy); - sw = DisplayWidth(dpy, screen); - sh = DisplayHeight(dpy, screen); - root = RootWindow(dpy, screen); - xinitvisual(); - drw = drw_create(dpy, screen, root, sw, sh, visual, depth, cmap); - if (!drw_fontset_create(drw, fonts, LENGTH(fonts))) - die("no fonts could be loaded."); - lrpad = drw->fonts->h + horizpadbar; - bh = drw->fonts->h + vertpadbar; - updategeom(); - /* init atoms */ - utf8string = XInternAtom(dpy, "UTF8_STRING", False); - wmatom[WMProtocols] = XInternAtom(dpy, "WM_PROTOCOLS", False); - wmatom[WMDelete] = XInternAtom(dpy, "WM_DELETE_WINDOW", False); - wmatom[WMState] = XInternAtom(dpy, "WM_STATE", False); - wmatom[WMTakeFocus] = XInternAtom(dpy, "WM_TAKE_FOCUS", False); - netatom[NetActiveWindow] = XInternAtom(dpy, "_NET_ACTIVE_WINDOW", False); - netatom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False); - netatom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False); - netatom[NetWMState] = XInternAtom(dpy, "_NET_WM_STATE", False); - netatom[NetWMCheck] = XInternAtom(dpy, "_NET_SUPPORTING_WM_CHECK", False); - netatom[NetWMFullscreen] = XInternAtom(dpy, "_NET_WM_STATE_FULLSCREEN", False); - netatom[NetWMWindowType] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE", False); - netatom[NetWMWindowTypeDialog] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DIALOG", False); - netatom[NetClientList] = XInternAtom(dpy, "_NET_CLIENT_LIST", False); - /* init cursors */ - cursor[CurNormal] = drw_cur_create(drw, XC_left_ptr); - cursor[CurResize] = drw_cur_create(drw, XC_sizing); - cursor[CurMove] = drw_cur_create(drw, XC_fleur); - /* init appearance */ - scheme = ecalloc(LENGTH(colors), sizeof(Clr *)); - for (i = 0; i < LENGTH(colors); i++) - scheme[i] = drw_scm_create(drw, colors[i], alphas[i], 3); - /* init bars */ - updatebars(); - updatestatus(); - /* supporting window for NetWMCheck */ - wmcheckwin = XCreateSimpleWindow(dpy, root, 0, 0, 1, 1, 0, 0, 0); - XChangeProperty(dpy, wmcheckwin, netatom[NetWMCheck], XA_WINDOW, 32, - PropModeReplace, (unsigned char *) &wmcheckwin, 1); - XChangeProperty(dpy, wmcheckwin, netatom[NetWMName], utf8string, 8, - PropModeReplace, (unsigned char *) "dwm", 3); - XChangeProperty(dpy, root, netatom[NetWMCheck], XA_WINDOW, 32, - PropModeReplace, (unsigned char *) &wmcheckwin, 1); - /* EWMH support per view */ - XChangeProperty(dpy, root, netatom[NetSupported], XA_ATOM, 32, - PropModeReplace, (unsigned char *) netatom, NetLast); - XDeleteProperty(dpy, root, netatom[NetClientList]); - /* select events */ - wa.cursor = cursor[CurNormal]->cursor; - wa.event_mask = SubstructureRedirectMask|SubstructureNotifyMask - |ButtonPressMask|PointerMotionMask|EnterWindowMask - |LeaveWindowMask|StructureNotifyMask|PropertyChangeMask; - XChangeWindowAttributes(dpy, root, CWEventMask|CWCursor, &wa); - XSelectInput(dpy, root, wa.event_mask); - grabkeys(); - focus(NULL); -} - - -void -seturgent(Client *c, int urg) -{ - XWMHints *wmh; - - c->isurgent = urg; - if (!(wmh = XGetWMHints(dpy, c->win))) - return; - wmh->flags = urg ? (wmh->flags | XUrgencyHint) : (wmh->flags & ~XUrgencyHint); - XSetWMHints(dpy, c->win, wmh); - XFree(wmh); -} - -void -showhide(Client *c) -{ - if (!c) - return; - if (ISVISIBLE(c)) { - /* show clients top down */ - XMoveWindow(dpy, c->win, c->x, c->y); - if ((!c->mon->lt[c->mon->sellt]->arrange || c->isfloating) && !c->isfullscreen) - resize(c, c->x, c->y, c->w, c->h, 0); - showhide(c->snext); - } else { - /* hide clients bottom up */ - showhide(c->snext); - XMoveWindow(dpy, c->win, WIDTH(c) * -2, c->y); - } -} - -void -sigchld(int unused) -{ - if (signal(SIGCHLD, sigchld) == SIG_ERR) - die("can't install SIGCHLD handler:"); - while (0 < waitpid(-1, NULL, WNOHANG)); -} - -void -sighup(int unused) -{ - Arg a = {.i = 1}; - quit(&a); -} - -void -sigterm(int unused) -{ - Arg a = {.i = 0}; - quit(&a); -} - -void -spawn(const Arg *arg) -{ - if (arg->v == dmenucmd) - dmenumon[0] = '0' + selmon->num; - if (fork() == 0) { - if (dpy) - close(ConnectionNumber(dpy)); - setsid(); - execvp(((char **)arg->v)[0], (char **)arg->v); - fprintf(stderr, "dwm: execvp %s", ((char **)arg->v)[0]); - perror(" failed"); - exit(EXIT_SUCCESS); - } -} - -void -tag(const Arg *arg) -{ - if (selmon->sel && arg->ui & TAGMASK) { - selmon->sel->tags = arg->ui & TAGMASK; - focus(NULL); - arrange(selmon); - } -} - -void -tagmon(const Arg *arg) -{ - if (!selmon->sel || !mons->next) - return; - sendmon(selmon->sel, dirtomon(arg->i)); -} - -void -tile(Monitor *m) -{ - unsigned int i, n, h, mw, my, ty; - Client *c; - - for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); - if (n == 0) - return; - - if (n > m->nmaster) - mw = m->nmaster ? m->ww * m->mfact : 0; - else - mw = m->ww; - for (i = my = ty = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) - if (i < m->nmaster) { - h = (m->wh - my) / (MIN(n, m->nmaster) - i); - resize(c, m->wx, m->wy + my, mw - (2*c->bw), h - (2*c->bw), 0); - my += HEIGHT(c); - } else { - h = (m->wh - ty) / (n - i); - resize(c, m->wx + mw, m->wy + ty, m->ww - mw - (2*c->bw), h - (2*c->bw), 0); - ty += HEIGHT(c); - } -} - -void -togglebar(const Arg *arg) -{ - selmon->showbar = !selmon->showbar; - updatebarpos(selmon); - XMoveResizeWindow(dpy, selmon->barwin, selmon->wx, selmon->by, selmon->ww, bh); - arrange(selmon); -} - -void -togglefloating(const Arg *arg) -{ - if (!selmon->sel) - return; - if (selmon->sel->isfullscreen) /* no support for fullscreen windows */ - return; - selmon->sel->isfloating = !selmon->sel->isfloating || selmon->sel->isfixed; - if (selmon->sel->isfloating) - resize(selmon->sel, selmon->sel->x, selmon->sel->y, - selmon->sel->w, selmon->sel->h, 0); - arrange(selmon); -} - -void -toggletag(const Arg *arg) -{ - unsigned int newtags; - - if (!selmon->sel) - return; - newtags = selmon->sel->tags ^ (arg->ui & TAGMASK); - if (newtags) { - selmon->sel->tags = newtags; - focus(NULL); - arrange(selmon); - } -} - -void -toggleview(const Arg *arg) -{ - unsigned int newtagset = selmon->tagset[selmon->seltags] ^ (arg->ui & TAGMASK); - - if (newtagset) { - selmon->tagset[selmon->seltags] = newtagset; - focus(NULL); - arrange(selmon); - } -} - -void -unfocus(Client *c, int setfocus) -{ - if (!c) - return; - grabbuttons(c, 0); - XSetWindowBorder(dpy, c->win, scheme[SchemeNorm][ColBorder].pixel); - if (setfocus) { - XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime); - XDeleteProperty(dpy, root, netatom[NetActiveWindow]); - } -} - -void -unmanage(Client *c, int destroyed) -{ - Monitor *m = c->mon; - XWindowChanges wc; - - detach(c); - detachstack(c); - if (!destroyed) { - wc.border_width = c->oldbw; - XGrabServer(dpy); /* avoid race conditions */ - XSetErrorHandler(xerrordummy); - XConfigureWindow(dpy, c->win, CWBorderWidth, &wc); /* restore border */ - XUngrabButton(dpy, AnyButton, AnyModifier, c->win); - setclientstate(c, WithdrawnState); - XSync(dpy, False); - XSetErrorHandler(xerror); - XUngrabServer(dpy); - } - free(c); - focus(NULL); - updateclientlist(); - arrange(m); -} - -void -unmapnotify(XEvent *e) -{ - Client *c; - XUnmapEvent *ev = &e->xunmap; - - if ((c = wintoclient(ev->window))) { - if (ev->send_event) - setclientstate(c, WithdrawnState); - else - unmanage(c, 0); - } -} - -void -updatebars(void) -{ - Monitor *m; - XSetWindowAttributes wa = { - .override_redirect = True, - .background_pixel = 0, - .border_pixel = 0, - .colormap = cmap, - .event_mask = ButtonPressMask|ExposureMask - }; - XClassHint ch = {"dwm", "dwm"}; - for (m = mons; m; m = m->next) { - if (m->barwin) - continue; - m->barwin = XCreateWindow(dpy, root, m->wx, m->by, m->ww, bh, 0, depth, - InputOutput, visual, - CWOverrideRedirect|CWBackPixel|CWBorderPixel|CWColormap|CWEventMask, &wa); - XDefineCursor(dpy, m->barwin, cursor[CurNormal]->cursor); - XMapRaised(dpy, m->barwin); - XSetClassHint(dpy, m->barwin, &ch); - } -} - -void -updatebarpos(Monitor *m) -{ - m->wy = m->my; - m->wh = m->mh; - if (m->showbar) { - m->wh -= bh; - m->by = m->topbar ? m->wy : m->wy + m->wh; - m->wy = m->topbar ? m->wy + bh : m->wy; - } else - m->by = -bh; -} - -void -updateclientlist() -{ - Client *c; - Monitor *m; - - XDeleteProperty(dpy, root, netatom[NetClientList]); - for (m = mons; m; m = m->next) - for (c = m->clients; c; c = c->next) - XChangeProperty(dpy, root, netatom[NetClientList], - XA_WINDOW, 32, PropModeAppend, - (unsigned char *) &(c->win), 1); -} - -int -updategeom(void) -{ - int dirty = 0; - -#ifdef XINERAMA - if (XineramaIsActive(dpy)) { - int i, j, n, nn; - Client *c; - Monitor *m; - XineramaScreenInfo *info = XineramaQueryScreens(dpy, &nn); - XineramaScreenInfo *unique = NULL; - - for (n = 0, m = mons; m; m = m->next, n++); - /* only consider unique geometries as separate screens */ - unique = ecalloc(nn, sizeof(XineramaScreenInfo)); - for (i = 0, j = 0; i < nn; i++) - if (isuniquegeom(unique, j, &info[i])) - memcpy(&unique[j++], &info[i], sizeof(XineramaScreenInfo)); - XFree(info); - nn = j; - if (n <= nn) { /* new monitors available */ - for (i = 0; i < (nn - n); i++) { - for (m = mons; m && m->next; m = m->next); - if (m) - m->next = createmon(); - else - mons = createmon(); - } - for (i = 0, m = mons; i < nn && m; m = m->next, i++) - if (i >= n - || unique[i].x_org != m->mx || unique[i].y_org != m->my - || unique[i].width != m->mw || unique[i].height != m->mh) - { - dirty = 1; - m->num = i; - m->mx = m->wx = unique[i].x_org; - m->my = m->wy = unique[i].y_org; - m->mw = m->ww = unique[i].width; - m->mh = m->wh = unique[i].height; - updatebarpos(m); - } - } else { /* less monitors available nn < n */ - for (i = nn; i < n; i++) { - for (m = mons; m && m->next; m = m->next); - while ((c = m->clients)) { - dirty = 1; - m->clients = c->next; - detachstack(c); - c->mon = mons; - attach(c); - attachaside(c); - attachstack(c); - } - if (m == selmon) - selmon = mons; - cleanupmon(m); - } - } - free(unique); - } else -#endif /* XINERAMA */ - { /* default monitor setup */ - if (!mons) - mons = createmon(); - if (mons->mw != sw || mons->mh != sh) { - dirty = 1; - mons->mw = mons->ww = sw; - mons->mh = mons->wh = sh; - updatebarpos(mons); - } - } - if (dirty) { - selmon = mons; - selmon = wintomon(root); - } - return dirty; -} - -void -updatenumlockmask(void) -{ - unsigned int i, j; - XModifierKeymap *modmap; - - numlockmask = 0; - modmap = XGetModifierMapping(dpy); - for (i = 0; i < 8; i++) - for (j = 0; j < modmap->max_keypermod; j++) - if (modmap->modifiermap[i * modmap->max_keypermod + j] - == XKeysymToKeycode(dpy, XK_Num_Lock)) - numlockmask = (1 << i); - XFreeModifiermap(modmap); -} - -void -updatesizehints(Client *c) -{ - long msize; - XSizeHints size; - - if (!XGetWMNormalHints(dpy, c->win, &size, &msize)) - /* size is uninitialized, ensure that size.flags aren't used */ - size.flags = PSize; - if (size.flags & PBaseSize) { - c->basew = size.base_width; - c->baseh = size.base_height; - } else if (size.flags & PMinSize) { - c->basew = size.min_width; - c->baseh = size.min_height; - } else - c->basew = c->baseh = 0; - if (size.flags & PResizeInc) { - c->incw = size.width_inc; - c->inch = size.height_inc; - } else - c->incw = c->inch = 0; - if (size.flags & PMaxSize) { - c->maxw = size.max_width; - c->maxh = size.max_height; - } else - c->maxw = c->maxh = 0; - if (size.flags & PMinSize) { - c->minw = size.min_width; - c->minh = size.min_height; - } else if (size.flags & PBaseSize) { - c->minw = size.base_width; - c->minh = size.base_height; - } else - c->minw = c->minh = 0; - if (size.flags & PAspect) { - c->mina = (float)size.min_aspect.y / size.min_aspect.x; - c->maxa = (float)size.max_aspect.x / size.max_aspect.y; - } else - c->maxa = c->mina = 0.0; - c->isfixed = (c->maxw && c->maxh && c->maxw == c->minw && c->maxh == c->minh); -} - -void -updatestatus(void) -{ - if (!gettextprop(root, XA_WM_NAME, stext, sizeof(stext))) - strcpy(stext, "dwm-"VERSION); - drawbar(selmon); -} - -void -updatetitle(Client *c) -{ - if (!gettextprop(c->win, netatom[NetWMName], c->name, sizeof c->name)) - gettextprop(c->win, XA_WM_NAME, c->name, sizeof c->name); - if (c->name[0] == '\0') /* hack to mark broken clients */ - strcpy(c->name, broken); -} - -void -updatewindowtype(Client *c) -{ - Atom state = getatomprop(c, netatom[NetWMState]); - Atom wtype = getatomprop(c, netatom[NetWMWindowType]); - - if (state == netatom[NetWMFullscreen]) - setfullscreen(c, 1); - if (wtype == netatom[NetWMWindowTypeDialog]) - c->isfloating = 1; -} - -void -updatewmhints(Client *c) -{ - XWMHints *wmh; - - if ((wmh = XGetWMHints(dpy, c->win))) { - if (c == selmon->sel && wmh->flags & XUrgencyHint) { - wmh->flags &= ~XUrgencyHint; - XSetWMHints(dpy, c->win, wmh); - } else - c->isurgent = (wmh->flags & XUrgencyHint) ? 1 : 0; - if (wmh->flags & InputHint) - c->neverfocus = !wmh->input; - else - c->neverfocus = 0; - XFree(wmh); - } -} - -void -view(const Arg *arg) -{ - if ((arg->ui & TAGMASK) == selmon->tagset[selmon->seltags]) - return; - selmon->seltags ^= 1; /* toggle sel tagset */ - if (arg->ui & TAGMASK) - selmon->tagset[selmon->seltags] = arg->ui & TAGMASK; - focus(NULL); - arrange(selmon); -} - -Client * -wintoclient(Window w) -{ - Client *c; - Monitor *m; - - for (m = mons; m; m = m->next) - for (c = m->clients; c; c = c->next) - if (c->win == w) - return c; - return NULL; -} - -Monitor * -wintomon(Window w) -{ - int x, y; - Client *c; - Monitor *m; - - if (w == root && getrootptr(&x, &y)) - return recttomon(x, y, 1, 1); - for (m = mons; m; m = m->next) - if (w == m->barwin) - return m; - if ((c = wintoclient(w))) - return c->mon; - return selmon; -} - -/* There's no way to check accesses to destroyed windows, thus those cases are - * ignored (especially on UnmapNotify's). Other types of errors call Xlibs - * default error handler, which may call exit. */ -int -xerror(Display *dpy, XErrorEvent *ee) -{ - if (ee->error_code == BadWindow - || (ee->request_code == X_SetInputFocus && ee->error_code == BadMatch) - || (ee->request_code == X_PolyText8 && ee->error_code == BadDrawable) - || (ee->request_code == X_PolyFillRectangle && ee->error_code == BadDrawable) - || (ee->request_code == X_PolySegment && ee->error_code == BadDrawable) - || (ee->request_code == X_ConfigureWindow && ee->error_code == BadMatch) - || (ee->request_code == X_GrabButton && ee->error_code == BadAccess) - || (ee->request_code == X_GrabKey && ee->error_code == BadAccess) - || (ee->request_code == X_CopyArea && ee->error_code == BadDrawable)) - return 0; - fprintf(stderr, "dwm: fatal error: request code=%d, error code=%d\n", - ee->request_code, ee->error_code); - return xerrorxlib(dpy, ee); /* may call exit */ -} - -int -xerrordummy(Display *dpy, XErrorEvent *ee) -{ - return 0; -} - -/* Startup Error handler to check if another window manager - * is already running. */ -int -xerrorstart(Display *dpy, XErrorEvent *ee) -{ - die("dwm: another window manager is already running"); - return -1; -} - -void -xinitvisual() -{ - XVisualInfo *infos; - XRenderPictFormat *fmt; - int nitems; - int i; - - XVisualInfo tpl = { - .screen = screen, - .depth = 32, - .class = TrueColor - }; - long masks = VisualScreenMask | VisualDepthMask | VisualClassMask; - - infos = XGetVisualInfo(dpy, masks, &tpl, &nitems); - visual = NULL; - for(i = 0; i < nitems; i ++) { - fmt = XRenderFindVisualFormat(dpy, infos[i].visual); - if (fmt->type == PictTypeDirect && fmt->direct.alphaMask) { - visual = infos[i].visual; - depth = infos[i].depth; - cmap = XCreateColormap(dpy, root, visual, AllocNone); - useargb = 1; - break; - } - } - - XFree(infos); - - if (! visual) { - visual = DefaultVisual(dpy, screen); - depth = DefaultDepth(dpy, screen); - cmap = DefaultColormap(dpy, screen); - } -} - -void -zoom(const Arg *arg) -{ - Client *c = selmon->sel; - - if (!selmon->lt[selmon->sellt]->arrange - || (selmon->sel && selmon->sel->isfloating)) - return; - if (c == nexttiled(selmon->clients)) - if (!c || !(c = nexttiled(c->next))) - return; - pop(c); -} - -int -main(int argc, char *argv[]) -{ - if (argc == 2 && !strcmp("-v", argv[1])) - die("dwm-"VERSION); - else if (argc != 1) - die("usage: dwm [-v]"); - if (!setlocale(LC_CTYPE, "") || !XSupportsLocale()) - fputs("warning: no locale support\n", stderr); - if (!(dpy = XOpenDisplay(NULL))) - die("dwm: cannot open display"); - checkotherwm(); - setup(); -#ifdef __OpenBSD__ - if (pledge("stdio rpath proc exec", NULL) == -1) - die("pledge"); -#endif /* __OpenBSD__ */ - scan(); - runAutostart(); - run(); - if(restart) execvp(argv[0], argv); - cleanup(); - XCloseDisplay(dpy); - return EXIT_SUCCESS; -} diff --git a/dwm/dwm.c.orig b/dwm/dwm.c.orig deleted file mode 100755 index be182ae..0000000 --- a/dwm/dwm.c.orig +++ /dev/null @@ -1,2356 +0,0 @@ -/* See LICENSE file for copyright and license details. - * - * dynamic window manager is designed like any other X client as well. It is - * driven through handling X events. In contrast to other X clients, a window - * manager selects for SubstructureRedirectMask on the root window, to receive - * events about window (dis-)appearance. Only one X connection at a time is - * allowed to select for this event mask. - * - * The event handlers of dwm are organized in an array which is accessed - * whenever a new event has been fetched. This allows event dispatching - * in O(1) time. - * - * Each child of the root window is called a client, except windows which have - * set the override_redirect flag. Clients are organized in a linked client - * list on each monitor, the focus history is remembered through a stack list - * on each monitor. Each client contains a bit array to indicate the tags of a - * client. - * - * Keys and tagging rules are organized as arrays and defined in config.h. - * - * To understand everything else, start reading main(). - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef XINERAMA -#include -#endif /* XINERAMA */ -#include - -#include "drw.h" -#include "util.h" - -/* macros */ -#define BUTTONMASK (ButtonPressMask|ButtonReleaseMask) -#define CLEANMASK(mask) (mask & ~(numlockmask|LockMask) & (ShiftMask|ControlMask|Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask)) -#define INTERSECT(x,y,w,h,m) (MAX(0, MIN((x)+(w),(m)->wx+(m)->ww) - MAX((x),(m)->wx)) \ - * MAX(0, MIN((y)+(h),(m)->wy+(m)->wh) - MAX((y),(m)->wy))) -#define 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 + gappx) -#define HEIGHT(X) ((X)->h + 2 * (X)->bw + gappx) -#define TAGMASK ((1 << LENGTH(tags)) - 1) -#define TEXTW(X) (drw_fontset_getwidth(drw, (X)) + lrpad) - -#define OPAQUE 0xffU - -/* enums */ -enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */ -enum { SchemeNorm, SchemeSel }; /* color schemes */ -enum { NetSupported, NetWMName, NetWMState, NetWMCheck, - NetWMFullscreen, NetActiveWindow, NetWMWindowType, - NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH atoms */ -enum { WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast }; /* default atoms */ -enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, - ClkClientWin, ClkRootWin, ClkLast }; /* clicks */ - -typedef union { - int i; - unsigned int ui; - float f; - const void *v; -} Arg; - -typedef struct { - unsigned int click; - unsigned int mask; - unsigned int button; - void (*func)(const Arg *arg); - const Arg arg; -} Button; - -typedef struct Monitor Monitor; -typedef struct Client Client; -struct Client { - char name[256]; - float mina, maxa; - int x, y, w, h; - int oldx, oldy, oldw, oldh; - int basew, baseh, incw, inch, maxw, maxh, minw, minh; - int bw, oldbw; - unsigned int tags; - int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen; - Client *next; - Client *snext; - Monitor *mon; - Window win; -}; - -typedef struct { - unsigned int mod; - KeySym keysym; - void (*func)(const Arg *); - const Arg arg; -} Key; - -typedef struct { - const char *symbol; - void (*arrange)(Monitor *); -} Layout; - -struct Monitor { - char ltsymbol[16]; - float mfact; - int nmaster; - int num; - int by; /* bar geometry */ - int mx, my, mw, mh; /* screen size */ - int wx, wy, ww, wh; /* window area */ - unsigned int seltags; - unsigned int sellt; - unsigned int tagset[2]; - int showbar; - int topbar; - Client *clients; - Client *sel; - Client *stack; - Monitor *next; - Window barwin; - const Layout *lt[2]; -}; - -typedef struct { - const char *class; - const char *instance; - const char *title; - unsigned int tags; - int isfloating; - int monitor; -} Rule; - -/* function declarations */ -static void applyrules(Client *c); -static int applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact); -static void arrange(Monitor *m); -static void arrangemon(Monitor *m); -static void attach(Client *c); -static void attachaside(Client *c); -static void attachstack(Client *c); -static void buttonpress(XEvent *e); -static void checkotherwm(void); -static void cleanup(void); -static void cleanupmon(Monitor *mon); -static void clientmessage(XEvent *e); -static void configure(Client *c); -static void configurenotify(XEvent *e); -static void configurerequest(XEvent *e); -static Monitor *createmon(void); -static void cyclelayout(const Arg *arg); -static void destroynotify(XEvent *e); -static void detach(Client *c); -static void detachstack(Client *c); -static Monitor *dirtomon(int dir); -static void drawbar(Monitor *m); -static void drawbars(void); -static void enqueue(Client *c); -static void enqueuestack(Client *c); -static void enternotify(XEvent *e); -static void expose(XEvent *e); -static void focus(Client *c); -static void focusin(XEvent *e); -static void focusmon(const Arg *arg); -static void focusstack(const Arg *arg); -static int getrootptr(int *x, int *y); -static long getstate(Window w); -static int gettextprop(Window w, Atom atom, char *text, unsigned int size); -static void grabbuttons(Client *c, int focused); -static void grabkeys(void); -static void incnmaster(const Arg *arg); -static void keypress(XEvent *e); -static void killclient(const Arg *arg); -static void manage(Window w, XWindowAttributes *wa); -static void mappingnotify(XEvent *e); -static void maprequest(XEvent *e); -static void monocle(Monitor *m); -static void motionnotify(XEvent *e); -static void movemouse(const Arg *arg); -static Client *nexttagged(Client *c); -static Client *nexttiled(Client *c); -static void pop(Client *); -static void propertynotify(XEvent *e); -static void quit(const Arg *arg); -static Monitor *recttomon(int x, int y, int w, int h); -static void resize(Client *c, int x, int y, int w, int h, int interact); -static void resizeclient(Client *c, int x, int y, int w, int h); -static void resizemouse(const Arg *arg); -static void restack(Monitor *m); -static void rotatestack(const Arg *arg); -static void run(void); -static void runAutostart(void); -static void scan(void); -static int sendevent(Client *c, Atom proto); -static void sendmon(Client *c, Monitor *m); -static void setclientstate(Client *c, long state); -static void setfocus(Client *c); -static void setfullscreen(Client *c, int fullscreen); -static void setlayout(const Arg *arg); -static void setmfact(const Arg *arg); -static void setup(void); -static void seturgent(Client *c, int urg); -static void showhide(Client *c); -static void sigchld(int unused); -static void spawn(const Arg *arg); -static void tag(const Arg *arg); -static void tagmon(const Arg *arg); -static void tile(Monitor *); -static void togglebar(const Arg *arg); -static void togglefloating(const Arg *arg); -static void toggletag(const Arg *arg); -static void toggleview(const Arg *arg); -static void unfocus(Client *c, int setfocus); -static void unmanage(Client *c, int destroyed); -static void unmapnotify(XEvent *e); -static void updatebarpos(Monitor *m); -static void updatebars(void); -static void updateclientlist(void); -static int updategeom(void); -static void updatenumlockmask(void); -static void updatesizehints(Client *c); -static void updatestatus(void); -static void updatetitle(Client *c); -static void 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 int xerror(Display *dpy, XErrorEvent *ee); -static int xerrordummy(Display *dpy, XErrorEvent *ee); -static int xerrorstart(Display *dpy, XErrorEvent *ee); -static void xinitvisual(); -static void zoom(const Arg *arg); - -/* variables */ -static const char broken[] = "broken"; -static char stext[256]; -static int screen; -static int sw, sh; /* X display screen geometry width, height */ -static int bh, blw = 0; /* bar geometry */ -static int lrpad; /* sum of left and right padding for text */ -static int (*xerrorxlib)(Display *, XErrorEvent *); -static unsigned int numlockmask = 0; -static void (*handler[LASTEvent]) (XEvent *) = { - [ButtonPress] = buttonpress, - [ClientMessage] = clientmessage, - [ConfigureRequest] = configurerequest, - [ConfigureNotify] = configurenotify, - [DestroyNotify] = destroynotify, - [EnterNotify] = enternotify, - [Expose] = expose, - [FocusIn] = focusin, - [KeyPress] = keypress, - [MappingNotify] = mappingnotify, - [MapRequest] = maprequest, - [MotionNotify] = motionnotify, - [PropertyNotify] = propertynotify, - [UnmapNotify] = unmapnotify -}; -static Atom wmatom[WMLast], netatom[NetLast]; -static int running = 1; -static Cur *cursor[CurLast]; -static Clr **scheme; -static Display *dpy; -static Drw *drw; -static Monitor *mons, *selmon; -static Window root, wmcheckwin; - -static int useargb = 0; -static Visual *visual; -static int depth; -static Colormap cmap; - -/* configuration, allows nested code to access above variables */ -#include "config.h" - -/* compile-time check if all tags fit into an unsigned int bit array. */ -struct NumTags { char limitexceeded[LENGTH(tags) > 31 ? -1 : 1]; }; - -/* function implementations */ -void -applyrules(Client *c) -{ - const char *class, *instance; - unsigned int i; - const Rule *r; - Monitor *m; - XClassHint ch = { NULL, NULL }; - - /* rule matching */ - c->isfloating = 0; - c->tags = 0; - XGetClassHint(dpy, c->win, &ch); - class = ch.res_class ? ch.res_class : broken; - instance = ch.res_name ? ch.res_name : broken; - - for (i = 0; i < LENGTH(rules); i++) { - r = &rules[i]; - if ((!r->title || strstr(c->name, r->title)) - && (!r->class || strstr(class, r->class)) - && (!r->instance || strstr(instance, r->instance))) - { - c->isfloating = r->isfloating; - c->tags |= r->tags; - for (m = mons; m && m->num != r->monitor; m = m->next); - if (m) - c->mon = m; - } - } - if (ch.res_class) - XFree(ch.res_class); - if (ch.res_name) - XFree(ch.res_name); - c->tags = c->tags & TAGMASK ? c->tags & TAGMASK : c->mon->tagset[c->mon->seltags]; -} - -int -applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact) -{ - int baseismin; - Monitor *m = c->mon; - - /* set minimum possible */ - *w = MAX(1, *w); - *h = MAX(1, *h); - if (interact) { - if (*x > sw) - *x = sw - WIDTH(c); - if (*y > sh) - *y = sh - HEIGHT(c); - if (*x + *w + 2 * c->bw < 0) - *x = 0; - if (*y + *h + 2 * c->bw < 0) - *y = 0; - } else { - if (*x >= m->wx + m->ww) - *x = m->wx + m->ww - WIDTH(c); - if (*y >= m->wy + m->wh) - *y = m->wy + m->wh - HEIGHT(c); - if (*x + *w + 2 * c->bw <= m->wx) - *x = m->wx; - if (*y + *h + 2 * c->bw <= m->wy) - *y = m->wy; - } - if (*h < bh) - *h = bh; - if (*w < bh) - *w = bh; - if (resizehints || c->isfloating || !c->mon->lt[c->mon->sellt]->arrange) { - /* see last two sentences in ICCCM 4.1.2.3 */ - baseismin = c->basew == c->minw && c->baseh == c->minh; - if (!baseismin) { /* temporarily remove base dimensions */ - *w -= c->basew; - *h -= c->baseh; - } - /* adjust for aspect limits */ - if (c->mina > 0 && c->maxa > 0) { - if (c->maxa < (float)*w / *h) - *w = *h * c->maxa + 0.5; - else if (c->mina < (float)*h / *w) - *h = *w * c->mina + 0.5; - } - if (baseismin) { /* increment calculation requires this */ - *w -= c->basew; - *h -= c->baseh; - } - /* adjust for increment value */ - if (c->incw) - *w -= *w % c->incw; - if (c->inch) - *h -= *h % c->inch; - /* restore base dimensions */ - *w = MAX(*w + c->basew, c->minw); - *h = MAX(*h + c->baseh, c->minh); - if (c->maxw) - *w = MIN(*w, c->maxw); - if (c->maxh) - *h = MIN(*h, c->maxh); - } - return *x != c->x || *y != c->y || *w != c->w || *h != c->h; -} - -void -arrange(Monitor *m) -{ - if (m) - showhide(m->stack); - else for (m = mons; m; m = m->next) - showhide(m->stack); - if (m) { - arrangemon(m); - restack(m); - } else for (m = mons; m; m = m->next) - arrangemon(m); -} - -void -arrangemon(Monitor *m) -{ - strncpy(m->ltsymbol, m->lt[m->sellt]->symbol, sizeof m->ltsymbol); - if (m->lt[m->sellt]->arrange) - m->lt[m->sellt]->arrange(m); -} - -void -attach(Client *c) -{ - c->next = c->mon->clients; - c->mon->clients = c; -} - -void -attachaside(Client *c) { - Client *at = nexttagged(c); - if(!at) { - attach(c); - return; - } - c->next = at->next; - at->next = c; -} - - -void -attachstack(Client *c) -{ - c->snext = c->mon->stack; - c->mon->stack = c; -} - -void -buttonpress(XEvent *e) -{ - unsigned int i, x, click; - Arg arg = {0}; - Client *c; - Monitor *m; - XButtonPressedEvent *ev = &e->xbutton; - - click = ClkRootWin; - /* focus monitor if necessary */ - if ((m = wintomon(ev->window)) && m != selmon) { - unfocus(selmon->sel, 1); - selmon = m; - focus(NULL); - } - if (ev->window == selmon->barwin) { - i = x = 0; - do - x += TEXTW(tags[i]); - while (ev->x >= x && ++i < LENGTH(tags)); - if (i < LENGTH(tags)) { - click = ClkTagBar; - arg.ui = 1 << i; - } else if (ev->x < x + blw) - click = ClkLtSymbol; - else if (ev->x > selmon->ww - TEXTW(stext)) - click = ClkStatusText; - else - click = ClkWinTitle; - } else if ((c = wintoclient(ev->window))) { - focus(c); - restack(selmon); - XAllowEvents(dpy, ReplayPointer, CurrentTime); - click = ClkClientWin; - } - for (i = 0; i < LENGTH(buttons); i++) - if (click == buttons[i].click && buttons[i].func && buttons[i].button == ev->button - && CLEANMASK(buttons[i].mask) == CLEANMASK(ev->state)) - buttons[i].func(click == ClkTagBar && buttons[i].arg.i == 0 ? &arg : &buttons[i].arg); -} - -void -checkotherwm(void) -{ - xerrorxlib = XSetErrorHandler(xerrorstart); - /* this causes an error if some other window manager is running */ - XSelectInput(dpy, DefaultRootWindow(dpy), SubstructureRedirectMask); - XSync(dpy, False); - XSetErrorHandler(xerror); - XSync(dpy, False); -} - -void -cleanup(void) -{ - Arg a = {.ui = ~0}; - Layout foo = { "", NULL }; - Monitor *m; - size_t i; - - view(&a); - selmon->lt[selmon->sellt] = &foo; - for (m = mons; m; m = m->next) - while (m->stack) - unmanage(m->stack, 0); - XUngrabKey(dpy, AnyKey, AnyModifier, root); - while (mons) - cleanupmon(mons); - for (i = 0; i < CurLast; i++) - drw_cur_free(drw, cursor[i]); - for (i = 0; i < LENGTH(colors); i++) - free(scheme[i]); - XDestroyWindow(dpy, wmcheckwin); - drw_free(drw); - XSync(dpy, False); - XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime); - XDeleteProperty(dpy, root, netatom[NetActiveWindow]); -} - -void -cleanupmon(Monitor *mon) -{ - Monitor *m; - - if (mon == mons) - mons = mons->next; - else { - for (m = mons; m && m->next != mon; m = m->next); - m->next = mon->next; - } - XUnmapWindow(dpy, mon->barwin); - XDestroyWindow(dpy, mon->barwin); - free(mon); -} - -void -clientmessage(XEvent *e) -{ - XClientMessageEvent *cme = &e->xclient; - Client *c = wintoclient(cme->window); - - if (!c) - return; - if (cme->message_type == netatom[NetWMState]) { - if (cme->data.l[1] == netatom[NetWMFullscreen] - || cme->data.l[2] == netatom[NetWMFullscreen]) - setfullscreen(c, (cme->data.l[0] == 1 /* _NET_WM_STATE_ADD */ - || (cme->data.l[0] == 2 /* _NET_WM_STATE_TOGGLE */ && !c->isfullscreen))); - } else if (cme->message_type == netatom[NetActiveWindow]) { - if (c != selmon->sel && !c->isurgent) - seturgent(c, 1); - } -} - -void -configure(Client *c) -{ - XConfigureEvent ce; - - ce.type = ConfigureNotify; - ce.display = dpy; - ce.event = c->win; - ce.window = c->win; - ce.x = c->x; - ce.y = c->y; - ce.width = c->w; - ce.height = c->h; - ce.border_width = c->bw; - ce.above = None; - ce.override_redirect = False; - XSendEvent(dpy, c->win, False, StructureNotifyMask, (XEvent *)&ce); -} - -void -configurenotify(XEvent *e) -{ - Monitor *m; - Client *c; - XConfigureEvent *ev = &e->xconfigure; - int dirty; - - /* TODO: updategeom handling sucks, needs to be simplified */ - if (ev->window == root) { - dirty = (sw != ev->width || sh != ev->height); - sw = ev->width; - sh = ev->height; - if (updategeom() || dirty) { - drw_resize(drw, sw, bh); - updatebars(); - for (m = mons; m; m = m->next) { - for (c = m->clients; c; c = c->next) - if (c->isfullscreen) - resizeclient(c, m->mx, m->my, m->mw, m->mh); - XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, bh); - } - focus(NULL); - arrange(NULL); - } - } -} - -void -configurerequest(XEvent *e) -{ - Client *c; - Monitor *m; - XConfigureRequestEvent *ev = &e->xconfigurerequest; - XWindowChanges wc; - - if ((c = wintoclient(ev->window))) { - if (ev->value_mask & CWBorderWidth) - c->bw = ev->border_width; - else if (c->isfloating || !selmon->lt[selmon->sellt]->arrange) { - m = c->mon; - if (ev->value_mask & CWX) { - c->oldx = c->x; - c->x = m->mx + ev->x; - } - if (ev->value_mask & CWY) { - c->oldy = c->y; - c->y = m->my + ev->y; - } - if (ev->value_mask & CWWidth) { - c->oldw = c->w; - c->w = ev->width; - } - if (ev->value_mask & CWHeight) { - c->oldh = c->h; - c->h = ev->height; - } - if ((c->x + c->w) > m->mx + m->mw && c->isfloating) - c->x = m->mx + (m->mw / 2 - WIDTH(c) / 2); /* center in x direction */ - if ((c->y + c->h) > m->my + m->mh && c->isfloating) - c->y = m->my + (m->mh / 2 - HEIGHT(c) / 2); /* center in y direction */ - if ((ev->value_mask & (CWX|CWY)) && !(ev->value_mask & (CWWidth|CWHeight))) - configure(c); - if (ISVISIBLE(c)) - XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h); - } else - configure(c); - } else { - wc.x = ev->x; - wc.y = ev->y; - wc.width = ev->width; - wc.height = ev->height; - wc.border_width = ev->border_width; - wc.sibling = ev->above; - wc.stack_mode = ev->detail; - XConfigureWindow(dpy, ev->window, ev->value_mask, &wc); - } - XSync(dpy, False); -} - -Monitor * -createmon(void) -{ - Monitor *m; - - m = ecalloc(1, sizeof(Monitor)); - m->tagset[0] = m->tagset[1] = 1; - m->mfact = mfact; - m->nmaster = nmaster; - m->showbar = showbar; - m->topbar = topbar; - m->lt[0] = &layouts[0]; - m->lt[1] = &layouts[1 % LENGTH(layouts)]; - strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol); - return m; -} - -void -cyclelayout(const Arg *arg) { - Layout *l; - for(l = (Layout *)layouts; l != selmon->lt[selmon->sellt]; l++); - if(arg->i > 0) { - if(l->symbol && (l + 1)->symbol) - setlayout(&((Arg) { .v = (l + 1) })); - else - setlayout(&((Arg) { .v = layouts })); - } else { - if(l != layouts && (l - 1)->symbol) - setlayout(&((Arg) { .v = (l - 1) })); - else - setlayout(&((Arg) { .v = &layouts[LENGTH(layouts) - 2] })); - } -} - -void -destroynotify(XEvent *e) -{ - Client *c; - XDestroyWindowEvent *ev = &e->xdestroywindow; - - if ((c = wintoclient(ev->window))) - unmanage(c, 1); -} - -void -detach(Client *c) -{ - Client **tc; - - for (tc = &c->mon->clients; *tc && *tc != c; tc = &(*tc)->next); - *tc = c->next; -} - -void -detachstack(Client *c) -{ - Client **tc, *t; - - for (tc = &c->mon->stack; *tc && *tc != c; tc = &(*tc)->snext); - *tc = c->snext; - - if (c == c->mon->sel) { - for (t = c->mon->stack; t && !ISVISIBLE(t); t = t->snext); - c->mon->sel = t; - } -} - -Monitor * -dirtomon(int dir) -{ - Monitor *m = NULL; - - if (dir > 0) { - if (!(m = selmon->next)) - m = mons; - } else if (selmon == mons) - for (m = mons; m->next; m = m->next); - else - for (m = mons; m->next != selmon; m = m->next); - return m; -} - -void -drawbar(Monitor *m) -{ - int x, w, sw = 0, tw, mw, ew = 0; - int boxs = drw->fonts->h / 9; - int boxw = drw->fonts->h / 6 + 2; - unsigned int i, occ = 0, urg = 0, n = 0; - Client *c; - - /* draw status first so it can be overdrawn by tags later */ - if (m == selmon) { /* status is only drawn on selected monitor */ - drw_setscheme(drw, scheme[SchemeNorm]); - sw = TEXTW(stext); - drw_text(drw, m->ww - sw, 0, sw, bh, lrpad / 2, stext, 0); - } - - for (c = m->clients; c; c = c->next) { - if (ISVISIBLE(c)) - n++; - occ |= c->tags; - if (c->isurgent) - urg |= c->tags; - } - 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_text(drw, x, 0, w, bh, lrpad / 2, tags[i], urg & 1 << i); - if (occ & 1 << i) - drw_rect(drw, x + boxs, boxs, boxw, boxw, - m == selmon && selmon->sel && selmon->sel->tags & 1 << i, - urg & 1 << i); - x += w; - } - w = blw = TEXTW(m->ltsymbol); - drw_setscheme(drw, scheme[SchemeNorm]); - x = drw_text(drw, x, 0, w, bh, lrpad / 2, m->ltsymbol, 0); - - if ((w = m->ww - sw - x) > bh) { - if (n > 0) { - tw = TEXTW(m->sel->name) + lrpad; - mw = (tw >= w || n == 1) ? 0 : (w - tw) / (n - 1); - - i = 0; - for (c = m->clients; c; c = c->next) { - if (!ISVISIBLE(c) || c == m->sel) - continue; - tw = TEXTW(c->name); - if(tw < mw) - ew += (mw - tw); - else - i++; - } - if (i > 0) - mw += ew / i; - - for (c = m->clients; c; c = c->next) { - if (!ISVISIBLE(c)) - continue; - tw = MIN(m->sel == c ? w : mw, TEXTW(c->name)); - - drw_setscheme(drw, scheme[m->sel == c ? SchemeSel : SchemeNorm]); - if (tw > 0) /* trap special handling of 0 in drw_text */ - drw_text(drw, x, 0, tw, bh, lrpad / 2, c->name, 0); - if (c->isfloating) - drw_rect(drw, x + boxs, boxs, boxw, boxw, c->isfixed, 0); - x += tw; - w -= tw; - } - } - drw_setscheme(drw, scheme[SchemeNorm]); - drw_rect(drw, x, 0, w, bh, 1, 1); - } - drw_map(drw, m->barwin, 0, 0, m->ww, bh); -} - -void -drawbars(void) -{ - Monitor *m; - - for (m = mons; m; m = m->next) - drawbar(m); -} - -void -enqueue(Client *c) -{ - Client *l; - for (l = c->mon->clients; l && l->next; l = l->next); - if (l) { - l->next = c; - c->next = NULL; - } -} - -void -enqueuestack(Client *c) -{ - Client *l; - for (l = c->mon->stack; l && l->snext; l = l->snext); - if (l) { - l->snext = c; - c->snext = NULL; - } -} - -void -enternotify(XEvent *e) -{ - Client *c; - Monitor *m; - XCrossingEvent *ev = &e->xcrossing; - - if ((ev->mode != NotifyNormal || ev->detail == NotifyInferior) && ev->window != root) - return; - c = wintoclient(ev->window); - m = c ? c->mon : wintomon(ev->window); - if (m != selmon) { - unfocus(selmon->sel, 1); - selmon = m; - } else if (!c || c == selmon->sel) - return; - focus(c); -} - -void -expose(XEvent *e) -{ - Monitor *m; - XExposeEvent *ev = &e->xexpose; - - if (ev->count == 0 && (m = wintomon(ev->window))) - drawbar(m); -} - -void -focus(Client *c) -{ - if (!c || !ISVISIBLE(c)) - for (c = selmon->stack; c && !ISVISIBLE(c); c = c->snext); - if (selmon->sel && selmon->sel != c) - unfocus(selmon->sel, 0); - if (c) { - if (c->mon != selmon) - selmon = c->mon; - if (c->isurgent) - seturgent(c, 0); - detachstack(c); - attachstack(c); - grabbuttons(c, 1); - XSetWindowBorder(dpy, c->win, scheme[SchemeSel][ColBorder].pixel); - setfocus(c); - } else { - XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime); - XDeleteProperty(dpy, root, netatom[NetActiveWindow]); - } - selmon->sel = c; - drawbars(); -} - -/* there are some broken focus acquiring clients needing extra handling */ -void -focusin(XEvent *e) -{ - XFocusChangeEvent *ev = &e->xfocus; - - if (selmon->sel && ev->window != selmon->sel->win) - setfocus(selmon->sel); -} - -void -focusmon(const Arg *arg) -{ - Monitor *m; - - if (!mons->next) - return; - if ((m = dirtomon(arg->i)) == selmon) - return; - unfocus(selmon->sel, 0); - selmon = m; - focus(NULL); -} - -void -focusstack(const Arg *arg) -{ - Client *c = NULL, *i; - - if (!selmon->sel) - 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); - } -} - -Atom -getatomprop(Client *c, Atom prop) -{ - int di; - unsigned long dl; - unsigned char *p = NULL; - Atom da, atom = None; - - if (XGetWindowProperty(dpy, c->win, prop, 0L, sizeof atom, False, XA_ATOM, - &da, &di, &dl, &dl, &p) == Success && p) { - atom = *(Atom *)p; - XFree(p); - } - return atom; -} - -int -getrootptr(int *x, int *y) -{ - int di; - unsigned int dui; - Window dummy; - - return XQueryPointer(dpy, root, &dummy, &dummy, x, y, &di, &di, &dui); -} - -long -getstate(Window w) -{ - int format; - long result = -1; - unsigned char *p = NULL; - unsigned long n, extra; - Atom real; - - if (XGetWindowProperty(dpy, w, wmatom[WMState], 0L, 2L, False, wmatom[WMState], - &real, &format, &n, &extra, (unsigned char **)&p) != Success) - return -1; - if (n != 0) - result = *p; - XFree(p); - return result; -} - -int -gettextprop(Window w, Atom atom, char *text, unsigned int size) -{ - char **list = NULL; - int n; - XTextProperty name; - - if (!text || size == 0) - return 0; - text[0] = '\0'; - if (!XGetTextProperty(dpy, w, &name, atom) || !name.nitems) - return 0; - if (name.encoding == XA_STRING) - strncpy(text, (char *)name.value, size - 1); - else { - if (XmbTextPropertyToTextList(dpy, &name, &list, &n) >= Success && n > 0 && *list) { - strncpy(text, *list, size - 1); - XFreeStringList(list); - } - } - text[size - 1] = '\0'; - XFree(name.value); - return 1; -} - -void -grabbuttons(Client *c, int focused) -{ - updatenumlockmask(); - { - unsigned int i, j; - unsigned int modifiers[] = { 0, LockMask, numlockmask, numlockmask|LockMask }; - XUngrabButton(dpy, AnyButton, AnyModifier, c->win); - if (!focused) - XGrabButton(dpy, AnyButton, AnyModifier, c->win, False, - BUTTONMASK, GrabModeSync, GrabModeSync, None, None); - for (i = 0; i < LENGTH(buttons); i++) - if (buttons[i].click == ClkClientWin) - for (j = 0; j < LENGTH(modifiers); j++) - XGrabButton(dpy, buttons[i].button, - buttons[i].mask | modifiers[j], - c->win, False, BUTTONMASK, - GrabModeAsync, GrabModeSync, None, None); - } -} - -void -grabkeys(void) -{ - updatenumlockmask(); - { - unsigned int i, j; - unsigned int modifiers[] = { 0, LockMask, numlockmask, numlockmask|LockMask }; - KeyCode code; - - XUngrabKey(dpy, AnyKey, AnyModifier, root); - for (i = 0; i < LENGTH(keys); i++) - if ((code = XKeysymToKeycode(dpy, keys[i].keysym))) - for (j = 0; j < LENGTH(modifiers); j++) - XGrabKey(dpy, code, keys[i].mod | modifiers[j], root, - True, GrabModeAsync, GrabModeAsync); - } -} - -void -incnmaster(const Arg *arg) -{ - selmon->nmaster = MAX(selmon->nmaster + arg->i, 0); - arrange(selmon); -} - -#ifdef XINERAMA -static int -isuniquegeom(XineramaScreenInfo *unique, size_t n, XineramaScreenInfo *info) -{ - while (n--) - if (unique[n].x_org == info->x_org && unique[n].y_org == info->y_org - && unique[n].width == info->width && unique[n].height == info->height) - return 0; - return 1; -} -#endif /* XINERAMA */ - -void -keypress(XEvent *e) -{ - unsigned int i; - KeySym keysym; - XKeyEvent *ev; - - ev = &e->xkey; - keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0); - for (i = 0; i < LENGTH(keys); i++) - if (keysym == keys[i].keysym - && CLEANMASK(keys[i].mod) == CLEANMASK(ev->state) - && keys[i].func) - keys[i].func(&(keys[i].arg)); -} - -void -killclient(const Arg *arg) -{ - if (!selmon->sel) - return; - if (!sendevent(selmon->sel, wmatom[WMDelete])) { - XGrabServer(dpy); - XSetErrorHandler(xerrordummy); - XSetCloseDownMode(dpy, DestroyAll); - XKillClient(dpy, selmon->sel->win); - XSync(dpy, False); - XSetErrorHandler(xerror); - XUngrabServer(dpy); - } -} - -void -manage(Window w, XWindowAttributes *wa) -{ - Client *c, *t = NULL; - Window trans = None; - XWindowChanges wc; - - c = ecalloc(1, sizeof(Client)); - c->win = w; - /* geometry */ - c->x = c->oldx = wa->x; - c->y = c->oldy = wa->y; - c->w = c->oldw = wa->width; - c->h = c->oldh = wa->height; - c->oldbw = wa->border_width; - - updatetitle(c); - if (XGetTransientForHint(dpy, w, &trans) && (t = wintoclient(trans))) { - c->mon = t->mon; - c->tags = t->tags; - } else { - c->mon = selmon; - applyrules(c); - } - - if (c->x + WIDTH(c) > c->mon->mx + c->mon->mw) - c->x = c->mon->mx + c->mon->mw - WIDTH(c); - if (c->y + HEIGHT(c) > c->mon->my + c->mon->mh) - c->y = c->mon->my + c->mon->mh - HEIGHT(c); - c->x = MAX(c->x, c->mon->mx); - /* only fix client y-offset, if the client center might cover the bar */ - c->y = MAX(c->y, ((c->mon->by == c->mon->my) && (c->x + (c->w / 2) >= c->mon->wx) - && (c->x + (c->w / 2) < c->mon->wx + c->mon->ww)) ? bh : c->mon->my); - c->bw = borderpx; - - wc.border_width = c->bw; - XConfigureWindow(dpy, w, CWBorderWidth, &wc); - XSetWindowBorder(dpy, w, scheme[SchemeNorm][ColBorder].pixel); - configure(c); /* propagates border_width, if size doesn't change */ - updatewindowtype(c); - updatesizehints(c); - updatewmhints(c); - XSelectInput(dpy, w, EnterWindowMask|FocusChangeMask|PropertyChangeMask|StructureNotifyMask); - grabbuttons(c, 0); - if (!c->isfloating) - c->isfloating = c->oldstate = trans != None || c->isfixed; - if (c->isfloating) - XRaiseWindow(dpy, c->win); - attachaside(c); - attachstack(c); - XChangeProperty(dpy, root, netatom[NetClientList], XA_WINDOW, 32, PropModeAppend, - (unsigned char *) &(c->win), 1); - XMoveResizeWindow(dpy, c->win, c->x + 2 * sw, c->y, c->w, c->h); /* some windows require this */ - setclientstate(c, NormalState); - if (c->mon == selmon) - unfocus(selmon->sel, 0); - c->mon->sel = c; - arrange(c->mon); - XMapWindow(dpy, c->win); - focus(NULL); -} - -void -mappingnotify(XEvent *e) -{ - XMappingEvent *ev = &e->xmapping; - - XRefreshKeyboardMapping(ev); - if (ev->request == MappingKeyboard) - grabkeys(); -} - -void -maprequest(XEvent *e) -{ - static XWindowAttributes wa; - XMapRequestEvent *ev = &e->xmaprequest; - - if (!XGetWindowAttributes(dpy, ev->window, &wa)) - return; - if (wa.override_redirect) - return; - if (!wintoclient(ev->window)) - manage(ev->window, &wa); -} - -void -monocle(Monitor *m) -{ - unsigned int n = 0; - Client *c; - - for (c = m->clients; c; c = c->next) - if (ISVISIBLE(c)) - n++; - if (n > 0) /* override layout symbol */ - snprintf(m->ltsymbol, sizeof m->ltsymbol, "[%d]", n); - for (c = nexttiled(m->clients); c; c = nexttiled(c->next)) - resize(c, m->wx, m->wy, m->ww - 2 * c->bw, m->wh - 2 * c->bw, 0); -} - -void -motionnotify(XEvent *e) -{ - static Monitor *mon = NULL; - Monitor *m; - XMotionEvent *ev = &e->xmotion; - - if (ev->window != root) - return; - if ((m = recttomon(ev->x_root, ev->y_root, 1, 1)) != mon && mon) { - unfocus(selmon->sel, 1); - selmon = m; - focus(NULL); - } - mon = m; -} - -void -movemouse(const Arg *arg) -{ - int x, y, ocx, ocy, nx, ny; - Client *c; - Monitor *m; - XEvent ev; - Time lasttime = 0; - - if (!(c = selmon->sel)) - return; - if (c->isfullscreen) /* no support moving fullscreen windows by mouse */ - return; - restack(selmon); - ocx = c->x; - ocy = c->y; - if (XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, - None, cursor[CurMove]->cursor, CurrentTime) != GrabSuccess) - return; - if (!getrootptr(&x, &y)) - return; - do { - XMaskEvent(dpy, MOUSEMASK|ExposureMask|SubstructureRedirectMask, &ev); - switch(ev.type) { - case ConfigureRequest: - case Expose: - case MapRequest: - handler[ev.type](&ev); - break; - case MotionNotify: - if ((ev.xmotion.time - lasttime) <= (1000 / 60)) - continue; - lasttime = ev.xmotion.time; - - nx = ocx + (ev.xmotion.x - x); - ny = ocy + (ev.xmotion.y - y); - if (abs(selmon->wx - nx) < snap) - nx = selmon->wx; - else if (abs((selmon->wx + selmon->ww) - (nx + WIDTH(c))) < snap) - nx = selmon->wx + selmon->ww - WIDTH(c); - if (abs(selmon->wy - ny) < snap) - ny = selmon->wy; - else if (abs((selmon->wy + selmon->wh) - (ny + HEIGHT(c))) < snap) - ny = selmon->wy + selmon->wh - HEIGHT(c); - if (!c->isfloating && selmon->lt[selmon->sellt]->arrange - && (abs(nx - c->x) > snap || abs(ny - c->y) > snap)) - togglefloating(NULL); - if (!selmon->lt[selmon->sellt]->arrange || c->isfloating) - resize(c, nx, ny, c->w, c->h, 1); - break; - } - } while (ev.type != ButtonRelease); - XUngrabPointer(dpy, CurrentTime); - if ((m = recttomon(c->x, c->y, c->w, c->h)) != selmon) { - sendmon(c, m); - selmon = m; - focus(NULL); - } -} - - Client * -nexttagged(Client *c) { - Client *walked = c->mon->clients; - for(; - walked && (walked->isfloating || !ISVISIBLEONTAG(walked, c->tags)); - walked = walked->next - ); - return walked; -} - -Client * -nexttiled(Client *c) -{ - for (; c && (c->isfloating || !ISVISIBLE(c)); c = c->next); - return c; -} - -void -pop(Client *c) -{ - detach(c); - attach(c); - focus(c); - arrange(c->mon); -} - -void -propertynotify(XEvent *e) -{ - Client *c; - Window trans; - XPropertyEvent *ev = &e->xproperty; - - if ((ev->window == root) && (ev->atom == XA_WM_NAME)) - updatestatus(); - else if (ev->state == PropertyDelete) - return; /* ignore */ - else if ((c = wintoclient(ev->window))) { - switch(ev->atom) { - default: break; - case XA_WM_TRANSIENT_FOR: - if (!c->isfloating && (XGetTransientForHint(dpy, c->win, &trans)) && - (c->isfloating = (wintoclient(trans)) != NULL)) - arrange(c->mon); - break; - case XA_WM_NORMAL_HINTS: - updatesizehints(c); - break; - case XA_WM_HINTS: - updatewmhints(c); - drawbars(); - break; - } - if (ev->atom == XA_WM_NAME || ev->atom == netatom[NetWMName]) { - updatetitle(c); - if (c == c->mon->sel) - drawbar(c->mon); - } - if (ev->atom == netatom[NetWMWindowType]) - updatewindowtype(c); - } -} - -void -quit(const Arg *arg) -{ - running = 0; -} - -Monitor * -recttomon(int x, int y, int w, int h) -{ - Monitor *m, *r = selmon; - int a, area = 0; - - for (m = mons; m; m = m->next) - if ((a = INTERSECT(x, y, w, h, m)) > area) { - area = a; - r = m; - } - return r; -} - -void -resize(Client *c, int x, int y, int w, int h, int interact) -{ - if (applysizehints(c, &x, &y, &w, &h, interact)) - resizeclient(c, x, y, w, h); -} - -void -resizeclient(Client *c, int x, int y, int w, int h) -{ - XWindowChanges wc; - unsigned int n; - unsigned int gapoffset; - unsigned int gapincr; - Client *nbc; - - wc.border_width = c->bw; - - /* Get number of clients for the selected monitor */ - for (n = 0, nbc = nexttiled(selmon->clients); nbc; nbc = nexttiled(nbc->next), n++); - - /* Do nothing if layout is floating */ - if (c->isfloating || selmon->lt[selmon->sellt]->arrange == NULL) { - gapincr = gapoffset = 0; - } else { - /* Remove border and gap if layout is monocle or only one client */ - if (selmon->lt[selmon->sellt]->arrange == monocle || n == 1) { - gapoffset = 0; - gapincr = -2 * borderpx; - wc.border_width = 0; - } else { - gapoffset = gappx; - gapincr = 2 * gappx; - } - } - - c->oldx = c->x; c->x = wc.x = x + gapoffset; - c->oldy = c->y; c->y = wc.y = y + gapoffset; - c->oldw = c->w; c->w = wc.width = w - gapincr; - c->oldh = c->h; c->h = wc.height = h - gapincr; - - XConfigureWindow(dpy, c->win, CWX|CWY|CWWidth|CWHeight|CWBorderWidth, &wc); - configure(c); - XSync(dpy, False); -} - -void -resizemouse(const Arg *arg) -{ - int ocx, ocy, nw, nh; - Client *c; - Monitor *m; - XEvent ev; - Time lasttime = 0; - - if (!(c = selmon->sel)) - return; - if (c->isfullscreen) /* no support resizing fullscreen windows by mouse */ - return; - restack(selmon); - ocx = c->x; - ocy = c->y; - 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); - do { - XMaskEvent(dpy, MOUSEMASK|ExposureMask|SubstructureRedirectMask, &ev); - switch(ev.type) { - case ConfigureRequest: - case Expose: - case MapRequest: - handler[ev.type](&ev); - break; - case MotionNotify: - if ((ev.xmotion.time - lasttime) <= (1000 / 60)) - continue; - lasttime = ev.xmotion.time; - - nw = MAX(ev.xmotion.x - ocx - 2 * c->bw + 1, 1); - nh = MAX(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) - { - if (!c->isfloating && selmon->lt[selmon->sellt]->arrange - && (abs(nw - c->w) > snap || abs(nh - c->h) > snap)) - togglefloating(NULL); - } - if (!selmon->lt[selmon->sellt]->arrange || c->isfloating) - resize(c, c->x, c->y, 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); - XUngrabPointer(dpy, CurrentTime); - while (XCheckMaskEvent(dpy, EnterWindowMask, &ev)); - if ((m = recttomon(c->x, c->y, c->w, c->h)) != selmon) { - sendmon(c, m); - selmon = m; - focus(NULL); - } -} - -void -restack(Monitor *m) -{ - Client *c; - XEvent ev; - XWindowChanges wc; - - drawbar(m); - if (!m->sel) - return; - if (m->sel->isfloating || !m->lt[m->sellt]->arrange) - XRaiseWindow(dpy, m->sel->win); - if (m->lt[m->sellt]->arrange) { - wc.stack_mode = Below; - wc.sibling = m->barwin; - for (c = m->stack; c; c = c->snext) - if (!c->isfloating && ISVISIBLE(c)) { - XConfigureWindow(dpy, c->win, CWSibling|CWStackMode, &wc); - wc.sibling = c->win; - } - } - XSync(dpy, False); - while (XCheckMaskEvent(dpy, EnterWindowMask, &ev)); -} - -void -rotatestack(const Arg *arg) -{ - Client *c = NULL, *f; - - if (!selmon->sel) - return; - f = selmon->sel; - if (arg->i > 0) { - for (c = nexttiled(selmon->clients); c && nexttiled(c->next); c = nexttiled(c->next)); - if (c){ - detach(c); - attach(c); - detachstack(c); - attachstack(c); - } - } else { - if ((c = nexttiled(selmon->clients))){ - detach(c); - enqueue(c); - detachstack(c); - enqueuestack(c); - } - } - if (c){ - arrange(selmon); - //unfocus(f, 1); - focus(f); - restack(selmon); - } -} - -void -run(void) -{ - XEvent ev; - /* main event loop */ - XSync(dpy, False); - while (running && !XNextEvent(dpy, &ev)) - if (handler[ev.type]) - handler[ev.type](&ev); /* call handler */ -} - -void -runAutostart(void) { - system("cd ~/.dwm; ./autostart_blocking.sh"); - system("cd ~/.dwm; ./autostart.sh &"); -} - -void -scan(void) -{ - unsigned int i, num; - Window d1, d2, *wins = NULL; - XWindowAttributes wa; - - if (XQueryTree(dpy, root, &d1, &d2, &wins, &num)) { - for (i = 0; i < num; i++) { - if (!XGetWindowAttributes(dpy, wins[i], &wa) - || wa.override_redirect || XGetTransientForHint(dpy, wins[i], &d1)) - continue; - if (wa.map_state == IsViewable || getstate(wins[i]) == IconicState) - manage(wins[i], &wa); - } - for (i = 0; i < num; i++) { /* now the transients */ - if (!XGetWindowAttributes(dpy, wins[i], &wa)) - continue; - if (XGetTransientForHint(dpy, wins[i], &d1) - && (wa.map_state == IsViewable || getstate(wins[i]) == IconicState)) - manage(wins[i], &wa); - } - if (wins) - XFree(wins); - } -} - -void -sendmon(Client *c, Monitor *m) -{ - if (c->mon == m) - return; - unfocus(c, 1); - detach(c); - detachstack(c); - c->mon = m; - c->tags = m->tagset[m->seltags]; /* assign tags of target monitor */ - attachaside(c); - attachstack(c); - focus(NULL); - arrange(NULL); -} - -void -setclientstate(Client *c, long state) -{ - long data[] = { state, None }; - - XChangeProperty(dpy, c->win, wmatom[WMState], wmatom[WMState], 32, - PropModeReplace, (unsigned char *)data, 2); -} - -int -sendevent(Client *c, Atom proto) -{ - int n; - Atom *protocols; - int exists = 0; - XEvent ev; - - if (XGetWMProtocols(dpy, c->win, &protocols, &n)) { - while (!exists && n--) - exists = protocols[n] == proto; - XFree(protocols); - } - if (exists) { - ev.type = ClientMessage; - ev.xclient.window = c->win; - ev.xclient.message_type = wmatom[WMProtocols]; - ev.xclient.format = 32; - ev.xclient.data.l[0] = proto; - ev.xclient.data.l[1] = CurrentTime; - XSendEvent(dpy, c->win, False, NoEventMask, &ev); - } - return exists; -} - -void -setfocus(Client *c) -{ - if (!c->neverfocus) { - XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime); - XChangeProperty(dpy, root, netatom[NetActiveWindow], - XA_WINDOW, 32, PropModeReplace, - (unsigned char *) &(c->win), 1); - } - sendevent(c, wmatom[WMTakeFocus]); -} - -void -setfullscreen(Client *c, int fullscreen) -{ - if (fullscreen && !c->isfullscreen) { - XChangeProperty(dpy, c->win, netatom[NetWMState], XA_ATOM, 32, - PropModeReplace, (unsigned char*)&netatom[NetWMFullscreen], 1); - c->isfullscreen = 1; - c->oldstate = c->isfloating; - c->oldbw = c->bw; - c->bw = 0; - c->isfloating = 1; - resizeclient(c, c->mon->mx, c->mon->my, c->mon->mw, c->mon->mh); - XRaiseWindow(dpy, c->win); - } else if (!fullscreen && c->isfullscreen){ - XChangeProperty(dpy, c->win, netatom[NetWMState], XA_ATOM, 32, - PropModeReplace, (unsigned char*)0, 0); - c->isfullscreen = 0; - c->isfloating = c->oldstate; - c->bw = c->oldbw; - c->x = c->oldx; - c->y = c->oldy; - c->w = c->oldw; - c->h = c->oldh; - resizeclient(c, c->x, c->y, c->w, c->h); - arrange(c->mon); - } -} - -void -setlayout(const Arg *arg) -{ - if (!arg || !arg->v || arg->v != selmon->lt[selmon->sellt]) - selmon->sellt ^= 1; - if (arg && arg->v) - selmon->lt[selmon->sellt] = (Layout *)arg->v; - strncpy(selmon->ltsymbol, selmon->lt[selmon->sellt]->symbol, sizeof selmon->ltsymbol); - if (selmon->sel) - arrange(selmon); - else - drawbar(selmon); -} - -/* arg > 1.0 will set mfact absolutely */ -void -setmfact(const Arg *arg) -{ - float f; - - if (!arg || !selmon->lt[selmon->sellt]->arrange) - return; - f = arg->f < 1.0 ? arg->f + selmon->mfact : arg->f - 1.0; - if (f < 0.1 || f > 0.9) - return; - selmon->mfact = f; - arrange(selmon); -} - -void -setup(void) -{ - int i; - XSetWindowAttributes wa; - Atom utf8string; - - /* clean up any zombies immediately */ - sigchld(0); - - /* init screen */ - screen = DefaultScreen(dpy); - sw = DisplayWidth(dpy, screen); - sh = DisplayHeight(dpy, screen); - root = RootWindow(dpy, screen); - xinitvisual(); - drw = drw_create(dpy, screen, root, sw, sh, visual, depth, cmap); - if (!drw_fontset_create(drw, fonts, LENGTH(fonts))) - die("no fonts could be loaded."); - lrpad = drw->fonts->h + horizpadbar; - bh = drw->fonts->h + vertpadbar; - updategeom(); - /* init atoms */ - utf8string = XInternAtom(dpy, "UTF8_STRING", False); - wmatom[WMProtocols] = XInternAtom(dpy, "WM_PROTOCOLS", False); - wmatom[WMDelete] = XInternAtom(dpy, "WM_DELETE_WINDOW", False); - wmatom[WMState] = XInternAtom(dpy, "WM_STATE", False); - wmatom[WMTakeFocus] = XInternAtom(dpy, "WM_TAKE_FOCUS", False); - netatom[NetActiveWindow] = XInternAtom(dpy, "_NET_ACTIVE_WINDOW", False); - netatom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False); - netatom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False); - netatom[NetWMState] = XInternAtom(dpy, "_NET_WM_STATE", False); - netatom[NetWMCheck] = XInternAtom(dpy, "_NET_SUPPORTING_WM_CHECK", False); - netatom[NetWMFullscreen] = XInternAtom(dpy, "_NET_WM_STATE_FULLSCREEN", False); - netatom[NetWMWindowType] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE", False); - netatom[NetWMWindowTypeDialog] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DIALOG", False); - netatom[NetClientList] = XInternAtom(dpy, "_NET_CLIENT_LIST", False); - /* init cursors */ - cursor[CurNormal] = drw_cur_create(drw, XC_left_ptr); - cursor[CurResize] = drw_cur_create(drw, XC_sizing); - cursor[CurMove] = drw_cur_create(drw, XC_fleur); - /* init appearance */ - scheme = ecalloc(LENGTH(colors), sizeof(Clr *)); - for (i = 0; i < LENGTH(colors); i++) - scheme[i] = drw_scm_create(drw, colors[i], alphas[i], 3); - /* init bars */ - updatebars(); - updatestatus(); - /* supporting window for NetWMCheck */ - wmcheckwin = XCreateSimpleWindow(dpy, root, 0, 0, 1, 1, 0, 0, 0); - XChangeProperty(dpy, wmcheckwin, netatom[NetWMCheck], XA_WINDOW, 32, - PropModeReplace, (unsigned char *) &wmcheckwin, 1); - XChangeProperty(dpy, wmcheckwin, netatom[NetWMName], utf8string, 8, - PropModeReplace, (unsigned char *) "dwm", 3); - XChangeProperty(dpy, root, netatom[NetWMCheck], XA_WINDOW, 32, - PropModeReplace, (unsigned char *) &wmcheckwin, 1); - /* EWMH support per view */ - XChangeProperty(dpy, root, netatom[NetSupported], XA_ATOM, 32, - PropModeReplace, (unsigned char *) netatom, NetLast); - XDeleteProperty(dpy, root, netatom[NetClientList]); - /* select events */ - wa.cursor = cursor[CurNormal]->cursor; - wa.event_mask = SubstructureRedirectMask|SubstructureNotifyMask - |ButtonPressMask|PointerMotionMask|EnterWindowMask - |LeaveWindowMask|StructureNotifyMask|PropertyChangeMask; - XChangeWindowAttributes(dpy, root, CWEventMask|CWCursor, &wa); - XSelectInput(dpy, root, wa.event_mask); - grabkeys(); - focus(NULL); -} - - -void -seturgent(Client *c, int urg) -{ - XWMHints *wmh; - - c->isurgent = urg; - if (!(wmh = XGetWMHints(dpy, c->win))) - return; - wmh->flags = urg ? (wmh->flags | XUrgencyHint) : (wmh->flags & ~XUrgencyHint); - XSetWMHints(dpy, c->win, wmh); - XFree(wmh); -} - -void -showhide(Client *c) -{ - if (!c) - return; - if (ISVISIBLE(c)) { - /* show clients top down */ - XMoveWindow(dpy, c->win, c->x, c->y); - if ((!c->mon->lt[c->mon->sellt]->arrange || c->isfloating) && !c->isfullscreen) - resize(c, c->x, c->y, c->w, c->h, 0); - showhide(c->snext); - } else { - /* hide clients bottom up */ - showhide(c->snext); - XMoveWindow(dpy, c->win, WIDTH(c) * -2, c->y); - } -} - -void -sigchld(int unused) -{ - if (signal(SIGCHLD, sigchld) == SIG_ERR) - die("can't install SIGCHLD handler:"); - while (0 < waitpid(-1, NULL, WNOHANG)); -} - -void -spawn(const Arg *arg) -{ - if (arg->v == dmenucmd) - dmenumon[0] = '0' + selmon->num; - if (fork() == 0) { - if (dpy) - close(ConnectionNumber(dpy)); - setsid(); - execvp(((char **)arg->v)[0], (char **)arg->v); - fprintf(stderr, "dwm: execvp %s", ((char **)arg->v)[0]); - perror(" failed"); - exit(EXIT_SUCCESS); - } -} - -void -tag(const Arg *arg) -{ - if (selmon->sel && arg->ui & TAGMASK) { - selmon->sel->tags = arg->ui & TAGMASK; - focus(NULL); - arrange(selmon); - } -} - -void -tagmon(const Arg *arg) -{ - if (!selmon->sel || !mons->next) - return; - sendmon(selmon->sel, dirtomon(arg->i)); -} - -void -tile(Monitor *m) -{ - unsigned int i, n, h, mw, my, ty; - Client *c; - - for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); - if (n == 0) - return; - - if (n > m->nmaster) - mw = m->nmaster ? m->ww * m->mfact : 0; - else - mw = m->ww; - for (i = my = ty = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) - if (i < m->nmaster) { - h = (m->wh - my) / (MIN(n, m->nmaster) - i); - resize(c, m->wx, m->wy + my, mw - (2*c->bw), h - (2*c->bw), 0); - my += HEIGHT(c); - } else { - h = (m->wh - ty) / (n - i); - resize(c, m->wx + mw, m->wy + ty, m->ww - mw - (2*c->bw), h - (2*c->bw), 0); - ty += HEIGHT(c); - } -} - -void -togglebar(const Arg *arg) -{ - selmon->showbar = !selmon->showbar; - updatebarpos(selmon); - XMoveResizeWindow(dpy, selmon->barwin, selmon->wx, selmon->by, selmon->ww, bh); - arrange(selmon); -} - -void -togglefloating(const Arg *arg) -{ - if (!selmon->sel) - return; - if (selmon->sel->isfullscreen) /* no support for fullscreen windows */ - return; - selmon->sel->isfloating = !selmon->sel->isfloating || selmon->sel->isfixed; - if (selmon->sel->isfloating) - resize(selmon->sel, selmon->sel->x, selmon->sel->y, - selmon->sel->w, selmon->sel->h, 0); - arrange(selmon); -} - -void -toggletag(const Arg *arg) -{ - unsigned int newtags; - - if (!selmon->sel) - return; - newtags = selmon->sel->tags ^ (arg->ui & TAGMASK); - if (newtags) { - selmon->sel->tags = newtags; - focus(NULL); - arrange(selmon); - } -} - -void -toggleview(const Arg *arg) -{ - unsigned int newtagset = selmon->tagset[selmon->seltags] ^ (arg->ui & TAGMASK); - - if (newtagset) { - selmon->tagset[selmon->seltags] = newtagset; - focus(NULL); - arrange(selmon); - } -} - -void -unfocus(Client *c, int setfocus) -{ - if (!c) - return; - grabbuttons(c, 0); - XSetWindowBorder(dpy, c->win, scheme[SchemeNorm][ColBorder].pixel); - if (setfocus) { - XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime); - XDeleteProperty(dpy, root, netatom[NetActiveWindow]); - } -} - -void -unmanage(Client *c, int destroyed) -{ - Monitor *m = c->mon; - XWindowChanges wc; - - detach(c); - detachstack(c); - if (!destroyed) { - wc.border_width = c->oldbw; - XGrabServer(dpy); /* avoid race conditions */ - XSetErrorHandler(xerrordummy); - XConfigureWindow(dpy, c->win, CWBorderWidth, &wc); /* restore border */ - XUngrabButton(dpy, AnyButton, AnyModifier, c->win); - setclientstate(c, WithdrawnState); - XSync(dpy, False); - XSetErrorHandler(xerror); - XUngrabServer(dpy); - } - free(c); - focus(NULL); - updateclientlist(); - arrange(m); -} - -void -unmapnotify(XEvent *e) -{ - Client *c; - XUnmapEvent *ev = &e->xunmap; - - if ((c = wintoclient(ev->window))) { - if (ev->send_event) - setclientstate(c, WithdrawnState); - else - unmanage(c, 0); - } -} - -void -updatebars(void) -{ - Monitor *m; - XSetWindowAttributes wa = { - .override_redirect = True, - .background_pixel = 0, - .border_pixel = 0, - .colormap = cmap, - .event_mask = ButtonPressMask|ExposureMask - }; - XClassHint ch = {"dwm", "dwm"}; - for (m = mons; m; m = m->next) { - if (m->barwin) - continue; - m->barwin = XCreateWindow(dpy, root, m->wx, m->by, m->ww, bh, 0, depth, - InputOutput, visual, - CWOverrideRedirect|CWBackPixel|CWBorderPixel|CWColormap|CWEventMask, &wa); - XDefineCursor(dpy, m->barwin, cursor[CurNormal]->cursor); - XMapRaised(dpy, m->barwin); - XSetClassHint(dpy, m->barwin, &ch); - } -} - -void -updatebarpos(Monitor *m) -{ - m->wy = m->my; - m->wh = m->mh; - if (m->showbar) { - m->wh -= bh; - m->by = m->topbar ? m->wy : m->wy + m->wh; - m->wy = m->topbar ? m->wy + bh : m->wy; - } else - m->by = -bh; -} - -void -updateclientlist() -{ - Client *c; - Monitor *m; - - XDeleteProperty(dpy, root, netatom[NetClientList]); - for (m = mons; m; m = m->next) - for (c = m->clients; c; c = c->next) - XChangeProperty(dpy, root, netatom[NetClientList], - XA_WINDOW, 32, PropModeAppend, - (unsigned char *) &(c->win), 1); -} - -int -updategeom(void) -{ - int dirty = 0; - -#ifdef XINERAMA - if (XineramaIsActive(dpy)) { - int i, j, n, nn; - Client *c; - Monitor *m; - XineramaScreenInfo *info = XineramaQueryScreens(dpy, &nn); - XineramaScreenInfo *unique = NULL; - - for (n = 0, m = mons; m; m = m->next, n++); - /* only consider unique geometries as separate screens */ - unique = ecalloc(nn, sizeof(XineramaScreenInfo)); - for (i = 0, j = 0; i < nn; i++) - if (isuniquegeom(unique, j, &info[i])) - memcpy(&unique[j++], &info[i], sizeof(XineramaScreenInfo)); - XFree(info); - nn = j; - if (n <= nn) { /* new monitors available */ - for (i = 0; i < (nn - n); i++) { - for (m = mons; m && m->next; m = m->next); - if (m) - m->next = createmon(); - else - mons = createmon(); - } - for (i = 0, m = mons; i < nn && m; m = m->next, i++) - if (i >= n - || unique[i].x_org != m->mx || unique[i].y_org != m->my - || unique[i].width != m->mw || unique[i].height != m->mh) - { - dirty = 1; - m->num = i; - m->mx = m->wx = unique[i].x_org; - m->my = m->wy = unique[i].y_org; - m->mw = m->ww = unique[i].width; - m->mh = m->wh = unique[i].height; - updatebarpos(m); - } - } else { /* less monitors available nn < n */ - for (i = nn; i < n; i++) { - for (m = mons; m && m->next; m = m->next); - while ((c = m->clients)) { - dirty = 1; - m->clients = c->next; - detachstack(c); - c->mon = mons; - attach(c); - attachaside(c); - attachstack(c); - } - if (m == selmon) - selmon = mons; - cleanupmon(m); - } - } - free(unique); - } else -#endif /* XINERAMA */ - { /* default monitor setup */ - if (!mons) - mons = createmon(); - if (mons->mw != sw || mons->mh != sh) { - dirty = 1; - mons->mw = mons->ww = sw; - mons->mh = mons->wh = sh; - updatebarpos(mons); - } - } - if (dirty) { - selmon = mons; - selmon = wintomon(root); - } - return dirty; -} - -void -updatenumlockmask(void) -{ - unsigned int i, j; - XModifierKeymap *modmap; - - numlockmask = 0; - modmap = XGetModifierMapping(dpy); - for (i = 0; i < 8; i++) - for (j = 0; j < modmap->max_keypermod; j++) - if (modmap->modifiermap[i * modmap->max_keypermod + j] - == XKeysymToKeycode(dpy, XK_Num_Lock)) - numlockmask = (1 << i); - XFreeModifiermap(modmap); -} - -void -updatesizehints(Client *c) -{ - long msize; - XSizeHints size; - - if (!XGetWMNormalHints(dpy, c->win, &size, &msize)) - /* size is uninitialized, ensure that size.flags aren't used */ - size.flags = PSize; - if (size.flags & PBaseSize) { - c->basew = size.base_width; - c->baseh = size.base_height; - } else if (size.flags & PMinSize) { - c->basew = size.min_width; - c->baseh = size.min_height; - } else - c->basew = c->baseh = 0; - if (size.flags & PResizeInc) { - c->incw = size.width_inc; - c->inch = size.height_inc; - } else - c->incw = c->inch = 0; - if (size.flags & PMaxSize) { - c->maxw = size.max_width; - c->maxh = size.max_height; - } else - c->maxw = c->maxh = 0; - if (size.flags & PMinSize) { - c->minw = size.min_width; - c->minh = size.min_height; - } else if (size.flags & PBaseSize) { - c->minw = size.base_width; - c->minh = size.base_height; - } else - c->minw = c->minh = 0; - if (size.flags & PAspect) { - c->mina = (float)size.min_aspect.y / size.min_aspect.x; - c->maxa = (float)size.max_aspect.x / size.max_aspect.y; - } else - c->maxa = c->mina = 0.0; - c->isfixed = (c->maxw && c->maxh && c->maxw == c->minw && c->maxh == c->minh); -} - -void -updatestatus(void) -{ - if (!gettextprop(root, XA_WM_NAME, stext, sizeof(stext))) - strcpy(stext, "dwm-"VERSION); - drawbar(selmon); -} - -void -updatetitle(Client *c) -{ - if (!gettextprop(c->win, netatom[NetWMName], c->name, sizeof c->name)) - gettextprop(c->win, XA_WM_NAME, c->name, sizeof c->name); - if (c->name[0] == '\0') /* hack to mark broken clients */ - strcpy(c->name, broken); -} - -void -updatewindowtype(Client *c) -{ - Atom state = getatomprop(c, netatom[NetWMState]); - Atom wtype = getatomprop(c, netatom[NetWMWindowType]); - - if (state == netatom[NetWMFullscreen]) - setfullscreen(c, 1); - if (wtype == netatom[NetWMWindowTypeDialog]) - c->isfloating = 1; -} - -void -updatewmhints(Client *c) -{ - XWMHints *wmh; - - if ((wmh = XGetWMHints(dpy, c->win))) { - if (c == selmon->sel && wmh->flags & XUrgencyHint) { - wmh->flags &= ~XUrgencyHint; - XSetWMHints(dpy, c->win, wmh); - } else - c->isurgent = (wmh->flags & XUrgencyHint) ? 1 : 0; - if (wmh->flags & InputHint) - c->neverfocus = !wmh->input; - else - c->neverfocus = 0; - XFree(wmh); - } -} - -void -view(const Arg *arg) -{ - if ((arg->ui & TAGMASK) == selmon->tagset[selmon->seltags]) - return; - selmon->seltags ^= 1; /* toggle sel tagset */ - if (arg->ui & TAGMASK) - selmon->tagset[selmon->seltags] = arg->ui & TAGMASK; - focus(NULL); - arrange(selmon); -} - -Client * -wintoclient(Window w) -{ - Client *c; - Monitor *m; - - for (m = mons; m; m = m->next) - for (c = m->clients; c; c = c->next) - if (c->win == w) - return c; - return NULL; -} - -Monitor * -wintomon(Window w) -{ - int x, y; - Client *c; - Monitor *m; - - if (w == root && getrootptr(&x, &y)) - return recttomon(x, y, 1, 1); - for (m = mons; m; m = m->next) - if (w == m->barwin) - return m; - if ((c = wintoclient(w))) - return c->mon; - return selmon; -} - -/* There's no way to check accesses to destroyed windows, thus those cases are - * ignored (especially on UnmapNotify's). Other types of errors call Xlibs - * default error handler, which may call exit. */ -int -xerror(Display *dpy, XErrorEvent *ee) -{ - if (ee->error_code == BadWindow - || (ee->request_code == X_SetInputFocus && ee->error_code == BadMatch) - || (ee->request_code == X_PolyText8 && ee->error_code == BadDrawable) - || (ee->request_code == X_PolyFillRectangle && ee->error_code == BadDrawable) - || (ee->request_code == X_PolySegment && ee->error_code == BadDrawable) - || (ee->request_code == X_ConfigureWindow && ee->error_code == BadMatch) - || (ee->request_code == X_GrabButton && ee->error_code == BadAccess) - || (ee->request_code == X_GrabKey && ee->error_code == BadAccess) - || (ee->request_code == X_CopyArea && ee->error_code == BadDrawable)) - return 0; - fprintf(stderr, "dwm: fatal error: request code=%d, error code=%d\n", - ee->request_code, ee->error_code); - return xerrorxlib(dpy, ee); /* may call exit */ -} - -int -xerrordummy(Display *dpy, XErrorEvent *ee) -{ - return 0; -} - -/* Startup Error handler to check if another window manager - * is already running. */ -int -xerrorstart(Display *dpy, XErrorEvent *ee) -{ - die("dwm: another window manager is already running"); - return -1; -} - -void -xinitvisual() -{ - XVisualInfo *infos; - XRenderPictFormat *fmt; - int nitems; - int i; - - XVisualInfo tpl = { - .screen = screen, - .depth = 32, - .class = TrueColor - }; - long masks = VisualScreenMask | VisualDepthMask | VisualClassMask; - - infos = XGetVisualInfo(dpy, masks, &tpl, &nitems); - visual = NULL; - for(i = 0; i < nitems; i ++) { - fmt = XRenderFindVisualFormat(dpy, infos[i].visual); - if (fmt->type == PictTypeDirect && fmt->direct.alphaMask) { - visual = infos[i].visual; - depth = infos[i].depth; - cmap = XCreateColormap(dpy, root, visual, AllocNone); - useargb = 1; - break; - } - } - - XFree(infos); - - if (! visual) { - visual = DefaultVisual(dpy, screen); - depth = DefaultDepth(dpy, screen); - cmap = DefaultColormap(dpy, screen); - } -} - -void -zoom(const Arg *arg) -{ - Client *c = selmon->sel; - - if (!selmon->lt[selmon->sellt]->arrange - || (selmon->sel && selmon->sel->isfloating)) - return; - if (c == nexttiled(selmon->clients)) - if (!c || !(c = nexttiled(c->next))) - return; - pop(c); -} - -int -main(int argc, char *argv[]) -{ - if (argc == 2 && !strcmp("-v", argv[1])) - die("dwm-"VERSION); - else if (argc != 1) - die("usage: dwm [-v]"); - if (!setlocale(LC_CTYPE, "") || !XSupportsLocale()) - fputs("warning: no locale support\n", stderr); - if (!(dpy = XOpenDisplay(NULL))) - die("dwm: cannot open display"); - checkotherwm(); - setup(); -#ifdef __OpenBSD__ - if (pledge("stdio rpath proc exec", NULL) == -1) - die("pledge"); -#endif /* __OpenBSD__ */ - scan(); - runAutostart(); - run(); - cleanup(); - XCloseDisplay(dpy); - return EXIT_SUCCESS; -} diff --git a/dwm/dwm.png b/dwm/dwm.png deleted file mode 100755 index b1f9ba7..0000000 Binary files a/dwm/dwm.png and /dev/null differ diff --git a/dwm/layouts.c b/dwm/layouts.c deleted file mode 100755 index d26acf3..0000000 --- a/dwm/layouts.c +++ /dev/null @@ -1,27 +0,0 @@ -void -grid(Monitor *m) { - unsigned int i, n, cx, cy, cw, ch, aw, ah, cols, rows; - Client *c; - - for(n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next)) - n++; - - /* grid dimensions */ - for(rows = 0; rows <= n/2; rows++) - if(rows*rows >= n) - break; - cols = (rows && (rows - 1) * rows >= n) ? rows - 1 : rows; - - /* window geoms (cell height/width) */ - ch = m->wh / (rows ? rows : 1); - cw = m->ww / (cols ? cols : 1); - for(i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next)) { - cx = m->wx + (i / rows) * cw; - cy = m->wy + (i % rows) * ch; - /* adjust height/width of last row/column's windows */ - ah = ((i + 1) % rows == 0) ? m->wh - ch * rows : 0; - aw = (i >= rows * (cols - 1)) ? m->ww - cw * cols : 0; - resize(c, cx, cy, cw - 2 * c->bw + aw, ch - 2 * c->bw + ah, False); - i++; - } -} diff --git a/dwm/transient.c b/dwm/transient.c deleted file mode 100755 index 040adb5..0000000 --- a/dwm/transient.c +++ /dev/null @@ -1,42 +0,0 @@ -/* cc transient.c -o transient -lX11 */ - -#include -#include -#include -#include - -int main(void) { - Display *d; - Window r, f, t = None; - XSizeHints h; - XEvent e; - - d = XOpenDisplay(NULL); - if (!d) - exit(1); - r = DefaultRootWindow(d); - - f = XCreateSimpleWindow(d, r, 100, 100, 400, 400, 0, 0, 0); - h.min_width = h.max_width = h.min_height = h.max_height = 400; - h.flags = PMinSize | PMaxSize; - XSetWMNormalHints(d, f, &h); - XStoreName(d, f, "floating"); - XMapWindow(d, f); - - XSelectInput(d, f, ExposureMask); - while (1) { - XNextEvent(d, &e); - - if (t == None) { - sleep(5); - t = XCreateSimpleWindow(d, r, 50, 50, 100, 100, 0, 0, 0); - XSetTransientForHint(d, t, f); - XStoreName(d, t, "transient"); - XMapWindow(d, t); - XSelectInput(d, t, ExposureMask); - } - } - - XCloseDisplay(d); - exit(0); -} diff --git a/dwm/util.c b/dwm/util.c deleted file mode 100755 index fe044fc..0000000 --- a/dwm/util.c +++ /dev/null @@ -1,35 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include -#include -#include -#include - -#include "util.h" - -void * -ecalloc(size_t nmemb, size_t size) -{ - void *p; - - if (!(p = calloc(nmemb, size))) - die("calloc:"); - return p; -} - -void -die(const char *fmt, ...) { - va_list ap; - - va_start(ap, fmt); - vfprintf(stderr, fmt, ap); - va_end(ap); - - if (fmt[0] && fmt[strlen(fmt)-1] == ':') { - fputc(' ', stderr); - perror(NULL); - } else { - fputc('\n', stderr); - } - - exit(1); -} diff --git a/dwm/util.h b/dwm/util.h deleted file mode 100755 index f633b51..0000000 --- a/dwm/util.h +++ /dev/null @@ -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); diff --git a/dwmblocks/LICENSE b/dwmblocks/LICENSE new file mode 100644 index 0000000..d159169 --- /dev/null +++ b/dwmblocks/LICENSE @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/dwmblocks/Makefile b/dwmblocks/Makefile new file mode 100644 index 0000000..b75ae9a --- /dev/null +++ b/dwmblocks/Makefile @@ -0,0 +1,7 @@ +output: dwmblocks.c blocks.h + cc `pkg-config --cflags x11` `pkg-config --libs x11` dwmblocks.c -o dwmblocks +clean: + rm -f *.o *.gch dwmblocks +install: output + mkdir -p /usr/local/bin + cp -f dwmblocks /usr/local/bin diff --git a/dwmblocks/README.md b/dwmblocks/README.md new file mode 100644 index 0000000..fe02a0c --- /dev/null +++ b/dwmblocks/README.md @@ -0,0 +1,5 @@ +# dwmblocks +Modular status bar for dwm written in c. +# modifying blocks +The statusbar is made from text output from commandline programs. +Blocks are added and removed by editing the blocks.h header file. diff --git a/dwmblocks/blocks.h b/dwmblocks/blocks.h new file mode 100644 index 0000000..db328c9 --- /dev/null +++ b/dwmblocks/blocks.h @@ -0,0 +1,18 @@ +//Modify this file to change what commands output to your statusbar, and recompile using the make command. +static const Block blocks[] = { + /*Icon*/ /*Command*/ /*Update Interval*/ /*Update Signal*/ + {" 🐧 ", "kernel", 360, 2}, + + {" ▲ ", "upt", 60, 2}, + + {" 📦 ", "pacupdate", 360, 9}, + + {" 💻 ", "memory", 6, 1}, + + {" 🔊 ", "volume", 2, 10}, + + {" 🕑 ", "clock", 5, 0}, +}; + +//sets delimeter between status commands. NULL character ('\0') means no delimeter. +static char delim = '|'; diff --git a/dwmblocks/dwmblocks b/dwmblocks/dwmblocks new file mode 100755 index 0000000..304cd07 Binary files /dev/null and b/dwmblocks/dwmblocks differ diff --git a/dwmblocks/dwmblocks.c b/dwmblocks/dwmblocks.c new file mode 100644 index 0000000..88bdfb0 --- /dev/null +++ b/dwmblocks/dwmblocks.c @@ -0,0 +1,175 @@ +#include +#include +#include +#include +#include +#include +#define LENGTH(X) (sizeof(X) / sizeof (X[0])) +#define CMDLENGTH 50 + +typedef struct { + char* icon; + char* command; + unsigned int interval; + unsigned int signal; +} Block; +void sighandler(int num); +void replace(char *str, char old, char new); +void getcmds(int time); +#ifndef __OpenBSD__ +void getsigcmds(int signal); +void setupsignals(); +void sighandler(int signum); +#endif +int getstatus(char *str, char *last); +void setroot(); +void statusloop(); +void termhandler(int signum); + + +#include "blocks.h" + +static Display *dpy; +static int screen; +static Window root; +static char statusbar[LENGTH(blocks)][CMDLENGTH] = {0}; +static char statusstr[2][256]; +static int statusContinue = 1; +static void (*writestatus) () = setroot; + +void replace(char *str, char old, char new) +{ + int N = strlen(str); + for(int i = 0; i < N; i++) + if(str[i] == old) + str[i] = new; +} + +//opens process *cmd and stores output in *output +void getcmd(const Block *block, char *output) +{ + strcpy(output, block->icon); + char *cmd = block->command; + FILE *cmdf = popen(cmd,"r"); + if (!cmdf) + return; + char c; + int i = strlen(block->icon); + fgets(output+i, CMDLENGTH-i, cmdf); + i = strlen(output); + if (delim != '\0' && --i) + output[i++] = delim; + output[i++] = '\0'; + pclose(cmdf); +} + +void getcmds(int time) +{ + const Block* current; + for(int i = 0; i < LENGTH(blocks); i++) + { + current = blocks + i; + if ((current->interval != 0 && time % current->interval == 0) || time == -1) + getcmd(current,statusbar[i]); + } +} + +#ifndef __OpenBSD__ +void getsigcmds(int signal) +{ + const Block *current; + for (int i = 0; i < LENGTH(blocks); i++) + { + current = blocks + i; + if (current->signal == signal) + getcmd(current,statusbar[i]); + } +} + +void setupsignals() +{ + for(int i = 0; i < LENGTH(blocks); i++) + { + if (blocks[i].signal > 0) + signal(SIGRTMIN+blocks[i].signal, sighandler); + } + +} +#endif + +int getstatus(char *str, char *last) +{ + strcpy(last, str); + str[0] = '\0'; + for(int i = 0; i < LENGTH(blocks); i++) + strcat(str, statusbar[i]); + str[strlen(str)-1] = '\0'; + return strcmp(str, last);//0 if they are the same +} + +void setroot() +{ + if (!getstatus(statusstr[0], statusstr[1]))//Only set root if text has changed. + return; + Display *d = XOpenDisplay(NULL); + if (d) { + dpy = d; + } + screen = DefaultScreen(dpy); + root = RootWindow(dpy, screen); + XStoreName(dpy, root, statusstr[0]); + XCloseDisplay(dpy); +} + +void pstdout() +{ + if (!getstatus(statusstr[0], statusstr[1]))//Only write out if text has changed. + return; + printf("%s\n",statusstr[0]); + fflush(stdout); +} + + +void statusloop() +{ +#ifndef __OpenBSD__ + setupsignals(); +#endif + int i = 0; + getcmds(-1); + while(statusContinue) + { + getcmds(i); + writestatus(); + sleep(1.0); + i++; + } +} + +#ifndef __OpenBSD__ +void sighandler(int signum) +{ + getsigcmds(signum-SIGRTMIN); + writestatus(); +} +#endif + +void termhandler(int signum) +{ + statusContinue = 0; + exit(0); +} + +int main(int argc, char** argv) +{ + for(int i = 0; i < argc; i++) + { + if (!strcmp("-d",argv[i])) + delim = argv[++i][0]; + else if(!strcmp("-p",argv[i])) + writestatus = pstdout; + } + signal(SIGTERM, termhandler); + signal(SIGINT, termhandler); + statusloop(); +} diff --git a/st/FAQ b/st/FAQ index 921c493..78c769a 100644 --- a/st/FAQ +++ b/st/FAQ @@ -1,6 +1,6 @@ ## Why does st not handle utmp entries? -Use the excellent tool of [utmp](http://git.suckless.org/utmp/) for this task. +Use the excellent tool of [utmp](https://git.suckless.org/utmp/) for this task. ## Some _random program_ complains that st is unknown/not recognised/unsupported/whatever! @@ -15,13 +15,6 @@ you can manually run `tic -sx st.info`. * Some programs don’t complain about the lacking st description and default to another terminal. In that case see the question about terminfo. -## I get some weird glitches/visual bug on _random program_! - -Try launching it with a different TERM: $ TERM=xterm myapp. toe(1) will give -you a list of available terminals, but you’ll most likely switch between xterm, -st or st-256color. The default value for TERM can be changed in config.h -(TNAME). - ## How do I scroll back up? Using a terminal multiplexer. @@ -104,7 +97,7 @@ St is emulating the Linux way of handling backspace being delete and delete bein backspace. This is an issue that was discussed in suckless mailing list -. Here is why some old grumpy +. Here is why some old grumpy terminal users wants its backspace to be how he feels it: Well, I am going to comment why I want to change the behaviour @@ -163,5 +156,40 @@ terminal users wants its backspace to be how he feels it: Apply [1]. -[1] http://st.suckless.org/patches/delkey +[1] https://st.suckless.org/patches/delkey +## Why do images not work in st (in programs such as w3m)? + +This is a terrible hack that overdraws an image on top of the terminal emulator +window. It also relies on a very specific way the terminal draws it's contents. + +A more proper (but limited way) would be using sixels. Which st doesn't +support. + +## BadLength X error in Xft when trying to render emoji + +Xft makes st crash when rendering color emojis with the following error: + +"X Error of failed request: BadLength (poly request too large or internal Xlib length error)" + Major opcode of failed request: 139 (RENDER) + Minor opcode of failed request: 20 (RenderAddGlyphs) + Serial number of failed request: 1595 + Current serial number in output stream: 1818" + +This is a known bug in Xft (not st) which happens on some platforms and +combination of particular fonts and fontconfig settings. + +See also: +https://gitlab.freedesktop.org/xorg/lib/libxft/issues/6 +https://bugs.freedesktop.org/show_bug.cgi?id=107534 +https://bugzilla.redhat.com/show_bug.cgi?id=1498269 + +The solution is to remove color emoji fonts or disable this in the fontconfig +XML configuration. As an ugly workaround (which may work only on newer +fontconfig versions (FC_COLOR)), the following code can be used to mask color +fonts: + + FcPatternAddBool(fcpattern, FC_COLOR, FcFalse); + +Please don't bother reporting this bug to st, but notify the upstream Xft +developers about fixing this bug. diff --git a/st/config.def.h b/st/config.def.h index 7e8fe75..57fd9d3 100644 --- a/st/config.def.h +++ b/st/config.def.h @@ -1,11 +1,16 @@ -/* See LICENSE file for copyright and license details. */ +/* ____ _____ */ +/* | _ \_ _| Derek Taylor (DistroTube) */ +/* | | | || | http://www.youtube.com/c/DistroTube */ +/* | |_| || | http://www.gitlab.com/dwt1/ */ +/* |____/ |_| */ -/* - * appearance - * - * font: see http://freedesktop.org/software/fontconfig/fontconfig-user.html - */ -static char *font = "Liberation Mono:pixelsize=12:antialias=true:autohint=true"; +/* See LICENSE file for copyright and license details. */ +/* appearance */ +static char *font = "Mononoki Nerd Font:pixelsize=14:antialias=true:autohint=true"; +static char *font2[] = { + "Inconsolata for Powerline:pixelsize=12:antialias=true:autohint=true", + "Hack Nerd Font Mono:pixelsize=11:antialias=true:autohint=true", +}; static int borderpx = 2; /* @@ -30,9 +35,9 @@ static float chscale = 1.0; /* * word delimiter string * - * More advanced example: " `'\"()[]{}" + * More advanced example: L" `'\"()[]{}" */ -char *worddelimiters = " "; +wchar_t *worddelimiters = L" "; /* selection timeouts (in milliseconds) */ static unsigned int doubleclicktimeout = 300; @@ -82,48 +87,51 @@ char *termname = "st-256color"; */ unsigned int tabspaces = 8; -/* bg opacity */ -unsigned int alpha = 0xcc; +/* bg opacity + * 0xff is no transparency. + * 0xee adds wee bit of transparency. + * Play with the value to get desired transparency. + */ +unsigned int alpha = 0xff; /* Terminal colors (16 first used in escape sequence) */ static const char *colorname[] = { /* 8 normal colors */ - "black", - "red3", - "green3", - "yellow3", - "blue2", - "magenta3", - "cyan3", - "gray90", + "#282a36", + "#f07178", + "#c3e88d", + "#ffcb6b", + "#82aaff", + "#c792ea", + "#89ddff", + "#d0d0d0", /* 8 bright colors */ - "gray50", - "red", - "green", - "yellow", - "#5c5cff", - "magenta", - "cyan", - "white", + "#434758", + "#ff8b92", + "#ddffa7", + "#ffe585", + "#9cc4ff", + "#e1acff", + "#a3f7ff", + "#ffffff", [255] = 0, /* more colors can be added after 255 to use with DefaultXX */ - "#cccccc", - "#555555", - "black", + "#282a36", + "#bbc5ff", + "#d7d7d7", }; - /* * Default colors (colorname index) * foreground, background, cursor, reverse cursor */ -unsigned int defaultfg = 7; -unsigned int defaultbg = 257; -static unsigned int defaultcs = 256; -static unsigned int defaultrcs = 257; +unsigned int defaultbg = 256; +unsigned int defaultfg = 257; +static unsigned int defaultcs = 258; +static unsigned int defaultrcs = 258; /* * Default shape of cursor @@ -154,20 +162,24 @@ static unsigned int mousebg = 0; */ static unsigned int defaultattr = 11; +/* + * Force mouse select/shortcuts while mask is active (when MODE_MOUSE is set). + * Note that if you want to use ShiftMask with selmasks, set this to an other + * modifier, set to 0 to not use it. + */ +static uint forcemousemod = ShiftMask; + /* * Internal mouse shortcuts. * Beware that overloading Button1 will disable the selection. */ static MouseShortcut mshortcuts[] = { - /* button mask string */ - { Button4, XK_NO_MOD, "\031" }, - { Button5, XK_NO_MOD, "\005" }, -}; - -MouseKey mkeys[] = { - /* button mask function argument */ - { Button4, XK_NO_MOD, kscrollup, {.i = 1} }, - { Button5, XK_NO_MOD, kscrolldown, {.i = 1} }, + /* mask button function argument release */ + { XK_ANY_MOD, Button4, kscrollup, {.i = 3}, 0, /* !alt */ -1 }, + { XK_ANY_MOD, Button5, kscrolldown, {.i = 3}, 0, /* !alt */ -1 }, + { XK_ANY_MOD, Button2, selpaste, {.i = 0}, 1 }, + { XK_ANY_MOD, Button4, ttysend, {.s = "\031"} }, + { XK_ANY_MOD, Button5, ttysend, {.s = "\005"} }, }; /* Internal keyboard shortcuts. */ @@ -180,16 +192,14 @@ static Shortcut shortcuts[] = { { ControlMask, XK_Print, toggleprinter, {.i = 0} }, { ShiftMask, XK_Print, printscreen, {.i = 0} }, { XK_ANY_MOD, XK_Print, printsel, {.i = 0} }, - { TERMMOD, XK_Prior, zoom, {.f = +1} }, - { TERMMOD, XK_Next, zoom, {.f = -1} }, - { TERMMOD, XK_Home, zoomreset, {.f = 0} }, + { TERMMOD, XK_K, zoom, {.f = +1} }, + { TERMMOD, XK_J, zoom, {.f = -1} }, + { TERMMOD, XK_U, zoomreset, {.f = 0} }, { TERMMOD, XK_C, clipcopy, {.i = 0} }, { TERMMOD, XK_V, clippaste, {.i = 0} }, { TERMMOD, XK_Y, selpaste, {.i = 0} }, { ShiftMask, XK_Insert, selpaste, {.i = 0} }, { TERMMOD, XK_Num_Lock, numlock, {.i = 0} }, - { ShiftMask, XK_Page_Up, kscrollup, {.i = -1} }, - { ShiftMask, XK_Page_Down, kscrolldown, {.i = -1} }, }; /* @@ -207,10 +217,6 @@ static Shortcut shortcuts[] = { * * 0: no value * * > 0: cursor application mode enabled * * < 0: cursor application mode disabled - * crlf value - * * 0: no value - * * > 0: crlf mode is enabled - * * < 0: crlf mode is disabled * * Be careful with the order of the definitions because st searches in * this table sequentially, so any XK_ANY_MOD must be in the last @@ -229,13 +235,6 @@ static KeySym mappedkeys[] = { -1 }; */ static uint ignoremod = Mod2Mask|XK_SWITCH_MOD; -/* - * Override mouse-select while mask is active (when MODE_MOUSE is set). - * Note that if you want to use ShiftMask with selmasks, set this to an other - * modifier, set to 0 to not use it. - */ -static uint forceselmod = ShiftMask; - /* * This is the huge key array which defines all compatibility to the Linux * world. Please decide about changes wisely. diff --git a/st/config.h b/st/config.h old mode 100755 new mode 100644 index 9dc9312..57fd9d3 --- a/st/config.h +++ b/st/config.h @@ -1,11 +1,16 @@ -/* See LICENSE file for copyright and license details. */ +/* ____ _____ */ +/* | _ \_ _| Derek Taylor (DistroTube) */ +/* | | | || | http://www.youtube.com/c/DistroTube */ +/* | |_| || | http://www.gitlab.com/dwt1/ */ +/* |____/ |_| */ -/* - * appearance - * - * font: see http://freedesktop.org/software/fontconfig/fontconfig-user.html - */ +/* See LICENSE file for copyright and license details. */ +/* appearance */ static char *font = "Mononoki Nerd Font:pixelsize=14:antialias=true:autohint=true"; +static char *font2[] = { + "Inconsolata for Powerline:pixelsize=12:antialias=true:autohint=true", + "Hack Nerd Font Mono:pixelsize=11:antialias=true:autohint=true", +}; static int borderpx = 2; /* @@ -24,15 +29,15 @@ char *stty_args = "stty raw pass8 nl -echo -iexten -cstopb 38400"; char *vtiden = "\033[?6c"; /* Kerning / character bounding-box multipliers */ -static float cwscale = 1.1; +static float cwscale = 1.0; static float chscale = 1.0; /* * word delimiter string * - * More advanced example: " `'\"()[]{}" + * More advanced example: L" `'\"()[]{}" */ -char *worddelimiters = " "; +wchar_t *worddelimiters = L" "; /* selection timeouts (in milliseconds) */ static unsigned int doubleclicktimeout = 300; @@ -82,8 +87,12 @@ char *termname = "st-256color"; */ unsigned int tabspaces = 8; -/* bg opacity */ -unsigned int alpha = 0xff; /* 0xf2 adds wee bit of transparency */ +/* bg opacity + * 0xff is no transparency. + * 0xee adds wee bit of transparency. + * Play with the value to get desired transparency. + */ +unsigned int alpha = 0xff; /* Terminal colors (16 first used in escape sequence) */ static const char *colorname[] = { @@ -153,39 +162,39 @@ static unsigned int mousebg = 0; */ static unsigned int defaultattr = 11; +/* + * Force mouse select/shortcuts while mask is active (when MODE_MOUSE is set). + * Note that if you want to use ShiftMask with selmasks, set this to an other + * modifier, set to 0 to not use it. + */ +static uint forcemousemod = ShiftMask; + /* * Internal mouse shortcuts. * Beware that overloading Button1 will disable the selection. */ static MouseShortcut mshortcuts[] = { - /* button mask string */ - { Button4, XK_ANY_MOD, "\031" }, - { Button5, XK_ANY_MOD, "\005" }, + /* mask button function argument release */ + { XK_ANY_MOD, Button4, kscrollup, {.i = 3}, 0, /* !alt */ -1 }, + { XK_ANY_MOD, Button5, kscrolldown, {.i = 3}, 0, /* !alt */ -1 }, + { XK_ANY_MOD, Button2, selpaste, {.i = 0}, 1 }, + { XK_ANY_MOD, Button4, ttysend, {.s = "\031"} }, + { XK_ANY_MOD, Button5, ttysend, {.s = "\005"} }, }; /* Internal keyboard shortcuts. */ #define MODKEY Mod1Mask #define TERMMOD (ControlMask|ShiftMask) -MouseKey mkeys[] = { - /* button mask function argument */ - { Button4, ShiftMask, kscrollup, {.i = 1} }, - { Button5, ShiftMask, kscrolldown, {.i = 1} }, - { Button4, TERMMOD, zoom, {.f = +1} }, - { Button5, TERMMOD, zoom, {.f = -1} }, -}; - static Shortcut shortcuts[] = { /* mask keysym function argument */ { XK_ANY_MOD, XK_Break, sendbreak, {.i = 0} }, { ControlMask, XK_Print, toggleprinter, {.i = 0} }, { ShiftMask, XK_Print, printscreen, {.i = 0} }, { XK_ANY_MOD, XK_Print, printsel, {.i = 0} }, - { ShiftMask, XK_Page_Up, kscrollup, {.i = 1} }, - { ShiftMask, XK_Page_Down, kscrolldown, {.i = 1} }, - { TERMMOD, XK_K, zoom, {.f = +1} }, - { TERMMOD, XK_J, zoom, {.f = -1} }, - { TERMMOD, XK_Home, zoomreset, {.f = 0} }, + { TERMMOD, XK_K, zoom, {.f = +1} }, + { TERMMOD, XK_J, zoom, {.f = -1} }, + { TERMMOD, XK_U, zoomreset, {.f = 0} }, { TERMMOD, XK_C, clipcopy, {.i = 0} }, { TERMMOD, XK_V, clippaste, {.i = 0} }, { TERMMOD, XK_Y, selpaste, {.i = 0} }, @@ -208,10 +217,6 @@ static Shortcut shortcuts[] = { * * 0: no value * * > 0: cursor application mode enabled * * < 0: cursor application mode disabled - * crlf value - * * 0: no value - * * > 0: crlf mode is enabled - * * < 0: crlf mode is disabled * * Be careful with the order of the definitions because st searches in * this table sequentially, so any XK_ANY_MOD must be in the last @@ -230,13 +235,6 @@ static KeySym mappedkeys[] = { -1 }; */ static uint ignoremod = Mod2Mask|XK_SWITCH_MOD; -/* - * Override mouse-select while mask is active (when MODE_MOUSE is set). - * Note that if you want to use ShiftMask with selmasks, set this to an other - * modifier, set to 0 to not use it. - */ -static uint forceselmod = ShiftMask; - /* * This is the huge key array which defines all compatibility to the Linux * world. Please decide about changes wisely. diff --git a/st/st-scrollback-20190122-3be4cf1.diff b/st/st-scrollback-20190122-3be4cf1.diff deleted file mode 100644 index adf522a..0000000 --- a/st/st-scrollback-20190122-3be4cf1.diff +++ /dev/null @@ -1,335 +0,0 @@ -diff --git a/config.def.h b/config.def.h -index 823e79f..f6278a3 100644 ---- a/config.def.h -+++ b/config.def.h -@@ -178,6 +178,8 @@ static Shortcut shortcuts[] = { - { TERMMOD, XK_Y, selpaste, {.i = 0} }, - { ShiftMask, XK_Insert, selpaste, {.i = 0} }, - { TERMMOD, XK_Num_Lock, numlock, {.i = 0} }, -+ { ShiftMask, XK_Page_Up, kscrollup, {.i = -1} }, -+ { ShiftMask, XK_Page_Down, kscrolldown, {.i = -1} }, - }; - - /* -diff --git a/st.c b/st.c -index b8e6077..218ae73 100644 ---- a/st.c -+++ b/st.c -@@ -35,6 +35,7 @@ - #define ESC_ARG_SIZ 16 - #define STR_BUF_SIZ ESC_BUF_SIZ - #define STR_ARG_SIZ ESC_ARG_SIZ -+#define HISTSIZE 2000 - - /* macros */ - #define IS_SET(flag) ((term.mode & (flag)) != 0) -@@ -42,6 +43,9 @@ - #define ISCONTROLC1(c) (BETWEEN(c, 0x80, 0x9f)) - #define ISCONTROL(c) (ISCONTROLC0(c) || ISCONTROLC1(c)) - #define ISDELIM(u) (utf8strchr(worddelimiters, u) != NULL) -+#define TLINE(y) ((y) < term.scr ? term.hist[((y) + term.histi - \ -+ term.scr + HISTSIZE + 1) % HISTSIZE] : \ -+ term.line[(y) - term.scr]) - - enum term_mode { - MODE_WRAP = 1 << 0, -@@ -117,6 +121,9 @@ typedef struct { - int col; /* nb col */ - Line *line; /* screen */ - Line *alt; /* alternate screen */ -+ Line hist[HISTSIZE]; /* history buffer */ -+ int histi; /* history index */ -+ int scr; /* scroll back */ - int *dirty; /* dirtyness of lines */ - TCursor c; /* cursor */ - int ocx; /* old cursor col */ -@@ -184,8 +191,8 @@ static void tnewline(int); - static void tputtab(int); - static void tputc(Rune); - static void treset(void); --static void tscrollup(int, int); --static void tscrolldown(int, int); -+static void tscrollup(int, int, int); -+static void tscrolldown(int, int, int); - static void tsetattr(int *, int); - static void tsetchar(Rune, Glyph *, int, int); - static void tsetdirt(int, int); -@@ -427,10 +434,10 @@ tlinelen(int y) - { - int i = term.col; - -- if (term.line[y][i - 1].mode & ATTR_WRAP) -+ if (TLINE(y)[i - 1].mode & ATTR_WRAP) - return i; - -- while (i > 0 && term.line[y][i - 1].u == ' ') -+ while (i > 0 && TLINE(y)[i - 1].u == ' ') - --i; - - return i; -@@ -539,7 +546,7 @@ selsnap(int *x, int *y, int direction) - * Snap around if the word wraps around at the end or - * beginning of a line. - */ -- prevgp = &term.line[*y][*x]; -+ prevgp = &TLINE(*y)[*x]; - prevdelim = ISDELIM(prevgp->u); - for (;;) { - newx = *x + direction; -@@ -554,14 +561,14 @@ selsnap(int *x, int *y, int direction) - yt = *y, xt = *x; - else - yt = newy, xt = newx; -- if (!(term.line[yt][xt].mode & ATTR_WRAP)) -+ if (!(TLINE(yt)[xt].mode & ATTR_WRAP)) - break; - } - - if (newx >= tlinelen(newy)) - break; - -- gp = &term.line[newy][newx]; -+ gp = &TLINE(newy)[newx]; - delim = ISDELIM(gp->u); - if (!(gp->mode & ATTR_WDUMMY) && (delim != prevdelim - || (delim && gp->u != prevgp->u))) -@@ -582,14 +589,14 @@ selsnap(int *x, int *y, int direction) - *x = (direction < 0) ? 0 : term.col - 1; - if (direction < 0) { - for (; *y > 0; *y += direction) { -- if (!(term.line[*y-1][term.col-1].mode -+ if (!(TLINE(*y-1)[term.col-1].mode - & ATTR_WRAP)) { - break; - } - } - } else if (direction > 0) { - for (; *y < term.row-1; *y += direction) { -- if (!(term.line[*y][term.col-1].mode -+ if (!(TLINE(*y)[term.col-1].mode - & ATTR_WRAP)) { - break; - } -@@ -620,13 +627,13 @@ getsel(void) - } - - if (sel.type == SEL_RECTANGULAR) { -- gp = &term.line[y][sel.nb.x]; -+ gp = &TLINE(y)[sel.nb.x]; - lastx = sel.ne.x; - } else { -- gp = &term.line[y][sel.nb.y == y ? sel.nb.x : 0]; -+ gp = &TLINE(y)[sel.nb.y == y ? sel.nb.x : 0]; - lastx = (sel.ne.y == y) ? sel.ne.x : term.col-1; - } -- last = &term.line[y][MIN(lastx, linelen-1)]; -+ last = &TLINE(y)[MIN(lastx, linelen-1)]; - while (last >= gp && last->u == ' ') - --last; - -@@ -849,6 +856,9 @@ void - ttywrite(const char *s, size_t n, int may_echo) - { - const char *next; -+ Arg arg = (Arg) { .i = term.scr }; -+ -+ kscrolldown(&arg); - - if (may_echo && IS_SET(MODE_ECHO)) - twrite(s, n, 1); -@@ -1060,13 +1070,53 @@ tswapscreen(void) - } - - void --tscrolldown(int orig, int n) -+kscrolldown(const Arg* a) -+{ -+ int n = a->i; -+ -+ if (n < 0) -+ n = term.row + n; -+ -+ if (n > term.scr) -+ n = term.scr; -+ -+ if (term.scr > 0) { -+ term.scr -= n; -+ selscroll(0, -n); -+ tfulldirt(); -+ } -+} -+ -+void -+kscrollup(const Arg* a) -+{ -+ int n = a->i; -+ -+ if (n < 0) -+ n = term.row + n; -+ -+ if (term.scr <= HISTSIZE-n) { -+ term.scr += n; -+ selscroll(0, n); -+ tfulldirt(); -+ } -+} -+ -+void -+tscrolldown(int orig, int n, int copyhist) - { - int i; - Line temp; - - LIMIT(n, 0, term.bot-orig+1); - -+ if (copyhist) { -+ term.histi = (term.histi - 1 + HISTSIZE) % HISTSIZE; -+ temp = term.hist[term.histi]; -+ term.hist[term.histi] = term.line[term.bot]; -+ term.line[term.bot] = temp; -+ } -+ - tsetdirt(orig, term.bot-n); - tclearregion(0, term.bot-n+1, term.col-1, term.bot); - -@@ -1080,13 +1130,23 @@ tscrolldown(int orig, int n) - } - - void --tscrollup(int orig, int n) -+tscrollup(int orig, int n, int copyhist) - { - int i; - Line temp; - - LIMIT(n, 0, term.bot-orig+1); - -+ if (copyhist) { -+ term.histi = (term.histi + 1) % HISTSIZE; -+ temp = term.hist[term.histi]; -+ term.hist[term.histi] = term.line[orig]; -+ term.line[orig] = temp; -+ } -+ -+ if (term.scr > 0 && term.scr < HISTSIZE) -+ term.scr = MIN(term.scr + n, HISTSIZE-1); -+ - tclearregion(0, orig, term.col-1, orig+n-1); - tsetdirt(orig+n, term.bot); - -@@ -1135,7 +1195,7 @@ tnewline(int first_col) - int y = term.c.y; - - if (y == term.bot) { -- tscrollup(term.top, 1); -+ tscrollup(term.top, 1, 1); - } else { - y++; - } -@@ -1300,14 +1360,14 @@ void - tinsertblankline(int n) - { - if (BETWEEN(term.c.y, term.top, term.bot)) -- tscrolldown(term.c.y, n); -+ tscrolldown(term.c.y, n, 0); - } - - void - tdeleteline(int n) - { - if (BETWEEN(term.c.y, term.top, term.bot)) -- tscrollup(term.c.y, n); -+ tscrollup(term.c.y, n, 0); - } - - int32_t -@@ -1737,11 +1797,11 @@ csihandle(void) - break; - case 'S': /* SU -- Scroll line up */ - DEFAULT(csiescseq.arg[0], 1); -- tscrollup(term.top, csiescseq.arg[0]); -+ tscrollup(term.top, csiescseq.arg[0], 0); - break; - case 'T': /* SD -- Scroll line down */ - DEFAULT(csiescseq.arg[0], 1); -- tscrolldown(term.top, csiescseq.arg[0]); -+ tscrolldown(term.top, csiescseq.arg[0], 0); - break; - case 'L': /* IL -- Insert blank lines */ - DEFAULT(csiescseq.arg[0], 1); -@@ -2243,7 +2303,7 @@ eschandle(uchar ascii) - return 0; - case 'D': /* IND -- Linefeed */ - if (term.c.y == term.bot) { -- tscrollup(term.top, 1); -+ tscrollup(term.top, 1, 1); - } else { - tmoveto(term.c.x, term.c.y+1); - } -@@ -2256,7 +2316,7 @@ eschandle(uchar ascii) - break; - case 'M': /* RI -- Reverse index */ - if (term.c.y == term.top) { -- tscrolldown(term.top, 1); -+ tscrolldown(term.top, 1, 1); - } else { - tmoveto(term.c.x, term.c.y-1); - } -@@ -2475,7 +2535,7 @@ twrite(const char *buf, int buflen, int show_ctrl) - void - tresize(int col, int row) - { -- int i; -+ int i, j; - int minrow = MIN(row, term.row); - int mincol = MIN(col, term.col); - int *bp; -@@ -2512,6 +2572,14 @@ tresize(int col, int row) - term.dirty = xrealloc(term.dirty, row * sizeof(*term.dirty)); - term.tabs = xrealloc(term.tabs, col * sizeof(*term.tabs)); - -+ for (i = 0; i < HISTSIZE; i++) { -+ term.hist[i] = xrealloc(term.hist[i], col * sizeof(Glyph)); -+ for (j = mincol; j < col; j++) { -+ term.hist[i][j] = term.c.attr; -+ term.hist[i][j].u = ' '; -+ } -+ } -+ - /* resize each row to new width, zero-pad if needed */ - for (i = 0; i < minrow; i++) { - term.line[i] = xrealloc(term.line[i], col * sizeof(Glyph)); -@@ -2569,7 +2637,7 @@ drawregion(int x1, int y1, int x2, int y2) - continue; - - term.dirty[y] = 0; -- xdrawline(term.line[y], x1, y, x2); -+ xdrawline(TLINE(y), x1, y, x2); - } - } - -@@ -2590,8 +2658,9 @@ draw(void) - cx--; - - drawregion(0, 0, term.col, term.row); -- xdrawcursor(cx, term.c.y, term.line[term.c.y][cx], -- term.ocx, term.ocy, term.line[term.ocy][term.ocx]); -+ if (term.scr == 0) -+ xdrawcursor(cx, term.c.y, term.line[term.c.y][cx], -+ term.ocx, term.ocy, term.line[term.ocy][term.ocx]); - term.ocx = cx, term.ocy = term.c.y; - xfinishdraw(); - } -diff --git a/st.h b/st.h -index 38c61c4..17a79e0 100644 ---- a/st.h -+++ b/st.h -@@ -80,6 +80,8 @@ void die(const char *, ...); - void redraw(void); - void draw(void); - -+void kscrolldown(const Arg *); -+void kscrollup(const Arg *); - void printscreen(const Arg *); - void printsel(const Arg *); - void sendbreak(const Arg *); diff --git a/st/st-scrollback-mouse-0.8.diff b/st/st-scrollback-mouse-0.8.diff deleted file mode 100644 index 3b2729e..0000000 --- a/st/st-scrollback-mouse-0.8.diff +++ /dev/null @@ -1,71 +0,0 @@ -diff --git a/config.def.h b/config.def.h -index 27d42ca..feec7e2 100644 ---- a/config.def.h -+++ b/config.def.h -@@ -156,8 +156,14 @@ static unsigned int defaultattr = 11; - */ - static MouseShortcut mshortcuts[] = { - /* button mask string */ -- { Button4, XK_ANY_MOD, "\031" }, -- { Button5, XK_ANY_MOD, "\005" }, -+ { Button4, XK_NO_MOD, "\031" }, -+ { Button5, XK_NO_MOD, "\005" }, -+}; -+ -+MouseKey mkeys[] = { -+ /* button mask function argument */ -+ { Button4, ShiftMask, kscrollup, {.i = 1} }, -+ { Button5, ShiftMask, kscrolldown, {.i = 1} }, - }; - - /* Internal keyboard shortcuts. */ -diff --git a/st.h b/st.h -index 628e876..cdd25ae 100644 ---- a/st.h -+++ b/st.h -@@ -81,6 +81,13 @@ typedef union { - const void *v; - } Arg; - -+typedef struct { -+ uint b; -+ uint mask; -+ void (*func)(const Arg *); -+ const Arg arg; -+} MouseKey; -+ - void die(const char *, ...); - void redraw(void); - void draw(void); -@@ -129,3 +136,4 @@ extern char *termname; - extern unsigned int tabspaces; - extern unsigned int defaultfg; - extern unsigned int defaultbg; -+extern MouseKey mkeys[]; -diff --git a/x.c b/x.c -index d43a529..754d859 100644 ---- a/x.c -+++ b/x.c -@@ -409,6 +409,7 @@ bpress(XEvent *e) - { - struct timespec now; - MouseShortcut *ms; -+ MouseKey *mk; - int snap; - - if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forceselmod)) { -@@ -424,6 +425,14 @@ bpress(XEvent *e) - } - } - -+ for (mk = mkeys; mk < mkeys + LEN(mkeys); mk++) { -+ if (e->xbutton.button == mk->b -+ && match(mk->mask, e->xbutton.state)) { -+ mk->func(&mk->arg); -+ return; -+ } -+ } -+ - if (e->xbutton.button == Button1) { - /* - * If the user clicks below predefined timeouts specific diff --git a/st/st-scrollback-mouse-altscreen-20190131-e23acb9.diff b/st/st-scrollback-mouse-altscreen-20190131-e23acb9.diff deleted file mode 100644 index e9d9d21..0000000 --- a/st/st-scrollback-mouse-altscreen-20190131-e23acb9.diff +++ /dev/null @@ -1,66 +0,0 @@ -diff --git a/config.def.h b/config.def.h -index a6d2fb9..16830c8 100644 ---- a/config.def.h -+++ b/config.def.h -@@ -162,8 +162,8 @@ static MouseShortcut mshortcuts[] = { - - MouseKey mkeys[] = { - /* button mask function argument */ -- { Button4, ShiftMask, kscrollup, {.i = 1} }, -- { Button5, ShiftMask, kscrolldown, {.i = 1} }, -+ { Button4, XK_NO_MOD, kscrollup, {.i = 1} }, -+ { Button5, XK_NO_MOD, kscrolldown, {.i = 1} }, - }; - - /* Internal keyboard shortcuts. */ -diff --git a/st.c b/st.c -index 218ae73..f543305 100644 ---- a/st.c -+++ b/st.c -@@ -1058,6 +1058,11 @@ tnew(int col, int row) - treset(); - } - -+int tisaltscr(void) -+{ -+ return IS_SET(MODE_ALTSCREEN); -+} -+ - void - tswapscreen(void) - { -diff --git a/st.h b/st.h -index 3592957..23f4ca3 100644 ---- a/st.h -+++ b/st.h -@@ -95,6 +95,7 @@ void sendbreak(const Arg *); - void toggleprinter(const Arg *); - - int tattrset(int); -+int tisaltscr(void); - void tnew(int, int); - void tresize(int, int); - void tsetdirtattr(int); -diff --git a/x.c b/x.c -index e9fd6e9..2dc315e 100644 ---- a/x.c -+++ b/x.c -@@ -417,11 +417,13 @@ bpress(XEvent *e) - return; - } - -- for (ms = mshortcuts; ms < mshortcuts + LEN(mshortcuts); ms++) { -- if (e->xbutton.button == ms->b -- && match(ms->mask, e->xbutton.state)) { -- ttywrite(ms->s, strlen(ms->s), 1); -- return; -+ if (tisaltscr()) { -+ for (ms = mshortcuts; ms < mshortcuts + LEN(mshortcuts); ms++) { -+ if (e->xbutton.button == ms->b -+ && match(ms->mask, e->xbutton.state)) { -+ ttywrite(ms->s, strlen(ms->s), 1); -+ return; -+ } - } - } - diff --git a/st/st.c b/st/st.c index aa2cbeb..7de1369 100644 --- a/st/st.c +++ b/st/st.c @@ -42,7 +42,7 @@ #define ISCONTROLC0(c) (BETWEEN(c, 0, 0x1f) || (c) == '\177') #define ISCONTROLC1(c) (BETWEEN(c, 0x80, 0x9f)) #define ISCONTROL(c) (ISCONTROLC0(c) || ISCONTROLC1(c)) -#define ISDELIM(u) (utf8strchr(worddelimiters, u) != NULL) +#define ISDELIM(u) (u && wcschr(worddelimiters, u)) #define TLINE(y) ((y) < term.scr ? term.hist[((y) + term.histi - \ term.scr + HISTSIZE + 1) % HISTSIZE] : \ term.line[(y) - term.scr]) @@ -142,7 +142,7 @@ typedef struct { /* ESC '[' [[ [] [;]] []] */ typedef struct { char buf[ESC_BUF_SIZ]; /* raw string */ - int len; /* raw string length */ + size_t len; /* raw string length */ char priv; int arg[ESC_ARG_SIZ]; int narg; /* nb of args */ @@ -153,8 +153,9 @@ typedef struct { /* ESC type [[ [] [;]] ] ESC '\' */ typedef struct { char type; /* ESC type ... */ - char buf[STR_BUF_SIZ]; /* raw string */ - int len; /* raw string length */ + char *buf; /* allocated raw string */ + size_t siz; /* allocation size */ + size_t len; /* raw string length */ char *args[STR_ARG_SIZ]; int narg; /* nb of args */ } STREscape; @@ -217,7 +218,6 @@ static void selsnap(int *, int *, int); static size_t utf8decode(const char *, Rune *, size_t); static Rune utf8decodebyte(char, size_t *); static char utf8encodebyte(Rune, size_t); -static char *utf8strchr(char *, Rune); static size_t utf8validate(Rune *, size_t); static char *base64dec(const char *); @@ -344,23 +344,6 @@ utf8encodebyte(Rune u, size_t i) return utfbyte[i] | (u & ~utfmask[i]); } -char * -utf8strchr(char *s, Rune u) -{ - Rune r; - size_t i, j, len; - - len = strlen(s); - for (i = 0, j = 0; i < len; i += j) { - if (!(j = utf8decode(&s[i], &r, len - i))) - break; - if (r == u) - return &(s[i]); - } - - return NULL; -} - size_t utf8validate(Rune *u, size_t i) { @@ -391,7 +374,7 @@ char base64dec_getc(const char **src) { while (**src && !isprint(**src)) (*src)++; - return *((*src)++); + return **src ? *((*src)++) : '='; /* emulate padding if string ends */ } char * @@ -409,6 +392,10 @@ base64dec(const char *src) int c = base64_digits[(unsigned char) base64dec_getc(&src)]; int d = base64_digits[(unsigned char) base64dec_getc(&src)]; + /* invalid input. 'a' can be -1, e.g. if src is "\n" (c-str) */ + if (a == -1 || b == -1) + break; + *dst++ = (a << 2) | ((b & 0x30) >> 4); if (c == -1) break; @@ -483,7 +470,7 @@ selextend(int col, int row, int type, int done) selnormalize(); sel.type = type; - if (oldey != sel.oe.y || oldex != sel.oe.x || oldtype != sel.type) + if (oldey != sel.oe.y || oldex != sel.oe.x || oldtype != sel.type || sel.mode == SEL_EMPTY) tsetdirt(MIN(sel.nb.y, oldsby), MAX(sel.ne.y, oldsey)); sel.mode = done ? SEL_IDLE : SEL_READY; @@ -1640,6 +1627,7 @@ tsetmode(int priv, int set, int *args, int narg) case 1015: /* urxvt mangled mouse mode; incompatible and can be mistaken for other control codes. */ + break; default: fprintf(stderr, "erresc: unknown private set/reset mode %d\n", @@ -1881,7 +1869,7 @@ csihandle(void) void csidump(void) { - int i; + size_t i; uint c; fprintf(stderr, "ESC["); @@ -1911,7 +1899,7 @@ csireset(void) void strhandle(void) { - char *p = NULL; + char *p = NULL, *dec; int j, narg, par; term.esc &= ~(ESC_STR_END|ESC_STR); @@ -1929,8 +1917,6 @@ strhandle(void) return; case 52: if (narg > 2) { - char *dec; - dec = base64dec(strescseq.args[2]); if (dec) { xsetsel(dec); @@ -1948,7 +1934,10 @@ strhandle(void) case 104: /* color reset, here p = NULL */ j = (narg > 1) ? atoi(strescseq.args[1]) : -1; if (xsetcolorname(j, p)) { - fprintf(stderr, "erresc: invalid color %s\n", p); + if (par == 104 && narg <= 1) + return; /* color reset without parameter */ + fprintf(stderr, "erresc: invalid color j=%d, p=%s\n", + j, p ? p : "(null)"); } else { /* * TODO if defaultbg color is changed, borders @@ -1998,7 +1987,7 @@ strparse(void) void strdump(void) { - int i; + size_t i; uint c; fprintf(stderr, "ESC%c", strescseq.type); @@ -2025,7 +2014,10 @@ strdump(void) void strreset(void) { - memset(&strescseq, 0, sizeof(strescseq)); + strescseq = (STREscape){ + .buf = xrealloc(strescseq.buf, STR_BUF_SIZ), + .siz = STR_BUF_SIZ, + }; } void @@ -2400,7 +2392,6 @@ tputc(Rune u) goto check_control_code; } - if (IS_SET(MODE_SIXEL)) { /* TODO: implement sixel mode */ return; @@ -2408,7 +2399,7 @@ tputc(Rune u) if (term.esc&ESC_DCS && strescseq.len == 0 && u == 'q') term.mode |= MODE_SIXEL; - if (strescseq.len+len >= sizeof(strescseq.buf)-1) { + if (strescseq.len+len >= strescseq.siz) { /* * Here is a bug in terminals. If the user never sends * some code to stop the str or esc command, then st @@ -2422,7 +2413,10 @@ tputc(Rune u) * term.esc = 0; * strhandle(); */ - return; + if (strescseq.siz > (SIZE_MAX - UTF_SIZ) / 2) + return; + strescseq.siz *= 2; + strescseq.buf = xrealloc(strescseq.buf, strescseq.siz); } memmove(&strescseq.buf[strescseq.len], c, len); diff --git a/st/st.h b/st/st.h index 3febb97..3c3b7a5 100644 --- a/st/st.h +++ b/st/st.h @@ -6,7 +6,7 @@ /* macros */ #define MIN(a, b) ((a) < (b) ? (a) : (b)) #define MAX(a, b) ((a) < (b) ? (b) : (a)) -#define LEN(a) (sizeof(a) / sizeof(a)[0]) +#define LEN(a) (sizeof(a) / sizeof(a)[0]) #define BETWEEN(x, a, b) ((a) <= (x) && (x) <= (b)) #define DIVCEIL(n, d) (((n) + ((d) - 1)) / (d)) #define DEFAULT(a, b) (a) = (a) ? (a) : (b) @@ -74,15 +74,9 @@ typedef union { uint ui; float f; const void *v; + const char *s; } Arg; -typedef struct { - uint b; - uint mask; - void (*func)(const Arg *); - const Arg arg; -} MouseKey; - void die(const char *, ...); void redraw(void); void draw(void); @@ -124,11 +118,10 @@ char *xstrdup(char *); extern char *utmp; extern char *stty_args; extern char *vtiden; -extern char *worddelimiters; +extern wchar_t *worddelimiters; extern int allowaltscreen; extern char *termname; extern unsigned int tabspaces; extern unsigned int alpha; extern unsigned int defaultfg; extern unsigned int defaultbg; -extern MouseKey mkeys[]; diff --git a/st/st.info b/st/st.info index 52fc617..78ffd30 100644 --- a/st/st.info +++ b/st/st.info @@ -189,10 +189,10 @@ st| simpleterm, rmxx=\E[29m, smxx=\E[9m, # tmux extensions, see TERMINFO EXTENSIONS in tmux(1) - Se, - Ss, Tc, Ms=\E]52;%p1%s;%p2%s\007, + Se=\E[2 q, + Ss=\E[%p1%d q, st-256color| simpleterm with 256 colors, use=st, diff --git a/st/x.c b/st/x.c index 3691449..35fa064 100644 --- a/st/x.c +++ b/st/x.c @@ -29,9 +29,12 @@ typedef struct { } Shortcut; typedef struct { - uint b; - uint mask; - char *s; + uint mod; + uint button; + void (*func)(const Arg *); + const Arg arg; + uint release; + int altscrn; /* 0: don't care, -1: not alt screen, 1: alt screen */ } MouseShortcut; typedef struct { @@ -60,6 +63,7 @@ static void selpaste(const Arg *); static void zoom(const Arg *); static void zoomabs(const Arg *); static void zoomreset(const Arg *); +static void ttysend(const Arg *); /* config.h for applying patches and the configuration. */ #include "config.h" @@ -95,8 +99,12 @@ typedef struct { Drawable buf; GlyphFontSpec *specbuf; /* font spec buffer used for rendering */ Atom xembed, wmdeletewin, netwmname, netwmpid; - XIM xim; - XIC xic; + struct { + XIM xim; + XIC xic; + XPoint spot; + XVaNestedList spotlist; + } ime; Draw draw; Visual *vis; XSetWindowAttributes attrs; @@ -144,9 +152,10 @@ static void xdrawglyphfontspecs(const XftGlyphFontSpec *, Glyph, int, int, int); static void xdrawglyph(Glyph, int, int); static void xclear(int, int, int, int); static int xgeommasktogravity(int); -static void ximopen(Display *); +static int ximopen(Display *); static void ximinstantiate(Display *, XPointer, XPointer); static void ximdestroy(XIM, XPointer, XPointer); +static int xicdestroy(XIC, XPointer, XPointer); static void xinit(int, int); static void cresize(int, int); static void xresize(int, int); @@ -154,6 +163,8 @@ static void xhints(void); static int xloadcolor(int, const char *, Color *); static int xloadfont(Font *, FcPattern *); static void xloadfonts(char *, double); +static int xloadsparefont(FcPattern *, int); +static void xloadsparefonts(void); static void xunloadfont(Font *); static void xunloadfonts(void); static void xsetenv(void); @@ -168,6 +179,7 @@ static void kpress(XEvent *); static void cmessage(XEvent *); static void resize(XEvent *); static void focus(XEvent *); +static int mouseaction(XEvent *, uint); static void brelease(XEvent *); static void bpress(XEvent *); static void bmotion(XEvent *); @@ -231,8 +243,9 @@ typedef struct { } Fontcache; /* Fontcache is an array now. A new font will be appended to the array. */ -static Fontcache frc[16]; +static Fontcache *frc = NULL; static int frclen = 0; +static int frccap = 0; static char *usedfont = NULL; static double usedfontsize = 0; static double defaultfontsize = 0; @@ -300,6 +313,7 @@ zoomabs(const Arg *arg) { xunloadfonts(); xloadfonts(usedfont, arg->f); + xloadsparefonts(); cresize(0, 0); redraw(); xhints(); @@ -316,6 +330,12 @@ zoomreset(const Arg *arg) } } +void +ttysend(const Arg *arg) +{ + ttywrite(arg->s, strlen(arg->s), 1); +} + int evcol(XEvent *e) { @@ -336,7 +356,7 @@ void mousesel(XEvent *e, int done) { int type, seltype = SEL_REGULAR; - uint state = e->xbutton.state & ~(Button1Mask | forceselmod); + uint state = e->xbutton.state & ~(Button1Mask | forcemousemod); for (type = 1; type < LEN(selmasks); ++type) { if (match(selmasks[type], state)) { @@ -412,36 +432,38 @@ mousereport(XEvent *e) ttywrite(buf, len, 0); } +int +mouseaction(XEvent *e, uint release) +{ + MouseShortcut *ms; + + for (ms = mshortcuts; ms < mshortcuts + LEN(mshortcuts); ms++) { + if (ms->release == release && + ms->button == e->xbutton.button && + (!ms->altscrn || (ms->altscrn == (tisaltscr() ? 1 : -1))) && + (match(ms->mod, e->xbutton.state) || /* exact or forced */ + match(ms->mod, e->xbutton.state & ~forcemousemod))) { + ms->func(&(ms->arg)); + return 1; + } + } + + return 0; +} + void bpress(XEvent *e) { struct timespec now; - MouseShortcut *ms; - MouseKey *mk; int snap; - if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forceselmod)) { + if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forcemousemod)) { mousereport(e); return; } - if (tisaltscr()) { - for (ms = mshortcuts; ms < mshortcuts + LEN(mshortcuts); ms++) { - if (e->xbutton.button == ms->b - && match(ms->mask, e->xbutton.state)) { - ttywrite(ms->s, strlen(ms->s), 1); - return; - } - } - } - - for (mk = mkeys; mk < mkeys + LEN(mkeys); mk++) { - if (e->xbutton.button == mk->b - && match(mk->mask, e->xbutton.state)) { - mk->func(&mk->arg); - return; - } - } + if (mouseaction(e, 0)) + return; if (e->xbutton.button == Button1) { /* @@ -657,21 +679,21 @@ xsetsel(char *str) void brelease(XEvent *e) { - if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forceselmod)) { + if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forcemousemod)) { mousereport(e); return; } - if (e->xbutton.button == Button2) - selpaste(NULL); - else if (e->xbutton.button == Button1) + if (mouseaction(e, 1)) + return; + if (e->xbutton.button == Button1) mousesel(e, 1); } void bmotion(XEvent *e) { - if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forceselmod)) { + if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forcemousemod)) { mousereport(e); return; } @@ -786,7 +808,6 @@ xsetcolorname(int x, const char *name) if (!BETWEEN(x, 0, dc.collen)) return 1; - if (!xloadcolor(x, name, &ncolor)) return 1; @@ -1012,6 +1033,101 @@ xloadfonts(char *fontstr, double fontsize) FcPatternDestroy(pattern); } +int +xloadsparefont(FcPattern *pattern, int flags) +{ + FcPattern *match; + FcResult result; + + match = FcFontMatch(NULL, pattern, &result); + if (!match) { + return 1; + } + + if (!(frc[frclen].font = XftFontOpenPattern(xw.dpy, match))) { + FcPatternDestroy(match); + return 1; + } + + frc[frclen].flags = flags; + /* Believe U+0000 glyph will present in each default font */ + frc[frclen].unicodep = 0; + frclen++; + + return 0; +} + +void +xloadsparefonts(void) +{ + FcPattern *pattern; + double sizeshift, fontval; + int fc; + char **fp; + + if (frclen != 0) + die("can't embed spare fonts. cache isn't empty"); + + /* Calculate count of spare fonts */ + fc = sizeof(font2) / sizeof(*font2); + if (fc == 0) + return; + + /* Allocate memory for cache entries. */ + if (frccap < 4 * fc) { + frccap += 4 * fc - frccap; + frc = xrealloc(frc, frccap * sizeof(Fontcache)); + } + + for (fp = font2; fp - font2 < fc; ++fp) { + + if (**fp == '-') + pattern = XftXlfdParse(*fp, False, False); + else + pattern = FcNameParse((FcChar8 *)*fp); + + if (!pattern) + die("can't open spare font %s\n", *fp); + + if (defaultfontsize > 0) { + sizeshift = usedfontsize - defaultfontsize; + if (sizeshift != 0 && + FcPatternGetDouble(pattern, FC_PIXEL_SIZE, 0, &fontval) == + FcResultMatch) { + fontval += sizeshift; + FcPatternDel(pattern, FC_PIXEL_SIZE); + FcPatternDel(pattern, FC_SIZE); + FcPatternAddDouble(pattern, FC_PIXEL_SIZE, fontval); + } + } + + FcPatternAddBool(pattern, FC_SCALABLE, 1); + + FcConfigSubstitute(NULL, pattern, FcMatchPattern); + XftDefaultSubstitute(xw.dpy, xw.scr, pattern); + + if (xloadsparefont(pattern, FRC_NORMAL)) + die("can't open spare font %s\n", *fp); + + FcPatternDel(pattern, FC_SLANT); + FcPatternAddInteger(pattern, FC_SLANT, FC_SLANT_ITALIC); + if (xloadsparefont(pattern, FRC_ITALIC)) + die("can't open spare font %s\n", *fp); + + FcPatternDel(pattern, FC_WEIGHT); + FcPatternAddInteger(pattern, FC_WEIGHT, FC_WEIGHT_BOLD); + if (xloadsparefont(pattern, FRC_ITALICBOLD)) + die("can't open spare font %s\n", *fp); + + FcPatternDel(pattern, FC_SLANT); + FcPatternAddInteger(pattern, FC_SLANT, FC_SLANT_ROMAN); + if (xloadsparefont(pattern, FRC_BOLD)) + die("can't open spare font %s\n", *fp); + + FcPatternDestroy(pattern); + } +} + void xunloadfont(Font *f) { @@ -1034,41 +1150,58 @@ xunloadfonts(void) xunloadfont(&dc.ibfont); } -void +int ximopen(Display *dpy) { - XIMCallback destroy = { .client_data = NULL, .callback = ximdestroy }; + XIMCallback imdestroy = { .client_data = NULL, .callback = ximdestroy }; + XICCallback icdestroy = { .client_data = NULL, .callback = xicdestroy }; - if ((xw.xim = XOpenIM(xw.dpy, NULL, NULL, NULL)) == NULL) { - XSetLocaleModifiers("@im=local"); - if ((xw.xim = XOpenIM(xw.dpy, NULL, NULL, NULL)) == NULL) { - XSetLocaleModifiers("@im="); - if ((xw.xim = XOpenIM(xw.dpy, NULL, NULL, NULL)) == NULL) - die("XOpenIM failed. Could not open input device.\n"); - } + xw.ime.xim = XOpenIM(xw.dpy, NULL, NULL, NULL); + if (xw.ime.xim == NULL) + return 0; + + if (XSetIMValues(xw.ime.xim, XNDestroyCallback, &imdestroy, NULL)) + fprintf(stderr, "XSetIMValues: " + "Could not set XNDestroyCallback.\n"); + + xw.ime.spotlist = XVaCreateNestedList(0, XNSpotLocation, &xw.ime.spot, + NULL); + + if (xw.ime.xic == NULL) { + xw.ime.xic = XCreateIC(xw.ime.xim, XNInputStyle, + XIMPreeditNothing | XIMStatusNothing, + XNClientWindow, xw.win, + XNDestroyCallback, &icdestroy, + NULL); } - if (XSetIMValues(xw.xim, XNDestroyCallback, &destroy, NULL) != NULL) - die("XSetIMValues failed. Could not set input method value.\n"); - xw.xic = XCreateIC(xw.xim, XNInputStyle, XIMPreeditNothing | XIMStatusNothing, - XNClientWindow, xw.win, XNFocusWindow, xw.win, NULL); - if (xw.xic == NULL) - die("XCreateIC failed. Could not obtain input method.\n"); + if (xw.ime.xic == NULL) + fprintf(stderr, "XCreateIC: Could not create input context.\n"); + + return 1; } void ximinstantiate(Display *dpy, XPointer client, XPointer call) { - ximopen(dpy); - XUnregisterIMInstantiateCallback(xw.dpy, NULL, NULL, NULL, - ximinstantiate, NULL); + if (ximopen(dpy)) + XUnregisterIMInstantiateCallback(xw.dpy, NULL, NULL, NULL, + ximinstantiate, NULL); } void ximdestroy(XIM xim, XPointer client, XPointer call) { - xw.xim = NULL; + xw.ime.xim = NULL; XRegisterIMInstantiateCallback(xw.dpy, NULL, NULL, NULL, - ximinstantiate, NULL); + ximinstantiate, NULL); + XFree(xw.ime.spotlist); +} + +int +xicdestroy(XIC xim, XPointer client, XPointer call) +{ + xw.ime.xic = NULL; + return 1; } void @@ -1125,6 +1258,9 @@ xinit(int cols, int rows) usedfont = (opt_font == NULL)? font : opt_font; xloadfonts(usedfont, 0); + /* spare fonts */ + xloadsparefonts(); + /* colors */ if (!USE_ARGB) xw.cmap = XDefaultColormap(xw.dpy, xw.scr); @@ -1172,7 +1308,10 @@ xinit(int cols, int rows) xw.draw = XftDrawCreate(xw.dpy, xw.buf, xw.vis, xw.cmap); /* input methods */ - ximopen(xw.dpy); + if (!ximopen(xw.dpy)) { + XRegisterIMInstantiateCallback(xw.dpy, NULL, NULL, NULL, + ximinstantiate, NULL); + } /* white cursor, black outline */ cursor = XCreateFontCursor(xw.dpy, mouseshape); @@ -1203,8 +1342,8 @@ xinit(int cols, int rows) win.mode = MODE_NUMLOCK; resettitle(); - XMapWindow(xw.dpy, xw.win); xhints(); + XMapWindow(xw.dpy, xw.win); XSync(xw.dpy, False); clock_gettime(CLOCK_MONOTONIC, &xsel.tclick1); @@ -1314,13 +1453,10 @@ xmakeglyphfontspecs(XftGlyphFontSpec *specs, const Glyph *glyphs, int len, int x fontpattern = FcFontSetMatch(0, fcsets, 1, fcpattern, &fcres); - /* - * Overwrite or create the new cache entry. - */ - if (frclen >= LEN(frc)) { - frclen = LEN(frc) - 1; - XftFontClose(xw.dpy, frc[frclen].font); - frc[frclen].unicodep = 0; + /* Allocate memory for the new cache entry. */ + if (frclen >= frccap) { + frccap += 16; + frc = xrealloc(frc, frccap * sizeof(Fontcache)); } frc[frclen].font = XftFontOpenPattern(xw.dpy, @@ -1653,11 +1789,13 @@ xfinishdraw(void) void xximspot(int x, int y) { - XPoint spot = { borderpx + x * win.cw, borderpx + (y + 1) * win.ch }; - XVaNestedList attr = XVaCreateNestedList(0, XNSpotLocation, &spot, NULL); + if (xw.ime.xic == NULL) + return; - XSetICValues(xw.xic, XNPreeditAttributes, attr, NULL); - XFree(attr); + xw.ime.spot.x = borderpx + x * win.cw; + xw.ime.spot.y = borderpx + (y + 1) * win.ch; + + XSetICValues(xw.ime.xic, XNPreeditAttributes, xw.ime.spotlist, NULL); } void @@ -1734,13 +1872,15 @@ focus(XEvent *ev) return; if (ev->type == FocusIn) { - XSetICFocus(xw.xic); + if (xw.ime.xic) + XSetICFocus(xw.ime.xic); win.mode |= MODE_FOCUSED; xseturgency(0); if (IS_SET(MODE_FOCUS)) ttywrite("\033[I", 3, 0); } else { - XUnsetICFocus(xw.xic); + if (xw.ime.xic) + XUnsetICFocus(xw.ime.xic); win.mode &= ~MODE_FOCUSED; if (IS_SET(MODE_FOCUS)) ttywrite("\033[O", 3, 0); @@ -1795,7 +1935,7 @@ kpress(XEvent *ev) { XKeyEvent *e = &ev->xkey; KeySym ksym; - char buf[32], *customkey; + char buf[64], *customkey; int len; Rune c; Status status; @@ -1804,7 +1944,10 @@ kpress(XEvent *ev) if (IS_SET(MODE_KBDLOCK)) return; - len = XmbLookupString(xw.xic, e, buf, sizeof buf, &ksym, &status); + if (xw.ime.xic) + len = XmbLookupString(xw.ime.xic, e, buf, sizeof buf, &ksym, &status); + else + len = XLookupString(e, buf, sizeof buf, &ksym, NULL); /* 1. shortcuts */ for (bp = shortcuts; bp < shortcuts + LEN(shortcuts); bp++) { if (ksym == bp->keysym && match(bp->mod, e->state)) { @@ -1837,7 +1980,6 @@ kpress(XEvent *ev) ttywrite(buf, len, 1); } - void cmessage(XEvent *e) { diff --git a/surf/config.h b/surf/config.h index 6d4813c..a8fc6ad 100755 --- a/surf/config.h +++ b/surf/config.h @@ -122,6 +122,8 @@ static WebKitFindOptions findopts = WEBKIT_FIND_OPTIONS_CASE_INSENSITIVE | static SiteSpecific styles[] = { /* regexp file in $styledir */ /* { ".*", "default.css" }, */ + { ".*arcolinux.info.*", "arcolinux-info.css" }, + { ".*arcolinuxforum.com.*", "arcolinuxforum.css" }, { ".*suckless.org.*", "suckless.css" }, { ".*wikipedia.org.*", "wikipedia.css" }, };