fair layout patch

This commit is contained in:
yosh 2023-01-05 12:02:36 -06:00
parent 65b3be249a
commit f97d6ade0c
7 changed files with 370 additions and 1 deletions

View File

@ -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

View File

@ -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 *);

115
client.c
View File

@ -28,6 +28,7 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <math.h>
#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);
}

2
conf.c
View File

@ -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) },

View File

@ -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

View File

@ -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)
{

228
patches/fairlayout.diff Normal file
View File

@ -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 <stdlib.h>
#include <string.h>
#include <unistd.h>
+#include <math.h>
#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)
{