Applying "deck" patch to dwm-6.1

I am trying to apply the deck patch to dwm (AL version). I downloaded the patch file into the appropriate folder, and did git apply . It says patch failed: dwm.c:667
I am using dwm version 6.1, and I downloaded dwm-deck-rmaster-6.1.diff from here:https://dwm.suckless.org/patches/deck/

The deck-rmaster patch should only be needed if you’re using the rmaster patch already. Use the proper patch
https://dwm.suckless.org/patches/deck/dwm-deck-6.0.diff

I had tried that one first. It gave me same error message (w/ different line number). Then I tried the 6.1 since I am on dwm version 6.1.

I’m not sure about this, but I think the patch is not applying since AL makes some changes to the original dwm config.def.h.

No we don’t, we just git clone and make install. Right from suckless.org

install_suckless()
{
	local dir="$1/suckless"
	shift

	if [[ $1 == 'chroot' ]]; then
		chrun "mkdir -pv '$dir'"
		for i in dwm dmenu st; do
			if chrun "git clone 'https://git.suckless.org/$i' '$dir/$i'"; then
				chrun "cd '$dir/$i' && make PREFIX=/usr install"
			else
				printf "failed to clone %s repo\n" "$i"
			fi
		done
	else
		mkdir -pv "$dir"
		for i in dwm dmenu st; do
			if git clone "https://git.suckless.org/$i" "$dir/$i"; then
				cd "$dir/$i" && make PREFIX=/usr install
			else
				printf "failed to clone %s repo\n" "$i"
			fi
		done
	fi
}

Are you sure? The current upstream version is 6.2.

I also see that error with the latest upstream version:

~/git/dwm$ git apply dwm-deck-rmaster-6.1.diff                                                                           
error: patch failed: dwm.c:667
error: dwm.c: patch does not apply
~/git/dwm1$

Looks like dwm.c has been changed significantly since v6.1 so the old patch won’t apply. Unfortunately my C skills are nearly non-existent and I’m too tired to try to make a new version of the patch, sorry.

Are you using any other patches? After work I’ll check it out and post a working patch here.

Yes, Mr. HoaS. When I do dwm -v, I get dwm-6.1.
Pl. rest. This is not urgent by any means. Take care.

No, I have not done any other patches (I’m new to the patch thingy, and deck was the first one I thought to try since I need that functionality in my workflow). Thank you for your interest and help. Are you one of the two main people behind this distro (one guy w/ the strange face mask and other guy, are you the other guy since I saw the face mask id separately). Really cool distro you two made. My compliments.

Here is a working patch

diff --git a/config.def.h b/config.def.h
index 1c0b587..15f52dc 100644
--- a/config.def.h
+++ b/config.def.h
@@ -41,6 +41,7 @@ static const Layout layouts[] = {
 	{ "[]=",      tile },    /* first entry is default */
 	{ "><>",      NULL },    /* no layout function means floating behavior */
 	{ "[M]",      monocle },
+	{ "[D]",      deck },
 };
 
 /* key definitions */
@@ -76,6 +77,7 @@ static Key keys[] = {
 	{ MODKEY,                       XK_t,      setlayout,      {.v = &layouts[0]} },
 	{ MODKEY,                       XK_f,      setlayout,      {.v = &layouts[1]} },
 	{ MODKEY,                       XK_m,      setlayout,      {.v = &layouts[2]} },
+	{ MODKEY,                       XK_c,      setlayout,      {.v = &layouts[3]} },
 	{ MODKEY,                       XK_space,  setlayout,      {0} },
 	{ MODKEY|ShiftMask,             XK_space,  togglefloating, {0} },
 	{ MODKEY,                       XK_0,      view,           {.ui = ~0 } },
diff --git a/dwm.c b/dwm.c
index 9fd0286..2fed713 100644
--- a/dwm.c
+++ b/dwm.c
@@ -157,6 +157,7 @@ static void configure(Client *c);
 static void configurenotify(XEvent *e);
 static void configurerequest(XEvent *e);
 static Monitor *createmon(void);
+static void deck(Monitor *m);
 static void destroynotify(XEvent *e);
 static void detach(Client *c);
 static void detachstack(Client *c);
@@ -645,6 +646,34 @@ createmon(void)
 	return m;
 }
 
