Compare commits

...

15 Commits
4.8 ... 4.9

Author SHA1 Message Date
65be875f5a Prepared 4.9 release. 2019-02-02 04:54:15 -08:00
7d19b2055d dmenu.1: document improved fastgrab behaviour from previous patch 2019-01-27 15:28:02 +01:00
dok
11a65377da Use slow path if stdin is a tty
If stdin is a tty and dmenu is ran with the fast option then it's
impossible to close stdin because the keyboard is already grabbed.
2019-01-27 15:26:04 +01:00
bbc464dc80 dmenu_path: always use the cachedir 2018-07-21 12:49:00 +02:00
a314412f4b Makefile: just show the compiler output
Don't be fancy and just show the actual output so debugging is simpler.
2018-06-02 17:09:01 +02:00
a9eae39e93 Do not strip at link stage
Building with debug symbols is worthless unless LDFLAGS are manually adjusted
as well.
2018-06-02 17:01:24 +02:00
851b73d178 code-style for pledge: check the return code -1, not < 0
this is the proper idiom
2018-05-25 13:07:17 +02:00
05c138f5b8 code-style for pledge(2)
feedback from Klemens, thanks
2018-05-25 13:03:25 +02:00
cd132c8d5b Pledge on OpenBSD 2018-05-25 12:04:22 +02:00
e75494b730 Use bold for keyboard shortcuts in dmenu.1
Like dwm, use the same syntax for all keyboard shortcuts for
consistency.
2018-05-12 19:12:25 +02:00
0f76dd2fb8 Fix cursor drawn position with wide glyphs 2018-04-22 14:19:20 +02:00
0b57480218 Makefile: bikesheddingly replace ${} with $() 2018-04-22 14:09:05 +02:00
377bd37e21 Handle IME input
Thanks to nzl <uruabi@gmail.com> for the patch!
2018-04-22 14:09:05 +02:00
b6d2cc9aea Fix handling of input strings 2018-04-22 14:09:05 +02:00
2f398981fe Update LICENSE
Only "meaningful" commits and contributors who made changes over the
years have been added.
2018-03-15 18:29:32 +01:00
7 changed files with 133 additions and 111 deletions

12
LICENSE
View File

@ -1,13 +1,15 @@
MIT/X Consortium License MIT/X Consortium License
© 2006-2014 Anselm R Garbe <anselm@garbe.us> © 2006-2019 Anselm R Garbe <anselm@garbe.ca>
© 2010-2012 Connor Lane Smith <cls@lubutu.com> © 2006-2008 Sander van Dijk <a.h.vandijk@gmail.com>
© 2006-2007 Michał Janeczek <janeczek@gmail.com>
© 2007 Kris Maglione <jg@suckless.org>
© 2009 Gottox <gottox@s01.de> © 2009 Gottox <gottox@s01.de>
© 2009 Markus Schnalke <meillo@marmaro.de> © 2009 Markus Schnalke <meillo@marmaro.de>
© 2009 Evan Gates <evan.gates@gmail.com> © 2009 Evan Gates <evan.gates@gmail.com>
© 2006-2008 Sander van Dijk <a dot h dot vandijk at gmail dot com> © 2010-2012 Connor Lane Smith <cls@lubutu.com>
© 2006-2007 Michał Janeczek <janeczek at gmail dot com> © 2014-2019 Hiltjo Posthuma <hiltjo@codemadness.org>
© 2014-2015 Hiltjo Posthuma <hiltjo@codemadness.org> © 2015-2018 Quentin Rameau <quinq@fifth.space>
Permission is hereby granted, free of charge, to any person obtaining a Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"), copy of this software and associated documentation files (the "Software"),

View File

