46 Commits
0.3 ... 1.0

Author SHA1 Message Date
Anselm R. Garbe
81bcf078f6 made function signatures more consistent to my coding style 2006-09-12 10:59:00 +02:00
Anselm R. Garbe
0e5f467aa8 commented dmenu 2006-09-11 13:18:09 +02:00
Anselm R. Garbe
c51406b279 Added tag 0.9 for changeset d046c818ea467555cc338751c9bf3024609f1f12 2006-09-08 08:31:19 +02:00
Anselm R. Garbe
32f7fe4835 implemented early keyboard grab for dmenu with a timeout for stdin data writers to prevent endless grabbings of the keyboard 2006-09-08 07:33:20 +02:00
Anselm R. Garbe
0fa5a339ff new version of dmenu 2006-09-07 19:12:04 +02:00
Anselm R. Garbe
358f078c0b another fix 2006-09-07 09:40:09 +02:00
Anselm R. Garbe
1f207893e6 made dmenu.1 also concise 2006-09-07 09:36:53 +02:00
Anselm R. Garbe
1c5be1c553 Added tag 0.8 for changeset 409667a57221f7e50ba8b5248f638915cd61b366 2006-09-06 10:53:15 +02:00
Anselm R. Garbe
32ea45084b fixed man page 2006-09-04 19:47:09 +02:00
Anselm R. Garbe
cc7d863b6e Added tag 0.7 for changeset 5fc20d7158bd16b4d5f8d1c25e177680b6d54252 2006-09-04 17:17:08 +02:00
Anselm R. Garbe
04eade6a76 small change of main event loop 2006-09-04 07:28:03 +02:00
Anselm R. Garbe
49ce444d32 updated version 2006-08-28 12:26:25 +02:00
Anselm R. Garbe
2e9515ee27 Added tag 0.6 for changeset 25f679fb19686140a907684ffcb423b9e9d44b53 2006-08-28 10:20:10 +02:00
Anselm R. Garbe
d4a4cc1ab8 updated man page 2006-08-28 07:22:38 +02:00
Anselm R. Garbe
11bda99968 fixed 2006-08-25 18:15:24 +02:00
Anselm R. Garbe
82b0bc83f8 switching back to a dark color scheme with larger font 2006-08-25 18:03:30 +02:00
Anselm R. Garbe
bd1172e689 small color fixes 2006-08-25 17:44:40 +02:00
Anselm R. Garbe
13ef97e65e updated dmenu to borderless drawing as well 2006-08-25 14:45:17 +02:00
Anselm R. Garbe
65be999a3f back to 3 colors 2006-08-25 07:54:20 +02:00
Anselm R. Garbe
37faefb1aa removed useless call 2006-08-24 12:04:41 +02:00
Anselm R. Garbe
18ec376aa9 fixed minor bug 2006-08-24 12:03:40 +02:00
Anselm R. Garbe
6c1e46654d small color change 2006-08-24 11:57:58 +02:00
Anselm R. Garbe
e980c7ff18 migrated dmenu to use 4 instead of 3 colors 2006-08-24 11:47:08 +02:00
Anselm R. Garbe
7848b53dc3 Added tag 0.5 for changeset 4a0ecd881c4fc15de4a0bebd79308b064be020ef 2006-08-24 10:22:51 +02:00
Anselm R. Garbe
865c938856 prepared dmenu-0.5 2006-08-24 10:22:30 +02:00
Anselm R. Garbe
30d72e5f87 removed unnecessary Xlib call 2006-08-24 09:27:01 +02:00
Anselm R. Garbe
0ffd139f2c sanitizing my colorscheme 2006-08-23 19:05:20 +02:00
Anselm R. Garbe
86512ce930 back to terminus font 2006-08-23 18:55:48 +02:00
Anselm R. Garbe
d3206194c1 font fix 2006-08-22 10:01:45 +02:00
Anselm R. Garbe
8148b515a1 fixed 2006-08-22 09:49:56 +02:00
arg@localhost.10kloc.org
35210e3998 applied OpenBSD changes.. 2006-08-21 17:45:46 +02:00
Anselm R.Garbe
df85dd743c renamed bad_malloc into badmalloc as well 2006-08-21 07:34:16 +02:00
Anselm R.Garbe
d9f6fa426b small changes in dmenu.1 2006-08-21 07:31:33 +02:00
Anselm R.Garbe
bbb2cc2a72 fixed a typo in config.mk, fixed cleanup code in dmenu (now frees all allocated stuff) 2006-08-16 19:25:04 +02:00
Anselm R.Garbe
02ddc93c94 applied sanders patch 2006-08-16 12:37:01 +02:00
Anselm R.Garbe
0faf441367 applied sanders Makefile patch 2006-08-16 08:57:10 +02:00
Anselm R.Garbe
be6b534520 fixed the same issue in dmenu 2006-08-15 16:56:55 +02:00
Anselm R.Garbe
db76b0f9a5 Added tag 0.4 for changeset 7acf0dde1120542917bae12e0e42293f9d2cc899 2006-08-15 10:39:26 +02:00
Anselm R.Garbe
26fc52fcf6 removed finished message 2006-08-14 16:11:38 +02:00
Anselm R.Garbe
6a26e97f74 fixed string cutting 2006-08-14 10:56:57 +02:00
Anselm R.Garbe
0e21ef5f37 fixed string cutting 2006-08-14 08:52:28 +02:00
Anselm R.Garbe
2f3068fb77 added comment 2006-08-14 08:44:54 +02:00
Anselm R.Garbe
b7f8911455 applied Sanders LD patch 2006-08-14 08:42:23 +02:00
Anselm R.Garbe
35a06ccd2e applied my new color scheme 2006-08-11 18:12:07 +02:00
Anselm R.Garbe
67649463c8 simplified drawborder 2006-08-11 11:52:34 +02:00
Anselm R.Garbe
d1415ea497 Added tag 0.3 for changeset d352e9dc112ee96aa5cad961a0ed880ae9ce7276 2006-08-10 15:19:03 +02:00
11 changed files with 151 additions and 145 deletions

