diff --git a/calmwm.h b/calmwm.h index bbc96b2..f85d37a 100644 --- a/calmwm.h +++ b/calmwm.h @@ -88,6 +88,10 @@ size_t strlcat(char *, const char *, size_t); #define ARG_CHAR 0x0001 #define ARG_INT 0x0002 + +#define CWM_TILE_HORIZ 0x0001 +#define CWM_TILE_VERT 0x0002 + union arg { char *c; int i; @@ -333,6 +337,7 @@ void client_freeze(struct client_ctx *); void client_getsizehints(struct client_ctx *); void client_hide(struct client_ctx *); void client_hmaximize(struct client_ctx *); +void client_htile(struct client_ctx *); void client_leave(struct client_ctx *); void client_lower(struct client_ctx *); void client_map(struct client_ctx *); @@ -350,6 +355,7 @@ int client_snapcalc(int, int, int, int, int); void client_transient(struct client_ctx *); void client_unhide(struct client_ctx *); void client_vmaximize(struct client_ctx *); +void client_vtile(struct client_ctx *); void client_warp(struct client_ctx *); void group_alltoggle(struct screen_ctx *); @@ -420,6 +426,7 @@ void kbfunc_quit_wm(struct client_ctx *, union arg *); void kbfunc_restart(struct client_ctx *, union arg *); void kbfunc_ssh(struct client_ctx *, union arg *); void kbfunc_term(struct client_ctx *, union arg *); +void kbfunc_tile(struct client_ctx *, union arg *); void mousefunc_menu_cmd(struct client_ctx *, void *); void mousefunc_menu_group(struct client_ctx *, void *); diff --git a/client.c b/client.c index a72ecfb..59b9fe9 100644 --- a/client.c +++ b/client.c @@ -286,10 +286,7 @@ client_maximize(struct client_ctx *cc) cc->geom.x + cc->geom.w / 2, cc->geom.y + cc->geom.h / 2); - cc->geom.x = xine.x + sc->gap.left; - cc->geom.y = xine.y + sc->gap.top; - cc->geom.h = xine.h - (sc->gap.top + sc->gap.bottom); - cc->geom.w = xine.w - (sc->gap.left + sc->gap.right); + cc->geom = xine; cc->bwidth = 0; cc->flags |= CLIENT_MAXIMIZED; @@ -329,9 +326,8 @@ client_vmaximize(struct client_ctx *cc) cc->geom.x + cc->geom.w / 2, cc->geom.y + cc->geom.h / 2); - cc->geom.y = xine.y + sc->gap.top; - cc->geom.h = xine.h - (cc->bwidth * 2) - (sc->gap.top + - sc->gap.bottom); + cc->geom.y = xine.y; + cc->geom.h = xine.h - (cc->bwidth * 2); cc->flags |= CLIENT_VMAXIMIZED; resize: @@ -370,9 +366,8 @@ client_hmaximize(struct client_ctx *cc) cc->geom.x + cc->geom.w / 2, cc->geom.y + cc->geom.h / 2); - cc->geom.x = xine.x + sc->gap.left; - cc->geom.w = xine.w - (cc->bwidth * 2) - (sc->gap.left + - sc->gap.right); + cc->geom.x = xine.x; + cc->geom.w = xine.w - (cc->bwidth * 2); cc->flags |= CLIENT_HMAXIMIZED; resize: @@ -660,6 +655,8 @@ client_placecalc(struct client_ctx *cc) xu_ptr_getpos(sc->rootwin, &xmouse, &ymouse); xine = screen_find_xinerama(sc, xmouse, ymouse); + xine.w += xine.x; + xine.h += xine.y; xmouse = MAX(xmouse, xine.x) - cc->geom.w / 2; ymouse = MAX(ymouse, xine.y) - cc->geom.h / 2; @@ -670,22 +667,16 @@ client_placecalc(struct client_ctx *cc) yslack = xine.h - cc->geom.h - cc->bwidth * 2; if (xslack >= xine.x) { - cc->geom.x = MAX(MIN(xmouse, xslack), - xine.x + sc->gap.left); - if (cc->geom.x > (xslack - sc->gap.right)) - cc->geom.x -= sc->gap.right; + cc->geom.x = MAX(MIN(xmouse, xslack), xine.x); } else { - cc->geom.x = xine.x + sc->gap.left; - cc->geom.w = xine.w - sc->gap.left; + cc->geom.x = xine.x; + cc->geom.w = xine.w; } if (yslack >= xine.y) { - cc->geom.y = MAX(MIN(ymouse, yslack), - xine.y + sc->gap.top); - if (cc->geom.y > (yslack - sc->gap.bottom)) - cc->geom.y -= sc->gap.bottom; + cc->geom.y = MAX(MIN(ymouse, yslack), xine.y); } else { - cc->geom.y = xine.y + sc->gap.top; - cc->geom.h = xine.h - sc->gap.top; + cc->geom.y = xine.y; + cc->geom.h = xine.h; } } } @@ -875,3 +866,121 @@ client_snapcalc(int n0, int n1, int e0, int e1, int snapdist) else return (0); } + +void +client_htile(struct client_ctx *cc) +{ + struct client_ctx *ci; + struct group_ctx *gc = cc->group; + struct screen_ctx *sc = cc->sc; + struct geom xine; + int i, n, mh, x, h, w; + + if (!gc) + return; + i = n = 0; + + TAILQ_FOREACH(ci, &gc->clients, group_entry) { + if (ci->flags & CLIENT_HIDDEN || + ci->flags & CLIENT_IGNORE || (ci == cc)) + continue; + n++; + } + if (n == 0) + return; + + xine = screen_find_xinerama(sc, + cc->geom.x + cc->geom.w / 2, + cc->geom.y + cc->geom.h / 2); + + if (cc->flags & CLIENT_VMAXIMIZED || + cc->geom.h + (cc->bwidth * 2) >= xine.h) + return; + + cc->flags &= ~CLIENT_HMAXIMIZED; + cc->geom.x = xine.x; + cc->geom.y = xine.y; + cc->geom.w = xine.w - (cc->bwidth * 2); + client_resize(cc, 1); + client_ptrwarp(cc); + + mh = cc->geom.h + (cc->bwidth * 2); + x = xine.x; + w = xine.w / n; + h = xine.h - mh; + TAILQ_FOREACH(ci, &gc->clients, group_entry) { + if (ci->flags & CLIENT_HIDDEN || + ci->flags & CLIENT_IGNORE || (ci == cc)) + continue; + ci->bwidth = Conf.bwidth; + ci->geom.y = xine.y + mh; + ci->geom.x = x; + ci->geom.h = h - (ci->bwidth * 2); + ci->geom.w = w - (ci->bwidth * 2); + if (i + 1 == n) + ci->geom.w = xine.x + xine.w - + ci->geom.x - (ci->bwidth * 2); + x += w; + client_resize(ci, 1); + i++; + } +} + +void +client_vtile(struct client_ctx *cc) +{ + struct client_ctx *ci; + struct group_ctx *gc = cc->group; + struct screen_ctx *sc = cc->sc; + struct geom xine; + int i, n, mw, y, h, w; + + if (!gc) + return; + i = n = 0; + + TAILQ_FOREACH(ci, &gc->clients, group_entry) { + if (ci->flags & CLIENT_HIDDEN || + ci->flags & CLIENT_IGNORE || (ci == cc)) + continue; + n++; + } + if (n == 0) + return; + + xine = screen_find_xinerama(sc, + cc->geom.x + cc->geom.w / 2, + cc->geom.y + cc->geom.h / 2); + + if (cc->flags & CLIENT_HMAXIMIZED || + cc->geom.w + (cc->bwidth * 2) >= xine.w) + return; + + cc->flags &= ~CLIENT_VMAXIMIZED; + cc->geom.x = xine.x; + cc->geom.y = xine.y; + cc->geom.h = xine.h - (cc->bwidth * 2); + client_resize(cc, 1); + client_ptrwarp(cc); + + mw = cc->geom.w + (cc->bwidth * 2); + y = xine.y; + h = xine.h / n; + w = xine.w - mw; + TAILQ_FOREACH(ci, &gc->clients, group_entry) { + if (ci->flags & CLIENT_HIDDEN || + ci->flags & CLIENT_IGNORE || (ci == cc)) + continue; + ci->bwidth = Conf.bwidth; + ci->geom.y = y; + ci->geom.x = xine.x + mw; + ci->geom.h = h - (ci->bwidth * 2); + ci->geom.w = w - (ci->bwidth * 2); + if (i + 1 == n) + ci->geom.h = xine.y + xine.h - + ci->geom.y - (ci->bwidth * 2); + y += h; + client_resize(ci, 1); + i++; + } +} diff --git a/conf.c b/conf.c index 17c10b9..342fd6a 100644 --- a/conf.c +++ b/conf.c @@ -375,6 +375,10 @@ static struct { {.i = (CWM_LEFT|CWM_PTRMOVE|CWM_BIGMOVE)} }, { "bigptrmoveright", kbfunc_moveresize, 0, {.i = (CWM_RIGHT|CWM_PTRMOVE|CWM_BIGMOVE)} }, + { "htile", kbfunc_tile, KBFLAG_NEEDCLIENT, + {.i = CWM_TILE_HORIZ } }, + { "vtile", kbfunc_tile, KBFLAG_NEEDCLIENT, + {.i = CWM_TILE_VERT } }, }; /* diff --git a/cwmrc.5 b/cwmrc.5 index c8ea841..b475d5e 100644 --- a/cwmrc.5 +++ b/cwmrc.5 @@ -14,7 +14,7 @@ .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" -.Dd $Mdocdate: November 29 2012 $ +.Dd $Mdocdate: December 17 2012 $ .Dt CWMRC 5 .Os .Sh NAME @@ -438,6 +438,12 @@ pixels right. Move pointer 10 times .Ar moveamount pixels left. +.It htile +Current window is placed at the top of the screen and maximized +horizontally, other windows in its group share remaining screen space. +.It vtile +Current window is placed on the left of the screen and maximized +vertically, other windows in its group share remaining screen space. .El .Sh MOUSEBIND COMMAND LIST .Bl -tag -width 18n -compact diff --git a/group.c b/group.c index 8b8823c..e471d63 100644 --- a/group.c +++ b/group.c @@ -160,7 +160,7 @@ group_init(struct screen_ctx *sc) xu_ewmh_net_showing_desktop(sc); xu_ewmh_net_virtual_roots(sc); - group_setactive(sc, 0); + group_setactive(sc, 1); } void @@ -269,8 +269,12 @@ group_hidetoggle(struct screen_ctx *sc, int idx) if (gc->hidden) group_show(sc, gc); - else + else { group_hide(sc, gc); + /* make clients stick to empty group */ + if (TAILQ_EMPTY(&gc->clients)) + group_setactive(sc, idx); + } } void diff --git a/kbfunc.c b/kbfunc.c index eda9a39..473d1de 100644 --- a/kbfunc.c +++ b/kbfunc.c @@ -479,3 +479,16 @@ kbfunc_restart(struct client_ctx *cc, union arg *arg) (void)setsid(); (void)execvp(cwm_argv[0], cwm_argv); } + +void +kbfunc_tile(struct client_ctx *cc, union arg *arg) +{ + switch (arg->i) { + case CWM_TILE_HORIZ: + client_htile(cc); + break; + case CWM_TILE_VERT: + client_vtile(cc); + break; + } +} diff --git a/menu.c b/menu.c index 9f152fb..5a1c601 100644 --- a/menu.c +++ b/menu.c @@ -394,6 +394,8 @@ menu_draw(struct screen_ctx *sc, struct menu_ctx *mc, struct menu_q *menuq, } xine = screen_find_xinerama(sc, mc->x, mc->y); + xine.w += xine.x; + xine.h += xine.y; xsave = mc->x; ysave = mc->y; diff --git a/screen.c b/screen.c index 5f7af56..f63032e 100644 --- a/screen.c +++ b/screen.c @@ -132,7 +132,7 @@ screen_find_xinerama(struct screen_ctx *sc, int x, int y) struct geom geom; int i; - geom = sc->view; + geom = sc->work; if (sc->xinerama == NULL) return (geom); @@ -141,10 +141,10 @@ screen_find_xinerama(struct screen_ctx *sc, int x, int y) info = &sc->xinerama[i]; if (x >= info->x_org && x < info->x_org + info->width && y >= info->y_org && y < info->y_org + info->height) { - geom.x = info->x_org; - geom.y = info->y_org; - geom.w = info->width; - geom.h = info->height; + geom.x = info->x_org + sc->gap.left; + geom.y = info->y_org + sc->gap.top; + geom.w = info->width - (sc->gap.left + sc->gap.right); + geom.h = info->height - (sc->gap.top + sc->gap.bottom); break; } }