+void
+deck(Monitor *m)
+{
+	Client *c;
+	unsigned int i, n, h, mw, my;
+
+	for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++)
+		;
+	if (n == 0)
+		return;
+
+	if (n > m->nmaster) {
+		mw = m->nmaster ? m->ww * m->mfact : 0;
+		snprintf(m->ltsymbol, sizeof m->ltsymbol, "[%d]", n - m->nmaster);
+	} else {
+		mw = m->ww;
+	}
+
+	for (i = my = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++)
+		if (i < m->nmaster) {
+			h = (m->wh - my) / (MIN(n, m->nmaster) - i);
+			resize(c, m->wx, m->wy + my, mw - (2 * c->bw), h - (2*c->bw), 0);
+			my += HEIGHT(c);
+		} else {
+			resize(c, m->wx + mw, m->wy, m->ww - mw - (2 * c->bw), m->wh - (2 * c->bw), 0);
+		}
+}
+
 void
 destroynotify(XEvent *e)
 {

Sorry it fails with error: patch failed, config.def.h:41

Here is my config.def.h in case that helps:
/* See LICENSE file for copyright and license details. */

/* appearance /
static const unsigned int borderpx = 2; /
border pixel of windows /
static const unsigned int snap = 0; /
screen edge snap pixel /
static const unsigned int minwsz = 80; /
minimum height of a client for smfact /
static const unsigned int gappx = 8; /
pixel gap between windows /
static const unsigned int maxgap = 100; /
maximum pixel gap between windows /
static const unsigned int barpx = 0; /
space for external top bar /
static const unsigned int toffset = 0; /
tag text left offset, 0 is original /
static const int showbar = 1; /
0 means no bar /
static const int bartitle = 0; /
0 means no bar title /
static const int topbar = 1; /
0 means bottom bar /
static const int floatborder = 0; /
0 means no floating client borders */

static const char *fonts[] = { “monospace:size=11” };
static const char dmenufont[] = “monospace:size=11”;

static const char col_backgr[] = “#4D545E”;
static const char col_foregr[] = “#E1E1E1”;
static const char col_active[] = “#457EBC”;
static const char col_dimmed[] = “#8C8C8C”;
static const char col_black[] = “#2B303B”;
static const char colors[][3] = {
/
scheme fg bg border */
[SchemeNorm] = { col_dimmed, col_black, col_black },
[SchemeSel] = { col_active, col_black, col_active },
};

/* tags */
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 },
{ “Steam”, NULL, NULL, 0, 1, -1 },
{ “Firefox”, NULL, NULL, 1 << 8, 0, -1 },
};

/* layout(s) /
static const float mfact = 0.61; /
factor of master area size [0.05…0.95] /
static const float smfact = 0.20; /
factor of tiled clients [0.00…0.95] /
static const int nmaster = 1; /
number of clients in master area /
static const int resizehints = 0; /
1 means respect size hints in tiled resizes */

