diff options
Diffstat (limited to 'main.c')
| -rw-r--r-- | main.c | 154 |
1 files changed, 154 insertions, 0 deletions
@@ -0,0 +1,154 @@ +/* xmenu + * a simple fuzzy-selection menu made with Xlib + */ + +#include <X11/Xlib.h> +#include <X11/Xutil.h> +#include <X11/XKBlib.h> +#include <stdio.h> + +#define ARENA_IMPL +#define STR_IMPL + +#include "arena.h" +#include "dynarr.h" +#include "str.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; +} |
