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++;
> +       }
> +}

Reply via email to