static const Layout layouts[] = {
/* symbol arrange function /
{ “[]=”, tile }, /
first entry is default /
{ “><>”, NULL }, /
no layout function means floating behavior */
{ “[M]”, monocle },
{ “###”, grid },
{ “___”, bstack },
};

/* key definitions */
#define MODKEY Mod1Mask
#define TAGKEYS(KEY,TAG)
{ MODKEY, KEY, view, {.ui = 1 << TAG} },
{ MODKEY|ControlMask, KEY, toggleview, {.ui = 1 << TAG} },
{ MODKEY|ShiftMask, KEY, tag, {.ui = 1 << TAG} },
{ MODKEY|ControlMask|ShiftMask, KEY, toggletag, {.ui = 1 << TAG} },

/* helper for spawning shell commands in the pre dwm-5.0 fashion /
#define SHCMD(cmd) { .v = (const char
[]){ “/bin/sh”, “-c”, cmd, NULL } }

/* spawn commands */
static const char *termcmd[] = { “st”, NULL };
static const char *scrotcmd[] = { “scrot”, “%a-%H%M%S.png”, “-e”, “mv $f ~/scrots/”, NULL };

/* component of dmenucmd, manipulated in spawn() */
static char dmenumon[2] = “0”;

/* dmenu command */
static const char *dmenucmd[] = { “dmenu_run”, “-i”, “-fn”, dmenufont, “-m”, dmenumon,
“-p”, “>>”, “-nb”, col_black, “-nf”, col_dimmed, “-sb”, col_black, “-sf”, col_active, NULL };

/* logout dmenu */
static const char *logoutcmd[] = { “dmenu_logout”, “-i”, “-fn”, dmenufont,
“-W”, “300”, “-l”, “4”, “-m”, dmenumon, “-p”, “>>”, “-nb”, col_black,
“-nf”, col_dimmed, “-sb”, col_black, “-sf”, col_active, NULL };

/* XF86Audio keys */
static const char *voltogg[] = { “pamixer”, “-t”, NULL };
static const char *volincr[] = { “pamixer”, “-i”, “2”, NULL };
static const char *voldecr[] = { “pamixer”, “-d”, “2”, NULL };

static Key keys[] = {
/* modifier(s) key function argument */
{ 0, XF86XK_AudioMute, spawn, {.v = voltogg} },
{ 0, XF86XK_AudioRaiseVolume, spawn, {.v = volincr} },
{ 0, XF86XK_AudioLowerVolume, spawn, {.v = voldecr} },

{ 0,                  XK_Print,                spawn,                            {.v = scrotcmd} },
{ 0,                  XK_Pause,                spawn,                           {.v = logoutcmd} },
{ Mod4Mask,           XK_x,                    spawn,                           {.v = logoutcmd} },
{ MODKEY,             XK_p,                    spawn,                            {.v = dmenucmd} },
{ MODKEY,             XK_F1,                   spawn,                            {.v = dmenucmd} },
{ MODKEY|ControlMask, XK_t,                    spawn,                             {.v = termcmd} },
{ MODKEY|ShiftMask,   XK_Return,               spawn,                             {.v = termcmd} },
{ Mod4Mask,           XK_Return,               spawn,                             {.v = termcmd} },

{ MODKEY|ShiftMask,   XK_q,                    quit,                                         {0} },
{ MODKEY,             XK_q,                    killclient,                                   {0} },

{ Mod4Mask,           XK_j,                    moveresize, {.v = (int []){   0,  20,   0,   0 }} },
{ Mod4Mask,           XK_k,                    moveresize, {.v = (int []){   0, -20,   0,   0 }} },
{ Mod4Mask,           XK_l,                    moveresize, {.v = (int []){  20,   0,   0,   0 }} },
{ Mod4Mask,           XK_h,                    moveresize, {.v = (int []){ -20,   0,   0,   0 }} },
{ Mod4Mask|ShiftMask, XK_j,                    moveresize, {.v = (int []){   0,   0,   0,  20 }} },
{ Mod4Mask|ShiftMask, XK_k,                    moveresize, {.v = (int []){   0,   0,   0, -20 }} },
{ Mod4Mask|ShiftMask, XK_l,                    moveresize, {.v = (int []){   0,   0,  20,   0 }} },
{ Mod4Mask|ShiftMask, XK_h,                    moveresize, {.v = (int []){   0,   0, -20,   0 }} },

{ MODKEY,             XK_equal,                incgappx,                                     {0} },
{ MODKEY|ShiftMask,   XK_equal,                incgappx,                               {.i = +2} },
{ MODKEY,             XK_minus,                incgappx,                               {.i = -2} },

{ MODKEY,             XK_i,                    incnmaster,                             {.i = +1} },
{ MODKEY,             XK_d,                    incnmaster,                             {.i = -1} },

{ MODKEY|ShiftMask,   XK_j,                    movestack,                              {.i = +1} },
{ MODKEY|ShiftMask,   XK_k,                    movestack,                              {.i = -1} },
{ MODKEY,             XK_j,                    focusstack,                             {.i = +1} },
{ MODKEY,             XK_k,                    focusstack,                             {.i = -1} },

{ MODKEY|ShiftMask,   XK_h,                    setsmfact,                           {.f = -0.02} },
{ MODKEY|ShiftMask,   XK_l,                    setsmfact,                           {.f = +0.02} },
{ MODKEY,             XK_h,                    setmfact,                            {.f = -0.02} },
{ MODKEY,             XK_l,                    setmfact,                            {.f = +0.02} },

{ MODKEY,             XK_b,                    togglebar,                                    {0} },
{ MODKEY|ShiftMask,   XK_space,                togglefloat,                                  {0} },
{ MODKEY,             XK_space,                setlayout,                                    {0} },
{ MODKEY|ShiftMask,   XK_t,                    setlayout,                     {.v = &layouts[0]} },
{ MODKEY|ShiftMask,   XK_f,                    setlayout,                     {.v = &layouts[1]} },
{ MODKEY|ShiftMask,   XK_m,                    setlayout,                     {.v = &layouts[2]} },
{ MODKEY|ShiftMask,   XK_g,                    setlayout,                     {.v = &layouts[3]} },
{ MODKEY|ShiftMask,   XK_b,                    setlayout,                     {.v = &layouts[4]} },

{ 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} },

{ MODKEY,             XK_Tab,                  zoom,                                         {0} },
{ MODKEY|ShiftMask,   XK_Tab,                  view,                                         {0} },
{ MODKEY,             XK_0,                    view,                                  {.ui = ~0} },
{ MODKEY|ShiftMask,   XK_0,                    tag,                                   {.ui = ~0} },
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)

};

