diff options
| author | terminaldweller <thabogre@gmail.com> | 2022-07-04 18:44:40 +0000 | 
|---|---|---|
| committer | terminaldweller <thabogre@gmail.com> | 2022-07-04 18:44:40 +0000 | 
| commit | d7f50d26e3207136234adfae6965dcee749674fc (patch) | |
| tree | 77db6903b92639bbd061dcbce16152ab48665fb0 | |
| parent | first commit (diff) | |
| download | dwm-main.tar.gz dwm-main.zip | |
Diffstat (limited to '')
| -rw-r--r-- | config.def.h | 206 | ||||
| -rw-r--r-- | config.mk | 8 | ||||
| -rw-r--r-- | drw.c | 2 | ||||
| -rw-r--r-- | drw.h | 2 | ||||
| -rw-r--r-- | dwm-anybar-polybar-tray-fix-20200810-bb2e722.diff | 430 | ||||
| -rw-r--r-- | dwm-bidi-20220309-0386419.diff | 132 | ||||
| -rw-r--r-- | dwm-xresources-20210827-138b405.diff | 240 | ||||
| -rw-r--r-- | dwm.c | 304 | 
8 files changed, 1210 insertions, 114 deletions
| diff --git a/config.def.h b/config.def.h index a2ac963..cfcfc2d 100644 --- a/config.def.h +++ b/config.def.h @@ -1,116 +1,146 @@  /* See LICENSE file for copyright and license details. */  /* appearance */ -static const unsigned int borderpx  = 1;        /* border pixel of windows */ -static const unsigned int snap      = 32;       /* snap pixel */ -static const int showbar            = 1;        /* 0 means no bar */ -static const int topbar             = 1;        /* 0 means bottom bar */ -static const char *fonts[]          = { "monospace:size=10" }; -static const char dmenufont[]       = "monospace:size=10"; -static const char col_gray1[]       = "#222222"; -static const char col_gray2[]       = "#444444"; -static const char col_gray3[]       = "#bbbbbb"; -static const char col_gray4[]       = "#eeeeee"; -static const char col_cyan[]        = "#005577"; -static const char *colors[][3]      = { -	/*               fg         bg         border   */ -	[SchemeNorm] = { col_gray3, col_gray1, col_gray2 }, -	[SchemeSel]  = { col_gray4, col_cyan,  col_cyan  }, +static unsigned int borderpx = 1;           /* border pixel of windows */ +static unsigned int snap = 32;              /* snap pixel */ +static int showbar = 1;                     /* 0 means no bar */ +static int topbar = 1;                      /* 0 means bottom bar */ +static const int usealtbar = 1;             /* 1 means use non-dwm status bar */ +static const char *altbarclass = "Polybar"; /* Alternate bar class name */ +static const char *alttrayname = "tray";    /* Polybar tray instance name */ +static const char *altbarcmd = +    "$HOME/bar.sh"; /* Alternate bar launch command */ +static char font[] = "monospace:size=10"; +static char dmenufont[] = "monospace:size=10"; +static const char *fonts[] = {font}; +static char normbgcolor[] = "#222222"; +static char normbordercolor[] = "#444444"; +static char normfgcolor[] = "#bbbbbb"; +static char selfgcolor[] = "#eeeeee"; +static char selbordercolor[] = "#005577"; +static char selbgcolor[] = "#005577"; +static char *colors[][3] = { +    /*               fg           bg           border   */ +    [SchemeNorm] = {normfgcolor, normbgcolor, normbordercolor}, +    [SchemeSel] = {selfgcolor, selbgcolor, selbordercolor},  };  /* tagging */ -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): -	 *	WM_CLASS(STRING) = instance, class -	 *	WM_NAME(STRING) = title -	 */ -	/* class      instance    title       tags mask     isfloating   monitor */ -	{ "Gimp",     NULL,       NULL,       0,            1,           -1 }, -	{ "Firefox",  NULL,       NULL,       1 << 8,       0,           -1 }, +    /* xprop(1): +     *	WM_CLASS(STRING) = instance, class +     *	WM_NAME(STRING) = title +     */ +    /* class      instance    title       tags mask     isfloating   monitor */ +    {"Gimp", NULL, NULL, 0, 1, -1}, +    {"Firefox", NULL, NULL, 1 << 8, 0, -1},  };  /* layout(s) */ -static const float mfact     = 0.55; /* factor of master area size [0.05..0.95] */ -static const int nmaster     = 1;    /* number of clients in master area */ -static const int resizehints = 1;    /* 1 means respect size hints in tiled resizals */ -static const int lockfullscreen = 1; /* 1 will force focus on the fullscreen window */ +static float mfact = 0.55;  /* factor of master area size [0.05..0.95] */ +static int nmaster = 1;     /* number of clients in master area */ +static int resizehints = 1; /* 1 means respect size hints in tiled resizals */ +static const int lockfullscreen = +    1; /* 1 will force focus on the fullscreen window */  static const Layout layouts[] = { -	/* symbol     arrange function */ -	{ "[]=",      tile },    /* first entry is default */ -	{ "><>",      NULL },    /* no layout function means floating behavior */ -	{ "[M]",      monocle }, +    /* symbol     arrange function */ +    {"[]=", tile}, /* first entry is default */ +    {"><>", NULL}, /* no layout function means floating behavior */ +    {"[M]", monocle},  };  /* key definitions */  #define MODKEY Mod1Mask -#define TAGKEYS(KEY,TAG) \ -	{ MODKEY,                       KEY,      view,           {.ui = 1 << TAG} }, \ -	{ MODKEY|ControlMask,           KEY,      toggleview,     {.ui = 1 << TAG} }, \ -	{ MODKEY|ShiftMask,             KEY,      tag,            {.ui = 1 << TAG} }, \ -	{ MODKEY|ControlMask|ShiftMask, KEY,      toggletag,      {.ui = 1 << TAG} }, +#define TAGKEYS(KEY, TAG)                                                      \ +  {MODKEY, KEY, view, {.ui = 1 << TAG}},                                       \ +      {MODKEY | ControlMask, KEY, toggleview, {.ui = 1 << TAG}},               \ +      {MODKEY | ShiftMask, KEY, tag, {.ui = 1 << TAG}},                        \ +      {MODKEY | ControlMask | ShiftMask, KEY, toggletag, {.ui = 1 << TAG}},  /* helper for spawning shell commands in the pre dwm-5.0 fashion */ -#define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } } +#define SHCMD(cmd)                                                             \ +  {                                                                            \ +    .v = (const char *[]) { "/bin/sh", "-c", cmd, NULL }                       \ +  }  /* commands */ -static char dmenumon[2] = "0"; /* component of dmenucmd, manipulated in spawn() */ -static const char *dmenucmd[] = { "dmenu_run", "-m", dmenumon, "-fn", dmenufont, "-nb", col_gray1, "-nf", col_gray3, "-sb", col_cyan, "-sf", col_gray4, NULL }; -static const char *termcmd[]  = { "st", NULL }; +static char dmenumon[2] = +    "0"; /* component of dmenucmd, manipulated in spawn() */ +static const char *dmenucmd[] = {"dmenu_run", "-m",  dmenumon,       "-fn", +                                 dmenufont,   "-nb", normbgcolor,    "-nf", +                                 normfgcolor, "-sb", selbordercolor, "-sf", +                                 selfgcolor,  NULL}; +static const char *termcmd[] = {"st", NULL}; + +/* + * Xresources preferences to load at startup + */ +ResourcePref resources[] = { +    {"font", STRING, &font}, +    {"dmenufont", STRING, &dmenufont}, +    {"normbgcolor", STRING, &normbgcolor}, +    {"normbordercolor", STRING, &normbordercolor}, +    {"normfgcolor", STRING, &normfgcolor}, +    {"selbgcolor", STRING, &selbgcolor}, +    {"selbordercolor", STRING, &selbordercolor}, +    {"selfgcolor", STRING, &selfgcolor}, +    {"borderpx", INTEGER, &borderpx}, +    {"snap", INTEGER, &snap}, +    {"showbar", INTEGER, &showbar}, +    {"topbar", INTEGER, &topbar}, +    {"nmaster", INTEGER, &nmaster}, +    {"resizehints", INTEGER, &resizehints}, +    {"mfact", FLOAT, &mfact}, +};  static Key keys[] = { -	/* modifier                     key        function        argument */ -	{ MODKEY,                       XK_p,      spawn,          {.v = dmenucmd } }, -	{ MODKEY|ShiftMask,             XK_Return, spawn,          {.v = termcmd } }, -	{ MODKEY,                       XK_b,      togglebar,      {0} }, -	{ MODKEY,                       XK_j,      focusstack,     {.i = +1 } }, -	{ MODKEY,                       XK_k,      focusstack,     {.i = -1 } }, -	{ MODKEY,                       XK_i,      incnmaster,     {.i = +1 } }, -	{ MODKEY,                       XK_d,      incnmaster,     {.i = -1 } }, -	{ MODKEY,                       XK_h,      setmfact,       {.f = -0.05} }, -	{ MODKEY,                       XK_l,      setmfact,       {.f = +0.05} }, -	{ MODKEY,                       XK_Return, zoom,           {0} }, -	{ MODKEY,                       XK_Tab,    view,           {0} }, -	{ MODKEY|ShiftMask,             XK_c,      killclient,     {0} }, -	{ MODKEY,                       XK_t,      setlayout,      {.v = &layouts[0]} }, -	{ MODKEY,                       XK_f,      setlayout,      {.v = &layouts[1]} }, -	{ MODKEY,                       XK_m,      setlayout,      {.v = &layouts[2]} }, -	{ MODKEY,                       XK_space,  setlayout,      {0} }, -	{ MODKEY|ShiftMask,             XK_space,  togglefloating, {0} }, -	{ MODKEY,                       XK_0,      view,           {.ui = ~0 } }, -	{ MODKEY|ShiftMask,             XK_0,      tag,            {.ui = ~0 } }, -	{ MODKEY,                       XK_comma,  focusmon,       {.i = -1 } }, -	{ MODKEY,                       XK_period, focusmon,       {.i = +1 } }, -	{ MODKEY|ShiftMask,             XK_comma,  tagmon,         {.i = -1 } }, -	{ MODKEY|ShiftMask,             XK_period, tagmon,         {.i = +1 } }, -	TAGKEYS(                        XK_1,                      0) -	TAGKEYS(                        XK_2,                      1) -	TAGKEYS(                        XK_3,                      2) -	TAGKEYS(                        XK_4,                      3) -	TAGKEYS(                        XK_5,                      4) -	TAGKEYS(                        XK_6,                      5) -	TAGKEYS(                        XK_7,                      6) -	TAGKEYS(                        XK_8,                      7) -	TAGKEYS(                        XK_9,                      8) -	{ MODKEY|ShiftMask,             XK_q,      quit,           {0} }, +    /* modifier                     key        function        argument */ +    {MODKEY, XK_p, spawn, {.v = dmenucmd}}, +    {MODKEY | ShiftMask, XK_Return, spawn, {.v = termcmd}}, +    {MODKEY, XK_b, togglebar, {0}}, +    {MODKEY, XK_j, focusstack, {.i = +1}}, +    {MODKEY, XK_k, focusstack, {.i = -1}}, +    {MODKEY, XK_i, incnmaster, {.i = +1}}, +    {MODKEY, XK_d, incnmaster, {.i = -1}}, +    {MODKEY, XK_h, setmfact, {.f = -0.05}}, +    {MODKEY, XK_l, setmfact, {.f = +0.05}}, +    {MODKEY, XK_Return, zoom, {0}}, +    {MODKEY, XK_Tab, view, {0}}, +    {MODKEY | ShiftMask, XK_c, killclient, {0}}, +    {MODKEY, XK_t, setlayout, {.v = &layouts[0]}}, +    {MODKEY, XK_f, setlayout, {.v = &layouts[1]}}, +    {MODKEY, XK_m, setlayout, {.v = &layouts[2]}}, +    {MODKEY, XK_space, setlayout, {0}}, +    {MODKEY | ShiftMask, XK_space, togglefloating, {0}}, +    {MODKEY, XK_0, view, {.ui = ~0}}, +    {MODKEY | ShiftMask, XK_0, tag, {.ui = ~0}}, +    {MODKEY, XK_comma, focusmon, {.i = -1}}, +    {MODKEY, XK_period, focusmon, {.i = +1}}, +    {MODKEY | ShiftMask, XK_comma, tagmon, {.i = -1}}, +    {MODKEY | ShiftMask, XK_period, tagmon, {.i = +1}}, +    TAGKEYS(XK_1, 0) TAGKEYS(XK_2, 1) TAGKEYS(XK_3, 2) TAGKEYS(XK_4, 3) +        TAGKEYS(XK_5, 4) TAGKEYS(XK_6, 5) TAGKEYS(XK_7, 6) TAGKEYS(XK_8, 7) +            TAGKEYS(XK_9, 8){MODKEY | ShiftMask, XK_q, quit, {0}},  };  /* button definitions */ -/* click can be ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, or ClkRootWin */ +/* click can be ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, + * ClkClientWin, or ClkRootWin */  static Button buttons[] = { -	/* click                event mask      button          function        argument */ -	{ ClkLtSymbol,          0,              Button1,        setlayout,      {0} }, -	{ ClkLtSymbol,          0,              Button3,        setlayout,      {.v = &layouts[2]} }, -	{ ClkWinTitle,          0,              Button2,        zoom,           {0} }, -	{ ClkStatusText,        0,              Button2,        spawn,          {.v = termcmd } }, -	{ ClkClientWin,         MODKEY,         Button1,        movemouse,      {0} }, -	{ ClkClientWin,         MODKEY,         Button2,        togglefloating, {0} }, -	{ ClkClientWin,         MODKEY,         Button3,        resizemouse,    {0} }, -	{ ClkTagBar,            0,              Button1,        view,           {0} }, -	{ ClkTagBar,            0,              Button3,        toggleview,     {0} }, -	{ ClkTagBar,            MODKEY,         Button1,        tag,            {0} }, -	{ ClkTagBar,            MODKEY,         Button3,        toggletag,      {0} }, +    /* click                event mask      button          function argument +     */ +    {ClkLtSymbol, 0, Button1, setlayout, {0}}, +    {ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]}}, +    {ClkWinTitle, 0, Button2, zoom, {0}}, +    {ClkStatusText, 0, Button2, spawn, {.v = termcmd}}, +    {ClkClientWin, MODKEY, Button1, movemouse, {0}}, +    {ClkClientWin, MODKEY, Button2, togglefloating, {0}}, +    {ClkClientWin, MODKEY, Button3, resizemouse, {0}}, +    {ClkTagBar, 0, Button1, view, {0}}, +    {ClkTagBar, 0, Button3, toggleview, {0}}, +    {ClkTagBar, MODKEY, Button1, tag, {0}}, +    {ClkTagBar, MODKEY, Button3, toggletag, {0}},  }; - @@ -10,6 +10,8 @@ MANPREFIX = ${PREFIX}/share/man  X11INC = /usr/X11R6/include  X11LIB = /usr/X11R6/lib +BDINC = /usr/include/fribidi +  # Xinerama, comment if you don't want it  XINERAMALIBS  = -lXinerama  XINERAMAFLAGS = -DXINERAMA @@ -20,9 +22,11 @@ FREETYPEINC = /usr/include/freetype2  # OpenBSD (uncomment)  #FREETYPEINC = ${X11INC}/freetype2 +BDLIBS = -lfribidi +  # includes and libs -INCS = -I${X11INC} -I${FREETYPEINC} -LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} +INCS = -I${X11INC} -I${FREETYPEINC} -I$(BDINC) +LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} $(BDLIBS)  # flags  CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_POSIX_C_SOURCE=200809L -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS} @@ -208,7 +208,7 @@ drw_clr_create(Drw *drw, Clr *dest, const char *clrname)  /* Wrapper to create color schemes. The caller has to call free(3) on the   * returned color scheme when done using it. */  Clr * -drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount) +drw_scm_create(Drw *drw, char *clrnames[], size_t clrcount)  {  	size_t i;  	Clr *ret; @@ -39,7 +39,7 @@ void drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned in  /* Colorscheme abstraction */  void drw_clr_create(Drw *drw, Clr *dest, const char *clrname); -Clr *drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount); +Clr *drw_scm_create(Drw *drw, char *clrnames[], size_t clrcount);  /* Cursor abstraction */  Cur *drw_cur_create(Drw *drw, int shape); diff --git a/dwm-anybar-polybar-tray-fix-20200810-bb2e722.diff b/dwm-anybar-polybar-tray-fix-20200810-bb2e722.diff new file mode 100644 index 0000000..065ee1e --- /dev/null +++ b/dwm-anybar-polybar-tray-fix-20200810-bb2e722.diff @@ -0,0 +1,430 @@ +From 9b5719969ce85c3ecc0238d49c0255c5c2cc79f0 Mon Sep 17 00:00:00 2001 +From: mihirlad55 <mihirlad55@gmail.com> +Date: Mon, 10 Aug 2020 01:39:28 +0000 +Subject: [PATCH] Add support for managing external status bars + +This patch allows dwm to manage other status bars such as +polybar/lemonbar without them needing to set override-redirect. For +all intents and purposes, DWM treats this bar as if it were its own +and as a result helps the status bar and DWM live in harmony. + +This has a few advantages +* The bar does not block fullscreen windows +* DWM makes room for the status bar, so windows do not overlap the bar +* The bar can be hidden/killed and DWM will not keep an unsightly gap +  where the bar was +* DWM receives EnterNotify events when your cursor enters the bar + +To use another status bar, set usealtbar to 1 in your config.h and set +altbarclass to the class name (can be found using xprop) to the class +name of your status bar. Also make sure that if your status bar will +be displayed on top, topbar is set to 1 in your config, and if it will +be displayed on bottom, topbar is set to 0. This patch does not +support bars that are not docked at the top or at the bottom of your +monitor. + +This verison of the patch fixes handling of polybar's tray. + +The patch is developed at https://github.com/mihirlad55/dwm-anybar +--- + config.def.h |   4 ++ + dwm.c        | 192 +++++++++++++++++++++++++++++++++++++++++++++++---- + 2 files changed, 181 insertions(+), 15 deletions(-) + +diff --git a/dwm.c b/dwm.c +index 9fd0286..c1d8ce0 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -47,8 +47,8 @@ + /* macros */ + #define BUTTONMASK              (ButtonPressMask|ButtonReleaseMask) + #define CLEANMASK(mask)         (mask & ~(numlockmask|LockMask) & (ShiftMask|ControlMask|Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask)) +-#define INTERSECT(x,y,w,h,m)    (MAX(0, MIN((x)+(w),(m)->wx+(m)->ww) - MAX((x),(m)->wx)) \ +-                               * MAX(0, MIN((y)+(h),(m)->wy+(m)->wh) - MAX((y),(m)->wy))) ++#define INTERSECT(x,y,w,h,m)    (MAX(0, MIN((x)+(w),(m)->mx+(m)->mw) - MAX((x),(m)->mx)) \ ++                               * MAX(0, MIN((y)+(h),(m)->my+(m)->mh) - MAX((y),(m)->my))) + #define ISVISIBLE(C)            ((C->tags & C->mon->tagset[C->mon->seltags])) + #define LENGTH(X)               (sizeof X / sizeof X[0]) + #define MOUSEMASK               (BUTTONMASK|PointerMotionMask) +@@ -116,7 +116,8 @@ struct Monitor { + 	float mfact; + 	int nmaster; + 	int num; +-	int by;               /* bar geometry */ ++	int by, bh;           /* bar geometry */ ++	int tx, tw;           /* bar tray geometry */ + 	int mx, my, mw, mh;   /* screen size */ + 	int wx, wy, ww, wh;   /* window area  */ + 	unsigned int seltags; +@@ -129,6 +130,7 @@ struct Monitor { + 	Client *stack; + 	Monitor *next; + 	Window barwin; ++	Window traywin; + 	const Layout *lt[2]; + }; +  +@@ -179,6 +181,8 @@ static void incnmaster(const Arg *arg); + static void keypress(XEvent *e); + static void killclient(const Arg *arg); + static void manage(Window w, XWindowAttributes *wa); ++static void managealtbar(Window win, XWindowAttributes *wa); ++static void managetray(Window win, XWindowAttributes *wa); + static void mappingnotify(XEvent *e); + static void maprequest(XEvent *e); + static void monocle(Monitor *m); +@@ -195,6 +199,7 @@ static void resizemouse(const Arg *arg); + static void restack(Monitor *m); + static void run(void); + static void scan(void); ++static void scantray(void); + static int sendevent(Client *c, Atom proto); + static void sendmon(Client *c, Monitor *m); + static void setclientstate(Client *c, long state); +@@ -207,6 +212,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 void spawnbar(); + static void tag(const Arg *arg); + static void tagmon(const Arg *arg); + static void tile(Monitor *); +@@ -216,6 +222,8 @@ static void toggletag(const Arg *arg); + static void toggleview(const Arg *arg); + static void unfocus(Client *c, int setfocus); + static void unmanage(Client *c, int destroyed); ++static void unmanagealtbar(Window w); ++static void unmanagetray(Window w); + static void unmapnotify(XEvent *e); + static void updatebarpos(Monitor *m); + static void updatebars(void); +@@ -230,6 +238,7 @@ static void updatewmhints(Client *c); + static void view(const Arg *arg); + static Client *wintoclient(Window w); + static Monitor *wintomon(Window w); ++static int wmclasscontains(Window win, const char *class, const char *name); + static int xerror(Display *dpy, XErrorEvent *ee); + static int xerrordummy(Display *dpy, XErrorEvent *ee); + static int xerrorstart(Display *dpy, XErrorEvent *ee); +@@ -505,8 +514,10 @@ cleanupmon(Monitor *mon) + 		for (m = mons; m && m->next != mon; m = m->next); + 		m->next = mon->next; + 	} +-	XUnmapWindow(dpy, mon->barwin); +-	XDestroyWindow(dpy, mon->barwin); ++	if (!usealtbar) { ++		XUnmapWindow(dpy, mon->barwin); ++		XDestroyWindow(dpy, mon->barwin); ++	} + 	free(mon); + } +  +@@ -568,7 +579,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); ++				XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, m->bh); + 			} + 			focus(NULL); + 			arrange(NULL); +@@ -639,6 +650,7 @@ createmon(void) + 	m->nmaster = nmaster; + 	m->showbar = showbar; + 	m->topbar = topbar; ++	m->bh = bh; + 	m->lt[0] = &layouts[0]; + 	m->lt[1] = &layouts[1 % LENGTH(layouts)]; + 	strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol); +@@ -649,10 +661,15 @@ void + destroynotify(XEvent *e) + { + 	Client *c; ++	Monitor *m; + 	XDestroyWindowEvent *ev = &e->xdestroywindow; +  + 	if ((c = wintoclient(ev->window))) + 		unmanage(c, 1); ++	else if ((m = wintomon(ev->window)) && m->barwin == ev->window) ++		unmanagealtbar(ev->window); ++	else if (m->traywin == ev->window) ++		unmanagetray(ev->window); + } +  + void +@@ -696,6 +713,9 @@ dirtomon(int dir) + void + drawbar(Monitor *m) + { ++	if (usealtbar) ++		return; ++ + 	int x, w, tw = 0; + 	int boxs = drw->fonts->h / 9; + 	int boxw = drw->fonts->h / 6 + 2; +@@ -1077,6 +1097,45 @@ manage(Window w, XWindowAttributes *wa) + 	focus(NULL); + } +  ++void ++managealtbar(Window win, XWindowAttributes *wa) ++{ ++	Monitor *m; ++	if (!(m = recttomon(wa->x, wa->y, wa->width, wa->height))) ++		return; ++ ++	m->barwin = win; ++	m->by = wa->y; ++	bh = m->bh = wa->height; ++	updatebarpos(m); ++	arrange(m); ++	XSelectInput(dpy, win, EnterWindowMask|FocusChangeMask|PropertyChangeMask|StructureNotifyMask); ++	XMoveResizeWindow(dpy, win, wa->x, wa->y, wa->width, wa->height); ++	XMapWindow(dpy, win); ++	XChangeProperty(dpy, root, netatom[NetClientList], XA_WINDOW, 32, PropModeAppend, ++		(unsigned char *) &win, 1); ++} ++ ++void ++managetray(Window win, XWindowAttributes *wa) ++{ ++	Monitor *m; ++	if (!(m = recttomon(wa->x, wa->y, wa->width, wa->height))) ++		return; ++ ++	m->traywin = win; ++	m->tx = wa->x; ++	m->tw = wa->width; ++	updatebarpos(m); ++	arrange(m); ++	XSelectInput(dpy, win, EnterWindowMask|FocusChangeMask|PropertyChangeMask|StructureNotifyMask); ++	XMoveResizeWindow(dpy, win, wa->x, wa->y, wa->width, wa->height); ++	XMapWindow(dpy, win); ++	XChangeProperty(dpy, root, netatom[NetClientList], XA_WINDOW, 32, PropModeAppend, ++			(unsigned char *) &win, 1); ++} ++ ++ + void + mappingnotify(XEvent *e) + { +@@ -1097,7 +1156,9 @@ maprequest(XEvent *e) + 		return; + 	if (wa.override_redirect) + 		return; +-	if (!wintoclient(ev->window)) ++	if (wmclasscontains(ev->window, altbarclass, "")) ++		managealtbar(ev->window, &wa); ++	else if (!wintoclient(ev->window)) + 		manage(ev->window, &wa); + } +  +@@ -1393,7 +1454,9 @@ scan(void) + 			if (!XGetWindowAttributes(dpy, wins[i], &wa) + 			|| wa.override_redirect || XGetTransientForHint(dpy, wins[i], &d1)) + 				continue; +-			if (wa.map_state == IsViewable || getstate(wins[i]) == IconicState) ++			if (wmclasscontains(wins[i], altbarclass, "")) ++				managealtbar(wins[i], &wa); ++			else if (wa.map_state == IsViewable || getstate(wins[i]) == IconicState) + 				manage(wins[i], &wa); + 		} + 		for (i = 0; i < num; i++) { /* now the transients */ +@@ -1408,6 +1471,29 @@ scan(void) + 	} + } +  ++void ++scantray(void) ++{ ++	unsigned int num; ++	Window d1, d2, *wins = NULL; ++	XWindowAttributes wa; ++ ++	if (XQueryTree(dpy, root, &d1, &d2, &wins, &num)) { ++		for (unsigned int i = 0; i < num; i++) { ++			if (wmclasscontains(wins[i], altbarclass, alttrayname)) { ++				if (!XGetWindowAttributes(dpy, wins[i], &wa)) ++					break; ++				managetray(wins[i], &wa); ++			} ++		} ++	} ++ ++	if (wins) ++		XFree(wins); ++} ++ ++ ++ + void + sendmon(Client *c, Monitor *m) + { +@@ -1546,7 +1632,7 @@ setup(void) + 	if (!drw_fontset_create(drw, fonts, LENGTH(fonts))) + 		die("no fonts could be loaded."); + 	lrpad = drw->fonts->h; +-	bh = drw->fonts->h + 2; ++	bh = usealtbar ? 0 : drw->fonts->h + 2; + 	updategeom(); + 	/* init atoms */ + 	utf8string = XInternAtom(dpy, "UTF8_STRING", False); +@@ -1595,6 +1681,7 @@ setup(void) + 	XSelectInput(dpy, root, wa.event_mask); + 	grabkeys(); + 	focus(NULL); ++	spawnbar(); + } +  +  +@@ -1653,6 +1740,13 @@ spawn(const Arg *arg) + 	} + } +  ++void ++spawnbar() ++{ ++	if (*altbarcmd) ++		system(altbarcmd); ++} ++ + void + tag(const Arg *arg) + { +@@ -1702,9 +1796,18 @@ tile(Monitor *m) + void + togglebar(const Arg *arg) + { ++	/** ++     * Polybar tray does not raise maprequest event. It must be manually scanned ++	 * for. Scanning it too early while the tray is being populated would give ++	 * wrong dimensions. ++     */ ++	if (!selmon->traywin) ++		scantray(); ++ + 	selmon->showbar = !selmon->showbar; + 	updatebarpos(selmon); +-	XMoveResizeWindow(dpy, selmon->barwin, selmon->wx, selmon->by, selmon->ww, bh); ++	XMoveResizeWindow(dpy, selmon->barwin, selmon->wx, selmon->by, selmon->ww, selmon->bh); ++	XMoveResizeWindow(dpy, selmon->traywin, selmon->tx, selmon->by, selmon->tw, selmon->bh); + 	arrange(selmon); + } +  +@@ -1787,10 +1890,41 @@ unmanage(Client *c, int destroyed) + 	arrange(m); + } +  ++void ++unmanagealtbar(Window w) ++{ ++    Monitor *m = wintomon(w); ++ ++    if (!m) ++        return; ++ ++    m->barwin = 0; ++    m->by = 0; ++    m->bh = 0; ++    updatebarpos(m); ++    arrange(m); ++} ++ ++void ++unmanagetray(Window w) ++{ ++	Monitor *m = wintomon(w); ++ ++	if (!m) ++		return; ++ ++	m->traywin = 0; ++	m->tx = 0; ++	m->tw = 0; ++	updatebarpos(m); ++	arrange(m); ++} ++ + void + unmapnotify(XEvent *e) + { + 	Client *c; ++	Monitor *m; + 	XUnmapEvent *ev = &e->xunmap; +  + 	if ((c = wintoclient(ev->window))) { +@@ -1798,12 +1932,18 @@ unmapnotify(XEvent *e) + 			setclientstate(c, WithdrawnState); + 		else + 			unmanage(c, 0); +-	} ++	} else if ((m = wintomon(ev->window)) && m->barwin == ev->window) ++		unmanagealtbar(ev->window); ++	else if (m->traywin == ev->window) ++		unmanagetray(ev->window); + } +  + void + updatebars(void) + { ++	if (usealtbar) ++		return; ++ + 	Monitor *m; + 	XSetWindowAttributes wa = { + 		.override_redirect = True, +@@ -1829,11 +1969,11 @@ updatebarpos(Monitor *m) + 	m->wy = m->my; + 	m->wh = m->mh; + 	if (m->showbar) { +-		m->wh -= bh; ++		m->wh -= m->bh; + 		m->by = m->topbar ? m->wy : m->wy + m->wh; +-		m->wy = m->topbar ? m->wy + bh : m->wy; ++		m->wy = m->topbar ? m->wy + m->bh : m->wy; + 	} else +-		m->by = -bh; ++		m->by = -m->bh; + } +  + void +@@ -2070,13 +2210,35 @@ wintomon(Window w) + 	if (w == root && getrootptr(&x, &y)) + 		return recttomon(x, y, 1, 1); + 	for (m = mons; m; m = m->next) +-		if (w == m->barwin) ++		if (w == m->barwin || w == m->traywin) + 			return m; + 	if ((c = wintoclient(w))) + 		return c->mon; + 	return selmon; + } +  ++int ++wmclasscontains(Window win, const char *class, const char *name) ++{ ++	XClassHint ch = { NULL, NULL }; ++	int res = 1; ++ ++	if (XGetClassHint(dpy, win, &ch)) { ++		if (ch.res_name && strstr(ch.res_name, name) == NULL) ++			res = 0; ++		if (ch.res_class && strstr(ch.res_class, class) == NULL) ++			res = 0; ++	} else ++		res = 0; ++ ++	if (ch.res_class) ++		XFree(ch.res_class); ++	if (ch.res_name) ++		XFree(ch.res_name); ++ ++	return res; ++} ++ + /* There's no way to check accesses to destroyed windows, thus those cases are +  * ignored (especially on UnmapNotify's). Other types of errors call Xlibs +  * default error handler, which may call exit. */ +--  +2.28.0 + diff --git a/dwm-bidi-20220309-0386419.diff b/dwm-bidi-20220309-0386419.diff new file mode 100644 index 0000000..1d9be02 --- /dev/null +++ b/dwm-bidi-20220309-0386419.diff @@ -0,0 +1,132 @@ +From 0386419cfb5311d4a7516ece8f3f8fe923c43098 Mon Sep 17 00:00:00 2001 +From: MahdiMirzade <me@mahdym.ir> +Date: Wed, 9 Mar 2022 17:44:42 +0330 +Subject: [PATCH] [PATCH] Added support for RTL languages (Farsi, Arabic and + Hebrew using the FriBiDi library) - 9th Mar 2022 Fix + +--- + config.mk |  8 ++++++-- + dwm.c     | 40 +++++++++++++++++++++++++++++++++------- + 2 files changed, 39 insertions(+), 9 deletions(-) + +diff --git a/config.mk b/config.mk +index b6eb7e0..5b60a24 100644 +--- a/config.mk ++++ b/config.mk +@@ -10,6 +10,8 @@ MANPREFIX = ${PREFIX}/share/man + X11INC = /usr/X11R6/include + X11LIB = /usr/X11R6/lib +  ++BDINC = /usr/include/fribidi ++ + # Xinerama, comment if you don't want it + XINERAMALIBS  = -lXinerama + XINERAMAFLAGS = -DXINERAMA +@@ -20,9 +22,11 @@ FREETYPEINC = /usr/include/freetype2 + # OpenBSD (uncomment) + #FREETYPEINC = ${X11INC}/freetype2 +  ++BDLIBS = -lfribidi ++ + # includes and libs +-INCS = -I${X11INC} -I${FREETYPEINC} +-LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} ++INCS = -I${X11INC} -I${FREETYPEINC} -I$(BDINC) ++LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} $(BDLIBS) +  + # flags + CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_POSIX_C_SOURCE=200809L -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS} +diff --git a/dwm.c b/dwm.c +index a96f33c..4f11fa0 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -40,6 +40,7 @@ + #include <X11/extensions/Xinerama.h> + #endif /* XINERAMA */ + #include <X11/Xft/Xft.h> ++#include <fribidi.h> +  + #include "drw.h" + #include "util.h" +@@ -238,6 +239,7 @@ static void zoom(const Arg *arg); + /* variables */ + static const char broken[] = "broken"; + 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 */ +@@ -276,6 +278,26 @@ static Window root, wmcheckwin; + struct NumTags { char limitexceeded[LENGTH(tags) > 31 ? -1 : 1]; }; +  + /* function implementations */ ++static void ++apply_fribidi(char *str) ++{ ++        FriBidiStrIndex len = strlen(str); ++        FriBidiChar logical[BUFSIZ]; ++        FriBidiChar visual[BUFSIZ]; ++        FriBidiParType base = FRIBIDI_PAR_ON; ++        FriBidiCharSet charset; ++        fribidi_boolean result; ++     ++        fribidi_text[0] = 0; ++        if (len>0) ++        { ++                charset = fribidi_parse_charset("UTF-8"); ++                len = fribidi_charset_to_unicode(charset, str, len, logical); ++                result = fribidi_log2vis(logical, len, &base, visual, NULL, NULL, NULL); ++                len = fribidi_unicode_to_charset(charset, visual, len, fribidi_text); ++        } ++} ++ + void + applyrules(Client *c) + { +@@ -708,8 +730,9 @@ drawbar(Monitor *m) + 	/* draw status first so it can be overdrawn by tags later */ + 	if (m == selmon) { /* status is only drawn on selected monitor */ + 		drw_setscheme(drw, scheme[SchemeNorm]); +-		tw = TEXTW(stext) - lrpad + 2; /* 2px right padding */ +-		drw_text(drw, m->ww - tw, 0, tw, bh, 0, stext, 0); ++                apply_fribidi(stext); ++		tw = TEXTW(fribidi_text) - lrpad + 2; /* 2px right padding */ ++		drw_text(drw, m->ww - tw, 0, tw, bh, 0, fribidi_text, 0); + 	} +  + 	for (c = m->clients; c; c = c->next) { +@@ -719,23 +742,26 @@ drawbar(Monitor *m) + 	} + 	x = 0; + 	for (i = 0; i < LENGTH(tags); i++) { +-		w = TEXTW(tags[i]); ++                apply_fribidi(tags[i]); ++		w = TEXTW(fribidi_text); + 		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); ++		drw_text(drw, x, 0, w, bh, lrpad / 2, fribidi_text, urg & 1 << i); + 		if (occ & 1 << i) + 			drw_rect(drw, x + boxs, boxs, boxw, boxw, + 				m == selmon && selmon->sel && selmon->sel->tags & 1 << i, + 				urg & 1 << i); + 		x += w; + 	} +-	w = blw = TEXTW(m->ltsymbol); ++        apply_fribidi(m->ltsymbol); ++	w = blw = TEXTW(fribidi_text); + 	drw_setscheme(drw, scheme[SchemeNorm]); +-	x = drw_text(drw, x, 0, w, bh, lrpad / 2, m->ltsymbol, 0); ++	x = drw_text(drw, x, 0, w, bh, lrpad / 2, fribidi_text, 0); +  + 	if ((w = m->ww - tw - 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); ++                        apply_fribidi(m->sel->name); ++			drw_text(drw, x, 0, w, bh, lrpad / 2, fribidi_text, 0); + 			if (m->sel->isfloating) + 				drw_rect(drw, x + boxs, boxs, boxw, boxw, m->sel->isfixed, 0); + 		} else { +--  +2.35.1 + diff --git a/dwm-xresources-20210827-138b405.diff b/dwm-xresources-20210827-138b405.diff new file mode 100644 index 0000000..29852a9 --- /dev/null +++ b/dwm-xresources-20210827-138b405.diff @@ -0,0 +1,240 @@ +From f30583c6e2ab5e7de6ef4ebf156076ac0f6e69fc Mon Sep 17 00:00:00 2001 +From: Jack Bird <jack.bird@durham.ac.uk> +Date: Fri, 27 Aug 2021 00:53:14 +0100 +Subject: [PATCH] xresources updated for 138b405 + +--- + config.def.h | 61 ++++++++++++++++++++++++++++++-------------- + drw.c        |  2 +- + drw.h        |  2 +- + dwm.c        | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++++ + 4 files changed, 116 insertions(+), 21 deletions(-) + +diff --git a/config.def.h b/config.def.h +index a2ac963..87ac198 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -1,21 +1,23 @@ + /* See LICENSE file for copyright and license details. */ +  + /* appearance */ +-static const unsigned int borderpx  = 1;        /* border pixel of windows */ +-static const unsigned int snap      = 32;       /* snap pixel */ +-static const int showbar            = 1;        /* 0 means no bar */ +-static const int topbar             = 1;        /* 0 means bottom bar */ +-static const char *fonts[]          = { "monospace:size=10" }; +-static const char dmenufont[]       = "monospace:size=10"; +-static const char col_gray1[]       = "#222222"; +-static const char col_gray2[]       = "#444444"; +-static const char col_gray3[]       = "#bbbbbb"; +-static const char col_gray4[]       = "#eeeeee"; +-static const char col_cyan[]        = "#005577"; +-static const char *colors[][3]      = { +-	/*               fg         bg         border   */ +-	[SchemeNorm] = { col_gray3, col_gray1, col_gray2 }, +-	[SchemeSel]  = { col_gray4, col_cyan,  col_cyan  }, ++static unsigned int borderpx  = 1;        /* border pixel of windows */ ++static unsigned int snap      = 32;       /* snap pixel */ ++static int showbar            = 1;        /* 0 means no bar */ ++static int topbar             = 1;        /* 0 means bottom bar */ ++static char font[]            = "monospace:size=10"; ++static char dmenufont[]       = "monospace:size=10"; ++static const char *fonts[]          = { font }; ++static char normbgcolor[]           = "#222222"; ++static char normbordercolor[]       = "#444444"; ++static char normfgcolor[]           = "#bbbbbb"; ++static char selfgcolor[]            = "#eeeeee"; ++static char selbordercolor[]        = "#005577"; ++static char selbgcolor[]            = "#005577"; ++static char *colors[][3] = { ++       /*               fg           bg           border   */ ++       [SchemeNorm] = { normfgcolor, normbgcolor, normbordercolor }, ++       [SchemeSel]  = { selfgcolor,  selbgcolor,  selbordercolor  }, + }; +  + /* tagging */ +@@ -32,9 +34,9 @@ static const Rule rules[] = { + }; +  + /* layout(s) */ +-static const float mfact     = 0.55; /* factor of master area size [0.05..0.95] */ +-static const int nmaster     = 1;    /* number of clients in master area */ +-static const int resizehints = 1;    /* 1 means respect size hints in tiled resizals */ ++static float mfact     = 0.55; /* factor of master area size [0.05..0.95] */ ++static int nmaster     = 1;    /* number of clients in master area */ ++static int resizehints = 1;    /* 1 means respect size hints in tiled resizals */ + static const int lockfullscreen = 1; /* 1 will force focus on the fullscreen window */ +  + static const Layout layouts[] = { +@@ -57,9 +59,30 @@ static const Layout layouts[] = { +  + /* commands */ + static char dmenumon[2] = "0"; /* component of dmenucmd, manipulated in spawn() */ +-static const char *dmenucmd[] = { "dmenu_run", "-m", dmenumon, "-fn", dmenufont, "-nb", col_gray1, "-nf", col_gray3, "-sb", col_cyan, "-sf", col_gray4, NULL }; ++static const char *dmenucmd[] = { "dmenu_run", "-m", dmenumon, "-fn", dmenufont, "-nb", normbgcolor, "-nf", normfgcolor, "-sb", selbordercolor, "-sf", selfgcolor, NULL }; + static const char *termcmd[]  = { "st", NULL }; +  ++/* ++ * Xresources preferences to load at startup ++ */ ++ResourcePref resources[] = { ++		{ "font",               STRING,  &font }, ++		{ "dmenufont",          STRING,  &dmenufont }, ++		{ "normbgcolor",        STRING,  &normbgcolor }, ++		{ "normbordercolor",    STRING,  &normbordercolor }, ++		{ "normfgcolor",        STRING,  &normfgcolor }, ++		{ "selbgcolor",         STRING,  &selbgcolor }, ++		{ "selbordercolor",     STRING,  &selbordercolor }, ++		{ "selfgcolor",         STRING,  &selfgcolor }, ++		{ "borderpx",          	INTEGER, &borderpx }, ++		{ "snap",          		INTEGER, &snap }, ++		{ "showbar",          	INTEGER, &showbar }, ++		{ "topbar",          	INTEGER, &topbar }, ++		{ "nmaster",          	INTEGER, &nmaster }, ++		{ "resizehints",       	INTEGER, &resizehints }, ++		{ "mfact",      	 	FLOAT,   &mfact }, ++}; ++ + static Key keys[] = { + 	/* modifier                     key        function        argument */ + 	{ MODKEY,                       XK_p,      spawn,          {.v = dmenucmd } }, +diff --git a/drw.c b/drw.c +index 4cdbcbe..8f1059e 100644 +--- a/drw.c ++++ b/drw.c +@@ -208,7 +208,7 @@ drw_clr_create(Drw *drw, Clr *dest, const char *clrname) + /* Wrapper to create color schemes. The caller has to call free(3) on the +  * returned color scheme when done using it. */ + Clr * +-drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount) ++drw_scm_create(Drw *drw, char *clrnames[], size_t clrcount) + { + 	size_t i; + 	Clr *ret; +diff --git a/drw.h b/drw.h +index 4bcd5ad..42b04ce 100644 +--- a/drw.h ++++ b/drw.h +@@ -39,7 +39,7 @@ void drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned in +  + /* Colorscheme abstraction */ + void drw_clr_create(Drw *drw, Clr *dest, const char *clrname); +-Clr *drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount); ++Clr *drw_scm_create(Drw *drw, char *clrnames[], size_t clrcount); +  + /* Cursor abstraction */ + Cur *drw_cur_create(Drw *drw, int shape); +diff --git a/dwm.c b/dwm.c +index 5e4d494..2214b19 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -36,6 +36,7 @@ + #include <X11/Xlib.h> + #include <X11/Xproto.h> + #include <X11/Xutil.h> ++#include <X11/Xresource.h> + #ifdef XINERAMA + #include <X11/extensions/Xinerama.h> + #endif /* XINERAMA */ +@@ -141,6 +142,19 @@ typedef struct { + 	int monitor; + } Rule; +  ++/* 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 void applyrules(Client *c); + static int applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact); +@@ -234,6 +248,8 @@ static int xerror(Display *dpy, XErrorEvent *ee); + static int xerrordummy(Display *dpy, XErrorEvent *ee); + static int xerrorstart(Display *dpy, XErrorEvent *ee); + static void zoom(const Arg *arg); ++static void load_xresources(void); ++static void resource_load(XrmDatabase db, char *name, enum resource_type rtype, void *dst); +  + /* variables */ + static const char broken[] = "broken"; +@@ -2127,6 +2143,60 @@ zoom(const Arg *arg) + 	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 ++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[]) + { +@@ -2139,6 +2209,8 @@ main(int argc, char *argv[]) + 	if (!(dpy = XOpenDisplay(NULL))) + 		die("dwm: cannot open display"); + 	checkotherwm(); ++	XrmInitialize(); ++	load_xresources(); + 	setup(); + #ifdef __OpenBSD__ + 	if (pledge("stdio rpath proc exec", NULL) == -1) +--  +2.33.0 + @@ -36,10 +36,12 @@  #include <X11/Xlib.h>  #include <X11/Xproto.h>  #include <X11/Xutil.h> +#include <X11/Xresource.h>  #ifdef XINERAMA  #include <X11/extensions/Xinerama.h>  #endif /* XINERAMA */  #include <X11/Xft/Xft.h> +#include <fribidi.h>  #include "drw.h"  #include "util.h" @@ -47,8 +49,8 @@  /* macros */  #define BUTTONMASK              (ButtonPressMask|ButtonReleaseMask)  #define CLEANMASK(mask)         (mask & ~(numlockmask|LockMask) & (ShiftMask|ControlMask|Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask)) -#define INTERSECT(x,y,w,h,m)    (MAX(0, MIN((x)+(w),(m)->wx+(m)->ww) - MAX((x),(m)->wx)) \ -                               * MAX(0, MIN((y)+(h),(m)->wy+(m)->wh) - MAX((y),(m)->wy))) +#define INTERSECT(x,y,w,h,m)    (MAX(0, MIN((x)+(w),(m)->mx+(m)->mw) - MAX((x),(m)->mx)) \ +                               * MAX(0, MIN((y)+(h),(m)->my+(m)->mh) - MAX((y),(m)->my)))  #define ISVISIBLE(C)            ((C->tags & C->mon->tagset[C->mon->seltags]))  #define LENGTH(X)               (sizeof X / sizeof X[0])  #define MOUSEMASK               (BUTTONMASK|PointerMotionMask) @@ -116,7 +118,8 @@ struct Monitor {  	float mfact;  	int nmaster;  	int num; -	int by;               /* bar geometry */ +	int by, bh;           /* bar geometry */ +	int tx, tw;           /* bar tray geometry */  	int mx, my, mw, mh;   /* screen size */  	int wx, wy, ww, wh;   /* window area  */  	unsigned int seltags; @@ -129,6 +132,7 @@ struct Monitor {  	Client *stack;  	Monitor *next;  	Window barwin; +	Window traywin;  	const Layout *lt[2];  }; @@ -141,6 +145,19 @@ typedef struct {  	int monitor;  } Rule; +/* 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 void applyrules(Client *c);  static int applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact); @@ -179,6 +196,8 @@ static void incnmaster(const Arg *arg);  static void keypress(XEvent *e);  static void killclient(const Arg *arg);  static void manage(Window w, XWindowAttributes *wa); +static void managealtbar(Window win, XWindowAttributes *wa); +static void managetray(Window win, XWindowAttributes *wa);  static void mappingnotify(XEvent *e);  static void maprequest(XEvent *e);  static void monocle(Monitor *m); @@ -195,6 +214,7 @@ static void resizemouse(const Arg *arg);  static void restack(Monitor *m);  static void run(void);  static void scan(void); +static void scantray(void);  static int sendevent(Client *c, Atom proto);  static void sendmon(Client *c, Monitor *m);  static void setclientstate(Client *c, long state); @@ -207,6 +227,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 void spawnbar();  static void tag(const Arg *arg);  static void tagmon(const Arg *arg);  static void tile(Monitor *); @@ -216,6 +237,8 @@ static void toggletag(const Arg *arg);  static void toggleview(const Arg *arg);  static void unfocus(Client *c, int setfocus);  static void unmanage(Client *c, int destroyed); +static void unmanagealtbar(Window w); +static void unmanagetray(Window w);  static void unmapnotify(XEvent *e);  static void updatebarpos(Monitor *m);  static void updatebars(void); @@ -230,14 +253,18 @@ static void updatewmhints(Client *c);  static void view(const Arg *arg);  static Client *wintoclient(Window w);  static Monitor *wintomon(Window w); +static int wmclasscontains(Window win, const char *class, const char *name);  static int xerror(Display *dpy, XErrorEvent *ee);  static int xerrordummy(Display *dpy, XErrorEvent *ee);  static int xerrorstart(Display *dpy, XErrorEvent *ee);  static void zoom(const Arg *arg); +static void load_xresources(void); +static void resource_load(XrmDatabase db, char *name, enum resource_type rtype, void *dst);  /* variables */  static const char broken[] = "broken";  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 */ @@ -276,6 +303,26 @@ static Window root, wmcheckwin;  struct NumTags { char limitexceeded[LENGTH(tags) > 31 ? -1 : 1]; };  /* function implementations */ +static void +apply_fribidi(char const * str) +{ +        FriBidiStrIndex len = strlen(str); +        FriBidiChar logical[BUFSIZ]; +        FriBidiChar visual[BUFSIZ]; +        FriBidiParType base = FRIBIDI_PAR_ON; +        FriBidiCharSet charset; +        fribidi_boolean result; + +        fribidi_text[0] = 0; +        if (len>0) +        { +                charset = fribidi_parse_charset("UTF-8"); +                len = fribidi_charset_to_unicode(charset, str, len, logical); +                result = fribidi_log2vis(logical, len, &base, visual, NULL, NULL, NULL); +                len = fribidi_unicode_to_charset(charset, visual, len, fribidi_text); +        } +} +  void  applyrules(Client *c)  { @@ -505,8 +552,10 @@ cleanupmon(Monitor *mon)  		for (m = mons; m && m->next != mon; m = m->next);  		m->next = mon->next;  	} -	XUnmapWindow(dpy, mon->barwin); -	XDestroyWindow(dpy, mon->barwin); +	if (!usealtbar) { +		XUnmapWindow(dpy, mon->barwin); +		XDestroyWindow(dpy, mon->barwin); +	}  	free(mon);  } @@ -568,7 +617,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); +				XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, m->bh);  			}  			focus(NULL);  			arrange(NULL); @@ -639,6 +688,7 @@ createmon(void)  	m->nmaster = nmaster;  	m->showbar = showbar;  	m->topbar = topbar; +	m->bh = bh;  	m->lt[0] = &layouts[0];  	m->lt[1] = &layouts[1 % LENGTH(layouts)];  	strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol); @@ -649,10 +699,15 @@ void  destroynotify(XEvent *e)  {  	Client *c; +	Monitor *m;  	XDestroyWindowEvent *ev = &e->xdestroywindow;  	if ((c = wintoclient(ev->window)))  		unmanage(c, 1); +	else if ((m = wintomon(ev->window)) && m->barwin == ev->window) +		unmanagealtbar(ev->window); +	else if (m->traywin == ev->window) +		unmanagetray(ev->window);  }  void @@ -696,6 +751,9 @@ dirtomon(int dir)  void  drawbar(Monitor *m)  { +	if (usealtbar) +		return; +  	int x, w, tw = 0;  	int boxs = drw->fonts->h / 9;  	int boxw = drw->fonts->h / 6 + 2; @@ -708,8 +766,9 @@ drawbar(Monitor *m)  	/* draw status first so it can be overdrawn by tags later */  	if (m == selmon) { /* status is only drawn on selected monitor */  		drw_setscheme(drw, scheme[SchemeNorm]); -		tw = TEXTW(stext) - lrpad + 2; /* 2px right padding */ -		drw_text(drw, m->ww - tw, 0, tw, bh, 0, stext, 0); +                apply_fribidi(stext); +		tw = TEXTW(fribidi_text) - lrpad + 2; /* 2px right padding */ +		drw_text(drw, m->ww - tw, 0, tw, bh, 0, fribidi_text, 0);  	}  	for (c = m->clients; c; c = c->next) { @@ -719,23 +778,26 @@ drawbar(Monitor *m)  	}  	x = 0;  	for (i = 0; i < LENGTH(tags); i++) { -		w = TEXTW(tags[i]); +                apply_fribidi(tags[i]); +		w = TEXTW(fribidi_text);  		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); +		drw_text(drw, x, 0, w, bh, lrpad / 2, fribidi_text, urg & 1 << i);  		if (occ & 1 << i)  			drw_rect(drw, x + boxs, boxs, boxw, boxw,  				m == selmon && selmon->sel && selmon->sel->tags & 1 << i,  				urg & 1 << i);  		x += w;  	} -	w = blw = TEXTW(m->ltsymbol); +        apply_fribidi(m->ltsymbol); +	w = blw = TEXTW(fribidi_text);  	drw_setscheme(drw, scheme[SchemeNorm]); -	x = drw_text(drw, x, 0, w, bh, lrpad / 2, m->ltsymbol, 0); +	x = drw_text(drw, x, 0, w, bh, lrpad / 2, fribidi_text, 0);  	if ((w = m->ww - tw - 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); +                        apply_fribidi(m->sel->name); +			drw_text(drw, x, 0, w, bh, lrpad / 2, fribidi_text, 0);  			if (m->sel->isfloating)  				drw_rect(drw, x + boxs, boxs, boxw, boxw, m->sel->isfixed, 0);  		} else { @@ -1081,6 +1143,45 @@ manage(Window w, XWindowAttributes *wa)  }  void +managealtbar(Window win, XWindowAttributes *wa) +{ +	Monitor *m; +	if (!(m = recttomon(wa->x, wa->y, wa->width, wa->height))) +		return; + +	m->barwin = win; +	m->by = wa->y; +	bh = m->bh = wa->height; +	updatebarpos(m); +	arrange(m); +	XSelectInput(dpy, win, EnterWindowMask|FocusChangeMask|PropertyChangeMask|StructureNotifyMask); +	XMoveResizeWindow(dpy, win, wa->x, wa->y, wa->width, wa->height); +	XMapWindow(dpy, win); +	XChangeProperty(dpy, root, netatom[NetClientList], XA_WINDOW, 32, PropModeAppend, +		(unsigned char *) &win, 1); +} + +void +managetray(Window win, XWindowAttributes *wa) +{ +	Monitor *m; +	if (!(m = recttomon(wa->x, wa->y, wa->width, wa->height))) +		return; + +	m->traywin = win; +	m->tx = wa->x; +	m->tw = wa->width; +	updatebarpos(m); +	arrange(m); +	XSelectInput(dpy, win, EnterWindowMask|FocusChangeMask|PropertyChangeMask|StructureNotifyMask); +	XMoveResizeWindow(dpy, win, wa->x, wa->y, wa->width, wa->height); +	XMapWindow(dpy, win); +	XChangeProperty(dpy, root, netatom[NetClientList], XA_WINDOW, 32, PropModeAppend, +			(unsigned char *) &win, 1); +} + + +void  mappingnotify(XEvent *e)  {  	XMappingEvent *ev = &e->xmapping; @@ -1100,7 +1201,9 @@ maprequest(XEvent *e)  		return;  	if (wa.override_redirect)  		return; -	if (!wintoclient(ev->window)) +	if (wmclasscontains(ev->window, altbarclass, "")) +		managealtbar(ev->window, &wa); +	else if (!wintoclient(ev->window))  		manage(ev->window, &wa);  } @@ -1396,7 +1499,9 @@ scan(void)  			if (!XGetWindowAttributes(dpy, wins[i], &wa)  			|| wa.override_redirect || XGetTransientForHint(dpy, wins[i], &d1))  				continue; -			if (wa.map_state == IsViewable || getstate(wins[i]) == IconicState) +			if (wmclasscontains(wins[i], altbarclass, "")) +				managealtbar(wins[i], &wa); +			else if (wa.map_state == IsViewable || getstate(wins[i]) == IconicState)  				manage(wins[i], &wa);  		}  		for (i = 0; i < num; i++) { /* now the transients */ @@ -1412,6 +1517,29 @@ scan(void)  }  void +scantray(void) +{ +	unsigned int num; +	Window d1, d2, *wins = NULL; +	XWindowAttributes wa; + +	if (XQueryTree(dpy, root, &d1, &d2, &wins, &num)) { +		for (unsigned int i = 0; i < num; i++) { +			if (wmclasscontains(wins[i], altbarclass, alttrayname)) { +				if (!XGetWindowAttributes(dpy, wins[i], &wa)) +					break; +				managetray(wins[i], &wa); +			} +		} +	} + +	if (wins) +		XFree(wins); +} + + + +void  sendmon(Client *c, Monitor *m)  {  	if (c->mon == m) @@ -1549,7 +1677,7 @@ setup(void)  	if (!drw_fontset_create(drw, fonts, LENGTH(fonts)))  		die("no fonts could be loaded.");  	lrpad = drw->fonts->h; -	bh = drw->fonts->h + 2; +	bh = usealtbar ? 0 : drw->fonts->h + 2;  	updategeom();  	/* init atoms */  	utf8string = XInternAtom(dpy, "UTF8_STRING", False); @@ -1598,6 +1726,7 @@ setup(void)  	XSelectInput(dpy, root, wa.event_mask);  	grabkeys();  	focus(NULL); +	spawnbar();  } @@ -1657,6 +1786,13 @@ spawn(const Arg *arg)  }  void +spawnbar() +{ +	if (*altbarcmd) +		system(altbarcmd); +} + +void  tag(const Arg *arg)  {  	if (selmon->sel && arg->ui & TAGMASK) { @@ -1705,9 +1841,18 @@ tile(Monitor *m)  void  togglebar(const Arg *arg)  { +	/** +     * Polybar tray does not raise maprequest event. It must be manually scanned +	 * for. Scanning it too early while the tray is being populated would give +	 * wrong dimensions. +     */ +	if (!selmon->traywin) +		scantray(); +  	selmon->showbar = !selmon->showbar;  	updatebarpos(selmon); -	XMoveResizeWindow(dpy, selmon->barwin, selmon->wx, selmon->by, selmon->ww, bh); +	XMoveResizeWindow(dpy, selmon->barwin, selmon->wx, selmon->by, selmon->ww, selmon->bh); +	XMoveResizeWindow(dpy, selmon->traywin, selmon->tx, selmon->by, selmon->tw, selmon->bh);  	arrange(selmon);  } @@ -1791,9 +1936,40 @@ unmanage(Client *c, int destroyed)  }  void +unmanagealtbar(Window w) +{ +    Monitor *m = wintomon(w); + +    if (!m) +        return; + +    m->barwin = 0; +    m->by = 0; +    m->bh = 0; +    updatebarpos(m); +    arrange(m); +} + +void +unmanagetray(Window w) +{ +	Monitor *m = wintomon(w); + +	if (!m) +		return; + +	m->traywin = 0; +	m->tx = 0; +	m->tw = 0; +	updatebarpos(m); +	arrange(m); +} + +void  unmapnotify(XEvent *e)  {  	Client *c; +	Monitor *m;  	XUnmapEvent *ev = &e->xunmap;  	if ((c = wintoclient(ev->window))) { @@ -1801,12 +1977,18 @@ unmapnotify(XEvent *e)  			setclientstate(c, WithdrawnState);  		else  			unmanage(c, 0); -	} +	} else if ((m = wintomon(ev->window)) && m->barwin == ev->window) +		unmanagealtbar(ev->window); +	else if (m->traywin == ev->window) +		unmanagetray(ev->window);  }  void  updatebars(void)  { +	if (usealtbar) +		return; +  	Monitor *m;  	XSetWindowAttributes wa = {  		.override_redirect = True, @@ -1832,11 +2014,11 @@ updatebarpos(Monitor *m)  	m->wy = m->my;  	m->wh = m->mh;  	if (m->showbar) { -		m->wh -= bh; +		m->wh -= m->bh;  		m->by = m->topbar ? m->wy : m->wy + m->wh; -		m->wy = m->topbar ? m->wy + bh : m->wy; +		m->wy = m->topbar ? m->wy + m->bh : m->wy;  	} else -		m->by = -bh; +		m->by = -m->bh;  }  void @@ -2073,13 +2255,35 @@ wintomon(Window w)  	if (w == root && getrootptr(&x, &y))  		return recttomon(x, y, 1, 1);  	for (m = mons; m; m = m->next) -		if (w == m->barwin) +		if (w == m->barwin || w == m->traywin)  			return m;  	if ((c = wintoclient(w)))  		return c->mon;  	return selmon;  } +int +wmclasscontains(Window win, const char *class, const char *name) +{ +	XClassHint ch = { NULL, NULL }; +	int res = 1; + +	if (XGetClassHint(dpy, win, &ch)) { +		if (ch.res_name && strstr(ch.res_name, name) == NULL) +			res = 0; +		if (ch.res_class && strstr(ch.res_class, class) == NULL) +			res = 0; +	} else +		res = 0; + +	if (ch.res_class) +		XFree(ch.res_class); +	if (ch.res_name) +		XFree(ch.res_name); + +	return res; +} +  /* There's no way to check accesses to destroyed windows, thus those cases are   * ignored (especially on UnmapNotify's). Other types of errors call Xlibs   * default error handler, which may call exit. */ @@ -2130,6 +2334,60 @@ zoom(const Arg *arg)  	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 +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[])  { @@ -2142,6 +2400,8 @@ main(int argc, char *argv[])  	if (!(dpy = XOpenDisplay(NULL)))  		die("dwm: cannot open display");  	checkotherwm(); +	XrmInitialize(); +	load_xresources();  	setup();  #ifdef __OpenBSD__  	if (pledge("stdio rpath proc exec", NULL) == -1) | 