@ -4,71 +4,61 @@
include config.mk include config.mk
SRC = drw.c dmenu.c stest.c util.c SRC = drw.c dmenu.c stest.c util.c
OBJ = ${SRC:.c=.o} OBJ = $(SRC:.c=.o)
all: options dmenu stest all: options dmenu stest
options: options:
@echo dmenu build options: @echo dmenu build options:
@echo "CFLAGS = ${CFLAGS}" @echo "CFLAGS = $(CFLAGS)"
@echo "LDFLAGS = ${LDFLAGS}" @echo "LDFLAGS = $(LDFLAGS)"
@echo "CC = ${CC}" @echo "CC = $(CC)"
.c.o: .c.o:
@echo CC $< $(CC) -c $(CFLAGS) $<
@${CC} -c ${CFLAGS} $<
config.h: config.h:
@echo creating $@ from config.def.h cp config.def.h $@
@cp config.def.h $@
${OBJ}: arg.h config.h config.mk drw.h $(OBJ): arg.h config.h config.mk drw.h
dmenu: dmenu.o drw.o util.o dmenu: dmenu.o drw.o util.o
@echo CC -o $@ $(CC) -o $@ dmenu.o drw.o util.o $(LDFLAGS)
@${CC} -o $@ dmenu.o drw.o util.o ${LDFLAGS}
stest: stest.o stest: stest.o
@echo CC -o $@ $(CC) -o $@ stest.o $(LDFLAGS)
@${CC} -o $@ stest.o ${LDFLAGS}
clean: clean:
@echo cleaning rm -f dmenu stest $(OBJ) dmenu-$(VERSION).tar.gz
@rm -f dmenu stest ${OBJ} dmenu-${VERSION}.tar.gz
dist: clean dist: clean
@echo creating dist tarball mkdir -p dmenu-$(VERSION)
@mkdir -p dmenu-${VERSION} cp LICENSE Makefile README arg.h config.def.h config.mk dmenu.1\
@cp LICENSE Makefile README arg.h config.def.h config.mk dmenu.1 \ drw.h util.h dmenu_path dmenu_run stest.1 $(SRC)\
drw.h util.h dmenu_path dmenu_run stest.1 ${SRC} \ dmenu-$(VERSION)
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 executables to ${DESTDIR}${PREFIX}/bin mkdir -p $(DESTDIR)$(PREFIX)/bin
@mkdir -p ${DESTDIR}${PREFIX}/bin cp -f dmenu dmenu_path dmenu_run stest $(DESTDIR)$(PREFIX)/bin
@cp -f dmenu dmenu_path dmenu_run stest ${DESTDIR}${PREFIX}/bin chmod 755 $(DESTDIR)$(PREFIX)/bin/dmenu
@chmod 755 ${DESTDIR}${PREFIX}/bin/dmenu chmod 755 $(DESTDIR)$(PREFIX)/bin/dmenu_path
@chmod 755 ${DESTDIR}${PREFIX}/bin/dmenu_path chmod 755 $(DESTDIR)$(PREFIX)/bin/dmenu_run
@chmod 755 ${DESTDIR}${PREFIX}/bin/dmenu_run chmod 755 $(DESTDIR)$(PREFIX)/bin/stest
@chmod 755 ${DESTDIR}${PREFIX}/bin/stest mkdir -p $(DESTDIR)$(MANPREFIX)/man1
@echo installing manual pages to ${DESTDIR}${MANPREFIX}/man1 sed "s/VERSION/$(VERSION)/g" < dmenu.1 > $(DESTDIR)$(MANPREFIX)/man1/dmenu.1
@mkdir -p ${DESTDIR}${MANPREFIX}/man1 sed "s/VERSION/$(VERSION)/g" < stest.1 > $(DESTDIR)$(MANPREFIX)/man1/stest.1
@sed "s/VERSION/${VERSION}/g" < dmenu.1 > ${DESTDIR}${MANPREFIX}/man1/dmenu.1 chmod 644 $(DESTDIR)$(MANPREFIX)/man1/dmenu.1
@sed "s/VERSION/${VERSION}/g" < stest.1 > ${DESTDIR}${MANPREFIX}/man1/stest.1 chmod 644 $(DESTDIR)$(MANPREFIX)/man1/stest.1
@chmod 644 ${DESTDIR}${MANPREFIX}/man1/dmenu.1
@chmod 644 ${DESTDIR}${MANPREFIX}/man1/stest.1
uninstall: uninstall:
@echo removing executables from ${DESTDIR}${PREFIX}/bin rm -f $(DESTDIR)$(PREFIX)/bin/dmenu\
@rm -f ${DESTDIR}${PREFIX}/bin/dmenu $(DESTDIR)$(PREFIX)/bin/dmenu_path\
@rm -f ${DESTDIR}${PREFIX}/bin/dmenu_path $(DESTDIR)$(PREFIX)/bin/dmenu_run\
@rm -f ${DESTDIR}${PREFIX}/bin/dmenu_run $(DESTDIR)$(PREFIX)/bin/stest\
@rm -f ${DESTDIR}${PREFIX}/bin/stest $(DESTDIR)$(MANPREFIX)/man1/dmenu.1\
@echo removing manual page from ${DESTDIR}${MANPREFIX}/man1 $(DESTDIR)$(MANPREFIX)/man1/stest.1
@rm -f ${DESTDIR}${MANPREFIX}/man1/dmenu.1
@rm -f ${DESTDIR}${MANPREFIX}/man1/stest.1
.PHONY: all options clean dist install uninstall .PHONY: all options clean dist install uninstall

