tiling is only useful for text applications for that i use tmux
On Sun, Jun 3, 2012 at 12:37 PM, Alexander Polakov <[email protected]> wrote: > I'd like to start a discussion about adding tiling to cwm with > these two diffs. > > First diff adds a helper function to get the area of the screen. > I don't have a second screen here, so no idea if it works with > Xinerama (please test!). > > Index: calmwm.h > =================================================================== > RCS file: /cvs/xenocara/app/cwm/calmwm.h,v > retrieving revision 1.146 > diff -u -r1.146 calmwm.h > --- calmwm.h 16 May 2012 01:17:14 -0000 1.146 > +++ calmwm.h 2 Jun 2012 15:16:26 -0000 > @@ -103,6 +103,13 @@ > int right; > }; > > +struct rect { > + int x; > + int y; > + int width; > + int height; > +}; > + > struct winname { > TAILQ_ENTRY(winname) entry; > char *name; > @@ -118,12 +125,7 @@ > XSizeHints *size; > Colormap cmap; > u_int bwidth; /* border width */ > - struct { > - int x; /* x position */ > - int y; /* y position */ > - int width; /* width */ > - int height;/* height */ > - } geom, savegeom; > + struct rect geom, savegeom; > struct { > int basew; /* desired width */ > int baseh; /* desired height */ > @@ -361,6 +363,7 @@ > XineramaScreenInfo *screen_find_xinerama(struct screen_ctx *, int, int); > struct screen_ctx *screen_fromroot(Window); > void screen_init_xinerama(struct screen_ctx *); > +struct rect *screen_get_area(struct screen_ctx *, int); > void screen_update_geometry(struct screen_ctx *, int, > int); > void screen_updatestackingorder(struct screen_ctx *); > > Index: client.c > =================================================================== > RCS file: /cvs/xenocara/app/cwm/client.c,v > retrieving revision 1.94 > diff -u -r1.94 client.c > --- client.c 16 May 2012 01:09:17 -0000 1.94 > +++ client.c 2 Jun 2012 15:16:27 -0000 > @@ -277,8 +277,7 @@ > client_maximize(struct client_ctx *cc) > { > struct screen_ctx *sc = cc->sc; > - int xmax = sc->xmax, ymax = sc->ymax; > - int x_org = 0, y_org = 0; > + struct rect *sa; > > if (cc->flags & CLIENT_FREEZE) > return; > @@ -300,28 +299,9 @@ > cc->savegeom.x = cc->geom.x; > } > > - if (HasXinerama) { > - XineramaScreenInfo *xine; > - /* > - * pick screen that the middle of the window is on. > - * that's probably more fair than if just the origin of > - * a window is poking over a boundary > - */ > - xine = screen_find_xinerama(sc, > - cc->geom.x + cc->geom.width / 2, > - cc->geom.y + cc->geom.height / 2); > - if (xine == NULL) > - goto calc; > - x_org = xine->x_org; > - y_org = xine->y_org; > - xmax = xine->width; > - ymax = xine->height; > - } > -calc: > - cc->geom.x = x_org + sc->gap.left; > - cc->geom.y = y_org + sc->gap.top; > - cc->geom.height = ymax - (sc->gap.top + sc->gap.bottom); > - cc->geom.width = xmax - (sc->gap.left + sc->gap.right); > + sa = screen_get_area(sc, 1); > + memcpy(&cc->geom, sa, sizeof(*sa)); > + free(sa); > cc->bwidth = 0; > cc->flags |= CLIENT_MAXIMIZED; > > @@ -333,7 +313,7 @@ > client_vertmaximize(struct client_ctx *cc) > { > struct screen_ctx *sc = cc->sc; > - int y_org = 0, ymax = sc->ymax; > + struct rect *sa; > > if (cc->flags & CLIENT_FREEZE) > return; > @@ -357,21 +337,11 @@ > cc->bwidth = 0; > } > > - if (HasXinerama) { > - XineramaScreenInfo *xine; > - xine = screen_find_xinerama(sc, > - cc->geom.x + cc->geom.width / 2, > - cc->geom.y + cc->geom.height / 2); > - if (xine == NULL) > - goto calc; > - y_org = xine->y_org; > - ymax = xine->height; > - } > -calc: > - cc->geom.y = y_org + sc->gap.top; > - cc->geom.height = ymax - (cc->bwidth * 2) - (sc->gap.top + > - sc->gap.bottom); > + sa = screen_get_area(sc, 1); > + cc->geom.y = sa->y; > + cc->geom.height = sa->height - (cc->bwidth * 2); > cc->flags |= CLIENT_VMAXIMIZED; > + free(sa); > > resize: > client_resize(cc); > @@ -381,7 +351,7 @@ > client_horizmaximize(struct client_ctx *cc) > { > struct screen_ctx *sc = cc->sc; > - int x_org = 0, xmax = sc->xmax; > + struct rect *sa; > > if (cc->flags & CLIENT_FREEZE) > return; > @@ -405,21 +375,11 @@ > cc->bwidth = 0; > } > > - if (HasXinerama) { > - XineramaScreenInfo *xine; > - xine = screen_find_xinerama(sc, > - cc->geom.x + cc->geom.width / 2, > - cc->geom.y + cc->geom.height / 2); > - if (xine == NULL) > - goto calc; > - x_org = xine->x_org; > - xmax = xine->width; > - } > -calc: > - cc->geom.x = x_org + sc->gap.left; > - cc->geom.width = xmax - (cc->bwidth * 2) - (sc->gap.left + > - sc->gap.right); > + sa = screen_get_area(sc, 1); > + cc->geom.x = sa->x; > + cc->geom.width = sa->width - (cc->bwidth * 2); > cc->flags |= CLIENT_HMAXIMIZED; > + free(sa); > > resize: > client_resize(cc); > Index: screen.c > =================================================================== > RCS file: /cvs/xenocara/app/cwm/screen.c,v > retrieving revision 1.28 > diff -u -r1.28 screen.c > --- screen.c 11 May 2011 13:53:51 -0000 1.28 > +++ screen.c 2 Jun 2012 15:16:27 -0000 > @@ -131,3 +131,34 @@ > XA_CARDINAL, 32, PropModeReplace, > (unsigned char *)workareas, CALMWM_NGROUPS * 4); > } > + > +struct rect* > +screen_get_area(struct screen_ctx *sc, int gap) > +{ > + int px, py; > + struct rect *r; > + > + r = calloc(1, sizeof(*r)); > + r->width = sc->xmax; > + r->height = sc->ymax; > + > + if (HasXinerama) { > + XineramaScreenInfo *xine; > + xu_ptr_getpos(sc->rootwin, &px, &py); > + xine = screen_find_xinerama(sc, px, py); > + if (xine == NULL) > + goto calc; > + r->x = xine->x_org; > + r->width = xine->width; > + r->y = xine->y_org; > + r->height = xine->height; > + } > +calc: > + if (gap) { > + r->x += sc->gap.left; > + r->y += sc->gap.top; > + r->width -= sc->gap.left + sc->gap.right; > + r->height -= sc->gap.top + sc->gap.bottom; > + } > + return r; > +} > > > This diff adds support support for "horizontal tiling" (a la dwm's > "bottom stack layout"). You have one "master" in a group, you set > its height as usual (and it doesn't change) and every other window > in the same group is resized to fit into the screen. The layout is > not dynamic, which means that new windows are *not* automatically > tiled. You have to press htile hotkey to tile them. > > It looks like this: > ___________________ > | | > | master | > | | > ------------------- > | 1 | 2 | 3 | > |_____|_____|_____| > > This layout fits all my tiling needs for now, but I anticipate > requests to add "right stack layout" by people with wide-screen > monitors. It would be easy, but at first I'd like to know, do we > want tiling in cwm? Do we want it done this way, or, maybe, > dwm-way? Or some other way? > > diff --git a/Makefile b/Makefile > index a6c5ea8..e7543d6 100644 > --- a/Makefile > +++ b/Makefile > @@ -6,7 +6,7 @@ PROG= cwm > > SRCS= calmwm.c screen.c xmalloc.c client.c menu.c \ > search.c util.c xutil.c conf.c xevents.c group.c \ > - kbfunc.c mousefunc.c font.c parse.y > + kbfunc.c mousefunc.c font.c tile.c parse.y > > CPPFLAGS+= -I${X11BASE}/include -I${X11BASE}/include/freetype2 > -I${.CURDIR} > > diff --git a/calmwm.h b/calmwm.h > index 30df5e6..1ff4a77 100644 > --- a/calmwm.h > +++ b/calmwm.h > @@ -406,6 +406,7 @@ void kbfunc_quit_wm(struct > client_ctx *, union arg *); > void kbfunc_reload(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 *); > @@ -450,6 +451,8 @@ void font_init(struct screen_ctx > *, const char *); > int font_width(struct screen_ctx *, const char *, int); > XftFont *font_make(struct screen_ctx *, const char *); > > +void tile_horiz(struct client_ctx *cc); > + > void xev_loop(void); > > void xu_btn_grab(Window, int, u_int); > diff --git a/conf.c b/conf.c > index 60e49ca..fee764b 100644 > --- a/conf.c > +++ b/conf.c > @@ -422,6 +422,7 @@ 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 = 0 } }, > }; > > /* > diff --git a/kbfunc.c b/kbfunc.c > index 224b9af..577dbc8 100644 > --- a/kbfunc.c > +++ b/kbfunc.c > @@ -502,3 +502,9 @@ kbfunc_reload(struct client_ctx *cc, union arg *arg) > { > conf_reload(&Conf); > } > + > +void > +kbfunc_tile(struct client_ctx *cc, union arg *arg) > +{ > + tile_horiz(cc); > +} > diff --git a/tile.c b/tile.c > new file mode 100644 > index 0000000..aef94a9 > --- /dev/null > +++ b/tile.c > @@ -0,0 +1,73 @@ > +/* > + * calmwm - the calm window manager > + * > + * Copyright (c) 2004 Marius Aamodt Eriksen <[email protected]> > + * > + * Permission to use, copy, modify, and distribute this software for any > + * purpose with or without fee is hereby granted, provided that the above > + * copyright notice and this permission notice appear in all copies. > + * > + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES > + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF > + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR > + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES > + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN > + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF > + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. > + * > + * $OpenBSD$ > + */ > + > +#include <sys/param.h> > +#include <sys/queue.h> > + > +#include "calmwm.h" > + > +void > +tile_horiz(struct client_ctx *cc) > +{ > + struct client_ctx *ci; > + struct group_ctx *gc = cc->group; > + struct screen_ctx *sc = cc->sc; > + struct rect *sa; > + 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; > + > + sa = screen_get_area(sc, 1); > + cc->geom.x = sa->x; > + cc->geom.y = sa->y; > + cc->geom.width = sa->width - 2*cc->bwidth; > + client_resize(cc); > + client_ptrwarp(cc); > + > + mh = cc->geom.height + 2*cc->bwidth; > + x = sa->x; > + w = sa->width/n; > + h = sa->height - mh; > + TAILQ_FOREACH(ci, &gc->clients, group_entry) { > + if (ci->flags & CLIENT_HIDDEN || > + ci->flags & CLIENT_IGNORE || (ci == cc)) > + continue; > + ci->geom.y = sa->y + mh; > + ci->geom.x = x; > + ci->geom.height = h - 2*ci->bwidth; > + ci->geom.width = w - 2*ci->bwidth; > + if (i+1 == n) > + ci->geom.width = sa->x + sa->width - ci->geom.x - > 2*ci->bwidth; > + x += w; > + client_resize(ci); > + i++; > + } > +}
