fixed bugs, no more config.h, updated manpage, new libdraw

This commit is contained in:
Connor Lane Smith 2010-08-02 14:22:54 +01:00
parent a3606ecb0e
commit a7aee433cc
7 changed files with 162 additions and 220 deletions

View File

@ -3,9 +3,6 @@
include config.mk include config.mk
SRC = dmenu.c
OBJ = ${SRC:.c=.o}
all: options dmenu all: options dmenu
options: options:
@ -14,34 +11,28 @@ options:
@echo "LDFLAGS = ${LDFLAGS}" @echo "LDFLAGS = ${LDFLAGS}"
@echo "CC = ${CC}" @echo "CC = ${CC}"
.c.o: dmenu.o: dmenu.c config.mk
@echo CC $< @echo CC $<
@${CC} -c ${CFLAGS} $< @${CC} -c ${CFLAGS} $<
${OBJ}: config.h config.mk dmenu: dmenu.o
config.h:
@echo creating $@ from config.def.h
@cp config.def.h $@
dmenu: ${OBJ}
@echo CC -o $@ @echo CC -o $@
@${CC} -o $@ $+ ${LDFLAGS} @${CC} -o $@ $+ ${LDFLAGS}
clean: clean:
@echo cleaning @echo cleaning
@rm -f dmenu ${OBJ} dmenu-${VERSION}.tar.gz @rm -f dmenu dmenu.o dmenu-${VERSION}.tar.gz
dist: clean dist: clean
@echo creating dist tarball @echo creating dist tarball
@mkdir -p dmenu-${VERSION} @mkdir -p dmenu-${VERSION}
@cp -R LICENSE Makefile README config.mk dmenu.1 config.def.h dmenu_path dmenu_run ${SRC} dmenu-${VERSION} @cp -R LICENSE Makefile README config.mk dmenu.1 dmenu.c dmenu_path dmenu_run dmenu-${VERSION}
@tar -cf dmenu-${VERSION}.tar dmenu-${VERSION} @tar -cf dmenu-${VERSION}.tar dmenu-${VERSION}
@gzip dmenu-${VERSION}.tar @gzip dmenu-${VERSION}.tar
@rm -rf dmenu-${VERSION} @rm -rf dmenu-${VERSION}
install: all install: all
@echo installing executable file to ${DESTDIR}${PREFIX}/bin @echo installing executables to ${DESTDIR}${PREFIX}/bin
@mkdir -p ${DESTDIR}${PREFIX}/bin @mkdir -p ${DESTDIR}${PREFIX}/bin
@cp -f dmenu dmenu_path dmenu_run ${DESTDIR}${PREFIX}/bin @cp -f dmenu dmenu_path dmenu_run ${DESTDIR}${PREFIX}/bin
@chmod 755 ${DESTDIR}${PREFIX}/bin/dmenu @chmod 755 ${DESTDIR}${PREFIX}/bin/dmenu
@ -53,8 +44,9 @@ install: all
@chmod 644 ${DESTDIR}${MANPREFIX}/man1/dmenu.1 @chmod 644 ${DESTDIR}${MANPREFIX}/man1/dmenu.1
uninstall: uninstall:
@echo removing executable file from ${DESTDIR}${PREFIX}/bin @echo removing executables from ${DESTDIR}${PREFIX}/bin
@rm -f ${DESTDIR}${PREFIX}/bin/dmenu ${DESTDIR}${PREFIX}/bin/dmenu_path @rm -f ${DESTDIR}${PREFIX}/bin/dmenu
@rm -f ${DESTDIR}${PREFIX}/bin/dmenu_path
@rm -f ${DESTDIR}${PREFIX}/bin/dmenu_run @rm -f ${DESTDIR}${PREFIX}/bin/dmenu_run
@echo removing manual page from ${DESTDIR}${MANPREFIX}/man1 @echo removing manual page from ${DESTDIR}${MANPREFIX}/man1
@rm -f ${DESTDIR}${MANPREFIX}/man1/dmenu.1 @rm -f ${DESTDIR}${MANPREFIX}/man1/dmenu.1

11
README
View File

