summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorxAlpharax <42233094+xAlpharax@users.noreply.github.com>2023-08-16 20:21:39 +0300
committerxAlpharax <42233094+xAlpharax@users.noreply.github.com>2023-08-16 20:21:39 +0300
commit812aa788fa06c9a48fb7b5f54d08c99cbb4f709c (patch)
treedf191225e3f3d9e755b06c0546668d244de539d7
parent1dec076282eae69d44e5aa3168ae8ed0e7bfb94d (diff)
Fixed the attachbottom patch and pulled in some new diff files to merge.
Changes to be committed: modified: dwm.c modified: dwm.c.orig modified: dwm.c.rej new file: patches_new/dwm-fullgaps-6.4.diff new file: patches_new/dwm-noborderflicker-20211227-8657affa2a61.diff new file: patches_new/dwm-resizecorners-6.2.diff new file: patches_new/dwm-sticky-6.4.diff new file: patches_new/dwm-tag-preview-6.3.diff new file: patches_new/dwm-toggleborder-6.3.diff new file: patches_new/dwm-winicon-6.3-v2.1.diff
-rw-r--r--dwm.c14
-rw-r--r--dwm.c.orig249
-rw-r--r--dwm.c.rej61
-rw-r--r--patches_new/dwm-fullgaps-6.4.diff94
-rw-r--r--patches_new/dwm-noborderflicker-20211227-8657affa2a61.diff0
-rw-r--r--patches_new/dwm-resizecorners-6.2.diff68
-rw-r--r--patches_new/dwm-sticky-6.4.diff141
-rw-r--r--patches_new/dwm-tag-preview-6.3.diff315
-rw-r--r--patches_new/dwm-toggleborder-6.3.diff53
-rw-r--r--patches_new/dwm-winicon-6.3-v2.1.diff371
10 files changed, 1065 insertions, 301 deletions
diff --git a/dwm.c b/dwm.c
index f4b2644..c5ee1d0 100644
--- a/dwm.c
+++ b/dwm.c
@@ -148,6 +148,7 @@ static int applysizehints(Client *c, int *x, int *y, int *w, int *h, int interac
static void arrange(Monitor *m);
static void arrangemon(Monitor *m);
static void attach(Client *c);
+static void attachbottom(Client *c);
static void attachstack(Client *c);
static void buttonpress(XEvent *e);
static void checkotherwm(void);
@@ -418,6 +419,15 @@ attach(Client *c)
}
void
+attachbottom(Client *c)
+{
+ Client **tc;
+ c->next = NULL;
+ for (tc = &c->mon->clients; *tc; tc = &(*tc)->next);
+ *tc = c;
+}
+
+void
attachstack(Client *c)
{
c->snext = c->mon->stack;
@@ -1084,7 +1094,7 @@ manage(Window w, XWindowAttributes *wa)
c->isfloating = c->oldstate = trans != None || c->isfixed;
if (c->isfloating)
XRaiseWindow(dpy, c->win);
- attach(c);
+ attachbottom(c);
attachstack(c);
XChangeProperty(dpy, root, netatom[NetClientList], XA_WINDOW, 32, PropModeAppend,
(unsigned char *) &(c->win), 1);
@@ -1506,7 +1516,7 @@ sendmon(Client *c, Monitor *m)
detachstack(c);
c->mon = m;
c->tags = m->tagset[m->seltags]; /* assign tags of target monitor */
- attach(c);
+ attachbottom(c);
attachstack(c);
focus(NULL);
arrange(NULL);
diff --git a/dwm.c.orig b/dwm.c.orig
index 4f273b8..f4b2644 100644
--- a/dwm.c.orig
+++ b/dwm.c.orig
@@ -1235,75 +1235,6 @@ nexttag(void)
return seltag;
}
-unsigned int
-nexttag(void)
-{
- unsigned int seltag = selmon->tagset[selmon->seltags];
- unsigned int usedtags = 0;
- Client *c = selmon->clients;
-
- if (!c)
- return seltag;
-
- /* skip vacant tags */
- do {
- usedtags |= c->tags;
- c = c->next;
- } while (c);
-
- do {
- seltag = seltag == (1 << (LENGTH(tags) - 1)) ? 1 : seltag << 1;
- } while (!(seltag & usedtags));
-
- return seltag;
-}
-
-unsigned int
-nexttag(void)
-{
- unsigned int seltag = selmon->tagset[selmon->seltags];
- unsigned int usedtags = 0;
- Client *c = selmon->clients;
-
- if (!c)
- return seltag;
-
- /* skip vacant tags */
- do {
- usedtags |= c->tags;
- c = c->next;
- } while (c);
-
- do {
- seltag = seltag == (1 << (LENGTH(tags) - 1)) ? 1 : seltag << 1;
- } while (!(seltag & usedtags));
-
- return seltag;
-}
-
-unsigned int
-nexttag(void)
-{
- unsigned int seltag = selmon->tagset[selmon->seltags];
- unsigned int usedtags = 0;
- Client *c = selmon->clients;
-
- if (!c)
- return seltag;
-
- /* skip vacant tags */
- do {
- usedtags |= c->tags;
- c = c->next;
- } while (c);
-
- do {
- seltag = seltag == (1 << (LENGTH(tags) - 1)) ? 1 : seltag << 1;
- } while (!(seltag & usedtags));
-
- return seltag;
-}
-
Client *
nexttiled(Client *c)
{
@@ -1342,72 +1273,6 @@ prevtag(void)
return seltag;
}
-unsigned int
-prevtag(void)
-{
- unsigned int seltag = selmon->tagset[selmon->seltags];
- unsigned int usedtags = 0;
- Client *c = selmon->clients;
- if (!c)
- return seltag;
-
- /* skip vacant tags */
- do {
- usedtags |= c->tags;
- c = c->next;
- } while (c);
-
- do {
- seltag = seltag == 1 ? (1 << (LENGTH(tags) - 1)) : seltag >> 1;
- } while (!(seltag & usedtags));
-
- return seltag;
-}
-
-unsigned int
-prevtag(void)
-{
- unsigned int seltag = selmon->tagset[selmon->seltags];
- unsigned int usedtags = 0;
- Client *c = selmon->clients;
- if (!c)
- return seltag;
-
- /* skip vacant tags */
- do {
- usedtags |= c->tags;
- c = c->next;
- } while (c);
-
- do {
- seltag = seltag == 1 ? (1 << (LENGTH(tags) - 1)) : seltag >> 1;
- } while (!(seltag & usedtags));
-
- return seltag;
-}
-
-unsigned int
-prevtag(void)
-{
- unsigned int seltag = selmon->tagset[selmon->seltags];
- unsigned int usedtags = 0;
- Client *c = selmon->clients;
- if (!c)
- return seltag;
-
- /* skip vacant tags */
- do {
- usedtags |= c->tags;
- c = c->next;
- } while (c);
-
- do {
- seltag = seltag == 1 ? (1 << (LENGTH(tags) - 1)) : seltag >> 1;
- } while (!(seltag & usedtags));
-
- return seltag;
-}
-
void
propertynotify(XEvent *e)
{
@@ -1939,96 +1804,6 @@ tagtoprev(const Arg *arg)
}
void
-tagtonext(const Arg *arg)
-{
- unsigned int tmp;
-
- if (selmon->sel == NULL)
- return;
-
- if ((tmp = nexttag()) == selmon->tagset[selmon->seltags])
- return;
-
- tag(&(const Arg){.ui = tmp });
- view(&(const Arg){.ui = tmp });
-}
-
-void
-tagtoprev(const Arg *arg)
-{
- unsigned int tmp;
-
- if (selmon->sel == NULL)
- return;
-
- if ((tmp = prevtag()) == selmon->tagset[selmon->seltags])
- return;
-
- tag(&(const Arg){.ui = tmp });
- view(&(const Arg){.ui = tmp });
-}
-
-void
-tagtonext(const Arg *arg)
-{
- unsigned int tmp;
-
- if (selmon->sel == NULL)
- return;
-
- if ((tmp = nexttag()) == selmon->tagset[selmon->seltags])
- return;
-
- tag(&(const Arg){.ui = tmp });
- view(&(const Arg){.ui = tmp });
-}
-
-void
-tagtoprev(const Arg *arg)
-{
- unsigned int tmp;
-
- if (selmon->sel == NULL)
- return;
-
- if ((tmp = prevtag()) == selmon->tagset[selmon->seltags])
- return;
-
- tag(&(const Arg){.ui = tmp });
- view(&(const Arg){.ui = tmp });
-}
-
-void
-tagtonext(const Arg *arg)
-{
- unsigned int tmp;
-
- if (selmon->sel == NULL)
- return;
-
- if ((tmp = nexttag()) == selmon->tagset[selmon->seltags])
- return;
-
- tag(&(const Arg){.ui = tmp });
- view(&(const Arg){.ui = tmp });
-}
-
-void
-tagtoprev(const Arg *arg)
-{
- unsigned int tmp;
-
- if (selmon->sel == NULL)
- return;
-
- if ((tmp = prevtag()) == selmon->tagset[selmon->seltags])
- return;
-
- tag(&(const Arg){.ui = tmp });
- view(&(const Arg){.ui = tmp });
-}
-
-void
tile(Monitor *m)
{
unsigned int i, n, h, mw, my, ty;
@@ -2425,30 +2200,6 @@ viewprev(const Arg *arg)
view(&(const Arg){.ui = prevtag()});
}
-void
-viewnext(const Arg *arg)
-{
- view(&(const Arg){.ui = nexttag()});
-}
-
-void
-viewprev(const Arg *arg)
-{
- view(&(const Arg){.ui = prevtag()});
-}
-
-void
-viewnext(const Arg *arg)
-{
- view(&(const Arg){.ui = nexttag()});
-}
-
-void
-viewprev(const Arg *arg)
-{
- view(&(const Arg){.ui = prevtag()});
-}
-
Client *
wintoclient(Window w)
{
diff --git a/dwm.c.rej b/dwm.c.rej
index 422e803..67e66a5 100644
--- a/dwm.c.rej
+++ b/dwm.c.rej
@@ -1,50 +1,11 @@
---- dwm.c 2021-10-02 14:22:28.034782413 +0100
-+++ dwm.c 2021-10-02 14:27:54.599845767 +0100
-@@ -183,8 +183,10 @@ static void maprequest(XEvent *e);
- static void monocle(Monitor *m);
- static void motionnotify(XEvent *e);
- static void movemouse(const Arg *arg);
-+static unsigned int nexttag(void);
- static Client *nexttiled(Client *c);
- static void pop(Client *);
-+static unsigned int prevtag(void);
- static void propertynotify(XEvent *e);
- static void quit(const Arg *arg);
- static Monitor *recttomon(int x, int y, int w, int h);
-@@ -208,6 +210,8 @@ static void sigchld(int unused);
- static void spawn(const Arg *arg);
- static void tag(const Arg *arg);
- static void tagmon(const Arg *arg);
-+static void tagtonext(const Arg *arg);
-+static void tagtoprev(const Arg *arg);
- static void tile(Monitor *);
- static void togglebar(const Arg *arg);
- static void togglefloating(const Arg *arg);
-@@ -227,6 +231,8 @@ static void updatetitle(Client *c);
- static void updatewindowtype(Client *c);
- static void updatewmhints(Client *c);
- static void view(const Arg *arg);
-+static void viewnext(const Arg *arg);
-+static void viewprev(const Arg *arg);
- static Client *wintoclient(Window w);
- static Monitor *wintomon(Window w);
- static int xerror(Display *dpy, XErrorEvent *ee);
-@@ -2119,6 +2200,18 @@ view(const Arg *arg)
- arrange(selmon);
- }
-
-+void
-+viewnext(const Arg *arg)
-+{
-+ view(&(const Arg){.ui = nexttag()});
-+}
-+
-+void
-+viewprev(const Arg *arg)
-+{
-+ view(&(const Arg){.ui = prevtag()});
-+}
-+
- Client *
- wintoclient(Window w)
- {
+--- dwm.c 2022-01-07 12:42:18.000000000 +0100
++++ dwm.c 2022-08-17 22:14:41.813809073 +0200
+@@ -1913,7 +1923,7 @@ updategeom(void)
+ m->clients = c->next;
+ detachstack(c);
+ c->mon = mons;
+- attach(c);
++ attachbottom(c);
+ attachstack(c);
+ }
+ if (m == selmon)
diff --git a/patches_new/dwm-fullgaps-6.4.diff b/patches_new/dwm-fullgaps-6.4.diff
new file mode 100644
index 0000000..dc52139
--- /dev/null
+++ b/patches_new/dwm-fullgaps-6.4.diff
@@ -0,0 +1,94 @@
+diff -up a/config.def.h b/config.def.h
+--- 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 */
+@@ -85,6 +86,9 @@ static const 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 -up a/dwm.c b/dwm.c
+--- a/dwm.c 2023-04-30
++++ b/dwm.c 2023-04-30
+@@ -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 *
+ 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);
+@@ -641,6 +643,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);
+@@ -1508,6 +1511,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)
+ {
+ if (!arg || !arg->v || arg->v != selmon->lt[selmon->sellt])
+@@ -1697,18 +1710,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++)
+- 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);
++ 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) - 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;
+ }
+ }
diff --git a/patches_new/dwm-noborderflicker-20211227-8657affa2a61.diff b/patches_new/dwm-noborderflicker-20211227-8657affa2a61.diff
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/patches_new/dwm-noborderflicker-20211227-8657affa2a61.diff
diff --git a/patches_new/dwm-resizecorners-6.2.diff b/patches_new/dwm-resizecorners-6.2.diff
new file mode 100644
index 0000000..016351c
--- /dev/null
+++ b/patches_new/dwm-resizecorners-6.2.diff
@@ -0,0 +1,68 @@
+diff -r -u a/dwm.c b/dwm.c
+--- a/dwm.c 2019-02-02 07:55:28.000000000 -0500
++++ b/dwm.c 2022-01-17 22:38:33.614493243 -0500
+@@ -1291,9 +1291,14 @@
+ resizemouse(const Arg *arg)
+ {
+ int ocx, ocy, nw, nh;
++ int ocx2, ocy2, nx, ny;
+ Client *c;
+ Monitor *m;
+ XEvent ev;
++ int horizcorner, vertcorner;
++ int di;
++ unsigned int dui;
++ Window dummy;
+ Time lasttime = 0;
+
+ if (!(c = selmon->sel))
+@@ -1303,10 +1308,18 @@
+ restack(selmon);
+ ocx = c->x;
+ ocy = c->y;
++ ocx2 = c->x + c->w;
++ ocy2 = c->y + c->h;
+ if (XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync,
+ None, cursor[CurResize]->cursor, CurrentTime) != GrabSuccess)
+ return;
+- XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w + c->bw - 1, c->h + c->bw - 1);
++ if (!XQueryPointer (dpy, c->win, &dummy, &dummy, &di, &di, &nx, &ny, &dui))
++ return;
++ horizcorner = nx < c->w / 2;
++ vertcorner = ny < c->h / 2;
++ XWarpPointer (dpy, None, c->win, 0, 0, 0, 0,
++ horizcorner ? (-c->bw) : (c->w + c->bw -1),
++ vertcorner ? (-c->bw) : (c->h + c->bw -1));
+ do {
+ XMaskEvent(dpy, MOUSEMASK|ExposureMask|SubstructureRedirectMask, &ev);
+ switch(ev.type) {
+@@ -1320,8 +1333,11 @@
+ continue;
+ lasttime = ev.xmotion.time;
+
+- nw = MAX(ev.xmotion.x - ocx - 2 * c->bw + 1, 1);
+- nh = MAX(ev.xmotion.y - ocy - 2 * c->bw + 1, 1);
++ nx = horizcorner ? ev.xmotion.x : c->x;
++ ny = vertcorner ? ev.xmotion.y : c->y;
++ nw = MAX(horizcorner ? (ocx2 - nx) : (ev.xmotion.x - ocx - 2 * c->bw + 1), 1);
++ nh = MAX(vertcorner ? (ocy2 - ny) : (ev.xmotion.y - ocy - 2 * c->bw + 1), 1);
++
+ if (c->mon->wx + nw >= selmon->wx && c->mon->wx + nw <= selmon->wx + selmon->ww
+ && c->mon->wy + nh >= selmon->wy && c->mon->wy + nh <= selmon->wy + selmon->wh)
+ {
+@@ -1330,11 +1346,13 @@
+ togglefloating(NULL);
+ }
+ if (!selmon->lt[selmon->sellt]->arrange || c->isfloating)
+- resize(c, c->x, c->y, nw, nh, 1);
++ resize(c, nx, ny, nw, nh, 1);
+ break;
+ }
+ } while (ev.type != ButtonRelease);
+- XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w + c->bw - 1, c->h + c->bw - 1);
++ XWarpPointer(dpy, None, c->win, 0, 0, 0, 0,
++ horizcorner ? (-c->bw) : (c->w + c->bw - 1),
++ vertcorner ? (-c->bw) : (c->h + c->bw - 1));
+ XUngrabPointer(dpy, CurrentTime);
+ while (XCheckMaskEvent(dpy, EnterWindowMask, &ev));
+ if ((m = recttomon(c->x, c->y, c->w, c->h)) != selmon) {
diff --git a/patches_new/dwm-sticky-6.4.diff b/patches_new/dwm-sticky-6.4.diff
new file mode 100644
index 0000000..2c26343
--- /dev/null
+++ b/patches_new/dwm-sticky-6.4.diff
@@ -0,0 +1,141 @@
+From d47ba0b8aab26ffb2569c0d05df24fdd61b3f4b0 Mon Sep 17 00:00:00 2001
+From: aymey <fabianpaci@gmail.com>
+Date: Mon, 5 Dec 2022 22:57:41 +1100
+Subject: [PATCH] Sticky windows respect EWMH
+
+---
+ dwm.c | 51 ++++++++++++++++++++++++++++++++++++++++++++-------
+ 1 file changed, 44 insertions(+), 7 deletions(-)
+
+diff --git a/dwm.c b/dwm.c
+index 253aba7..a9157bf 100644
+--- a/dwm.c
++++ b/dwm.c
+@@ -49,7 +49,7 @@
+ #define CLEANMASK(mask) (mask & ~(numlockmask|LockMask) & (ShiftMask|ControlMask|Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask))
+ #define INTERSECT(x,y,w,h,m) (MAX(0, MIN((x)+(w),(m)->wx+(m)->ww) - MAX((x),(m)->wx)) \
+ * MAX(0, MIN((y)+(h),(m)->wy+(m)->wh) - MAX((y),(m)->wy)))
+-#define ISVISIBLE(C) ((C->tags & C->mon->tagset[C->mon->seltags]))
++#define ISVISIBLE(C) ((C->tags & C->mon->tagset[C->mon->seltags]) || C->issticky)
+ #define LENGTH(X) (sizeof X / sizeof X[0])
+ #define MOUSEMASK (BUTTONMASK|PointerMotionMask)
+ #define WIDTH(X) ((X)->w + 2 * (X)->bw)
+@@ -61,7 +61,7 @@
+ enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */
+ enum { SchemeNorm, SchemeSel }; /* color schemes */
+ enum { NetSupported, NetWMName, NetWMState, NetWMCheck,
+- NetWMFullscreen, NetActiveWindow, NetWMWindowType,
++ NetWMFullscreen, NetWMSticky, NetActiveWindow, NetWMWindowType,
+ NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH atoms */
+ enum { WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast }; /* default atoms */
+ enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle,
+@@ -92,7 +92,7 @@ struct Client {
+ int basew, baseh, incw, inch, maxw, maxh, minw, minh, hintsvalid;
+ int bw, oldbw;
+ unsigned int tags;
+- int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen;
++ int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen, issticky;
+ Client *next;
+ Client *snext;
+ Monitor *mon;
+@@ -200,6 +200,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 setsticky(Client *c, int sticky);
+ static void setlayout(const Arg *arg);
+ static void setmfact(const Arg *arg);
+ static void setup(void);
+@@ -212,6 +213,7 @@ static void tagmon(const Arg *arg);
+ static void tile(Monitor *m);
+ static void togglebar(const Arg *arg);
+ static void togglefloating(const Arg *arg);
++static void togglesticky(const Arg *arg);
+ static void toggletag(const Arg *arg);
+ static void toggleview(const Arg *arg);
+ static void unfocus(Client *c, int setfocus);
+@@ -526,6 +528,10 @@ clientmessage(XEvent *e)
+ || cme->data.l[2] == netatom[NetWMFullscreen])
+ setfullscreen(c, (cme->data.l[0] == 1 /* _NET_WM_STATE_ADD */
+ || (cme->data.l[0] == 2 /* _NET_WM_STATE_TOGGLE */ && !c->isfullscreen)));
++
++ if (cme->data.l[1] == netatom[NetWMSticky]
++ || cme->data.l[2] == netatom[NetWMSticky])
++ setsticky(c, (cme->data.l[0] == 1 || (cme->data.l[0] == 2 && !c->issticky)));
+ } else if (cme->message_type == netatom[NetActiveWindow]) {
+ if (c != selmon->sel && !c->isurgent)
+ seturgent(c, 1);
+@@ -1498,6 +1504,23 @@ setfullscreen(Client *c, int fullscreen)
+ }
+ }
+
++void
++setsticky(Client *c, int sticky)
++{
++
++ if(sticky && !c->issticky) {
++ XChangeProperty(dpy, c->win, netatom[NetWMState], XA_ATOM, 32,
++ PropModeReplace, (unsigned char *) &netatom[NetWMSticky], 1);
++ c->issticky = 1;
++ } else if(!sticky && c->issticky){
++ XChangeProperty(dpy, c->win, netatom[NetWMState], XA_ATOM, 32,
++ PropModeReplace, (unsigned char *)0, 0);
++ c->issticky = 0;
++ arrange(c->mon);
++ }
++}
++
++
+ void
+ setlayout(const Arg *arg)
+ {
+@@ -1560,6 +1583,7 @@ setup(void)
+ 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[NetWMSticky] = XInternAtom(dpy, "_NET_WM_STATE_STICKY", 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);
+@@ -1719,6 +1743,15 @@ togglefloating(const Arg *arg)
+ arrange(selmon);
+ }
+
++void
++togglesticky(const Arg *arg)
++{
++ if (!selmon->sel)
++ return;
++ setsticky(selmon->sel, !selmon->sel->issticky);
++ arrange(selmon);
++}
++
+ void
+ toggletag(const Arg *arg)
+ {
+@@ -2009,10 +2042,13 @@ updatewindowtype(Client *c)
+ Atom state = getatomprop(c, netatom[NetWMState]);
+ Atom wtype = getatomprop(c, netatom[NetWMWindowType]);
+
+- if (state == netatom[NetWMFullscreen])
+- setfullscreen(c, 1);
+- if (wtype == netatom[NetWMWindowTypeDialog])
+- c->isfloating = 1;
++ if (state == netatom[NetWMFullscreen])
++ setfullscreen(c, 1);
++ if (state == netatom[NetWMSticky]) {
++ setsticky(c, 1);
++ }
++ if (wtype == netatom[NetWMWindowTypeDialog])
++ c->isfloating = 1;
+ }
+
+ void
+@@ -2147,3 +2183,4 @@ main(int argc, char *argv[])
+ XCloseDisplay(dpy);
+ return EXIT_SUCCESS;
+ }
++
+--
+2.38.1
+
diff --git a/patches_new/dwm-tag-preview-6.3.diff b/patches_new/dwm-tag-preview-6.3.diff
new file mode 100644
index 0000000..dbee35d
--- /dev/null
+++ b/patches_new/dwm-tag-preview-6.3.diff
@@ -0,0 +1,315 @@
+From 841ad7d5767f945ee9da6c5afc8cff98ca2f8231 Mon Sep 17 00:00:00 2001
+From: explosion-mental <explosion0mental@gmail.com>
+Date: Thu, 1 Sep 2022 16:21:58 -0500
+Subject: [PATCH] [PATCH] tag previews: free() tagmap and add previewtag func
+
+Allows you to see the contents of an already viewed tag. So a more
+accurate description would be to re-view a tag.
+
+Allows you to see the contents of an already viewed tag. So a more
+accurate description would be to re-view a tag.
+
+Compatibility with the alpha patch (replacing DefaultDepth() and
+DefaultVisual() with depth and visual + window masks) and hide vacants can be
+achieved, I left some lines to uncomment.
+
+added:
+* more compact structure, more probable to patch on top of other patches
+ or easier to patch manually (like not moving the Monitor struct..)
+* create the window preview in updatebars()
+* renamed switchtag() -> takepreview(), makes more sense since it's
+ "taking" the preview (basically a screenshot).
+* option previewbar, whether to show the bar in the preview or not.
+* previewtag which takes a tag (unsigned int from 0 to the last tag) and
+ previews it. This allows to preview tags without using the
+ cursor/mouse (which avoids a recursive previews preview).
+ adding it to the TAGKEYS macro makes more sense so I've added it
+ replacing (keybinding wise, not functionality) toggletag.
+```
+\#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, previewtag, {.ui = TAG } },
+```
+---
+ config.def.h | 4 +-
+ config.mk | 5 +-
+ dwm.c | 139 ++++++++++++++++++++++++++++++++++++++++++++++++++-
+ 3 files changed, 145 insertions(+), 3 deletions(-)
+
+diff --git a/config.def.h b/config.def.h
+index a2ac963..eb70348 100644
+--- a/config.def.h
++++ b/config.def.h
+@@ -3,6 +3,8 @@
+ /* appearance */
+ static const unsigned int borderpx = 1; /* border pixel of windows */
+ static const unsigned int snap = 32; /* snap pixel */
++static const int scalepreview = 4; /* preview scaling (display w and h / scalepreview) */
++static const int previewbar = 1; /* show the bar in the preview window */
+ 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" };
+@@ -50,7 +52,7 @@ static const Layout layouts[] = {
+ { 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} },
++ { MODKEY|ControlMask|ShiftMask, KEY, previewtag, {.ui = TAG } }, \
+
+ /* helper for spawning shell commands in the pre dwm-5.0 fashion */
+ #define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } }
+diff --git a/config.mk b/config.mk
+index b6eb7e0..6f5129e 100644
+--- a/config.mk
++++ b/config.mk
+@@ -20,9 +20,12 @@ FREETYPEINC = /usr/include/freetype2
+ # OpenBSD (uncomment)
+ #FREETYPEINC = ${X11INC}/freetype2
+
++# Imlib2 (tag previews)
++IMLIB2LIBS = -lImlib2
++
+ # includes and libs
+ INCS = -I${X11INC} -I${FREETYPEINC}
+-LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS}
++LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} ${IMLIB2LIBS}
+
+ # 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..0c0ba12 100644
+--- a/dwm.c
++++ b/dwm.c
+@@ -40,6 +40,7 @@
+ #include <X11/extensions/Xinerama.h>
+ #endif /* XINERAMA */
+ #include <X11/Xft/Xft.h>
++#include <Imlib2.h>
+
+ #include "drw.h"
+ #include "util.h"
+@@ -112,6 +113,9 @@ typedef struct {
+ } Layout;
+
+ struct Monitor {
++ int previewshow;
++ Window tagwin;
++ Pixmap *tagmap;
+ char ltsymbol[16];
+ float mfact;
+ int nmaster;
+@@ -235,6 +239,10 @@ static int xerrordummy(Display *dpy, XErrorEvent *ee);
+ static int xerrorstart(Display *dpy, XErrorEvent *ee);
+ static void zoom(const Arg *arg);
+
++static void showtagpreview(unsigned int i);
++static void takepreview(void);
++static void previewtag(const Arg *arg);
++
+ /* variables */
+ static const char broken[] = "broken";
+ static char stext[256];
+@@ -438,6 +446,11 @@ buttonpress(XEvent *e)
+ if (i < LENGTH(tags)) {
+ click = ClkTagBar;
+ arg.ui = 1 << i;
++ /* hide preview if we click the bar */
++ if (selmon->previewshow) {
++ selmon->previewshow = 0;
++ XUnmapWindow(dpy, selmon->tagwin);
++ }
+ } else if (ev->x < x + blw)
+ click = ClkLtSymbol;
+ else if (ev->x > selmon->ww - (int)TEXTW(stext))
+@@ -498,6 +511,7 @@ void
+ cleanupmon(Monitor *mon)
+ {
+ Monitor *m;
++ size_t i;
+
+ if (mon == mons)
+ mons = mons->next;
+@@ -505,8 +519,14 @@ cleanupmon(Monitor *mon)
+ for (m = mons; m && m->next != mon; m = m->next);
+ m->next = mon->next;
+ }
++ for (i = 0; i < LENGTH(tags); i++)
++ if (mon->tagmap[i])
++ XFreePixmap(dpy, mon->tagmap[i]);
++ free(mon->tagmap);
+ XUnmapWindow(dpy, mon->barwin);
+ XDestroyWindow(dpy, mon->barwin);
++ XUnmapWindow(dpy, mon->tagwin);
++ XDestroyWindow(dpy, mon->tagwin);
+ free(mon);
+ }
+
+@@ -641,6 +661,7 @@ createmon(void)
+ m->topbar = topbar;
+ m->lt[0] = &layouts[0];
+ m->lt[1] = &layouts[1 % LENGTH(layouts)];
++ m->tagmap = ecalloc(LENGTH(tags), sizeof(Pixmap));
+ strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol);
+ return m;
+ }
+@@ -1125,6 +1146,36 @@ motionnotify(XEvent *e)
+ static Monitor *mon = NULL;
+ Monitor *m;
+ XMotionEvent *ev = &e->xmotion;
++ unsigned int i, x;
++
++ if (ev->window == selmon->barwin) {
++ i = x = 0;
++ do
++ x += TEXTW(tags[i]);
++ while (ev->x >= x && ++i < LENGTH(tags));
++ /* FIXME when hovering the mouse over the tags and we view the tag,
++ * the preview window get's in the preview shot */
++
++ if (i < LENGTH(tags)) {
++ if (selmon->previewshow != (i + 1)
++ && !(selmon->tagset[selmon->seltags] & 1 << i)) {
++ selmon->previewshow = i + 1;
++ showtagpreview(i);
++ } else if (selmon->tagset[selmon->seltags] & 1 << i) {
++ selmon->previewshow = 0;
++ XUnmapWindow(dpy, selmon->tagwin);
++ }
++ } else if (selmon->previewshow) {
++ selmon->previewshow = 0;
++ XUnmapWindow(dpy, selmon->tagwin);
++ }
++ } else if (ev->window == selmon->tagwin) {
++ selmon->previewshow = 0;
++ XUnmapWindow(dpy, selmon->tagwin);
++ } else if (selmon->previewshow) {
++ selmon->previewshow = 0;
++ XUnmapWindow(dpy, selmon->tagwin);
++ }
+
+ if (ev->window != root)
+ return;
+@@ -1530,6 +1581,82 @@ setmfact(const Arg *arg)
+ arrange(selmon);
+ }
+
++void
++showtagpreview(unsigned int i)
++{
++ if (!selmon->previewshow || !selmon->tagmap[i]) {
++ XUnmapWindow(dpy, selmon->tagwin);
++ return;
++ }
++
++ XSetWindowBackgroundPixmap(dpy, selmon->tagwin, selmon->tagmap[i]);
++ XCopyArea(dpy, selmon->tagmap[i], selmon->tagwin, drw->gc, 0, 0,
++ selmon->mw / scalepreview, selmon->mh / scalepreview,
++ 0, 0);
++ XSync(dpy, False);
++ XMapRaised(dpy, selmon->tagwin);
++}
++
++void
++takepreview(void)
++{
++ Client *c;
++ Imlib_Image image;
++ unsigned int occ = 0, i;
++
++ for (c = selmon->clients; c; c = c->next)
++ occ |= c->tags;
++ //occ |= c->tags == 255 ? 0 : c->tags; /* hide vacants */
++
++ for (i = 0; i < LENGTH(tags); i++) {
++ /* searching for tags that are occupied && selected */
++ if (!(occ & 1 << i) || !(selmon->tagset[selmon->seltags] & 1 << i))
++ continue;
++
++ if (selmon->tagmap[i]) { /* tagmap exist, clean it */
++ XFreePixmap(dpy, selmon->tagmap[i]);
++ selmon->tagmap[i] = 0;
++ }
++
++ /* try to unmap the window so it doesn't show the preview on the preview */
++ selmon->previewshow = 0;
++ XUnmapWindow(dpy, selmon->tagwin);
++ XSync(dpy, False);
++
++ if (!(image = imlib_create_image(sw, sh))) {
++ fprintf(stderr, "dwm: imlib: failed to create image, skipping.");
++ continue;
++ }
++ imlib_context_set_image(image);
++ imlib_context_set_display(dpy);
++ /* uncomment if using alpha patch */
++ //imlib_image_set_has_alpha(1);
++ //imlib_context_set_blend(0);
++ //imlib_context_set_visual(visual);
++ imlib_context_set_visual(DefaultVisual(dpy, screen));
++ imlib_context_set_drawable(root);
++
++ if (previewbar)
++ imlib_copy_drawable_to_image(0, selmon->wx, selmon->wy, selmon->ww, selmon->wh, 0, 0, 1);
++ else
++ imlib_copy_drawable_to_image(0, selmon->mx, selmon->my, selmon->mw ,selmon->mh, 0, 0, 1);
++ selmon->tagmap[i] = XCreatePixmap(dpy, selmon->tagwin, selmon->mw / scalepreview, selmon->mh / scalepreview, DefaultDepth(dpy, screen));
++ imlib_context_set_drawable(selmon->tagmap[i]);
++ imlib_render_image_part_on_drawable_at_size(0, 0, selmon->mw, selmon->mh, 0, 0, selmon->mw / scalepreview, selmon->mh / scalepreview);
++ imlib_free_image();
++ }
++}
++
++void
++previewtag(const Arg *arg)
++{
++ if (selmon->previewshow != (arg->ui + 1))
++ selmon->previewshow = arg->ui + 1;
++ else
++ selmon->previewshow = 0;
++ showtagpreview(arg->ui);
++}
++
+ void
+ setup(void)
+ {
+@@ -1746,6 +1873,7 @@ toggleview(const Arg *arg)
+ unsigned int newtagset = selmon->tagset[selmon->seltags] ^ (arg->ui & TAGMASK);
+
+ if (newtagset) {
++ takepreview();
+ selmon->tagset[selmon->seltags] = newtagset;
+ focus(NULL);
+ arrange(selmon);
+@@ -1811,10 +1939,18 @@ updatebars(void)
+ XSetWindowAttributes wa = {
+ .override_redirect = True,
+ .background_pixmap = ParentRelative,
+- .event_mask = ButtonPressMask|ExposureMask
++ .event_mask = ButtonPressMask|ExposureMask|PointerMotionMask
+ };
++
+ XClassHint ch = {"dwm", "dwm"};
+ for (m = mons; m; m = m->next) {
++ if (!m->tagwin) {
++ m->tagwin = XCreateWindow(dpy, root, m->wx, m->by + bh, m->mw / scalepreview,
++ m->mh / scalepreview, 0, DefaultDepth(dpy, screen), CopyFromParent,
++ DefaultVisual(dpy, screen), CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa);
++ XDefineCursor(dpy, m->tagwin, cursor[CurNormal]->cursor);
++ XUnmapWindow(dpy, m->tagwin);
++ }
+ if (m->barwin)
+ continue;
+ m->barwin = XCreateWindow(dpy, root, m->wx, m->by, m->ww, bh, 0, DefaultDepth(dpy, screen),
+@@ -2043,6 +2179,7 @@ view(const Arg *arg)
+ {
+ if ((arg->ui & TAGMASK) == selmon->tagset[selmon->seltags])
+ return;
++ takepreview();
+ selmon->seltags ^= 1; /* toggle sel tagset */
+ if (arg->ui & TAGMASK)
+ selmon->tagset[selmon->seltags] = arg->ui & TAGMASK;
+--
+2.37.3
+
diff --git a/patches_new/dwm-toggleborder-6.3.diff b/patches_new/dwm-toggleborder-6.3.diff
new file mode 100644
index 0000000..24172a2
--- /dev/null
+++ b/patches_new/dwm-toggleborder-6.3.diff
@@ -0,0 +1,53 @@
+From ef85b0473590615fda4ba4b20a717e42c99e3f99 Mon Sep 17 00:00:00 2001
+From: Stanisław Bitner <sbitner420@tutanota.com>
+Date: Tue, 9 Aug 2022 23:17:47 +0200
+Subject: [PATCH] toggleborder
+
+This patch allows you to toggle client border. It works by setting the
+border of the client to 0 or to borderpx defined in configuration file.
+---
+ config.def.h | 1 +
+ dwm.c | 8 ++++++++
+ 2 files changed, 9 insertions(+)
+
+diff --git a/config.def.h b/config.def.h
+index a2ac963..60b811f 100644
+--- a/config.def.h
++++ b/config.def.h
+@@ -65,6 +65,7 @@ static Key keys[] = {
+ { MODKEY, XK_p, spawn, {.v = dmenucmd } },
+ { MODKEY|ShiftMask, XK_Return, spawn, {.v = termcmd } },
+ { MODKEY, XK_b, togglebar, {0} },
++ { MODKEY|ShiftMask, XK_b, toggleborder, {0} },
+ { MODKEY, XK_j, focusstack, {.i = +1 } },
+ { MODKEY, XK_k, focusstack, {.i = -1 } },
+ { MODKEY, XK_i, incnmaster, {.i = +1 } },
+diff --git a/dwm.c b/dwm.c
+index 967c9e8..91d00f6 100644
+--- a/dwm.c
++++ b/dwm.c
+@@ -211,6 +211,7 @@ static void tag(const Arg *arg);
+ static void tagmon(const Arg *arg);
+ static void tile(Monitor *m);
+ static void togglebar(const Arg *arg);
++static void toggleborder(const Arg *arg);
+ static void togglefloating(const Arg *arg);
+ static void toggletag(const Arg *arg);
+ static void toggleview(const Arg *arg);
+@@ -1707,6 +1708,13 @@ togglebar(const Arg *arg)
+ arrange(selmon);
+ }
+
++void
++toggleborder(const Arg *arg)
++{
++ selmon->sel->bw = (selmon->sel->bw == borderpx ? 0 : borderpx);
++ arrange(selmon);
++}
++
+ void
+ togglefloating(const Arg *arg)
+ {
+--
+2.37.1
+
diff --git a/patches_new/dwm-winicon-6.3-v2.1.diff b/patches_new/dwm-winicon-6.3-v2.1.diff
new file mode 100644
index 0000000..4278431
--- /dev/null
+++ b/patches_new/dwm-winicon-6.3-v2.1.diff
@@ -0,0 +1,371 @@
+diff --git a/config.def.h b/config.def.h
+index a2ac963..322d181 100644
+--- a/config.def.h
++++ b/config.def.h
+@@ -5,6 +5,8 @@ static const unsigned int borderpx = 1; /* border pixel of windows */
+ static const unsigned int snap = 32; /* snap pixel */
+ static const int showbar = 1; /* 0 means no bar */
+ static const int topbar = 1; /* 0 means bottom bar */
++#define ICONSIZE 16 /* icon size */
++#define ICONSPACING 5 /* space between icon and title */
+ static const char *fonts[] = { "monospace:size=10" };
+ static const char dmenufont[] = "monospace:size=10";
+ static const char col_gray1[] = "#222222";
+diff --git a/config.mk b/config.mk
+index b6eb7e0..f3c01b0 100644
+--- a/config.mk
++++ b/config.mk
+@@ -22,7 +22,7 @@ FREETYPEINC = /usr/include/freetype2
+
+ # includes and libs
+ INCS = -I${X11INC} -I${FREETYPEINC}
+-LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS}
++LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} -lXrender -lImlib2
+
+ # flags
+ CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_POSIX_C_SOURCE=200809L -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS}
+diff --git a/drw.c b/drw.c
+index 4cdbcbe..9b474c5 100644
+--- a/drw.c
++++ b/drw.c
+@@ -4,6 +4,7 @@
+ #include <string.h>
+ #include <X11/Xlib.h>
+ #include <X11/Xft/Xft.h>
++#include <Imlib2.h>
+
+ #include "drw.h"
+ #include "util.h"
+@@ -71,6 +72,7 @@ drw_create(Display *dpy, int screen, Window root, unsigned int w, unsigned int h
+ drw->w = w;
+ drw->h = h;
+ drw->drawable = XCreatePixmap(dpy, root, w, h, DefaultDepth(dpy, screen));
++ drw->picture = XRenderCreatePicture(dpy, drw->drawable, XRenderFindVisualFormat(dpy, DefaultVisual(dpy, screen)), 0, NULL);
+ drw->gc = XCreateGC(dpy, root, 0, NULL);
+ XSetLineAttributes(dpy, drw->gc, 1, LineSolid, CapButt, JoinMiter);
+
+@@ -85,14 +87,18 @@ drw_resize(Drw *drw, unsigned int w, unsigned int h)
+
+ drw->w = w;
+ drw->h = h;
++ if (drw->picture)
++ XRenderFreePicture(drw->dpy, drw->picture);
+ if (drw->drawable)
+ XFreePixmap(drw->dpy, drw->drawable);
+ drw->drawable = XCreatePixmap(drw->dpy, drw->root, w, h, DefaultDepth(drw->dpy, drw->screen));
++ drw->picture = XRenderCreatePicture(drw->dpy, drw->drawable, XRenderFindVisualFormat(drw->dpy, DefaultVisual(drw->dpy, drw->screen)), 0, NULL);
+ }
+
+ void
+ drw_free(Drw *drw)
+ {
++ XRenderFreePicture(drw->dpy, drw->picture);
+ XFreePixmap(drw->dpy, drw->drawable);
+ XFreeGC(drw->dpy, drw->gc);
+ drw_fontset_free(drw->fonts);
+@@ -236,6 +242,67 @@ drw_setscheme(Drw *drw, Clr *scm)
+ drw->scheme = scm;
+ }
+
++Picture
++drw_picture_create_resized(Drw *drw, char *src, unsigned int srcw, unsigned int srch, unsigned int dstw, unsigned int dsth) {
++ Pixmap pm;
++ Picture pic;
++ GC gc;
++
++ if (srcw <= (dstw << 1u) && srch <= (dsth << 1u)) {
++ XImage img = {
++ srcw, srch, 0, ZPixmap, src,
++ ImageByteOrder(drw->dpy), BitmapUnit(drw->dpy), BitmapBitOrder(drw->dpy), 32,
++ 32, 0, 32,
++ 0, 0, 0
++ };
++ XInitImage(&img);
++
++ pm = XCreatePixmap(drw->dpy, drw->root, srcw, srch, 32);
++ gc = XCreateGC(drw->dpy, pm, 0, NULL);
++ XPutImage(drw->dpy, pm, gc, &img, 0, 0, 0, 0, srcw, srch);
++ XFreeGC(drw->dpy, gc);
++
++ pic = XRenderCreatePicture(drw->dpy, pm, XRenderFindStandardFormat(drw->dpy, PictStandardARGB32), 0, NULL);
++ XFreePixmap(drw->dpy, pm);
++
++ XRenderSetPictureFilter(drw->dpy, pic, FilterBilinear, NULL, 0);
++ XTransform xf;
++ xf.matrix[0][0] = (srcw << 16u) / dstw; xf.matrix[0][1] = 0; xf.matrix[0][2] = 0;
++ xf.matrix[1][0] = 0; xf.matrix[1][1] = (srch << 16u) / dsth; xf.matrix[1][2] = 0;
++ xf.matrix[2][0] = 0; xf.matrix[2][1] = 0; xf.matrix[2][2] = 65536;
++ XRenderSetPictureTransform(drw->dpy, pic, &xf);
++ } else {
++ Imlib_Image origin = imlib_create_image_using_data(srcw, srch, (DATA32 *)src);
++ if (!origin) return None;
++ imlib_context_set_image(origin);
++ imlib_image_set_has_alpha(1);
++ Imlib_Image scaled = imlib_create_cropped_scaled_image(0, 0, srcw, srch, dstw, dsth);
++ imlib_free_image_and_decache();
++ if (!scaled) return None;
++ imlib_context_set_image(scaled);
++ imlib_image_set_has_alpha(1);
++
++ XImage img = {
++ dstw, dsth, 0, ZPixmap, (char *)imlib_image_get_data_for_reading_only(),
++ ImageByteOrder(drw->dpy), BitmapUnit(drw->dpy), BitmapBitOrder(drw->dpy), 32,
++ 32, 0, 32,
++ 0, 0, 0
++ };
++ XInitImage(&img);
++
++ pm = XCreatePixmap(drw->dpy, drw->root, dstw, dsth, 32);
++ gc = XCreateGC(drw->dpy, pm, 0, NULL);
++ XPutImage(drw->dpy, pm, gc, &img, 0, 0, 0, 0, dstw, dsth);
++ imlib_free_image_and_decache();
++ XFreeGC(drw->dpy, gc);
++
++ pic = XRenderCreatePicture(drw->dpy, pm, XRenderFindStandardFormat(drw->dpy, PictStandardARGB32), 0, NULL);
++ XFreePixmap(drw->dpy, pm);
++ }
++
++ return pic;
++}
++
+ void
+ drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int invert)
+ {
+@@ -379,6 +446,14 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
+ return x + (render ? w : 0);
+ }
+
++void
++drw_pic(Drw *drw, int x, int y, unsigned int w, unsigned int h, Picture pic)
++{
++ if (!drw)
++ return;
++ XRenderComposite(drw->dpy, PictOpOver, pic, None, drw->picture, 0, 0, 0, 0, x, y, w, h);
++}
++
+ void
+ drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h)
+ {
+diff --git a/drw.h b/drw.h
+index 4bcd5ad..71aefa2 100644
+--- a/drw.h
++++ b/drw.h
+@@ -21,6 +21,7 @@ typedef struct {
+ int screen;
+ Window root;
+ Drawable drawable;
++ Picture picture;
+ GC gc;
+ Clr *scheme;
+ Fnt *fonts;
+@@ -49,9 +50,12 @@ void drw_cur_free(Drw *drw, Cur *cursor);
+ void drw_setfontset(Drw *drw, Fnt *set);
+ void drw_setscheme(Drw *drw, Clr *scm);
+
++Picture drw_picture_create_resized(Drw *drw, char *src, unsigned int src_w, unsigned int src_h, unsigned int dst_w, unsigned int dst_h);
++
+ /* Drawing functions */
+ void drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int invert);
+ int drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert);
++void drw_pic(Drw *drw, int x, int y, unsigned int w, unsigned int h, Picture pic);
+
+ /* Map functions */
+ void drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h);
+diff --git a/dwm.c b/dwm.c
+index a96f33c..033ccec 100644
+--- a/dwm.c
++++ b/dwm.c
+@@ -28,6 +28,8 @@
+ #include <stdlib.h>
+ #include <string.h>
+ #include <unistd.h>
++#include <limits.h>
++#include <stdint.h>
+ #include <sys/types.h>
+ #include <sys/wait.h>
+ #include <X11/cursorfont.h>
+@@ -60,7 +62,7 @@
+ /* enums */
+ enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */
+ enum { SchemeNorm, SchemeSel }; /* color schemes */
+-enum { NetSupported, NetWMName, NetWMState, NetWMCheck,
++enum { NetSupported, NetWMName, NetWMIcon, NetWMState, NetWMCheck,
+ NetWMFullscreen, NetActiveWindow, NetWMWindowType,
+ NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH atoms */
+ enum { WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast }; /* default atoms */
+@@ -93,6 +95,7 @@ struct Client {
+ int bw, oldbw;
+ unsigned int tags;
+ int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen;
++ unsigned int icw, ich; Picture icon;
+ Client *next;
+ Client *snext;
+ Monitor *mon;
+@@ -170,6 +173,7 @@ static void focusin(XEvent *e);
+ static void focusmon(const Arg *arg);
+ static void focusstack(const Arg *arg);
+ static Atom getatomprop(Client *c, Atom prop);
++static Picture geticonprop(Window w, unsigned int *icw, unsigned int *ich);
+ static int getrootptr(int *x, int *y);
+ static long getstate(Window w);
+ static int gettextprop(Window w, Atom atom, char *text, unsigned int size);
+@@ -214,6 +218,7 @@ static void togglebar(const Arg *arg);
+ static void togglefloating(const Arg *arg);
+ static void toggletag(const Arg *arg);
+ static void toggleview(const Arg *arg);
++static void freeicon(Client *c);
+ static void unfocus(Client *c, int setfocus);
+ static void unmanage(Client *c, int destroyed);
+ static void unmapnotify(XEvent *e);
+@@ -225,6 +230,7 @@ static void updatenumlockmask(void);
+ static void updatesizehints(Client *c);
+ static void updatestatus(void);
+ static void updatetitle(Client *c);
++static void updateicon(Client *c);
+ static void updatewindowtype(Client *c);
+ static void updatewmhints(Client *c);
+ static void view(const Arg *arg);
+@@ -735,7 +741,8 @@ drawbar(Monitor *m)
+ 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);
++ drw_text(drw, x, 0, w, bh, lrpad / 2 + (m->sel->icon ? m->sel->icw + ICONSPACING : 0), m->sel->name, 0);
++ if (m->sel->icon) drw_pic(drw, x + lrpad / 2, (bh - m->sel->ich) / 2, m->sel->icw, m->sel->ich, m->sel->icon);
+ if (m->sel->isfloating)
+ drw_rect(drw, x + boxs, boxs, boxw, boxw, m->sel->isfixed, 0);
+ } else {
+@@ -875,6 +882,67 @@ getatomprop(Client *c, Atom prop)
+ return atom;
+ }
+
++static uint32_t prealpha(uint32_t p) {
++ uint8_t a = p >> 24u;
++ uint32_t rb = (a * (p & 0xFF00FFu)) >> 8u;
++ uint32_t g = (a * (p & 0x00FF00u)) >> 8u;
++ return (rb & 0xFF00FFu) | (g & 0x00FF00u) | (a << 24u);
++}
++
++Picture
++geticonprop(Window win, unsigned int *picw, unsigned int *pich)
++{
++ int format;
++ unsigned long n, extra, *p = NULL;
++ Atom real;
++
++ if (XGetWindowProperty(dpy, win, netatom[NetWMIcon], 0L, LONG_MAX, False, AnyPropertyType,
++ &real, &format, &n, &extra, (unsigned char **)&p) != Success)
++ return None;
++ if (n == 0 || format != 32) { XFree(p); return None; }
++
++ unsigned long *bstp = NULL;
++ uint32_t w, h, sz;
++ {
++ unsigned long *i; const unsigned long *end = p + n;
++ uint32_t bstd = UINT32_MAX, d, m;
++ for (i = p; i < end - 1; i += sz) {
++ if ((w = *i++) >= 16384 || (h = *i++) >= 16384) { XFree(p); return None; }
++ if ((sz = w * h) > end - i) break;
++ if ((m = w > h ? w : h) >= ICONSIZE && (d = m - ICONSIZE) < bstd) { bstd = d; bstp = i; }
++ }
++ if (!bstp) {
++ for (i = p; i < end - 1; i += sz) {
++ if ((w = *i++) >= 16384 || (h = *i++) >= 16384) { XFree(p); return None; }
++ if ((sz = w * h) > end - i) break;
++ if ((d = ICONSIZE - (w > h ? w : h)) < bstd) { bstd = d; bstp = i; }
++ }
++ }
++ if (!bstp) { XFree(p); return None; }
++ }
++
++ if ((w = *(bstp - 2)) == 0 || (h = *(bstp - 1)) == 0) { XFree(p); return None; }
++
++ uint32_t icw, ich;
++ if (w <= h) {
++ ich = ICONSIZE; icw = w * ICONSIZE / h;
++ if (icw == 0) icw = 1;
++ }
++ else {
++ icw = ICONSIZE; ich = h * ICONSIZE / w;
++ if (ich == 0) ich = 1;
++ }
++ *picw = icw; *pich = ich;
++
++ uint32_t i, *bstp32 = (uint32_t *)bstp;
++ for (sz = w * h, i = 0; i < sz; ++i) bstp32[i] = prealpha(bstp[i]);
++
++ Picture ret = drw_picture_create_resized(drw, (char *)bstp, w, h, icw, ich);
++ XFree(p);
++
++ return ret;
++}
++
+ int
+ getrootptr(int *x, int *y)
+ {
+@@ -1034,6 +1102,7 @@ manage(Window w, XWindowAttributes *wa)
+ c->h = c->oldh = wa->height;
+ c->oldbw = wa->border_width;
+
++ updateicon(c);
+ updatetitle(c);
+ if (XGetTransientForHint(dpy, w, &trans) && (t = wintoclient(trans))) {
+ c->mon = t->mon;
+@@ -1244,6 +1313,11 @@ propertynotify(XEvent *e)
+ if (c == c->mon->sel)
+ drawbar(c->mon);
+ }
++ else if (ev->atom == netatom[NetWMIcon]) {
++ updateicon(c);
++ if (c == c->mon->sel)
++ drawbar(c->mon);
++ }
+ if (ev->atom == netatom[NetWMWindowType])
+ updatewindowtype(c);
+ }
+@@ -1560,6 +1634,7 @@ setup(void)
+ netatom[NetActiveWindow] = XInternAtom(dpy, "_NET_ACTIVE_WINDOW", False);
+ netatom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False);
+ netatom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False);
++ netatom[NetWMIcon] = XInternAtom(dpy, "_NET_WM_ICON", 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);
+@@ -1752,6 +1827,15 @@ toggleview(const Arg *arg)
+ }
+ }
+
++void
++freeicon(Client *c)
++{
++ if (c->icon) {
++ XRenderFreePicture(dpy, c->icon);
++ c->icon = None;
++ }
++}
++
+ void
+ unfocus(Client *c, int setfocus)
+ {
+@@ -1773,6 +1857,7 @@ unmanage(Client *c, int destroyed)
+
+ detach(c);
+ detachstack(c);
++ freeicon(c);
+ if (!destroyed) {
+ wc.border_width = c->oldbw;
+ XGrabServer(dpy); /* avoid race conditions */
+@@ -2007,6 +2092,13 @@ updatetitle(Client *c)
+ strcpy(c->name, broken);
+ }
+
++void
++updateicon(Client *c)
++{
++ freeicon(c);
++ c->icon = geticonprop(c->win, &c->icw, &c->ich);
++}
++
+ void
+ updatewindowtype(Client *c)
+ {