From cdf3b51d7afc3cf95e84c1784ecaa5605269212d Mon Sep 17 00:00:00 2001 From: Jean-Marie Mineau Date: Sun, 11 Oct 2020 11:49:31 +0200 Subject: [PATCH] border patch --- config.def.h | 3 + config.def.h.orig | 25 + config.h | 3 + dmenu | Bin 44048 -> 44096 bytes dmenu-border-4.9.diff | 25 + dmenu-borderoption-20200217-bf60a1e.diff | 46 -- dmenu.c | 3 +- dmenu.c.orig | 796 +++++++++++++++++++++++ dmenu.o | Bin 33632 -> 33808 bytes 9 files changed, 854 insertions(+), 47 deletions(-) create mode 100644 config.def.h.orig create mode 100644 dmenu-border-4.9.diff delete mode 100644 dmenu-borderoption-20200217-bf60a1e.diff create mode 100644 dmenu.c.orig diff --git a/config.def.h b/config.def.h index 88ef264..890a9d4 100644 --- a/config.def.h +++ b/config.def.h @@ -23,3 +23,6 @@ static unsigned int lines = 0; * for example: " /?\"&[]" */ static const char worddelimiters[] = " "; + +/* Size of the window border */ +static const unsigned int border_width = 5; diff --git a/config.def.h.orig b/config.def.h.orig new file mode 100644 index 0000000..88ef264 --- /dev/null +++ b/config.def.h.orig @@ -0,0 +1,25 @@ +/* See LICENSE file for copyright and license details. */ +/* Default settings; can be overriden by command line. */ + +static int topbar = 1; /* -b option; if 0, dmenu appears at bottom */ +static int centered = 0; /* -c option; centers dmenu on screen */ +static int min_width = 500; /* minimum width when centered */ +/* -fn option overrides fonts[0]; default X11 font or font set */ +static const char *fonts[] = { + "monospace:size=10" +}; +static const char *prompt = NULL; /* -p option; prompt to the left of input field */ +static const char *colors[SchemeLast][2] = { + /* fg bg */ + [SchemeNorm] = { "#bbbbbb", "#222222" }, + [SchemeSel] = { "#eeeeee", "#005577" }, + [SchemeOut] = { "#000000", "#00ffff" }, +}; +/* -l option; if nonzero, dmenu uses vertical list with given number of lines */ +static unsigned int lines = 0; + +/* + * Characters not considered part of a word while deleting words + * for example: " /?\"&[]" + */ +static const char worddelimiters[] = " "; diff --git a/config.h b/config.h index 6a2bf95..636ec46 100644 --- a/config.h +++ b/config.h @@ -25,3 +25,6 @@ static unsigned int lines = 0; * for example: " /?\"&[]" */ static const char worddelimiters[] = " "; + +/* Size of the window border */ +static const unsigned int border_width = 5; diff --git a/dmenu b/dmenu index 02b8de6e6c6c87893f282323a67f5bdd77b25149..3db7a004b920d8ce5d68647e2531fa15b4fde13a 100755 GIT binary patch delta 10343 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 delta 10248 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 fwQmP>SB>l+?>rEmyIPaE*bndY7G)OyZpwcHW -Date: Mon, 17 Feb 2020 11:02:35 -0500 -Subject: [PATCH] added border with option - - -diff --git a/config.def.h b/config.def.h -index 1edb647..dd3eb31 100644 ---- a/config.def.h -+++ b/config.def.h -@@ -21,3 +21,6 @@ static unsigned int lines = 0; - * for example: " /?\"&[]" - */ - static const char worddelimiters[] = " "; -+ -+/* Size of the window border */ -+static unsigned int border_width = 0; -diff --git a/dmenu.c b/dmenu.c -index 65f25ce..f0c3c6f 100644 ---- a/dmenu.c -+++ b/dmenu.c -@@ -659,9 +659,11 @@ setup(void) - swa.override_redirect = True; - swa.background_pixel = scheme[SchemeNorm][ColBg].pixel; - swa.event_mask = ExposureMask | KeyPressMask | VisibilityChangeMask; -- win = XCreateWindow(dpy, parentwin, x, y, mw, mh, 0, -+ win = XCreateWindow(dpy, parentwin, x, y, mw, mh, border_width, - CopyFromParent, CopyFromParent, CopyFromParent, - CWOverrideRedirect | CWBackPixel | CWEventMask, &swa); -+ if (border_width) -+ XSetWindowBorder(dpy, win, scheme[SchemeSel][ColBg].pixel); - XSetClassHint(dpy, win, &ch); - - -@@ -733,6 +735,8 @@ main(int argc, char *argv[]) - colors[SchemeSel][ColFg] = argv[++i]; - else if (!strcmp(argv[i], "-w")) /* embedding window id */ - embed = argv[++i]; -+ else if (!strcmp(argv[i], "-bw")) -+ border_width = atoi(argv[++i]); /* border width */ - else - usage(); - --- -2.24.1 - diff --git a/dmenu.c b/dmenu.c index 041c7f8..70e5922 100644 --- a/dmenu.c +++ b/dmenu.c @@ -682,9 +682,10 @@ setup(void) swa.override_redirect = True; swa.background_pixel = scheme[SchemeNorm][ColBg].pixel; swa.event_mask = ExposureMask | KeyPressMask | VisibilityChangeMask; - win = XCreateWindow(dpy, parentwin, x, y, mw, mh, 0, + win = XCreateWindow(dpy, parentwin, x, y, mw, mh, border_width, CopyFromParent, CopyFromParent, CopyFromParent, CWOverrideRedirect | CWBackPixel | CWEventMask, &swa); + XSetWindowBorder(dpy, win, scheme[SchemeSel][ColBg].pixel); XSetClassHint(dpy, win, &ch); diff --git a/dmenu.c.orig b/dmenu.c.orig new file mode 100644 index 0000000..041c7f8 --- /dev/null +++ b/dmenu.c.orig @@ -0,0 +1,796 @@ +/* See LICENSE file for copyright and license details. */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#ifdef XINERAMA +#include +#endif +#include + +#include "drw.h" +#include "util.h" + +/* macros */ +#define INTERSECT(x,y,w,h,r) (MAX(0, MIN((x)+(w),(r).x_org+(r).width) - MAX((x),(r).x_org)) \ + * MAX(0, MIN((y)+(h),(r).y_org+(r).height) - MAX((y),(r).y_org))) +#define LENGTH(X) (sizeof X / sizeof X[0]) +#define TEXTW(X) (drw_fontset_getwidth(drw, (X)) + lrpad) + +/* enums */ +enum { SchemeNorm, SchemeSel, SchemeOut, SchemeLast }; /* color schemes */ + +struct item { + char *text; + struct item *left, *right; + int out; +}; + +static char text[BUFSIZ] = ""; +static char *embed; +static int bh, mw, mh; +static int inputw = 0, promptw; +static int lrpad; /* sum of left and right padding */ +static size_t cursor; +static struct item *items = NULL; +static struct item *matches, *matchend; +static struct item *prev, *curr, *next, *sel; +static int mon = -1, screen; + +static Atom clip, utf8; +static Display *dpy; +static Window root, parentwin, win; +static XIC xic; + +static Drw *drw; +static Clr *scheme[SchemeLast]; + +#include "config.h" + +static int (*fstrncmp)(const char *, const char *, size_t) = strncmp; +static char *(*fstrstr)(const char *, const char *) = strstr; + +static void +appenditem(struct item *item, struct item **list, struct item **last) +{ + if (*last) + (*last)->right = item; + else + *list = item; + + item->left = *last; + item->right = NULL; + *last = item; +} + +static void +calcoffsets(void) +{ + int i, n; + + if (lines > 0) + n = lines * bh; + else + n = mw - (promptw + inputw + TEXTW("<") + TEXTW(">")); + /* calculate which items will begin the next page and previous page */ + for (i = 0, next = curr; next; next = next->right) + if ((i += (lines > 0) ? bh : MIN(TEXTW(next->text), n)) > n) + break; + for (i = 0, prev = curr; prev && prev->left; prev = prev->left) + if ((i += (lines > 0) ? bh : MIN(TEXTW(prev->left->text), n)) > n) + break; +} + +static int +max_textw(void) +{ + int len = 0; + for (struct item *item = items; item && item->text; item++) + len = MAX(TEXTW(item->text), len); + return len; +} + +static void +cleanup(void) +{ + size_t i; + + XUngrabKey(dpy, AnyKey, AnyModifier, root); + for (i = 0; i < SchemeLast; i++) + free(scheme[i]); + drw_free(drw); + XSync(dpy, False); + XCloseDisplay(dpy); +} + +static char * +cistrstr(const char *s, const char *sub) +{ + size_t len; + + for (len = strlen(sub); *s; s++) + if (!strncasecmp(s, sub, len)) + return (char *)s; + return NULL; +} + +static int +drawitem(struct item *item, int x, int y, int w) +{ + if (item == sel) + drw_setscheme(drw, scheme[SchemeSel]); + else if (item->out) + drw_setscheme(drw, scheme[SchemeOut]); + else + drw_setscheme(drw, scheme[SchemeNorm]); + + return drw_text(drw, x, y, w, bh, lrpad / 2, item->text, 0); +} + +static void +drawmenu(void) +{ + unsigned int curpos; + struct item *item; + int x = 0, y = 0, w; + + drw_setscheme(drw, scheme[SchemeNorm]); + drw_rect(drw, 0, 0, mw, mh, 1, 1); + + if (prompt && *prompt) { + drw_setscheme(drw, scheme[SchemeSel]); + x = drw_text(drw, x, 0, promptw, bh, lrpad / 2, prompt, 0); + } + /* draw input field */ + w = (lines > 0 || !matches) ? mw - x : inputw; + drw_setscheme(drw, scheme[SchemeNorm]); + drw_text(drw, x, 0, w, bh, lrpad / 2, text, 0); + + curpos = TEXTW(text) - TEXTW(&text[cursor]); + if ((curpos += lrpad / 2 - 1) < w) { + drw_setscheme(drw, scheme[SchemeNorm]); + drw_rect(drw, x + curpos, 2, 2, bh - 4, 1, 0); + } + + if (lines > 0) { + /* draw vertical list */ + for (item = curr; item != next; item = item->right) + drawitem(item, x, y += bh, mw - x); + } else if (matches) { + /* draw horizontal list */ + x += inputw; + w = TEXTW("<"); + if (curr->left) { + drw_setscheme(drw, scheme[SchemeNorm]); + drw_text(drw, x, 0, w, bh, lrpad / 2, "<", 0); + } + x += w; + for (item = curr; item != next; item = item->right) + x = drawitem(item, x, 0, MIN(TEXTW(item->text), mw - x - TEXTW(">"))); + if (next) { + w = TEXTW(">"); + drw_setscheme(drw, scheme[SchemeNorm]); + drw_text(drw, mw - w, 0, w, bh, lrpad / 2, ">", 0); + } + } + 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, + GrabModeAsync, CurrentTime) == GrabSuccess) + return; + nanosleep(&ts, NULL); + } + die("cannot grab keyboard"); +} + +static void +match(void) +{ + static char **tokv = NULL; + static int tokn = 0; + + char buf[sizeof text], *s; + int i, tokc = 0; + size_t len, textsize; + struct item *item, *lprefix, *lsubstr, *prefixend, *substrend; + + strcpy(buf, text); + /* 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:", tokn * sizeof *tokv); + len = tokc ? strlen(tokv[0]) : 0; + + matches = lprefix = lsubstr = matchend = prefixend = substrend = NULL; + textsize = strlen(text) + 1; + for (item = items; item && item->text; item++) { + for (i = 0; i < tokc; i++) + if (!fstrstr(item->text, tokv[i])) + break; + if (i != tokc) /* not all tokens match */ + continue; + /* exact matches go first, then prefixes, then substrings */ + if (!tokc || !fstrncmp(text, item->text, textsize)) + appenditem(item, &matches, &matchend); + else if (!fstrncmp(tokv[0], item->text, len)) + appenditem(item, &lprefix, &prefixend); + else + appenditem(item, &lsubstr, &substrend); + } + if (lprefix) { + if (matches) { + matchend->right = lprefix; + lprefix->left = matchend; + } else + matches = lprefix; + matchend = prefixend; + } + if (lsubstr) { + if (matches) { + matchend->right = lsubstr; + lsubstr->left = matchend; + } else + matches = lsubstr; + matchend = substrend; + } + curr = sel = matches; + calcoffsets(); +} + +static void +insert(const char *str, ssize_t n) +{ + if (strlen(text) + n > sizeof text - 1) + return; + /* move existing text out of the way, insert new text, and update cursor */ + memmove(&text[cursor + n], &text[cursor], sizeof text - cursor - MAX(n, 0)); + if (n > 0) + memcpy(&text[cursor], str, n); + cursor += n; + match(); +} + +static size_t +nextrune(int inc) +{ + ssize_t n; + + /* return location of next utf8 rune in the given direction (+1 or -1) */ + for (n = cursor + inc; n + inc >= 0 && (text[n] & 0xc0) == 0x80; n += inc) + ; + return n; +} + +static void +movewordedge(int dir) +{ + if (dir < 0) { /* move cursor to the start of the word*/ + while (cursor > 0 && strchr(worddelimiters, text[nextrune(-1)])) + cursor = nextrune(-1); + while (cursor > 0 && !strchr(worddelimiters, text[nextrune(-1)])) + cursor = nextrune(-1); + } else { /* move cursor to the end of the word */ + while (text[cursor] && strchr(worddelimiters, text[cursor])) + cursor = nextrune(+1); + while (text[cursor] && !strchr(worddelimiters, text[cursor])) + cursor = nextrune(+1); + } +} + +static void +keypress(XKeyEvent *ev) +{ + char buf[32]; + int len; + KeySym ksym; + Status status; + + len = XmbLookupString(xic, ev, buf, sizeof buf, &ksym, &status); + switch (status) { + default: /* XLookupNone, XBufferOverflow */ + return; + case XLookupChars: + goto insert; + case XLookupKeySym: + case XLookupBoth: + break; + } + + if (ev->state & ControlMask) { + switch(ksym) { + case XK_a: ksym = XK_Home; break; + case XK_b: ksym = XK_Left; break; + case XK_c: ksym = XK_Escape; break; + case XK_d: ksym = XK_Delete; break; + case XK_e: ksym = XK_End; break; + case XK_f: ksym = XK_Right; break; + case XK_g: ksym = XK_Escape; break; + case XK_h: ksym = XK_BackSpace; break; + case XK_i: ksym = XK_Tab; break; + case XK_j: /* fallthrough */ + case XK_J: /* fallthrough */ + case XK_m: /* fallthrough */ + case XK_M: ksym = XK_Return; ev->state &= ~ControlMask; break; + case XK_n: ksym = XK_Down; break; + case XK_p: ksym = XK_Up; break; + + case XK_k: /* delete right */ + text[cursor] = '\0'; + match(); + break; + case XK_u: /* delete left */ + insert(NULL, 0 - cursor); + break; + case XK_w: /* delete word */ + while (cursor > 0 && strchr(worddelimiters, text[nextrune(-1)])) + insert(NULL, nextrune(-1) - cursor); + while (cursor > 0 && !strchr(worddelimiters, text[nextrune(-1)])) + insert(NULL, nextrune(-1) - cursor); + break; + case XK_y: /* paste selection */ + case XK_Y: + XConvertSelection(dpy, (ev->state & ShiftMask) ? clip : XA_PRIMARY, + utf8, utf8, win, CurrentTime); + return; + case XK_Left: + movewordedge(-1); + goto draw; + case XK_Right: + movewordedge(+1); + goto draw; + case XK_Return: + case XK_KP_Enter: + break; + case XK_bracketleft: + cleanup(); + exit(1); + default: + return; + } + } else if (ev->state & Mod1Mask) { + switch(ksym) { + case XK_b: + movewordedge(-1); + goto draw; + case XK_f: + movewordedge(+1); + goto draw; + case XK_g: ksym = XK_Home; break; + case XK_G: ksym = XK_End; break; + case XK_h: ksym = XK_Up; break; + case XK_j: ksym = XK_Next; break; + case XK_k: ksym = XK_Prior; break; + case XK_l: ksym = XK_Down; break; + default: + return; + } + } + + switch(ksym) { + default: +insert: + if (!iscntrl(*buf)) + insert(buf, len); + break; + case XK_Delete: + if (text[cursor] == '\0') + return; + cursor = nextrune(+1); + /* fallthrough */ + case XK_BackSpace: + if (cursor == 0) + return; + insert(NULL, nextrune(-1) - cursor); + break; + case XK_End: + if (text[cursor] != '\0') { + cursor = strlen(text); + break; + } + if (next) { + /* jump to end of list and position items in reverse */ + curr = matchend; + calcoffsets(); + curr = prev; + calcoffsets(); + while (next && (curr = curr->right)) + calcoffsets(); + } + sel = matchend; + break; + case XK_Escape: + cleanup(); + exit(1); + case XK_Home: + if (sel == matches) { + cursor = 0; + break; + } + sel = curr = matches; + calcoffsets(); + break; + case XK_Left: + if (cursor > 0 && (!sel || !sel->left || lines > 0)) { + cursor = nextrune(-1); + break; + } + if (lines > 0) + return; + /* fallthrough */ + case XK_Up: + if (sel && sel->left && (sel = sel->left)->right == curr) { + curr = prev; + calcoffsets(); + } + break; + case XK_Next: + if (!next) + return; + sel = curr = next; + calcoffsets(); + break; + case XK_Prior: + if (!prev) + return; + sel = curr = prev; + calcoffsets(); + break; + case XK_Return: + case XK_KP_Enter: + puts((sel && !(ev->state & ShiftMask)) ? sel->text : text); + if (!(ev->state & ControlMask)) { + cleanup(); + exit(0); + } + if (sel) + sel->out = 1; + break; + case XK_Right: + if (text[cursor] != '\0') { + cursor = nextrune(+1); + break; + } + if (lines > 0) + return; + /* fallthrough */ + case XK_Down: + if (sel && sel->right && (sel = sel->right) == next) { + curr = next; + calcoffsets(); + } + break; + case XK_Tab: + if (!sel) + return; + strncpy(text, sel->text, sizeof text - 1); + text[sizeof text - 1] = '\0'; + cursor = strlen(text); + match(); + break; + } + +draw: + drawmenu(); +} + +static void +paste(void) +{ + char *p, *q; + int di; + unsigned long dl; + Atom da; + + /* we have been given the current selection, now insert it into input */ + if (XGetWindowProperty(dpy, win, utf8, 0, (sizeof text / 4) + 1, False, + utf8, &da, &di, &dl, &dl, (unsigned char **)&p) + == Success && p) { + insert(p, (q = strchr(p, '\n')) ? q - p : (ssize_t)strlen(p)); + XFree(p); + } + drawmenu(); +} + +static void +readstdin(void) +{ + char buf[sizeof text], *p; + size_t i, imax = 0, size = 0; + unsigned int tmpmax = 0; + + /* read each line from stdin and add it to the item list */ + for (i = 0; fgets(buf, sizeof buf, stdin); i++) { + if (i + 1 >= size / sizeof *items) + if (!(items = realloc(items, (size += BUFSIZ)))) + die("cannot realloc %u bytes:", size); + if ((p = strchr(buf, '\n'))) + *p = '\0'; + if (!(items[i].text = strdup(buf))) + die("cannot strdup %u bytes:", strlen(buf) + 1); + items[i].out = 0; + drw_font_getexts(drw->fonts, buf, strlen(buf), &tmpmax, NULL); + if (tmpmax > inputw) { + inputw = tmpmax; + imax = i; + } + } + if (items) + items[i].text = NULL; + inputw = items ? TEXTW(items[imax].text) : 0; + lines = MIN(lines, i); +} + +static void +run(void) +{ + XEvent ev; + + while (!XNextEvent(dpy, &ev)) { + if (XFilterEvent(&ev, win)) + continue; + switch(ev.type) { + case DestroyNotify: + if (ev.xdestroywindow.window != win) + break; + cleanup(); + exit(1); + case Expose: + 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; + case SelectionNotify: + if (ev.xselection.property == utf8) + paste(); + break; + case VisibilityNotify: + if (ev.xvisibility.state != VisibilityUnobscured) + XRaiseWindow(dpy, win); + break; + } + } +} + +static void +setup(void) +{ + int x, y, i, j; + unsigned int du; + XSetWindowAttributes swa; + XIM xim; + Window w, dw, *dws; + XWindowAttributes wa; + XClassHint ch = {"dmenu", "dmenu"}; +#ifdef XINERAMA + XineramaScreenInfo *info; + Window pw; + int a, di, n, area = 0; +#endif + /* init appearance */ + 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); + + /* calculate menu geometry */ + bh = drw->fonts->h + 2; + lines = MAX(lines, 0); + mh = (lines + 1) * bh; + promptw = (prompt && *prompt) ? TEXTW(prompt) - lrpad / 4 : 0; +#ifdef XINERAMA + i = 0; + if (parentwin == root && (info = XineramaQueryScreens(dpy, &n))) { + XGetInputFocus(dpy, &w, &di); + if (mon >= 0 && mon < n) + i = mon; + else if (w != root && w != PointerRoot && w != None) { + /* find top-level window containing current input focus */ + do { + if (XQueryTree(dpy, (pw = w), &dw, &w, &dws, &du) && dws) + XFree(dws); + } while (w != root && w != pw); + /* find xinerama screen with which the window intersects most */ + if (XGetWindowAttributes(dpy, pw, &wa)) + for (j = 0; j < n; j++) + if ((a = INTERSECT(wa.x, wa.y, wa.width, wa.height, info[j])) > area) { + area = a; + i = j; + } + } + /* no focused window is on screen, so use pointer location instead */ + if (mon < 0 && !area && XQueryPointer(dpy, root, &dw, &dw, &x, &y, &di, &di, &du)) + for (i = 0; i < n; i++) + if (INTERSECT(x, y, 1, 1, info[i])) + break; + + if (centered) { + mw = MIN(MAX(max_textw() + promptw, min_width), info[i].width); + x = info[i].x_org + ((info[i].width - mw) / 2); + y = info[i].y_org + ((info[i].height - mh) / 2); + } else { + x = info[i].x_org; + y = info[i].y_org + (topbar ? 0 : info[i].height - mh); + mw = info[i].width; + } + + XFree(info); + } else +#endif + { + if (!XGetWindowAttributes(dpy, parentwin, &wa)) + die("could not get embedding window attributes: 0x%lx", + parentwin); + + if (centered) { + mw = MIN(MAX(max_textw() + promptw, min_width), wa.width); + x = (wa.width - mw) / 2; + y = (wa.height - mh) / 2; + } else { + x = 0; + y = topbar ? 0 : wa.height - mh; + mw = wa.width; + } + } + inputw = MIN(inputw, mw/3); + match(); + + /* create menu window */ + swa.override_redirect = True; + swa.background_pixel = scheme[SchemeNorm][ColBg].pixel; + swa.event_mask = ExposureMask | KeyPressMask | VisibilityChangeMask; + win = XCreateWindow(dpy, parentwin, x, y, mw, mh, 0, + CopyFromParent, CopyFromParent, CopyFromParent, + CWOverrideRedirect | CWBackPixel | CWEventMask, &swa); + XSetClassHint(dpy, win, &ch); + + + /* input methods */ + if ((xim = XOpenIM(dpy, NULL, NULL, NULL)) == NULL) + die("XOpenIM failed: could not open input device"); + + xic = XCreateIC(xim, XNInputStyle, XIMPreeditNothing | XIMStatusNothing, + XNClientWindow, win, XNFocusWindow, win, NULL); + + XMapRaised(dpy, win); + if (embed) { + XSelectInput(dpy, parentwin, FocusChangeMask | SubstructureNotifyMask); + 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(); +} + +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] [-w windowid]\n", stderr); + exit(1); +} + +int +main(int argc, char *argv[]) +{ + XWindowAttributes wa; + int i, fast = 0; + + for (i = 1; i < argc; i++) + /* these options take no arguments */ + if (!strcmp(argv[i], "-v")) { /* prints version information */ + puts("dmenu-"VERSION); + exit(0); + } else if (!strcmp(argv[i], "-b")) /* appears at the bottom of the screen */ + topbar = 0; + else if (!strcmp(argv[i], "-f")) /* grabs keyboard before reading stdin */ + fast = 1; + else if (!strcmp(argv[i], "-c")) /* centers dmenu on screen */ + centered = 1; + else if (!strcmp(argv[i], "-i")) { /* case-insensitive item matching */ + fstrncmp = strncasecmp; + fstrstr = cistrstr; + } else if (i + 1 == argc) + usage(); + /* these options take one argument */ + else if (!strcmp(argv[i], "-l")) /* number of lines in vertical list */ + lines = atoi(argv[++i]); + else if (!strcmp(argv[i], "-m")) + mon = atoi(argv[++i]); + else if (!strcmp(argv[i], "-p")) /* adds prompt to left of input field */ + prompt = argv[++i]; + else if (!strcmp(argv[i], "-fn")) /* font or font set */ + fonts[0] = argv[++i]; + else if (!strcmp(argv[i], "-nb")) /* normal background color */ + colors[SchemeNorm][ColBg] = argv[++i]; + else if (!strcmp(argv[i], "-nf")) /* normal foreground color */ + colors[SchemeNorm][ColFg] = argv[++i]; + else if (!strcmp(argv[i], "-sb")) /* selected background color */ + 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"); + screen = DefaultScreen(dpy); + root = RootWindow(dpy, screen); + 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; + +#ifdef __OpenBSD__ + if (pledge("stdio rpath", NULL) == -1) + die("pledge"); +#endif + + if (fast && !isatty(0)) { + grabkeyboard(); + readstdin(); + } else { + readstdin(); + grabkeyboard(); + } + setup(); + run(); + + return 1; /* unreachable */ +} diff --git a/dmenu.o b/dmenu.o index 254a18126948ad15772f74465a42530be101553c..49cdd4c7b6ea62ba0087c1eb63b41ccb16d54359 100644 GIT binary patch delta 3387 zcmZ{me{54#6vunZHt1HMmB{r;48wJyqKQ<(#*i`U57LE(urOhenXIx62HR-I*w}{9 zjzRVV!{$LiF|Z~=W;BLcjbI>b0d=V08qn}7x*~>=Ed2OG0&2u_@4FXoZo*COdGDRi z_k8bpw|%c2-eK)-w|2Y9Q0%#9oYu|^h&ZRjS2;fzH!HQv?^@DT?DCITaQM3N`C;4X znZAy1eI2Rn%KuKa%jfIj=f18b4)CT=if2E)A|1l670{iP62IhnaSS;HHuti$k_q87 zYh}E`z28nw#mVfS2w4cB97>9LEakD1#}JQOc{9!KMMbHge2 zlLp5-=^Sn-g8(`8;-%0!;! z_Tc>Ip*dEwDpJcFj0Q!sSJAx9{o5gdtLz0YDi0{iT19z?xfx$7J(MZ*I7G2_P@!)r z^elL)D7nDU28t2Dj3I}sy^R~F7-#ERg(Zk~U9u(D3 z*jHoEW{xQY0}k5+^T>8#El#-$Q@~kE$+Hlvp@v6jui_MpM?ajl{wM8WQ5%>e=p*31(5ZW z)Ib1ZJwI>ZaVN_d?<-ZTQtsU$rZM7zvfkI=l>2ZJ29TanYMJ6goNNriU8GkZLw|>9 zK}tp-g7G#KVZ6sPf3r-X)nR(DUYO@L^U`A1@;gPIJ|>?HNpyYzydg^Rz!{=Op{9%r zhoxLo0U=a2@Yu#PQ5KCptxB$Y3=&Ac(P*3SJjdy;8kMzwaR0F|P)A7?1nQ_U%V`#} zyJl1F^IT3}S18+)v8LFvlsOndjmjPxIc?LZ?4bjuZJ^{m-ot0$tf$6Tn(}g{xy%WO zpz<{9gq(rc25S7QDa%DaqmV@Umqz8cnnD6s$$7#Qv-?n=zD3|gx=c{H5Axes1|g&s z8oeQYJGVl#o_cmDl)1}wyOb3_!o1wuKDb#wopge8BQ=hT_sKZ3IsO^U#PfdeBHbh2 zC*tFLL+^hZ(qlvXm&32+Q$&7=mLDhb#aiAj@+Df{VdiH% z`fy~^IpSqerWKSyQ6n`riVuLjg4mE%oe)9#xu8K4KBC`24C!`3H)(Vjl8vP zO&8nOrsWrje7lxk0Nzd1m@H_wMrT6^sb6f$K8-GhDAHmXNE0>M z#kxl{x&}N*&kK4~qd^EDeO~N*zef9@2dR881~u9b14vJcui%hIPrzNIx5T;^HF^%F zHPb@*U<_+CL-cc9%gdj)5iNffBF)rT=rGfFG`byPNZsOwoDu*4 delta 3202 zcmZ{mYiv|S6vua#7FwXlLU4KkwUtG-7);j$+Gt@ZXxM5KSVRg@v@3+tWm~#DWT6nc zEy_D~JrbUQmI(5acG-Z02xI`#ocmAwG_? zH-&v$*h*n*gpCT@By6*=Ey5lXwnNy9!v0J)IkC7p15TH;CF{l?9L-80zJRl7;6*zN zf@t3-j}^+MVjYeQ?Ax&a^^e_FKpJU-Mr$>?j`CRBBy}RG)aV`vRCDiPjeelfHZA9N z&3{tVc1BcnUW=v5O0ZMA1hHyvT{Y;BHgt4BXBB5R#ZJ@EjY?-<8&QRnr(7ztArj(N zuB1c&yV|=Cx&xf~N#mWaX?ALw*_!`T&Ho;-g`CZU1ZD_<7sn9@zQtJ-f;e6cr6JB5 zA&%qyqJ}TEJiE0#UyB;fLuw%}dn7e#7wT#Z>xTi@sQx|JRsCnAU+Gto2-_71gn3!F zMoFMdRb9%o6GgPBy;@XK)4!_uk3y`1TPJetXv#$Wf!t$C(C-X-K+dlL ztK}nq(CnRY@yEF!qQROA30*sU3$_q-Xz! zegmCY$z||HIO_z4_L}hgDm*tRGrKQ5kA>|6anuZeG}>X1ig4@2f%ZC7FRh!jr;f2g zGX?S&)0>d&eBo&lb|VBa!!C#|=GGTRhP5(7J5kmll;4V|Tf%07YYDf8xNI4%OI=-! z;ew9RC{@+R7GqTrjGb;!wc>0+=Nojhj9mzwOE_Cj8gH}IQ0`XjYV{pP?Daf5crSRD za&~}fV@Dvklv`gJ%6YaB-yU(KzZg_KjgNsL%^hTmY4s3xwfY!HBQ2IxT^V(DCPDr( zZcQ=h&E9sdAOw&u&?seB>()RD>)!}FmW^UzNTG6%JnLC@xVQ&}INk?oq)~Z_<*j`} z4@3Tk+&U&>bB);J5I}lT(maEnh8WVbl6nk!4iZQ&NJ^DZqiaCp%g~MViloJauqpZj zxR!Hki#*X21^bU)htlPI&Fk__=r`!^GH1Er|3mtx8UEYSKg00fm;PCX|4-XL`pK~g}eduqM)Xt!r(>vnWS|#d_oUF5NVa9QG=d?c$Am@Bx!>|?@Iq# z!#_q|*7b(}c}U}0k7QJ{K{@2F;MPm>qqyCmg%ChGPSO^Gz5+3%6C^!o&`FR$8j@AD z8}tq6MtVZhQwE(5u9e)%kypOMpc|nSsX7=J4Z05^NDs){eAS?Pp%v*>x$ZTCwnOJi zUZxI4mqG8zs2he~eS~@pe;at~x#byXyB`{~3W7-c$`{ZhgHC`r(lavFAwSyc={g0e zdOl>gygo8ih(3pV^&IZj_lKh+vY^Y8ksQ9Nycf$$R