swim.git

user.c

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

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

#include <X11/keysym.h>
#include <X11/Xlib.h>
#include <X11/XKBlib.h>
#include <xkbcommon/xkbcommon.h>

#include "bar.h"
#include "conv.h"
#include "draw.h"
#include "func.h"
#include "grab.h"
#include "swim.h"
#include "user.h"
#include "util.h"

#define CLEAN(mask) (mask & ~(IGMASK) & (ShiftMask | LockMask | ControlMask | \
		Mod1Mask | Mod2Mask | Mod3Mask | Mod4Mask | Mod5Mask))

extern const keyp_t keys[63];
extern const but_t buts[6];

int exec = -1;
char stext[256] = "", etext[256] = "";

void
buttonpress(XEvent *ev)
{
	extern mon_t *sel;
	extern const char *tags[9];

	cli_t *cli; mon_t *mon;
	if ((mon = wintomon(ev->xbutton.window)) != NULL && mon != sel)
		unfocus(sel->sel, false), sel = mon, focus(NULL);

	clk_t clk = CLK_ROOT; int num;
	if (ev->xbutton.window == sel->win) {
		size_t i = 0; uint16_t w = 0, tw = 0;
		do drawwide(tags[i], mon->w, &w);
		while ((w += PW) < ev->xbutton.x && ++i < LENGTH(tags));
		if (i >= LENGTH(tags)) {
			drawwide(stext, mon->w, &tw);
			clk = ev->xbutton.x > sel->w - tw - PW ?
					CLK_STATUS : CLK_TITLE;
		} else {
			clk = CLK_TAG, num = 1 << i;
		}
	} else if ((cli = wintocli(ev->xbutton.window)) != NULL) {
		XAllowEvents(dpy, ReplayPointer, CurrentTime);
		clk = CLK_CLI; focus(cli);
	}

	for (size_t i = 0; i < LENGTH(buts); ++i) {
		if (CLEAN(buts[i].mask) == CLEAN(ev->xbutton.state) &&
				clk == buts[i].clk &&
				buts[i].but == (int)ev->xbutton.button) {
			buts[i].func(clk == CLK_TAG && buts[i].arg == 0 ?
					num : buts[i].arg);
		}
	}
}

void
keypress(XEvent *ev)
{
	KeySym sym;
	if (exec == -1) {
		sym = XkbKeycodeToKeysym(dpy, ev->xkey.keycode, 0, 0);
		for (size_t i = 0; i < LENGTH(keys); ++i)
			if (sym == keys[i].keysym && CLEAN(keys[i].mod) ==
					CLEAN(ev->xkey.state))
				keys[i].func(keys[i].arg);
		return;
	}

	/* preserve uppercase keysym information */
	switch (sym = XkbKeycodeToKeysym(dpy, ev->xkey.keycode, 0,
			ev->xkey.state & ShiftMask)) {
	case XK_Return:
		spawn((long)(void *[]){ (char []){ "sh" },
				(char []){ "-c" }, etext, NULL });
		/* FALLTHROUGH */
	case XK_Escape:
		exec = -1, etext[0] = '\0', etext[6] = '\0';
		grabkeys();
		break;
	case XK_BackSpace:
		while (exec > 0 && (etext[--exec] & 0xC0) == 0x80);
		etext[exec] = '\0';
		break;
	default:
		exec += xkb_keysym_to_utf8(sym, &etext[exec], 255 - exec);
		if (etext[exec - 1] == '\0' && exec > 0) --exec;
	}
	drawbars();
}