diff options
| author | Lukasz Kasprzak <lukasz@arcofasiagroup.com> | 2026-08-21 10:16:51 +0200 |
|---|---|---|
| committer | Lukasz Kasprzak <lukasz@arcofasiagroup.com> | 2026-08-21 10:16:51 +0200 |
| commit | 69add3767988d0dfc6ecac37405cfb10abe8dbb7 (patch) | |
| tree | 8154e3f62a0415e7c99880c24a1f1a56665c143c | |
| parent | 31db51d7fb782c8e79bf1df067dadc1a8be63255 (diff) | |
| download | colitur-x-69add3767988d0dfc6ecac37405cfb10abe8dbb7.tar.gz colitur-x-69add3767988d0dfc6ecac37405cfb10abe8dbb7.zip | |
feat(colitur-x): fill the window instead of a fixed grid
Cell size is now computed from the window -- width divided seven ways,
height six -- and the number of lines a feast name gets is whatever fits
the resulting cell. config.h holds minimums rather than sizes.
Under a tiling window manager the calendar now uses its whole tile. It
previously drew a fixed 196x116 grid and left the rest of the tile black,
which is what every screenshot of it has shown.
The size hint is now PREFERRED plus MINIMUM, never fixed. Pinning it
fought the WM, which ignored it anyway, and stopped the grid using a
larger tile.
Added -g WxH, the same flag st takes, mainly because it makes the reflow
testable: verified at 1365x687 (two name lines) and 1852x1024 (three).
| -rw-r--r-- | README.md | 7 | ||||
| -rwxr-xr-x | colitur-x | bin | 27032 -> 27120 bytes | |||
| -rw-r--r-- | colitur-x.c | 39 | ||||
| -rw-r--r-- | config.h | 31 |
4 files changed, 59 insertions, 18 deletions
@@ -14,8 +14,15 @@ presentation choice and belongs in a viewer: colitur's own kernel is pure and deliberately never asks what day it is, which is what lets it be tested to the year 9999. + colitur-x -g 1200x820 < day.csv # preferred size, if the WM allows CX_DUMP=/tmp/f.ppm colitur-x < day.csv # write one frame, then exit +The grid **fills whatever size it is given**: cell width is the window +divided seven ways, cell height six ways, and the number of lines a feast +name gets is whatever fits. Under a tiling window manager it therefore uses +its whole tile rather than sitting in a corner of one, and resizing reflows +instead of clipping. `config.h` sets minimums, not sizes. + It reads CSV on **stdin** and nothing else, so the shell decides what it shows. One month: diff --git a/colitur-x.c b/colitur-x.c index 5307c24..dffbbe6 100644 --- a/colitur-x.c +++ b/colitur-x.c @@ -198,6 +198,14 @@ static void redraw(void) } fill(col_bg, 0, 0, wa.width, wa.height); + /* Cells are sized from the window, not from a constant, so the grid + fills its tile. Six rows is the most a month can need: 31 days + starting on a Saturday spans six Sunday-started weeks. */ + int CELL_W = (wa.width - 2 * PAD) / 7; + int CELL_H = (wa.height - HEAD_H - DETAIL_H) / 6; + if (CELL_W < CELL_W_MIN) CELL_W = CELL_W_MIN; + if (CELL_H < CELL_H_MIN) CELL_H = CELL_H_MIN; + XftColor head, detail, sel_dark, sel_light, grid; alloc(col_head, &head); alloc(col_detail, &detail); alloc(col_sel_dark, &sel_dark); alloc(col_sel_light, &sel_light); @@ -256,8 +264,11 @@ static void redraw(void) character count, so it is right for any font in config.h. */ const char *nm = rows[i].f[6]; int avail = CELL_W - 12, ty = y + bigh + 8 + fnt->ascent; + int room = (CELL_H - 2 - (bigh + 8)) / lh; /* lines that fit */ + if (room > NAME_LINES_MAX) room = NAME_LINES_MAX; + if (room < 1) room = 1; const char *p = nm; - for (int ln = 0; ln < NAME_LINES && *p; ln++) { + for (int ln = 0; ln < room && *p; ln++) { size_t take = strlen(p), best = 0; XGlyphInfo gi; for (size_t k = 1; k <= take; k++) { @@ -298,8 +309,20 @@ static void redraw(void) } } -int main(void) +static void usage(void) { + fputs("usage: colitur-x [-g WxH] < calendar.csv\n", stderr); + exit(2); +} + +int main(int argc, char **argv) +{ + int w = WIN_W, h = WIN_H; + for (int i = 1; i < argc; i++) { + if (!strcmp(argv[i], "-g") && i + 1 < argc) { + if (sscanf(argv[++i], "%dx%d", &w, &h) != 2) usage(); + } else usage(); + } load(); if (!nrows) { fputs("colitur-x: no rows on stdin\n", stderr); return 2; } select_today(); @@ -309,17 +332,19 @@ int main(void) vis = DefaultVisual(dpy, scr); cmap = DefaultColormap(dpy, scr); - int w = PAD*2 + 7*CELL_W, h = HEAD_H + 6*CELL_H + DETAIL_H; win = XCreateSimpleWindow(dpy, RootWindow(dpy, scr), 0, 0, w, h, 0, BlackPixel(dpy, scr), BlackPixel(dpy, scr)); XStoreName(dpy, win, window_title); - { /* Ask the window manager for exactly the grid we drew. Without - this a tiling or maximising WM picks its own size and the grid - floats in a field of background. */ + { /* A PREFERRED size and a MINIMUM, never a fixed one. Pinning the + size was the earlier mistake: it fights a tiling window manager, + which ignores it anyway, and it stops the grid making use of a + larger tile. The layout reflows, so any size above the minimum + is legitimate. */ XSizeHints *sh = XAllocSizeHints(); sh->flags = PSize | PMinSize; sh->width = w; sh->height = h; - sh->min_width = w; sh->min_height = h; + sh->min_width = PAD*2 + 7*CELL_W_MIN; + sh->min_height = HEAD_H + 6*CELL_H_MIN + DETAIL_H; XSetWMNormalHints(dpy, win, sh); XFree(sh); } @@ -39,18 +39,27 @@ static const char *col_sel_light = "#ffd24a"; enum { SEL_RING = 3 }; /* px per ring */ /* --------------------------------------------------------------- geometry */ -/* CELL_W/CELL_H must suit the font: a cell holds the day number plus - NAME_LINES lines of `font`. Line height itself is taken from the font at - runtime, so only these two need revisiting when you change size. - Rough guide: CELL_W >= 10 * (widest name chars you want), CELL_H >= - big-font height + NAME_LINES * font height + 12. */ +/* The grid FILLS the window: cell size is computed from whatever space the + window manager gives us, divided seven across and six down. Under a + tiling WM that means the calendar uses its whole tile instead of sitting + in a corner of it, and resizing reflows rather than clipping. + + These are therefore MINIMUMS, not sizes. If the window is too small to + honour them the grid stops shrinking and simply overflows -- better than + cells too small to read. How many lines a name gets is likewise derived + from the cell height at runtime; NAME_LINES_MAX only caps it. */ enum { - CELL_W = 196, - CELL_H = 116, - PAD = 10, /* margin around the grid */ - HEAD_H = 62, /* title + weekday headings */ - DETAIL_H = 116, /* the pane under the grid */ - NAME_LINES = 3, /* how many lines a feast name gets */ + CELL_W_MIN = 96, + CELL_H_MIN = 52, + PAD = 10, /* margin around the grid */ + HEAD_H = 62, /* title + weekday headings */ + DETAIL_H = 116, /* the pane under the grid */ + NAME_LINES_MAX = 5, + + /* Preferred size when the window manager lets us choose. A tiling WM + will not, and that is fine: the grid reflows to whatever it gets. */ + WIN_W = 1200, + WIN_H = 820, }; /* ------------------------------------------------------------------ labels */ |
