From f97d6ade0cd6eb4e27fb20764c7f319b8771dfbb Mon Sep 17 00:00:00 2001 From: yosh Date: Thu, 5 Jan 2023 12:02:36 -0600 Subject: [PATCH] fair layout patch --- Makefile | 2 +- calmwm.h | 4 + client.c | 115 ++++++++++++++++++++ conf.c | 2 + cwmrc.5 | 8 ++ kbfunc.c | 12 +++ patches/fairlayout.diff | 228 ++++++++++++++++++++++++++++++++++++++++ 7 files changed, 370 insertions(+), 1 deletion(-) create mode 100644 patches/fairlayout.diff diff --git a/Makefile b/Makefile index 1f56cd4..4e295ac 100644 --- a/Makefile +++ b/Makefile @@ -20,7 +20,7 @@ CPPFLAGS+= `${PKG_CONFIG} --cflags x11 xft xrandr` CFLAGS?= -Wall -O2 -g -D_GNU_SOURCE -LDFLAGS+= `${PKG_CONFIG} --libs x11 xft xrandr` +LDFLAGS+= `${PKG_CONFIG} --libs x11 xft xrandr` -lm MANPREFIX?= ${PREFIX}/share/man diff --git a/calmwm.h b/calmwm.h index b3992c3..42ed9a4 100644 --- a/calmwm.h +++ b/calmwm.h @@ -429,6 +429,7 @@ struct client_ctx *client_find(Window); void client_get_sizehints(struct client_ctx *); void client_hide(struct client_ctx *); void client_htile(struct client_ctx *); +void client_hfair(struct client_ctx *); int client_inbound(struct client_ctx *, int, int); struct client_ctx *client_init(Window, struct screen_ctx *); void client_lower(struct client_ctx *); @@ -458,6 +459,7 @@ void client_toggle_vmaximize(struct client_ctx *); void client_transient(struct client_ctx *); void client_urgency(struct client_ctx *); void client_vtile(struct client_ctx *); +void client_vfair(struct client_ctx *); void client_wm_hints(struct client_ctx *); void group_assign(struct group_ctx *, struct client_ctx *); @@ -528,7 +530,9 @@ void kbfunc_client_toggle_maximize(void *, struct cargs *); void kbfunc_client_toggle_hmaximize(void *, struct cargs *); void kbfunc_client_toggle_vmaximize(void *, struct cargs *); void kbfunc_client_htile(void *, struct cargs *); +void kbfunc_client_hfair(void *, struct cargs *); void kbfunc_client_vtile(void *, struct cargs *); +void kbfunc_client_vfair(void *, struct cargs *); void kbfunc_client_cycle(void *, struct cargs *); void kbfunc_client_toggle_group(void *, struct cargs *); void kbfunc_client_movetogroup(void *, struct cargs *); diff --git a/client.c b/client.c index 8fa4f6b..3cafac8 100644 --- a/client.c +++ b/client.c @@ -28,6 +28,7 @@ #include #include #include +#include #include "calmwm.h" @@ -1039,3 +1040,117 @@ client_vtile(struct client_ctx *cc) client_resize(ci, 1); } } + +void +client_vfair(struct client_ctx *cc) +{ + struct client_ctx *ci; + struct screen_ctx *sc = cc->sc; + struct geom area; + int i, n, w, h, rows, cols, rh, t; + + i = n = 0; + area = screen_area(sc, + cc->geom.x + cc->geom.w / 2, + cc->geom.y + cc->geom.h / 2, 1); + + TAILQ_FOREACH(ci, &sc->clientq, entry) { + if (ci->gc != cc->gc) + continue; + if (ci->flags & CLIENT_HIDDEN || + ci->flags & CLIENT_IGNORE || + ci->geom.x < area.x || + ci->geom.x > (area.x + area.w) || + ci->geom.y < area.y || + ci->geom.y > (area.y + area.h)) + continue; + n++; + } + if (n == 0) + return; + + cc->flags &= ~CLIENT_MAXIMIZED; + rows = (n == 2) ? 1 : ceil(sqrt(n)); + cols = ceil((double)n / rows); + w = area.w / cols; + h = area.h / rows; + rh = area.h / (n % rows == 0 ? rows : n % rows); + t = rows * (cols - 1); + + TAILQ_FOREACH(ci, &sc->clientq, entry) { + if (ci->gc != cc->gc) + continue; + if (ci->flags & CLIENT_HIDDEN || + ci->flags & CLIENT_IGNORE || + ci->geom.x < area.x || + ci->geom.x > (area.x + area.w) || + ci->geom.y < area.y || + ci->geom.y > (area.y + area.h)) + continue; + ci->bwidth = Conf.bwidth; + ci->geom.x = area.x + (i / rows) * w; + ci->geom.y = area.y + (i % rows) * (i < t ? h : rh); + ci->geom.w = w - (ci->bwidth * 2); + ci->geom.h = (i < t ? h : rh) - (ci->bwidth * 2); + i++; + client_resize(ci, 1); + } + client_ptr_warp(cc); +} + +void +client_hfair(struct client_ctx *cc) +{ + struct client_ctx *ci; + struct screen_ctx *sc = cc->sc; + struct geom area; + int i, n, w, h, rows, cols, rw, t; + + i = n = 0; + area = screen_area(sc, + cc->geom.x + cc->geom.w / 2, + cc->geom.y + cc->geom.h / 2, 1); + + TAILQ_FOREACH(ci, &sc->clientq, entry) { + if (ci->gc != cc->gc) + continue; + if (ci->flags & CLIENT_HIDDEN || + ci->flags & CLIENT_IGNORE || + ci->geom.x < area.x || + ci->geom.x > (area.x + area.w) || + ci->geom.y < area.y || + ci->geom.y > (area.y + area.h)) + continue; + n++; + } + if (n == 0) + return; + + cc->flags &= ~CLIENT_MAXIMIZED; + cols = (n == 2) ? 1 : ceil(sqrt(n)); + rows = ceil((double)n / cols); + w = area.w / cols; + h = area.h / rows; + rw = area.w / (n % cols == 0 ? cols : n % cols); + t = cols * (rows - 1); + + TAILQ_FOREACH(ci, &sc->clientq, entry) { + if (ci->gc != cc->gc) + continue; + if (ci->flags & CLIENT_HIDDEN || + ci->flags & CLIENT_IGNORE || + ci->geom.x < area.x || + ci->geom.x > (area.x + area.w) || + ci->geom.y < area.y || + ci->geom.y > (area.y + area.h)) + continue; + ci->bwidth = Conf.bwidth; + ci->geom.y = area.y + (i / cols) * h; + ci->geom.x = area.x + (i % cols) * (i < t ? w : rw); + ci->geom.h = h - (ci->bwidth * 2); + ci->geom.w = (i < t ? w : rw) - (ci->bwidth * 2); + i++; + client_resize(ci, 1); + } + client_ptr_warp(cc); +} diff --git a/conf.c b/conf.c index 68bf157..b2f5011 100644 --- a/conf.c +++ b/conf.c @@ -86,6 +86,8 @@ static const struct { { FUNC_CC(window-delete, client_close, 0) }, { FUNC_CC(window-htile, client_htile, 0) }, { FUNC_CC(window-vtile, client_vtile, 0) }, + { FUNC_CC(window-hfair, client_hfair, 0) }, + { FUNC_CC(window-vfair, client_vfair, 0) }, { FUNC_CC(window-stick, client_toggle_sticky, 0) }, { FUNC_CC(window-fullscreen, client_toggle_fullscreen, 0) }, { FUNC_CC(window-maximize, client_toggle_maximize, 0) }, diff --git a/cwmrc.5 b/cwmrc.5 index 7075288..4046a97 100644 --- a/cwmrc.5 +++ b/cwmrc.5 @@ -329,6 +329,14 @@ and resized to .Ar vtile (default half) of the horizontal screen space. Other windows in its group share remaining screen space. +.It window-hfair +Current window is placed at the top left of the screen, and all windows +attempt to occupy the screen space fairly, with remainder windows being +distributed evenly along the bottom. +.It window-vfair +Current window is placed at the top left of the screen, and all windows +attempt to occupy the screen space fairly, with remainder windows being +distributed evenly along the right side. .It window-move Move current window. .It window-resize diff --git a/kbfunc.c b/kbfunc.c index ed1d7cb..bb12595 100644 --- a/kbfunc.c +++ b/kbfunc.c @@ -401,6 +401,18 @@ kbfunc_client_vtile(void *ctx, struct cargs *cargs) client_vtile(ctx); } +void +kbfunc_client_vfair(void *ctx, struct cargs *cargs) +{ + client_vfair(ctx); +} + +void +kbfunc_client_hfair(void *ctx, struct cargs *cargs) +{ + client_hfair(ctx); +} + void kbfunc_client_cycle(void *ctx, struct cargs *cargs) { diff --git a/patches/fairlayout.diff b/patches/fairlayout.diff new file mode 100644 index 0000000..d8f423f --- /dev/null +++ b/patches/fairlayout.diff @@ -0,0 +1,228 @@ +diff --git a/Makefile b/Makefile +index 1f56cd4..4e295ac 100644 +--- a/Makefile ++++ b/Makefile +@@ -20,7 +20,7 @@ CPPFLAGS+= `${PKG_CONFIG} --cflags x11 xft xrandr` + + CFLAGS?= -Wall -O2 -g -D_GNU_SOURCE + +-LDFLAGS+= `${PKG_CONFIG} --libs x11 xft xrandr` ++LDFLAGS+= `${PKG_CONFIG} --libs x11 xft xrandr` -lm + + MANPREFIX?= ${PREFIX}/share/man + +diff --git a/calmwm.h b/calmwm.h +index b3992c3..42ed9a4 100644 +--- a/calmwm.h ++++ b/calmwm.h +@@ -429,6 +429,7 @@ struct client_ctx *client_find(Window); + void client_get_sizehints(struct client_ctx *); + void client_hide(struct client_ctx *); + void client_htile(struct client_ctx *); ++void client_hfair(struct client_ctx *); + int client_inbound(struct client_ctx *, int, int); + struct client_ctx *client_init(Window, struct screen_ctx *); + void client_lower(struct client_ctx *); +@@ -458,6 +459,7 @@ void client_toggle_vmaximize(struct client_ctx *); + void client_transient(struct client_ctx *); + void client_urgency(struct client_ctx *); + void client_vtile(struct client_ctx *); ++void client_vfair(struct client_ctx *); + void client_wm_hints(struct client_ctx *); + + void group_assign(struct group_ctx *, struct client_ctx *); +@@ -528,7 +530,9 @@ void kbfunc_client_toggle_maximize(void *, struct cargs *); + void kbfunc_client_toggle_hmaximize(void *, struct cargs *); + void kbfunc_client_toggle_vmaximize(void *, struct cargs *); + void kbfunc_client_htile(void *, struct cargs *); ++void kbfunc_client_hfair(void *, struct cargs *); + void kbfunc_client_vtile(void *, struct cargs *); ++void kbfunc_client_vfair(void *, struct cargs *); + void kbfunc_client_cycle(void *, struct cargs *); + void kbfunc_client_toggle_group(void *, struct cargs *); + void kbfunc_client_movetogroup(void *, struct cargs *); +diff --git a/client.c b/client.c +index 59bc7b0..eba9a37 100644 +--- a/client.c ++++ b/client.c +@@ -28,6 +28,7 @@ + #include + #include + #include ++#include + + #include "calmwm.h" + +@@ -1047,3 +1048,117 @@ client_vtile(struct client_ctx *cc) + client_resize(ci, 1); + } + } ++ ++void ++client_vfair(struct client_ctx *cc) ++{ ++ struct client_ctx *ci; ++ struct screen_ctx *sc = cc->sc; ++ struct geom area; ++ int i, n, w, h, rows, cols, rh, t; ++ ++ i = n = 0; ++ area = screen_area(sc, ++ cc->geom.x + cc->geom.w / 2, ++ cc->geom.y + cc->geom.h / 2, 1); ++ ++ TAILQ_FOREACH(ci, &sc->clientq, entry) { ++ if (ci->gc != cc->gc) ++ continue; ++ if (ci->flags & CLIENT_HIDDEN || ++ ci->flags & CLIENT_IGNORE || ++ ci->geom.x < area.x || ++ ci->geom.x > (area.x + area.w) || ++ ci->geom.y < area.y || ++ ci->geom.y > (area.y + area.h)) ++ continue; ++ n++; ++ } ++ if (n == 0) ++ return; ++ ++ cc->flags &= ~CLIENT_MAXIMIZED; ++ rows = (n == 2) ? 1 : ceil(sqrt(n)); ++ cols = ceil((double)n / rows); ++ w = area.w / cols; ++ h = area.h / rows; ++ rh = area.h / (n % rows == 0 ? rows : n % rows); ++ t = rows * (cols - 1); ++ ++ TAILQ_FOREACH(ci, &sc->clientq, entry) { ++ if (ci->gc != cc->gc) ++ continue; ++ if (ci->flags & CLIENT_HIDDEN || ++ ci->flags & CLIENT_IGNORE || ++ ci->geom.x < area.x || ++ ci->geom.x > (area.x + area.w) || ++ ci->geom.y < area.y || ++ ci->geom.y > (area.y + area.h)) ++ continue; ++ ci->bwidth = Conf.bwidth; ++ ci->geom.x = area.x + (i / rows) * w; ++ ci->geom.y = area.y + (i % rows) * (i < t ? h : rh); ++ ci->geom.w = w - (ci->bwidth * 2); ++ ci->geom.h = (i < t ? h : rh) - (ci->bwidth * 2); ++ i++; ++ client_resize(ci, 1); ++ } ++ client_ptr_warp(cc); ++} ++ ++void ++client_hfair(struct client_ctx *cc) ++{ ++ struct client_ctx *ci; ++ struct screen_ctx *sc = cc->sc; ++ struct geom area; ++ int i, n, w, h, rows, cols, rw, t; ++ ++ i = n = 0; ++ area = screen_area(sc, ++ cc->geom.x + cc->geom.w / 2, ++ cc->geom.y + cc->geom.h / 2, 1); ++ ++ TAILQ_FOREACH(ci, &sc->clientq, entry) { ++ if (ci->gc != cc->gc) ++ continue; ++ if (ci->flags & CLIENT_HIDDEN || ++ ci->flags & CLIENT_IGNORE || ++ ci->geom.x < area.x || ++ ci->geom.x > (area.x + area.w) || ++ ci->geom.y < area.y || ++ ci->geom.y > (area.y + area.h)) ++ continue; ++ n++; ++ } ++ if (n == 0) ++ return; ++ ++ cc->flags &= ~CLIENT_MAXIMIZED; ++ cols = (n == 2) ? 1 : ceil(sqrt(n)); ++ rows = ceil((double)n / cols); ++ w = area.w / cols; ++ h = area.h / rows; ++ rw = area.w / (n % cols == 0 ? cols : n % cols); ++ t = cols * (rows - 1); ++ ++ TAILQ_FOREACH(ci, &sc->clientq, entry) { ++ if (ci->gc != cc->gc) ++ continue; ++ if (ci->flags & CLIENT_HIDDEN || ++ ci->flags & CLIENT_IGNORE || ++ ci->geom.x < area.x || ++ ci->geom.x > (area.x + area.w) || ++ ci->geom.y < area.y || ++ ci->geom.y > (area.y + area.h)) ++ continue; ++ ci->bwidth = Conf.bwidth; ++ ci->geom.y = area.y + (i / cols) * h; ++ ci->geom.x = area.x + (i % cols) * (i < t ? w : rw); ++ ci->geom.h = h - (ci->bwidth * 2); ++ ci->geom.w = (i < t ? w : rw) - (ci->bwidth * 2); ++ i++; ++ client_resize(ci, 1); ++ } ++ client_ptr_warp(cc); ++} +diff --git a/conf.c b/conf.c +index 7d3ae6e..dbd9ed0 100644 +--- a/conf.c ++++ b/conf.c +@@ -86,6 +86,8 @@ static const struct { + { FUNC_CC(window-delete, client_close, 0) }, + { FUNC_CC(window-htile, client_htile, 0) }, + { FUNC_CC(window-vtile, client_vtile, 0) }, ++ { FUNC_CC(window-hfair, client_hfair, 0) }, ++ { FUNC_CC(window-vfair, client_vfair, 0) }, + { FUNC_CC(window-stick, client_toggle_sticky, 0) }, + { FUNC_CC(window-fullscreen, client_toggle_fullscreen, 0) }, + { FUNC_CC(window-maximize, client_toggle_maximize, 0) }, +diff --git a/cwmrc.5 b/cwmrc.5 +index 7075288..4046a97 100644 +--- a/cwmrc.5 ++++ b/cwmrc.5 +@@ -329,6 +329,14 @@ and resized to + .Ar vtile + (default half) of the horizontal screen space. + Other windows in its group share remaining screen space. ++.It window-hfair ++Current window is placed at the top left of the screen, and all windows ++attempt to occupy the screen space fairly, with remainder windows being ++distributed evenly along the bottom. ++.It window-vfair ++Current window is placed at the top left of the screen, and all windows ++attempt to occupy the screen space fairly, with remainder windows being ++distributed evenly along the right side. + .It window-move + Move current window. + .It window-resize +diff --git a/kbfunc.c b/kbfunc.c +index ed1d7cb..bb12595 100644 +--- a/kbfunc.c ++++ b/kbfunc.c +@@ -401,6 +401,18 @@ kbfunc_client_vtile(void *ctx, struct cargs *cargs) + client_vtile(ctx); + } + ++void ++kbfunc_client_vfair(void *ctx, struct cargs *cargs) ++{ ++ client_vfair(ctx); ++} ++ ++void ++kbfunc_client_hfair(void *ctx, struct cargs *cargs) ++{ ++ client_hfair(ctx); ++} ++ + void + kbfunc_client_cycle(void *ctx, struct cargs *cargs) + {