View File

@ -1,9 +1,9 @@
# dmenu version # dmenu version
VERSION = 4.8 VERSION = 4.9
# paths # paths
PREFIX = /usr/local PREFIX = /usr/local
MANPREFIX = ${PREFIX}/share/man MANPREFIX = $(PREFIX)/share/man
X11INC = /usr/X11R6/include X11INC = /usr/X11R6/include
X11LIB = /usr/X11R6/lib X11LIB = /usr/X11R6/lib
@ -16,16 +16,16 @@ XINERAMAFLAGS = -DXINERAMA
FREETYPELIBS = -lfontconfig -lXft FREETYPELIBS = -lfontconfig -lXft
FREETYPEINC = /usr/include/freetype2 FREETYPEINC = /usr/include/freetype2
# OpenBSD (uncomment) # OpenBSD (uncomment)
#FREETYPEINC = ${X11INC}/freetype2 #FREETYPEINC = $(X11INC)/freetype2
# includes and libs # includes and libs
INCS = -I${X11INC} -I${FREETYPEINC} INCS = -I$(X11INC) -I$(FREETYPEINC)
LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} LIBS = -L$(X11LIB) -lX11 $(XINERAMALIBS) $(FREETYPELIBS)
# flags # flags
CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_XOPEN_SOURCE=700 -D_POSIX_C_SOURCE=200809L -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS} CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_XOPEN_SOURCE=700 -D_POSIX_C_SOURCE=200809L -DVERSION=\"$(VERSION)\" $(XINERAMAFLAGS)
CFLAGS = -std=c99 -pedantic -Wall -Os ${INCS} ${CPPFLAGS} CFLAGS = -std=c99 -pedantic -Wall -Os $(INCS) $(CPPFLAGS)
LDFLAGS = -s ${LIBS} LDFLAGS = $(LIBS)
# compiler and linker # compiler and linker
CC = cc CC = cc

60
dmenu.1
View File