View File

@@ -1,2 +1,9 @@
fcc8a282cb52c6a9343b461026b386825590cd31 0.1
656be0f47df545dfdd2e1e0663663b8b1b26f031 0.2
d352e9dc112ee96aa5cad961a0ed880ae9ce7276 0.3
7acf0dde1120542917bae12e0e42293f9d2cc899 0.4
4a0ecd881c4fc15de4a0bebd79308b064be020ef 0.5
25f679fb19686140a907684ffcb423b9e9d44b53 0.6
5fc20d7158bd16b4d5f8d1c25e177680b6d54252 0.7
409667a57221f7e50ba8b5248f638915cd61b366 0.8
d046c818ea467555cc338751c9bf3024609f1f12 0.9

View File

@@ -7,19 +7,19 @@ SRC = draw.c main.c util.c
OBJ = ${SRC:.c=.o}
all: options dmenu
@echo finished
options:
@echo dmenu build options:
@echo "CFLAGS = ${CFLAGS}"
@echo "LDFLAGS = ${LDFLAGS}"
@echo "CC = ${CC}"
@echo "LD = ${LD}"
.c.o:
@echo CC $<
@${CC} -c ${CFLAGS} $<
${OBJ}: dmenu.h config.h
${OBJ}: dmenu.h config.h config.mk
config.h:
@echo creating $@ from config.default.h
@@ -27,7 +27,7 @@ config.h:
dmenu: ${OBJ}
@echo LD $@
@${CC} -o $@ ${OBJ} ${LDFLAGS}
@${LD} -o $@ ${OBJ} ${LDFLAGS}
@strip $@
clean:

3
README
View File

@@ -1,7 +1,6 @@
dmenu - dynamic menu
--------------------
dmenu is a generic, highly customizable, and efficient menu for the
X Window System.
dmenu is a generic and efficient menu for X.
Requirements

View File

@@ -4,6 +4,8 @@
*/
#define FONT "-*-terminus-medium-*-*-*-12-*-*-*-*-*-iso10646-*"
#define BGCOLOR "#eeeeee"
#define FGCOLOR "#666699"
#define BORDERCOLOR "#9999CC"
#define SELBGCOLOR "#333366"
#define SELFGCOLOR "#eeeeee"
#define NORMBGCOLOR "#333333"
#define NORMFGCOLOR "#dddddd"
#define STDIN_TIMEOUT 3 /* seconds */

