commit 55ae285ef587942dc34c5f95b7f97037deb791a2
parent d1dea11d1091b4eacefb8be73a0740f87444fe29
Author: William Casarin <jb55@jb55.com>
Date: Mon, 9 Jul 2018 10:19:59 -0700
getting there
Diffstat:
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);