@ -41,8 +41,8 @@ which lists programs in the user's $PATH and runs the result in their $SHELL.
dmenu appears at the bottom of the screen. dmenu appears at the bottom of the screen.
.TP .TP
.B \-f .B \-f
dmenu grabs the keyboard before reading stdin. This is faster, but will lock up dmenu grabs the keyboard before reading stdin if not reading from a tty. This
X until stdin reaches end\-of\-file. is faster, but will lock up X until stdin reaches end\-of\-file.
.TP .TP
.B \-i .B \-i
dmenu matches menu items case insensitively. dmenu matches menu items case insensitively.
@ -106,88 +106,88 @@ Move cursor to the start of the current word
.B Ctrl-Right .B Ctrl-Right
Move cursor to the end of the current word Move cursor to the end of the current word
.TP .TP
C\-a .B C\-a
Home Home
.TP .TP
C\-b .B C\-b
Left Left
.TP .TP
C\-c .B C\-c
Escape Escape
.TP .TP
C\-d .B C\-d
Delete Delete
.TP .TP
C\-e .B C\-e
End End
.TP .TP
C\-f .B C\-f
Right Right
.TP .TP
C\-g .B C\-g
Escape Escape
.TP .TP
C\-h .B C\-h
Backspace Backspace
.TP .TP
C\-i .B C\-i
Tab Tab
.TP .TP
C\-j .B C\-j
Return Return
.TP .TP
C\-J .B C\-J
Shift-Return Shift-Return
.TP .TP
C\-k .B C\-k
Delete line right Delete line right
.TP .TP
C\-m .B C\-m
Return Return
.TP .TP
C\-M .B C\-M
Shift-Return Shift-Return
.TP .TP
C\-n .B C\-n
Down Down
.TP .TP
C\-p .B C\-p
Up Up
.TP .TP
C\-u .B C\-u
Delete line left Delete line left
.TP .TP
C\-w .B C\-w
Delete word left Delete word left
.TP .TP
C\-y .B C\-y
Paste from primary X selection Paste from primary X selection
.TP .TP
C\-Y .B C\-Y
Paste from X clipboard Paste from X clipboard
.TP .TP
M\-b .B M\-b
Move cursor to the start of the current word Move cursor to the start of the current word
.TP .TP
M\-f .B M\-f
Move cursor to the end of the current word Move cursor to the end of the current word
.TP .TP
M\-g .B M\-g
Home Home
.TP .TP
M\-G .B M\-G
End End
.TP .TP
M\-h .B M\-h
Up Up
.TP .TP
M\-j .B M\-j
Page down Page down
.TP .TP
M\-k .B M\-k
Page up Page up
.TP .TP
M\-l .B M\-l
Down Down
.SH SEE ALSO .SH SEE ALSO
.IR dwm (1), .IR dwm (1),

50
dmenu.c
View File

