swim.git
user.c
/* 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();
}