X-Git-Url: https://git.xinqibao.xyz/dmenu.git/blobdiff_plain/b43ec0577f2ad8ad33a0b893fe5360d966036786..0d22715b0a30380c118f6eb8c552bed15ba2417d:/dmenu.c diff --git a/dmenu.c b/dmenu.c index 085dc29..15737ca 100644 --- a/dmenu.c +++ b/dmenu.c @@ -10,6 +10,7 @@ #include #include +#include #include #ifdef XINERAMA #include @@ -25,6 +26,8 @@ #define LENGTH(X) (sizeof X / sizeof X[0]) #define TEXTW(X) (drw_fontset_getwidth(drw, (X)) + lrpad) +#define OPAQUE 0xffU + /* enums */ enum { SchemeNorm, SchemeSel, SchemeOut, SchemeLast }; /* color schemes */ @@ -53,10 +56,16 @@ static XIC xic; static Drw *drw; static Clr *scheme[SchemeLast]; +static int useargb = 0; +static Visual *visual; +static int depth; +static Colormap cmap; + #include "config.h" static int (*fstrncmp)(const char *, const char *, size_t) = strncmp; static char *(*fstrstr)(const char *, const char *) = strstr; +static void xinitvisual(); static unsigned int textw_clamp(const char *str, unsigned int n) @@ -96,6 +105,15 @@ calcoffsets(void) 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) { @@ -415,7 +433,7 @@ keypress(XKeyEvent *ev) switch(ksym) { default: insert: - if (!iscntrl(*buf)) + if (!iscntrl((unsigned char)*buf)) insert(buf, len); break; case XK_Delete: @@ -624,7 +642,7 @@ setup(void) #endif /* init appearance */ for (j = 0; j < SchemeLast; j++) - scheme[j] = drw_scm_create(drw, colors[j], 2); + scheme[j] = drw_scm_create(drw, colors[j], alphas[j], 2); clip = XInternAtom(dpy, "CLIPBOARD", False); utf8 = XInternAtom(dpy, "UTF8_STRING", False); @@ -633,6 +651,7 @@ setup(void) 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))) { @@ -659,9 +678,16 @@ setup(void) if (INTERSECT(x, y, 1, 1, info[i]) != 0) break; - x = info[i].x_org; - y = info[i].y_org + (topbar ? 0 : info[i].height - mh); - mw = info[i].width; + 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 @@ -669,11 +695,17 @@ setup(void) if (!XGetWindowAttributes(dpy, parentwin, &wa)) die("could not get embedding window attributes: 0x%lx", parentwin); - x = 0; - y = topbar ? 0 : wa.height - mh; - mw = wa.width; + + 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; + } } - promptw = (prompt && *prompt) ? TEXTW(prompt) - lrpad / 4 : 0; for (item = items; item && item->text; ++item) { if ((tmp = textw_clamp(item->text, mw/3)) > inputw) { if ((inputw = tmp) == mw/3) @@ -684,11 +716,13 @@ setup(void) /* create menu window */ swa.override_redirect = True; - swa.background_pixel = scheme[SchemeNorm][ColBg].pixel; + swa.background_pixel = 0; + swa.border_pixel = 0; + swa.colormap = cmap; swa.event_mask = ExposureMask | KeyPressMask | VisibilityChangeMask; win = XCreateWindow(dpy, parentwin, x, y, mw, mh, 0, - CopyFromParent, CopyFromParent, CopyFromParent, - CWOverrideRedirect | CWBackPixel | CWEventMask, &swa); + depth, CopyFromParent, visual, + CWOverrideRedirect | CWBackPixel | CWBorderPixel | CWColormap | CWEventMask, &swa); XSetClassHint(dpy, win, &ch); @@ -736,6 +770,8 @@ main(int argc, char *argv[]) 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; @@ -774,7 +810,8 @@ main(int argc, char *argv[]) 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); + xinitvisual(); + drw = drw_create(dpy, screen, root, wa.width, wa.height, visual, depth, cmap); if (!drw_fontset_create(drw, fonts, LENGTH(fonts))) die("no fonts could be loaded."); lrpad = drw->fonts->h; @@ -796,3 +833,40 @@ main(int argc, char *argv[]) return 1; /* unreachable */ } + + void +xinitvisual() +{ + XVisualInfo *infos; + XRenderPictFormat *fmt; + int nitems; + int i; + + XVisualInfo tpl = { + .screen = screen, + .depth = 32, + .class = TrueColor + }; + long masks = VisualScreenMask | VisualDepthMask | VisualClassMask; + + infos = XGetVisualInfo(dpy, masks, &tpl, &nitems); + visual = NULL; + for(i = 0; i < nitems; i ++) { + fmt = XRenderFindVisualFormat(dpy, infos[i].visual); + if (fmt->type == PictTypeDirect && fmt->direct.alphaMask) { + visual = infos[i].visual; + depth = infos[i].depth; + cmap = XCreateColormap(dpy, root, visual, AllocNone); + useargb = 1; + break; + } + } + + XFree(infos); + + if (! visual) { + visual = DefaultVisual(dpy, screen); + depth = DefaultDepth(dpy, screen); + cmap = DefaultColormap(dpy, screen); + } +}