View File

@@ -4,6 +4,8 @@
*/
#define FONT "fixed"
#define BGCOLOR "#666699"
#define FGCOLOR "#eeeeee"
#define BORDERCOLOR "#9999CC"
#define SELBGCOLOR "#666699"
#define SELFGCOLOR "#eeeeee"
#define NORMBGCOLOR "#333366"
#define NORMFGCOLOR "#cccccc"
#define STDIN_TIMEOUT 3 /* seconds */

View File

@@ -1,5 +1,5 @@
# dmenu version
VERSION = 0.3
VERSION = 1.0
# Customize below to fit your system
@@ -11,7 +11,7 @@ X11INC = /usr/X11R6/include
X11LIB = /usr/X11R6/lib
# includes and libs
INCS = -I/usr/lib -I${X11INC}
INCS = -I. -I/usr/include -I${X11INC}
LIBS = -L/usr/lib -lc -L${X11LIB} -lX11
# flags
@@ -20,5 +20,6 @@ LDFLAGS = ${LIBS}
#CFLAGS = -g -Wall -O2 ${INCS} -DVERSION=\"${VERSION}\"
#LDFLAGS = -g ${LIBS}
# compiler
# compiler and linker
CC = cc
LD = ${CC}

63
dmenu.1
View File

@@ -6,59 +6,54 @@ dmenu \- dynamic menu
.RB [ \-v ]
.SH DESCRIPTION
.SS Overview
.B dmenu
is a generic, highly customizable, and efficient menu for the X Window System,
originally designed for
dmenu is a generic menu for X, originally designed for
.BR dwm (1).
It supports arbitrary, user defined menu contents.
It manages huge amounts (up to 10.000 and more) of user defined menu items
efficiently.
.SS Options
.TP
.B \-v
prints version information to stdout, then exits.
prints version information to standard output, then exits.
.SH USAGE
.B dmenu
reads a list of newline-separated items from stdin and creates a menu.
When the user selects an item or enters any text and presses Return, his choice
is printed to stdout and
.B dmenu
terminates.
.B dmenu
is completely controlled by the keyboard. The following keys are recognized:
dmenu reads a list of newline-separated items from standard input and creates a
menu. When the user selects an item or enters any text and presses Return, his
choice is printed to standard output and dmenu terminates.
.P
dmenu is completely controlled by the keyboard. The following keys are recognized:
.TP
Any printable character
Appends the character to the text in the input field. This works as a filter:
.B Any printable character
Appends the character to the text in the input field. This works as a filter:
only items containing this text will be displayed.
.TP
Left/Right
.B Left/Right
Select the previous/next item.
.TP
Tab
.B Tab
Copy the selected item to the input field.
.TP
Return
Confirm selection and quit (print the selected item to stdout).
.B Return
Confirm selection and quit (print the selected item to standard output). Returns
.B 0
on termination.
.TP
Shift-Return
Confirm selection and quit (print the text in the input field to stdout).
.B Shift-Return
Confirm selection and quit (print the text in the input field to standard output).
Returns
.B 0
on termination.
.TP
Escape
Quit without selecting an item.
.B Escape
Quit without selecting an item. Returns
.B 1
on termination.
.TP
Backspace (Control-h)
.B Backspace (Control-h)
Remove enough characters from the input field to change its filtering effect.
.TP
Control-u
.B Control-u
Remove all characters from the input field.
.P
.B dmenu
returns
.B 0
if Return is pressed on termination,
.B 1
if Escape is pressed.
.SH CUSTOMIZATION
.B dmenu
is customized by creating a custom config.h and (re)compiling the source
dmenu is customized by creating a custom config.h and (re)compiling the source
code. This keeps it fast, secure and simple.
.SH SEE ALSO
.BR dwm (1)

29
dmenu.h
View File

