Below is a diff that enables cwm to maximize a window in a given direction (left / right / up / down) only.
Only left/right is implemented actually; I want to make sure this isn't completely wrong before writing up the other half (which will be dual of course). The motivating situation for me is that my usual X setup is a vertically maximized xterm in the upper left corner (to write what I am writing) and whatever accompanies it (xdvi, firefox, mupdf, ...) in the rest of the screen. Setting that up is not complicated, but maximizing the other window to the "rest of the screen" means: align its left border to the right border of the xterm, then hold CMS-l until the window enlarges fully to the right. Obviously, the obligate h/j/k/l keys are taken already, so I chose (CM-) the arrows for the default keybindings. In the current implementation of e.g. hmaximize, it is checked whether this actually means full maximization. As there are currently only two parts of full maximization (CLIENT_HMAXIMIZED, CLIENT_VMAXIMIZED) it is done by checking the other one. With four parts of maximization now, I have used a macro (LASTMAX) instead that checks whether this is the last bit that's missing in full maximization. I believe the current [vh]maximizing function should be so altered too. Xinerama considerations: first of all, I only have one monitor, so could please someone with more screens test this? My logic of placing the maximized window is obvious: when left-maximizing, the new left border is the left border of the screen where the current left border is; that is, the leftmost screen which is 'hit' by the current window is where the left-maximization happens. I believe this is the sensible thing. Similarly for right. This differs from the logic currently implemented in the maximizing functions: the screen holding the center of the window is found, and the window is maximized within that screen. I object to this, with the following counterexample in mind: with 3 screens, and a window spanning a little more than the central screen, "maximizing" it actually means shrinking it! This difference in placement logic is what stops me from replacing hmaximize with a call to lmaximize and rmaximize. Comments? Jan Index: calmwm.h =================================================================== RCS file: /cvs/xenocara/app/cwm/calmwm.h,v retrieving revision 1.185 diff -u -p -r1.185 calmwm.h --- calmwm.h 4 Jan 2013 16:30:03 -0000 1.185 +++ calmwm.h 5 Jan 2013 18:52:35 -0000 @@ -148,15 +148,22 @@ struct client_ctx { int xproto; #define CLIENT_HIDDEN 0x0001 #define CLIENT_IGNORE 0x0002 -#define CLIENT_VMAXIMIZED 0x0004 -#define CLIENT_HMAXIMIZED 0x0008 #define CLIENT_FREEZE 0x0010 #define CLIENT_GROUP 0x0020 #define CLIENT_UNGROUP 0x0040 +#define CLIENT_LMAXIMIZED 0x0100 +#define CLIENT_RMAXIMIZED 0x0200 +#define CLIENT_UMAXIMIZED 0x0400 +#define CLIENT_DMAXIMIZED 0x0800 #define CLIENT_HIGHLIGHT (CLIENT_GROUP | CLIENT_UNGROUP) -#define CLIENT_MAXFLAGS (CLIENT_VMAXIMIZED | CLIENT_HMAXIMIZED) +#define CLIENT_HMAXIMIZED (CLIENT_LMAXIMIZED | CLIENT_RMAXIMIZED) +#define CLIENT_VMAXIMIZED (CLIENT_UMAXIMIZED | CLIENT_DMAXIMIZED) #define CLIENT_MAXIMIZED (CLIENT_VMAXIMIZED | CLIENT_HMAXIMIZED) +#define CLIENT_MAXFLAGS (CLIENT_MAXIMIZED) +#define LASTMAX(f, b) (((f | b) & CLIENT_MAXFLAGS) \ + == CLIENT_MAXIMIZED) + int flags; int state; int active; @@ -315,6 +322,7 @@ void client_cycle(struct screen_ctx * void client_cycle_leave(struct screen_ctx *, struct client_ctx *); void client_delete(struct client_ctx *); +void client_dmaximize(struct client_ctx *); void client_draw_border(struct client_ctx *); struct client_ctx *client_find(Window); void client_freeze(struct client_ctx *); @@ -322,6 +330,7 @@ void client_getsizehints(struct clien void client_hide(struct client_ctx *); void client_hmaximize(struct client_ctx *); void client_leave(struct client_ctx *); +void client_lmaximize(struct client_ctx *); void client_lower(struct client_ctx *); void client_map(struct client_ctx *); void client_maximize(struct client_ctx *); @@ -331,11 +340,13 @@ void client_ptrsave(struct client_ctx void client_ptrwarp(struct client_ctx *); void client_raise(struct client_ctx *); void client_resize(struct client_ctx *, int); +void client_rmaximize(struct client_ctx *); void client_send_delete(struct client_ctx *); void client_setactive(struct client_ctx *, int); void client_setname(struct client_ctx *); int client_snapcalc(int, int, int, int, int); void client_transient(struct client_ctx *); +void client_umaximize(struct client_ctx *); void client_unhide(struct client_ctx *); void client_vmaximize(struct client_ctx *); void client_warp(struct client_ctx *); @@ -377,6 +388,8 @@ void kbfunc_client_cycle(struct clien void kbfunc_client_cyclegroup(struct client_ctx *, union arg *); void kbfunc_client_delete(struct client_ctx *, union arg *); +void kbfunc_client_dmaximize(struct client_ctx *, + union arg *); void kbfunc_client_freeze(struct client_ctx *, union arg *); void kbfunc_client_group(struct client_ctx *, union arg *); void kbfunc_client_grouponly(struct client_ctx *, @@ -387,6 +400,8 @@ void kbfunc_client_hide(struct client void kbfunc_client_hmaximize(struct client_ctx *, union arg *); void kbfunc_client_label(struct client_ctx *, union arg *); +void kbfunc_client_lmaximize(struct client_ctx *, + union arg *); void kbfunc_client_lower(struct client_ctx *, union arg *); void kbfunc_client_maximize(struct client_ctx *, union arg *); @@ -396,7 +411,11 @@ void kbfunc_client_nogroup(struct cli union arg *); void kbfunc_client_raise(struct client_ctx *, union arg *); void kbfunc_client_rcycle(struct client_ctx *, union arg *); +void kbfunc_client_rmaximize(struct client_ctx *, + union arg *); void kbfunc_client_search(struct client_ctx *, union arg *); +void kbfunc_client_umaximize(struct client_ctx *, + union arg *); void kbfunc_client_vmaximize(struct client_ctx *, union arg *); void kbfunc_cmdexec(struct client_ctx *, union arg *); Index: client.c =================================================================== RCS file: /cvs/xenocara/app/cwm/client.c,v retrieving revision 1.115 diff -u -p -r1.115 client.c --- client.c 4 Jan 2013 16:30:03 -0000 1.115 +++ client.c 5 Jan 2013 18:52:35 -0000 @@ -320,7 +320,7 @@ client_vmaximize(struct client_ctx *cc) cc->savegeom.h = cc->geom.h; /* if this will make us fully maximized then remove boundary */ - if ((cc->flags & CLIENT_MAXFLAGS) == CLIENT_HMAXIMIZED) { + if (LASTMAX(cc->flags, CLIENT_VMAXIMIZED)) { cc->geom.w += Conf.bwidth * 2; cc->bwidth = 0; } @@ -361,7 +361,7 @@ client_hmaximize(struct client_ctx *cc) cc->savegeom.w = cc->geom.w; /* if this will make us fully maximized then remove boundary */ - if ((cc->flags & CLIENT_MAXFLAGS) == CLIENT_VMAXIMIZED) { + if (LASTMAX(cc->flags, CLIENT_HMAXIMIZED)) { cc->geom.h += cc->bwidth * 2; cc->bwidth = 0; } @@ -377,6 +377,95 @@ client_hmaximize(struct client_ctx *cc) resize: client_resize(cc, 0); +} + +void +client_lmaximize(struct client_ctx *cc) +{ + struct screen_ctx *sc = cc->sc; + struct geom xine; + + if (cc->flags & CLIENT_FREEZE) + return; + + if (cc->flags & CLIENT_LMAXIMIZED) { + cc->geom.x = cc->savegeom.x; + cc->geom.w = cc->savegeom.w; + cc->bwidth = Conf.bwidth; + /* when exiting full maximization, restore boundary */ + if ((cc->flags & CLIENT_MAXFLAGS) == CLIENT_MAXIMIZED) + cc->geom.h -= cc->bwidth * 2; + cc->flags &= ~CLIENT_LMAXIMIZED; + goto resize; + } + + cc->savegeom.x = cc->geom.x; + if ((cc->flags & CLIENT_RMAXIMIZED) == 0) + cc->savegeom.w = cc->geom.w; + + /* if this will make us fully maximized then remove boundary */ + if (LASTMAX(cc->flags, CLIENT_LMAXIMIZED)) { + cc->geom.h += cc->bwidth * 2; + cc->bwidth = 0; + } + + /* left-maximize in the screen(s) where the left boundary is now */ + xine = screen_find_xinerama(sc, cc->geom.x, cc->geom.y); + + cc->geom.w += (cc->geom.x - xine.x) - sc->gap.left; + cc->geom.x = xine.x + sc->gap.left; + cc->flags |= CLIENT_LMAXIMIZED; + +resize: + client_resize(cc, 0); +} + +void +client_rmaximize(struct client_ctx *cc) +{ + struct screen_ctx *sc = cc->sc; + struct geom xine; + + if (cc->flags & CLIENT_FREEZE) + return; + + if (cc->flags & CLIENT_RMAXIMIZED) { + cc->geom.w = cc->savegeom.w; + cc->bwidth = Conf.bwidth; + /* when exiting full maximization, restore boundary */ + if ((cc->flags & CLIENT_MAXFLAGS) == CLIENT_MAXIMIZED) + cc->geom.h -= cc->bwidth * 2; + cc->flags &= ~CLIENT_RMAXIMIZED; + goto resize; + } + + if ((cc->flags & CLIENT_LMAXIMIZED) == 0) + cc->savegeom.w = cc->geom.w; + + /* if this will make us fully maximized then remove boundary */ + if (LASTMAX(cc->flags, CLIENT_RMAXIMIZED)) { + cc->geom.h += cc->bwidth * 2; + cc->bwidth = 0; + } + + /* right-maximize in the screen(s) where the right boundary is now */ + xine = screen_find_xinerama(sc, cc->geom.x + cc->geom.w, cc->geom.y); + cc->geom.w += (xine.x + xine.w) - (cc->geom.x + cc->geom.w) + - (cc->bwidth * 2) - sc->gap.right; + cc->flags |= CLIENT_RMAXIMIZED; + +resize: + client_resize(cc, 0); +} + +void +client_umaximize(struct client_ctx *cc) +{ +} + +void +client_dmaximize(struct client_ctx *cc) +{ } void Index: conf.c =================================================================== RCS file: /cvs/xenocara/app/cwm/conf.c,v retrieving revision 1.120 diff -u -p -r1.120 conf.c --- conf.c 4 Jan 2013 16:27:58 -0000 1.120 +++ conf.c 5 Jan 2013 18:52:36 -0000 @@ -121,6 +121,10 @@ static struct { { "CM-f", "maximize" }, { "CM-equal", "vmaximize" }, { "CMS-equal", "hmaximize" }, + { "CM-Left", "lmaximize" }, + { "CM-Right", "rmaximize" }, + { "CM-Up", "umaximize" }, + { "CM-Down", "dmaximize" }, { "CMS-f", "freeze" }, { "CMS-r", "restart" }, { "CMS-q", "quit" }, @@ -322,6 +326,10 @@ static struct { { "maximize", kbfunc_client_maximize, KBFLAG_NEEDCLIENT, {0} }, { "vmaximize", kbfunc_client_vmaximize, KBFLAG_NEEDCLIENT, {0} }, { "hmaximize", kbfunc_client_hmaximize, KBFLAG_NEEDCLIENT, {0} }, + { "lmaximize", kbfunc_client_lmaximize, KBFLAG_NEEDCLIENT, {0} }, + { "rmaximize", kbfunc_client_rmaximize, KBFLAG_NEEDCLIENT, {0} }, + { "umaximize", kbfunc_client_umaximize, KBFLAG_NEEDCLIENT, {0} }, + { "dmaximize", kbfunc_client_dmaximize, KBFLAG_NEEDCLIENT, {0} }, { "freeze", kbfunc_client_freeze, KBFLAG_NEEDCLIENT, {0} }, { "restart", kbfunc_restart, 0, {0} }, { "quit", kbfunc_quit_wm, 0, {0} }, Index: cwmrc.5 =================================================================== RCS file: /cvs/xenocara/app/cwm/cwmrc.5,v retrieving revision 1.51 diff -u -p -r1.51 cwmrc.5 --- cwmrc.5 17 Dec 2012 02:53:29 -0000 1.51 +++ cwmrc.5 5 Jan 2013 18:52:37 -0000 @@ -169,7 +169,7 @@ This .Dq gap can be used for applications such as .Xr xclock 1 , -where the user may wish to remain visible. +which the user might wish to remain visible. .Pp .It Ic ignore Ar windowname Ignore, and do not warp to, windows with the name @@ -342,6 +342,14 @@ Maximize current window full-screen. Maximize current window vertically. .It hmaximize Maximize current window horizontally. +.It lmaximize +Maximize current window to the left. +.It rmaximize +Maximize current window to the right. +.It umaximize +Maximize current window up. +.It dmaximize +Maximize current window down. .It moveup Move window .Ar moveamount Index: kbfunc.c =================================================================== RCS file: /cvs/xenocara/app/cwm/kbfunc.c,v retrieving revision 1.75 diff -u -p -r1.75 kbfunc.c --- kbfunc.c 4 Jan 2013 16:30:03 -0000 1.75 +++ kbfunc.c 5 Jan 2013 18:52:37 -0000 @@ -462,6 +462,30 @@ kbfunc_client_hmaximize(struct client_ct } void +kbfunc_client_lmaximize(struct client_ctx *cc, union arg *arg) +{ + client_lmaximize(cc); +} + +void +kbfunc_client_rmaximize(struct client_ctx *cc, union arg *arg) +{ + client_rmaximize(cc); +} + +void +kbfunc_client_umaximize(struct client_ctx *cc, union arg *arg) +{ + client_umaximize(cc); +} + +void +kbfunc_client_dmaximize(struct client_ctx *cc, union arg *arg) +{ + client_dmaximize(cc); +} + +void kbfunc_client_freeze(struct client_ctx *cc, union arg *arg) { client_freeze(cc);