Refactored dwm

This commit is contained in:
Clay Gomera 2022-07-20 10:51:13 -04:00
parent 0aadcb22e7
commit 57cecd9032
9 changed files with 326 additions and 277 deletions

View file

@ -63,7 +63,8 @@ static const Rule rules[] = {
static const float mfact = 0.50; /* factor of master area size [0.05..0.95] */ 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 nmaster = 1; /* number of clients in master area */
static const int resizehints = 0; /* 1 means respect size hints in tiled resizals */ static const int resizehints = 0; /* 1 means respect size hints in tiled resizals */
#include "layouts.c" static const int lockfullscreen = 1; /* 1 will force focus on the fullscreen window */
#include "grid.c"
static const Layout layouts[] = { static const Layout layouts[] = {
/* symbol arrange function */ /* symbol arrange function */
{ "[]=", tile }, /* first entry is default */ { "[]=", tile }, /* first entry is default */
@ -77,13 +78,12 @@ static const Layout layouts[] = {
/* |||--- VARIABLES ---||| */ /* |||--- VARIABLES ---||| */
/* key definitions */ /* key definitions */
#define MODKEY Mod4Mask #define MODKEY Mod4Mask
#define TAGKEYS(CHAIN,KEY,TAG) \ #define TAGKEYS(KEY,TAG) \
{ MODKEY, CHAIN, KEY, view, {.ui = 1 << TAG} }, \ {1, {{MODKEY, KEY}}, view, {.ui = 1 << TAG} }, \
{ MODKEY|ControlMask, CHAIN, KEY, toggleview, {.ui = 1 << TAG} }, \ {1, {{MODKEY|ControlMask, KEY}}, toggleview, {.ui = 1 << TAG} }, \
{ MODKEY|ShiftMask, CHAIN, KEY, tag, {.ui = 1 << TAG} }, \ {1, {{MODKEY|ShiftMask, KEY}}, tag, {.ui = 1 << TAG} }, \
{ MODKEY|ControlMask|ShiftMask, CHAIN, KEY, toggletag, {.ui = 1 << TAG} }, {1, {{MODKEY|ControlMask|ShiftMask, KEY}}, toggletag, {.ui = 1 << TAG} },
/* helper for spawning shell commands in the pre dwm-5.0 fashion */ /* helper for spawning shell commands in the pre dwm-5.0 fashion */
#define CMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } }
#define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } } #define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } }
/* dmenu */ /* dmenu */
static char dmenumon[2] = "0"; /* component of dmenucmd, manipulated in spawn() */ static char dmenumon[2] = "0"; /* component of dmenucmd, manipulated in spawn() */
@ -93,160 +93,160 @@ static const char *termcmd[] = { "alacritty", NULL };
/* |||--- KEY BIDINGS ---||| */ /* |||--- KEY BIDINGS ---||| */
static Key keys[] = { static Keychord keychords[] = {
/* modifier chain key key function argument */ /* modifier chain key key function argument */
/* Terminal */ /* Terminal */
{ MODKEY, -1, XK_Return, spawn, {.v = termcmd } }, {1, {{MODKEY, XK_Return}}, spawn, {.v = termcmd } },
/* Top bar toggle */ /* Top bar toggle */
{ MODKEY, -1, XK_b, togglebar, {0} }, {1, {{MODKEY|ShiftMask, XK_b}}, togglebar, {0} },
/* WINDOW TAG AND LAYOUT MANIPULATION */ /* WINDOW TAG AND LAYOUT MANIPULATION */
/* Tag Bindings */ /* Tag Bindings */
TAGKEYS( -1, XK_1, 0) TAGKEYS( XK_1, 0)
TAGKEYS( -1, XK_2, 1) TAGKEYS( XK_2, 1)
TAGKEYS( -1, XK_3, 2) TAGKEYS( XK_3, 2)
TAGKEYS( -1, XK_4, 3) TAGKEYS( XK_4, 3)
TAGKEYS( -1, XK_5, 4) TAGKEYS( XK_5, 4)
TAGKEYS( -1, XK_6, 5) TAGKEYS( XK_6, 5)
TAGKEYS( -1, XK_7, 6) TAGKEYS( XK_7, 6)
TAGKEYS( -1, XK_8, 7) TAGKEYS( XK_8, 7)
TAGKEYS( -1, XK_9, 8) TAGKEYS( XK_9, 8)
/* Close Window */ /* Close Window */
{ MODKEY, -1, XK_q, killclient, {0} }, {1, {{MODKEY|ShiftMask, XK_c}}, killclient, {0} },
/* Cycle between tags */ /* Cycle between tags */
{ MODKEY|ControlMask, -1, XK_Tab, view, {0} }, {1, {{MODKEY|ControlMask, XK_Tab}}, view, {0} },
/* Window moving */ /* Window moving */
{ MODKEY|ShiftMask, -1, XK_j, rotatestack, {.i = +1 } }, {1, {{MODKEY|ShiftMask, XK_j}}, rotatestack, {.i = +1 } },
{ MODKEY|ShiftMask, -1, XK_k, rotatestack, {.i = -1 } }, {1, {{MODKEY|ShiftMask, XK_k}}, rotatestack, {.i = -1 } },
/* Window focusing */ /* Window focusing */
{ MODKEY, -1, XK_j, focusstack, {.i = +1 } }, {1, {{MODKEY, XK_j}}, focusstack, {.i = +1 } },
{ MODKEY, -1, XK_k, focusstack, {.i = -1 } }, {1, {{MODKEY, XK_k}}, focusstack, {.i = -1 } },
/* Increase and decrease master windows count */ /* Increase and decrease master windows count */
{ MODKEY, -1, XK_i, incnmaster, {.i = +1 } }, {1, {{MODKEY, XK_i}}, incnmaster, {.i = +1 } },
{ MODKEY, -1, XK_d, incnmaster, {.i = -1 } }, {1, {{MODKEY, XK_d}}, incnmaster, {.i = -1 } },
/* Increase and decrease master window size */ /* Increase and decrease master window size */
{ MODKEY, -1, XK_h, setmfact, {.f = -0.05} }, {1, {{MODKEY, XK_h}}, setmfact, {.f = -0.05} },
{ MODKEY, -1, XK_l, setmfact, {.f = +0.05} }, {1, {{MODKEY, XK_l}}, setmfact, {.f = +0.05} },
/* Move window to master */ /* Move window to master */
{ MODKEY|ControlMask, -1, XK_Return, zoom, {0} }, {1, {{MODKEY|ControlMask, XK_Return}}, zoom, {0} },
/* Cycle between layouts fowards and backwards */ /* Cycle between layouts fowards and backwards */
{ MODKEY, -1, XK_Tab, cyclelayout, {.i = -1 } }, {1, {{ MODKEY, XK_Tab}}, cyclelayout, {.i = -1 } },
{ MODKEY|ShiftMask, -1, XK_Tab, cyclelayout, {.i = +1 } }, {1, {{ MODKEY|ShiftMask, XK_Tab}}, cyclelayout, {.i = +1 } },
/* Cycle between recently used layouts */
{ MODKEY, -1, XK_space, setlayout, {0} },
/* Switch to tiling layout */ /* Switch to tiling layout */
{ MODKEY, -1, XK_t, setlayout, {.v = &layouts[0]} }, {1, {{MODKEY, XK_t}}, setlayout, {.v = &layouts[0]} },
/* Switch to floating layout */ /* Switch to floating layout */
{ MODKEY, -1, XK_f, setlayout, {.v = &layouts[1]} }, {1, {{MODKEY, XK_f}}, setlayout, {.v = &layouts[1]} },
/* Switch to monocle layout */ /* Switch to monocle layout */
{ MODKEY, -1, XK_m, setlayout, {.v = &layouts[2]} }, {1, {{MODKEY, XK_m}}, setlayout, {.v = &layouts[2]} },
/* Switch to grid layout */ /* Switch to grid layout */
{ MODKEY, -1, XK_g, setlayout, {.v = &layouts[3]} }, {1, {{MODKEY, XK_g}}, setlayout, {.v = &layouts[3]} },
/* Toggle floating mode */ /* Toggle floating mode */
{ MODKEY|ShiftMask, -1, XK_space, togglefloating, {0} }, {1, {{MODKEY|ShiftMask, XK_f}}, togglefloating, {0} },
/* Toggle fullscreen mode */
{1, {{MODKEY, XK_space}}, togglefullscr, {0} },
/* View all windows of all tags in the current tag */ /* View all windows of all tags in the current tag */
{ MODKEY, -1, XK_0, view, {.ui = ~0 } }, {1, {{MODKEY, XK_0}}, view, {.ui = ~0 } },
/* Show focused window on all tags */ /* Show focused window on all tags */
{ MODKEY|ShiftMask, -1, XK_0, tag, {.ui = ~0 } }, {1, {{MODKEY|ShiftMask, XK_0}}, tag, {.ui = ~0 } },
/* Focusing between monitors */ /* Focusing between monitors */
{ MODKEY, -1, XK_comma, focusmon, {.i = -1 } }, {1, {{MODKEY, XK_comma}}, focusmon, {.i = -1 } },
{ MODKEY, -1, XK_period, focusmon, {.i = +1 } }, {1, {{MODKEY, XK_period}}, focusmon, {.i = +1 } },
/* Move focused window between monitors */ /* Move focused window between monitors */
{ MODKEY|ShiftMask, -1, XK_comma, tagmon, {.i = -1 } }, {1, {{MODKEY|ShiftMask, XK_comma}}, tagmon, {.i = -1 } },
{ MODKEY|ShiftMask, -1, XK_period, tagmon, {.i = +1 } }, {1, {{MODKEY|ShiftMask, XK_period}}, tagmon, {.i = +1 } },
/* VOLUME CONTROL */ /* VOLUME CONTROL */
/* Toggle mute */ /* Toggle mute */
{ MODKEY, -1, XK_F1, spawn, CMD("pamixer -t") }, {1, {{MODKEY, XK_F1}}, spawn, SHCMD("pamixer -t") },
/* Decrease volume by 5% */ /* Decrease volume by 5% */
{ MODKEY, -1, XK_F2, spawn, CMD("pamixer -d 5") }, {1, {{MODKEY, XK_F2}}, spawn, SHCMD("pamixer -d 5") },
/* Increase volume by 5% */ /* Increase volume by 5% */
{ MODKEY, -1, XK_F3, spawn, CMD("pamixer -i 5") }, {1, {{MODKEY, XK_F3}}, spawn, SHCMD("pamixer -i 5") },
/* Toggle microphone mute */ /* Toggle microphone mute */
{ MODKEY, -1, XK_F4, spawn, CMD("pamixer --default-source -t") }, {1, {{MODKEY, XK_F4}}, spawn, SHCMD("pamixer --default-source -t") },
/* BRIGHTNESS CONTROL */ /* BRIGHTNESS CONTROL */
/* Decrease brightness by 5% */ /* Decrease brightness by 5% */
{ MODKEY, -1, XK_F5, spawn, CMD("xbacklight -dec 10") }, {1, {{MODKEY, XK_F5}}, spawn, SHCMD("xbacklight -dec 10") },
/* Increase brightness by 5% */ /* Increase brightness by 5% */
{ MODKEY, -1, XK_F6, spawn, CMD("xbacklight -inc 10") }, {1, {{MODKEY, XK_F6}}, spawn, SHCMD("xbacklight -inc 10") },
/* Set screen backlight to off */ /* Set screen backlight to off */
{ MODKEY, -1, XK_F7, spawn, CMD("xbacklight -set 0") }, {1, {{MODKEY, XK_F7}}, spawn, SHCMD("xbacklight -set 0") },
/* KEYBOARD LAYOUTS changed with emacs-style keychords SUPER + k (keyboard) followed by "key" */ /* KEYBOARD LAYOUTS changed with emacs-style keychords SUPER + k (keyboard) followed by "key" */
/* Switch to the spanish keyboard layout */ /* Switch to the spanish keyboard layout */
{ MODKEY, XK_k, XK_e, spawn, CMD("setxkbmap -layout es") }, {2, {{MODKEY, XK_k}, {0, XK_e}}, spawn, SHCMD("setxkbmap -layout es") },
/* Switch to the english keyboard layout */ /* Switch to the english keyboard layout */
{ MODKEY, XK_k, XK_u, spawn, CMD("setxkbmap -layout us") }, {2, {{MODKEY, XK_k}, {0, XK_u}}, spawn, SHCMD("setxkbmap -layout us") },
/* EMACS PROGRAMS launched with emacs-style heychords SUPER + e (app) followed by "key" */ /* EMACS PROGRAMS launched with emacs-style heychords SUPER + e (app) followed by "key" */
{ MODKEY, XK_e, XK_e, spawn, CMD("emacsclient -c -a 'emacs'") }, {2, {{MODKEY, XK_e}, {0, XK_e}}, spawn, SHCMD("emacsclient -c -a 'emacs'") },
{ MODKEY, XK_e, XK_b, spawn, CMD("emacsclient -c -a 'emacs' --eval '(ibuffer)'") }, {2, {{MODKEY, XK_e}, {0, XK_b}}, spawn, SHCMD("emacsclient -c -a 'emacs' --eval '(ibuffer)'") },
{ MODKEY, XK_e, XK_d, spawn, CMD("emacsclient -c -a 'emacs' --eval '(dired nil)'") }, {2, {{MODKEY, XK_e}, {0, XK_d}}, spawn, SHCMD("emacsclient -c -a 'emacs' --eval '(dired nil)'") },
{ MODKEY, XK_e, XK_t, spawn, CMD("emacsclient -c -a 'emacs' --eval '(+vterm/here nil)'") }, {2, {{MODKEY, XK_e}, {0, XK_v}}, spawn, SHCMD("emacsclient -c -a 'emacs' --eval '(+vterm/here nil)'") },
{ MODKEY, XK_e, XK_w, spawn, CMD("emacsclient -c -a 'emacs' --eval '(doom/window-maximize-buffer(eww \"gnu.org\"))'") }, {2, {{MODKEY, XK_e}, {0, XK_s}}, spawn, SHCMD("emacsclient -c -a 'emacs' --eval '(eshell)'") },
{ MODKEY, XK_e, XK_s, spawn, CMD("emacsclient -c -a 'emacs' --eval '(eshell)'") }, {2, {{MODKEY, XK_e}, {0, XK_w}}, spawn, SHCMD("emacsclient -c -a 'emacs' --eval '(doom/window-maximize-buffer(eww \"gnu.org\"))'") },
/* PROGRAMS launched with emacs-style keychords SUPER + a (app) followed by "key" */ /* PROGRAMS launched with emacs-style keychords SUPER + a (app) followed by "key" */
/* File manager */ /* File manager */
{ MODKEY, XK_a, XK_f, spawn, CMD("alacritty -t exp --class exp,exp -e $HOME/.config/vifm/scripts/vifmrun") }, {2, {{MODKEY, XK_a}, {0, XK_f}}, spawn, SHCMD("alacritty -t exp --class exp,exp -e $HOME/.config/vifm/scripts/vifmrun") },
/* Web browser */ /* Web browser */
{ MODKEY, XK_a, XK_w, spawn, CMD("qutebrowser") }, {2, {{MODKEY, XK_a}, {0, XK_w}}, spawn, SHCMD("qutebrowser") },
/* Chat app */ /* Chat app */
{ MODKEY, XK_a, XK_c, spawn, CMD("alacritty -t cht --class cht,cht -e gomuks") }, {2, {{MODKEY, XK_a}, {0, XK_c}}, spawn, SHCMD("alacritty -t cht --class cht,cht -e gomuks") },
/* Music player */ /* Music player */
{ MODKEY, XK_a, XK_m, spawn, CMD("alacritty -t msc --class msc,msc -e cmus") }, {2, {{MODKEY, XK_a}, {0, XK_m}}, spawn, SHCMD("alacritty -t msc --class msc,msc -e cmus") },
/* Game app */ /* Game app */
{ MODKEY, XK_a, XK_g, spawn, CMD("retroarch") }, {2, {{MODKEY, XK_a}, {0, XK_g}}, spawn, SHCMD("retroarch") },
/* Virtual machine manager */ /* Virtual machine manager */
{ MODKEY, XK_a, XK_v, spawn, CMD("virt-manager") }, {2, {{MODKEY, XK_a}, {0, XK_v}}, spawn, SHCMD("virt-manager") },
/* MISC PROGRAMS launched with emacs-style keychords SUPER + m (app) followed by "key" */ /* MISC PROGRAMS launched with emacs-style keychords SUPER + m (app) followed by "key" */
/* System monitor btop */ /* System monitor btop */
{ MODKEY, XK_s, XK_b, spawn, CMD("alacritty -t misc --class misc,misc -e btop") }, {2, {{MODKEY, XK_s}, {0, XK_b}}, spawn, SHCMD("alacritty -t misc --class misc,misc -e btop") },
/* System monitor htop */ /* System monitor htop */
{ MODKEY, XK_s, XK_h, spawn, CMD("alacritty -t misc --class misc,misc -e htop") }, {2, {{MODKEY, XK_s}, {0, XK_h}}, spawn, SHCMD("alacritty -t misc --class misc,misc -e htop") },
/* Pulse mixer */ /* Pulse mixer */
{ MODKEY, XK_s, XK_p, spawn, CMD("alacritty -t misc --class misc,misc -e pulsemixer") }, {2, {{MODKEY, XK_s}, {0, XK_p}}, spawn, SHCMD("alacritty -t misc --class misc,misc -e pulsemixer") },
/* Alsa mixer */ /* Alsa mixer */
{ MODKEY, XK_s, XK_m, spawn, CMD("alacritty -t misc --class misc,misc -e alsamixer") }, {2, {{MODKEY, XK_s}, {0, XK_m}}, spawn, SHCMD("alacritty -t misc --class misc,misc -e alsamixer") },
/* Rss reader */ /* Rss reader */
{ MODKEY, XK_s, XK_n, spawn, CMD("alacritty -t misc --class misc,misc -e newsboat") }, {2, {{MODKEY, XK_s}, {0, XK_n}}, spawn, SHCMD("alacritty -t misc --class misc,misc -e newsboat") },
/* Ytfzf */ /* Ytfzf */
{ MODKEY, XK_s, XK_y, spawn, CMD("alacritty -t misc --class misc,misc -e ytfzf -flst") }, {2, {{MODKEY, XK_s}, {0, XK_y}}, spawn, SHCMD("alacritty -t misc --class misc,misc -e ytfzf -flst") },
/* Ani-cli */ /* Ani-cli */
{ MODKEY, XK_s, XK_a, spawn, CMD("alacritty -t misc --class misc,misc -e ani-cli") }, {2, {{MODKEY, XK_s}, {0, XK_a}}, spawn, SHCMD("alacritty -t misc --class misc,misc -e ani-cli") },
/* Flix-cli */ /* Flix-cli */
{ MODKEY, XK_s, XK_f, spawn, CMD("alacritty -t misc --class misc,misc -e flix-cli") }, {2, {{MODKEY, XK_s}, {0, XK_f}}, spawn, SHCMD("alacritty -t misc --class misc,misc -e flix-cli") },
/* Castero */ /* Castero */
{ MODKEY, XK_s, XK_c, spawn, CMD("alacritty -t misc --class misc,misc -e castero") }, {2, {{MODKEY, XK_s}, {0, XK_c}}, spawn, SHCMD("alacritty -t misc --class misc,misc -e castero") },
/* DMENU PROMPTS launched with emacs-style keychords SUPER + p (prompt) followed by "key" */ /* DMENU PROMPTS launched with emacs-style keychords SUPER + p (prompt) followed by "key" */
/* dmenu */ /* dmenu */
{ MODKEY, XK_p, XK_r, spawn, {.v = dmenucmd } }, {2, {{MODKEY, XK_p}, {0, XK_r}}, spawn, {.v = dmenucmd } },
/* dmenu_power */ /* dmenu_power */
{ MODKEY, XK_p, XK_q, spawn, CMD("$HOME/.config/suckless/dmenu/scripts/dmenu_power") }, {2, {{MODKEY, XK_p}, {0, XK_q}}, spawn, SHCMD("$HOME/.config/suckless/dmenu/scripts/dmenu_power") },
/* dmenu_wifi */ /* dmenu_wifi */
{ MODKEY, XK_p, XK_i, spawn, CMD("$HOME/.config/suckless/dmenu/scripts/dmenu_wifi") }, {2, {{MODKEY, XK_p}, {0, XK_i}}, spawn, SHCMD("$HOME/.config/suckless/dmenu/scripts/dmenu_wifi") },
/* dmenu_wall */ /* dmenu_wall */
{ MODKEY, XK_p, XK_w, spawn, CMD("$HOME/.config/suckless/dmenu/scripts/dmenu_wall") }, {2, {{MODKEY, XK_p}, {0, XK_w}}, spawn, SHCMD("$HOME/.config/suckless/dmenu/scripts/dmenu_wall") },
/* dmenu_edit */ /* dmenu_edit */
{ MODKEY, XK_p, XK_e, spawn, CMD("$HOME/.config/suckless/dmenu/scripts/dmenu_edit") }, {2, {{MODKEY, XK_p}, {0, XK_e}}, spawn, SHCMD("$HOME/.config/suckless/dmenu/scripts/dmenu_edit") },
/* dmenu_scrot */ /* dmenu_scrot */
{ MODKEY, XK_p, XK_s, spawn, CMD("$HOME/.config/suckless/dmenu/scripts/dmenu_scrot") }, {2, {{MODKEY, XK_p}, {0, XK_s}}, spawn, SHCMD("$HOME/.config/suckless/dmenu/scripts/dmenu_scrot") },
/* dmenu_drun */ /* dmenu_drun */
{ MODKEY, XK_p, XK_d, spawn, CMD("$HOME/.config/suckless/dmenu/scripts/dmenu_drun") }, {2, {{MODKEY, XK_p}, {0, XK_d}}, spawn, SHCMD("$HOME/.config/suckless/dmenu/scripts/dmenu_drun") },
/* dmenu_blue */ /* dmenu_blue */
{ MODKEY, XK_p, XK_b, spawn, CMD("$HOME/.config/suckless/dmenu/scripts/dmenu_blue") }, {2, {{MODKEY, XK_p}, {0, XK_b}}, spawn, SHCMD("$HOME/.config/suckless/dmenu/scripts/dmenu_blue") },
/* dmenu_emoji */ /* dmenu_emoji */
{ MODKEY, XK_p, XK_z, spawn, CMD("$HOME/.config/suckless/dmenu/scripts/dmenu_emoji") }, {2, {{MODKEY, XK_p}, {0, XK_z}}, spawn, SHCMD("$HOME/.config/suckless/dmenu/scripts/dmenu_emoji") },
/* DWM BOOTSTRAP */ /* DWM BOOTSTRAP */
{ MODKEY|ShiftMask|ControlMask, -1, XK_q, quit, {0} }, {1, {{MODKEY|ControlMask, XK_r}}, quit, {1} },
{ MODKEY|ControlMask, -1, XK_r, quit, {1} }, {1, {{MODKEY|ShiftMask, XK_q}}, quit, {0} },
}; };
/* button definitions */ /* button definitions */

View file

@ -1,3 +1,4 @@
/* See LICENSE file for copyright and license details. */
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@ -97,6 +98,7 @@ drw_free(Drw *drw)
{ {
XFreePixmap(drw->dpy, drw->drawable); XFreePixmap(drw->dpy, drw->drawable);
XFreeGC(drw->dpy, drw->gc); XFreeGC(drw->dpy, drw->gc);
drw_fontset_free(drw->fonts);
free(drw); free(drw);
} }
@ -134,6 +136,19 @@ xfont_create(Drw *drw, const char *fontname, FcPattern *fontpattern)
die("no font specified."); 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 = ecalloc(1, sizeof(Fnt));
font->xfont = xfont; font->xfont = xfont;
font->pattern = pattern; font->pattern = pattern;
@ -240,12 +255,10 @@ drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int
int int
drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert) 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 i, ty, ellipsis_x = 0;
int ty; unsigned int tmpw, ew, ellipsis_w = 0, ellipsis_len;
unsigned int ew;
XftDraw *d = NULL; XftDraw *d = NULL;
Fnt *usedfont, *curfont, *nextfont; Fnt *usedfont, *curfont, *nextfont;
size_t i, len;
int utf8strlen, utf8charlen, render = x || y || w || h; int utf8strlen, utf8charlen, render = x || y || w || h;
long utf8codepoint = 0; long utf8codepoint = 0;
const char *utf8str; const char *utf8str;
@ -253,13 +266,17 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
FcPattern *fcpattern; FcPattern *fcpattern;
FcPattern *match; FcPattern *match;
XftResult result; XftResult result;
int charexists = 0; int charexists = 0, overflow = 0;
/* keep track of a couple codepoints for which we have no match. */
enum { nomatches_len = 64 };
static struct { long codepoint[nomatches_len]; unsigned int idx; } nomatches;
static unsigned int ellipsis_width = 0;
if (!drw || (render && !drw->scheme) || !text || !drw->fonts) if (!drw || (render && (!drw->scheme || !w)) || !text || !drw->fonts)
return 0; return 0;
if (!render) { if (!render) {
w = ~w; w = invert ? invert : ~invert;
} else { } else {
XSetForeground(drw->dpy, drw->gc, drw->scheme[invert ? ColFg : ColBg].pixel); XSetForeground(drw->dpy, drw->gc, drw->scheme[invert ? ColFg : ColBg].pixel);
XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h); XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h);
@ -269,8 +286,10 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
} }
usedfont = drw->fonts; usedfont = drw->fonts;
if (!ellipsis_width && render)
ellipsis_width = drw_fontset_getwidth(drw, "...");
while (1) { while (1) {
utf8strlen = 0; ew = ellipsis_len = utf8strlen = 0;
utf8str = text; utf8str = text;
nextfont = NULL; nextfont = NULL;
while (*text) { while (*text) {
@ -278,9 +297,27 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
for (curfont = drw->fonts; curfont; curfont = curfont->next) { for (curfont = drw->fonts; curfont; curfont = curfont->next) {
charexists = charexists || XftCharExists(drw->dpy, curfont->xfont, utf8codepoint); charexists = charexists || XftCharExists(drw->dpy, curfont->xfont, utf8codepoint);
if (charexists) { if (charexists) {
if (curfont == usedfont) { drw_font_getexts(curfont, text, utf8charlen, &tmpw, NULL);
if (ew + ellipsis_width <= w) {
/* keep track where the ellipsis still fits */
ellipsis_x = x + ew;
ellipsis_w = w - ew;
ellipsis_len = utf8strlen;
}
if (ew + tmpw > w) {
overflow = 1;
/* called from drw_fontset_getwidth_clamp():
* it wants the width AFTER the overflow
*/
if (!render)
x += tmpw;
else
utf8strlen = ellipsis_len;
} else if (curfont == usedfont) {
utf8strlen += utf8charlen; utf8strlen += utf8charlen;
text += utf8charlen; text += utf8charlen;
ew += tmpw;
} else { } else {
nextfont = curfont; nextfont = curfont;
} }
@ -288,36 +325,25 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
} }
} }
if (!charexists || nextfont) if (overflow || !charexists || nextfont)
break; break;
else else
charexists = 0; charexists = 0;
} }
if (utf8strlen) { if (utf8strlen) {
drw_font_getexts(usedfont, utf8str, utf8strlen, &ew, NULL); if (render) {
/* shorten text if necessary */ ty = y + (h - usedfont->h) / 2 + usedfont->xfont->ascent;
for (len = MIN(utf8strlen, sizeof(buf) - 1); len && ew > w; len--) XftDrawStringUtf8(d, &drw->scheme[invert ? ColBg : ColFg],
drw_font_getexts(usedfont, utf8str, len, &ew, NULL); usedfont->xfont, x, ty, (XftChar8 *)utf8str, utf8strlen);
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;
} }
x += ew;
w -= ew;
} }
if (render && overflow)
drw_text(drw, ellipsis_x, y, ellipsis_w, h, 0, "...", invert);
if (!*text) { if (!*text || overflow) {
break; break;
} else if (nextfont) { } else if (nextfont) {
charexists = 0; charexists = 0;
@ -327,6 +353,12 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
* character must be drawn. */ * character must be drawn. */
charexists = 1; charexists = 1;
for (i = 0; i < nomatches_len; ++i) {
/* avoid calling XftFontMatch if we know we won't find a match */
if (utf8codepoint == nomatches.codepoint[i])
goto no_match;
}
fccharset = FcCharSetCreate(); fccharset = FcCharSetCreate();
FcCharSetAddChar(fccharset, utf8codepoint); FcCharSetAddChar(fccharset, utf8codepoint);
@ -355,6 +387,8 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
curfont->next = usedfont; curfont->next = usedfont;
} else { } else {
xfont_free(usedfont); xfont_free(usedfont);
nomatches.codepoint[++nomatches.idx % nomatches_len] = utf8codepoint;
no_match:
usedfont = drw->fonts; usedfont = drw->fonts;
} }
} }
@ -384,6 +418,15 @@ drw_fontset_getwidth(Drw *drw, const char *text)
return drw_text(drw, 0, 0, 0, 0, 0, text, 0); return drw_text(drw, 0, 0, 0, 0, 0, text, 0);
} }
unsigned int
drw_fontset_getwidth_clamp(Drw *drw, const char *text, unsigned int n)
{
unsigned int tmp = 0;
if (drw && drw->fonts && text && n)
tmp = drw_text(drw, 0, 0, 0, 0, 0, text, n);
return MIN(n, tmp);
}
void void
drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h) drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h)
{ {
@ -421,4 +464,3 @@ drw_cur_free(Drw *drw, Cur *cursor)
XFreeCursor(drw->dpy, cursor->cursor); XFreeCursor(drw->dpy, cursor->cursor);
free(cursor); free(cursor);
} }