@@ -9,6 +9,9 @@
#define SPACE 30 /* px */
/* color */
enum { ColFG, ColBG, ColLast };
typedef struct DC DC;
typedef struct Fnt Fnt;
@@ -20,27 +23,27 @@ struct Fnt {
int height;
};
struct DC { /* draw context */
struct DC {
int x, y, w, h;
unsigned long bg;
unsigned long fg;
unsigned long border;
unsigned long norm[ColLast];
unsigned long sel[ColLast];
Drawable drawable;
Fnt font;
GC gc;
};
}; /* draw context */
extern int screen;
extern Display *dpy;
extern DC dc;
extern DC dc; /* global drawing context */
/* draw.c */
extern void drawtext(const char *text, Bool invert, Bool border);
extern unsigned long getcolor(const char *colstr);
extern void setfont(const char *fontstr);
extern unsigned int textw(const char *text);
extern void drawtext(const char *text,
unsigned long col[ColLast]); /* draws text with the defined color tuple */
extern unsigned long getcolor(const char *colstr); /* returns color of colstr */
extern void setfont(const char *fontstr); /* sets global font */
extern unsigned int textw(const char *text); /* returns width of text in px */
/* util.c */
extern void *emalloc(unsigned int size);
extern void eprint(const char *errstr, ...);
extern char *estrdup(const char *str);
extern void *emalloc(unsigned int size); /* allocates memory, exits on error */
extern void eprint(const char *errstr, ...); /* prints errstr and exits with 1 */
extern char *estrdup(const char *str); /* duplicates str, exits on allocation error */

65
draw.c
View File

