From ccec3e7f471e727fd008eb94454412281b8a4e43 Mon Sep 17 00:00:00 2001 From: katalx Date: Wed, 28 Jan 2026 18:26:48 -0500 Subject: uhhh git --- ui.c | 149 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 149 insertions(+) create mode 100644 ui.c (limited to 'ui.c') diff --git a/ui.c b/ui.c new file mode 100644 index 0000000..542cb8b --- /dev/null +++ b/ui.c @@ -0,0 +1,149 @@ +/* xmenu + * a simple fuzzy-selection menu made with Xlib + */ + +#include +#include +#include +#include + +#include "dynarr.h" + +typedef DYNARR(char) DynStr; + +int +umod(int a, int b) +{ + if (a < 0) { + return b + a % b; + } else { + return a % b; + } +} + +int +main(int argc, char **argv) +{ + Display *dsp = XOpenDisplay(""); + int scr = DefaultScreen(dsp); + unsigned long fg = BlackPixel(dsp, scr); + unsigned long bg = WhitePixel(dsp, scr); + + XSizeHints szhint = { 0 }; + szhint.width = 350; + szhint.height = 250; + szhint.flags = PSize; + + Window win = XCreateSimpleWindow( + dsp, + DefaultRootWindow(dsp), + szhint.x, szhint.y, + szhint.width, szhint.height, + 5 /* border width */, + fg, bg); + + char title[] = "xmenu"; + XSetStandardProperties(dsp, win, title, title, + None, argv, argc, &szhint); + + GC gc = XCreateGC(dsp, win, 0, 0); + XSetBackground(dsp, gc, bg); + XSetForeground(dsp, gc, fg); + + XSelectInput(dsp, win, ButtonPressMask | KeyPressMask | ExposureMask); + XMapRaised(dsp, win); + + Font freg = XLoadFont(dsp, "-*-new century schoolbook-medium-r-*-*-24-*-*-*-*-*-*-*"); + Font fital = XLoadFont(dsp, "-*-new century schoolbook-medium-i-*-*-24-*-*-*-*-*-*-*"); + + /* see Xft(3) */ + + DynStr input = { 0 }; + + int seli = 0; + + const char *optv[] = { "she shit on my thang until i vomit", "what", "who are you", "why are you", "where'd you come from" }; + int optc = sizeof optv / sizeof *optv; + + for (;;) { + XEvent ev; + KeySym key; + XNextEvent(dsp, &ev); + switch (ev.type) { + case KeyPress: { + char kbuf[32]; + KeyCode kc = ev.xkey.keycode; + KeySym sym = XkbKeycodeToKeysym(dsp, kc, 0, + !!(ev.xkey.state & ShiftMask)); + int rune = ksym_to_unicode(sym); + switch (sym) { + case XK_Escape: + goto done; + case XK_BackSpace: + if (input.n > 0) input.n--; + goto draw; + case XK_Return: + input.n = 0; + goto draw; + case XK_Down: + seli = umod(seli + 1, optc); + goto draw; + case XK_Up: + seli = umod(seli - 1, optc); + goto draw; + default: { + int n = XLookupString(&ev.xkey, kbuf, 10, &key, 0); + if (!n) break; + DA_PUSH_MULT(&input, kbuf, n); + seli = 0; + goto draw; + } break; + } + } break; + case Expose: { + draw:; + XWindowAttributes attr; + XClearWindow(dsp, win); + XGetWindowAttributes(dsp, win, &attr); + //XGetSizeHints(dsp, win, &szhint); + XSetFont(dsp, gc, fital); + int w = XTextWidth(XQueryFont(dsp, XGContextFromGC(gc)), input.v, input.n); + DA_PUSH(&input, '_'); + XDrawString(dsp, win, gc, 16, 24, input.v, input.n); + input.n--; + XSetFont(dsp, gc, freg); + for (int i = 0; i < optc; i++) { + if (i == seli) { + int w = XTextWidth(XQueryFont(dsp, + XGContextFromGC(gc)), + optv[i], strlen(optv[i])); + XFillRectangle(dsp, win, gc, + 16, 28 + i * 24 + 8, + w, 24); + XSetForeground(dsp, gc, bg); + XDrawString(dsp, win, gc, + 16, 48 + i * 24 + 8, + optv[i], strlen(optv[i])); + XSetForeground(dsp, gc, fg); + } else { + XDrawString(dsp, win, gc, + 16, 48 + i * 24 + 8, + optv[i], strlen(optv[i])); + } + + } + } break; + /* TODO: figure out quit events */ + } + } + +done: ; + + XUnloadFont(dsp, freg); + XUnloadFont(dsp, fital); + XFreeGC(dsp, gc); + XDestroyWindow(dsp, win); + XCloseDisplay(dsp); + + return 0; +} -- cgit v1.2.3