View file

@ -1,8 +1,4 @@
/* ____ __ */ /* See LICENSE file for copyright and license details. */
/* / __ \_________ _/ /_____ */
/* / / / / ___/ __ `/ //_/ _ \ */
/* / /_/ / / / /_/ / ,< / __/ Clay Gomera (Drake) */
/* /_____/_/ \__,_/_/|_|\___/ My custom dwm build */
typedef struct { typedef struct {
Cursor cursor; Cursor cursor;
@ -42,6 +38,7 @@ void drw_free(Drw *drw);
Fnt *drw_fontset_create(Drw* drw, const char *fonts[], size_t fontcount); Fnt *drw_fontset_create(Drw* drw, const char *fonts[], size_t fontcount);
void drw_fontset_free(Fnt* set); void drw_fontset_free(Fnt* set);
unsigned int drw_fontset_getwidth(Drw *drw, const char *text); unsigned int drw_fontset_getwidth(Drw *drw, const char *text);
unsigned int drw_fontset_getwidth_clamp(Drw *drw, const char *text, unsigned int n);
void drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h); void drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h);
/* Colorscheme abstraction */ /* Colorscheme abstraction */
@ -62,4 +59,3 @@ int drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned in
/* Map functions */ /* Map functions */
void drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h); void drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h);

