|
|
|
@ -34,8 +34,8 @@ struct item { |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
static char text[BUFSIZ] = ""; |
|
|
|
|
static char *embed; |
|
|
|
|
static int bh, mw, mh; |
|
|
|
|
static int sw, sh; /* X display screen geometry width, height */ |
|
|
|
|
static int inputw = 0, promptw; |
|
|
|
|
static int lrpad; /* sum of left and right padding */ |
|
|
|
|
static size_t cursor; |
|
|
|
@ -46,7 +46,7 @@ static int mon = -1, screen; |
|
|
|
|
|
|
|
|
|
static Atom clip, utf8; |
|
|
|
|
static Display *dpy; |
|
|
|
|
static Window root, win; |
|
|
|
|
static Window root, parentwin, win; |
|
|
|
|
static XIC xic; |
|
|
|
|
|
|
|
|
|
static Drw *drw; |
|
|
|
@ -174,12 +174,31 @@ drawmenu(void) |
|
|
|
|
drw_map(drw, win, 0, 0, mw, mh); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void |
|
|
|
|
grabfocus(void) |
|
|
|
|
{ |
|
|
|
|
struct timespec ts = { .tv_sec = 0, .tv_nsec = 10000000 }; |
|
|
|
|
Window focuswin; |
|
|
|
|
int i, revertwin; |
|
|
|
|
|
|
|
|
|
for (i = 0; i < 100; ++i) { |
|
|
|
|
XGetInputFocus(dpy, &focuswin, &revertwin); |
|
|
|
|
if (focuswin == win) |
|
|
|
|
return; |
|
|
|
|
XSetInputFocus(dpy, win, RevertToParent, CurrentTime); |
|
|
|
|
nanosleep(&ts, NULL); |
|
|
|
|
} |
|
|
|
|
die("cannot grab focus"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void |
|
|
|
|
grabkeyboard(void) |
|
|
|
|
{ |
|
|
|
|
struct timespec ts = { .tv_sec = 0, .tv_nsec = 1000000 }; |
|
|
|
|
int i; |
|
|
|
|
|
|
|
|
|
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(dpy, DefaultRootWindow(dpy), True, GrabModeAsync, |
|
|
|
@ -497,6 +516,11 @@ run(void) |
|
|
|
|
if (ev.xexpose.count == 0) |
|
|
|
|
drw_map(drw, win, 0, 0, mw, mh); |
|
|
|
|
break; |
|
|
|
|
case FocusIn: |
|
|
|
|
/* regrab focus from parent window */ |
|
|
|
|
if (ev.xfocus.window != win) |
|
|
|
|
grabfocus(); |
|
|
|
|
break; |
|
|
|
|
case KeyPress: |
|
|
|
|
keypress(&ev.xkey); |
|
|
|
|
break; |
|
|
|
@ -539,7 +563,7 @@ setup(void) |
|
|
|
|
lines = MAX(lines, 0); |
|
|
|
|
mh = (lines + 1) * bh; |
|
|
|
|
#ifdef XINERAMA |
|
|
|
|
if ((info = XineramaQueryScreens(dpy, &n))) { |
|
|
|
|
if (parentwin == root && (info = XineramaQueryScreens(dpy, &n))) { |
|
|
|
|
XGetInputFocus(dpy, &w, &di); |
|
|
|
|
if (mon >= 0 && mon < n) |
|
|
|
|
i = mon; |
|
|
|
@ -570,9 +594,12 @@ setup(void) |
|
|
|
|
} else |
|
|
|
|
#endif |
|
|
|
|
{ |
|
|
|
|
if (!XGetWindowAttributes(dpy, parentwin, &wa)) |
|
|
|
|
die("could not get embedding window attributes: 0x%lx", |
|
|
|
|
parentwin); |
|
|
|
|
x = 0; |
|
|
|
|
y = topbar ? 0 : sh - mh; |
|
|
|
|
mw = sw; |
|
|
|
|
y = topbar ? 0 : wa.height - mh; |
|
|
|
|
mw = wa.width; |
|
|
|
|
} |
|
|
|
|
promptw = (prompt && *prompt) ? TEXTW(prompt) - lrpad / 4 : 0; |
|
|
|
|
inputw = MIN(inputw, mw/3); |
|
|
|
@ -582,9 +609,8 @@ setup(void) |
|
|
|
|
swa.override_redirect = True; |
|
|
|
|
swa.background_pixel = scheme[SchemeNorm][ColBg].pixel; |
|
|
|
|
swa.event_mask = ExposureMask | KeyPressMask | VisibilityChangeMask; |
|
|
|
|
win = XCreateWindow(dpy, root, x, y, mw, mh, 0, |
|
|
|
|
DefaultDepth(dpy, screen), CopyFromParent, |
|
|
|
|
DefaultVisual(dpy, screen), |
|
|
|
|
win = XCreateWindow(dpy, parentwin, x, y, mw, mh, 0, |
|
|
|
|
CopyFromParent, CopyFromParent, CopyFromParent, |
|
|
|
|
CWOverrideRedirect | CWBackPixel | CWEventMask, &swa); |
|
|
|
|
|
|
|
|
|
/* open input methods */ |
|
|
|
@ -593,6 +619,15 @@ setup(void) |
|
|
|
|
XNClientWindow, win, XNFocusWindow, win, NULL); |
|
|
|
|
|
|
|
|
|
XMapRaised(dpy, win); |
|
|
|
|
if (embed) { |
|
|
|
|
XSelectInput(dpy, parentwin, FocusChangeMask); |
|
|
|
|
if (XQueryTree(dpy, parentwin, &dw, &w, &dws, &du) && dws) { |
|
|
|
|
for (i = 0; i < du && dws[i] != win; ++i) |
|
|
|
|
XSelectInput(dpy, dws[i], FocusChangeMask); |
|
|
|
|
XFree(dws); |
|
|
|
|
} |
|
|
|
|
grabfocus(); |
|
|
|
|
} |
|
|
|
|
drw_resize(drw, mw, mh); |
|
|
|
|
drawmenu(); |
|
|
|
|
} |
|
|
|
@ -601,13 +636,14 @@ static void |
|
|
|
|
usage(void) |
|
|
|
|
{ |
|
|
|
|
fputs("usage: dmenu [-bfiv] [-l lines] [-p prompt] [-fn font] [-m monitor]\n" |
|
|
|
|
" [-nb color] [-nf color] [-sb color] [-sf color]\n", stderr); |
|
|
|
|
" [-nb color] [-nf color] [-sb color] [-sf color] [-w windowid]\n", stderr); |
|
|
|
|
exit(1); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
int |
|
|
|
|
main(int argc, char *argv[]) |
|
|
|
|
{ |
|
|
|
|
XWindowAttributes wa; |
|
|
|
|
int i, fast = 0; |
|
|
|
|
|
|
|
|
|
for (i = 1; i < argc; i++) |
|
|
|
@ -641,6 +677,8 @@ main(int argc, char *argv[]) |
|
|
|
|
colors[SchemeSel][ColBg] = argv[++i]; |
|
|
|
|
else if (!strcmp(argv[i], "-sf")) /* selected foreground color */ |
|
|
|
|
colors[SchemeSel][ColFg] = argv[++i]; |
|
|
|
|
else if (!strcmp(argv[i], "-w")) /* embedding window id */ |
|
|
|
|
embed = argv[++i]; |
|
|
|
|
else |
|
|
|
|
usage(); |
|
|
|
|
|
|
|
|
@ -650,9 +688,12 @@ main(int argc, char *argv[]) |
|
|
|
|
die("cannot open display"); |
|
|
|
|
screen = DefaultScreen(dpy); |
|
|
|
|
root = RootWindow(dpy, screen); |
|
|
|
|
sw = DisplayWidth(dpy, screen); |
|
|
|
|
sh = DisplayHeight(dpy, screen); |
|
|
|
|
drw = drw_create(dpy, screen, root, sw, sh); |
|
|
|
|
if (!embed || !(parentwin = strtol(embed, NULL, 0))) |
|
|
|
|
parentwin = root; |
|
|
|
|
if (!XGetWindowAttributes(dpy, parentwin, &wa)) |
|
|
|
|
die("could not get embedding window attributes: 0x%lx", |
|
|
|
|
parentwin); |
|
|
|
|
drw = drw_create(dpy, screen, root, wa.width, wa.height); |
|
|
|
|
if (!drw_fontset_create(drw, fonts, LENGTH(fonts))) |
|
|
|
|
die("no fonts could be loaded."); |
|
|
|
|
lrpad = drw->fonts->h; |
|
|
|
|