/* Mouse button definitions /
/
click can be 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]} },
{ ClkStatusText, 0, Button2, spawn, {.v = termcmd} },
{ ClkWinTitle, 0, Button2, zoom, {0} },
{ ClkTagBar, 0, Button1, view, {0} },
{ ClkTagBar, 0, Button3, toggleview, {0} },
{ ClkTagBar, MODKEY, Button1, tag, {0} },
{ ClkTagBar, MODKEY, Button3, toggletag, {0} },
{ ClkClientWin, MODKEY, Button1, movemouse, {0} },
{ ClkClientWin, MODKEY, Button2, togglefloat, {0} },
{ ClkClientWin, MODKEY, Button3, resizemouse, {0} },
};

And as you can see: I have not made any changes, this is what AL shipped with.
That deck idea looks cool though: maybe you guys will consider it as standard with AL.

Ok this is one of my old heavily patched dwm branches. There was a short period where the installer used this but it was swapped in favour of stock dwm, that fork is no longer maintained so I’d really suggest switching to stock dwm and build up your own. This is a very simple patch with no logic changes or removals so you can just manually apply it failing that.

diff --git a/config.def.h b/config.def.h
index a6edbb6..02dc8d8 100644
--- a/config.def.h
+++ b/config.def.h
@@ -53,6 +53,7 @@ static const Layout layouts[] = {
 	{ "[M]",      monocle },
 	{ "###",      grid },
 	{ "___",      bstack },
+	{ "[D]",      deck },
 };
 
 /* key definitions */