View file

@ -30,10 +30,18 @@ top left corner. The tags which are applied to one or more windows are
indicated with an empty square in the top left corner. indicated with an empty square in the top left corner.
.P .P
dwm draws a small border around windows to indicate the focus state. dwm draws a small border around windows to indicate the focus state.
.P
On start, dwm can start additional programs that may be specified in two special
shell scripts (see the FILES section below), autostart_blocking.sh and
autostart.sh. The former is executed first and dwm will wait for its
termination before starting. The latter is executed in the background before
dwm enters its handler loop.
.P
Either of these files may be omitted.
.SH OPTIONS .SH OPTIONS
.TP .TP
.B \-v .B \-v
prints version information to standard output, then exits. prints version information to stderr, then exits.
.SH USAGE .SH USAGE
.SS Status bar .SS Status bar
.TP .TP
@ -122,6 +130,9 @@ Zooms/cycles focused window to/from master area (tiled layouts only).
.B Mod1\-Shift\-c .B Mod1\-Shift\-c
Close focused window. Close focused window.
.TP .TP
.B Mod1\-Shift\-f
Toggle fullscreen for focused window.
.TP
.B Mod1\-Shift\-space .B Mod1\-Shift\-space
Toggle focused window between tiled and floating state. Toggle focused window between tiled and floating state.
.TP .TP
@ -161,6 +172,21 @@ Toggles focused window between floating and tiled state.
.TP .TP
.B Mod1\-Button3 .B Mod1\-Button3
Resize focused window while dragging. Tiled windows will be toggled to the floating state. Resize focused window while dragging. Tiled windows will be toggled to the floating state.
.SH FILES
The files containing programs to be started along with dwm are searched for in
the following directories:
.IP "1. $XDG_DATA_HOME/dwm"
.IP "2. $HOME/.local/share/dwm"
.IP "3. $HOME/.dwm"
.P
The first existing directory is scanned for any of the autostart files below.
.TP 15
autostart.sh
This file is started as a shell background process before dwm enters its handler
loop.
.TP 15
autostart_blocking.sh
This file is started before any autostart.sh; dwm waits for its termination.
.SH CUSTOMIZATION .SH CUSTOMIZATION
dwm is customized by creating a custom config.h and (re)compiling the source dwm is customized by creating a custom config.h and (re)compiling the source
code. This keeps it fast, secure and simple. code. This keeps it fast, secure and simple.