@ -6,6 +6,7 @@
#include <string.h> #include <string.h>
#include <strings.h> #include <strings.h>
#include <time.h> #include <time.h>
#include <unistd.h>
#include <X11/Xlib.h> #include <X11/Xlib.h>
#include <X11/Xatom.h> #include <X11/Xatom.h>
@ -144,7 +145,7 @@ drawmenu(void)
drw_setscheme(drw, scheme[SchemeNorm]); drw_setscheme(drw, scheme[SchemeNorm]);
drw_text(drw, x, 0, w, bh, lrpad / 2, text, 0); drw_text(drw, x, 0, w, bh, lrpad / 2, text, 0);
drw_font_getexts(drw->fonts, text, cursor, &curpos, NULL); curpos = TEXTW(text) - TEXTW(&text[cursor]);
if ((curpos += lrpad / 2 - 1) < w) { if ((curpos += lrpad / 2 - 1) < w) {
drw_setscheme(drw, scheme[SchemeNorm]); drw_setscheme(drw, scheme[SchemeNorm]);
drw_rect(drw, x + curpos, 2, 2, bh - 4, 1, 0); drw_rect(drw, x + curpos, 2, 2, bh - 4, 1, 0);
@ -308,13 +309,21 @@ keypress(XKeyEvent *ev)
{ {
char buf[32]; char buf[32];
int len; int len;
KeySym ksym = NoSymbol; KeySym ksym;
Status status; Status status;
len = XmbLookupString(xic, ev, buf, sizeof buf, &ksym, &status); len = XmbLookupString(xic, ev, buf, sizeof buf, &ksym, &status);
if (status == XBufferOverflow) switch (status) {
default: /* XLookupNone, XBufferOverflow */
return; return;
if (ev->state & ControlMask) case XLookupChars:
goto insert;
case XLookupKeySym:
case XLookupBoth:
break;
}
if (ev->state & ControlMask) {
switch(ksym) { switch(ksym) {
case XK_a: ksym = XK_Home; break; case XK_a: ksym = XK_Home; break;
case XK_b: ksym = XK_Left; break; case XK_b: ksym = XK_Left; break;
@ -352,12 +361,10 @@ keypress(XKeyEvent *ev)
return; return;
case XK_Left: case XK_Left:
movewordedge(-1); movewordedge(-1);
ksym = NoSymbol; goto draw;
break;
case XK_Right: case XK_Right:
movewordedge(+1); movewordedge(+1);
ksym = NoSymbol; goto draw;
break;
case XK_Return: case XK_Return:
case XK_KP_Enter: case XK_KP_Enter:
break; break;
@ -367,16 +374,14 @@ keypress(XKeyEvent *ev)
default: default:
return; return;
} }
else if (ev->state & Mod1Mask) } else if (ev->state & Mod1Mask) {
switch(ksym) { switch(ksym) {
case XK_b: case XK_b:
movewordedge(-1); movewordedge(-1);
ksym = NoSymbol; goto draw;
break;
case XK_f: case XK_f:
movewordedge(+1); movewordedge(+1);
ksym = NoSymbol; goto draw;
break;
case XK_g: ksym = XK_Home; break; case XK_g: ksym = XK_Home; break;
case XK_G: ksym = XK_End; break; case XK_G: ksym = XK_End; break;
case XK_h: ksym = XK_Up; break; case XK_h: ksym = XK_Up; break;
@ -386,13 +391,14 @@ keypress(XKeyEvent *ev)
default: default:
return; return;
} }
}
switch(ksym) { switch(ksym) {
default: default:
insert:
if (!iscntrl(*buf)) if (!iscntrl(*buf))
insert(buf, len); insert(buf, len);
break; break;
case NoSymbol:
break;
case XK_Delete: case XK_Delete:
if (text[cursor] == '\0') if (text[cursor] == '\0')
return; return;
@ -489,6 +495,8 @@ keypress(XKeyEvent *ev)
match(); match();
break; break;
} }
draw:
drawmenu(); drawmenu();
} }
@ -545,7 +553,7 @@ run(void)
XEvent ev; XEvent ev;
while (!XNextEvent(dpy, &ev)) { while (!XNextEvent(dpy, &ev)) {
if (XFilterEvent(&ev, win)) if (XFilterEvent(&ev, None))
continue; continue;
switch(ev.type) { switch(ev.type) {
case Expose: case Expose:
@ -657,6 +665,7 @@ setup(void)
XNClientWindow, win, XNFocusWindow, win, NULL); XNClientWindow, win, XNFocusWindow, win, NULL);
XMapRaised(dpy, win); XMapRaised(dpy, win);
XSetInputFocus(dpy, win, RevertToParent, CurrentTime);
if (embed) { if (embed) {
XSelectInput(dpy, parentwin, FocusChangeMask); XSelectInput(dpy, parentwin, FocusChangeMask);
if (XQueryTree(dpy, parentwin, &dw, &w, &dws, &du) && dws) { if (XQueryTree(dpy, parentwin, &dw, &w, &dws, &du) && dws) {
@ -722,6 +731,8 @@ main(int argc, char *argv[])
if (!setlocale(LC_CTYPE, "") || !XSupportsLocale()) if (!setlocale(LC_CTYPE, "") || !XSupportsLocale())
fputs("warning: no locale support\n", stderr); fputs("warning: no locale support\n", stderr);
if (!XSetLocaleModifiers(""))
fputs("warning: no locale modifiers support\n", stderr);
if (!(dpy = XOpenDisplay(NULL))) if (!(dpy = XOpenDisplay(NULL)))
die("cannot open display"); die("cannot open display");
screen = DefaultScreen(dpy); screen = DefaultScreen(dpy);
@ -736,7 +747,12 @@ main(int argc, char *argv[])
die("no fonts could be loaded."); die("no fonts could be loaded.");
lrpad = drw->fonts->h; lrpad = drw->fonts->h;
if (fast) { #ifdef __OpenBSD__
if (pledge("stdio rpath", NULL) == -1)
die("pledge");
#endif
if (fast && !isatty(0)) {
grabkeyboard(); grabkeyboard();
readstdin(); readstdin();
} else { } else {

View File

@ -1,10 +1,10 @@
#!/bin/sh #!/bin/sh
cachedir=${XDG_CACHE_HOME:-"$HOME/.cache"}
if [ -d "$cachedir" ]; then cachedir="${XDG_CACHE_HOME:-"$HOME/.cache"}"
cache=$cachedir/dmenu_run cache="$cachedir/dmenu_run"
else
cache=$HOME/.dmenu_cache # if no xdg dir, fall back to dotfile in ~ [ ! -e "$cachedir" ] && mkdir -p "$cachedir"
fi
IFS=: IFS=:
if stest -dqr -n "$cache" $PATH; then if stest -dqr -n "$cache" $PATH; then
stest -flx $PATH | sort -u | tee "$cache" stest -flx $PATH | sort -u | tee "$cache"

16
drw.c
View File

@ -132,6 +132,19 @@ xfont_create(Drw *drw, const char *fontname, FcPattern *fontpattern)
die("no font specified."); die("no font specified.");
} }
/* Do not allow using color fonts. This is a workaround for a BadLength
* error from Xft with color glyphs. Modelled on the Xterm workaround. See
* https://bugzilla.redhat.com/show_bug.cgi?id=1498269
* https://lists.suckless.org/dev/1701/30932.html
* https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=916349
* and lots more all over the internet.
*/
FcBool iscol;
if(FcPatternGetBool(xfont->pattern, FC_COLOR, 0, &iscol) == FcResultMatch && iscol) {
XftFontClose(drw->dpy, xfont);
return NULL;
}
font = ecalloc(1, sizeof(Fnt)); font = ecalloc(1, sizeof(Fnt));
font->xfont = xfont; font->xfont = xfont;
font->pattern = pattern; font->pattern = pattern;
@ -200,7 +213,7 @@ drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount)
Clr *ret; Clr *ret;
/* need at least two colors for a scheme */ /* need at least two colors for a scheme */
if (!drw || !clrnames || clrcount < 2 || !(ret = ecalloc(clrcount, sizeof(Clr)))) if (!drw || !clrnames || clrcount < 2 || !(ret = ecalloc(clrcount, sizeof(XftColor))))
return NULL; return NULL;
for (i = 0; i < clrcount; i++) for (i = 0; i < clrcount; i++)
@ -337,6 +350,7 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
fcpattern = FcPatternDuplicate(drw->fonts->pattern); fcpattern = FcPatternDuplicate(drw->fonts->pattern);
FcPatternAddCharSet(fcpattern, FC_CHARSET, fccharset); FcPatternAddCharSet(fcpattern, FC_CHARSET, fccharset);
FcPatternAddBool(fcpattern, FC_SCALABLE, FcTrue); FcPatternAddBool(fcpattern, FC_SCALABLE, FcTrue);
FcPatternAddBool(fcpattern, FC_COLOR, FcFalse);
FcConfigSubstitute(NULL, fcpattern, FcMatchPattern); FcConfigSubstitute(NULL, fcpattern, FcMatchPattern);
FcDefaultSubstitute(fcpattern); FcDefaultSubstitute(fcpattern);