diff --git a/README b/README index 1454170..aedc988 100644 --- a/README +++ b/README @@ -40,6 +40,14 @@ embedded = false; line_height = 22; border_width = 2; min_password_length = 32; +prompt_fg_alpha = 255; +prompt_bg_alpha = 255; +normal_fg_alpha = 255; +normal_bg_alpha = 230; +select_fg_alpha = 255; +select_bg_alpha = 255; +desc_fg_alpha = 255; +desc_bg_alpha = 255; font = "DejaVuSansMono Nerd Font:pixelsize=16:antialias=true:autohint=true"; prompt = ""; asterisk= "*"; diff --git a/config.def.h b/config.def.h index cd0047b..f7a1e77 100644 --- a/config.def.h +++ b/config.def.h @@ -9,6 +9,14 @@ static unsigned int embedded = 0; static unsigned int lineheight = 22; static unsigned int borderwidth = 2; static unsigned int minpwlen = 32; +static unsigned int alphas[SchemeLast][2] = { + /* values between 0 (transparent) and 255 (opaque) */ + /* foreground, background */ + [SchemePrompt] = { 255, 255 }, + [SchemeNormal] = { 255, 230 }, + [SchemeSelect] = { 255, 255 }, + [SchemeDesc] = { 255, 255 }, +}; static const char *fonts[] = { "DejaVuSansMono Nerd Font:pixelsize=16:antialias=true:autohint=true" @@ -20,5 +28,5 @@ static const char *colors[SchemeLast][2] = { [SchemePrompt] = { "#cccccc", "#4185d7" }, [SchemeNormal] = { "#cccccc", "#000000" }, [SchemeSelect] = { "#ffffff", "#4185d7" }, - [SchemeDesc] = { "#cccccc", "#4185d7" } + [SchemeDesc] = { "#cccccc", "#4185d7" }, }; diff --git a/drw.c b/drw.c index c1582e7..6624f95 100644 --- a/drw.c +++ b/drw.c @@ -61,7 +61,7 @@ utf8decode(const char *c, long *u, size_t clen) } Drw * -drw_create(Display *dpy, int screen, Window root, unsigned int w, unsigned int h) +drw_create(Display *dpy, int screen, Window root, unsigned int w, unsigned int h, Visual *visual, unsigned int depth, Colormap cmap) { Drw *drw = ecalloc(1, sizeof(Drw)); @@ -70,8 +70,11 @@ drw_create(Display *dpy, int screen, Window root, unsigned int w, unsigned int h drw->root = root; drw->w = w; drw->h = h; - drw->drawable = XCreatePixmap(dpy, root, w, h, DefaultDepth(dpy, screen)); - drw->gc = XCreateGC(dpy, root, 0, NULL); + drw->visual = visual; + drw->depth = depth; + drw->cmap = cmap; + drw->drawable = XCreatePixmap(dpy, root, w, h, depth); + drw->gc = XCreateGC(dpy, drw->drawable, 0, NULL); XSetLineAttributes(dpy, drw->gc, 1, LineSolid, CapButt, JoinMiter); return drw; @@ -87,7 +90,7 @@ drw_resize(Drw *drw, unsigned int w, unsigned int h) drw->h = h; if (drw->drawable) XFreePixmap(drw->dpy, drw->drawable); - drw->drawable = XCreatePixmap(drw->dpy, drw->root, w, h, DefaultDepth(drw->dpy, drw->screen)); + drw->drawable = XCreatePixmap(drw->dpy, drw->root, w, h, drw->depth); } void @@ -180,21 +183,22 @@ drw_fontset_free(Fnt *font) } void -drw_clr_create(Drw *drw, Clr *dest, const char *clrname) +drw_clr_create(Drw *drw, Clr *dest, const char *clrname, unsigned int alpha) { if (!drw || !dest || !clrname) return; - if (!XftColorAllocName(drw->dpy, DefaultVisual(drw->dpy, drw->screen), - DefaultColormap(drw->dpy, drw->screen), + if (!XftColorAllocName(drw->dpy, drw->visual, drw->cmap, clrname, dest)) die("error, cannot allocate color '%s'", clrname); + + dest->pixel = (dest->pixel & 0x00ffffffU) | (alpha << 24); } /* Wrapper to create color schemes. The caller has to call free(3) on the * returned color scheme when done using it. */ Clr * -drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount) +drw_scm_create(Drw *drw, const char *clrnames[], unsigned int alphas[], size_t clrcount) { size_t i; Clr *ret; @@ -204,7 +208,7 @@ drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount) return NULL; for (i = 0; i < clrcount; i++) - drw_clr_create(drw, &ret[i], clrnames[i]); + drw_clr_create(drw, &ret[i], clrnames[i], alphas[i]); return ret; } @@ -260,9 +264,7 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp } else { XSetForeground(drw->dpy, drw->gc, drw->scheme[invert ? ColFg : ColBg].pixel); XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h); - d = XftDrawCreate(drw->dpy, drw->drawable, - DefaultVisual(drw->dpy, drw->screen), - DefaultColormap(drw->dpy, drw->screen)); + d = XftDrawCreate(drw->dpy, drw->drawable, drw->visual, drw->cmap); x += lpad; w -= lpad; } diff --git a/drw.h b/drw.h index 4c67419..b91a753 100644 --- a/drw.h +++ b/drw.h @@ -20,6 +20,9 @@ typedef struct { Display *dpy; int screen; Window root; + Visual *visual; + unsigned int depth; + Colormap cmap; Drawable drawable; GC gc; Clr *scheme; @@ -27,7 +30,7 @@ typedef struct { } Drw; /* Drawable abstraction */ -Drw *drw_create(Display *dpy, int screen, Window win, unsigned int w, unsigned int h); +Drw *drw_create(Display *dpy, int screen, Window win, unsigned int w, unsigned int h, Visual*, unsigned int, Colormap); void drw_resize(Drw *drw, unsigned int w, unsigned int h); void drw_free(Drw *drw); @@ -38,8 +41,8 @@ unsigned int drw_fontset_getwidth(Drw *drw, const char *text); void drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h); /* Colorscheme abstraction */ -void drw_clr_create(Drw *drw, Clr *dest, const char *clrname); -Clr *drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount); +void drw_clr_create(Drw *drw, Clr *dest, const char *clrname, unsigned int alpha); +Clr *drw_scm_create(Drw *drw, const char *clrnames[], unsigned int alphas[], size_t clrcount); /* Cursor abstraction */ Cur *drw_cur_create(Drw *drw, int shape); diff --git a/pinentry-dmenu.1 b/pinentry-dmenu.1 index 556a7d6..c8efa37 100644 --- a/pinentry-dmenu.1 +++ b/pinentry-dmenu.1 @@ -49,6 +49,35 @@ Defines the border width for the menu. .BI "min_password_length =" " 32" The minimal space of the password field. This value has affect to the description field after the password field. .TP +.BI "prompt_fg_alpha =" " 255" +Defines the prompt foreground alpha value. +Values between +.IR 0 +(transparent) and +.IR 255 +(opaque) are supported. +.TP +.BI "prompt_bg_alpha =" " 255" +Defines the prompt background alpha value. +.TP +.BI "normal_fg_alpha =" " 255" +Defines the normal foreground alpha value. +.TP +.BI "normal_bg_alpha =" " 230" +Defines the normal background alpha value. +.TP +.BI "select_fg_alpha =" " 255" +Defines the selected foreground alpha value. +.TP +.BI "select_bg_alpha =" " 255" +Defines the selected background alpha value. +.TP +.BI "desc_fg_alpha =" " 255" +Defines the description foreground alpha value. +.TP +.BI "desc_bg_alpha =" " 255" +Defines the description background alpha value. +.TP .BI "font =" " DejaVuSansMono Nerd Font:pixelsize=16:antialias=true:autohint=true" Defines the font or font set used. .TP @@ -205,6 +234,14 @@ embedded = false; line_height = 22; border_width = 2; min_password_length = 32; +prompt_fg_alpha = 255; +prompt_bg_alpha = 255; +normal_fg_alpha = 255; +normal_bg_alpha = 230; +select_fg_alpha = 255; +select_bg_alpha = 255; +desc_fg_alpha = 255; +desc_bg_alpha = 255; font = "DejaVuSansMono Nerd Font:pixelsize=16:antialias=true:autohint=true"; prompt = ""; asterisk= "*"; diff --git a/pinentry-dmenu.c b/pinentry-dmenu.c index 24a0608..a0d0e24 100644 --- a/pinentry-dmenu.c +++ b/pinentry-dmenu.c @@ -13,6 +13,7 @@ #include #include +#include #include #ifdef XINERAMA #include @@ -34,7 +35,6 @@ #define TEXTW(X) (drw_fontset_getwidth(drw, (X)) + lrpad) #define MINDESCLEN 8 - enum { SchemePrompt, SchemeNormal, SchemeSelect, SchemeDesc, SchemeLast }; enum { WinPin, WinConfirm }; enum { Ok, NotOk, Cancel }; @@ -62,12 +62,19 @@ static XIC xic; static Drw *drw; static Clr *scheme[SchemeLast]; +static int useargb = 0; +static Visual *visual; +static int depth; +static Colormap cmap; + static int timed_out; static int winmode; pinentry_t pinentry_info; #include "config.h" +static void xinitvisual(); + static int drawitem(const char* text, Bool sel, int x, int y, int w) { unsigned int i = (sel) ? SchemeSelect : SchemeNormal; @@ -274,7 +281,7 @@ drawwin(void) { static void setup(void) { - int x, y, i = 0; + int x, y, i = 0, j; unsigned int du; XSetWindowAttributes swa; XIM xim; @@ -283,14 +290,12 @@ setup(void) { #ifdef XINERAMA XineramaScreenInfo *info; Window pw; - int a, j, di, n, area = 0; + int a, di, n, area = 0; #endif /* Init appearance */ - scheme[SchemePrompt] = drw_scm_create(drw, colors[SchemePrompt], 2); - scheme[SchemeNormal] = drw_scm_create(drw, colors[SchemeNormal], 2); - scheme[SchemeSelect] = drw_scm_create(drw, colors[SchemeSelect], 2); - scheme[SchemeDesc] = drw_scm_create(drw, colors[SchemeDesc], 2); + for (j = 0; j < SchemeLast; j++) + scheme[j] = drw_scm_create(drw, colors[j], alphas[j], 2); clip = XInternAtom(dpy, "CLIPBOARD", False); utf8 = XInternAtom(dpy, "UTF8_STRING", False); @@ -367,11 +372,13 @@ setup(void) { /* Create menu window */ swa.override_redirect = True; - swa.background_pixel = scheme[SchemePrompt][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, borderwidth, - CopyFromParent, CopyFromParent, CopyFromParent, - CWOverrideRedirect | CWBackPixel | CWEventMask, &swa); + depth, CopyFromParent, visual, + CWOverrideRedirect | CWBackPixel | CWBorderPixel | CWColormap | CWEventMask, &swa); if (borderwidth) XSetWindowBorder(dpy, win, scheme[SchemeSelect][ColBg].pixel); @@ -399,11 +406,11 @@ setup(void) { static void cleanup(void) { + size_t i; + XUngrabKey(dpy, AnyKey, AnyModifier, root); - free(scheme[SchemeDesc]); - free(scheme[SchemeSelect]); - free(scheme[SchemeNormal]); - free(scheme[SchemePrompt]); + for (i = 0; i < SchemeLast; i++) + free(scheme[i]); drw_free(drw); XSync(dpy, False); XCloseDisplay(dpy); @@ -687,7 +694,8 @@ cmdhandler(pinentry_t received_pinentry) { 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."); } @@ -813,6 +821,30 @@ main(int argc, char *argv[]) { if (config_lookup_string(&cfg, "desc_bg", &str)) { colors[SchemeDesc][ColBg] = str; } + if (config_lookup_int(&cfg, "prompt_fg_alpha", &val)) { + alphas[SchemePrompt][0] = val; + } + if (config_lookup_int(&cfg, "prompt_bg_alpha", &val)) { + alphas[SchemePrompt][1] = val; + } + if (config_lookup_int(&cfg, "normal_fg_alpha", &val)) { + alphas[SchemeNormal][0] = val; + } + if (config_lookup_int(&cfg, "normal_bg_alpha", &val)) { + alphas[SchemeNormal][1] = val; + } + if (config_lookup_int(&cfg, "select_fg_alpha", &val)) { + alphas[SchemeSelect][0] = val; + } + if (config_lookup_int(&cfg, "select_bg_alpha", &val)) { + alphas[SchemeSelect][1] = val; + } + if (config_lookup_int(&cfg, "desc_fg_alpha", &val)) { + alphas[SchemeDesc][0] = val; + } + if (config_lookup_int(&cfg, "desc_bg_alpha", &val)) { + alphas[SchemeDesc][1] = val; + } } else if ((str = config_error_file(&cfg))) { fprintf(stderr, "%s:%d: %s\n", config_error_file(&cfg), config_error_line(&cfg), config_error_text(&cfg)); @@ -832,3 +864,40 @@ main(int argc, char *argv[]) { return 0; } + +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); + } +}