[dwm] not a patch: spirals and stacking

From: Robert Figura <nc-figuraro_AT_netcologne.de>
Date: Fri, 27 Jul 2007 14:26:03 +0200

Hi,

i was wondering why there are so many stacking layout patches. After
looking into them i came to the conclusion that the cause for this is
that a stacking utility function is badly missing in dwm:

typedef enum Dir { L2R = 0, B2T = 1, R2L = 2, T2B = 3 } Dir;
static void stacktile( Client *c, Dir dir, unsigned *fx, unsigned *fy,
                       unsigned *fw, unsigned *fh, unsigned s ) {
    switch ( dir ) {
    case L2R:
        resize( c, *fx, *fy, s - 2 * c->border, *fh - 2 * c->border, False );
        *fw -= s;
        *fx += s;
        break;
    case T2B:
        resize( c, *fx, *fy, *fw - 2 * c->border, s - 2 * c->border, False );
        *fh -= s;
        *fy += s;
        break;
    case R2L:
        resize( c, *fx + *fw - s, *fy, s - 2 * c->border, *fh - 2 * c->border, False );
        *fw -= s;
        break;
    case B2T:
        resize( c, *fx, *fy + *fh - s, *fw - 2 * c->border, s - 2 * c->border, False );
        *fh -= s;
        break;
    }
}

Of course, the SLOC count of this function could be reduced by some
clever techniques but the readability would suffer so i refrained.

With such a beast the fibonacci spiral tiling becomes an easy exercise:

static void
fibtile( void ) {
    unsigned int i, n;
    unsigned int fx = wax, fy = way, fw = waw, fh = wah;

    unsigned int mw = waw * masterw / 1000;
    unsigned int mh = wah / nmaster;
    fx += mw;
    fw -= mw;
    
    Client *c;
    for ( n = 0, c = nexttiled( clients ); c; c = nexttiled( c->next ) )
        ++n;

    if ( n <= nmaster )
        mw = waw;
    
    for ( i = 0, c = clients; c; c = c->next )
        if ( isvisible( c ) ) {
            unban( c );
            if(c->isfloating)
                continue;

            if ( i+1 < nmaster )
                resize( c, wax, way + i*mh, mw - 2 * c->border, mh - 2 * c->border, False );
            else if ( i < nmaster )
                resize( c, wax, way + i*mh, mw - 2 * c->border, mh + wah % nmaster - 2 * c->border, False );
            else if ( i+1 == n )
                resize( c, fx, fy, fw - 2 * c->border, fh - 2 * c->border, False );
            else
                stacktile( c, (i-nmaster+1)&3, &fx, &fy, &fw, &fh, ((i-nmaster+1)&1?fh:fw) * masterw / 1000 );

            ++i;
        }
        else
            ban( c );

    focus(NULL);
    restack();
    
}

As you may have noticed, the actual spiral code is basically a single line.
For those who want to try the code, i suggest this symbol in config.h:

#define LAYOUTS \
static Layout layout[] = { \
        { "\\_9", fibtile }, \
};

BTW: Why do incmasterw() and incnmaster() insist on operating in tile mode
only? If the purpose is to avoid non-feedback situations it would still be
better to exclude the cases where it won't work instead.

Happy hacking

-- 
Robert Figura
Received on Fri Jul 27 2007 - 14:35:04 UTC

This archive was generated by hypermail 2.2.0 : Sun Jul 13 2008 - 14:47:07 UTC