dmenu-alpha-20230110-5.2.diff (9717B)
1 From 4709ed81c8b8df043420ca9de016054088beb934 Mon Sep 17 00:00:00 2001 2 From: Andrew Slice <edward.andrew.slice@gmail.com> 3 Date: Tue, 10 Jan 2023 17:22:44 -0500 4 Subject: [PATCH] Adds alpha transparency. This also fixes a crash that happens 5 when using '-w' to embed dmenu in a window that has alpha transparency. 6 7 Based on the original patch by Marcin Lukow <marcin@nerdy.cat> 8 --- 9 config.def.h | 7 ++++++ 10 config.mk | 2 +- 11 dmenu.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++----- 12 drw.c | 26 ++++++++++++----------- 13 drw.h | 9 +++++--- 14 5 files changed, 83 insertions(+), 21 deletions(-) 15 16 diff --git a/config.def.h b/config.def.h 17 index 1edb647..809c96e 100644 18 --- a/config.def.h 19 +++ b/config.def.h 20 @@ -2,6 +2,7 @@ 21 /* Default settings; can be overriden by command line. */ 22 23 static int topbar = 1; /* -b option; if 0, dmenu appears at bottom */ 24 +static const unsigned int alpha = 0xff; /* Amount of opacity. 0xff is opaque */ 25 /* -fn option overrides fonts[0]; default X11 font or font set */ 26 static const char *fonts[] = { 27 "monospace:size=10" 28 @@ -13,6 +14,12 @@ static const char *colors[SchemeLast][2] = { 29 [SchemeSel] = { "#eeeeee", "#005577" }, 30 [SchemeOut] = { "#000000", "#00ffff" }, 31 }; 32 + 33 +static const unsigned int alphas[SchemeLast][2] = { 34 + [SchemeNorm] = { OPAQUE, alpha }, 35 + [SchemeSel] = { OPAQUE, alpha }, 36 + [SchemeOut] = { OPAQUE, alpha }, 37 +}; 38 /* -l option; if nonzero, dmenu uses vertical list with given number of lines */ 39 static unsigned int lines = 0; 40 41 diff --git a/config.mk b/config.mk 42 index 566348b..fa2b4fc 100644 43 --- a/config.mk 44 +++ b/config.mk 45 @@ -21,7 +21,7 @@ FREETYPEINC = /usr/include/freetype2 46 47 # includes and libs 48 INCS = -I$(X11INC) -I$(FREETYPEINC) 49 -LIBS = -L$(X11LIB) -lX11 $(XINERAMALIBS) $(FREETYPELIBS) 50 +LIBS = -L$(X11LIB) -lX11 $(XINERAMALIBS) $(FREETYPELIBS) -lXrender 51 52 # flags 53 CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_XOPEN_SOURCE=700 -D_POSIX_C_SOURCE=200809L -DVERSION=\"$(VERSION)\" $(XINERAMAFLAGS) 54 diff --git a/dmenu.c b/dmenu.c 55 index 27b7a30..a20302f 100644 56 --- a/dmenu.c 57 +++ b/dmenu.c 58 @@ -10,10 +10,12 @@ 59 60 #include <X11/Xlib.h> 61 #include <X11/Xatom.h> 62 +#include <X11/Xproto.h> 63 #include <X11/Xutil.h> 64 #ifdef XINERAMA 65 #include <X11/extensions/Xinerama.h> 66 #endif 67 +#include <X11/extensions/Xrender.h> 68 #include <X11/Xft/Xft.h> 69 70 #include "drw.h" 71 @@ -25,6 +27,8 @@ 72 #define LENGTH(X) (sizeof X / sizeof X[0]) 73 #define TEXTW(X) (drw_fontset_getwidth(drw, (X)) + lrpad) 74 75 +#define OPAQUE 0xffu 76 + 77 /* enums */ 78 enum { SchemeNorm, SchemeSel, SchemeOut, SchemeLast }; /* color schemes */ 79 80 @@ -53,10 +57,16 @@ static XIC xic; 81 static Drw *drw; 82 static Clr *scheme[SchemeLast]; 83 84 +static int useargb = 0; 85 +static Visual *visual; 86 +static int depth; 87 +static Colormap cmap; 88 + 89 #include "config.h" 90 91 static int (*fstrncmp)(const char *, const char *, size_t) = strncmp; 92 static char *(*fstrstr)(const char *, const char *) = strstr; 93 +static void xinitvisual(); 94 95 static unsigned int 96 textw_clamp(const char *str, unsigned int n) 97 @@ -627,7 +637,7 @@ setup(void) 98 #endif 99 /* init appearance */ 100 for (j = 0; j < SchemeLast; j++) 101 - scheme[j] = drw_scm_create(drw, colors[j], 2); 102 + scheme[j] = drw_scm_create(drw, colors[j], alphas[i], 2); 103 104 clip = XInternAtom(dpy, "CLIPBOARD", False); 105 utf8 = XInternAtom(dpy, "UTF8_STRING", False); 106 @@ -682,11 +692,13 @@ setup(void) 107 108 /* create menu window */ 109 swa.override_redirect = True; 110 - swa.background_pixel = scheme[SchemeNorm][ColBg].pixel; 111 + swa.background_pixel = 0; 112 + swa.border_pixel = 0; 113 + swa.colormap = cmap; 114 swa.event_mask = ExposureMask | KeyPressMask | VisibilityChangeMask; 115 win = XCreateWindow(dpy, parentwin, x, y, mw, mh, 0, 116 - CopyFromParent, CopyFromParent, CopyFromParent, 117 - CWOverrideRedirect | CWBackPixel | CWEventMask, &swa); 118 + depth, CopyFromParent, visual, 119 + CWOverrideRedirect | CWBackPixel | CWBorderPixel | CWColormap | CWEventMask, &swa); 120 XSetClassHint(dpy, win, &ch); 121 122 123 @@ -771,7 +783,8 @@ main(int argc, char *argv[]) 124 if (!XGetWindowAttributes(dpy, parentwin, &wa)) 125 die("could not get embedding window attributes: 0x%lx", 126 parentwin); 127 - drw = drw_create(dpy, screen, root, wa.width, wa.height); 128 + xinitvisual(); 129 + drw = drw_create(dpy, screen, root, wa.width, wa.height, visual, depth, cmap); 130 if (!drw_fontset_create(drw, fonts, LENGTH(fonts))) 131 die("no fonts could be loaded."); 132 lrpad = drw->fonts->h; 133 @@ -793,3 +806,40 @@ main(int argc, char *argv[]) 134 135 return 1; /* unreachable */ 136 } 137 + 138 +void 139 +xinitvisual() 140 +{ 141 + XVisualInfo *infos; 142 + XRenderPictFormat *fmt; 143 + int nitems; 144 + int i; 145 + 146 + XVisualInfo tpl = { 147 + .screen = screen, 148 + .depth = 32, 149 + .class = TrueColor 150 + }; 151 + long masks = VisualScreenMask | VisualDepthMask | VisualClassMask; 152 + 153 + infos = XGetVisualInfo(dpy, masks, &tpl, &nitems); 154 + visual = NULL; 155 + for(i = 0; i < nitems; i ++) { 156 + fmt = XRenderFindVisualFormat(dpy, infos[i].visual); 157 + if (fmt->type == PictTypeDirect && fmt->direct.alphaMask) { 158 + visual = infos[i].visual; 159 + depth = infos[i].depth; 160 + cmap = XCreateColormap(dpy, root, visual, AllocNone); 161 + useargb = 1; 162 + break; 163 + } 164 + } 165 + 166 + XFree(infos); 167 + 168 + if (! visual) { 169 + visual = DefaultVisual(dpy, screen); 170 + depth = DefaultDepth(dpy, screen); 171 + cmap = DefaultColormap(dpy, screen); 172 + } 173 +} 174 diff --git a/drw.c b/drw.c 175 index a58a2b4..42700e5 100644 176 --- a/drw.c 177 +++ b/drw.c 178 @@ -61,7 +61,7 @@ utf8decode(const char *c, long *u, size_t clen) 179 } 180 181 Drw * 182 -drw_create(Display *dpy, int screen, Window root, unsigned int w, unsigned int h) 183 +drw_create(Display *dpy, int screen, Window root, unsigned int w, unsigned int h, Visual *visual, unsigned int depth, Colormap cmap) 184 { 185 Drw *drw = ecalloc(1, sizeof(Drw)); 186 187 @@ -70,8 +70,11 @@ drw_create(Display *dpy, int screen, Window root, unsigned int w, unsigned int h 188 drw->root = root; 189 drw->w = w; 190 drw->h = h; 191 - drw->drawable = XCreatePixmap(dpy, root, w, h, DefaultDepth(dpy, screen)); 192 - drw->gc = XCreateGC(dpy, root, 0, NULL); 193 + drw->visual = visual; 194 + drw->depth = depth; 195 + drw->cmap = cmap; 196 + drw->drawable = XCreatePixmap(dpy, root, w, h, depth); 197 + drw->gc = XCreateGC(dpy, drw->drawable, 0, NULL); 198 XSetLineAttributes(dpy, drw->gc, 1, LineSolid, CapButt, JoinMiter); 199 200 return drw; 201 @@ -87,7 +90,7 @@ drw_resize(Drw *drw, unsigned int w, unsigned int h) 202 drw->h = h; 203 if (drw->drawable) 204 XFreePixmap(drw->dpy, drw->drawable); 205 - drw->drawable = XCreatePixmap(drw->dpy, drw->root, w, h, DefaultDepth(drw->dpy, drw->screen)); 206 + drw->drawable = XCreatePixmap(drw->dpy, drw->root, w, h, drw->depth); 207 } 208 209 void 210 @@ -181,21 +184,22 @@ drw_fontset_free(Fnt *font) 211 } 212 213 void 214 -drw_clr_create(Drw *drw, Clr *dest, const char *clrname) 215 +drw_clr_create(Drw *drw, Clr *dest, const char *clrname, unsigned int alpha) 216 { 217 if (!drw || !dest || !clrname) 218 return; 219 220 - if (!XftColorAllocName(drw->dpy, DefaultVisual(drw->dpy, drw->screen), 221 - DefaultColormap(drw->dpy, drw->screen), 222 + if (!XftColorAllocName(drw->dpy, drw->visual, drw->cmap, 223 clrname, dest)) 224 die("error, cannot allocate color '%s'", clrname); 225 + 226 + dest->pixel = (dest->pixel & 0x00ffffffU) | (alpha << 24); 227 } 228 229 /* Wrapper to create color schemes. The caller has to call free(3) on the 230 * returned color scheme when done using it. */ 231 Clr * 232 -drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount) 233 +drw_scm_create(Drw *drw, const char *clrnames[], const unsigned int alphas[], size_t clrcount) 234 { 235 size_t i; 236 Clr *ret; 237 @@ -205,7 +209,7 @@ drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount) 238 return NULL; 239 240 for (i = 0; i < clrcount; i++) 241 - drw_clr_create(drw, &ret[i], clrnames[i]); 242 + drw_clr_create(drw, &ret[i], clrnames[i], alphas[i]); 243 return ret; 244 } 245 246 @@ -263,9 +267,7 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp 247 } else { 248 XSetForeground(drw->dpy, drw->gc, drw->scheme[invert ? ColFg : ColBg].pixel); 249 XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h); 250 - d = XftDrawCreate(drw->dpy, drw->drawable, 251 - DefaultVisual(drw->dpy, drw->screen), 252 - DefaultColormap(drw->dpy, drw->screen)); 253 + d = XftDrawCreate(drw->dpy, drw->drawable, drw->visual, drw->cmap); 254 x += lpad; 255 w -= lpad; 256 } 257 diff --git a/drw.h b/drw.h 258 index fd7631b..48f2f93 100644 259 --- a/drw.h 260 +++ b/drw.h 261 @@ -20,6 +20,9 @@ typedef struct { 262 Display *dpy; 263 int screen; 264 Window root; 265 + Visual *visual; 266 + unsigned int depth; 267 + Colormap cmap; 268 Drawable drawable; 269 GC gc; 270 Clr *scheme; 271 @@ -27,7 +30,7 @@ typedef struct { 272 } Drw; 273 274 /* Drawable abstraction */ 275 -Drw *drw_create(Display *dpy, int screen, Window win, unsigned int w, unsigned int h); 276 +Drw *drw_create(Display *dpy, int screen, Window win, unsigned int w, unsigned int h, Visual*, unsigned int, Colormap); 277 void drw_resize(Drw *drw, unsigned int w, unsigned int h); 278 void drw_free(Drw *drw); 279 280 @@ -39,8 +42,8 @@ unsigned int drw_fontset_getwidth_clamp(Drw *drw, const char *text, unsigned int 281 void drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h); 282 283 /* Colorscheme abstraction */ 284 -void drw_clr_create(Drw *drw, Clr *dest, const char *clrname); 285 -Clr *drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount); 286 +void drw_clr_create(Drw *drw, Clr *dest, const char *clrname, unsigned int alpha); 287 +Clr *drw_scm_create(Drw *drw, const char *clrnames[], const unsigned int alphas[], size_t clrcount); 288 289 /* Cursor abstraction */ 290 Cur *drw_cur_create(Drw *drw, int shape); 291 -- 292 2.37.4 293