X-Git-Url: https://git.armaanb.net/?a=blobdiff_plain;f=dmenu.c;h=91330f191f7b219aff9217c1e20bf51afeb769c4;hb=41379f7c39e6aa0a17d7807b22b49ea148f5b0fa;hp=df51e7695afe2acc97335c637d4efc889fdeb910;hpb=d14670b9959f8b3760b63dd40a70687a90312b8a;p=dmenu.git diff --git a/dmenu.c b/dmenu.c index df51e76..91330f1 100644 --- a/dmenu.c +++ b/dmenu.c @@ -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, @@ -187,7 +206,7 @@ grabkeyboard(void) return; nanosleep(&ts, NULL); } - die("cannot grab keyboard\n"); + die("cannot grab keyboard"); } static void @@ -205,11 +224,11 @@ match(void) /* separate input text into tokens to be matched individually */ for (s = strtok(buf, " "); s; tokv[tokc - 1] = s, s = strtok(NULL, " ")) if (++tokc > tokn && !(tokv = realloc(tokv, ++tokn * sizeof *tokv))) - die("cannot realloc %u bytes\n", tokn * sizeof *tokv); + die("cannot realloc %u bytes:", tokn * sizeof *tokv); len = tokc ? strlen(tokv[0]) : 0; matches = lprefix = lsubstr = matchend = prefixend = substrend = NULL; - textsize = strlen(text); + textsize = strlen(text) + 1; for (item = items; item && item->text; item++) { for (i = 0; i < tokc; i++) if (!fstrstr(item->text, tokv[i])) @@ -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; @@ -515,21 +539,22 @@ run(void) static void setup(void) { - int x, y; + int x, y, i = 0; + unsigned int du; XSetWindowAttributes swa; XIM xim; + Window w, dw, *dws; + XWindowAttributes wa; + XClassHint ch = {"dmenu", "dmenu"}; #ifdef XINERAMA XineramaScreenInfo *info; - Window w, pw, dw, *dws; - XWindowAttributes wa; - int a, j, di, n, i = 0, area = 0; - unsigned int du; + Window pw; + int a, j, di, n, area = 0; #endif /* init appearance */ - scheme[SchemeNorm] = drw_scm_create(drw, colors[SchemeNorm], 2); - scheme[SchemeSel] = drw_scm_create(drw, colors[SchemeSel], 2); - scheme[SchemeOut] = drw_scm_create(drw, colors[SchemeOut], 2); + for (j = 0; j < SchemeLast; j++) + scheme[j] = drw_scm_create(drw, colors[j], 2); clip = XInternAtom(dpy, "CLIPBOARD", False); utf8 = XInternAtom(dpy, "UTF8_STRING", False); @@ -539,7 +564,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 +595,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,10 +610,10 @@ 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); + XSetClassHint(dpy, win, &ch); /* open input methods */ xim = XOpenIM(dpy, NULL, NULL, NULL); @@ -593,6 +621,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(); } @@ -600,14 +637,15 @@ setup(void) static void usage(void) { - fputs("usage: dmenu [-b] [-f] [-i] [-l lines] [-p prompt] [-fn font] [-m monitor]\n" - " [-nb color] [-nf color] [-sb color] [-sf color] [-v]\n", stderr); + fputs("usage: dmenu [-bfiv] [-l lines] [-p prompt] [-fn font] [-m monitor]\n" + " [-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,20 +679,25 @@ 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(); if (!setlocale(LC_CTYPE, "") || !XSupportsLocale()) fputs("warning: no locale support\n", stderr); if (!(dpy = XOpenDisplay(NULL))) - die("cannot open display\n"); + 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.\n"); + die("no fonts could be loaded."); lrpad = drw->fonts->h; if (fast) {