[dwm] small dwm tile() patch

2008-01-13 Thread Chris Webb
I grabbed the latest dwm earlier to port various bits of my own into
clean patches against the latest dwm. I hadn't looked at the standard
tile function for a little while, but I notice that the current
incarnation recalculates the window geometries (mw and th) for each
client rather than once in front of the client loop. hg bisect says this
started happening at changeset 1072:5a06b4b69479 when the Xinerama work
began.

Obviously mw and th are different from monitor to monitor, but within a
monitor they're constant, so I think the following (trivial) patch is
correct:

diff --git a/dwm.c b/dwm.c
--- a/dwm.c
+++ b/dwm.c
@@ -1689,12 +1689,13 @@ tile(void) {
for(n = 0, c = nexttiled(clients, m); c; c = nexttiled(c-next, 
m))
n++;
 
+   /* window geoms */
+   mw = (n == 1) ? m-waw : m-mwfact * m-waw;
+   th = (n  1) ? m-wah / (n - 1) : 0;
+   if(n  1  th  bh)
+   th = m-wah;
+
for(j = 0, c = mc = nexttiled(clients, m); c; c = 
nexttiled(c-next, m)) {
-   /* window geoms */
-   mw = (n == 1) ? m-waw : m-mwfact * m-waw;
-   th = (n  1) ? m-wah / (n - 1) : 0;
-   if(n  1  th  bh)
-   th = m-wah;
if(j == 0) { /* master */
nx = m-wax;
ny = m-way;


Best wishes,

Chris.



Re: [dwm] dzen replacing dwm status bar

2007-12-23 Thread Chris Webb
Anselm R. Garbe [EMAIL PROTECTED] writes:

[Re: embedded windows]
 I'd like to keep this complexity out of dwm. I really think to
 provide a more flexible way to change the bar position and
 geometry.

One simple solution that might be sufficient: here I have two gaps
defined, a top gap and a bottom gap. During the geometry setup, I add the
top gap to sy and subtract (top gap + bottom gap) from sh.

I guess if one could limit the dwm bar to a fraction of the width of the
screen, there would also be space to the right or left of that for
something like a dzen.

Best wishes,

Chris.



Re: [dwm] Xinerama support

2007-12-11 Thread Chris Webb
pancake [EMAIL PROTECTED] writes:

 This way you can achieve any of the possibilities (show the same client in 
 both
 monitors, move a window from one to another, etc..

X doesn't give you a mechanism for showing the same client on both monitors.

Best wishes,

Chris.



Re: [dwm] dwm wish, a tidy-up function

2007-12-06 Thread Chris Webb
Sander van Dijk [EMAIL PROTECTED] writes:

 On Dec 6, 2007 11:23 AM, Anselm R. Garbe [EMAIL PROTECTED] wrote:
  Ok, but the DWMTAGS idea is ok for everyone?
 
 Would that work? If the new dwm is a child of the old one it would,
 but when the dwm restart is controlled by a shell loop such as
 
 while true
 do
 dwm
 done
 
 I believe this wouldn't work, right?

If dwm were to produce the list of selected tags on stdout on exit and
could accept a list of tags as arguments on startup, this would allow a
'restart by quit' without losing the selected tags and without requiring a
special 'quit and exec' function.

Also, if the point of a restart is just to retag windows according to the
rules, wouldn't it be cleaner to implement just that rather than a full
re-exec?

Best wishes,

Chris.



Re: [dwm] input status text bug?

2007-10-31 Thread Chris Webb
Anselm R. Garbe [EMAIL PROTECTED] writes:

 If we decide for line-based input reading, one easily could
 block dwm from further event processing through running
 
 echo -n foo | dwm
 
 I think that'd be a big disadvantage.

It could append read text to the end of stext[] whenever it successfully
reads(), except that the first character after a '\n' clears stext[] and
starts a new status. It needn't block.

Best wishes,

Chris.



Re: [dwm] Taglayouts poll

2007-10-30 Thread Chris Webb
Kai Grossjohann [EMAIL PROTECTED] writes:

 On Fri, Oct 26, 2007 at 05:09:06PM +0100, Chris Webb wrote:
 
  One completely different approach to implementing multiple layouts in a
  pure tagging context is to introduce a new layout index, completely
  independent of the tag toggles. In the same way you can view() or
  toggleview() a tag at present, you could select() by index a particular
  set of layout parameters. You'd need to display the selected layout as
  well as the selected tags in the status bar, or it would rapidly become
  very confusing. This would be interesting to try and I confess I haven't
  tried it. However, I suspect in my normal usage it would just replace one
  keystroke with two.
 
 I think you can have one key execute two actions, by adding two lines
 for the same key into the keybindings.
 
 Then folks who like it can bind keys that do view() followed by
 select().

While we're examining the solution space, I'll point out that it's a
small step from doing this sort of layout indexing to completely
replacing the single workspace with multiple workspaces. Windows would
belong to tags as in standard dwm, each workspace having a set of
selected tags (not necessary disjoint) as well as their own independent
layout and parameters. Finally, a status bar of the form

  WORKSPACES LAYOUT TAGS TITLE MESSAGE

would be needed, rather than dwm's

  TAGS LAYOUT TITLE MESSAGE

One might then switch between different workspaces for different jobs,
and mix in and out tags full of windows within a particular job.

Initialisation is an issue here: what tags are present in each workspace
at startup? Just the first tag in each? Just tag i % k in workspace i?
There's no canonical choice as far as I can see, which is untidy.

Cheers,

Chris.



Re: [dwm] Taglayouts poll

2007-10-26 Thread Chris Webb
Sander van Dijk [EMAIL PROTECTED] writes:

 No, it shouldn't, for the simple reason that it doesn't fit within the
 tagging paradigm.

You're right, it doesn't really. I would characterise this patch (and
variants such as the one I use) as changing the underlying paradigm from
pure tagging to something closer to traditional workspaces. In addition
to the unordered set of selected tags, the patch leads to one tag being
distinguished as the 'main' selected tag. This main tag is then used to
index the layouts, regardless of the other selected tags.

One way to view this is that the 'main' tag, reset by view(), is the
current workspace, and that toggleview() allows you to temporarily mix in
the windows from other workspaces using the current workspace's layout.
In my personal dwm derivative, I even color the main selected tag and
additional mixed-in tags differently in the status bar to emphasise their
different status.

This is a more complicated model than pure tagging. Conceptually, the
tagging model is simpler and neater---more dwm-like in fact. I doubt this
fits well into upstream dwm. However, when I came to put together and use
a working environment based upon dwm, and particularly as I added a
couple more layouts and extended tile() to be more flexible, I discovered
that having a single layout into which I could choose sets of windows to
drop felt significantly less convenient to me than multiple layouts on
multiple workspaces. view() tag A, set up layout suitable for task A;
view() tag B, set up layout suitable for task B; return to viewing tag A,
reset layout for task A... is a pattern that was begging to be optimised
away. Clearly YMMV.

Incidentally, something else needed for consistency when implementing
taglayouts-type behaviour is to index all the layout parameters like
mwfact, nmaster (if you have it) and nstack/ncols/nrows (if you have any
of them). I don't think this patch currently does this?

 Hence, to do this taglayouts stuff right

One completely different approach to implementing multiple layouts in a
pure tagging context is to introduce a new layout index, completely
independent of the tag toggles. In the same way you can view() or
toggleview() a tag at present, you could select() by index a particular
set of layout parameters. You'd need to display the selected layout as
well as the selected tags in the status bar, or it would rapidly become
very confusing. This would be interesting to try and I confess I haven't
tried it. However, I suspect in my normal usage it would just replace one
keystroke with two.

Cheers,

Chris.



Re: [dwm] Taglayouts poll

2007-10-26 Thread Chris Webb
Jan Christoph Ebersbach [EMAIL PROTECTED] writes:

 On Fri 26-10-2007 17:09 +0100, Chris Webb wrote:
 
  Incidentally, something else needed for consistency when implementing
  taglayouts-type behaviour is to index all the layout parameters like
  mwfact, nmaster (if you have it) and nstack/ncols/nrows (if you have
  any of them). I don't think this patch currently does this?
 
 You are right, the patch doesn't do this at the moment and it's one
 thing that I really miss.

As far as I remember, it's sufficient to replace the definition of mwfact
with

  double mwfact[NTAGS];

add

  for (i = 0; i  NTAGS; i++)
mwfact[i] = MWFACT;

into setup() (or preferably put the mwfact initialisation into the ltidx
loop), insert a

  free(mwfact);

into cleanup() and replace mwfact by mwfact[csel] everywhere else.

Cheers,

Chris.



Re: [dwm] Taglayouts poll

2007-10-26 Thread Chris Webb
Chris Webb [EMAIL PROTECTED] writes:

 insert a
 
   free(mwfact);
 
 into cleanup()

You don't need this bit with a static mwfact[NTAGS] of course. D'oh.
Edited my email after writing to reflect the fact that dwm has gone
static but didn't delete the unnecessary free().

Best wishes,

Chris.



Re: [dwm] idxoftag

2007-10-22 Thread Chris Webb
Isn't the fundamental problem with all this that you are assuming that
tags are named by their number. You can't do this in the more general case
where you have tags like 'www' or 'scratchpad'.

Best wishes,

Chris.



Re: [dwm] RESIZEHINTS broken?

2007-10-22 Thread Chris Webb
Anselm R. Garbe [EMAIL PROTECTED] writes:

 Agreed, I will change the resize code accordingly. So
 RESIZEHINTS will be renamed to INCRESIZE or something like that.

I think the situation is slightly more complex than this. You want full
size hint support (including hints that enlarge the window beyond the
requested size) for floating windows and in floating mode, whereas you
want restricted size hint support (disallowing growth of a window beyond
requested dimensions) in tiling modes. The sizehints argument to resize()
probably therefore needs to be a tri-state.

Best wishes,

Chris.



Re: [dwm] idxoftag

2007-10-22 Thread Chris Webb
Stefano Soffia [EMAIL PROTECTED] writes:

 I do not understand what you mean with `more general case'. Note that
 currently, the idxoftag() function performs a comparison between
 pointers not between strings.

Ah, I've just spotted what you're doing: it's not actually what I thought
you were doing. Please ignore my comment.

Best wishes,

Chris.



Re: [dwm] setmwfact bug

2007-10-01 Thread Chris Webb
Szabolcs Nagy [EMAIL PROTECTED] writes:

 there's a typo in in dwm.c in setmwfact():
 
 ...
 else if(1 == sscanf(arg, %lf, delta)) {
 if(arg[0] == '+' || arg[0] == '-')
 mwfact += delta;
 else
 mwfact = delta; // should be -=
 ...
 }

I don't think it should be. The current behaviour is that
setmwfact(+0.1) adds 0.1 to mwfact, setmwfact(-0.1) subtracts 0.1
from mwfact, and setmwfact(0.1) sets mwfact equal to 0.1. Your =- would
make setmwfact(0.1) equivalent to setmwfact(-0.1).

Cheers,

hrus.



Re: [dwm] improved tile()

2007-10-01 Thread Chris Webb
Anselm R. Garbe [EMAIL PROTECTED] writes:

 I know my English is totally crap, so excuse that. Anyway you
 describe the problem pretty well.

No, your English is fine; it's my reading that's dodgy! :-)

Cheers,

Chris.



[dwm] [PATCH] An experiment with X resources

2007-09-24 Thread Chris Webb
This morning I've been thinking about run time configuration of dwm. 

I've never especially liked the compile-time rules table in config.h. The
fact that one or two programs I use happen to be broken and need a rule
with isfloating = 1 doesn't seem like something that the dwm binary
should be cluttered with. Clearly this is a matter of personal taste and
your mileage will probably vary, but it definitely grates for me. I also
have a couple of different screens and I'd like to be able to reconfigure
fonts and colours (depending on the display dwm is managing) without
keeping multiple dwm binaries in my home directory.

As an experiment, I've added support for customisation with X resources
in a branch of my own tree. To avoid growing the code too much, I
completely replaced the hard-coded rules table with a dynamic one
populated from X resources, but all other settings use config.h values as
defaults. Key bindings remain a matter for config.h. As far as I can see,
configuring these at runtime would introduce a big, ugly symbol table
into dwm for little or no gain.

Doing all this grows dwm.c less than I was originally expecting, as can
be seen from the patch. Most of the extra code is involved with
constructing the tag and rule lists rather than just to add simpler
config options like fonts and colours.

I've ported my patch back to upstream dwm (hg tip) and attached it at the
end of this message in case anyone else on the list is interested in
experimenting along the same lines. A sample .Xresources file to merge
(use xrdb -merge/-load) might be:

  Dwm.bar: top
  Dwm.font: -*-terminus-medium-r-*-*-12-*-*-*-*-*-iso10646-*

  Dwm.normal.border: #cc
  Dwm.normal.background: #ff
  Dwm.normal.background: #00
  Dwm.selected.border: #ff
  Dwm.selected.background: #ff
  Dwm.selected.foreground: #ff

  Dwm.tags: 1 2 3 4 5 6 7 8 9
  Dwm.rules: scratchpad browser

  Dwm.properties.scratchpad: URxvt:scratch
  Dwm.floating.scratchpad: True

  Dwm.properties.browser: Opera
  Dwm.tags.browser: 2

Cheers,

Chris.


diff -r 92c19c929a59 config.def.h
--- a/config.def.h  Sun Sep 23 18:50:04 2007 +0200
+++ b/config.def.h  Mon Sep 24 14:28:26 2007 +0100
@@ -1,4 +1,8 @@
 /* See LICENSE file for copyright and license details. */
+
+/* resources */
+#define RESNAMEdwm
+#define RESCLASS   Dwm
 
 /* appearance */
 #define BARPOS BarTop /* BarBot, BarOff */
@@ -12,14 +16,7 @@
 #define SELFGCOLOR #ff
 
 /* tagging */
-const char *tags[] = { 1, 2, 3, 4, 5, 6, 7, 8, www, NULL };
-Rule rules[] = {
-   /* class:instance:title regex   tags regex  isfloating */
-   { Firefox,www,  False },
-   { Gimp,   NULL,   True },
-   { MPlayer,NULL,   True },
-   { Acroread,   NULL,   True },
-};
+#define TAGS   1 2 3 4 5 6 7 8 9
 
 /* layout(s) */
 #define ISTILE isarrange(tile) /* || isarrange(custom) */
diff -r 92c19c929a59 dwm.c
--- a/dwm.c Sun Sep 23 18:50:04 2007 +0200
+++ b/dwm.c Mon Sep 24 14:28:26 2007 +0100
@@ -40,6 +40,7 @@
 #include X11/Xatom.h
 #include X11/Xlib.h
 #include X11/Xproto.h
+#include X11/Xresource.h
 #include X11/Xutil.h
 
 /* macros */
@@ -132,6 +133,8 @@ void *emallocz(unsigned int size);
 void *emallocz(unsigned int size);
 void enternotify(XEvent *e);
 void eprint(const char *errstr, ...);
+void *erealloc(void *res, unsigned int size);
+char *estrdup(const char *s);
 void expose(XEvent *e);
 void floating(void); /* default floating layout */
 void focus(Client *c);
@@ -139,7 +142,10 @@ void focusprev(const char *arg);
 void focusprev(const char *arg);
 Client *getclient(Window w);
 unsigned long getcolor(const char *colstr);
+char *getresource(const char *resource, char *defval);
+void getrules(void);
 long getstate(Window w);
+void gettags(void);
 Bool gettextprop(Window w, Atom atom, char *text, unsigned int size);
 void grabbuttons(Client *c, Bool focused);
 unsigned int idxoftag(const char *tag);
@@ -190,11 +196,11 @@ void zoom(const char *arg);
 void zoom(const char *arg);
 
 /* variables */
-char stext[256];
+char stext[256], **tags;
 double mwfact;
 int screen, sx, sy, sw, sh, wax, way, waw, wah;
 int (*xerrorxlib)(Display *, XErrorEvent *);
-unsigned int bh, bpos, ntags;
+unsigned int bh, bpos, ntags = 0;
 unsigned int blw = 0;
 unsigned int ltidx = 0; /* default */
 unsigned int nlayouts = 0;
@@ -226,7 +232,9 @@ Display *dpy;
 Display *dpy;
 DC dc = {0};
 Window barwin, root;
+Rule *rules;
 Regs *regs = NULL;
+XrmDatabase xrdb;
 
 /* configuration, allows nested code to access above variables */
 #include config.h
@@ -402,7 +410,6 @@ compileregs(void) {
 
if(regs)
return;
-   nrules = sizeof rules / sizeof rules[0];
regs = emallocz(nrules * sizeof(Regs));
for(i = 0; i  nrules; i++) {

Re: [dwm] [PATCH] An experiment with X resources

2007-09-24 Thread Chris Webb
Anselm R. Garbe [EMAIL PROTECTED] writes:

 The only questionable issue I don't like is the strsep(3) use,
 because of portability concerns.

Failing all else, I guess a strsep() tokeniser

while(tag = strsep(line,  \t\n)) {
if(!tag[0])
continue;
tags = erealloc(tags, sizeof(char *) * ++ntags);
tags[ntags - 1] = tag;
}

can always be expanded to something like this

do {
tag = line;
if (line = strpbrk(line,  \t\n))
*line++ = '\0';
if !tag[0]
continue;
tags = erealloc(tags, sizeof(char *) * ++ntags);
tags[ntags - 1] = tag;
} while (line);

assuming strpbrk is reasonably universal.

Cheers,

Chris.



Re: [dwm] [PATCH] An experiment with X resources

2007-09-24 Thread Chris Webb
Jukka Salmi [EMAIL PROTECTED] writes:

 Hmm, why using the ternary operator? Are there systems where
 `realloc(NULL, size)' does not behave identically to `malloc(size)'?

I remember some old unix systems that segfault if you pass realloc a null
pointer! I haven't seen anything like that for a long time, though, and I
think ISO C now specifies that realloc(NULL, size) is the same as
malloc(size), so I was probably just being over-paranoid.

Cheers,

Chris.



Re: [dwm] [PATCH] An experiment with X resources

2007-09-24 Thread Chris Webb
Anselm R. Garbe [EMAIL PROTECTED] writes:

 it won't last long that the need arises to also configure the key
 bindings, and the terminal command, and the dmenu command, and what not
 using such capabilities.

Actually... :-)

What wasn't in that patch, but is in my tree, is a little convenience
function that lets you define commands by name in .Xresources:

  Dwm.command.xterm: urxvt -bg red
  Dwm.command.browser: opera

and then bind them in config.h

  Key keys[] = {
  [...]
  { MODKEY, XK_Return, spawn_command, xterm }
  { MODKEY | ShiftMask, XK_Return, spawn_command, browser }
  [...]
  }

At present, my spawn_command is a no-op if the corresponding
Dwm.command.* X resource isn't defined.

Unfortunately, to do this requires that xrdb doesn't get freed at the end
of setup(), so I need to rethink this a bit before I'll be happy with it.

I also now configure my mwfact, nmaster, nrows and ncols parameters for
my 'supertile()' through X resources.

For me, this gives a sweet spot between runtime configurability and
keeping code complexity low, with compiled-in key bindings which are
constant across all the systems I use, but runtime configurable colours,
rules, tag names and commands, which vary from system to system.

I used X resources not because I think they're a nice system per se, but
rather because I end up having to use them for other X apps anyway. I
didn't fancy trying to express a rules table as a command line argument
or environment variable!

 Besides this, the X resource file format always seemed insane to me.

Yes, I agree. Many of the design choices in Xlib are baroque to the point
of insanity.

Cheers,

Chris.



Re: [dwm] [patch] nmaster for dwm 4.5

2007-09-21 Thread Chris Webb
Peter Hartlich [EMAIL PROTECTED] writes:

 Attached is Jeroen Schot's nmaster patch, ported to dwm (pre-)4.5 and
 with incnmaster() renamed setnmaster().
[...]
 void
 setnmaster(const char *arg) {
   int i;
 
   if(!isarrange(tile))
   return;
   if(!arg)
   nmaster = NMASTER;
   else {
   i = atoi(arg);
   if((nmaster + i)  1 || wah / (nmaster + i) = 2 * BORDERPX)
   return;
   nmaster += i;
   }
   if(sel)
   arrange();
   else
   drawbar();
 }
 

For setnmaster to behave consistently with setmwfact (which takes an
absolute value or a delta beginning with + or -), you might prefer
something like

void 
setnmaster(const char *arg) {
int i;
if(!isarrange(tile))
return;
if(!arg)
nmaster = NMASTER;
else {
if(arg[0] != '+'  arg[0] != '-')
i = atoi(arg);
else
i = nmaster + atoi(arg);
if(i  1 || wah / i = 2 * BORDERPX)
return;
nmaster = i;
}
if(sel)
arrange();
else
drawbar();
}

Best wishes,

Chris.



Re: [dwm] Unused space between clients

2007-09-20 Thread Chris Webb
Xavier [EMAIL PROTECTED] writes:

[rxvt-unicode]
 Previously, I had some weird corruptions at the place of this unused
 space. This only happened with urxvt though, not xterm. Not sure why..
 But I'm happier with urxvt anyway.

I've noticed this behaviour with urxvt when window size hints are being
over-ruled by dwm. Terminals certainly do look much nicer in tiled mode
when it does this, so it would be nice to fix urxvt to do the right
thing. Sometimes after resizing, when the window is 'cleared', the bottom
part line and/or rightmost part column doesn't clear, leading to the
corruptions you describe. Another manifestation is that focus tinting
doesn't properly affect the extra half line/column space at the bottom
and right of a resized window.

I wonder whether it would be easy to fix urxvt to 'round up' the area it
refreshes instead of 'rounding down' when there are partial rows and
columns...

Best wishes,

Chris.



Re: [dwm] [patch] Stack columns patch for dwm-4.4.1

2007-09-17 Thread Chris Webb
pancake [EMAIL PROTECTED] writes:

 Here's my keybindings
 
 { MODKEY|ShiftMask, XK_l,   setncols,   +1 
 }, \
 { MODKEY|ShiftMask, XK_h,   setncols,   -1 
 }, \
 { MODKEY|ShiftMask, XK_j,   setnmaster, +1 
 }, \
 { MODKEY|ShiftMask, XK_k,   setnmaster, -1 
 }, \

[I.e. interchanging the setncols and setnmaster keybindings.]

Okay, if you think this a more natural extension of the default binding
set, I'll pick this change up back into my own patch. My personal tree
has diverged quite a bit, so in preparing a patch for others to use
against stock dwm, I just copied the config.default.h bindings from the
other nmaster patch out there, and added something by analogy rather than
actually trying to live with the suggested extra keystrokes!

 Some tips:
 
 config.default.h:
 //#define NCOLS   1   /* maximum number of stacking area 
 columns */
 #define NCOLS   1   /* default number of stacking area 
 columns */

Actually, I guess it's the 'default limit to the number of stacking area
columns', as the code won't create ncols columns unless there are enough
windows (more than (ncols - 1)*nrows) to fill them.

 The i  0 condition has been changed to i  1 to avoid strange situations.

The ncols setting of zero is intentional, creating as many columns as
required without limit to give exactly nrows clients per row. Maybe
you're right that it isn't especially useful and just adds confusion:
it's indistinguishable from ncols  1 for practical purposes.

Originally, my tile() had no ncols limit, and so I needed an nrows of
zero to get the default behaviour of an unlimited number of clients
stacked in a single column. Now I agree, this is less confusingly
achieved by setting ncols = 1, so nrows = 0 can go away.

Removing these two special cases will also simplify a couple of tests in
tile(), which is no bad thing!

 You can check this code here:
   http://news.nopcode.org/pvcroot/dwm-4.4.1-pancake.tar.gz

Glancing through, I notice you've merged in the incnmaster function as
well as my very similar setnmaster function. setnmaster is a superset of
incnmaster, so you probably don't want to also carry the additional code
weight of the latter.

The bstack code could do with supporting the same set of possibilities as
my extended tile. I'll take a look at allowing the master area to be
either above or to the left of the stacking area in my tiling code, and
define two layout functions with the common code pulled out to share. (I
really need to update my personal tree to descend from the single dwm.c
in hg tip in any case.)

Cheers,

Chris.



[dwm] [patch] Stack columns patch for dwm-4.4.1

2007-09-09 Thread Chris Webb
Below is a patch for the current release (4.4.1) of dwm which enables
multiple columns in the stacking area. It introduces variables nrows and
ncols with corresponding default values NROWS and NCOLS in
config.h.default, and corresponding setnrows() and setncols() for use in
keybindings.

If nrows == ncols == 0, tile() behaves in the normal manner. When nrows 
0, tile() creates an extra column if adding another window to the current
one would cause it to exceed nrows clients. If ncols  0, the maximum
number of columns created cannot exceed ncols, overriding the nrows
setting. The patch also reintroduces nmaster in a similar way to the
existing nmaster patch, but allows it to be zero to simulate a grid mode.
Where there are not enough windows to fill all the columns evenly, the
extra space is used by the top-most client in the first column.

I'd be interested in any feedback. (I use this 'extended tiling' mode
myself, and so intend to maintain the patch going forward.)

Best wishes,

Chris.


diff -uNrd dwm-4.4.1.orig/config.default.h dwm-4.4.1/config.default.h
--- dwm-4.4.1.orig/config.default.h 2007-08-26 11:53:49.0 +0100
+++ dwm-4.4.1/config.default.h  2007-09-09 16:35:23.0 +0100
@@ -33,6 +33,9 @@
{ ,floating }, \
 };
 #define MWFACT 0.6 /* master width factor [0.1 .. 0.9] */
+#define NMASTER1   /* clients in master area */
+#define NROWS  2   /* clients per column in stacking area 
*/
+#define NCOLS  3   /* maximum number of stacking area 
columns */
 #define SNAP   32  /* snap pixel */
 
 /* key definitions */
@@ -48,6 +51,12 @@
{ MODKEY,   XK_k,   focusprev,  NULL }, 
\
{ MODKEY,   XK_h,   setmwfact,  -0.05 
}, \
{ MODKEY,   XK_l,   setmwfact,  +0.05 
}, \
+   { MODKEY|ShiftMask, XK_j,   setnrows,   -1 }, 
\
+   { MODKEY|ShiftMask, XK_k,   setnrows,   +1 }, 
\
+   { MODKEY|ControlMask,   XK_j,   setncols,   -1 }, 
\
+   { MODKEY|ControlMask,   XK_k,   setncols,   +1 }, 
\
+   { MODKEY|ShiftMask, XK_h,   setnmaster, -1 }, 
\
+   { MODKEY|ShiftMask, XK_l,   setnmaster, +1 }, 
\
{ MODKEY,   XK_m,   togglemax,  NULL }, 
\
{ MODKEY,   XK_Return,  zoom,   NULL }, 
\
{ MODKEY|ShiftMask, XK_space,   togglefloating, NULL }, 
\
diff -uNrd dwm-4.4.1.orig/tile.c dwm-4.4.1/tile.c
--- dwm-4.4.1.orig/tile.c   2007-08-26 11:53:49.0 +0100
+++ dwm-4.4.1/tile.c2007-09-09 16:34:17.0 +0100
@@ -5,10 +5,82 @@
 /* static */
 
 static double mwfact = MWFACT;
+static unsigned int nmaster = NMASTER;
+static unsigned int nrows = NROWS;
+static unsigned int ncols = NCOLS;
 
 /* extern */
 
 void
+setnmaster(const char *arg) {
+   int i;
+
+   if(!isarrange(tile))
+   return;
+   if(!arg)
+   i = NMASTER;
+   else if(arg[0] != '+'  arg[0] != '-')
+   i = atoi(arg);
+   else
+   i = nmaster + atoi(arg);
+
+   if(i  0 || wah = 2 * BORDERPX * i)
+   return;
+   
+   nmaster = i;
+   if(sel)
+   arrange();
+   else
+   drawstatus();
+}
+
+void
+setnrows(const char *arg) {
+   int i;
+
+   if(!isarrange(tile))
+   return;
+   if(!arg)
+   i = NROWS;
+   else if(arg[0] != '+'  arg[0] != '-')
+   i = atoi(arg);
+   else
+   i = nrows + atoi(arg);
+
+   if(i  0 || wah = 2 * BORDERPX * i)
+   return;
+   nrows = i;
+
+   if(sel)
+   arrange();
+   else
+   drawstatus();
+}
+
+void
+setncols(const char *arg) {
+   int i;
+
+   if(!isarrange(tile))
+   return;
+   if(!arg)
+   i = NCOLS;
+   else if(arg[0] != '+'  arg[0] != '-')
+   i = atoi(arg);
+   else
+   i = ncols + atoi(arg);
+
+   if((i  0) || (i = 1  waw / i = 2 * BORDERPX))
+   return;
+   ncols = i;
+
+   if(sel)
+   arrange();
+   else
+   drawstatus();
+}
+
+void
 setmwfact(const char *arg) {
double delta;
 
@@ -32,40 +104,79 @@
 
 void
 tile(void) {
-   unsigned int i, n, nx, ny, nw, nh, mw, th;
+   unsigned int i, n, nx, ny, nw, nh, mw, mh, tw, th, tw1, cols, rows, 
rows1;
Client *c;
 
for(n = 0, c = nexttiled(clients); c; c = nexttiled(c-next))
n++;
 
+   /* calculate correct number of rows */
+   if(ncols  0  n - nmaster  nrows * ncols)
+   rows = (n - nmaster) / ncols + ((n - nmaster) % ncols ? 1 :