View file

@ -1,9 +1,5 @@
/* ____ __ */ /* See LICENSE file for copyright and license details.
/* / __ \_________ _/ /_____ */ *
/* / / / / ___/ __ `/ //_/ _ \ */
/* / /_/ / / / /_/ / ,< / __/ Clay Gomera (Drake) */
/* /_____/_/ \__,_/_/|_|\___/ My custom dwm build */
/*
* dynamic window manager is designed like any other X client as well. It is * 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 * driven through handling X events. In contrast to other X clients, a window
* manager selects for SubstructureRedirectMask on the root window, to receive * manager selects for SubstructureRedirectMask on the root window, to receive
@ -24,7 +20,6 @@
* *
* To understand everything else, start reading main(). * To understand everything else, start reading main().
*/ */
#include <errno.h> #include <errno.h>
#include <locale.h> #include <locale.h>
#include <signal.h> #include <signal.h>
@ -34,6 +29,7 @@
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h> #include <sys/wait.h>
#include <X11/cursorfont.h> #include <X11/cursorfont.h>
#include <X11/keysym.h> #include <X11/keysym.h>
@ -54,8 +50,7 @@
#define CLEANMASK(mask) (mask & ~(numlockmask|LockMask) & (ShiftMask|ControlMask|Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask)) #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)) \ #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))) * MAX(0, MIN((y)+(h),(m)->wy+(m)->wh) - MAX((y),(m)->wy)))
#define ISVISIBLEONTAG(C, T) ((C->tags & T)) #define ISVISIBLE(C) ((C->tags & C->mon->tagset[C->mon->seltags]))
#define ISVISIBLE(C) ISVISIBLEONTAG(C, C->mon->tagset[C->mon->seltags])
#define LENGTH(X) (sizeof X / sizeof X[0]) #define LENGTH(X) (sizeof X / sizeof X[0])
#define MOUSEMASK (BUTTONMASK|PointerMotionMask) #define MOUSEMASK (BUTTONMASK|PointerMotionMask)
#define WIDTH(X) ((X)->w + 2 * (X)->bw + gappx) #define WIDTH(X) ((X)->w + 2 * (X)->bw + gappx)
@ -97,7 +92,7 @@ struct Client {
float mina, maxa; float mina, maxa;
int x, y, w, h; int x, y, w, h;
int oldx, oldy, oldw, oldh; int oldx, oldy, oldw, oldh;
int basew, baseh, incw, inch, maxw, maxh, minw, minh; int basew, baseh, incw, inch, maxw, maxh, minw, minh, hintsvalid;
int bw, oldbw; int bw, oldbw;
unsigned int tags; unsigned int tags;
int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen; int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen;
@ -109,11 +104,15 @@ struct Client {
typedef struct { typedef struct {
unsigned int mod; unsigned int mod;
KeySym chain;
KeySym keysym; KeySym keysym;
} Key;
typedef struct {
unsigned int n;
const Key keys[5];
void (*func)(const Arg *); void (*func)(const Arg *);
const Arg arg; const Arg arg;
} Key; } Keychord;
typedef struct { typedef struct {
const char *symbol; const char *symbol;
@ -156,7 +155,7 @@ static int applysizehints(Client *c, int *x, int *y, int *w, int *h, int interac
static void arrange(Monitor *m); static void arrange(Monitor *m);
static void arrangemon(Monitor *m); static void arrangemon(Monitor *m);
static void attach(Client *c); static void attach(Client *c);
static void attachaside(Client *c); static void attachbottom(Client *c);
static void attachstack(Client *c); static void attachstack(Client *c);
static void buttonpress(XEvent *e); static void buttonpress(XEvent *e);
static void checkotherwm(void); static void checkotherwm(void);
@ -182,6 +181,7 @@ static void focus(Client *c);
static void focusin(XEvent *e); static void focusin(XEvent *e);
static void focusmon(const Arg *arg); static void focusmon(const Arg *arg);
static void focusstack(const Arg *arg); static void focusstack(const Arg *arg);
static Atom getatomprop(Client *c, Atom prop);
static int getrootptr(int *x, int *y); static int getrootptr(int *x, int *y);
static long getstate(Window w); static long getstate(Window w);
static int gettextprop(Window w, Atom atom, char *text, unsigned int size); static int gettextprop(Window w, Atom atom, char *text, unsigned int size);
@ -196,7 +196,6 @@ static void maprequest(XEvent *e);
static void monocle(Monitor *m); static void monocle(Monitor *m);
static void motionnotify(XEvent *e); static void motionnotify(XEvent *e);
static void movemouse(const Arg *arg); static void movemouse(const Arg *arg);
static Client *nexttagged(Client *c);
static Client *nexttiled(Client *c); static Client *nexttiled(Client *c);
static void pop(Client *); static void pop(Client *);
static void propertynotify(XEvent *e); static void propertynotify(XEvent *e);
@ -229,6 +228,7 @@ static void tagmon(const Arg *arg);
static void tile(Monitor *); static void tile(Monitor *);
static void togglebar(const Arg *arg); static void togglebar(const Arg *arg);
static void togglefloating(const Arg *arg); static void togglefloating(const Arg *arg);
static void togglefullscr(const Arg *arg);
static void toggletag(const Arg *arg); static void toggletag(const Arg *arg);
static void toggleview(const Arg *arg); static void toggleview(const Arg *arg);
static void unfocus(Client *c, int setfocus); static void unfocus(Client *c, int setfocus);
@ -287,7 +287,7 @@ static Display *dpy;
static Drw *drw; static Drw *drw;
static Monitor *mons, *selmon; static Monitor *mons, *selmon;
static Window root, wmcheckwin; static Window root, wmcheckwin;
static KeySym keychain = -1; unsigned int currentkey = 0;
static int useargb = 0; static int useargb = 0;
static Visual *visual; static Visual *visual;
@ -370,6 +370,8 @@ applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact)
if (*w < bh) if (*w < bh)
*w = bh; *w = bh;
if (resizehints || c->isfloating || !c->mon->lt[c->mon->sellt]->arrange) { if (resizehints || c->isfloating || !c->mon->lt[c->mon->sellt]->arrange) {
if (!c->hintsvalid)
updatesizehints(c);
/* see last two sentences in ICCCM 4.1.2.3 */ /* see last two sentences in ICCCM 4.1.2.3 */
baseismin = c->basew == c->minw && c->baseh == c->minh; baseismin = c->basew == c->minw && c->baseh == c->minh;
if (!baseismin) { /* temporarily remove base dimensions */ if (!baseismin) { /* temporarily remove base dimensions */
@ -433,17 +435,14 @@ attach(Client *c)
} }
void void
attachaside(Client *c) { attachbottom(Client *c)
Client *at = nexttagged(c); {
if(!at) { Client **tc;
attach(c); c->next = NULL;
return; for (tc = &c->mon->clients; *tc; tc = &(*tc)->next);
} *tc = c;
c->next = at->next;
at->next = c;
} }
void void
attachstack(Client *c) attachstack(Client *c)
{ {
@ -477,7 +476,7 @@ buttonpress(XEvent *e)
arg.ui = 1 << i; arg.ui = 1 << i;
} else if (ev->x < x + blw) } else if (ev->x < x + blw)
click = ClkLtSymbol; click = ClkLtSymbol;
else if (ev->x > selmon->ww - TEXTW(stext)) else if (ev->x > selmon->ww - (int)TEXTW(stext))
click = ClkStatusText; click = ClkStatusText;
else else
click = ClkWinTitle; click = ClkWinTitle;
@ -524,6 +523,7 @@ cleanup(void)
drw_cur_free(drw, cursor[i]); drw_cur_free(drw, cursor[i]);
for (i = 0; i < LENGTH(colors); i++) for (i = 0; i < LENGTH(colors); i++)
free(scheme[i]); free(scheme[i]);
free(scheme);
XDestroyWindow(dpy, wmcheckwin); XDestroyWindow(dpy, wmcheckwin);
drw_free(drw); drw_free(drw);
XSync(dpy, False); XSync(dpy, False);
@ -750,17 +750,20 @@ dirtomon(int dir)
void void
drawbar(Monitor *m) drawbar(Monitor *m)
{ {
int x, w, sw = 0; int x, w, tw = 0;
int boxs = drw->fonts->h / 9; int boxs = drw->fonts->h / 9;
int boxw = drw->fonts->h / 6 + 2; int boxw = drw->fonts->h / 6 + 2;
unsigned int i, occ = 0, urg = 0; unsigned int i, occ = 0, urg = 0;
Client *c; Client *c;
if (!m->showbar)
return;
/* draw status first so it can be overdrawn by tags later */ /* draw status first so it can be overdrawn by tags later */
if (m == selmon || 1) { /* status is only drawn on selected monitor */ if (m == selmon) { /* status is only drawn on selected monitor */
drw_setscheme(drw, scheme[SchemeNorm]); drw_setscheme(drw, scheme[SchemeNorm]);
sw = TEXTW(stext); tw = TEXTW(stext);
drw_text(drw, m->ww - sw, 0, sw, bh, lrpad / 2, stext, 0); drw_text(drw, m->ww - tw, 0, tw, bh, lrpad / 2, stext, 0);
} }
for (c = m->clients; c; c = c->next) { for (c = m->clients; c; c = c->next) {
@ -783,7 +786,7 @@ drawbar(Monitor *m)
drw_setscheme(drw, scheme[SchemeNorm]); drw_setscheme(drw, scheme[SchemeNorm]);
x = drw_text(drw, x, 0, w, bh, lrpad / 2, m->ltsymbol, 0); x = drw_text(drw, x, 0, w, bh, lrpad / 2, m->ltsymbol, 0);
if ((w = m->ww - sw - x) > bh) { if ((w = m->ww - tw - x) > bh) {
if (m->sel) { if (m->sel) {
drw_setscheme(drw, scheme[m == selmon ? SchemeSel : SchemeNorm]); drw_setscheme(drw, scheme[m == selmon ? SchemeSel : SchemeNorm]);
drw_text(drw, x, 0, w, bh, lrpad / 2, m->sel->name, 0); drw_text(drw, x, 0, w, bh, lrpad / 2, m->sel->name, 0);
@ -911,7 +914,7 @@ focusstack(const Arg *arg)
{ {
Client *c = NULL, *i; Client *c = NULL, *i;
if (!selmon->sel) if (!selmon->sel || (selmon->sel->isfullscreen && lockfullscreen))
return; return;
if (arg->i > 0) { if (arg->i > 0) {
for (c = selmon->sel->next; c && !ISVISIBLE(c); c = c->next); for (c = selmon->sel->next; c && !ISVISIBLE(c); c = c->next);
@ -1027,21 +1030,16 @@ grabkeys(void)
{ {
updatenumlockmask(); updatenumlockmask();
{ {
unsigned int i, j; unsigned int i, k;
unsigned int modifiers[] = { 0, LockMask, numlockmask, numlockmask|LockMask }; unsigned int modifiers[] = { 0, LockMask, numlockmask, numlockmask|LockMask };
KeyCode code; KeyCode code;
KeyCode chain;
XUngrabKey(dpy, AnyKey, AnyModifier, root); XUngrabKey(dpy, AnyKey, AnyModifier, root);
for (i = 0; i < LENGTH(keys); i++) for (i = 0; i < LENGTH(keychords); i++)
if ((code = XKeysymToKeycode(dpy, keys[i].keysym))) { if ((code = XKeysymToKeycode(dpy, keychords[i].keys[currentkey].keysym)))
if (keys[i].chain != -1 && for (k = 0; k < LENGTH(modifiers); k++)
((chain = XKeysymToKeycode(dpy, keys[i].chain)))) XGrabKey(dpy, code, keychords[i].keys[currentkey].mod | modifiers[k], root,
code = chain; True, GrabModeAsync, GrabModeAsync);
for (j = 0; j < LENGTH(modifiers); j++)
XGrabKey(dpy, code, keys[i].mod | modifiers[j], root,
True, GrabModeAsync, GrabModeAsync);
}
} }
} }
@ -1067,37 +1065,48 @@ isuniquegeom(XineramaScreenInfo *unique, size_t n, XineramaScreenInfo *info)
void void
keypress(XEvent *e) keypress(XEvent *e)
{ {
unsigned int i, j; XEvent event = *e;
Keychord *keychord;
unsigned int ran = 0;
KeySym keysym; KeySym keysym;
XKeyEvent *ev; XKeyEvent *ev;
int current = 0; Keychord *newoptions;
unsigned int modifiers[] = { 0, LockMask, numlockmask, numlockmask|LockMask }; Keychord *oldoptions = (Keychord *)malloc(sizeof(keychords));
ev = &e->xkey; memcpy(oldoptions, keychords, sizeof(keychords));
keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0); size_t numoption = 0;
for (i = 0; i < LENGTH(keys); i++) { while(!ran){
if (keysym == keys[i].keysym && keys[i].chain == -1 ev = &event.xkey;
&& CLEANMASK(keys[i].mod) == CLEANMASK(ev->state) keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0);
&& keys[i].func) newoptions = (Keychord *)malloc(0);
keys[i].func(&(keys[i].arg)); numoption = 0;
else if (keysym == keys[i].chain && keychain == -1 for (keychord = oldoptions; keychord->n != 0 && currentkey < 5; keychord = (Keychord *)((char *)keychord + sizeof(Keychord))){
&& CLEANMASK(keys[i].mod) == CLEANMASK(ev->state) if(keysym == keychord->keys[currentkey].keysym
&& keys[i].func) { && CLEANMASK(keychord->keys[currentkey].mod) == CLEANMASK(ev->state)
current = 1; && keychord->func){
keychain = keysym; if(keychord->n == currentkey +1){
for (j = 0; j < LENGTH(modifiers); j++) keychord->func(&(keychord->arg));
XGrabKey(dpy, AnyKey, 0 | modifiers[j], root, ran = 1;
True, GrabModeAsync, GrabModeAsync); }else{
} else if (!current && keysym == keys[i].keysym numoption++;
&& keychain != -1 newoptions = (Keychord *)realloc(newoptions, numoption * sizeof(Keychord));
&& keys[i].chain == keychain memcpy((char *)newoptions + (numoption -1) * sizeof(Keychord),keychord, sizeof(Keychord));
&& keys[i].func) }
keys[i].func(&(keys[i].arg)); }
} }
if (!current) { currentkey++;
keychain = -1; if(numoption == 0)
break;
grabkeys(); grabkeys();
while (running && !XNextEvent(dpy, &event) && !ran)
if(event.type == KeyPress)
break;
free(oldoptions);
oldoptions = newoptions;
} }
free(newoptions);
currentkey = 0;
grabkeys();
} }
void void
@ -1164,7 +1173,7 @@ manage(Window w, XWindowAttributes *wa)
c->isfloating = c->oldstate = trans != None || c->isfixed; c->isfloating = c->oldstate = trans != None || c->isfixed;
if (c->isfloating) if (c->isfloating)
XRaiseWindow(dpy, c->win); XRaiseWindow(dpy, c->win);
attachaside(c); attachbottom(c);
attachstack(c); attachstack(c);
XChangeProperty(dpy, root, netatom[NetClientList], XA_WINDOW, 32, PropModeAppend, XChangeProperty(dpy, root, netatom[NetClientList], XA_WINDOW, 32, PropModeAppend,
(unsigned char *) &(c->win), 1); (unsigned char *) &(c->win), 1);
@ -1294,16 +1303,6 @@ 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 * Client *
nexttiled(Client *c) nexttiled(Client *c)
{ {
@ -1340,7 +1339,7 @@ propertynotify(XEvent *e)
arrange(c->mon); arrange(c->mon);
break; break;
case XA_WM_NORMAL_HINTS: case XA_WM_NORMAL_HINTS:
updatesizehints(c); c->hintsvalid = 0;
break; break;
case XA_WM_HINTS: case XA_WM_HINTS:
updatewmhints(c); updatewmhints(c);
@ -1396,15 +1395,15 @@ resizeclient(Client *c, int x, int y, int w, int h)
wc.border_width = c->bw; wc.border_width = c->bw;
/* Get number of clients for the selected monitor */ /* Get number of clients for the client's monitor */
for (n = 0, nbc = nexttiled(selmon->clients); nbc; nbc = nexttiled(nbc->next), n++); for (n = 0, nbc = nexttiled(c->mon->clients); nbc; nbc = nexttiled(nbc->next), n++);
/* Do nothing if layout is floating */ /* Do nothing if layout is floating */
if (c->isfloating || selmon->lt[selmon->sellt]->arrange == NULL) { if (c->isfloating || c->mon->lt[c->mon->sellt]->arrange == NULL) {
gapincr = gapoffset = 0; gapincr = gapoffset = 0;
} else { } else {
/* Remove border and gap if layout is monocle or only one client */ /* Remove border and gap if layout is monocle or only one client */
if (selmon->lt[selmon->sellt]->arrange == monocle || n == 1) { if (c->mon->lt[c->mon->sellt]->arrange == monocle || n == 1) {
gapoffset = 0; gapoffset = 0;
gapincr = -2 * borderpx; gapincr = -2 * borderpx;
wc.border_width = 0; wc.border_width = 0;
@ -1591,7 +1590,7 @@ sendmon(Client *c, Monitor *m)
detachstack(c); detachstack(c);
c->mon = m; c->mon = m;
c->tags = m->tagset[m->seltags]; /* assign tags of target monitor */ c->tags = m->tagset[m->seltags]; /* assign tags of target monitor */
attachaside(c); attachbottom(c);
attachstack(c); attachstack(c);
focus(NULL); focus(NULL);
arrange(NULL); arrange(NULL);
@ -1694,7 +1693,7 @@ setmfact(const Arg *arg)
if (!arg || !selmon->lt[selmon->sellt]->arrange) if (!arg || !selmon->lt[selmon->sellt]->arrange)
return; return;
f = arg->f < 1.0 ? arg->f + selmon->mfact : arg->f - 1.0; f = arg->f < 1.0 ? arg->f + selmon->mfact : arg->f - 1.0;
if (f < 0.1 || f > 0.9) if (f < 0.05 || f > 0.95)
return; return;
selmon->mfact = f; selmon->mfact = f;
arrange(selmon); arrange(selmon);
@ -1879,12 +1878,14 @@ tile(Monitor *m)
for (i = my = ty = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) for (i = my = ty = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++)
if (i < m->nmaster) { if (i < m->nmaster) {
h = (m->wh - my) / (MIN(n, m->nmaster) - i); 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); resize(c, m->wx, m->wy + my, mw - (2*c->bw) + (n > 1 ? gappx : 0), h - (2*c->bw), 0);
my += HEIGHT(c); if (my + HEIGHT(c) < m->wh)
my += HEIGHT(c);
} else { } else {
h = (m->wh - ty) / (n - i); 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); resize(c, m->wx + mw, m->wy + ty, m->ww - mw - (2*c->bw), h - (2*c->bw), 0);
ty += HEIGHT(c); if (ty + HEIGHT(c) < m->wh)
ty += HEIGHT(c);
} }
} }
@ -1911,6 +1912,13 @@ togglefloating(const Arg *arg)
arrange(selmon); arrange(selmon);
} }
void
togglefullscr(const Arg *arg)
{
if(selmon->sel)
setfullscreen(selmon->sel, !selmon->sel->isfullscreen);
}
void void
toggletag(const Arg *arg) toggletag(const Arg *arg)
{ {
@ -2062,43 +2070,43 @@ updategeom(void)
memcpy(&unique[j++], &info[i], sizeof(XineramaScreenInfo)); memcpy(&unique[j++], &info[i], sizeof(XineramaScreenInfo));
XFree(info); XFree(info);
nn = j; nn = j;
if (n <= nn) { /* new monitors available */
for (i = 0; i < (nn - n); i++) { /* new monitors if nn > n */
for (m = mons; m && m->next; m = m->next); for (i = n; i < nn; i++) {
if (m) for (m = mons; m && m->next; m = m->next);
m->next = createmon(); if (m)
else m->next = createmon();
mons = 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);
} }
for (i = 0, m = mons; i < nn && m; m = m->next, i++) /* removed monitors if n > nn */
if (i >= n for (i = nn; i < n; i++) {
|| unique[i].x_org != m->mx || unique[i].y_org != m->my for (m = mons; m && m->next; m = m->next);
|| unique[i].width != m->mw || unique[i].height != m->mh) while ((c = m->clients)) {
{ dirty = 1;
dirty = 1; m->clients = c->next;
m->num = i; detachstack(c);
m->mx = m->wx = unique[i].x_org; c->mon = mons;
m->my = m->wy = unique[i].y_org; attach(c);
m->mw = m->ww = unique[i].width; attachbottom(c);
m->mh = m->wh = unique[i].height; attachstack(c);
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);
} }
if (m == selmon)
selmon = mons;
cleanupmon(m);
} }
free(unique); free(unique);
} else } else
@ -2177,16 +2185,15 @@ updatesizehints(Client *c)
} else } else
c->maxa = c->mina = 0.0; c->maxa = c->mina = 0.0;
c->isfixed = (c->maxw && c->maxh && c->maxw == c->minw && c->maxh == c->minh); c->isfixed = (c->maxw && c->maxh && c->maxw == c->minw && c->maxh == c->minh);
c->hintsvalid = 1;
} }
void void
updatestatus(void) updatestatus(void)
{ {
Monitor* m;
if (!gettextprop(root, XA_WM_NAME, stext, sizeof(stext))) if (!gettextprop(root, XA_WM_NAME, stext, sizeof(stext)))
strcpy(stext, "dwm-"VERSION); strcpy(stext, "dwm-"VERSION);
for(m = mons; m; m = m->next) drawbar(selmon);
drawbar(m);
} }
void void
@ -2383,4 +2390,3 @@ main(int argc, char *argv[])
XCloseDisplay(dpy); XCloseDisplay(dpy);
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }

View file

@ -1,9 +1,3 @@
/* ____ __ */
/* / __ \_________ _/ /_____ */
/* / / / / ___/ __ `/ //_/ _ \ */
/* / /_/ / / / /_/ / ,< / __/ Clay Gomera (Drake) */
/* /_____/_/ \__,_/_/|_|\___/ My custom dwm build */
void void
grid(Monitor *m) { grid(Monitor *m) {
unsigned int i, n, cx, cy, cw, ch, aw, ah, cols, rows; unsigned int i, n, cx, cy, cw, ch, aw, ah, cols, rows;
@ -31,3 +25,4 @@ grid(Monitor *m) {
i++; i++;
} }
} }

View file

@ -1,10 +1,5 @@
/* ____ __ */
/* / __ \_________ _/ /_____ */
/* / / / / ___/ __ `/ //_/ _ \ */
/* / /_/ / / / /_/ / ,< / __/ Clay Gomera (Drake) */
/* /_____/_/ \__,_/_/|_|\___/ My custom dwm build */
/* cc transient.c -o transient -lX11 */ /* cc transient.c -o transient -lX11 */
#include <stdlib.h> #include <stdlib.h>
#include <unistd.h> #include <unistd.h>
#include <X11/Xlib.h> #include <X11/Xlib.h>

View file

@ -1,9 +1,4 @@
/* ____ __ */ /* See LICENSE file for copyright and license details. */
/* / __ \_________ _/ /_____ */
/* / / / / ___/ __ `/ //_/ _ \ */
/* / /_/ / / / /_/ / ,< / __/ Clay Gomera (Drake) */
/* /_____/_/ \__,_/_/|_|\___/ My custom dwm build */
#include <stdarg.h> #include <stdarg.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@ -38,4 +33,3 @@ die(const char *fmt, ...) {
exit(1); exit(1);
} }

View file

@ -1,8 +1,4 @@
/* ____ __ */ /* See LICENSE file for copyright and license details. */
/* / __ \_________ _/ /_____ */
/* / / / / ___/ __ `/ //_/ _ \ */
/* / /_/ / / / /_/ / ,< / __/ Clay Gomera (Drake) */
/* /_____/_/ \__,_/_/|_|\___/ My custom dwm build */
#define MAX(A, B) ((A) > (B) ? (A) : (B)) #define MAX(A, B) ((A) > (B) ? (A) : (B))
#define MIN(A, B) ((A) < (B) ? (A) : (B)) #define MIN(A, B) ((A) < (B) ? (A) : (B))
@ -10,4 +6,3 @@
void die(const char *fmt, ...); void die(const char *fmt, ...);
void *ecalloc(size_t nmemb, size_t size); void *ecalloc(size_t nmemb, size_t size);