commit 0965179162275a481f08b42e0cdc7490c1eb6031
parent a2f05d7af4cb17f58d1e3b6b0c8980d410752b9d
Author: Mahdi Mirzade <[email protected]>
Date: Wed, 12 Oct 2022 21:18:23 +0330
Debloat build, reconfigure workspaces, more minimalist colors, update to 6.4
Removed patches: fullgaps, rainbowtags, status2d-systray
Diffstat:
10 files changed, 375 insertions(+), 1982 deletions(-)
diff --git a/config.h b/config.h
@@ -3,28 +3,25 @@
/* Load essentials */
#include <X11/XF86keysym.h> /* For XF86 multimedia binds */
-/* System Tray */
-static const int showsystray = 0; /* 0 means no systray */
-static const unsigned int systraypadding= 1; /* systray vertical padding */
-static const unsigned int systrayspacing= 2; /* systray spacing */
-static const unsigned int systrayonleft = 0; /* 0: systray in the right corner, 1: systray on left of status text */
-
-static const unsigned int systraypinning= 1; /* 0: sloppy systray follows selected monitor, 1: pin systray to monitor X */
-static const int systraypinningfailfirst= 1; /* 1: if pinning fails, display systray on the first monitor, 0: display systray on the last monitor*/
-
/* appearance */
-static const char *fonts[] = { "monospace:size=9", "Vazir:size=9" };
-static const unsigned int borderpx = 0; /* border pixel of windows */
-static const unsigned int gappx = 10; /* gaps between windows */
+static const char *fonts[] = {
+ "JetBrainsMono Nerd Font:size=9",
+ "Vazirmatn:size=9",
+ "Noto Sans Mono CJK JP:size=9",
+ "Noto Sans Mono CJK KR:size=9",
+ "Noto Sans Mono CJK HK:size=9",
+ "Noto Sans Mono CJK SC:size=9",
+ "Noto Sans Mono CJK TC:size=9",
+ "Noto Color Emoji:size=9"
+};
+static const unsigned int borderpx = 2; /* border pixel of windows */
static const unsigned int snap = 32; /* snap pixel */
static const int showbar = 1; /* 0 means no bar */
static const int topbar = 1; /* 0 means bottom bar */
static const int barheight = 3; /* Spacing around the bar's font */
-static const int hidevacanttags = 1; /* 1 means hide empty tags / 0: show every tag */
-static const int hidetagindicator = 1; /* 1 means hide default top-left square-shaped tag indicator */
-static const int showtitle = 0; /* 1 means show WM_NAME of the currently selected window */
+static const int hidevacanttags = 0; /* 1 means hide empty tags / 0: show every tag */
+static const int showtitle = 1; /* 1 means show WM_NAME of the currently selected window */
static const int truecenteredtitle = 0; /* 1 means center the WM_NAME on the status bar */
-static const unsigned int colorfultag = 0; /* 0 means use SchemeSel for selected tag */
static char fgcolor[] = "#D8DEE9";
static char bgcolor[] = "#2E3440";
static char color0[] = "#3B4252";
@@ -43,51 +40,45 @@ static char color12[] = "#81A1C1";
static char color13[] = "#B48EAD";
static char color14[] = "#8FBCBB";
static char color15[] = "#ECEFF4";
-static const char *colors[][3] = {
- /* fg bg border */
- [SchemeNorm] = { color12, color0, color8 },
- [SchemeSel] = { color0, color12, color12 },
- [SchemeLayout] = { color12, color0, color8 },
-};
-/* if colorfultag == 1: */
-static const char *colortags[][2] = {
- { color1, color0 },
- { color2, color0 },
- { color3, color0 },
- { color4, color0 },
- { color5, color0 },
- { color6, color0 },
- { color9, color0 },
- { color10, color0 },
- { color11, color0 },
+/* Underline active tags (only works if hidevacanttags == 0) */
+static const unsigned int ulinepad = 5; /* horizontal padding between the underline and tag */
+static const unsigned int ulinestroke = 1; /* thickness / height of the underline */
+static const unsigned int ulinevoffset = 2; /* how far above the bottom of the bar the line should appear */
+
+/*
+ * Xresources preferences to load at startup
+ */
+ResourcePref resources[] = {
+ { "foreground", STRING, &fgcolor},
+ { "background", STRING, &bgcolor},
+ { "color0", STRING, &color0},
+ { "color1", STRING, &color1},
+ { "color2", STRING, &color2},
+ { "color3", STRING, &color3},
+ { "color4", STRING, &color4},
+ { "color5", STRING, &color5},
+ { "color6", STRING, &color6},
+ { "color7", STRING, &color7},
+ { "color8", STRING, &color8},
+ { "color9", STRING, &color9},
+ { "color10", STRING, &color10},
+ { "color11", STRING, &color11},
+ { "color12", STRING, &color12},
+ { "color13", STRING, &color13},
+ { "color14", STRING, &color14},
+ { "color15", STRING, &color15},
};
-//static const char *colortags_sel[][2] = {
-// { color1, color8 },
-// { color2, color8 },
-// { color3, color8 },
-// { color4, color8 },
-// { color5, color8 },
-// { color6, color8 },
-// { color9, color8 },
-// { color10, color8 },
-// { color11, color8 },
-//};
-static const char *colortags_sel[][2] = {
- { color0, color1 },
- { color0, color2 },
- { color0, color3 },
- { color0, color4 },
- { color0, color5 },
- { color0, color6 },
- { color0, color9 },
- { color0, color10 },
- { color0, color11 },
+
+static const char *colors[][3] = {
+ /* fg bg border */
+ [SchemeNorm] = { fgcolor, bgcolor, color0 },
+ [SchemeSel] = { fgcolor, color8, color8 },
+ [SchemeLayout] = { fgcolor, bgcolor, color0 },
};
/* tagging */
-static const char *tags[] = { "𐎠", "𐎡", "𐎢", "𐎣", "𐎤", "𐎥", "𐎦", "𐎧", "𐎨" };
-//static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" };
+static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" };
static const Rule rules[] = {
/* xprop(1):
@@ -106,25 +97,17 @@ static const Rule rules[] = {
/* layout(s) */
static const float mfact = 0.5; /* factor of master area size [0.05..0.95] */
static const int nmaster = 1; /* number of clients in master area */
-static const int resizehints = 1; /* 1 means respect size hints in tiled resizals */
+static const int resizehints = 0; /* 1 means respect size hints in tiled resizals */
static const int lockfullscreen = 1; /* 1 will force focus on the fullscreen window */
static int layouts_default = 0; /* Default layout */
static const int layouts_floating = 2;/* Layout number for floating mode */
-//static const Layout layouts[] = {
-// /* symbol arrange function */
-// { "Tile", tile }, /* first entry is default */
-// { "Monocle", monocle },
-// { "Float", NULL }, /* no layout function means floating behavior */
-// { NULL, NULL },
-//};
-
static const Layout layouts[] = {
/* symbol arrange function */
- { "[]=", tile }, /* first entry is default */
- { "[M]", monocle },
- { "><>", NULL }, /* no layout function means floating behavior */
- { NULL, NULL },
+ { "[]=", tile }, /* first entry is default */
+ { "[M]", monocle },
+ { "><>", NULL }, /* no layout function means floating behavior */
+ { NULL, NULL },
};
/* key definitions */
@@ -142,19 +125,19 @@ static const Layout layouts[] = {
#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", "-i", "-p", "Run:", NULL };
//static const char *termcmd[] = { "st", NULL };
//static const char *termcmdfloat[] = { "st", "-c", "st-float", NULL };
static const char *termcmd[] = { "tabbed", "-cd", "-r", "2", "st", "-w", "''", NULL };
static const char *termcmdfloat[] = { "tabbed", "-cd", "-n", "st-float", "-r", "2", "st", "-w", "''", NULL };
-static Key keys[] = {
+static const Key keys[] = {
/* modifier key function argument */
{ MODKEY, XK_a, spawn, SHCMD("dmenu_drun") },
{ MODKEY, XK_c, spawn, {.v = dmenucmd } },
{ MODKEY, XK_Return, spawn, {.v = termcmd } },
- { MODKEY|ShiftMask, XK_Return, spawn, {.v = termcmdfloat } },
+ { MODKEY|ShiftMask, XK_Return, spawn, SHCMD("konsole") },
+ //{ MODKEY|ShiftMask, XK_Return, spawn, {.v = termcmdfloat } },
{ MODKEY, XK_b, togglebar, {0} },
{ MODKEY, XK_j, focusstack, {.i = +1 } },
{ MODKEY, XK_k, focusstack, {.i = -1 } },
@@ -162,17 +145,17 @@ static Key keys[] = {
{ MODKEY, XK_d, incnmaster, {.i = -1 } },
{ MODKEY, XK_h, setmfact, {.f = -0.05} },
{ MODKEY, XK_l, setmfact, {.f = +0.05} },
- { MODKEY|ShiftMask, XK_j, movestack, {.i = +1 } },
- { MODKEY|ShiftMask, XK_k, movestack, {.i = -1 } },
+ { MODKEY|ShiftMask, XK_j, movestack, {.i = +1 } },
+ { MODKEY|ShiftMask, XK_k, movestack, {.i = -1 } },
{ MODKEY, XK_space, zoom, {0} },
{ MODKEY, XK_Tab, view, {0} },
{ MODKEY, XK_t, setlayout, {.v = &layouts[0]} },
{ MODKEY, XK_m, setlayout, {.v = &layouts[1]} },
{ MODKEY, XK_f, setlayout, {.v = &layouts[2]} },
- { MODKEY|ControlMask, XK_comma, cyclelayout, {.i = -1 } },
- { MODKEY|ControlMask, XK_period, cyclelayout, {.i = +1 } },
+ { MODKEY|ControlMask, XK_comma, cyclelayout, {.i = -1 } },
+ { MODKEY|ControlMask, XK_period, cyclelayout, {.i = +1 } },
{ MODKEY|ShiftMask, XK_space, togglefloating, {0} },
- { MODKEY|ShiftMask, XK_f, togglefullscr, {0} },
+ { MODKEY|ShiftMask, XK_f, togglefullscr, {0} },
{ MODKEY, XK_s, togglesticky, {0} },
{ MODKEY, XK_0, view, {.ui = ~0 } },
{ MODKEY|ShiftMask, XK_0, tag, {.ui = ~0 } },
@@ -180,12 +163,8 @@ static Key keys[] = {
{ MODKEY, XK_period, focusmon, {.i = +1 } },
{ MODKEY|ShiftMask, XK_comma, tagmon, {.i = -1 } },
{ MODKEY|ShiftMask, XK_period, tagmon, {.i = +1 } },
- { MODKEY, XK_F5, xrdb, {.v = NULL } },
- { MODKEY, XK_minus, setgaps, {.i = -1 } },
- { MODKEY, XK_equal, setgaps, {.i = +1 } },
- { MODKEY|ShiftMask, XK_equal, setgaps, {.i = 0 } },
- { MODKEY|ControlMask, XK_minus, shiftview, {.i = -1 } },
- { MODKEY|ControlMask, XK_equal, shiftview, {.i = +1 } },
+ { MODKEY|ShiftMask, XK_h, shiftview, {.i = -1 } },
+ { MODKEY|ShiftMask, XK_l, shiftview, {.i = +1 } },
TAGKEYS( XK_1, 0)
TAGKEYS( XK_2, 1)
TAGKEYS( XK_3, 2)
@@ -195,52 +174,59 @@ static Key keys[] = {
TAGKEYS( XK_7, 6)
TAGKEYS( XK_8, 7)
TAGKEYS( XK_9, 8)
+ { MODKEY, XK_F5, live_reload_xresources,{0} },
{ MODKEY|ShiftMask, XK_r, restart, {0} },
{ MODKEY, XK_q, killclient, {0} },
{ MODKEY|ControlMask, XK_q, quit, {0} },
{ MODKEY|ShiftMask, XK_b, spawn, SHCMD("dwm-bar -M") },
{ MODKEY|ShiftMask, XK_q, spawn, SHCMD("dmenu-power") },
- { MODKEY, XK_r, spawn, SHCMD("dmenu-record") },
- { MODKEY, XK_w, spawn, SHCMD("surf-open") },
- { MODKEY|ControlMask, XK_w, spawn, SHCMD("surf") },
- { MODKEY|ShiftMask, XK_e, spawn, SHCMD("st -e sh -c \"mutt\"") },
- { MODKEY|ShiftMask, XK_m, spawn, SHCMD("dmenu-man") },
- { MODKEY|ShiftMask, XK_w, spawn, SHCMD("st -c \"st-float\" -g \"100x20\" -e sh -c \"SET_BG_SELECT=1 bg-set\"") },
- { MODKEY|ShiftMask, XK_u, spawn, SHCMD("st -c \"st-float\" -g \"100x28\" -e sh -c \"doas pacman -Syu --noconfirm && rm ~/.cache/pkg_updates\"") },
- { MODKEY|ShiftMask, XK_t, spawn, SHCMD("theme-sel -s") },
- { MODKEY|ShiftMask, XK_g, spawn, SHCMD("gtt") },
- { MODKEY|ShiftMask, XK_y, spawn, SHCMD("myt -d") },
- { MODKEY|ControlMask, XK_l, spawn, SHCMD("lock") },
- { MODKEY, XK_grave, spawn, SHCMD("dmenu-emoji insert") },
- { ControlMask, XK_grave, spawn, SHCMD("dmenu-emoji clipboard") },
- { 0, XK_Print, spawn, SHCMD("screenshot -xc") },
- { ShiftMask, XK_Print, spawn, SHCMD("screenshot -xc -t 5") },
- { ControlMask, XK_Print, spawn, SHCMD("screenshot -xc -s yes") },
- { ControlMask|ShiftMask, XK_Print, spawn, SHCMD("screenshot -xc -s yes -t 5") },
- { 0, XF86XK_WebCam, spawn, SHCMD("webcam") },
- { 0, XF86XK_TouchpadToggle, spawn, SHCMD("toggle-touch") },
- { 0, XF86XK_TouchpadOn, spawn, SHCMD("toggle-touch") },
- { 0, XF86XK_TouchpadOff, spawn, SHCMD("toggle-touch") },
- { 0, XF86XK_AudioPlay, spawn, SHCMD("media-controller toggle") },
- { 0, XF86XK_AudioPause, spawn, SHCMD("media-controller toggle") },
- { 0, XF86XK_AudioNext, spawn, SHCMD("media-controller next") },
- { 0, XF86XK_AudioPrev, spawn, SHCMD("media-controller prev") },
- { ShiftMask, XF86XK_AudioPlay, spawn, SHCMD("media-controller pause-all") },
- { ShiftMask, XF86XK_AudioPause, spawn, SHCMD("media-controller pause-all") },
- { ShiftMask, XF86XK_AudioNext, spawn, SHCMD("media-controller seek-fwd") },
- { ShiftMask, XF86XK_AudioPrev, spawn, SHCMD("media-controller seek-bwd") },
- { 0, XF86XK_MonBrightnessUp, spawn, SHCMD("backlight -i") },
- { 0, XF86XK_MonBrightnessDown, spawn, SHCMD("backlight -d") },
- { 0, XF86XK_AudioRaiseVolume, spawn, SHCMD("volume -i") },
- { 0, XF86XK_AudioLowerVolume, spawn, SHCMD("volume -d") },
- { 0, XF86XK_AudioMute, spawn, SHCMD("volume -m") },
- { 0, XF86XK_AudioMicMute, spawn, SHCMD("volume -M") },
+ { MODKEY, XK_r, spawn, SHCMD("dmenu-record") },
+ { MODKEY, XK_w, spawn, SHCMD("surf-open") },
+ { MODKEY|ControlMask, XK_w, spawn, SHCMD("surf") },
+ { MODKEY|ShiftMask, XK_e, spawn, SHCMD("st -e sh -c \"mutt\"") },
+ { MODKEY|ShiftMask, XK_m, spawn, SHCMD("dmenu-man") },
+ { MODKEY|ShiftMask, XK_w, spawn, SHCMD("st -c \"st-float\" -g \"100x20\" -e sh -c \"SET_BG_SELECT=1 bg-set\"") },
+ { MODKEY|ShiftMask, XK_u, spawn, SHCMD("st -c \"st-float\" -g \"100x28\" -e sh -c \"doas pacman -Syu --noconfirm && rm ~/.cache/pkg_updates\"") },
+ { MODKEY|ShiftMask, XK_t, spawn, SHCMD("theme-sel -s") },
+ { MODKEY|ShiftMask, XK_g, spawn, SHCMD("gtt") },
+ { MODKEY|ShiftMask, XK_y, spawn, SHCMD("myt -d") },
+ { MODKEY|ControlMask, XK_l, spawn, SHCMD("slock") },
+ { MODKEY, XK_grave, spawn, SHCMD("dmenu-emoji insert") },
+ { MODKEY|ControlMask, XK_grave, spawn, SHCMD("dmenu-emoji clipboard") },
+ { 0, XK_Print, spawn, SHCMD("screenshot -xc") },
+ { ShiftMask, XK_Print, spawn, SHCMD("screenshot -xc -t 5") },
+ { ControlMask, XK_Print, spawn, SHCMD("screenshot -xc -s yes") },
+ { ControlMask|ShiftMask, XK_Print, spawn, SHCMD("screenshot -xc -s yes -t 5") },
+
+ { MODKEY, XK_F11, spawn, SHCMD("bright -nd") },
+ { MODKEY, XK_F12, spawn, SHCMD("bright -ni") },
+ { 0, XF86XK_WebCam, spawn, SHCMD("webcam") },
+ { 0, XF86XK_TouchpadToggle, spawn, SHCMD("toggle-touch") },
+ { 0, XF86XK_TouchpadOn, spawn, SHCMD("toggle-touch") },
+ { 0, XF86XK_TouchpadOff, spawn, SHCMD("toggle-touch") },
+ { 0, XF86XK_AudioPlay, spawn, SHCMD("media-controller toggle") },
+ { 0, XF86XK_AudioPause, spawn, SHCMD("media-controller toggle") },
+ { 0, XF86XK_AudioNext, spawn, SHCMD("media-controller next") },
+ { 0, XF86XK_AudioPrev, spawn, SHCMD("media-controller prev") },
+ { ShiftMask, XF86XK_AudioPlay, spawn, SHCMD("media-controller pause-all") },
+ { ShiftMask, XF86XK_AudioPause, spawn, SHCMD("media-controller pause-all") },
+ { ShiftMask, XF86XK_AudioNext, spawn, SHCMD("media-controller seek-fwd") },
+ { ShiftMask, XF86XK_AudioPrev, spawn, SHCMD("media-controller seek-bwd") },
+ { 0, XF86XK_MonBrightnessUp, spawn, SHCMD("bright -ni") },
+ { 0, XF86XK_MonBrightnessDown, spawn, SHCMD("bright -nd") },
+ { 0, XF86XK_AudioRaiseVolume, spawn, SHCMD("snd -ni") },
+ { 0, XF86XK_AudioLowerVolume, spawn, SHCMD("snd -nd") },
+ { 0, XF86XK_AudioMute, spawn, SHCMD("snd -nm") },
+ { ShiftMask, XF86XK_AudioRaiseVolume, spawn, SHCMD("snd -nI") },
+ { ShiftMask, XF86XK_AudioLowerVolume, spawn, SHCMD("snd -nD") },
+ { ShiftMask, XF86XK_AudioMute, spawn, SHCMD("snd -nM") },
+ { 0, XF86XK_AudioMicMute, spawn, SHCMD("snd -nM") },
};
/* button definitions */
/* click can be ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, or ClkRootWin */
-static Button buttons[] = {
+static const Button buttons[] = {
/* click event mask button function argument */
/* placemouse options, choose which feels more natural:
* 0 - tiled position is relative to mouse cursor
@@ -259,14 +245,14 @@ static Button buttons[] = {
{ ClkTagBar, 0, Button3, toggleview, {0} },
{ ClkTagBar, MODKEY, Button1, tag, {0} },
{ ClkTagBar, MODKEY, Button3, toggletag, {0} },
- { ClkTagBar, 0, Button4, shiftview, {.i = -1} },
- { ClkTagBar, 0, Button5, shiftview, {.i = +1} },
- { ClkLtSymbol, 0, Button1, cyclelayout, {.i = +1} },
- { ClkLtSymbol, 0, Button3, cyclelayout, {.i = -1} },
- { ClkLtSymbol, 0, Button2, setlayout, {.v = &layouts[0]} },
- { ClkLtSymbol, 0, Button4, cyclelayout, {.i = -1} },
- { ClkLtSymbol, 0, Button5, cyclelayout, {.i = +1} },
+ { ClkTagBar, 0, Button4, shiftview, {.i = -1} },
+ { ClkTagBar, 0, Button5, shiftview, {.i = +1} },
+ { ClkLtSymbol, 0, Button1, cyclelayout, {.i = +1} },
+ { ClkLtSymbol, 0, Button3, cyclelayout, {.i = -1} },
+ { ClkLtSymbol, 0, Button2, setlayout, {.v = &layouts[0]} },
+ { ClkLtSymbol, 0, Button4, cyclelayout, {.i = -1} },
+ { ClkLtSymbol, 0, Button5, cyclelayout, {.i = +1} },
{ ClkWinTitle, 0, Button2, togglesticky, {0} },
- { ClkStatusText, 0, Button3, spawn, SHCMD("dwm_bar -M") },
+ { ClkStatusText, 0, Button3, spawn, SHCMD("dwm-bar -M") },
};
diff --git a/config.mk b/config.mk
@@ -1,5 +1,5 @@
# dwm version
-VERSION = 6.3
+VERSION = 6.4
# Customize below to fit your system
diff --git a/drw.c b/drw.c
@@ -133,19 +133,6 @@ xfont_create(Drw *drw, const char *fontname, FcPattern *fontpattern)
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;
@@ -351,7 +338,6 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
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);
diff --git a/dwm.1 b/dwm.1
@@ -149,16 +149,6 @@ View all windows with any tag.
.B Mod4\-Control\-[1..n]
Add/remove all windows with nth tag to/from the view.
.TP
-.B Mod4\--
-Decrease the gaps around windows.
-.TP
-.B Mod4\-=
-Increase the gaps around windows.
-.TP
-.B Mod4\-Shift-=
-Reset the gaps around windows to
-.BR 0 .
-.TP
.B Mod4\-Shift\-q
Quit dwm.
.TP
diff --git a/dwm.c b/dwm.c
@@ -60,43 +60,13 @@
#define HEIGHT(X) ((X)->h + 2 * (X)->bw)
#define TAGMASK ((1 << LENGTH(tags)) - 1)
#define TEXTW(X) (drw_fontset_getwidth(drw, (X)) + lrpad)
-#define XRDB_LOAD_COLOR(R,V) if (XrmGetResource(xrdb, R, NULL, &type, &value) == True) { \
- if (value.addr != NULL && strnlen(value.addr, 8) == 7 && value.addr[0] == '#') { \
- int i = 1; \
- for (; i <= 6; i++) { \
- if (value.addr[i] < 48) break; \
- if (value.addr[i] > 57 && value.addr[i] < 65) break; \
- if (value.addr[i] > 70 && value.addr[i] < 97) break; \
- if (value.addr[i] > 102) break; \
- } \
- if (i == 7) { \
- strncpy(V, value.addr, 7); \
- V[7] = '\0'; \
- } \
- } \
- }
-
-#define SYSTEM_TRAY_REQUEST_DOCK 0
-/* XEMBED messages */
-#define XEMBED_EMBEDDED_NOTIFY 0
-#define XEMBED_WINDOW_ACTIVATE 1
-#define XEMBED_FOCUS_IN 4
-#define XEMBED_MODALITY_ON 10
-#define XEMBED_MAPPED (1 << 0)
-#define XEMBED_WINDOW_ACTIVATE 1
-#define XEMBED_WINDOW_DEACTIVATE 2
-#define VERSION_MAJOR 0
-#define VERSION_MINOR 0
-#define XEMBED_EMBEDDED_VERSION (VERSION_MAJOR << 16) | VERSION_MINOR
/* enums */
enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */
enum { SchemeNorm, SchemeSel, SchemeLayout }; /* color schemes */
enum { NetSupported, NetWMName, NetWMState, NetWMCheck,
- NetSystemTray, NetSystemTrayOP, NetSystemTrayOrientation, NetSystemTrayOrientationHorz,
NetWMFullscreen, NetActiveWindow, NetWMWindowType,
NetWMWindowTypeDialog, NetClientList, NetClientInfo, NetLast }; /* EWMH atoms */
-enum { Manager, Xembed, XembedInfo, XLast }; /* Xembed atoms */
enum { WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast }; /* default atoms */
enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle,
ClkClientWin, ClkRootWin, ClkLast }; /* clicks */
@@ -154,11 +124,9 @@ struct Monitor {
int by; /* bar geometry */
int mx, my, mw, mh; /* screen size */
int wx, wy, ww, wh; /* window area */
- int gappx; /* gaps between windows */
unsigned int seltags;
unsigned int sellt;
unsigned int tagset[2];
- unsigned int colorfultag;
int showbar;
int topbar;
Client *clients;
@@ -178,35 +146,38 @@ typedef struct {
int monitor;
} Rule;
-typedef struct Systray Systray;
-struct Systray {
- Window win;
- Client *icons;
+/* Xresources preferences */
+enum resource_type {
+ STRING = 0,
+ INTEGER = 1,
+ FLOAT = 2
};
+typedef struct {
+ char *name;
+ enum resource_type type;
+ void *dst;
+} ResourcePref;
+
/* function declarations */
static Atom getatomprop(Client *c, Atom prop);
static Client *nexttiled(Client *c);
static Client *recttoclient(int x, int y, int w, int h);
static Client *wintoclient(Window w);
-static Client *wintosystrayicon(Window w);
static Monitor *createmon(void);
static Monitor *dirtomon(int dir);
static Monitor *numtomon(int num);
static Monitor *recttomon(int x, int y, int w, int h);
-static Monitor *systraytomon(Monitor *m);
static Monitor *wintomon(Window w);
static int applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact);
-static int drawstatusbar(Monitor *m, int bh, char* text);
static int getrootptr(int *x, int *y);
static int gettextprop(Window w, Atom atom, char *text, unsigned int size);
-static int sendevent(Window w, Atom proto, int m, long d0, long d1, long d2, long d3, long d4);
+static int sendevent(Client *c, Atom proto);
static int updategeom(void);
static int xerror(Display *dpy, XErrorEvent *ee);
static int xerrordummy(Display *dpy, XErrorEvent *ee);
static int xerrorstart(Display *dpy, XErrorEvent *ee);
static long getstate(Window w);
-static unsigned int getsystraywidth();
static void applyrules(Client *c);
static void arrange(Monitor *m);
static void arrangemon(Monitor *m);
@@ -227,7 +198,6 @@ static void detach(Client *c);
static void detachstack(Client *c);
static void drawbar(Monitor *m);
static void drawbars(void);
-static int drawstatusbar(Monitor *m, int bh, char* text);
static void enternotify(XEvent *e);
static void expose(XEvent *e);
static void focus(Client *c);
@@ -240,7 +210,6 @@ static void grabkeys(void);
static void incnmaster(const Arg *arg);
static void keypress(XEvent *e);
static void killclient(const Arg *arg);
-static void loadxrdb(void);
static void manage(Window w, XWindowAttributes *wa);
static void mappingnotify(XEvent *e);
static void maprequest(XEvent *e);
@@ -254,12 +223,9 @@ static void pop(Client *);
static void propertynotify(XEvent *e);
static void restart(const Arg *arg);
static void quit(const Arg *arg);
-static void removesystrayicon(Client *i);
static void resize(Client *c, int x, int y, int w, int h, int interact);
-static void resizebarwin(Monitor *m);
static void resizeclient(Client *c, int x, int y, int w, int h);
static void resizemouse(const Arg *arg);
-static void resizerequest(XEvent *e);
static void restack(Monitor *m);
static void run(void);
static void scan(void);
@@ -268,7 +234,6 @@ static void setclientstate(Client *c, long state);
static void setclienttagprop(Client *c);
static void setfocus(Client *c);
static void setfullscreen(Client *c, int fullscreen);
-static void setgaps(const Arg *arg);
static void setlayout(const Arg *arg);
static void setmfact(const Arg *arg);
static void setup(void);
@@ -279,7 +244,6 @@ static void sigchld(int unused);
static void sighup(int unused);
static void sigterm(int unused);
static void spawn(const Arg *arg);
-static Monitor *systraytomon(Monitor *m);
static void tag(const Arg *arg);
static void tagmon(const Arg *arg);
static void tagnthmon(const Arg *arg);
@@ -299,25 +263,24 @@ static void updateclientlist(void);
static void updatenumlockmask(void);
static void updatesizehints(Client *c);
static void updatestatus(void);
-static void updatesystray(void);
-static void updatesystrayicongeom(Client *i, int w, int h);
-static void updatesystrayiconstate(Client *i, XPropertyEvent *ev);
static void updatetitle(Client *c);
static void updatewindowtype(Client *c);
static void updatewmhints(Client *c);
static void view(const Arg *arg);
static void warp(const Client *c);
-static void xrdb(const Arg *arg);
static void zoom(const Arg *arg);
+static void live_reload_xresources(const Arg *arg);
+static void load_xresources(void);
+static void resource_load(XrmDatabase db, char *name, enum resource_type rtype, void *dst);
+
/* variables */
-static Systray *systray = NULL;
static const char broken[] = "broken";
-static char stext[1024];
+static char stext[256];
static char fribidi_text[BUFSIZ] = "";
static int screen;
static int sw, sh; /* X display screen geometry width, height */
-static int bh, blw = 0; /* bar geometry */
+static int bh = 0; /* bar geometry */
static int lrpad; /* sum of left and right padding for text */
static int (*xerrorxlib)(Display *, XErrorEvent *);
static unsigned int numlockmask = 0;
@@ -335,16 +298,13 @@ static void (*handler[LASTEvent]) (XEvent *) = {
[MapRequest] = maprequest,
[MotionNotify] = motionnotify,
[PropertyNotify] = propertynotify,
- [ResizeRequest] = resizerequest,
[UnmapNotify] = unmapnotify
};
-static Atom wmatom[WMLast], netatom[NetLast], xatom[XLast];
+static Atom wmatom[WMLast], netatom[NetLast];
static int restartsig = 0;
static int running = 1;
static Cur *cursor[CurLast];
static Clr **scheme;
-static Clr **tagscheme;
-static Clr **tagscheme_sel;
static Display *dpy;
static Drw *drw;
static Monitor *mons, *selmon;
@@ -554,9 +514,9 @@ buttonpress(XEvent *e)
if (i < LENGTH(tags)) {
click = ClkTagBar;
arg.ui = 1 << i;
- } else if (ev->x < x + blw)
+ } else if (ev->x < x + TEXTW(selmon->ltsymbol))
click = ClkLtSymbol;
- else if (showtitle != 1 || ev->x > selmon->ww - (int)TEXTW(stext) - getsystraywidth())
+ else if (showtitle != 1 || ev->x > selmon->ww - (int)TEXTW(stext))
click = ClkStatusText;
else
click = ClkWinTitle;
@@ -600,15 +560,9 @@ cleanup(void)
while (mons)
cleanupmon(mons);
- if (showsystray) {
- XUnmapWindow(dpy, systray->win);
- XDestroyWindow(dpy, systray->win);
- free(systray);
- }
-
for (i = 0; i < CurLast; i++)
drw_cur_free(drw, cursor[i]);
- for (i = 0; i < LENGTH(colors) + 1; i++)
+ for (i = 0; i < LENGTH(colors); i++)
free(scheme[i]);
free(scheme);
XDestroyWindow(dpy, wmcheckwin);
@@ -637,58 +591,9 @@ cleanupmon(Monitor *mon)
void
clientmessage(XEvent *e)
{
- XWindowAttributes wa;
- XSetWindowAttributes swa;
XClientMessageEvent *cme = &e->xclient;
Client *c = wintoclient(cme->window);
- if (showsystray && cme->window == systray->win && cme->message_type == netatom[NetSystemTrayOP]) {
- /* add systray icons */
- if (cme->data.l[1] == SYSTEM_TRAY_REQUEST_DOCK) {
- if (!(c = (Client *)calloc(1, sizeof(Client))))
- die("fatal: could not malloc() %u bytes\n", sizeof(Client));
- if (!(c->win = cme->data.l[2])) {
- free(c);
- return;
- }
- c->mon = selmon;
- c->next = systray->icons;
- systray->icons = c;
- if (!XGetWindowAttributes(dpy, c->win, &wa)) {
- /* use sane defaults */
- wa.width = bh;
- wa.height = bh;
- wa.border_width = 0;
- }
- c->x = c->oldx = c->y = c->oldy = 0;
- c->w = c->oldw = wa.width;
- c->h = c->oldh = wa.height;
- c->oldbw = wa.border_width;
- c->bw = 0;
- c->isfloating = True;
- /* reuse tags field as mapped status */
- c->tags = 1;
- updatesizehints(c);
- updatesystrayicongeom(c, wa.width, wa.height);
- XAddToSaveSet(dpy, c->win);
- XSelectInput(dpy, c->win, StructureNotifyMask | PropertyChangeMask | ResizeRedirectMask);
- XReparentWindow(dpy, c->win, systray->win, 0, 0);
- /* use parents background color */
- swa.background_pixel = scheme[SchemeNorm][ColBg].pixel;
- XChangeWindowAttributes(dpy, c->win, CWBackPixel, &swa);
- sendevent(c->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_EMBEDDED_NOTIFY, 0 , systray->win, XEMBED_EMBEDDED_VERSION);
- /* FIXME not sure if I have to send these events, too */
- sendevent(c->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_FOCUS_IN, 0 , systray->win, XEMBED_EMBEDDED_VERSION);
- sendevent(c->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_WINDOW_ACTIVATE, 0 , systray->win, XEMBED_EMBEDDED_VERSION);
- sendevent(c->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_MODALITY_ON, 0 , systray->win, XEMBED_EMBEDDED_VERSION);
- XSync(dpy, False);
- resizebarwin(selmon);
- updatesystray();
- setclientstate(c, NormalState);
- }
- return;
- }
-
if (!c)
return;
if (cme->message_type == netatom[NetWMState]) {
@@ -741,7 +646,7 @@ configurenotify(XEvent *e)
for (c = m->clients; c; c = c->next)
if (c->isfullscreen)
resizeclient(c, m->mx, m->my, m->mw, m->mh);
- resizebarwin(m);
+ XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, bh);
}
focus(NULL);
arrange(NULL);
@@ -812,8 +717,6 @@ createmon(void)
m->nmaster = nmaster;
m->showbar = showbar;
m->topbar = topbar;
- m->gappx = gappx;
- m->colorfultag = colorfultag ? colorfultag : 0;
m->lt[0] = &layouts[layouts_default];
m->lt[1] = &layouts[(layouts_default + 1) % LENGTH(layouts)];
strncpy(m->ltsymbol, layouts[layouts_default].symbol, sizeof m->ltsymbol);
@@ -845,11 +748,6 @@ destroynotify(XEvent *e)
if ((c = wintoclient(ev->window)))
unmanage(c, 1);
- else if ((c = wintosystrayicon(ev->window))) {
- removesystrayicon(c);
- resizebarwin(selmon);
- updatesystray();
- }
}
void
@@ -890,116 +788,6 @@ dirtomon(int dir)
return m;
}
-int
-drawstatusbar(Monitor *m, int bh, char* stext) {
- int ret, i, w, x, len;
- short isCode = 0;
- char *text;
- char *p;
-
- len = strlen(stext) + 1 ;
- if (!(text = (char*) malloc(sizeof(char)*len)))
- die("malloc");
- p = text;
- memcpy(text, stext, len);
-
- /* compute width of the status text */
- w = 0;
- i = -1;
- while (text[++i]) {
- if (text[i] == '^') {
- if (!isCode) {
- isCode = 1;
- text[i] = '\0';
- w += TEXTW(text) - lrpad;
- text[i] = '^';
- if (text[++i] == 'f')
- w += atoi(text + ++i);
- } else {
- isCode = 0;
- text = text + i + 1;
- i = -1;
- }
- }
- }
- if (!isCode)
- w += TEXTW(text) - lrpad;
- else
- isCode = 0;
- text = p;
- if (showsystray)
- /* Xpx padding on both sides */
- w += systraypadding * 2;
- ret = m->ww - w;
- x = m->ww - w - getsystraywidth();
-
- drw_setscheme(drw, scheme[LENGTH(colors)]);
- drw->scheme[ColFg] = scheme[SchemeNorm][ColFg];
- drw->scheme[ColBg] = scheme[SchemeNorm][ColBg];
- drw_rect(drw, x, 0, w, bh, 1, 1);
- x++;
-
- /* process status text */
- i = -1;
- while (text[++i]) {
- if (text[i] == '^' && !isCode) {
- isCode = 1;
-
- text[i] = '\0';
- w = TEXTW(text) - lrpad;
- drw_text(drw, x, 0, w, bh, 0, text, 0);
-
- x += w;
-
- /* process code */
- while (text[++i] != '^') {
- if (text[i] == 'c') {
- char buf[8];
- memcpy(buf, (char*)text+i+1, 7);
- buf[7] = '\0';
- drw_clr_create(drw, &drw->scheme[ColFg], buf);
- i += 7;
- } else if (text[i] == 'b') {
- char buf[8];
- memcpy(buf, (char*)text+i+1, 7);
- buf[7] = '\0';
- drw_clr_create(drw, &drw->scheme[ColBg], buf);
- i += 7;
- } else if (text[i] == 'd') {
- drw->scheme[ColFg] = scheme[SchemeNorm][ColFg];
- drw->scheme[ColBg] = scheme[SchemeNorm][ColBg];
- } else if (text[i] == 'r') {
- int rx = atoi(text + ++i);
- while (text[++i] != ',');
- int ry = atoi(text + ++i);
- while (text[++i] != ',');
- int rw = atoi(text + ++i);
- while (text[++i] != ',');
- int rh = atoi(text + ++i);
-
- drw_rect(drw, rx + x, ry, rw, rh, 1, 0);
- } else if (text[i] == 'f') {
- x += atoi(text + ++i);
- }
- }
-
- text = text + i + 1;
- i=-1;
- isCode = 0;
- }
- }
-
- if (!isCode) {
- w = TEXTW(text) - lrpad;
- drw_text(drw, x, 0, w, bh, 0, text, 0);
- }
-
- drw_setscheme(drw, scheme[SchemeNorm]);
- free(p);
-
- return ret;
-}
-
Monitor *
numtomon(int num)
{
@@ -1015,7 +803,7 @@ numtomon(int num)
void
drawbar(Monitor *m)
{
- int x, w, tw = 0, stw = 0;
+ int x, w, tw = 0;
int boxs = drw->fonts->h / 9;
int boxw = drw->fonts->h / 6 + 2;
unsigned int i, occ = 0, urg = 0;
@@ -1024,20 +812,14 @@ drawbar(Monitor *m)
if (!m->showbar)
return;
- if (showsystray && m == systraytomon(m) && !systrayonleft)
- stw = getsystraywidth();
-
/* draw status first so it can be overdrawn by tags later */
if (m == selmon || 1) { /* status is drawn on all monitors */
- //drw_setscheme(drw, scheme[SchemeNorm]);
- //tw = TEXTW(stext) - lrpad + 2; /* 2px right padding */
- //drw_text(drw, m->ww - tw, 0, tw, bh, 0, stext, 0);
+ drw_setscheme(drw, scheme[SchemeNorm]);
+ tw = TEXTW(stext) - lrpad + 2; /* 2px right padding */
apply_fribidi(stext);
- tw = m->ww - drawstatusbar(m, bh, fribidi_text);
+ drw_text(drw, m->ww - tw, 0, tw, bh, 0, fribidi_text, 0);
}
- resizebarwin(m);
-
for (c = m->clients; c; c = c->next) {
occ |= c->tags;
if (c->isurgent)
@@ -1045,46 +827,50 @@ drawbar(Monitor *m)
}
x = 0;
for (i = 0; i < LENGTH(tags); i++) {
- if (hidevacanttags) /* Do not draw vacant tags */
- if (!(occ & 1 << i || m->tagset[m->seltags] & 1 << i)) continue;
- if (colorfultag)
- //drw_setscheme(drw, (m->tagset[m->seltags] & 1 << i ? tagscheme[i] : scheme[SchemeNorm]));
- //drw_setscheme(drw, (m->tagset[m->seltags] & 1 << i ? tagscheme_sel[i] : tagscheme[i]));
- drw_setscheme(drw, (occ & 1 << i ? (m->tagset[m->seltags] & 1 << i ? tagscheme_sel[i] : tagscheme[i]) : scheme[SchemeNorm]));
- else
- drw_setscheme(drw, scheme[m->tagset[m->seltags] & 1 << i ? SchemeSel : SchemeNorm]);
- apply_fribidi(tags[i]);
+ /* Do not draw vacant tags */
+ if (hidevacanttags &&
+ !(occ & 1 << i || m->tagset[m->seltags] & 1 << i)) continue;
+ drw_setscheme(drw, scheme[m->tagset[m->seltags] & 1 << i
+ ? SchemeSel : SchemeNorm]);
+ apply_fribidi(tags[i]);
w = TEXTW(fribidi_text);
drw_text(drw, x, 0, w, bh, lrpad / 2, fribidi_text, urg & 1 << i);
- if (!hidetagindicator) /* Do not draw top-left tag indicators */
- if (occ & 1 << i)
- drw_rect(drw, x + boxs, boxs, boxw, boxw,
- m == selmon && selmon->sel && selmon->sel->tags & 1 << i,
- urg & 1 << i);
+ //if (!hidevacanttags && m->tagset[m->seltags] & 1 << i)
+ if (!hidevacanttags) {
+ int linex = x + ulinepad + (w / 4);
+ int linew = (w / 2) - (ulinepad * 2);
+ if ((m->tagset[m->seltags] & 1 << i)) {
+ linex = x + ulinepad;
+ linew = w - (ulinepad * 2);
+ }
+ if (occ & 1 << i)
+ drw_rect(drw, linex, bh - ulinestroke - ulinevoffset,
+ linew, ulinestroke, 1, 0);
+ }
x += w;
}
apply_fribidi(m->ltsymbol);
- w = blw = TEXTW(fribidi_text);
+ w = TEXTW(fribidi_text);
drw_setscheme(drw, scheme[SchemeLayout]);
x = drw_text(drw, x, 0, w, bh, lrpad / 2, fribidi_text, 0);
- if ((w = m->ww - tw - stw - x) > bh) {
+ if ((w = m->ww - tw - x) > bh) {
if (showtitle && m->sel) {
drw_setscheme(drw, scheme[m == selmon ? SchemeSel : SchemeNorm]);
- apply_fribidi(m->sel->name);
- int mid = lrpad / 2;
- if (truecenteredtitle && TEXTW(fribidi_text) <= w)
- mid = (w - TEXTW(fribidi_text)) / 2;
- //mid = lrpad / 2;
- drw_text(drw, x, 0, w, bh, mid, fribidi_text, 0);
- if (m->sel->isfloating && !hidetagindicator)
+ apply_fribidi(m->sel->name);
+ int mid = lrpad / 2;
+ if (truecenteredtitle && TEXTW(fribidi_text) <= w)
+ mid = (w - TEXTW(fribidi_text)) / 2;
+ //mid = lrpad / 2;
+ drw_text(drw, x, 0, w, bh, mid, fribidi_text, 0);
+ if (!hidevacanttags && 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);
}
}
- drw_map(drw, m->barwin, 0, 0, m->ww - stw, bh);
+ drw_map(drw, m->barwin, 0, 0, m->ww, bh);
}
void
@@ -1121,11 +907,8 @@ expose(XEvent *e)
Monitor *m;
XExposeEvent *ev = &e->xexpose;
- if (ev->count == 0 && (m = wintomon(ev->window))) {
+ if (ev->count == 0 && (m = wintomon(ev->window)))
drawbar(m);
- if (m == selmon)
- updatesystray();
- }
}
void
@@ -1228,17 +1011,9 @@ getatomprop(Client *c, Atom prop)
unsigned char *p = NULL;
Atom da, atom = None;
- /* FIXME getatomprop should return the number of items and a pointer to
- * the stored data instead of this workaround */
- Atom req = XA_ATOM;
- if (prop == xatom[XembedInfo])
- req = xatom[XembedInfo];
-
- if (XGetWindowProperty(dpy, c->win, prop, 0L, sizeof atom, False, req,
+ if (XGetWindowProperty(dpy, c->win, prop, 0L, sizeof atom, False, XA_ATOM,
&da, &di, &dl, &dl, &p) == Success && p) {
atom = *(Atom *)p;
- if (da == xatom[XembedInfo] && dl == 2)
- atom = ((Atom *)p)[1];
XFree(p);
}
return atom;
@@ -1272,16 +1047,6 @@ getstate(Window w)
return result;
}
-unsigned int
-getsystraywidth()
-{
- unsigned int w = 0;
- Client *i;
- if(showsystray)
- for(i = systray->icons; i; w += i->w + systrayspacing, i = i->next) ;
- return w ? w + systrayspacing : 1;
-}
-
int
gettextprop(Window w, Atom atom, char *text, unsigned int size)
{
@@ -1294,13 +1059,11 @@ gettextprop(Window w, Atom atom, char *text, unsigned int size)
text[0] = '\0';
if (!XGetTextProperty(dpy, w, &name, atom) || !name.nitems)
return 0;
- if (name.encoding == XA_STRING)
+ 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);
- }
+ } 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);
@@ -1386,8 +1149,7 @@ killclient(const Arg *arg)
{
if (!selmon->sel)
return;
-
- if (!sendevent(selmon->sel->win, wmatom[WMDelete], NoEventMask, wmatom[WMDelete], CurrentTime, 0 , 0, 0)) {
+ if (!sendevent(selmon->sel, wmatom[WMDelete])) {
XGrabServer(dpy);
XSetErrorHandler(xerrordummy);
XSetCloseDownMode(dpy, DestroyAll);
@@ -1399,87 +1161,6 @@ killclient(const Arg *arg)
}
void
-loadxrdb()
-{
- Display *display;
- char * resm;
- XrmDatabase xrdb;
- char *type;
- XrmValue value;
-
- display = XOpenDisplay(NULL);
-
- if (display != NULL) {
- resm = XResourceManagerString(display);
-
- if (resm != NULL) {
- xrdb = XrmGetStringDatabase(resm);
-
- if (xrdb != NULL) {
- /* Load ^color* */
- XRDB_LOAD_COLOR("foreground", fgcolor);
- XRDB_LOAD_COLOR("background", bgcolor);
- XRDB_LOAD_COLOR("color0", color0);
- XRDB_LOAD_COLOR("color1", color1);
- XRDB_LOAD_COLOR("color2", color2);
- XRDB_LOAD_COLOR("color3", color3);
- XRDB_LOAD_COLOR("color4", color4);
- XRDB_LOAD_COLOR("color5", color5);
- XRDB_LOAD_COLOR("color6", color6);
- XRDB_LOAD_COLOR("color7", color7);
- XRDB_LOAD_COLOR("color8", color8);
- XRDB_LOAD_COLOR("color9", color9);
- XRDB_LOAD_COLOR("color10", color10);
- XRDB_LOAD_COLOR("color11", color11);
- XRDB_LOAD_COLOR("color12", color12);
- XRDB_LOAD_COLOR("color13", color13);
- XRDB_LOAD_COLOR("color14", color14);
- XRDB_LOAD_COLOR("color15", color15);
- /* Load ^*color* */
- XRDB_LOAD_COLOR("*foreground", fgcolor);
- XRDB_LOAD_COLOR("*background", bgcolor);
- XRDB_LOAD_COLOR("*color0", color0);
- XRDB_LOAD_COLOR("*color1", color1);
- XRDB_LOAD_COLOR("*color2", color2);
- XRDB_LOAD_COLOR("*color3", color3);
- XRDB_LOAD_COLOR("*color4", color4);
- XRDB_LOAD_COLOR("*color5", color5);
- XRDB_LOAD_COLOR("*color6", color6);
- XRDB_LOAD_COLOR("*color7", color7);
- XRDB_LOAD_COLOR("*color8", color8);
- XRDB_LOAD_COLOR("*color9", color9);
- XRDB_LOAD_COLOR("*color10", color10);
- XRDB_LOAD_COLOR("*color11", color11);
- XRDB_LOAD_COLOR("*color12", color12);
- XRDB_LOAD_COLOR("*color13", color13);
- XRDB_LOAD_COLOR("*color14", color14);
- XRDB_LOAD_COLOR("*color15", color15);
- /* Load ^*.color* */
- XRDB_LOAD_COLOR("*.foreground", fgcolor);
- XRDB_LOAD_COLOR("*.background", bgcolor);
- XRDB_LOAD_COLOR("*.color0", color0);
- XRDB_LOAD_COLOR("*.color1", color1);
- XRDB_LOAD_COLOR("*.color2", color2);
- XRDB_LOAD_COLOR("*.color3", color3);
- XRDB_LOAD_COLOR("*.color4", color4);
- XRDB_LOAD_COLOR("*.color5", color5);
- XRDB_LOAD_COLOR("*.color6", color6);
- XRDB_LOAD_COLOR("*.color7", color7);
- XRDB_LOAD_COLOR("*.color8", color8);
- XRDB_LOAD_COLOR("*.color9", color9);
- XRDB_LOAD_COLOR("*.color10", color10);
- XRDB_LOAD_COLOR("*.color11", color11);
- XRDB_LOAD_COLOR("*.color12", color12);
- XRDB_LOAD_COLOR("*.color13", color13);
- XRDB_LOAD_COLOR("*.color14", color14);
- XRDB_LOAD_COLOR("*.color15", color15);
- }
- }
- }
- XCloseDisplay(display);
-}
-
-void
manage(Window w, XWindowAttributes *wa)
{
Client *c, *t = NULL;
@@ -1504,14 +1185,12 @@ manage(Window w, XWindowAttributes *wa)
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);
+ if (c->x + WIDTH(c) > c->mon->wx + c->mon->ww)
+ c->x = c->mon->wx + c->mon->ww - WIDTH(c);
+ if (c->y + HEIGHT(c) > c->mon->wy + c->mon->wh)
+ c->y = c->mon->wy + c->mon->wh - HEIGHT(c);
+ c->x = MAX(c->x, c->mon->wx);
+ c->y = MAX(c->y, c->mon->wy);
c->bw = borderpx;
wc.border_width = c->bw;
@@ -1580,16 +1259,7 @@ maprequest(XEvent *e)
static XWindowAttributes wa;
XMapRequestEvent *ev = &e->xmaprequest;
- Client *i;
- if ((i = wintosystrayicon(ev->window))) {
- sendevent(i->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_WINDOW_ACTIVATE, 0, systray->win, XEMBED_EMBEDDED_VERSION);
- resizebarwin(selmon);
- updatesystray();
- }
-
- if (!XGetWindowAttributes(dpy, ev->window, &wa))
- return;
- if (wa.override_redirect)
+ if (!XGetWindowAttributes(dpy, ev->window, &wa) || wa.override_redirect)
return;
if (!wintoclient(ev->window))
manage(ev->window, &wa);
@@ -1851,18 +1521,7 @@ propertynotify(XEvent *e)
Window trans;
XPropertyEvent *ev = &e->xproperty;
- if ((c = wintosystrayicon(ev->window))) {
- if (ev->atom == XA_WM_NORMAL_HINTS) {
- updatesizehints(c);
- updatesystrayicongeom(c, c->w, c->h);
- }
- else
- updatesystrayiconstate(c, ev);
- resizebarwin(selmon);
- updatesystray();
- }
-
- if ((ev->window == root) && (ev->atom == XA_WM_NAME))
+ if ((ev->window == root) && (ev->atom == XA_WM_NAME))
updatestatus();
else if (ev->state == PropertyDelete)
return; /* ignore */
@@ -1935,19 +1594,6 @@ recttomon(int x, int y, int w, int h)
}
void
-removesystrayicon(Client *i)
-{
- Client **ii;
-
- if (!showsystray || !i)
- return;
- for (ii = &systray->icons; *ii && *ii != i; ii = &(*ii)->next);
- if (ii)
- *ii = i->next;
- free(i);
-}
-
-void
resize(Client *c, int x, int y, int w, int h, int interact)
{
if (applysizehints(c, &x, &y, &w, &h, interact))
@@ -1955,14 +1601,6 @@ resize(Client *c, int x, int y, int w, int h, int interact)
}
void
-resizebarwin(Monitor *m) {
- unsigned int w = m->ww;
- if (showsystray && m == systraytomon(m) && !systrayonleft)
- w -= getsystraywidth();
- XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, w, bh);
-}
-
-void
resizeclient(Client *c, int x, int y, int w, int h)
{
XWindowChanges wc;
@@ -2047,19 +1685,6 @@ resizemouse(const Arg *arg)
}
void
-resizerequest(XEvent *e)
-{
- XResizeRequestEvent *ev = &e->xresizerequest;
- Client *i;
-
- if ((i = wintosystrayicon(ev->window))) {
- updatesystrayicongeom(i, ev->width, ev->height);
- resizebarwin(selmon);
- updatesystray();
- }
-}
-
-void
restack(Monitor *m)
{
Client *c;
@@ -2150,37 +1775,26 @@ setclientstate(Client *c, long state)
}
int
-sendevent(Window w, Atom proto, int mask, long d0, long d1, long d2, long d3, long d4)
+sendevent(Client *c, Atom proto)
{
int n;
- Atom *protocols, mt;
+ Atom *protocols;
int exists = 0;
XEvent ev;
- if (proto == wmatom[WMTakeFocus] || proto == wmatom[WMDelete]) {
- mt = wmatom[WMProtocols];
- if (XGetWMProtocols(dpy, w, &protocols, &n)) {
- while (!exists && n--)
- exists = protocols[n] == proto;
- XFree(protocols);
- }
+ if (XGetWMProtocols(dpy, c->win, &protocols, &n)) {
+ while (!exists && n--)
+ exists = protocols[n] == proto;
+ XFree(protocols);
}
- else {
- exists = True;
- mt = proto;
- }
-
if (exists) {
ev.type = ClientMessage;
- ev.xclient.window = w;
- ev.xclient.message_type = mt;
+ ev.xclient.window = c->win;
+ ev.xclient.message_type = wmatom[WMProtocols];
ev.xclient.format = 32;
- ev.xclient.data.l[0] = d0;
- ev.xclient.data.l[1] = d1;
- ev.xclient.data.l[2] = d2;
- ev.xclient.data.l[3] = d3;
- ev.xclient.data.l[4] = d4;
- XSendEvent(dpy, w, False, mask, &ev);
+ ev.xclient.data.l[0] = proto;
+ ev.xclient.data.l[1] = CurrentTime;
+ XSendEvent(dpy, c->win, False, NoEventMask, &ev);
}
return exists;
}
@@ -2194,7 +1808,7 @@ setfocus(Client *c)
XA_WINDOW, 32, PropModeReplace,
(unsigned char *) &(c->win), 1);
}
- sendevent(c->win, wmatom[WMTakeFocus], NoEventMask, wmatom[WMTakeFocus], CurrentTime, 0, 0, 0);
+ sendevent(c, wmatom[WMTakeFocus]);
}
void
@@ -2226,16 +1840,6 @@ setfullscreen(Client *c, int fullscreen)
}
void
-setgaps(const Arg *arg)
-{
- if ((arg->i == 0) || (selmon->gappx + arg->i < 0))
- selmon->gappx = 0;
- else
- selmon->gappx += arg->i;
- arrange(selmon);
-}
-
-void
setlayout(const Arg *arg)
{
if (!arg || !arg->v || arg->v != selmon->lt[selmon->sellt])
@@ -2295,12 +1899,8 @@ setup(void)
wmatom[WMState] = XInternAtom(dpy, "WM_STATE", False);
wmatom[WMTakeFocus] = XInternAtom(dpy, "WM_TAKE_FOCUS", False);
netatom[NetActiveWindow] = XInternAtom(dpy, "_NET_ACTIVE_WINDOW", False);
- netatom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False);
- netatom[NetSystemTray] = XInternAtom(dpy, "_NET_SYSTEM_TRAY_S0", False);
- netatom[NetSystemTrayOP] = XInternAtom(dpy, "_NET_SYSTEM_TRAY_OPCODE", False);
- netatom[NetSystemTrayOrientation] = XInternAtom(dpy, "_NET_SYSTEM_TRAY_ORIENTATION", False);
- netatom[NetSystemTrayOrientationHorz] = XInternAtom(dpy, "_NET_SYSTEM_TRAY_ORIENTATION_HORZ", False);
- netatom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False);
+ netatom[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);
@@ -2308,30 +1908,14 @@ setup(void)
netatom[NetWMWindowTypeDialog] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DIALOG", False);
netatom[NetClientList] = XInternAtom(dpy, "_NET_CLIENT_LIST", False);
netatom[NetClientInfo] = XInternAtom(dpy, "_NET_CLIENT_INFO", False);
- xatom[Manager] = XInternAtom(dpy, "MANAGER", False);
- xatom[Xembed] = XInternAtom(dpy, "_XEMBED", False);
- xatom[XembedInfo] = XInternAtom(dpy, "_XEMBED_INFO", False);
- /* init cursors */
+ /* 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 */
- if (colorfultag) {
- if (LENGTH(tags) > LENGTH(colortags) || LENGTH(tags) > LENGTH(colortags_sel))
- die("too few color schemes for the tags");
- tagscheme = ecalloc(LENGTH(colortags), sizeof(Clr *));
- for (i = 0; i < LENGTH(colortags); i++)
- tagscheme[i] = drw_scm_create(drw, colortags[i], 2);
- tagscheme_sel = ecalloc(LENGTH(colortags_sel), sizeof(Clr *));
- for (i = 0; i < LENGTH(colortags_sel); i++)
- tagscheme_sel[i] = drw_scm_create(drw, colortags_sel[i], 2);
- }
- scheme = ecalloc(LENGTH(colors) + 1, sizeof(Clr *));
- scheme[LENGTH(colors)] = drw_scm_create(drw, colors[0], 3);
+ scheme = ecalloc(LENGTH(colors), sizeof(Clr *));
for (i = 0; i < LENGTH(colors); i++)
scheme[i] = drw_scm_create(drw, colors[i], 3);
- /* init system tray */
- updatesystray();
/* init bars */
updatebars();
updatestatus();
@@ -2416,16 +2000,12 @@ sigterm(int unused)
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);
+ die("dwm: execvp '%s' failed:", ((char **)arg->v)[0]);
}
}
@@ -2480,18 +2060,18 @@ tile(Monitor *m)
if (n > m->nmaster)
mw = m->nmaster ? m->ww * m->mfact : 0;
else
- mw = m->ww - m->gappx;
- for (i = 0, my = ty = m->gappx, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++)
+ 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) - m->gappx;
- resize(c, m->wx + m->gappx, m->wy + my, mw - (2*c->bw) - m->gappx, h - (2*c->bw), 0);
- if (my + HEIGHT(c) + m->gappx < m->wh)
- my += HEIGHT(c) + m->gappx;
+ 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);
+ if (my + HEIGHT(c) < m->wh)
+ my += HEIGHT(c);
} else {
- h = (m->wh - ty) / (n - i) - m->gappx;
- resize(c, m->wx + mw + m->gappx, m->wy + ty, m->ww - mw - (2*c->bw) - 2*m->gappx, h - (2*c->bw), 0);
- if (ty + HEIGHT(c) + m->gappx < m->wh)
- ty += HEIGHT(c) + m->gappx;
+ 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);
+ if (ty + HEIGHT(c) < m->wh)
+ ty += HEIGHT(c);
}
}
@@ -2500,18 +2080,7 @@ togglebar(const Arg *arg)
{
selmon->showbar = !selmon->showbar;
updatebarpos(selmon);
- resizebarwin(selmon);
- if (showsystray) {
- XWindowChanges wc;
- if (!selmon->showbar)
- wc.y = -bh;
- else if (selmon->showbar) {
- wc.y = 0;
- if (!selmon->topbar)
- wc.y = selmon->mh - bh;
- }
- XConfigureWindow(dpy, systray->win, CWY, &wc);
- }
+ XMoveResizeWindow(dpy, selmon->barwin, selmon->wx, selmon->by, selmon->ww, bh);
arrange(selmon);
}
@@ -2598,6 +2167,7 @@ unmanage(Client *c, int destroyed)
wc.border_width = c->oldbw;
XGrabServer(dpy); /* avoid race conditions */
XSetErrorHandler(xerrordummy);
+ XSelectInput(dpy, c->win, NoEventMask);
XConfigureWindow(dpy, c->win, CWBorderWidth, &wc); /* restore border */
XUngrabButton(dpy, AnyButton, AnyModifier, c->win);
setclientstate(c, WithdrawnState);
@@ -2623,18 +2193,11 @@ unmapnotify(XEvent *e)
else
unmanage(c, 0);
}
- else if ((c = wintosystrayicon(ev->window))) {
- /* KLUDGE! sometimes icons occasionally unmap their windows, but do
- * _not_ destroy them. We map those windows back */
- XMapRaised(dpy, c->win);
- updatesystray();
- }
}
void
updatebars(void)
{
- unsigned int w;
Monitor *m;
XSetWindowAttributes wa = {
.override_redirect = True,
@@ -2645,15 +2208,10 @@ updatebars(void)
for (m = mons; m; m = m->next) {
if (m->barwin)
continue;
- w = m->ww;
- if (showsystray && m == systraytomon(m))
- w -= getsystraywidth();
- m->barwin = XCreateWindow(dpy, root, m->wx, m->by, w, bh, 0, DefaultDepth(dpy, screen),
+ m->barwin = XCreateWindow(dpy, root, m->wx, m->by, m->ww, bh, 0, DefaultDepth(dpy, screen),
CopyFromParent, DefaultVisual(dpy, screen),
CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa);
XDefineCursor(dpy, m->barwin, cursor[CurNormal]->cursor);
- if (showsystray && m == systraytomon(m))
- XMapRaised(dpy, systray->win);
XMapRaised(dpy, m->barwin);
XSetClassHint(dpy, m->barwin, &ch);
}
@@ -2831,127 +2389,10 @@ updatestatus(void)
strcpy(stext, "dwm-"VERSION);
for(m = mons; m; m = m->next) {
drawbar(m);
- updatesystray();
}
}
void
-updatesystrayicongeom(Client *i, int w, int h)
-{
- if (i) {
- i->h = bh;
- if (w == h)
- i->w = bh;
- else if (h == bh)
- i->w = w;
- else
- i->w = (int) ((float)bh * ((float)w / (float)h));
- applysizehints(i, &(i->x), &(i->y), &(i->w), &(i->h), False);
- /* force icons into the systray dimensions if they don't want to */
- if (i->h > bh) {
- if (i->w == i->h)
- i->w = bh;
- else
- i->w = (int) ((float)bh * ((float)i->w / (float)i->h));
- i->h = bh;
- }
- }
-}
-
-void
-updatesystrayiconstate(Client *i, XPropertyEvent *ev)
-{
- long flags;
- int code = 0;
-
- if (!showsystray || !i || ev->atom != xatom[XembedInfo] ||
- !(flags = getatomprop(i, xatom[XembedInfo])))
- return;
-
- if (flags & XEMBED_MAPPED && !i->tags) {
- i->tags = 1;
- code = XEMBED_WINDOW_ACTIVATE;
- XMapRaised(dpy, i->win);
- setclientstate(i, NormalState);
- }
- else if (!(flags & XEMBED_MAPPED) && i->tags) {
- i->tags = 0;
- code = XEMBED_WINDOW_DEACTIVATE;
- XUnmapWindow(dpy, i->win);
- setclientstate(i, WithdrawnState);
- }
- else
- return;
- sendevent(i->win, xatom[Xembed], StructureNotifyMask, CurrentTime, code, 0,
- systray->win, XEMBED_EMBEDDED_VERSION);
-}
-void
-updatesystray(void)
-{
- XSetWindowAttributes wa;
- XWindowChanges wc;
- Client *i;
- Monitor *m = systraytomon(NULL);
- unsigned int x = m->mx + m->mw;
- unsigned int sw = TEXTW(stext) - lrpad + systrayspacing;
- unsigned int w = 1;
-
- if (!showsystray)
- return;
- if (systrayonleft)
- x -= sw + lrpad / 2;
- if (!systray) {
- /* init systray */
- if (!(systray = (Systray *)calloc(1, sizeof(Systray))))
- die("fatal: could not malloc() %u bytes\n", sizeof(Systray));
- systray->win = XCreateSimpleWindow(dpy, root, x, m->by, w, bh, 0, 0, scheme[SchemeSel][ColBg].pixel);
- wa.event_mask = ButtonPressMask | ExposureMask;
- wa.override_redirect = True;
- wa.background_pixel = scheme[SchemeNorm][ColBg].pixel;
- XSelectInput(dpy, systray->win, SubstructureNotifyMask);
- XChangeProperty(dpy, systray->win, netatom[NetSystemTrayOrientation], XA_CARDINAL, 32,
- PropModeReplace, (unsigned char *)&netatom[NetSystemTrayOrientationHorz], 1);
- XChangeWindowAttributes(dpy, systray->win, CWEventMask|CWOverrideRedirect|CWBackPixel, &wa);
- XMapRaised(dpy, systray->win);
- XSetSelectionOwner(dpy, netatom[NetSystemTray], systray->win, CurrentTime);
- if (XGetSelectionOwner(dpy, netatom[NetSystemTray]) == systray->win) {
- sendevent(root, xatom[Manager], StructureNotifyMask, CurrentTime, netatom[NetSystemTray], systray->win, 0, 0);
- XSync(dpy, False);
- }
- else {
- fprintf(stderr, "dwm: unable to obtain system tray.\n");
- free(systray);
- systray = NULL;
- return;
- }
- }
- for (w = 0, i = systray->icons; i; i = i->next) {
- /* make sure the background color stays the same */
- wa.background_pixel = scheme[SchemeNorm][ColBg].pixel;
- XChangeWindowAttributes(dpy, i->win, CWBackPixel, &wa);
- XMapRaised(dpy, i->win);
- w += systrayspacing;
- i->x = w;
- XMoveResizeWindow(dpy, i->win, i->x, 0, i->w, i->h);
- w += i->w;
- if (i->mon != m)
- i->mon = m;
- }
- w = w ? w + systrayspacing : 1;
- x -= w;
- XMoveResizeWindow(dpy, systray->win, x, m->by, w, bh);
- wc.x = x; wc.y = m->by; wc.width = w; wc.height = bh;
- wc.stack_mode = Above; wc.sibling = m->barwin;
- XConfigureWindow(dpy, systray->win, CWX|CWY|CWWidth|CWHeight|CWSibling|CWStackMode, &wc);
- XMapWindow(dpy, systray->win);
- XMapSubwindows(dpy, systray->win);
- /* redraw background */
- XSetForeground(dpy, drw->gc, scheme[SchemeNorm][ColBg].pixel);
- XFillRectangle(dpy, systray->win, drw->gc, 0, 0, w, bh);
- XSync(dpy, False);
-}
-
-void
updatetitle(Client *c)
{
if (!gettextprop(c->win, netatom[NetWMName], c->name, sizeof c->name))
@@ -3038,16 +2479,6 @@ wintoclient(Window w)
return NULL;
}
-Client *
-wintosystrayicon(Window w) {
- Client *i = NULL;
-
- if (!showsystray || !w)
- return i;
- for (i = systray->icons; i && i->win != w; i = i->next) ;
- return i;
-}
-
Monitor *
wintomon(Window w)
{
@@ -3102,25 +2533,6 @@ xerrorstart(Display *dpy, XErrorEvent *ee)
}
void
-xrdb(const Arg *arg)
-{
- loadxrdb();
- int i;
- if (colorfultag) {
- tagscheme = ecalloc(LENGTH(colortags), sizeof(Clr *));
- for (i = 0; i < LENGTH(colortags); i++)
- tagscheme[i] = drw_scm_create(drw, colortags[i], 2);
- tagscheme_sel = ecalloc(LENGTH(colortags_sel), sizeof(Clr *));
- for (i = 0; i < LENGTH(colortags_sel); i++)
- tagscheme_sel[i] = drw_scm_create(drw, colortags_sel[i], 2);
- }
- for (i=0; i < LENGTH(colors); i++)
- scheme[i] = drw_scm_create(drw, colors[i], 3);
- focus(NULL);
- arrange(NULL);
-}
-
-void
movestack(const Arg *arg) {
Client *c = NULL, *p = NULL, *pc = NULL, *i;
@@ -3172,62 +2584,137 @@ movestack(const Arg *arg) {
void
shiftview(const Arg *arg)
{
- Arg a;
- Client *c;
- unsigned visible = 0;
- int i = arg->i;
- int count = 0;
- int nextseltags, curseltags = selmon->tagset[selmon->seltags];
-
- do {
- if(i > 0) // left circular shift
- nextseltags = (curseltags << i) | (curseltags >> (LENGTH(tags) - i));
- else // right circular shift
- nextseltags = curseltags >> (- i) | (curseltags << (LENGTH(tags) + i));
-
- // Check if tag is visible
- for (c = selmon->clients; c && !visible; c = c->next)
- if (nextseltags & c->tags) { visible = 1; break; }
-
- i += arg->i;
- } while (!visible && ++count < LENGTH(tags));
-
- if (count < LENGTH(tags)) {
- a.i = nextseltags;
- view(&a);
- }
-}
+ Arg a;
+ Client *c;
+ unsigned visible = 0;
+ int i = arg->i;
+ int count = 0;
+ int nextseltags, curseltags = selmon->tagset[selmon->seltags];
+
+ if (!hidevacanttags) {
+ if (i > 0) // left circular shift
+ nextseltags = (curseltags << i)
+ | (curseltags >> (LENGTH(tags) - i));
+ else // right circular shift
+ nextseltags = curseltags >> (- i)
+ | (curseltags << (LENGTH(tags) + i));
+ } else {
+ do {
+ if (i > 0) // left circular shift
+ nextseltags = (curseltags << i)
+ | (curseltags >> (LENGTH(tags) - i));
+ else // right circular shift
+ nextseltags = curseltags >> (- i)
+ | (curseltags << (LENGTH(tags) + i));
+
+ // Check if tag is visible
+ for (c = selmon->clients; c && !visible; c = c->next) {
+ if (nextseltags & c->tags) {
+ visible = 1;
+ break;
+ }
+ }
+
+ i += arg->i;
+ } while (!visible && ++count < LENGTH(tags));
+ }
-Monitor *
-systraytomon(Monitor *m) {
- Monitor *t;
- int i, n;
- if(!systraypinning) {
- if(!m)
- return selmon;
- return m == selmon ? m : NULL;
+ if (count < LENGTH(tags)) {
+ a.i = nextseltags;
+ view(&a);
}
- for(n = 1, t = mons; t && t->next; n++, t = t->next) ;
- for(i = 1, t = mons; t && t->next && i < systraypinning; i++, t = t->next) ;
- if(systraypinningfailfirst && n < systraypinning)
- return mons;
- return t;
}
void
zoom(const Arg *arg)
{
Client *c = selmon->sel;
-
- if (!selmon->lt[selmon->sellt]->arrange
- || (selmon->sel && selmon->sel->isfloating))
+ if (!selmon->lt[selmon->sellt]->arrange || !c || c->isfloating)
+ return;
+ if (c == nexttiled(selmon->clients) && !(c = nexttiled(c->next)))
return;
- if (c == nexttiled(selmon->clients))
- if (!c || !(c = nexttiled(c->next)))
- return;
pop(c);
}
+void
+resource_load(XrmDatabase db, char *name, enum resource_type rtype, void *dst)
+{
+ char *sdst = NULL;
+ int *idst = NULL;
+ float *fdst = NULL;
+
+ sdst = dst;
+ idst = dst;
+ fdst = dst;
+
+ char fullname[256];
+ char *type;
+ XrmValue ret;
+
+ snprintf(fullname, sizeof(fullname), "%s.%s", "dwm", name);
+ fullname[sizeof(fullname) - 1] = '\0';
+
+ XrmGetResource(db, fullname, "*", &type, &ret);
+ if (!(ret.addr == NULL || strncmp("String", type, 64)))
+ {
+ switch (rtype) {
+ case STRING:
+ strcpy(sdst, ret.addr);
+ break;
+ case INTEGER:
+ *idst = strtoul(ret.addr, NULL, 10);
+ break;
+ case FLOAT:
+ *fdst = strtof(ret.addr, NULL);
+ break;
+ }
+ }
+}
+
+void
+live_reload_xresources(const Arg *arg)
+{
+ load_xresources();
+
+ Monitor *m;
+ XSetWindowAttributes wa;
+ unsigned int i;
+
+ for (m = mons; m; m = m->next) {
+
+ for(Client *c = m->clients; c; c = c->next) {
+ XWindowChanges wc;
+ wc.border_width = borderpx;
+ XConfigureWindow(dpy, c->win, CWBorderWidth, &wc);
+ }
+
+ }
+ for (i = 0; i < LENGTH(colors); i++)
+ scheme[i] = drw_scm_create(drw, colors[i], 3);
+
+ focus(NULL);
+ arrange(NULL);
+}
+
+void
+load_xresources(void)
+{
+ Display *display;
+ char *resm;
+ XrmDatabase db;
+ ResourcePref *p;
+
+ display = XOpenDisplay(NULL);
+ resm = XResourceManagerString(display);
+ if (!resm)
+ return;
+ db = XrmGetStringDatabase(resm);
+ for ( p = resources; p < resources + LENGTH(resources); p++)
+ resource_load(db, p->name, p->type, p->dst);
+ XCloseDisplay(display);
+}
+
+
int
main(int argc, char *argv[])
{
@@ -3248,7 +2735,7 @@ main(int argc, char *argv[])
}
checkotherwm();
XrmInitialize();
- loadxrdb();
+ load_xresources();
setup();
#ifdef __OpenBSD__
if (pledge("stdio rpath proc exec", NULL) == -1)
@@ -3256,7 +2743,8 @@ main(int argc, char *argv[])
#endif /* __OpenBSD__ */
scan();
run();
- if(restartsig) execvp(argv[0], argv);
+ if(restartsig)
+ execvp(argv[0], argv);
cleanup();
XCloseDisplay(dpy);
return EXIT_SUCCESS;
diff --git a/patches/dwm-fullgaps-20200508-7b77734.diff b/patches/dwm-fullgaps-20200508-7b77734.diff
@@ -1,138 +0,0 @@
-From 7b7773458c072e4b24d6ea32d0364a8e402e4a43 Mon Sep 17 00:00:00 2001
-From: swy7ch <[email protected]>
-Date: Fri, 8 May 2020 19:07:24 +0200
-Subject: [PATCH] [PATCH] update dwm-fullgaps patch to be used with tile layout
- update
-
-the recent tile layout changes in commit HEAD~1 (f09418b) broke the
-patch
-
-this patch adapt the new `if` statements to take gaps into account
-
-this patch also provides manpage entries for the keybindings
----
- config.def.h | 4 ++++
- dwm.1 | 10 ++++++++++
- dwm.c | 33 +++++++++++++++++++++++----------
- 3 files changed, 37 insertions(+), 10 deletions(-)
-
-diff --git a/config.def.h b/config.def.h
-index 1c0b587..38d2f6c 100644
---- a/config.def.h
-+++ b/config.def.h
-@@ -2,6 +2,7 @@
-
- /* appearance */
- static const unsigned int borderpx = 1; /* border pixel of windows */
-+static const unsigned int gappx = 5; /* gaps between 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 */
-@@ -84,6 +85,9 @@ static Key keys[] = {
- { MODKEY, XK_period, focusmon, {.i = +1 } },
- { MODKEY|ShiftMask, XK_comma, tagmon, {.i = -1 } },
- { MODKEY|ShiftMask, XK_period, tagmon, {.i = +1 } },
-+ { MODKEY, XK_minus, setgaps, {.i = -1 } },
-+ { MODKEY, XK_equal, setgaps, {.i = +1 } },
-+ { MODKEY|ShiftMask, XK_equal, setgaps, {.i = 0 } },
- TAGKEYS( XK_1, 0)
- TAGKEYS( XK_2, 1)
- TAGKEYS( XK_3, 2)
-diff --git a/dwm.1 b/dwm.1
-index 13b3729..0202d96 100644
---- a/dwm.1
-+++ b/dwm.1
-@@ -140,6 +140,16 @@ View all windows with any tag.
- .B Mod1\-Control\-[1..n]
- Add/remove all windows with nth tag to/from the view.
- .TP
-+.B Mod1\--
-+Decrease the gaps around windows.
-+.TP
-+.B Mod1\-=
-+Increase the gaps around windows.
-+.TP
-+.B Mod1\-Shift-=
-+Reset the gaps around windows to
-+.BR 0 .
-+.TP
- .B Mod1\-Shift\-q
- Quit dwm.
- .SS Mouse commands
-diff --git a/dwm.c b/dwm.c
-index 9fd0286..45a58f3 100644
---- a/dwm.c
-+++ b/dwm.c
-@@ -119,6 +119,7 @@ struct Monitor {
- int by; /* bar geometry */
- int mx, my, mw, mh; /* screen size */
- int wx, wy, ww, wh; /* window area */
-+ int gappx; /* gaps between windows */
- unsigned int seltags;
- unsigned int sellt;
- unsigned int tagset[2];
-@@ -200,6 +201,7 @@ 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 setgaps(const Arg *arg);
- static void setlayout(const Arg *arg);
- static void setmfact(const Arg *arg);
- static void setup(void);
-@@ -639,6 +641,7 @@ createmon(void)
- m->nmaster = nmaster;
- m->showbar = showbar;
- m->topbar = topbar;
-+ m->gappx = gappx;
- m->lt[0] = &layouts[0];
- m->lt[1] = &layouts[1 % LENGTH(layouts)];
- strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol);
-@@ -1498,6 +1501,16 @@ setfullscreen(Client *c, int fullscreen)
- }
- }
-
-+void
-+setgaps(const Arg *arg)
-+{
-+ if ((arg->i == 0) || (selmon->gappx + arg->i < 0))
-+ selmon->gappx = 0;
-+ else
-+ selmon->gappx += arg->i;
-+ arrange(selmon);
-+}
-+
- void
- setlayout(const Arg *arg)
- {
-@@ -1684,18 +1697,18 @@ tile(Monitor *m)
- 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++)
-+ mw = m->ww - m->gappx;
-+ for (i = 0, my = ty = m->gappx, 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);
-- if (my + HEIGHT(c) < m->wh)
-- my += HEIGHT(c);
-+ h = (m->wh - my) / (MIN(n, m->nmaster) - i) - m->gappx;
-+ resize(c, m->wx + m->gappx, m->wy + my, mw - (2*c->bw) - m->gappx, h - (2*c->bw), 0);
-+ if (my + HEIGHT(c) + m->gappx < m->wh)
-+ my += HEIGHT(c) + m->gappx;
- } 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);
-- if (ty + HEIGHT(c) < m->wh)
-- ty += HEIGHT(c);
-+ h = (m->wh - ty) / (n - i) - m->gappx;
-+ resize(c, m->wx + mw + m->gappx, m->wy + ty, m->ww - mw - (2*c->bw) - 2*m->gappx, h - (2*c->bw), 0);
-+ if (ty + HEIGHT(c) + m->gappx < m->wh)
-+ ty += HEIGHT(c) + m->gappx;
- }
- }
-
---
-2.26.2
-
diff --git a/patches/dwm-rainbowtags-6.2.diff b/patches/dwm-rainbowtags-6.2.diff
@@ -1,59 +0,0 @@
-diff --git a/config.def.h b/config.def.h
-index 1c0b587..3fb5cf8 100644
---- a/config.def.h
-+++ b/config.def.h
-@@ -21,6 +21,18 @@ static const char *colors[][3] = {
- /* tagging */
- static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" };
-
-+static const char *tagsel[][2] = {
-+ { "#ffffff", "#ff0000" },
-+ { "#ffffff", "#ff7f00" },
-+ { "#000000", "#ffff00" },
-+ { "#000000", "#00ff00" },
-+ { "#ffffff", "#0000ff" },
-+ { "#ffffff", "#4b0082" },
-+ { "#ffffff", "#9400d3" },
-+ { "#000000", "#ffffff" },
-+ { "#ffffff", "#000000" },
-+};
-+
- static const Rule rules[] = {
- /* xprop(1):
- * WM_CLASS(STRING) = instance, class
-diff --git a/dwm.c b/dwm.c
-index b0b3466..c16d5f5 100644
---- a/dwm.c
-+++ b/dwm.c
-@@ -264,6 +264,7 @@ static Atom wmatom[WMLast], netatom[NetLast];
- static int running = 1;
- static Cur *cursor[CurLast];
- static Clr **scheme;
-+static Clr **tagscheme;
- static Display *dpy;
- static Drw *drw;
- static Monitor *mons, *selmon;
-@@ -717,7 +718,7 @@ drawbar(Monitor *m)
- x = 0;
- for (i = 0; i < LENGTH(tags); i++) {
- w = TEXTW(tags[i]);
-- drw_setscheme(drw, scheme[m->tagset[m->seltags] & 1 << i ? SchemeSel : SchemeNorm]);
-+ drw_setscheme(drw, (m->tagset[m->seltags] & 1 << i ? tagscheme[i] : scheme[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,
-@@ -1568,9 +1569,14 @@ setup(void)
- cursor[CurResize] = drw_cur_create(drw, XC_sizing);
- cursor[CurMove] = drw_cur_create(drw, XC_fleur);
- /* init appearance */
-+ if (LENGTH(tags) > LENGTH(tagsel))
-+ die("too few color schemes for the tags");
- scheme = ecalloc(LENGTH(colors), sizeof(Clr *));
- for (i = 0; i < LENGTH(colors); i++)
- scheme[i] = drw_scm_create(drw, colors[i], 3);
-+ tagscheme = ecalloc(LENGTH(tagsel), sizeof(Clr *));
-+ for (i = 0; i < LENGTH(tagsel); i++)
-+ tagscheme[i] = drw_scm_create(drw, tagsel[i], 2);
- /* init bars */
- updatebars();
- updatestatus();
diff --git a/patches/dwm-status2d-systray-6.3.diff b/patches/dwm-status2d-systray-6.3.diff
@@ -1,888 +0,0 @@
-diff --git a/config.def.h b/config.def.h
-index a2ac963..86fcc84 100644
---- a/config.def.h
-+++ b/config.def.h
-@@ -3,8 +3,13 @@
- /* appearance */
- static const unsigned int borderpx = 1; /* border pixel of windows */
- static const unsigned int snap = 32; /* snap pixel */
--static const int showbar = 1; /* 0 means no bar */
--static const int topbar = 1; /* 0 means bottom bar */
-+static const unsigned int systraypinning = 0; /* 0: sloppy systray follows selected monitor, >0: pin systray to monitor X */
-+static const unsigned int systrayonleft = 0; /* 0: systray in the right corner, >0: systray on left of status text */
-+static const unsigned int systrayspacing = 2; /* systray spacing */
-+static const int systraypinningfailfirst = 1; /* 1: if pinning fails, display systray on the first monitor, False: display systray on the last monitor*/
-+static const int showsystray = 1; /* 0 means no systray */
-+static const int showbar = 1; /* 0 means no bar */
-+static const int topbar = 1; /* 0 means bottom bar */
- static const char *fonts[] = { "monospace:size=10" };
- static const char dmenufont[] = "monospace:size=10";
- static const char col_gray1[] = "#222222";
-@@ -101,8 +106,8 @@ static Key keys[] = {
- /* click can be ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, or ClkRootWin */
- static Button buttons[] = {
- /* click event mask button function argument */
-- { ClkLtSymbol, 0, Button1, setlayout, {0} },
-- { ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]} },
-+ { ClkTagBar, MODKEY, Button1, tag, {0} },
-+ { ClkTagBar, MODKEY, Button3, toggletag, {0} },
- { ClkWinTitle, 0, Button2, zoom, {0} },
- { ClkStatusText, 0, Button2, spawn, {.v = termcmd } },
- { ClkClientWin, MODKEY, Button1, movemouse, {0} },
-diff --git a/dwm.c b/dwm.c
-index a96f33c..8153bfe 100644
---- a/dwm.c
-+++ b/dwm.c
-@@ -57,12 +57,27 @@
- #define TAGMASK ((1 << LENGTH(tags)) - 1)
- #define TEXTW(X) (drw_fontset_getwidth(drw, (X)) + lrpad)
-
-+#define SYSTEM_TRAY_REQUEST_DOCK 0
-+/* XEMBED messages */
-+#define XEMBED_EMBEDDED_NOTIFY 0
-+#define XEMBED_WINDOW_ACTIVATE 1
-+#define XEMBED_FOCUS_IN 4
-+#define XEMBED_MODALITY_ON 10
-+#define XEMBED_MAPPED (1 << 0)
-+#define XEMBED_WINDOW_ACTIVATE 1
-+#define XEMBED_WINDOW_DEACTIVATE 2
-+#define VERSION_MAJOR 0
-+#define VERSION_MINOR 0
-+#define XEMBED_EMBEDDED_VERSION (VERSION_MAJOR << 16) | VERSION_MINOR
-+
- /* enums */
- enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */
- enum { SchemeNorm, SchemeSel }; /* color schemes */
- enum { NetSupported, NetWMName, NetWMState, NetWMCheck,
-+ NetSystemTray, NetSystemTrayOP, NetSystemTrayOrientation, NetSystemTrayOrientationHorz,
- NetWMFullscreen, NetActiveWindow, NetWMWindowType,
- NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH atoms */
-+enum { Manager, Xembed, XembedInfo, XLast }; /* Xembed atoms */
- enum { WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast }; /* default atoms */
- enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle,
- ClkClientWin, ClkRootWin, ClkLast }; /* clicks */
-@@ -141,6 +156,12 @@ typedef struct {
- int monitor;
- } Rule;
-
-+typedef struct Systray Systray;
-+struct Systray {
-+ Window win;
-+ Client *icons;
-+};
-+
- /* function declarations */
- static void applyrules(Client *c);
- static int applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact);
-@@ -163,6 +184,7 @@ static void detachstack(Client *c);
- static Monitor *dirtomon(int dir);
- static void drawbar(Monitor *m);
- static void drawbars(void);
-+static int drawstatusbar(Monitor *m, int bh, char* text);
- static void enternotify(XEvent *e);
- static void expose(XEvent *e);
- static void focus(Client *c);
-@@ -172,6 +194,7 @@ static void focusstack(const Arg *arg);
- static Atom getatomprop(Client *c, Atom prop);
- static int getrootptr(int *x, int *y);
- static long getstate(Window w);
-+static unsigned int getsystraywidth();
- static int gettextprop(Window w, Atom atom, char *text, unsigned int size);
- static void grabbuttons(Client *c, int focused);
- static void grabkeys(void);
-@@ -189,13 +212,16 @@ static void pop(Client *);
- static void propertynotify(XEvent *e);
- static void quit(const Arg *arg);
- static Monitor *recttomon(int x, int y, int w, int h);
-+static void removesystrayicon(Client *i);
- static void resize(Client *c, int x, int y, int w, int h, int interact);
-+static void resizebarwin(Monitor *m);
- static void resizeclient(Client *c, int x, int y, int w, int h);
- static void resizemouse(const Arg *arg);
-+static void resizerequest(XEvent *e);
- static void restack(Monitor *m);
- static void run(void);
- static void scan(void);
--static int sendevent(Client *c, Atom proto);
-+static int sendevent(Window w, Atom proto, int m, long d0, long d1, long d2, long d3, long d4);
- static void sendmon(Client *c, Monitor *m);
- static void setclientstate(Client *c, long state);
- static void setfocus(Client *c);
-@@ -207,6 +233,7 @@ static void seturgent(Client *c, int urg);
- static void showhide(Client *c);
- static void sigchld(int unused);
- static void spawn(const Arg *arg);
-+static Monitor *systraytomon(Monitor *m);
- static void tag(const Arg *arg);
- static void tagmon(const Arg *arg);
- static void tile(Monitor *);
-@@ -224,20 +251,25 @@ static int updategeom(void);
- static void updatenumlockmask(void);
- static void updatesizehints(Client *c);
- static void updatestatus(void);
-+static void updatesystray(void);
-+static void updatesystrayicongeom(Client *i, int w, int h);
-+static void updatesystrayiconstate(Client *i, XPropertyEvent *ev);
- static void updatetitle(Client *c);
- static void updatewindowtype(Client *c);
- static void updatewmhints(Client *c);
- static void view(const Arg *arg);
- static Client *wintoclient(Window w);
- static Monitor *wintomon(Window w);
-+static Client *wintosystrayicon(Window w);
- static int xerror(Display *dpy, XErrorEvent *ee);
- static int xerrordummy(Display *dpy, XErrorEvent *ee);
- static int xerrorstart(Display *dpy, XErrorEvent *ee);
- static void zoom(const Arg *arg);
-
- /* variables */
-+static Systray *systray = NULL;
- static const char broken[] = "broken";
--static char stext[256];
-+static char stext[1024];
- static int screen;
- static int sw, sh; /* X display screen geometry width, height */
- static int bh, blw = 0; /* bar geometry */
-@@ -258,9 +290,10 @@ static void (*handler[LASTEvent]) (XEvent *) = {
- [MapRequest] = maprequest,
- [MotionNotify] = motionnotify,
- [PropertyNotify] = propertynotify,
-+ [ResizeRequest] = resizerequest,
- [UnmapNotify] = unmapnotify
- };
--static Atom wmatom[WMLast], netatom[NetLast];
-+static Atom wmatom[WMLast], netatom[NetLast], xatom[XLast];
- static int running = 1;
- static Cur *cursor[CurLast];
- static Clr **scheme;
-@@ -440,7 +473,7 @@ buttonpress(XEvent *e)
- arg.ui = 1 << i;
- } else if (ev->x < x + blw)
- click = ClkLtSymbol;
-- else if (ev->x > selmon->ww - (int)TEXTW(stext))
-+ else if (ev->x > selmon->ww - (int)TEXTW(stext) - getsystraywidth())
- click = ClkStatusText;
- else
- click = ClkWinTitle;
-@@ -483,9 +516,16 @@ cleanup(void)
- XUngrabKey(dpy, AnyKey, AnyModifier, root);
- while (mons)
- cleanupmon(mons);
-- for (i = 0; i < CurLast; i++)
-+
-+ if (showsystray) {
-+ XUnmapWindow(dpy, systray->win);
-+ XDestroyWindow(dpy, systray->win);
-+ free(systray);
-+ }
-+
-+ for (i = 0; i < CurLast; i++)
- drw_cur_free(drw, cursor[i]);
-- for (i = 0; i < LENGTH(colors); i++)
-+ for (i = 0; i < LENGTH(colors) + 1; i++)
- free(scheme[i]);
- XDestroyWindow(dpy, wmcheckwin);
- drw_free(drw);
-@@ -513,9 +553,58 @@ cleanupmon(Monitor *mon)
- void
- clientmessage(XEvent *e)
- {
-+ XWindowAttributes wa;
-+ XSetWindowAttributes swa;
- XClientMessageEvent *cme = &e->xclient;
- Client *c = wintoclient(cme->window);
-
-+ if (showsystray && cme->window == systray->win && cme->message_type == netatom[NetSystemTrayOP]) {
-+ /* add systray icons */
-+ if (cme->data.l[1] == SYSTEM_TRAY_REQUEST_DOCK) {
-+ if (!(c = (Client *)calloc(1, sizeof(Client))))
-+ die("fatal: could not malloc() %u bytes\n", sizeof(Client));
-+ if (!(c->win = cme->data.l[2])) {
-+ free(c);
-+ return;
-+ }
-+ c->mon = selmon;
-+ c->next = systray->icons;
-+ systray->icons = c;
-+ if (!XGetWindowAttributes(dpy, c->win, &wa)) {
-+ /* use sane defaults */
-+ wa.width = bh;
-+ wa.height = bh;
-+ wa.border_width = 0;
-+ }
-+ c->x = c->oldx = c->y = c->oldy = 0;
-+ c->w = c->oldw = wa.width;
-+ c->h = c->oldh = wa.height;
-+ c->oldbw = wa.border_width;
-+ c->bw = 0;
-+ c->isfloating = True;
-+ /* reuse tags field as mapped status */
-+ c->tags = 1;
-+ updatesizehints(c);
-+ updatesystrayicongeom(c, wa.width, wa.height);
-+ XAddToSaveSet(dpy, c->win);
-+ XSelectInput(dpy, c->win, StructureNotifyMask | PropertyChangeMask | ResizeRedirectMask);
-+ XReparentWindow(dpy, c->win, systray->win, 0, 0);
-+ /* use parents background color */
-+ swa.background_pixel = scheme[SchemeNorm][ColBg].pixel;
-+ XChangeWindowAttributes(dpy, c->win, CWBackPixel, &swa);
-+ sendevent(c->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_EMBEDDED_NOTIFY, 0 , systray->win, XEMBED_EMBEDDED_VERSION);
-+ /* FIXME not sure if I have to send these events, too */
-+ sendevent(c->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_FOCUS_IN, 0 , systray->win, XEMBED_EMBEDDED_VERSION);
-+ sendevent(c->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_WINDOW_ACTIVATE, 0 , systray->win, XEMBED_EMBEDDED_VERSION);
-+ sendevent(c->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_MODALITY_ON, 0 , systray->win, XEMBED_EMBEDDED_VERSION);
-+ XSync(dpy, False);
-+ resizebarwin(selmon);
-+ updatesystray();
-+ setclientstate(c, NormalState);
-+ }
-+ return;
-+ }
-+
- if (!c)
- return;
- if (cme->message_type == netatom[NetWMState]) {
-@@ -568,7 +657,7 @@ configurenotify(XEvent *e)
- for (c = m->clients; c; c = c->next)
- if (c->isfullscreen)
- resizeclient(c, m->mx, m->my, m->mw, m->mh);
-- XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, bh);
-+ resizebarwin(m);
- }
- focus(NULL);
- arrange(NULL);
-@@ -653,6 +742,11 @@ destroynotify(XEvent *e)
-
- if ((c = wintoclient(ev->window)))
- unmanage(c, 1);
-+ else if ((c = wintosystrayicon(ev->window))) {
-+ removesystrayicon(c);
-+ resizebarwin(selmon);
-+ updatesystray();
-+ }
- }
-
- void
-@@ -693,10 +787,119 @@ dirtomon(int dir)
- return m;
- }
-
-+int
-+drawstatusbar(Monitor *m, int bh, char* stext) {
-+ int ret, i, w, x, len;
-+ short isCode = 0;
-+ char *text;
-+ char *p;
-+
-+ len = strlen(stext) + 1 ;
-+ if (!(text = (char*) malloc(sizeof(char)*len)))
-+ die("malloc");
-+ p = text;
-+ memcpy(text, stext, len);
-+
-+ /* compute width of the status text */
-+ w = 0;
-+ i = -1;
-+ while (text[++i]) {
-+ if (text[i] == '^') {
-+ if (!isCode) {
-+ isCode = 1;
-+ text[i] = '\0';
-+ w += TEXTW(text) - lrpad;
-+ text[i] = '^';
-+ if (text[++i] == 'f')
-+ w += atoi(text + ++i);
-+ } else {
-+ isCode = 0;
-+ text = text + i + 1;
-+ i = -1;
-+ }
-+ }
-+ }
-+ if (!isCode)
-+ w += TEXTW(text) - lrpad;
-+ else
-+ isCode = 0;
-+ text = p;
-+
-+ w += 2; /* 1px padding on both sides */
-+ ret = m->ww - w;
-+ x = m->ww - w - getsystraywidth();
-+
-+ drw_setscheme(drw, scheme[LENGTH(colors)]);
-+ drw->scheme[ColFg] = scheme[SchemeNorm][ColFg];
-+ drw->scheme[ColBg] = scheme[SchemeNorm][ColBg];
-+ drw_rect(drw, x, 0, w, bh, 1, 1);
-+ x++;
-+
-+ /* process status text */
-+ i = -1;
-+ while (text[++i]) {
-+ if (text[i] == '^' && !isCode) {
-+ isCode = 1;
-+
-+ text[i] = '\0';
-+ w = TEXTW(text) - lrpad;
-+ drw_text(drw, x, 0, w, bh, 0, text, 0);
-+
-+ x += w;
-+
-+ /* process code */
-+ while (text[++i] != '^') {
-+ if (text[i] == 'c') {
-+ char buf[8];
-+ memcpy(buf, (char*)text+i+1, 7);
-+ buf[7] = '\0';
-+ drw_clr_create(drw, &drw->scheme[ColFg], buf);
-+ i += 7;
-+ } else if (text[i] == 'b') {
-+ char buf[8];
-+ memcpy(buf, (char*)text+i+1, 7);
-+ buf[7] = '\0';
-+ drw_clr_create(drw, &drw->scheme[ColBg], buf);
-+ i += 7;
-+ } else if (text[i] == 'd') {
-+ drw->scheme[ColFg] = scheme[SchemeNorm][ColFg];
-+ drw->scheme[ColBg] = scheme[SchemeNorm][ColBg];
-+ } else if (text[i] == 'r') {
-+ int rx = atoi(text + ++i);
-+ while (text[++i] != ',');
-+ int ry = atoi(text + ++i);
-+ while (text[++i] != ',');
-+ int rw = atoi(text + ++i);
-+ while (text[++i] != ',');
-+ int rh = atoi(text + ++i);
-+
-+ drw_rect(drw, rx + x, ry, rw, rh, 1, 0);
-+ } else if (text[i] == 'f') {
-+ x += atoi(text + ++i);
-+ }
-+ }
-+
-+ text = text + i + 1;
-+ i=-1;
-+ isCode = 0;
-+ }
-+ }
-+
-+ if (!isCode) {
-+ w = TEXTW(text) - lrpad;
-+ drw_text(drw, x, 0, w, bh, 0, text, 0);
-+ }
-+
-+ drw_setscheme(drw, scheme[SchemeNorm]);
-+ free(p);
-+
-+ return ret;
-+}
-+
- void
- drawbar(Monitor *m)
- {
-- int x, w, tw = 0;
-+ int x, w, tw = 0, stw = 0;
- int boxs = drw->fonts->h / 9;
- int boxw = drw->fonts->h / 6 + 2;
- unsigned int i, occ = 0, urg = 0;
-@@ -705,13 +908,15 @@ drawbar(Monitor *m)
- if (!m->showbar)
- return;
-
-+ if(showsystray && m == systraytomon(m) && !systrayonleft)
-+ stw = getsystraywidth();
-+
- /* draw status first so it can be overdrawn by tags later */
- if (m == selmon) { /* status is only drawn on selected monitor */
-- drw_setscheme(drw, scheme[SchemeNorm]);
-- tw = TEXTW(stext) - lrpad + 2; /* 2px right padding */
-- drw_text(drw, m->ww - tw, 0, tw, bh, 0, stext, 0);
-+ tw = m->ww - drawstatusbar(m, bh, stext);
- }
-
-+ resizebarwin(m);
- for (c = m->clients; c; c = c->next) {
- occ |= c->tags;
- if (c->isurgent)
-@@ -732,7 +937,7 @@ drawbar(Monitor *m)
- drw_setscheme(drw, scheme[SchemeNorm]);
- x = drw_text(drw, x, 0, w, bh, lrpad / 2, m->ltsymbol, 0);
-
-- if ((w = m->ww - tw - x) > bh) {
-+ if ((w = m->ww - tw - stw - x) > bh) {
- if (m->sel) {
- drw_setscheme(drw, scheme[m == selmon ? SchemeSel : SchemeNorm]);
- drw_text(drw, x, 0, w, bh, lrpad / 2, m->sel->name, 0);
-@@ -743,7 +948,7 @@ drawbar(Monitor *m)
- drw_rect(drw, x, 0, w, bh, 1, 1);
- }
- }
-- drw_map(drw, m->barwin, 0, 0, m->ww, bh);
-+ drw_map(drw, m->barwin, 0, 0, m->ww - stw, bh);
- }
-
- void
-@@ -780,8 +985,11 @@ expose(XEvent *e)
- Monitor *m;
- XExposeEvent *ev = &e->xexpose;
-
-- if (ev->count == 0 && (m = wintomon(ev->window)))
-+ if (ev->count == 0 && (m = wintomon(ev->window))) {
- drawbar(m);
-+ if (m == selmon)
-+ updatesystray();
-+ }
- }
-
- void
-@@ -867,9 +1075,17 @@ getatomprop(Client *c, Atom prop)
- unsigned char *p = NULL;
- Atom da, atom = None;
-
-- if (XGetWindowProperty(dpy, c->win, prop, 0L, sizeof atom, False, XA_ATOM,
-+ /* FIXME getatomprop should return the number of items and a pointer to
-+ * the stored data instead of this workaround */
-+ Atom req = XA_ATOM;
-+ if (prop == xatom[XembedInfo])
-+ req = xatom[XembedInfo];
-+
-+ if (XGetWindowProperty(dpy, c->win, prop, 0L, sizeof atom, False, req,
- &da, &di, &dl, &dl, &p) == Success && p) {
- atom = *(Atom *)p;
-+ if (da == xatom[XembedInfo] && dl == 2)
-+ atom = ((Atom *)p)[1];
- XFree(p);
- }
- return atom;
-@@ -903,6 +1119,16 @@ getstate(Window w)
- return result;
- }
-
-+unsigned int
-+getsystraywidth()
-+{
-+ unsigned int w = 0;
-+ Client *i;
-+ if(showsystray)
-+ for(i = systray->icons; i; w += i->w + systrayspacing, i = i->next) ;
-+ return w ? w + systrayspacing : 1;
-+}
-+
- int
- gettextprop(Window w, Atom atom, char *text, unsigned int size)
- {
-@@ -1007,7 +1233,8 @@ killclient(const Arg *arg)
- {
- if (!selmon->sel)
- return;
-- if (!sendevent(selmon->sel, wmatom[WMDelete])) {
-+
-+ if (!sendevent(selmon->sel->win, wmatom[WMDelete], NoEventMask, wmatom[WMDelete], CurrentTime, 0 , 0, 0)) {
- XGrabServer(dpy);
- XSetErrorHandler(xerrordummy);
- XSetCloseDownMode(dpy, DestroyAll);
-@@ -1096,6 +1323,13 @@ maprequest(XEvent *e)
- static XWindowAttributes wa;
- XMapRequestEvent *ev = &e->xmaprequest;
-
-+ Client *i;
-+ if ((i = wintosystrayicon(ev->window))) {
-+ sendevent(i->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_WINDOW_ACTIVATE, 0, systray->win, XEMBED_EMBEDDED_VERSION);
-+ resizebarwin(selmon);
-+ updatesystray();
-+ }
-+
- if (!XGetWindowAttributes(dpy, ev->window, &wa))
- return;
- if (wa.override_redirect)
-@@ -1219,7 +1453,18 @@ propertynotify(XEvent *e)
- Window trans;
- XPropertyEvent *ev = &e->xproperty;
-
-- if ((ev->window == root) && (ev->atom == XA_WM_NAME))
-+ if ((c = wintosystrayicon(ev->window))) {
-+ if (ev->atom == XA_WM_NORMAL_HINTS) {
-+ updatesizehints(c);
-+ updatesystrayicongeom(c, c->w, c->h);
-+ }
-+ else
-+ updatesystrayiconstate(c, ev);
-+ resizebarwin(selmon);
-+ updatesystray();
-+ }
-+
-+ if ((ev->window == root) && (ev->atom == XA_WM_NAME))
- updatestatus();
- else if (ev->state == PropertyDelete)
- return; /* ignore */
-@@ -1269,6 +1514,19 @@ recttomon(int x, int y, int w, int h)
- return r;
- }
-
-+void
-+removesystrayicon(Client *i)
-+{
-+ Client **ii;
-+
-+ if (!showsystray || !i)
-+ return;
-+ for (ii = &systray->icons; *ii && *ii != i; ii = &(*ii)->next);
-+ if (ii)
-+ *ii = i->next;
-+ free(i);
-+}
-+
- void
- resize(Client *c, int x, int y, int w, int h, int interact)
- {
-@@ -1276,6 +1534,14 @@ resize(Client *c, int x, int y, int w, int h, int interact)
- resizeclient(c, x, y, w, h);
- }
-
-+void
-+resizebarwin(Monitor *m) {
-+ unsigned int w = m->ww;
-+ if (showsystray && m == systraytomon(m) && !systrayonleft)
-+ w -= getsystraywidth();
-+ XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, w, bh);
-+}
-+
- void
- resizeclient(Client *c, int x, int y, int w, int h)
- {
-@@ -1348,6 +1614,19 @@ resizemouse(const Arg *arg)
- }
- }
-
-+void
-+resizerequest(XEvent *e)
-+{
-+ XResizeRequestEvent *ev = &e->xresizerequest;
-+ Client *i;
-+
-+ if ((i = wintosystrayicon(ev->window))) {
-+ updatesystrayicongeom(i, ev->width, ev->height);
-+ resizebarwin(selmon);
-+ updatesystray();
-+ }
-+}
-+
- void
- restack(Monitor *m)
- {
-@@ -1437,26 +1716,37 @@ setclientstate(Client *c, long state)
- }
-
- int
--sendevent(Client *c, Atom proto)
-+sendevent(Window w, Atom proto, int mask, long d0, long d1, long d2, long d3, long d4)
- {
- int n;
-- Atom *protocols;
-+ Atom *protocols, mt;
- int exists = 0;
- XEvent ev;
-
-- if (XGetWMProtocols(dpy, c->win, &protocols, &n)) {
-- while (!exists && n--)
-- exists = protocols[n] == proto;
-- XFree(protocols);
-+ if (proto == wmatom[WMTakeFocus] || proto == wmatom[WMDelete]) {
-+ mt = wmatom[WMProtocols];
-+ if (XGetWMProtocols(dpy, w, &protocols, &n)) {
-+ while (!exists && n--)
-+ exists = protocols[n] == proto;
-+ XFree(protocols);
-+ }
- }
-+ else {
-+ exists = True;
-+ mt = proto;
-+ }
-+
- if (exists) {
- ev.type = ClientMessage;
-- ev.xclient.window = c->win;
-- ev.xclient.message_type = wmatom[WMProtocols];
-+ ev.xclient.window = w;
-+ ev.xclient.message_type = mt;
- ev.xclient.format = 32;
-- ev.xclient.data.l[0] = proto;
-- ev.xclient.data.l[1] = CurrentTime;
-- XSendEvent(dpy, c->win, False, NoEventMask, &ev);
-+ ev.xclient.data.l[0] = d0;
-+ ev.xclient.data.l[1] = d1;
-+ ev.xclient.data.l[2] = d2;
-+ ev.xclient.data.l[3] = d3;
-+ ev.xclient.data.l[4] = d4;
-+ XSendEvent(dpy, w, False, mask, &ev);
- }
- return exists;
- }
-@@ -1470,7 +1760,7 @@ setfocus(Client *c)
- XA_WINDOW, 32, PropModeReplace,
- (unsigned char *) &(c->win), 1);
- }
-- sendevent(c, wmatom[WMTakeFocus]);
-+ sendevent(c->win, wmatom[WMTakeFocus], NoEventMask, wmatom[WMTakeFocus], CurrentTime, 0, 0, 0);
- }
-
- void
-@@ -1558,22 +1848,32 @@ setup(void)
- wmatom[WMState] = XInternAtom(dpy, "WM_STATE", False);
- wmatom[WMTakeFocus] = XInternAtom(dpy, "WM_TAKE_FOCUS", False);
- netatom[NetActiveWindow] = XInternAtom(dpy, "_NET_ACTIVE_WINDOW", False);
-- netatom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False);
-- netatom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False);
-+ netatom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False);
-+ netatom[NetSystemTray] = XInternAtom(dpy, "_NET_SYSTEM_TRAY_S0", False);
-+ netatom[NetSystemTrayOP] = XInternAtom(dpy, "_NET_SYSTEM_TRAY_OPCODE", False);
-+ netatom[NetSystemTrayOrientation] = XInternAtom(dpy, "_NET_SYSTEM_TRAY_ORIENTATION", False);
-+ netatom[NetSystemTrayOrientationHorz] = XInternAtom(dpy, "_NET_SYSTEM_TRAY_ORIENTATION_HORZ", False);
-+ netatom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False);
- netatom[NetWMState] = XInternAtom(dpy, "_NET_WM_STATE", False);
- netatom[NetWMCheck] = XInternAtom(dpy, "_NET_SUPPORTING_WM_CHECK", False);
- netatom[NetWMFullscreen] = XInternAtom(dpy, "_NET_WM_STATE_FULLSCREEN", False);
- netatom[NetWMWindowType] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE", False);
- netatom[NetWMWindowTypeDialog] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DIALOG", False);
- netatom[NetClientList] = XInternAtom(dpy, "_NET_CLIENT_LIST", False);
-- /* init cursors */
-+ xatom[Manager] = XInternAtom(dpy, "MANAGER", False);
-+ xatom[Xembed] = XInternAtom(dpy, "_XEMBED", False);
-+ xatom[XembedInfo] = XInternAtom(dpy, "_XEMBED_INFO", False);
-+ /* init cursors */
- cursor[CurNormal] = drw_cur_create(drw, XC_left_ptr);
- cursor[CurResize] = drw_cur_create(drw, XC_sizing);
- cursor[CurMove] = drw_cur_create(drw, XC_fleur);
- /* init appearance */
-- scheme = ecalloc(LENGTH(colors), sizeof(Clr *));
-+ scheme = ecalloc(LENGTH(colors) + 1, sizeof(Clr *));
-+ scheme[LENGTH(colors)] = drw_scm_create(drw, colors[0], 3);
- for (i = 0; i < LENGTH(colors); i++)
- scheme[i] = drw_scm_create(drw, colors[i], 3);
-+ /* init system tray */
-+ updatesystray();
- /* init bars */
- updatebars();
- updatestatus();
-@@ -1707,7 +2007,18 @@ togglebar(const Arg *arg)
- {
- selmon->showbar = !selmon->showbar;
- updatebarpos(selmon);
-- XMoveResizeWindow(dpy, selmon->barwin, selmon->wx, selmon->by, selmon->ww, bh);
-+ resizebarwin(selmon);
-+ if (showsystray) {
-+ XWindowChanges wc;
-+ if (!selmon->showbar)
-+ wc.y = -bh;
-+ else if (selmon->showbar) {
-+ wc.y = 0;
-+ if (!selmon->topbar)
-+ wc.y = selmon->mh - bh;
-+ }
-+ XConfigureWindow(dpy, systray->win, CWY, &wc);
-+ }
- arrange(selmon);
- }
-
-@@ -1802,11 +2113,18 @@ unmapnotify(XEvent *e)
- else
- unmanage(c, 0);
- }
-+ else if ((c = wintosystrayicon(ev->window))) {
-+ /* KLUDGE! sometimes icons occasionally unmap their windows, but do
-+ * _not_ destroy them. We map those windows back */
-+ XMapRaised(dpy, c->win);
-+ updatesystray();
-+ }
- }
-
- void
- updatebars(void)
- {
-+ unsigned int w;
- Monitor *m;
- XSetWindowAttributes wa = {
- .override_redirect = True,
-@@ -1817,10 +2135,15 @@ updatebars(void)
- for (m = mons; m; m = m->next) {
- if (m->barwin)
- continue;
-- m->barwin = XCreateWindow(dpy, root, m->wx, m->by, m->ww, bh, 0, DefaultDepth(dpy, screen),
-+ w = m->ww;
-+ if (showsystray && m == systraytomon(m))
-+ w -= getsystraywidth();
-+ m->barwin = XCreateWindow(dpy, root, m->wx, m->by, w, bh, 0, DefaultDepth(dpy, screen),
- CopyFromParent, DefaultVisual(dpy, screen),
- CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa);
- XDefineCursor(dpy, m->barwin, cursor[CurNormal]->cursor);
-+ if (showsystray && m == systraytomon(m))
-+ XMapRaised(dpy, systray->win);
- XMapRaised(dpy, m->barwin);
- XSetClassHint(dpy, m->barwin, &ch);
- }
-@@ -1996,6 +2319,125 @@ updatestatus(void)
- if (!gettextprop(root, XA_WM_NAME, stext, sizeof(stext)))
- strcpy(stext, "dwm-"VERSION);
- drawbar(selmon);
-+ updatesystray();
-+}
-+
-+
-+void
-+updatesystrayicongeom(Client *i, int w, int h)
-+{
-+ if (i) {
-+ i->h = bh;
-+ if (w == h)
-+ i->w = bh;
-+ else if (h == bh)
-+ i->w = w;
-+ else
-+ i->w = (int) ((float)bh * ((float)w / (float)h));
-+ applysizehints(i, &(i->x), &(i->y), &(i->w), &(i->h), False);
-+ /* force icons into the systray dimensions if they don't want to */
-+ if (i->h > bh) {
-+ if (i->w == i->h)
-+ i->w = bh;
-+ else
-+ i->w = (int) ((float)bh * ((float)i->w / (float)i->h));
-+ i->h = bh;
-+ }
-+ }
-+}
-+
-+void
-+updatesystrayiconstate(Client *i, XPropertyEvent *ev)
-+{
-+ long flags;
-+ int code = 0;
-+
-+ if (!showsystray || !i || ev->atom != xatom[XembedInfo] ||
-+ !(flags = getatomprop(i, xatom[XembedInfo])))
-+ return;
-+
-+ if (flags & XEMBED_MAPPED && !i->tags) {
-+ i->tags = 1;
-+ code = XEMBED_WINDOW_ACTIVATE;
-+ XMapRaised(dpy, i->win);
-+ setclientstate(i, NormalState);
-+ }
-+ else if (!(flags & XEMBED_MAPPED) && i->tags) {
-+ i->tags = 0;
-+ code = XEMBED_WINDOW_DEACTIVATE;
-+ XUnmapWindow(dpy, i->win);
-+ setclientstate(i, WithdrawnState);
-+ }
-+ else
-+ return;
-+ sendevent(i->win, xatom[Xembed], StructureNotifyMask, CurrentTime, code, 0,
-+ systray->win, XEMBED_EMBEDDED_VERSION);
-+}
-+
-+void
-+updatesystray(void)
-+{
-+ XSetWindowAttributes wa;
-+ XWindowChanges wc;
-+ Client *i;
-+ Monitor *m = systraytomon(NULL);
-+ unsigned int x = m->mx + m->mw;
-+ unsigned int sw = TEXTW(stext) - lrpad + systrayspacing;
-+ unsigned int w = 1;
-+
-+ if (!showsystray)
-+ return;
-+ if (systrayonleft)
-+ x -= sw + lrpad / 2;
-+ if (!systray) {
-+ /* init systray */
-+ if (!(systray = (Systray *)calloc(1, sizeof(Systray))))
-+ die("fatal: could not malloc() %u bytes\n", sizeof(Systray));
-+ systray->win = XCreateSimpleWindow(dpy, root, x, m->by, w, bh, 0, 0, scheme[SchemeSel][ColBg].pixel);
-+ wa.event_mask = ButtonPressMask | ExposureMask;
-+ wa.override_redirect = True;
-+ wa.background_pixel = scheme[SchemeNorm][ColBg].pixel;
-+ XSelectInput(dpy, systray->win, SubstructureNotifyMask);
-+ XChangeProperty(dpy, systray->win, netatom[NetSystemTrayOrientation], XA_CARDINAL, 32,
-+ PropModeReplace, (unsigned char *)&netatom[NetSystemTrayOrientationHorz], 1);
-+ XChangeWindowAttributes(dpy, systray->win, CWEventMask|CWOverrideRedirect|CWBackPixel, &wa);
-+ XMapRaised(dpy, systray->win);
-+ XSetSelectionOwner(dpy, netatom[NetSystemTray], systray->win, CurrentTime);
-+ if (XGetSelectionOwner(dpy, netatom[NetSystemTray]) == systray->win) {
-+ sendevent(root, xatom[Manager], StructureNotifyMask, CurrentTime, netatom[NetSystemTray], systray->win, 0, 0);
-+ XSync(dpy, False);
-+ }
-+ else {
-+ fprintf(stderr, "dwm: unable to obtain system tray.\n");
-+ free(systray);
-+ systray = NULL;
-+ return;
-+ }
-+ }
-+ for (w = 0, i = systray->icons; i; i = i->next) {
-+ /* make sure the background color stays the same */
-+ wa.background_pixel = scheme[SchemeNorm][ColBg].pixel;
-+ XChangeWindowAttributes(dpy, i->win, CWBackPixel, &wa);
-+ XMapRaised(dpy, i->win);
-+ w += systrayspacing;
-+ i->x = w;
-+ XMoveResizeWindow(dpy, i->win, i->x, 0, i->w, i->h);
-+ w += i->w;
-+ if (i->mon != m)
-+ i->mon = m;
-+ }
-+ w = w ? w + systrayspacing : 1;
-+ x -= w;
-+ XMoveResizeWindow(dpy, systray->win, x, m->by, w, bh);
-+ wc.x = x; wc.y = m->by; wc.width = w; wc.height = bh;
-+ wc.stack_mode = Above; wc.sibling = m->barwin;
-+ XConfigureWindow(dpy, systray->win, CWX|CWY|CWWidth|CWHeight|CWSibling|CWStackMode, &wc);
-+ XMapWindow(dpy, systray->win);
-+ XMapSubwindows(dpy, systray->win);
-+ /* redraw background */
-+ XSetForeground(dpy, drw->gc, scheme[SchemeNorm][ColBg].pixel);
-+ XFillRectangle(dpy, systray->win, drw->gc, 0, 0, w, bh);
-+ XSync(dpy, False);
- }
-
- void
-@@ -2063,6 +2505,16 @@ wintoclient(Window w)
- return NULL;
- }
-
-+Client *
-+wintosystrayicon(Window w) {
-+ Client *i = NULL;
-+
-+ if (!showsystray || !w)
-+ return i;
-+ for (i = systray->icons; i && i->win != w; i = i->next) ;
-+ return i;
-+}
-+
- Monitor *
- wintomon(Window w)
- {
-@@ -2116,6 +2568,22 @@ xerrorstart(Display *dpy, XErrorEvent *ee)
- return -1;
- }
-
-+Monitor *
-+systraytomon(Monitor *m) {
-+ Monitor *t;
-+ int i, n;
-+ if(!systraypinning) {
-+ if(!m)
-+ return selmon;
-+ return m == selmon ? m : NULL;
-+ }
-+ for(n = 1, t = mons; t && t->next; n++, t = t->next) ;
-+ for(i = 1, t = mons; t && t->next && i < systraypinning; i++, t = t->next) ;
-+ if(systraypinningfailfirst && n < systraypinning)
-+ return mons;
-+ return t;
-+}
-+
- void
- zoom(const Arg *arg)
- {
diff --git a/patches/dwm-underlinetags-6.2.diff b/patches/dwm-underlinetags-6.2.diff
@@ -0,0 +1,27 @@
+diff -pu dwm.git/config.def.h dwm.underlinetags/config.def.h
+--- dwm.git/config.def.h 2021-02-27 20:04:32.030570909 -0600
++++ dwm.underlinetags/config.def.h 2021-03-16 16:42:26.278703624 -0500
+@@ -21,6 +21,11 @@ static const char *colors[][3] = {
+ /* tagging */
+ static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" };
+
++static const unsigned int ulinepad = 5; /* horizontal padding between the underline and tag */
++static const unsigned int ulinestroke = 2; /* thickness / height of the underline */
++static const unsigned int ulinevoffset = 0; /* how far above the bottom of the bar the line should appear */
++static const int ulineall = 0; /* 1 to show underline on all tags, 0 for just the active ones */
++
+ static const Rule rules[] = {
+ /* xprop(1):
+ * WM_CLASS(STRING) = instance, class
+diff -pu dwm.git/dwm.c dwm.underlinetags/dwm.c
+--- dwm.git/dwm.c 2021-02-27 20:04:32.030570909 -0600
++++ dwm.underlinetags/dwm.c 2021-03-16 16:41:21.468077151 -0500
+@@ -719,6 +719,8 @@ drawbar(Monitor *m)
+ 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 (ulineall || m->tagset[m->seltags] & 1 << i) /* if there are conflicts, just move these lines directly underneath both 'drw_setscheme' and 'drw_text' :) */
++ drw_rect(drw, x + ulinepad, bh - ulinestroke - ulinevoffset, w - (ulinepad * 2), ulinestroke, 1, 0);
+ if (occ & 1 << i)
+ drw_rect(drw, x + boxs, boxs, boxw, boxw,
+ m == selmon && selmon->sel && selmon->sel->tags & 1 << i,
diff --git a/util.c b/util.c
@@ -6,18 +6,9 @@
#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, ...) {
+die(const char *fmt, ...)
+{
va_list ap;
va_start(ap, fmt);
@@ -33,3 +24,13 @@ die(const char *fmt, ...) {
exit(1);
}
+
+void *
+ecalloc(size_t nmemb, size_t size)
+{
+ void *p;
+
+ if (!(p = calloc(nmemb, size)))
+ die("calloc:");
+ return p;
+}