@@ -9,29 +9,8 @@
/* static */
static void
drawborder(void)
{
XPoint points[5];
XSetLineAttributes(dpy, dc.gc, 1, LineSolid, CapButt, JoinMiter);
XSetForeground(dpy, dc.gc, dc.border);
points[0].x = dc.x;
points[0].y = dc.y;
points[1].x = dc.w - 1;
points[1].y = 0;
points[2].x = 0;
points[2].y = dc.h - 1;
points[3].x = -(dc.w - 1);
points[3].y = 0;
points[4].x = 0;
points[4].y = -(dc.h - 1);
XDrawLines(dpy, dc.drawable, dc.gc, points, 5, CoordModePrevious);
}
static unsigned int
textnw(const char *text, unsigned int len)
{
textnw(const char *text, unsigned int len) {
XRectangle r;
if(dc.font.set) {
@@ -44,25 +23,21 @@ textnw(const char *text, unsigned int len)
/* extern */
void
drawtext(const char *text, Bool invert, Bool border)
{
drawtext(const char *text, unsigned long col[ColLast]) {
int x, y, w, h;
static char buf[256];
unsigned int len;
unsigned int len, olen;
XGCValues gcv;
XRectangle r = { dc.x, dc.y, dc.w, dc.h };
XSetForeground(dpy, dc.gc, invert ? dc.fg : dc.bg);
XSetForeground(dpy, dc.gc, col[ColBG]);
XFillRectangles(dpy, dc.drawable, dc.gc, &r, 1);
w = 0;
if(border)
drawborder();
if(!text)
return;
len = strlen(text);
w = 0;
olen = len = strlen(text);
if(len >= sizeof(buf))
len = sizeof(buf) - 1;
memcpy(buf, text, len);
@@ -75,27 +50,33 @@ drawtext(const char *text, Bool invert, Bool border)
/* shorten text if necessary */
while(len && (w = textnw(buf, len)) > dc.w - h)
buf[--len] = 0;
if(len < olen) {
if(len > 1)
buf[len - 1] = '.';
if(len > 2)
buf[len - 2] = '.';
if(len > 3)
buf[len - 3] = '.';
}
if(w > dc.w)
return; /* too long */
gcv.foreground = invert ? dc.bg : dc.fg;
gcv.background = invert ? dc.fg : dc.bg;
gcv.foreground = col[ColFG];
if(dc.font.set) {
XChangeGC(dpy, dc.gc, GCForeground | GCBackground, &gcv);
XmbDrawImageString(dpy, dc.drawable, dc.font.set, dc.gc,
XChangeGC(dpy, dc.gc, GCForeground, &gcv);
XmbDrawString(dpy, dc.drawable, dc.font.set, dc.gc,
x, y, buf, len);
}
else {
gcv.font = dc.font.xfont->fid;
XChangeGC(dpy, dc.gc, GCForeground | GCBackground | GCFont, &gcv);
XDrawImageString(dpy, dc.drawable, dc.gc, x, y, buf, len);
XChangeGC(dpy, dc.gc, GCForeground | GCFont, &gcv);
XDrawString(dpy, dc.drawable, dc.gc, x, y, buf, len);
}
}
unsigned long
getcolor(const char *colstr)
{
getcolor(const char *colstr) {
Colormap cmap = DefaultColormap(dpy, screen);
XColor color;
@@ -104,8 +85,7 @@ getcolor(const char *colstr)
}
void
setfont(const char *fontstr)
{
setfont(const char *fontstr) {
char **missing, *def;
int i, n;
@@ -153,7 +133,6 @@ setfont(const char *fontstr)
}
unsigned int
textw(const char *text)
{
textw(const char *text) {
return textnw(text, strlen(text)) + dc.font.height;
}

84
main.c
View File

@@ -11,6 +11,8 @@
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/select.h>
#include <sys/time.h>
#include <X11/cursorfont.h>
#include <X11/Xutil.h>
#include <X11/keysym.h>
@@ -29,7 +31,7 @@ static int mx, my, mw, mh;
static int ret = 0;
static int nitem = 0;
static unsigned int cmdw = 0;
static Bool done = False;
static Bool running = True;
static Item *allitems = NULL; /* first of all items */
static Item *item = NULL; /* first of pattern matching items */
static Item *sel = NULL;
@@ -40,8 +42,7 @@ static Window root;
static Window win;
static void
calcoffsets()
{
calcoffsets() {
unsigned int tw, w;
if(!curr)
@@ -69,25 +70,24 @@ calcoffsets()
}
static void
drawmenu()
{
drawmenu() {
Item *i;
dc.x = 0;
dc.y = 0;
dc.w = mw;
dc.h = mh;
drawtext(NULL, False, False);
drawtext(NULL, dc.norm);
/* print command */
if(cmdw && item)
dc.w = cmdw;
drawtext(text[0] ? text : NULL, False, False);
drawtext(text[0] ? text : NULL, dc.norm);
dc.x += cmdw;
if(curr) {
dc.w = SPACE;
drawtext((curr && curr->left) ? "<" : NULL, False, False);
drawtext((curr && curr->left) ? "<" : NULL, dc.norm);
dc.x += dc.w;
/* determine maximum items */
@@ -95,21 +95,20 @@ drawmenu()
dc.w = textw(i->text);
if(dc.w > mw / 3)
dc.w = mw / 3;
drawtext(i->text, sel == i, sel == i);
drawtext(i->text, (sel == i) ? dc.sel : dc.norm);
dc.x += dc.w;
}
dc.x = mw - SPACE;
dc.w = SPACE;
drawtext(next ? ">" : NULL, False, False);
drawtext(next ? ">" : NULL, dc.norm);
}
XCopyArea(dpy, dc.drawable, win, dc.gc, 0, 0, mw, mh, 0, 0);
XFlush(dpy);
}
static void
match(char *pattern)
{
match(char *pattern) {
unsigned int plen;
Item *i, *j;
@@ -149,8 +148,7 @@ match(char *pattern)
}
static void
kpress(XKeyEvent * e)
{
kpress(XKeyEvent * e) {
char buf[32];
int num, prev_nitem;
unsigned int i, len;
@@ -219,11 +217,11 @@ kpress(XKeyEvent * e)
else if(text)
fprintf(stdout, "%s", text);
fflush(stdout);
done = True;
running = False;
break;
case XK_Escape:
ret = 1;
done = True;
running = False;
break;
case XK_BackSpace:
if((i = len)) {
@@ -249,8 +247,7 @@ kpress(XKeyEvent * e)
}
static char *
readstdin()
{
readstdin() {
static char *maxname = NULL;
char *p, buf[1024];
unsigned int len = 0, max = 0;
@@ -287,9 +284,11 @@ Display *dpy;
DC dc = {0};
int
main(int argc, char *argv[])
{
main(int argc, char *argv[]) {
char *maxname;
fd_set rd;
struct timeval timeout;
Item *i;
XEvent ev;
XSetWindowAttributes wa;
@@ -306,17 +305,28 @@ main(int argc, char *argv[])
screen = DefaultScreen(dpy);
root = RootWindow(dpy, screen);
maxname = readstdin();
/* grab as early as possible, but after reading all items!!! */
/* Note, the select() construction allows to grab all keypresses as
* early as possible, to not loose them. But if there is no standard
* input supplied, we will make sure to exit after MAX_WAIT_STDIN
* seconds. This is convenience behavior for rapid typers.
*/
while(XGrabKeyboard(dpy, root, True, GrabModeAsync,
GrabModeAsync, CurrentTime) != GrabSuccess)
usleep(1000);
timeout.tv_usec = 0;
timeout.tv_sec = STDIN_TIMEOUT;
FD_ZERO(&rd);
FD_SET(STDIN_FILENO, &rd);
if(select(ConnectionNumber(dpy) + 1, &rd, NULL, NULL, &timeout) < 1)
goto UninitializedEnd;
maxname = readstdin();
/* style */
dc.bg = getcolor(BGCOLOR);
dc.fg = getcolor(FGCOLOR);
dc.border = getcolor(BORDERCOLOR);
dc.sel[ColBG] = getcolor(SELBGCOLOR);
dc.sel[ColFG] = getcolor(SELFGCOLOR);
dc.norm[ColBG] = getcolor(NORMBGCOLOR);
dc.norm[ColFG] = getcolor(NORMFGCOLOR);
setfont(FONT);
wa.override_redirect = 1;
@@ -325,7 +335,7 @@ main(int argc, char *argv[])
mx = my = 0;
mw = DisplayWidth(dpy, screen);
mh = dc.font.height + 4;
mh = dc.font.height + 2;
win = XCreateWindow(dpy, root, mx, my, mw, mh, 0,
DefaultDepth(dpy, screen), CopyFromParent,
@@ -336,6 +346,7 @@ main(int argc, char *argv[])
/* pixmap */
dc.drawable = XCreatePixmap(dpy, root, mw, mh, DefaultDepth(dpy, screen));
dc.gc = XCreateGC(dpy, root, 0, 0);
XSetLineAttributes(dpy, dc.gc, 1, LineSolid, CapButt, JoinMiter);
if(maxname)
cmdw = textw(maxname);
@@ -349,8 +360,10 @@ main(int argc, char *argv[])
XSync(dpy, False);
/* main event loop */
while(!done && !XNextEvent(dpy, &ev)) {
while(running && !XNextEvent(dpy, &ev)) {
switch (ev.type) {
default: /* ignore all crap */
break;
case KeyPress:
kpress(&ev.xkey);
break;
@@ -358,15 +371,24 @@ main(int argc, char *argv[])
if(ev.xexpose.count == 0)
drawmenu();
break;
default:
break;
}
}
XUngrabKeyboard(dpy, CurrentTime);
while(allitems) {
i = allitems->next;
free(allitems->text);
free(allitems);
allitems = i;
}
if(dc.font.set)
XFreeFontSet(dpy, dc.font.set);
else
XFreeFont(dpy, dc.font.xfont);
XFreePixmap(dpy, dc.drawable);
XFreeGC(dpy, dc.gc);
XDestroyWindow(dpy, win);
UninitializedEnd:
XUngrabKeyboard(dpy, CurrentTime);
XCloseDisplay(dpy);
return ret;

16
util.c
View File

@@ -13,25 +13,22 @@
/* static */
static void
bad_malloc(unsigned int size)
{
badmalloc(unsigned int size) {
eprint("fatal: could not malloc() %u bytes\n", size);
}
/* extern */
void *
emalloc(unsigned int size)
{
emalloc(unsigned int size) {
void *res = malloc(size);
if(!res)
bad_malloc(size);
badmalloc(size);
return res;
}
void
eprint(const char *errstr, ...)
{
eprint(const char *errstr, ...) {
va_list ap;
va_start(ap, errstr);
@@ -41,10 +38,9 @@ eprint(const char *errstr, ...)
}
char *
estrdup(const char *str)
{
estrdup(const char *str) {
void *res = strdup(str);
if(!res)
bad_malloc(strlen(str));
badmalloc(strlen(str));
return res;
}