@ -1,21 +1,22 @@
dmenu - dynamic menu dmenu - dynamic menu
==================== ====================
dmenu is a generic and efficient menu for X. dmenu is an efficient dynamic menu for X.
Requirements Requirements
------------ ------------
In order to build dmenu you need the Xlib header files. In order to build dmenu you need the Xlib header files.
You also need libdraw, available from http://hg.suckless.org/libdraw You also need libdraw, available from http://hg.suckless.org/libdraw
Installation Installation
------------ ------------
Edit config.mk to match your local setup (dmenu is installed into the Edit config.mk to match your local setup (dmenu is installed into
/usr/local namespace by default). the /usr/local namespace by default).
Afterwards enter the following command to build and install dmenu (if Afterwards enter the following command to build and install dmenu
necessary as root): (if necessary as root):
make clean install make clean install

View File

@ -1,8 +0,0 @@
/* See LICENSE file for copyright and license details. */
/* appearance */
static const char *font = "-*-terminus-medium-r-normal-*-14-*-*-*-*-*-*-*";
static const char *normbgcolor = "#cccccc";
static const char *normfgcolor = "#000000";
static const char *selbgcolor = "#0066ff";
static const char *selfgcolor = "#ffffff";

View File

@ -1,5 +1,5 @@
# dmenu version # dmenu version
VERSION = 4.1.1 VERSION = 4.2
# Customize below to fit your system # Customize below to fit your system
@ -7,25 +7,22 @@ VERSION = 4.1.1
PREFIX = /usr/local PREFIX = /usr/local
MANPREFIX = ${PREFIX}/share/man MANPREFIX = ${PREFIX}/share/man
# Xlib
X11INC = /usr/X11R6/include X11INC = /usr/X11R6/include
X11LIB = /usr/X11R6/lib X11LIB = /usr/X11R6/lib
# Xinerama, comment if you don't want it # Xinerama, comment if you don't want it
XINERAMALIBS = -L${X11LIB} -lXinerama XINERAMALIBS = -lXinerama
XINERAMAFLAGS = -DXINERAMA XINERAMAFLAGS = -DXINERAMA
# includes and libs # includes and libs
INCS = -I. -I/usr/include -I${X11INC} INCS = -I${X11INC}
LIBS = -L/usr/lib -lc -L${X11LIB} -lX11 -ldraw ${XINERAMALIBS} LIBS = -L${X11LIB} -ldraw -lX11 ${XINERAMALIBS}
# flags # flags
CPPFLAGS = -D_BSD_SOURCE -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS} CPPFLAGS = -D_BSD_SOURCE -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS}
CFLAGS = -std=c99 -pedantic -Wall -Os ${INCS} ${CPPFLAGS} CFLAGS = -std=c99 -pedantic -Wall -Os ${INCS} ${CPPFLAGS}
LDFLAGS = -s ${LIBS} LDFLAGS = -s ${LIBS}
# Solaris
#CFLAGS = -fast ${INCS} -DVERSION=\"${VERSION}\"
#LDFLAGS = ${LIBS}
# compiler and linker # compiler and linker
CC = cc CC = cc

98
dmenu.1
View File

