swim.git

tile.c

espurr
/* swim - window manager
 * Copyright (C) 2022-2023 ArcNyxx
 * see LICENCE file for licensing information */

#include <stdbool.h>
#include <stdint.h>

#include <X11/Xlib.h>

#include "func.h"
#include "swim.h"
#include "tile.h"
#include "util.h"

#define GAPIH (mon->gap * 12)
#define GAPIV (mon->gap * 12)
#define GAPOH (mon->gap * 8)
#define GAPOV (mon->gap * 8)

static void move(cli_t *cli, uint16_t x, uint16_t y, uint16_t w, uint16_t h);

static void
move(cli_t *cli, uint16_t x, uint16_t y, uint16_t w, uint16_t h)
{
	/* possible to loop through and hide remaining windows and skip extra
	 * computation but would add too much complexity for rare case */
	if (y + h + 2 * BW > cli->mon->y + cli->mon->h) {
		MOVE(cli->win, -2 * (cli->w + 2 * BW), cli->y);
	} else if (x != cli->x || y != cli->y || w != cli->w || h != cli->h) {
		cli->x = x, cli->y = y, cli->w = w, cli->h = h;
		CSIZE(cli);
	}
}

void
attach(cli_t *cli)
{
	cli->next = cli->mon->cli, cli->mon->cli = cli;
}

void
detach(cli_t *cli)
{
	cli_t **find;
	for (find = &cli->mon->cli; *find != NULL && *find != cli;
			find = &(*find)->next);
	*find = cli->next;
}

cli_t *
next(cli_t *cli)
{
	for (; cli != NULL && (cli->flt || cli->fsc || !VIS(cli));
			cli = cli->next);
	return cli;
}

void
tile(mon_t *mon)
{
	int total = 0;
	cli_t *cli = mon->cli;
	for (; cli != NULL; total += (VIS(cli) && !cli->flt && !cli->fsc),
			cli = cli->next)
		MOVE(cli->win, VIS(cli) ?
				cli->x : -2 * (cli->w + 2 * BW), cli->y);

	int width = mon->w - 2 * GAPOH;
	if (total > mon->nmaster) /* two columns */
		width -= GAPIH, width = width * mon->mfact / 100;

	int num = 0, space = 0;
	for (cli = next(mon->cli); num < mon->nmaster && cli != NULL;
			++num, cli = next(cli->next)) {
		const int down = MIN(total, mon->nmaster) - num;
		const int height = (mon->h - H * mon->show - space -
				2 * GAPOV - GAPIV * (down - 1)) / down;
		move(cli, mon->x + GAPOH, mon->y +
				H * mon->show * mon->top + space + GAPOV,
				width - 2 * BW, MAX(height - 2 * BW, H));
		space += cli->h + 2 * BW + GAPIV;
	}

	space = 0;
	for (; cli != NULL; ++num, cli = next(cli->next)) {
		const int down = total - num;
		const int height = (mon->h - H * mon->show - space -
				2 * GAPOV - GAPIV * (down - 1)) / down;
		move(cli, mon->x + GAPOH + width + GAPIH, mon->y +
				H * mon->show * mon->top + space + GAPOV,
				mon->w - width - 2 * BW - 2 * GAPOH -
				GAPIH, MAX(height - 2 * BW, H));
		space += cli->h + 2 * BW + GAPIV;
	}
}