cmdtree

A trie command launcher for X11
git clone git://jb55.com/cmdtree
Log | Files | Refs | README | LICENSE

commit 55ae285ef587942dc34c5f95b7f97037deb791a2
parent d1dea11d1091b4eacefb8be73a0740f87444fe29
Author: William Casarin <jb55@jb55.com>
Date:   Mon,  9 Jul 2018 10:19:59 -0700

getting there

Diffstat:
M.gitignore | 2++
MMakefile | 8++++++++
Mcmdtree.c | 154++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------------
Aconfig.def.h | 23+++++++++++++++++++++++
Mdrw.c | 7+++++++
Mdrw.h | 8++++++++
Mutil.h | 6++++++
7 files changed, 175 insertions(+), 33 deletions(-)

diff --git a/.gitignore b/.gitignore @@ -1,3 +1,5 @@ /cmdtree *.d *.o +/config.h +/TAGS diff --git a/Makefile b/Makefile @@ -17,6 +17,11 @@ include $(OBJS:.o=.d) %.d: %.c $(CC) -MM $(CFLAGS) $< > $@ +cmdtree.c: config.h + +config.h: config.def.h + cp config.def.h $@ + all: cmdtree $(BIN): $(OBJS) @@ -25,4 +30,7 @@ $(BIN): $(OBJS) clean: fake rm -f $(OBJS) $(BIN) +TAGS: fake + etags *.c + .PHONY: fake diff --git a/cmdtree.c b/cmdtree.c @@ -1,36 +1,70 @@ -#include <X11/Xlib.h> -#include <X11/Xutil.h> -#include <X11/Xresource.h> - #include <stdarg.h> #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <time.h> +#include <X11/Xlib.h> +#include <X11/Xutil.h> +#include <X11/Xresource.h> +#include <X11/Xft/Xft.h> #include <unistd.h> +#include <assert.h> +#include "drw.h" #include "util.h" +enum { + SchemeNorm, + SchemeSel, + SchemeOut, + SchemeLast, +}; /* color schemes */ + static Window root, parentwin, win; static int screen; static Display *display; static int mw, mh; -static unsigned int lines = 0; static XIC xic; +static Clr *scheme[SchemeLast]; + +#include "config.h" -// config -static int topbar = 1; static void -setup() +grabkeyboard(void) { - int x, y; + struct timespec ts = { .tv_sec = 0, .tv_nsec = 1000000 }; + int i; + + // XXXembed + /* if (embed) */ + /* return; */ + /* try to grab keyboard, we may have to wait for another process to ungrab */ + for (i = 0; i < 1000; i++) { + if (XGrabKeyboard(display, DefaultRootWindow(display), True, + GrabModeAsync, GrabModeAsync, CurrentTime) + == GrabSuccess) + return; + nanosleep(&ts, NULL); + } + die("cannot grab keyboard"); +} + +static void +setup(Drw *drw) +{ + int x, y, j; XSetWindowAttributes swa; XWindowAttributes wa; XIM xim; XClassHint ch = {"cmdtree", "cmdtree"}; + /* init appearance */ + for (j = 0; j < SchemeLast; j++) + scheme[j] = drw_scm_create(drw, colors[j], 2); + if (!XGetWindowAttributes(display, parentwin, &wa)) die("could not get embedding window attributes: 0x%lx", parentwin); @@ -42,7 +76,7 @@ setup() mh = 100; swa.override_redirect = True; - /* swa.background_pixel = scheme[SchemeNorm][ColBg].pixel; */ + swa.background_pixel = scheme[SchemeNorm][ColBg].pixel; swa.event_mask = ExposureMask | KeyPressMask | VisibilityChangeMask; win = XCreateWindow(display, parentwin, x, y, mw, mh, 0, @@ -52,8 +86,8 @@ setup() XSetClassHint(display, win, &ch); // what do? - /* XMapRaised(display, win); */ - + XMapRaised(display, win); + XSetInputFocus(display, win, RevertToParent, CurrentTime); xim = XOpenIM(display, NULL, NULL, NULL); xic = XCreateIC(xim, XNInputStyle, XIMPreeditNothing | XIMStatusNothing, @@ -64,7 +98,7 @@ setup() XSetInputFocus(display, win, RevertToParent, CurrentTime); - // XXX embed + // XXXembed /* if (embed) { */ /* XSelectInput(dpy, parentwin, FocusChangeMask); */ /* if (XQueryTree(dpy, parentwin, &dw, &w, &dws, &du) && dws) { */ @@ -80,44 +114,88 @@ setup() } static void -draw_tree() { - static const char *msg = "cmdtree is a tree of commands"; +draw_command(Drw *drw, const char *name, const char *binding) { + + int x = 50; + int y = 10; + int lpad = 0; + unsigned int w = 100; + unsigned int h = 100; + int invert = 0; + int res = 1; + + /* XFillRectangle(display, win, DefaultGC(display, screen), x, y, 10, 10); */ + + drw_setscheme(drw, scheme[SchemeNorm]); + drw_rect(drw, 0, 0, mw, mh, 1, 1); + drw_setscheme(drw, scheme[SchemeSel]); + res = drw_text(drw, x, y, w, h, lpad, name, invert); + (void)res; + assert(res != 0); + + /* XDrawString(drw->dpy, win, DefaultGC(display, screen), 10, 50, name, */ + /* strlen(name)); */ + + /* XDrawString(drw->dpy, win, DefaultGC(display, screen), 10, 50, name, */ + /* strlen(name)); */ +} - XFillRectangle(display, win, DefaultGC(display, screen), - 20, 20, 10, 10); +static void +draw_tree(Drw *drw, int x, int y, int w, int h) { + draw_command(drw, "apps", "a"); + + if (!drw) + return; - XDrawString(display, win, DefaultGC(display, screen), 10, - 50, msg, strlen(msg)); + XCopyArea(drw->dpy, drw->drawable, win, drw->gc, x, y, w, h, x, y); + XSync(drw->dpy, False); } static void -run() { +cleanup(Drw *drw, int code) { + int i; + + for (i = 0; i < SchemeLast; i++) + free(scheme[i]); + + drw_free(drw); + exit(0); +} + +static void +run(Drw *drw) { XEvent e; int done = 0; char buf[32]; KeySym ksym = NoSymbol; Status status; + int code = 0; while (!done) { XNextEvent(display, &e); - if (e.type == Expose) { - draw_tree(); - } - - if (e.type == KeyPress) { - XmbLookupString(xic, (XKeyEvent*)&e, buf, - sizeof buf, &ksym, &status); - if (ksym == XK_q) done = 1; - if (ksym == XK_Escape) done = 1; + switch (e.type) { + case Expose: + draw_tree(drw, 0, 0, mw, mh); + break; + case KeyPress: + XmbLookupString(xic, (XKeyEvent*)&e, buf, sizeof buf, + &ksym, &status); + if (ksym == XK_q || ksym == XK_Escape) { + code = 1; + done = 1; + } + break; } - } + cleanup(drw, code); } int main(void) { + XWindowAttributes wa; + Drw *drw; display = XOpenDisplay(NULL); if (display == NULL) { @@ -128,14 +206,24 @@ int main(void) { screen = DefaultScreen(display); root = RootWindow(display, screen); - // XXX embed + // XXXembed /* if (!embed || !(parentwin = strtol(embed, NULL, 0))) */ /* parentwin = root; */ parentwin = root; - setup(); - run(); + if (!XGetWindowAttributes(display, parentwin, &wa)) + die("could not get embedding window attributes: 0x%lx", + parentwin); + + drw = drw_create(display, screen, root, wa.width, wa.height); + + if (!drw_fontset_create(drw, fonts, LENGTH(fonts))) + die("no fonts could be loaded."); + + grabkeyboard(); + setup(drw); + run(drw); XCloseDisplay(display); return 0; diff --git a/config.def.h b/config.def.h @@ -0,0 +1,23 @@ +/* See LICENSE file for copyright and license details. */ +/* Default settings; can be overriden by command line. */ + +static int topbar = 1; /* -b option; if 0, dmenu appears at bottom */ +/* -fn option overrides fonts[0]; default X11 font or font set */ +static const char *fonts[] = { + "Monospace:size=12" +}; +/* static const char *prompt = NULL; /\* -p option; prompt to the left of input field *\/ */ +static const char *colors[SchemeLast][2] = { + /* fg bg */ + [SchemeNorm] = { "#bbbbbb", "#222222" }, + [SchemeSel] = { "#eeeeee", "#005577" }, + [SchemeOut] = { "#000000", "#00ffff" }, +}; +/* -l option; if nonzero, dmenu uses vertical list with given number of lines */ +static unsigned int lines = 0; + +/* + * Characters not considered part of a word while deleting words + * for example: " /?\"&[]" + */ +static const char worddelimiters[] = " "; diff --git a/drw.c b/drw.c @@ -252,9 +252,13 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp XftResult result; int charexists = 0; + printf("1\n"); + if (!drw || (render && !drw->scheme) || !text || !drw->fonts) return 0; + printf("2\n"); + if (!render) { w = ~w; } else { @@ -267,6 +271,8 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp w -= lpad; } + printf("3\n"); + usedfont = drw->fonts; while (1) { utf8strlen = 0; @@ -364,6 +370,7 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp return x + (render ? w : 0); } + void drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h) { diff --git a/drw.h b/drw.h @@ -1,5 +1,10 @@ /* See LICENSE file for copyright and license details. */ +#ifndef CMDTREE_DRW_H +#define CMDTREE_DRW_H + +#include <X11/Xft/Xft.h> + typedef struct { Cursor cursor; } Cur; @@ -55,3 +60,6 @@ int drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned in /* Map functions */ void drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h); + + +#endif /* CMDTREE_DRW_H */ diff --git a/util.h b/util.h @@ -8,6 +8,12 @@ #define MIN(A, B) ((A) < (B) ? (A) : (B)) #define BETWEEN(X, A, B) ((A) <= (X) && (X) <= (B)) +#define INTERSECT(x,y,w,h,r) (MAX(0, MIN((x)+(w),(r).x_org+(r).width) - MAX((x),(r).x_org)) \ + * MAX(0, MIN((y)+(h),(r).y_org+(r).height) - MAX((y),(r).y_org))) +#define LENGTH(X) (sizeof X / sizeof X[0]) +#define TEXTW(X) (drw_fontset_getwidth(drw, (X)) + lrpad) + + void die(const char *fmt, ...); void *ecalloc(size_t nmemb, size_t size);