@ -5,81 +5,76 @@ dmenu \- dynamic menu
.B dmenu .B dmenu
.RB [ \-b ] .RB [ \-b ]
.RB [ \-i ] .RB [ \-i ]
.RB [ \-l " <lines>]" .RB [ \-l
.RB [ \-p " <prompt>]" .IR lines ]
.RB [ \-fn " <font>]" .RB [ \-p
.RB [ \-nb " <color>]" .IR prompt ]
.RB [ \-nf " <color>]" .RB [ \-fn
.RB [ \-sb " <color>]" .IR font ]
.RB [ \-sf " <color>]" .RB [ \-nb
.IR color ]
.RB [ \-nf
.IR color ]
.RB [ \-sb
.IR color ]
.RB [ \-sf
.IR color ]
.RB [ \-v ] .RB [ \-v ]
.P
.B dmenu_run .BR dmenu_run " ..."
.RB [ \-b ] .P
.RB [ \-i ]
.RB [ \-l " <lines>]"
.RB [ \-p " <prompt>]"
.RB [ \-fn " <font>]"
.RB [ \-nb " <color>]"
.RB [ \-nf " <color>]"
.RB [ \-sb " <color>]"
.RB [ \-sf " <color>]"
.RB [ \-v ]
.B dmenu_path .B dmenu_path
.SH DESCRIPTION .SH DESCRIPTION
.SS Overview
.B dmenu .B dmenu
is a generic menu for X, originally designed for is a dynamic menu for X, originally designed for
.BR dwm (1). .BR dwm (1).
It manages huge amounts (10000 and more) of user defined menu items efficiently. It manages huge numbers of user-defined menu items efficiently.
.P
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,
their choice is printed to standard output and dmenu terminates.
.P .P
.B dmenu_run .B dmenu_run
is a dmenu script which lists programs in the user's PATH and executes is a dmenu script used by dwm which lists programs in the user's PATH and
the selected item. executes the selected item.
.P .P
.B dmenu_path .B dmenu_path
is a script used by is a script used by dmenu_run to find and cache a list of programs.
.I dmenu_run .SH OPTIONS
to find and cache a list of programs.
.SS Options
.TP .TP
.B \-b .B \-b
dmenu appears at the bottom of the screen. dmenu appears at the bottom of the screen.
.TP .TP
.B \-i .B \-i
dmenu matches menu entries case insensitively. dmenu matches menu items case insensitively.
.TP .TP
.B \-l <lines> .BI \-l " lines"
dmenu lists items vertically, with the given number of lines. dmenu lists items vertically, with the given number of lines.
.TP .TP
.B \-p <prompt> .BI \-p " prompt"
sets the prompt to be displayed to the left of the input area. defines the prompt to be displayed to the left of the input area.
.TP .TP
.B \-fn <font> .BI \-fn " font"
sets the font. defines the font set used.
.TP .TP
.B \-nb <color> .BI \-nb " color"
sets the background color (#RGB, #RRGGBB, and color names are supported). defines the normal background color.
.IR #RGB ,
.IR #RRGGBB ,
and color names are supported.
.TP .TP
.B \-nf <color> .BI \-nf " color"
sets the foreground color (#RGB, #RRGGBB, and color names are supported). defines the normal foreground color.
.TP .TP
.B \-sb <color> .BI \-sb " color"
sets the background color of selected items (#RGB, #RRGGBB, and color names are defines the selected background color.
supported).
.TP .TP
.B \-sf <color> .BI \-sf " color"
sets the foreground color of selected items (#RGB, #RRGGBB, and color names are defines the selected foreground color.
supported).
.TP .TP
.B \-v .B \-v
prints version information to standard output, then exits. prints version information to standard output, then exits.
.SH USAGE .SH USAGE
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,
their choice is printed to standard output and dmenu terminates.
.P
dmenu is completely controlled by the keyboard. Besides standard Unix line dmenu is completely controlled by the keyboard. Besides standard Unix line
editing and item selection (Up/Down/Left/Right, PageUp/PageDown, Home/End), the editing and item selection (Up/Down/Left/Right, PageUp/PageDown, Home/End), the
following keys are recognized: following keys are recognized:
@ -96,10 +91,9 @@ Confirm input. Prints the input text to standard output and exits, returning
success. success.
.TP .TP
.B Escape (Control\-c) .B Escape (Control\-c)
Quit without selecting an item, returning failure. Exit without selecting an item, returning failure.
.TP .TP
.B Control\-y .B Control\-y
Paste the current X selection into the input field. Paste the current X selection into the input field.
.SH SEE ALSO .SH SEE ALSO
.BR dwm (1), .BR dwm (1)
.BR wmii (1).

222
dmenu.c
View File

@ -1,11 +1,9 @@
/* See LICENSE file for copyright and license details. */ /* See LICENSE file for copyright and license details. */
#include <ctype.h> #include <ctype.h>
#include <locale.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
#include <X11/keysym.h>
#include <X11/Xatom.h> #include <X11/Xatom.h>
#include <X11/Xlib.h> #include <X11/Xlib.h>
#include <X11/Xutil.h> #include <X11/Xutil.h>
@ -13,7 +11,6 @@
#include <X11/extensions/Xinerama.h> #include <X11/extensions/Xinerama.h>
#endif #endif
#include <draw.h> #include <draw.h>
#include "config.h"
#define INRECT(x,y,rx,ry,rw,rh) ((x) >= (rx) && (x) < (rx)+(rw) && (y) >= (ry) && (y) < (ry)+(rh)) #define INRECT(x,y,rx,ry,rw,rh) ((x) >= (rx) && (x) < (rx)+(rw) && (y) >= (ry) && (y) < (ry)+(rh))
#define MIN(a,b) ((a) < (b) ? (a) : (b)) #define MIN(a,b) ((a) < (b) ? (a) : (b))
@ -38,25 +35,27 @@ static void grabkeyboard(void);
static void insert(const char *s, ssize_t n); static void insert(const char *s, ssize_t n);
static void keypress(XKeyEvent *e); static void keypress(XKeyEvent *e);
static void match(void); static void match(void);
static void paste(Atom atom); static void paste(void);
static void readstdin(void); static void readstdin(void);
static void run(void); static void run(void);
static void setup(void); static void setup(void);
static void usage(void); static void usage(void);
static char *prompt;
static char text[4096]; static char text[4096];
static int screen;
static size_t cursor = 0; static size_t cursor = 0;
static const char *prompt = NULL;
static const char *normbgcolor = "#cccccc";
static const char *normfgcolor = "#000000";
static const char *selbgcolor = "#0066ff";
static const char *selfgcolor = "#ffffff";
static unsigned int inputw = 0; static unsigned int inputw = 0;
static unsigned int lines = 0; static unsigned int lines = 0;
static unsigned int mw, mh; static unsigned int mw, mh;
static unsigned int promptw = 0;
static unsigned long normcol[ColLast]; static unsigned long normcol[ColLast];
static unsigned long selcol[ColLast]; static unsigned long selcol[ColLast];
static Atom utf8; static Atom utf8;
static Bool topbar = True; static Bool topbar = True;
static DC dc; static DC *dc;
static Item *allitems, *matches; static Item *allitems, *matches;
static Item *curr, *prev, *next, *sel; static Item *curr, *prev, *next, *sel;
static Window root, win; static Window root, win;
@ -67,7 +66,7 @@ static void (*calcoffsets)(void) = calcoffsetsh;
void void
appenditem(Item *item, Item **list, Item **last) { appenditem(Item *item, Item **list, Item **last) {
if(!(*last)) if(!*last)
*list = item; *list = item;
else else
(*last)->right = item; (*last)->right = item;
@ -80,12 +79,12 @@ void
calcoffsetsh(void) { calcoffsetsh(void) {
unsigned int w, x; unsigned int w, x;
w = promptw + inputw + textw(&dc, "<") + textw(&dc, ">"); w = (prompt ? textw(dc, prompt) : 0) + inputw + textw(dc, "<") + textw(dc, ">");
for(x = w, next = curr; next; next = next->right) for(x = w, next = curr; next; next = next->right)
if((x += MIN(textw(&dc, next->text), mw / 3)) > mw) if((x += MIN(textw(dc, next->text), mw / 3)) > mw)
break; break;
for(x = w, prev = curr; prev && prev->left; prev = prev->left) for(x = w, prev = curr; prev && prev->left; prev = prev->left)
if((x += MIN(textw(&dc, prev->left->text), mw / 3)) > mw) if((x += MIN(textw(dc, prev->left->text), mw / 3)) > mw)
break; break;
} }
@ -96,101 +95,75 @@ calcoffsetsv(void) {
next = prev = curr; next = prev = curr;
for(i = 0; i < lines && next; i++) for(i = 0; i < lines && next; i++)
next = next->right; next = next->right;
mh = (dc.font.height + 2) * (i + 1);
for(i = 0; i < lines && prev && prev->left; i++) for(i = 0; i < lines && prev && prev->left; i++)
prev = prev->left; prev = prev->left;
} }
char * char *
cistrstr(const char *s, const char *sub) { cistrstr(const char *s, const char *sub) {
int c, csub; size_t len;
unsigned int len;
if(!sub) for(len = strlen(sub); *s; s++)
return (char *)s; if(!strncasecmp(s, sub, len))
if((c = tolower(*sub++)) != '\0') { return (char *)s;
len = strlen(sub); return NULL;
do {
do {
if((csub = *s++) == '\0')
return NULL;
}
while(tolower(csub) != c);
}
while(strncasecmp(s, sub, len) != 0);
s--;
}
return (char *)s;
} }
void void
drawmenu(void) { drawmenu(void) {
dc.x = 0; dc->x = 0;
dc.y = 0; dc->y = 0;
dc.w = mw; drawrect(dc, 0, 0, mw, mh, BG(dc, normcol));
dc.h = mh; dc->h = dc->font.height + 2;
drawbox(&dc, normcol); dc->y = topbar ? 0 : mh - dc->h;
dc.h = dc.font.height + 2;
dc.y = topbar ? 0 : mh - dc.h;
/* print prompt? */ /* print prompt? */
if(prompt) { if(prompt) {
dc.w = promptw; dc->w = textw(dc, prompt);
drawbox(&dc, selcol); drawtext(dc, prompt, selcol);
drawtext(&dc, prompt, selcol); dc->x = dc->w;
dc.x += dc.w;
} }
dc.w = mw - dc.x; dc->w = mw - dc->x;
/* print input area */ /* print input area */
if(matches && lines == 0 && textw(&dc, text) <= inputw) if(matches && lines == 0 && textw(dc, text) <= inputw)
dc.w = inputw; dc->w = inputw;
drawtext(&dc, text, normcol); drawtext(dc, text, normcol);
drawline(&dc, textnw(&dc, text, cursor) + dc.h/2 - 2, 2, 1, dc.h-4, normcol); drawrect(dc, textnw(dc, text, cursor) + dc->h/2 - 2, 2, 1, dc->h - 4, FG(dc, normcol));
if(lines > 0) if(lines > 0)
drawmenuv(); drawmenuv();
else if(curr && (dc.w == inputw || curr->next)) else if(curr && (dc->w == inputw || curr->next))
drawmenuh(); drawmenuh();
commitdraw(&dc, win); commitdraw(dc, win);
} }
void void
drawmenuh(void) { drawmenuh(void) {
Item *item; Item *item;
dc.x += inputw; dc->x += inputw;
dc.w = textw(&dc, "<"); dc->w = textw(dc, "<");
if(curr->left) if(curr->left)
drawtext(&dc, "<", normcol); drawtext(dc, "<", normcol);
dc.x += dc.w;
for(item = curr; item != next; item = item->right) { for(item = curr; item != next; item = item->right) {
dc.w = MIN(textw(&dc, item->text), mw / 3); dc->x += dc->w;
if(item == sel) dc->w = MIN(textw(dc, item->text), mw / 3);
drawbox(&dc, selcol); drawtext(dc, item->text, (item == sel) ? selcol : normcol);
drawtext(&dc, item->text, (item == sel) ? selcol : normcol);
dc.x += dc.w;
} }
dc.w = textw(&dc, ">"); dc->w = textw(dc, ">");
dc.x = mw - dc.w; dc->x = mw - dc->w;
if(next) if(next)
drawtext(&dc, ">", normcol); drawtext(dc, ">", normcol);
} }
void void
drawmenuv(void) { drawmenuv(void) {
Item *item; Item *item;
XWindowAttributes wa;
dc.y = topbar ? dc.h : 0; dc->y = topbar ? dc->h : 0;
dc.w = mw - dc.x; dc->w = mw - dc->x;
for(item = curr; item != next; item = item->right) { for(item = curr; item != next; item = item->right) {
if(item == sel) drawtext(dc, item->text, (item == sel) ? selcol : normcol);
drawbox(&dc, selcol); dc->y += dc->h;
drawtext(&dc, item->text, (item == sel) ? selcol : normcol);
dc.y += dc.h;
} }
if(!XGetWindowAttributes(dc.dpy, win, &wa))
eprintf("cannot get window attributes\n");
if(wa.height != mh)
XMoveResizeWindow(dc.dpy, win, wa.x, wa.y + (topbar ? 0 : wa.height - mh), mw, mh);
} }
void void
@ -198,7 +171,7 @@ grabkeyboard(void) {
int i; int i;
for(i = 0; i < 1000; i++) { for(i = 0; i < 1000; i++) {
if(!XGrabKeyboard(dc.dpy, root, True, GrabModeAsync, GrabModeAsync, CurrentTime)) if(!XGrabKeyboard(dc->dpy, root, True, GrabModeAsync, GrabModeAsync, CurrentTime))
return; return;
usleep(1000); usleep(1000);
} }
@ -254,6 +227,7 @@ keypress(XKeyEvent *e) {
break; break;
case XK_k: /* delete right */ case XK_k: /* delete right */
text[cursor] = '\0'; text[cursor] = '\0';
match();
break; break;
case XK_n: case XK_n:
ksym = XK_Down; ksym = XK_Down;
@ -270,10 +244,10 @@ keypress(XKeyEvent *e) {
n = 0; n = 0;
while(cursor - n++ > 0 && text[cursor - n] == ' '); while(cursor - n++ > 0 && text[cursor - n] == ' ');
while(cursor - n++ > 0 && text[cursor - n] != ' '); while(cursor - n++ > 0 && text[cursor - n] != ' ');
insert(NULL, -(--n)); insert(NULL, 1-n);
break; break;
case XK_y: /* paste selection */ case XK_y: /* paste selection */
XConvertSelection(dc.dpy, XA_PRIMARY, utf8, None, win, CurrentTime); XConvertSelection(dc->dpy, XA_PRIMARY, utf8, None, win, CurrentTime);
/* causes SelectionNotify event */ /* causes SelectionNotify event */
return; return;
} }
@ -348,7 +322,7 @@ keypress(XKeyEvent *e) {
break; break;
case XK_Return: case XK_Return:
case XK_KP_Enter: case XK_KP_Enter:
fputs(((e->state & ShiftMask) || sel) ? sel->text : text, stdout); fputs((sel && !(e->state & ShiftMask)) ? sel->text : text, stdout);
fflush(stdout); fflush(stdout);
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);
case XK_Right: case XK_Right:
@ -418,15 +392,14 @@ match(void) {
} }
void void
paste(Atom atom) paste(void) {
{
char *p, *q; char *p, *q;
int di; int di;
unsigned long dl; unsigned long dl;
Atom da; Atom da;
XGetWindowProperty(dc.dpy, win, atom, 0, sizeof text - cursor, True, XGetWindowProperty(dc->dpy, win, utf8, 0, sizeof text - cursor, True,
utf8, &da, &di, &dl, &dl, (unsigned char **)&p); utf8, &da, &di, &dl, &dl, (unsigned char **)&p);
insert(p, (q = strchr(p, '\n')) ? q-p : strlen(p)); insert(p, (q = strchr(p, '\n')) ? q-p : strlen(p));
XFree(p); XFree(p);
drawmenu(); drawmenu();
@ -434,24 +407,22 @@ paste(Atom atom)
void void
readstdin(void) { readstdin(void) {
char buf[sizeof text]; char buf[sizeof text], *p;
size_t len;
Item *item, *new; Item *item, *new;
allitems = NULL; allitems = NULL;
for(item = NULL; fgets(buf, sizeof buf, stdin); item = new) { for(item = NULL; fgets(buf, sizeof buf, stdin); item = new) {
len = strlen(buf); if((p = strchr(buf, '\n')))
if(buf[len-1] == '\n') *p = '\0';
buf[--len] = '\0';
if(!(new = malloc(sizeof *new))) if(!(new = malloc(sizeof *new)))
eprintf("cannot malloc %u bytes\n", sizeof *new); eprintf("cannot malloc %u bytes\n", sizeof *new);
if(!(new->text = strdup(buf))) if(!(new->text = strdup(buf)))
eprintf("cannot strdup %u bytes\n", len); eprintf("cannot strdup %u bytes\n", strlen(buf));
inputw = MAX(inputw, textw(&dc, new->text)); inputw = MAX(inputw, textw(dc, new->text));
new->next = new->left = new->right = NULL; new->next = new->left = new->right = NULL;
if(item) if(item)
item->next = new; item->next = new;
else else
allitems = new; allitems = new;
} }
} }
@ -460,7 +431,7 @@ void
run(void) { run(void) {
XEvent ev; XEvent ev;
while(!XNextEvent(dc.dpy, &ev)) while(!XNextEvent(dc->dpy, &ev))
switch(ev.type) { switch(ev.type) {
case Expose: case Expose:
if(ev.xexpose.count == 0) if(ev.xexpose.count == 0)
@ -470,39 +441,43 @@ run(void) {
keypress(&ev.xkey); keypress(&ev.xkey);
break; break;
case SelectionNotify: case SelectionNotify:
if(ev.xselection.property != None) if(ev.xselection.property == utf8)
paste(ev.xselection.property); paste();
break; break;
case VisibilityNotify: case VisibilityNotify:
if(ev.xvisibility.state != VisibilityUnobscured) if(ev.xvisibility.state != VisibilityUnobscured)
XRaiseWindow(dc.dpy, win); XRaiseWindow(dc->dpy, win);
break; break;
} }
} }
void void
setup(void) { setup(void) {
int x, y; int x, y, screen;
XSetWindowAttributes wa;
#ifdef XINERAMA #ifdef XINERAMA
int i, n; int n;
XineramaScreenInfo *info; XineramaScreenInfo *info;
#endif #endif
XSetWindowAttributes wa;
normcol[ColBG] = getcolor(&dc, normbgcolor); screen = DefaultScreen(dc->dpy);
normcol[ColFG] = getcolor(&dc, normfgcolor); root = RootWindow(dc->dpy, screen);
selcol[ColBG] = getcolor(&dc, selbgcolor); utf8 = XInternAtom(dc->dpy, "UTF8_STRING", False);
selcol[ColFG] = getcolor(&dc, selfgcolor);
normcol[ColBG] = getcolor(dc, normbgcolor);
normcol[ColFG] = getcolor(dc, normfgcolor);
selcol[ColBG] = getcolor(dc, selbgcolor);
selcol[ColFG] = getcolor(dc, selfgcolor);
/* input window geometry */ /* input window geometry */
mh = (dc.font.height + 2) * (lines + 1); mh = (dc->font.height + 2) * (lines + 1);
#ifdef XINERAMA #ifdef XINERAMA
if((info = XineramaQueryScreens(dc.dpy, &n))) { if((info = XineramaQueryScreens(dc->dpy, &n))) {
int di; int i, di;
unsigned int du; unsigned int du;
Window dw; Window dw;
XQueryPointer(dc.dpy, root, &dw, &dw, &x, &y, &di, &di, &du); XQueryPointer(dc->dpy, root, &dw, &dw, &x, &y, &di, &di, &du);
for(i = 0; i < n; i++) for(i = 0; i < n; i++)
if(INRECT(x, y, info[i].x_org, info[i].y_org, info[i].width, info[i].height)) if(INRECT(x, y, info[i].x_org, info[i].y_org, info[i].width, info[i].height))
break; break;
@ -515,31 +490,30 @@ setup(void) {
#endif #endif
{ {
x = 0; x = 0;
y = topbar ? 0 : DisplayHeight(dc.dpy, screen) - mh; y = topbar ? 0 : DisplayHeight(dc->dpy, screen) - mh;
mw = DisplayWidth(dc.dpy, screen); mw = DisplayWidth(dc->dpy, screen);
} }
/* input window */ /* input window */
wa.override_redirect = True; wa.override_redirect = True;
wa.background_pixmap = ParentRelative; wa.background_pixmap = ParentRelative;
wa.event_mask = ExposureMask | KeyPressMask | VisibilityChangeMask; wa.event_mask = ExposureMask | KeyPressMask | VisibilityChangeMask;
win = XCreateWindow(dc.dpy, root, x, y, mw, mh, 0, win = XCreateWindow(dc->dpy, root, x, y, mw, mh, 0,
DefaultDepth(dc.dpy, screen), CopyFromParent, DefaultDepth(dc->dpy, screen), CopyFromParent,
DefaultVisual(dc.dpy, screen), DefaultVisual(dc->dpy, screen),
CWOverrideRedirect | CWBackPixmap | CWEventMask, &wa); CWOverrideRedirect | CWBackPixmap | CWEventMask, &wa);
match();
grabkeyboard(); grabkeyboard();
setupdraw(&dc, win); setcanvas(dc, win, mw, mh);
inputw = MIN(inputw, mw / 3); inputw = MIN(inputw, mw/3);
utf8 = XInternAtom(dc.dpy, "UTF8_STRING", False); XMapRaised(dc->dpy, win);
XMapRaised(dc.dpy, win); match();
} }
void void
usage(void) { usage(void) {
fputs("usage: dmenu [-b] [-i] [-l <lines>] [-p <prompt>] [-fn <font>] [-nb <color>]\n" fputs("usage: dmenu [-b] [-i] [-l lines] [-p prompt] [-fn font] [-nb color]\n"
" [-nf <color>] [-sb <color>] [-sf <color>] [-v]\n", stderr); " [-nf color] [-sb color] [-sf color] [-v]\n", stderr);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
@ -548,8 +522,10 @@ main(int argc, char *argv[]) {
int i; int i;
progname = "dmenu"; progname = "dmenu";
dc = initdraw();
for(i = 1; i < argc; i++) for(i = 1; i < argc; i++)
/* 1-arg flags */ /* single flags */
if(!strcmp(argv[i], "-v")) { if(!strcmp(argv[i], "-v")) {
fputs("dmenu-"VERSION", © 2006-2010 dmenu engineers, see LICENSE for details\n", stdout); fputs("dmenu-"VERSION", © 2006-2010 dmenu engineers, see LICENSE for details\n", stdout);
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);
@ -562,17 +538,15 @@ main(int argc, char *argv[]) {
} }
else if(i == argc-1) else if(i == argc-1)
usage(); usage();
/* 2-arg flags */ /* double flags */
else if(!strcmp(argv[i], "-l")) { else if(!strcmp(argv[i], "-l")) {
if((lines = atoi(argv[++i])) > 0) if((lines = atoi(argv[++i])) > 0)
calcoffsets = calcoffsetsv; calcoffsets = calcoffsetsv;
} }
else if(!strcmp(argv[i], "-p")) { else if(!strcmp(argv[i], "-p"))
prompt = argv[++i]; prompt = argv[++i];
promptw = MIN(textw(&dc, prompt), mw/5);
}
else if(!strcmp(argv[i], "-fn")) else if(!strcmp(argv[i], "-fn"))
font = argv[++i]; initfont(dc, argv[i++]);
else if(!strcmp(argv[i], "-nb")) else if(!strcmp(argv[i], "-nb"))
normbgcolor = argv[++i]; normbgcolor = argv[++i];
else if(!strcmp(argv[i], "-nf")) else if(!strcmp(argv[i], "-nf"))
@ -584,14 +558,6 @@ main(int argc, char *argv[]) {
else else
usage(); usage();
if(!setlocale(LC_CTYPE, "") || !XSupportsLocale())
fputs("dmenu: warning: no locale support\n", stderr);
if(!(dc.dpy = XOpenDisplay(NULL)))
eprintf("cannot open display\n");
screen = DefaultScreen(dc.dpy);
root = RootWindow(dc.dpy, screen);
initfont(&dc, font);
readstdin(); readstdin();
setup(); setup();
run(); run();

View File

@ -19,7 +19,7 @@ then
do do
test -x "$file" && echo "$file" test -x "$file" && echo "$file"
done done
done | sort | uniq > "$CACHE".$$ && done | sort -u > "$CACHE".$$ &&
mv "$CACHE".$$ "$CACHE" mv "$CACHE".$$ "$CACHE"
fi fi