@@ -139,6 +140,7 @@ static Key keys[] = {
 	{ MODKEY|ShiftMask,   XK_m,                    setlayout,                     {.v = &layouts[2]} },
 	{ MODKEY|ShiftMask,   XK_g,                    setlayout,                     {.v = &layouts[3]} },
 	{ MODKEY|ShiftMask,   XK_b,                    setlayout,                     {.v = &layouts[4]} },
+	{ MODKEY|ShiftMask,   XK_c,                    setlayout,                     {.v = &layouts[5]} },
 
 	{ MODKEY,             XK_comma,                focusmon,                               {.i = -1} },
 	{ MODKEY,             XK_period,               focusmon,                               {.i = +1} },
diff --git a/dwm.c b/dwm.c
index 1a3dff9..10e7dd5 100644
--- a/dwm.c
+++ b/dwm.c
@@ -180,6 +180,7 @@ static void configure(Client *c);
 static void configurenotify(XEvent *e);
 static void configurerequest(XEvent *e);
 static Monitor *createmon(void);
+static void deck(Monitor *m);
 static void destroynotify(XEvent *e);
 static void detach(Client *c);
 static void detachstack(Client *c);
@@ -767,6 +768,34 @@ Monitor * createmon(void)
 	return m;
 }
 
+void
+deck(Monitor *m)
+{
+	Client *c;
+	unsigned int i, n, h, mw, my;
+
+	for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++)
+		;
+	if (n == 0)
+		return;
+
+	if (n > m->nmaster) {
+		mw = m->nmaster ? m->ww * m->mfact : 0;
+		snprintf(m->ltsymbol, sizeof m->ltsymbol, "[%d]", n - m->nmaster);
+	} else {
+		mw = m->ww;
+	}
+
+	for (i = my = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++)
+		if (i < m->nmaster) {
+			h = (m->wh - my) / (MIN(n, m->nmaster) - i);
+			resize(c, m->wx, m->wy + my, mw - (2 * c->bw), h - (2*c->bw), 0);
+			my += HEIGHT(c);
+		} else {
+			resize(c, m->wx + mw, m->wy, m->ww - mw - (2 * c->bw), m->wh - (2 * c->bw), 0);
+		}
+}
+
 void destroynotify(XEvent *e)
 {
 	Client *c;

EDIT: fixed error in layout index

Sorry, I’m not following. You had said that the AL dwm code is the unaltered version from suckless, right? So that means the code I have is the original suckless dwm code (aka stock dwm).

  1. I tried patching the deck patch from dwm website, it didn’t work
  2. I tried patching using your latest patch, it did patch, but when I Alt-Shift-q’d out and logged back in, the deck feature was not available. It was the same layout as stock dwm.
    I am sure I missed something important in your post, sorry could you pl. explain what I missed? Thanks!

My mistake for not clarifying.

The install and source you have is not the stock/official but one of my old forks from about a year ago.

Once logged back in you would need to change the layout to deck with the bind MOD-Shift-c

OK, got it. So then, with my dwm code (your old fork) + your patch, it should work. However, I did Alt-Shift-c and it does not change layout at all. I did it both with and without secondary windows. Is Alt-Shift-c all I need to do, or do I need to do something else to get the deck layout? Thanks so much for helping.

Did you transfer the config.def.h changes across to your local config.h? Do this or do rm config.h then rebuild.

Oh shoot. Yes, I forgot that! Sorry to take your time and mess up at my end. Will do that now (rm config.h and sudo make install clean). Will update in few mins.

OK, I did it, and indeed there is a layout change. This change is indicated by the symbol ### in the status bar. HOWEVER, this change is not to the deck layout, but rather to some form of equal tiled layout. Meaning, say I have one window in master, and 3 in secondary. When I press Alt-shift-c, I get all 4 windows equally taking space, each one taking up exactly 1/4th of my screen.
In Deck, in contrast, I would have my single window still in master, while the 3 secondary windows would convert into monocle layout, so that exactly 2 windows would be visible at any time.
I also confirmed that I can enter and exit all other layout modes from ### layout.
Maybe you send me the wrong patch, not for deck but for this other feature?
Thanks!

I was looking at your patch, and it seems what I get with Alt-Shift-c is called “grid”. Your patch does indeed contain the defn of deck, however the key binding for that is Alt-Shift-XK_b. I don’t know what that means, but I’ll try to figure out it. Thanks!