From e9a681783bc238afdc03f8bf7b48a6fe0a3675b2 Mon Sep 17 00:00:00 2001 From: bjarke-cachy-btw Date: Sat, 11 Jul 2026 23:05:15 +0200 Subject: [PATCH] fix awesomebar overdraw on statusbar:x --- config.def.h.orig | 3 + drw.c.orig | 482 +++++++++++++++++++++++++++++++++++ drw.h.orig | 63 +++++ dwm | Bin 100872 -> 100872 bytes dwm.c | 2 +- dwm.c.orig | 422 ++++++++++++++++++++++++++++-- dwm.c.rej | 248 +++--------------- dwm.o | Bin 97624 -> 97640 bytes patches/dwm-winicon-6.6.diff | 429 ------------------------------- 9 files changed, 979 insertions(+), 670 deletions(-) create mode 100644 drw.c.orig create mode 100644 drw.h.orig delete mode 100644 patches/dwm-winicon-6.6.diff diff --git a/config.def.h.orig b/config.def.h.orig index 6fff8ea..d749030 100644 --- a/config.def.h.orig +++ b/config.def.h.orig @@ -15,6 +15,8 @@ static const unsigned int gappov = 30; /* vert outer gap between window static int smartgaps = 0; /* 1 means no outer gap when there is only one window */ static const int showbar = 1; /* 0 means no bar */ static const int topbar = 1; /* 0 means bottom bar */ +static int iconsize = 16; /* icon size */ +static int iconspacing = 5; /* space between icon and title */ static const char *fonts[] = { "monospace:size=10" }; static const char dmenufont[] = "monospace:size=10"; static const char col_gray1[] = "#222222"; @@ -26,6 +28,7 @@ static const char *colors[][3] = { /* fg bg border */ [SchemeNorm] = { col_gray3, col_gray1, col_gray2 }, [SchemeSel] = { col_gray4, col_cyan, col_cyan }, + [SchemeHid] = { col_cyan, col_gray1, col_cyan }, }; typedef struct { diff --git a/drw.c.orig b/drw.c.orig new file mode 100644 index 0000000..ecc61b2 --- /dev/null +++ b/drw.c.orig @@ -0,0 +1,482 @@ +/* See LICENSE file for copyright and license details. */ +#include +#include +#include +#include +#include + +#include "drw.h" +#include "util.h" + +#define UTF_INVALID 0xFFFD + +static int +utf8decode(const char *s_in, long *u, int *err) +{ + static const unsigned char lens[] = { + /* 0XXXX */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + /* 10XXX */ 0, 0, 0, 0, 0, 0, 0, 0, /* invalid */ + /* 110XX */ 2, 2, 2, 2, + /* 1110X */ 3, 3, + /* 11110 */ 4, + /* 11111 */ 0, /* invalid */ + }; + static const unsigned char leading_mask[] = { 0x7F, 0x1F, 0x0F, 0x07 }; + static const unsigned int overlong[] = { 0x0, 0x80, 0x0800, 0x10000 }; + + const unsigned char *s = (const unsigned char *)s_in; + int len = lens[*s >> 3]; + *u = UTF_INVALID; + *err = 1; + if (len == 0) + return 1; + + long cp = s[0] & leading_mask[len - 1]; + for (int i = 1; i < len; ++i) { + if (s[i] == '\0' || (s[i] & 0xC0) != 0x80) + return i; + cp = (cp << 6) | (s[i] & 0x3F); + } + /* out of range, surrogate, overlong encoding */ + if (cp > 0x10FFFF || (cp >> 11) == 0x1B || cp < overlong[len - 1]) + return len; + + *err = 0; + *u = cp; + return len; +} + +Drw * +drw_create(Display *dpy, int screen, Window root, unsigned int w, unsigned int h) +{ + Drw *drw = ecalloc(1, sizeof(Drw)); + + drw->dpy = dpy; + drw->screen = screen; + drw->root = root; + drw->w = w; + drw->h = h; + drw->drawable = XCreatePixmap(dpy, root, w, h, DefaultDepth(dpy, screen)); + drw->picture = XRenderCreatePicture(dpy, drw->drawable, XRenderFindVisualFormat(dpy, DefaultVisual(dpy, screen)), 0, NULL); + drw->gc = XCreateGC(dpy, root, 0, NULL); + XSetLineAttributes(dpy, drw->gc, 1, LineSolid, CapButt, JoinMiter); + + return drw; +} + +void +drw_resize(Drw *drw, unsigned int w, unsigned int h) +{ + if (!drw) + return; + + drw->w = w; + drw->h = h; + if (drw->picture) + XRenderFreePicture(drw->dpy, drw->picture); + if (drw->drawable) + XFreePixmap(drw->dpy, drw->drawable); + drw->drawable = XCreatePixmap(drw->dpy, drw->root, w, h, DefaultDepth(drw->dpy, drw->screen)); +} + +void +drw_free(Drw *drw) +{ + XFreePixmap(drw->dpy, drw->drawable); + XFreeGC(drw->dpy, drw->gc); + drw_fontset_free(drw->fonts); + free(drw); +} + +/* This function is an implementation detail. Library users should use + * drw_fontset_create instead. + */ +static Fnt * +xfont_create(Drw *drw, const char *fontname, FcPattern *fontpattern) +{ + Fnt *font; + XftFont *xfont = NULL; + FcPattern *pattern = NULL; + + if (fontname) { + /* Using the pattern found at font->xfont->pattern does not yield the + * same substitution results as using the pattern returned by + * FcNameParse; using the latter results in the desired fallback + * behaviour whereas the former just results in missing-character + * rectangles being drawn, at least with some fonts. */ + if (!(xfont = XftFontOpenName(drw->dpy, drw->screen, fontname))) { + fprintf(stderr, "error, cannot load font from name: '%s'\n", fontname); + return NULL; + } + if (!(pattern = FcNameParse((FcChar8 *) fontname))) { + fprintf(stderr, "error, cannot parse font name to pattern: '%s'\n", fontname); + XftFontClose(drw->dpy, xfont); + return NULL; + } + } else if (fontpattern) { + if (!(xfont = XftFontOpenPattern(drw->dpy, fontpattern))) { + fprintf(stderr, "error, cannot load font from pattern.\n"); + return NULL; + } + } else { + die("no font specified."); + } + + font = ecalloc(1, sizeof(Fnt)); + font->xfont = xfont; + font->pattern = pattern; + font->h = xfont->ascent + xfont->descent; + font->dpy = drw->dpy; + + return font; +} + +static void +xfont_free(Fnt *font) +{ + if (!font) + return; + if (font->pattern) + FcPatternDestroy(font->pattern); + XftFontClose(font->dpy, font->xfont); + free(font); +} + +Fnt* +drw_fontset_create(Drw* drw, const char *fonts[], size_t fontcount) +{ + Fnt *cur, *ret = NULL; + size_t i; + + if (!drw || !fonts) + return NULL; + + for (i = 1; i <= fontcount; i++) { + if ((cur = xfont_create(drw, fonts[fontcount - i], NULL))) { + cur->next = ret; + ret = cur; + } + } + return (drw->fonts = ret); +} + +void +drw_fontset_free(Fnt *font) +{ + if (font) { + drw_fontset_free(font->next); + xfont_free(font); + } +} + +void +drw_clr_create(Drw *drw, Clr *dest, const char *clrname) +{ + if (!drw || !dest || !clrname) + return; + + if (!XftColorAllocName(drw->dpy, DefaultVisual(drw->dpy, drw->screen), + DefaultColormap(drw->dpy, drw->screen), + clrname, dest)) + die("error, cannot allocate color '%s'", clrname); +} + +/* Create color schemes. */ +Clr * +drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount) +{ + size_t i; + Clr *ret; + + /* need at least two colors for a scheme */ + if (!drw || !clrnames || clrcount < 2 || !(ret = ecalloc(clrcount, sizeof(Clr)))) + return NULL; + + for (i = 0; i < clrcount; i++) + drw_clr_create(drw, &ret[i], clrnames[i]); + return ret; +} + +void +drw_clr_free(Drw *drw, Clr *c) +{ + if (!drw || !c) + return; + + /* c is typedef XftColor Clr */ + XftColorFree(drw->dpy, DefaultVisual(drw->dpy, drw->screen), + DefaultColormap(drw->dpy, drw->screen), c); +} + +void +drw_scm_free(Drw *drw, Clr *scm, size_t clrcount) +{ + size_t i; + + if (!drw || !scm) + return; + + for (i = 0; i < clrcount; i++) + drw_clr_free(drw, &scm[i]); + free(scm); +} + +void +drw_setfontset(Drw *drw, Fnt *set) +{ + if (drw) + drw->fonts = set; +} + +void +drw_setscheme(Drw *drw, Clr *scm) +{ + if (drw) + drw->scheme = scm; +} + +void +drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int invert) +{ + if (!drw || !drw->scheme) + return; + XSetForeground(drw->dpy, drw->gc, invert ? drw->scheme[ColBg].pixel : drw->scheme[ColFg].pixel); + if (filled) + XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h); + else + XDrawRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w - 1, h - 1); +} + +int +drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert) +{ + int ty, ellipsis_x = 0; + unsigned int tmpw, ew, ellipsis_w = 0, ellipsis_len, hash, h0, h1; + XftDraw *d = NULL; + Fnt *usedfont, *curfont, *nextfont; + int utf8strlen, utf8charlen, utf8err, render = x || y || w || h; + long utf8codepoint = 0; + const char *utf8str; + FcCharSet *fccharset; + FcPattern *fcpattern; + FcPattern *match; + XftResult result; + int charexists = 0, overflow = 0; + /* keep track of a couple codepoints for which we have no match. */ + static unsigned int nomatches[128], ellipsis_width, invalid_width; + static const char invalid[] = "�"; + + if (!drw || (render && (!drw->scheme || !w)) || !text || !drw->fonts) + return 0; + + if (!render) { + w = invert ? invert : ~invert; + } else { + XSetForeground(drw->dpy, drw->gc, drw->scheme[invert ? ColFg : ColBg].pixel); + XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h); + if (w < lpad) + return x + w; + d = XftDrawCreate(drw->dpy, drw->drawable, + DefaultVisual(drw->dpy, drw->screen), + DefaultColormap(drw->dpy, drw->screen)); + x += lpad; + w -= lpad; + } + + usedfont = drw->fonts; + if (!ellipsis_width && render) + ellipsis_width = drw_fontset_getwidth(drw, "..."); + if (!invalid_width && render) + invalid_width = drw_fontset_getwidth(drw, invalid); + while (1) { + ew = ellipsis_len = utf8err = utf8charlen = utf8strlen = 0; + utf8str = text; + nextfont = NULL; + while (*text) { + utf8charlen = utf8decode(text, &utf8codepoint, &utf8err); + for (curfont = drw->fonts; curfont; curfont = curfont->next) { + charexists = charexists || XftCharExists(drw->dpy, curfont->xfont, utf8codepoint); + if (charexists) { + drw_font_getexts(curfont, text, utf8charlen, &tmpw, NULL); + if (ew + ellipsis_width <= w) { + /* keep track where the ellipsis still fits */ + ellipsis_x = x + ew; + ellipsis_w = w - ew; + ellipsis_len = utf8strlen; + } + + if (ew + tmpw > w) { + overflow = 1; + /* called from drw_fontset_getwidth_clamp(): + * it wants the width AFTER the overflow + */ + if (!render) + x += tmpw; + else + utf8strlen = ellipsis_len; + } else if (curfont == usedfont) { + text += utf8charlen; + utf8strlen += utf8err ? 0 : utf8charlen; + ew += utf8err ? 0 : tmpw; + } else { + nextfont = curfont; + } + break; + } + } + + if (overflow || !charexists || nextfont || utf8err) + break; + else + charexists = 0; + } + + if (utf8strlen) { + if (render) { + ty = y + (h - usedfont->h) / 2 + usedfont->xfont->ascent; + XftDrawStringUtf8(d, &drw->scheme[invert ? ColBg : ColFg], + usedfont->xfont, x, ty, (XftChar8 *)utf8str, utf8strlen); + } + x += ew; + w -= ew; + } + if (utf8err && (!render || invalid_width < w)) { + if (render) + drw_text(drw, x, y, w, h, 0, invalid, invert); + x += invalid_width; + w -= invalid_width; + } + if (render && overflow) + drw_text(drw, ellipsis_x, y, ellipsis_w, h, 0, "...", invert); + + if (!*text || overflow) { + break; + } else if (nextfont) { + charexists = 0; + usedfont = nextfont; + } else { + /* Regardless of whether or not a fallback font is found, the + * character must be drawn. */ + charexists = 1; + + hash = (unsigned int)utf8codepoint; + hash = ((hash >> 16) ^ hash) * 0x21F0AAAD; + hash = ((hash >> 15) ^ hash) * 0xD35A2D97; + h0 = ((hash >> 15) ^ hash) % LENGTH(nomatches); + h1 = (hash >> 17) % LENGTH(nomatches); + /* avoid expensive XftFontMatch call when we know we won't find a match */ + if (nomatches[h0] == utf8codepoint || nomatches[h1] == utf8codepoint) + goto no_match; + + fccharset = FcCharSetCreate(); + FcCharSetAddChar(fccharset, utf8codepoint); + + if (!drw->fonts->pattern) { + /* Refer to the comment in xfont_create for more information. */ + die("the first font in the cache must be loaded from a font string."); + } + + fcpattern = FcPatternDuplicate(drw->fonts->pattern); + FcPatternAddCharSet(fcpattern, FC_CHARSET, fccharset); + FcPatternAddBool(fcpattern, FC_SCALABLE, FcTrue); + + FcConfigSubstitute(NULL, fcpattern, FcMatchPattern); + FcDefaultSubstitute(fcpattern); + match = XftFontMatch(drw->dpy, drw->screen, fcpattern, &result); + + FcCharSetDestroy(fccharset); + FcPatternDestroy(fcpattern); + + if (match) { + usedfont = xfont_create(drw, NULL, match); + if (usedfont && XftCharExists(drw->dpy, usedfont->xfont, utf8codepoint)) { + for (curfont = drw->fonts; curfont->next; curfont = curfont->next) + ; /* NOP */ + curfont->next = usedfont; + } else { + xfont_free(usedfont); + nomatches[nomatches[h0] ? h1 : h0] = utf8codepoint; +no_match: + usedfont = drw->fonts; + } + } + } + } + if (d) + XftDrawDestroy(d); + + return x + (render ? w : 0); +} + +void +drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h) +{ + if (!drw) + return; + + XCopyArea(drw->dpy, drw->drawable, win, drw->gc, x, y, w, h, x, y); + XSync(drw->dpy, False); +} + +void +drw_pic(Drw *drw, int x, int y, unsigned int w, unsigned int h, Picture pic) +{ + if (!drw) + return; + XRenderComposite(drw->dpy, PictOpOver, pic, None, drw->picture, 0, 0, 0, 0, x, y, w, h); +} + +unsigned int +drw_fontset_getwidth(Drw *drw, const char *text) +{ + if (!drw || !drw->fonts || !text) + return 0; + return drw_text(drw, 0, 0, 0, 0, 0, text, 0); +} + +unsigned int +drw_fontset_getwidth_clamp(Drw *drw, const char *text, unsigned int n) +{ + unsigned int tmp = 0; + if (drw && drw->fonts && text && n) + tmp = drw_text(drw, 0, 0, 0, 0, 0, text, n); + return MIN(n, tmp); +} + +void +drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h) +{ + XGlyphInfo ext; + + if (!font || !text) + return; + + XftTextExtentsUtf8(font->dpy, font->xfont, (XftChar8 *)text, len, &ext); + if (w) + *w = ext.xOff; + if (h) + *h = font->h; +} + +Cur * +drw_cur_create(Drw *drw, int shape) +{ + Cur *cur; + + if (!drw || !(cur = ecalloc(1, sizeof(Cur)))) + return NULL; + + cur->cursor = XCreateFontCursor(drw->dpy, shape); + + return cur; +} + +void +drw_cur_free(Drw *drw, Cur *cursor) +{ + if (!cursor) + return; + + XFreeCursor(drw->dpy, cursor->cursor); + free(cursor); +} diff --git a/drw.h.orig b/drw.h.orig new file mode 100644 index 0000000..e929714 --- /dev/null +++ b/drw.h.orig @@ -0,0 +1,63 @@ +/* See LICENSE file for copyright and license details. */ + +typedef struct { + Cursor cursor; +} Cur; + +typedef struct Fnt { + Display *dpy; + unsigned int h; + XftFont *xfont; + FcPattern *pattern; + struct Fnt *next; +} Fnt; + +enum { ColFg, ColBg, ColBorder }; /* Clr scheme index */ +typedef XftColor Clr; + +typedef struct { + unsigned int w, h; + Display *dpy; + int screen; + Window root; + Drawable drawable; + Picture picture; + GC gc; + Clr *scheme; + Fnt *fonts; +} Drw; + +/* Drawable abstraction */ +Drw *drw_create(Display *dpy, int screen, Window win, unsigned int w, unsigned int h); +void drw_resize(Drw *drw, unsigned int w, unsigned int h); +void drw_free(Drw *drw); + +/* Fnt abstraction */ +Fnt *drw_fontset_create(Drw* drw, const char *fonts[], size_t fontcount); +void drw_fontset_free(Fnt* set); +unsigned int drw_fontset_getwidth(Drw *drw, const char *text); +unsigned int drw_fontset_getwidth_clamp(Drw *drw, const char *text, unsigned int n); +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); +void drw_clr_free(Drw *drw, Clr *c); +Clr *drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount); +void drw_scm_free(Drw *drw, Clr *scm, size_t clrcount); + +/* Cursor abstraction */ +Cur *drw_cur_create(Drw *drw, int shape); +void drw_cur_free(Drw *drw, Cur *cursor); + +/* Drawing context manipulation */ +void drw_setfontset(Drw *drw, Fnt *set); +void drw_setscheme(Drw *drw, Clr *scm); + +/* Drawing functions */ +void drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int invert); +int drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert); + +/* Map functions */ +void drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h); +void drw_pic(Drw *drw, int x, int y, unsigned int w, unsigned int h, Picture pic); + diff --git a/dwm b/dwm index ebab94ca4668f180bdfaa9b32daeb8e96883edfa..a3ccd6c983d840ad9d9f24700ecffb6dacd82e88 100755 GIT binary patch delta 17077 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 delta 16803 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 z%5APXname, 0); + drw_text(drw, x, 0, tabw > m->ww - tw - stw - x ? m->ww - tw - stw - x : tabw, bh, lrpad / 2, c->name, 0); x += tabw; } } else { diff --git a/dwm.c.orig b/dwm.c.orig index 9b3a0fe..a24e352 100644 --- a/dwm.c.orig +++ b/dwm.c.orig @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -51,6 +52,7 @@ * MAX(0, MIN((y)+(h),(m)->wy+(m)->wh) - MAX((y),(m)->wy))) #define ISVISIBLEONTAG(C, T) ((C->tags & T)) #define ISVISIBLE(C) ISVISIBLEONTAG(C, C->mon->tagset[C->mon->seltags]) +#define HIDDEN(C) ((getstate(C->win) == IconicState)) #define MOUSEMASK (BUTTONMASK|PointerMotionMask) #define WIDTH(X) ((X)->w + 2 * (X)->bw) #define HEIGHT(X) ((X)->h + 2 * (X)->bw) @@ -76,8 +78,8 @@ /* enums */ enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */ -enum { SchemeNorm, SchemeSel }; /* color schemes */ -enum { NetSupported, NetWMName, NetWMState, NetWMCheck, +enum { SchemeNorm, SchemeSel, SchemeHid }; /* color schemes */ +enum { NetSupported, NetWMName, NetWMIcon, NetWMState, NetWMCheck, NetSystemTray, NetSystemTrayOP, NetSystemTrayOrientation, NetSystemTrayOrientationHorz, NetWMFullscreen, NetActiveWindow, NetWMWindowType, NetWMWindowTypeDialog, NetClientList, NetClientInfo, NetDesktopNames, NetDesktopViewport, NetNumberOfDesktops, NetCurrentDesktop, NetLast }; /* EWMH atoms */ @@ -113,6 +115,8 @@ struct Client { int bw, oldbw; unsigned int tags; int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen; + unsigned int icw, ich; + Picture icon; int issteam; int fakefullscreen; Client *next; @@ -139,6 +143,8 @@ struct Monitor { int nmaster; int num; int by; /* bar geometry */ + int btw; /* width of tasks portion of bar */ + int bt; /* number of tasks */ int mx, my, mw, mh; /* screen size */ int wx, wy, ww, wh; /* window area */ int gappih; /* horizontal gap between windows */ @@ -150,6 +156,7 @@ struct Monitor { unsigned int tagset[2]; int showbar; int topbar; + int hidsel; Client *clients; Client *sel; Client *stack; @@ -181,6 +188,7 @@ static void arrangemon(Monitor *m); static void attach(Client *c); static void attachaside(Client *c); static void attachstack(Client *c); +static uint32_t *bilinear_scale(const uint32_t *src, int sw, int sh, uint32_t dw, uint32_t dh); static void buttonpress(XEvent *e); static void checkotherwm(void); static void cleanup(void); @@ -203,14 +211,20 @@ static void focus(Client *c); static void focusdir(const Arg *arg); static void focusin(XEvent *e); static void focusmon(const Arg *arg); -static void focusstack(const Arg *arg); +static void focusstackvis(const Arg *arg); +static void focusstackhid(const Arg *arg); +static void focusstack(int inc, int vis); +static void freeicon(Client *c); static Atom getatomprop(Client *c, Atom prop); static int getrootptr(int *x, int *y); static long getstate(Window w); +static Picture geticonprop(Display *dpy, Window w, int iconsize, unsigned int *icw, unsigned int *ich); static unsigned int getsystraywidth(); static int gettextprop(Window w, Atom atom, char *text, unsigned int size); static void grabbuttons(Client *c, int focused); static void grabkeys(void); +static void hide(const Arg *arg); +static void hidewin(Client *c); static void incnmaster(const Arg *arg); static void keypress(XEvent *e); static void killclient(const Arg *arg); @@ -225,6 +239,7 @@ static Client *nexttagged(Client *c); static Client *nexttiled(Client *c); static void placedir(const Arg *arg); static void pop(Client *c); +static uint32_t prealpha(uint32_t p); static void propertynotify(XEvent *e); static void quit(const Arg *arg); static Monitor *recttomon(int x, int y, int w, int h); @@ -253,6 +268,9 @@ static void setnumdesktops(void); static void setup(void); static void setviewport(void); static void seturgent(Client *c, int urg); +static void show(const Arg *arg); +static void showall(const Arg *arg); +static void showwin(Client *c); static void showhide(Client *c); static void sighup(int unused); static void sigterm(int unused); @@ -267,6 +285,7 @@ static void togglefullscreen(const Arg *arg); static void togglescratch(const Arg *arg); static void toggletag(const Arg *arg); static void toggleview(const Arg *arg); +static void togglewin(const Arg *arg); static void unfocus(Client *c, int setfocus); static void unmanage(Client *c, int destroyed); static void unmapnotify(XEvent *e); @@ -275,6 +294,7 @@ static void updatebarpos(Monitor *m); static void updatebars(void); static void updateclientlist(void); static int updategeom(void); +static void updateicon(Client *c); static void updatenumlockmask(void); static void updatesizehints(Client *c); static void updatestatus(void); @@ -539,6 +559,57 @@ attachstack(Client *c) c->mon->stack = c; } +uint32_t * +bilinear_scale(const uint32_t *src, int sw, int sh, unsigned int dw, unsigned int dh) +{ + uint32_t *dst = calloc(dw * dh, sizeof(uint32_t)); + if (!dst) return NULL; + + for (int y = 0; y < dh; y++) { + /* Source position (in fixed-point) */ + float sy = (y + 0.5f) * sh / (float)dh - 0.5f; + int y0 = (sy < 0) ? (int)(sy - 1) : (int)(sy);; + int y1 = y0 + 1; + float fy = sy - y0; + if (y0 < 0) { y0 = 0; y1 = 0; fy = 0; } + if (y1 >= sh) { y1 = sh-1; y0 = y1; fy = 0; } + + for (int x = 0; x < dw; x++) { + float sx = (x + 0.5f) * sw / (float)dw - 0.5f; + int x0 = (sx < 0) ? (int)(sx - 1) : (int)(sx); + int x1 = x0 + 1; + float fx = sx - x0; + if (x0 < 0) { x0 = 0; x1 = 0; fx = 0; } + if (x1 >= sw) { x1 = sw-1; x0 = x1; fx = 0; } + + uint32_t p00 = prealpha(src[y0*sw + x0]); + uint32_t p10 = prealpha(src[y0*sw + x1]); + uint32_t p01 = prealpha(src[y1*sw + x0]); + uint32_t p11 = prealpha(src[y1*sw + x1]); + + /* Extract premultiplied channels */ + int a00 = p00 >> 24, r00 = (p00 >> 16) & 0xFF, g00 = (p00 >> 8) & 0xFF, b00 = p00 & 0xFF; + int a10 = p10 >> 24, r10 = (p10 >> 16) & 0xFF, g10 = (p10 >> 8) & 0xFF, b10 = p10 & 0xFF; + int a01 = p01 >> 24, r01 = (p01 >> 16) & 0xFF, g01 = (p01 >> 8) & 0xFF, b01 = p01 & 0xFF; + int a11 = p11 >> 24, r11 = (p11 >> 16) & 0xFF, g11 = (p11 >> 8) & 0xFF, b11 = p11 & 0xFF; + + /* Bilinear weights */ + float w00 = (1.0f - fx) * (1.0f - fy); + float w10 = fx * (1.0f - fy); + float w01 = (1.0f - fx) * fy; + float w11 = fx * fy; + + int a = (int)(a00*w00 + a10*w10 + a01*w01 + a11*w11 + 0.5f); + int r = (int)(r00*w00 + r10*w10 + r01*w01 + r11*w11 + 0.5f); + int g = (int)(g00*w00 + g10*w10 + g01*w01 + g11*w11 + 0.5f); + int b = (int)(b00*w00 + b10*w10 + b01*w01 + b11*w11 + 0.5f); + + dst[y*dw + x] = (a << 24) | (r << 16) | (g << 8) | b; + } + } + return dst; +} + void buttonpress(XEvent *e) { @@ -565,10 +636,24 @@ buttonpress(XEvent *e) arg.ui = 1 << i; } else if (ev->x < x + TEXTW(selmon->ltsymbol)) click = ClkLtSymbol; - else if (ev->x > selmon->ww - (int)TEXTW(stext) - getsystraywidth()) + else if (ev->x > selmon->ww - (int)TEXTW(stext) - getsystraywidth() + lrpad - 2) click = ClkStatusText; - else - click = ClkWinTitle; + else { + x += TEXTW(selmon->ltsymbol); + c = m->clients; + + if (c) { + do { + if (!ISVISIBLE(c)) + continue; + else + x +=(1.0 / (double)m->bt) * m->btw; + } while (ev->x > x && (c = c->next)); + + click = ClkWinTitle; + arg.v = c; + } + } } else if ((c = wintoclient(ev->window))) { focus(c); restack(selmon); @@ -578,7 +663,7 @@ buttonpress(XEvent *e) for (i = 0; i < LENGTH(buttons); i++) if (click == buttons[i].click && buttons[i].func && buttons[i].button == ev->button && CLEANMASK(buttons[i].mask) == CLEANMASK(ev->state)) - buttons[i].func(click == ClkTagBar && buttons[i].arg.i == 0 ? &arg : &buttons[i].arg); + buttons[i].func((click == ClkTagBar || click == ClkWinTitle) && buttons[i].arg.i == 0 ? &arg : &buttons[i].arg); } void @@ -909,7 +994,7 @@ dirtomon(int dir) void drawbar(Monitor *m) { - int x, w, tw = 0, stw = 0; + int x, w, tw = 0, stw = 0, n = 0, scm; int boxs = drw->fonts->h / 9; int boxw = drw->fonts->h / 6 + 2; unsigned int i, occ = 0, urg = 0; @@ -930,6 +1015,8 @@ drawbar(Monitor *m) resizebarwin(m); for (c = m->clients; c; c = c->next) { + if (ISVISIBLE(c)) + n++; occ |= c->tags; if (c->isurgent) urg |= c->tags; @@ -950,16 +1037,41 @@ drawbar(Monitor *m) x = drw_text(drw, x, 0, w, bh, lrpad / 2, m->ltsymbol, 0); if ((w = m->ww - tw - stw - x) > bh) { - if (m->sel) { - drw_setscheme(drw, scheme[m == selmon ? SchemeSel : SchemeNorm]); - drw_text(drw, x, 0, w, bh, lrpad / 2, m->sel->name, 0); - if (m->sel->isfloating) - drw_rect(drw, x + boxs, boxs, boxw, boxw, m->sel->isfixed, 0); + if (n > 0) { + int remainder = w % n; + int tabw = (1.0 / (double)n) * w + 1; + for (c = m->clients; c; c = c->next) { + if (!ISVISIBLE(c)) + continue; + if (m->sel == c) + scm = SchemeSel; + else if (HIDDEN(c)) + scm = SchemeHid; + else + scm = SchemeNorm; + drw_setscheme(drw, scheme[scm]); + + if (remainder >= 0) { + if (remainder == 0) { + tabw--; + } + remainder--; + } + if (c->icon) { + drw_text(drw, x, 0, w > m->ww - tw - stw - x ? m->ww - tw - stw - x : w, bh, lrpad / 2 + c->ich + iconspacing, c->name, 0); + drw_pic(drw, x + lrpad / 2, (bh - c->ich) / 2, c->icw, c->ich, c->icon); + } else { + drw_text(drw, x, 0, tabw > m->ww - tw - stw - x ? m->ww - tw - stw - x : tabw, bh, lrpad / 2, c->name, 0); + } + x += tabw; + } } else { drw_setscheme(drw, scheme[SchemeNorm]); drw_rect(drw, x, 0, w, bh, 1, 1); } } + m->bt = n; + m->btw = w; drw_map(drw, m->barwin, 0, 0, m->ww - stw, bh); } @@ -1008,10 +1120,16 @@ void focus(Client *c) { if (!c || !ISVISIBLE(c)) - for (c = selmon->stack; c && !ISVISIBLE(c); c = c->snext); + for (c = selmon->stack; c && (!ISVISIBLE(c) || HIDDEN(c)); c = c->snext); if (selmon->sel && selmon->sel != c) { losefullscreen(c); unfocus(selmon->sel, 0); + if (selmon->hidsel) { + hidewin(selmon->sel); + if (c) + arrange(c->mon); + selmon->hidsel = 0; + } } if (c) { if (c->mon != selmon) @@ -1122,28 +1240,62 @@ focusmon(const Arg *arg) } void -focusstack(const Arg *arg) +focusstackvis(const Arg *arg) { + focusstack(arg->i, 0); +} + +void +focusstackhid(const Arg *arg) { + focusstack(arg->i, 1); +} + +void +focusstack(int inc, int hid) { Client *c = NULL, *i; - if (!selmon->sel || (selmon->sel->isfullscreen && selmon->sel->fakefullscreen != 1)) + // if no client selected AND exclude hidden client; if client selected but fullscreened + if ((!selmon->sel && !hid) || (selmon->sel && selmon->sel->isfullscreen && lockfullscreen)) return; - if (arg->i > 0) { - for (c = selmon->sel->next; c && !ISVISIBLE(c); c = c->next); + if (!selmon->clients) + return; + if (inc > 0) { + if (selmon->sel) + for (c = selmon->sel->next; + c && (!ISVISIBLE(c) || (!hid && HIDDEN(c))); + c = c->next); if (!c) - for (c = selmon->clients; c && !ISVISIBLE(c); c = c->next); + for (c = selmon->clients; + c && (!ISVISIBLE(c) || (!hid && HIDDEN(c))); + c = c->next); } else { - for (i = selmon->clients; i != selmon->sel; i = i->next) - if (ISVISIBLE(i)) - c = i; + if (selmon->sel) { + for (i = selmon->clients; i != selmon->sel; i = i->next) + if (ISVISIBLE(i) && !(!hid && HIDDEN(i))) + c = i; + } else + c = selmon->clients; if (!c) for (; i; i = i->next) - if (ISVISIBLE(i)) + if (ISVISIBLE(i) && !(!hid && HIDDEN(i))) c = i; } if (c) { focus(c); restack(selmon); + if (HIDDEN(c)) { + showwin(c); + c->mon->hidsel = 1; + } + } +} + +void +freeicon(Client *c) +{ + if (c->icon) { + XRenderFreePicture(dpy, c->icon); + c->icon = None; } } @@ -1209,6 +1361,104 @@ getstate(Window w) return result; } +/* geticonprop: read, scale, and return an XRender Picture */ +Picture +geticonprop(Display *dpy, Window win, int iconsize, unsigned int *icw, unsigned int *ich) { + Atom net_wm_icon = XInternAtom(dpy, "_NET_WM_ICON", False); + Atom actual_type; + int actual_format; + unsigned long nitems, bytes_after; + unsigned char *data = NULL; + Picture pict = None; + + if (XGetWindowProperty(dpy, win, net_wm_icon, 0, LONG_MAX, False, AnyPropertyType, + &actual_type, &actual_format, &nitems, &bytes_after, &data) != Success || !data) { + return None; + } + + unsigned long *p = (unsigned long *)data; + unsigned long *end = p + nitems; + + /* Pick icon closest to desired size */ + unsigned long *best = NULL; + unsigned long best_w = 0, best_h = 0; + unsigned long best_diff = ~0UL; + + while (p + 2 < end) { + unsigned long w0 = *p++; + unsigned long h0 = *p++; + if (w0 == 0 || h0 == 0 || p + w0*h0 > end) break; + + unsigned long diff = (w0 > (unsigned long)iconsize ? w0 - iconsize : iconsize - w0) + + (h0 > (unsigned long)iconsize ? h0 - iconsize : iconsize - h0); + + if (diff < best_diff) { + best_diff = diff; + best_w = w0; + best_h = h0; + best = p; + } + p += w0 * h0; + } + + if (!best) { + XFree(data); + return None; + } + + /* Copy into fixed 32-bit array */ + uint32_t *src = malloc(best_w * best_h * sizeof(uint32_t)); + for (size_t i = 0; i < best_w * best_h; i++) + src[i] = (uint32_t)best[i]; + + /* Scale */ + int dst_w, dst_h; + if (best_w > best_h) { + dst_w = iconsize; + dst_h = best_h * iconsize / best_w; + } else { + dst_h = iconsize; + dst_w = best_w * iconsize / best_h; + } + + uint32_t *scaled = bilinear_scale(src, best_w, best_h, dst_w, dst_h); + free(src); + XFree(data); + if (!scaled) return None; + + /* Create pixmap and upload pixels */ + Pixmap pm = XCreatePixmap(dpy, root, dst_w, dst_h, 32); + + XImage img; + memset(&img, 0, sizeof img); + img.width = dst_w; + img.height = dst_h; + img.format = ZPixmap; + img.data = (char*)scaled; + img.byte_order = LSBFirst; + img.bitmap_unit = 32; + img.bitmap_bit_order = LSBFirst; + img.bitmap_pad = 32; + img.depth = 32; + img.bits_per_pixel = 32; + img.bytes_per_line = dst_w * 4; + + XInitImage(&img); + GC gc = XCreateGC(dpy, pm, 0, NULL); + XPutImage(dpy, pm, gc, &img, 0, 0, 0, 0, dst_w, dst_h); + XFreeGC(dpy, gc); + + XRenderPictFormat *fmt = XRenderFindStandardFormat(dpy, PictStandardARGB32); + pict = XRenderCreatePicture(dpy, pm, fmt, 0, NULL); + XFreePixmap(dpy, pm); + + free(scaled); + + *icw = dst_w; + *ich = dst_h; + return pict; +} + int gettextprop(Window w, Atom atom, char *text, unsigned int size) { @@ -1281,6 +1531,36 @@ grabkeys(void) } } +void +hide(const Arg *arg) +{ + hidewin(selmon->sel); + focus(NULL); + arrange(selmon); +} + +void +hidewin(Client *c) { + if (!c || HIDDEN(c)) + return; + + Window w = c->win; + static XWindowAttributes ra, ca; + + // more or less taken directly from blackbox's hide() function + XGrabServer(dpy); + XGetWindowAttributes(dpy, root, &ra); + XGetWindowAttributes(dpy, w, &ca); + // prevent UnmapNotify events + XSelectInput(dpy, root, ra.your_event_mask & ~SubstructureNotifyMask); + XSelectInput(dpy, w, ca.your_event_mask & ~StructureNotifyMask); + XUnmapWindow(dpy, w); + setclientstate(c, IconicState); + XSelectInput(dpy, root, ra.your_event_mask); + XSelectInput(dpy, w, ca.your_event_mask); + XUngrabServer(dpy); +} + void incnmaster(const Arg *arg) { @@ -1360,6 +1640,7 @@ manage(Window w, XWindowAttributes *wa) c->oldbw = wa->border_width; c->cfact = 1.0; + updateicon(c); updatetitle(c); if (XGetTransientForHint(dpy, w, &trans) && (t = wintoclient(trans))) { c->mon = t->mon; @@ -1415,14 +1696,16 @@ manage(Window w, XWindowAttributes *wa) XChangeProperty(dpy, root, netatom[NetClientList], XA_WINDOW, 32, PropModeAppend, (unsigned char *) &(c->win), 1); XMoveResizeWindow(dpy, c->win, c->x + 2 * sw, c->y, c->w, c->h); /* some windows require this */ - setclientstate(c, NormalState); + if (!HIDDEN(c)) + setclientstate(c, NormalState); if (c->mon == selmon) { losefullscreen(c); unfocus(selmon->sel, 0); } c->mon->sel = c; arrange(c->mon); - XMapWindow(dpy, c->win); + if (!HIDDEN(c)) + XMapWindow(dpy, c->win); focus(NULL); } @@ -1560,7 +1843,7 @@ nexttagged(Client *c) { Client * nexttiled(Client *c) { - for (; c && (c->isfloating || !ISVISIBLE(c)); c = c->next); + for (; c && (c->isfloating || !ISVISIBLE(c) || HIDDEN(c)); c = c->next); return c; } @@ -1670,6 +1953,14 @@ pop(Client *c) arrange(c->mon); } +uint32_t +prealpha(uint32_t p) { + uint8_t a = p >> 24u; + uint32_t rb = (a * (p & 0xFF00FFu)) >> 8u; + uint32_t g = (a * (p & 0x00FF00u)) >> 8u; + return (rb & 0xFF00FFu) | (g & 0x00FF00u) | (a << 24u); +} + void propertynotify(XEvent *e) { @@ -1713,6 +2004,11 @@ propertynotify(XEvent *e) if (c == c->mon->sel) drawbar(c->mon); } + if (ev->atom == netatom[NetWMIcon]) { + updateicon(c); + if (c == c->mon->sel) + drawbar(c->mon); + } if (ev->atom == netatom[NetWMWindowType]) updatewindowtype(c); } @@ -1721,6 +2017,16 @@ propertynotify(XEvent *e) void quit(const Arg *arg) { + // fix: reloading dwm keeps all the hidden clients hidden + Monitor *m; + Client *c; + for (m = mons; m; m = m->next) { + if (m) { + for (c = m->stack; c; c = c->next) + if (c && HIDDEN(c)) showwin(c); + } + } + if(arg->i) restart = 1; running = 0; } @@ -2188,6 +2494,7 @@ setup(void) netatom[NetSystemTrayOrientation] = XInternAtom(dpy, "_NET_SYSTEM_TRAY_ORIENTATION", False); netatom[NetSystemTrayOrientationHorz] = XInternAtom(dpy, "_NET_SYSTEM_TRAY_ORIENTATION_HORZ", False); netatom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False); + netatom[NetWMIcon] = XInternAtom(dpy, "_NET_WM_ICON", False); netatom[NetWMState] = XInternAtom(dpy, "_NET_WM_STATE", False); netatom[NetWMCheck] = XInternAtom(dpy, "_NET_SUPPORTING_WM_CHECK", False); netatom[NetWMFullscreen] = XInternAtom(dpy, "_NET_WM_STATE_FULLSCREEN", False); @@ -2261,6 +2568,42 @@ seturgent(Client *c, int urg) XFree(wmh); } +void +show(const Arg *arg) +{ + if (selmon->hidsel) + selmon->hidsel = 0; + showwin(selmon->sel); +} + +void +showall(const Arg *arg) +{ + Client *c = NULL; + selmon->hidsel = 0; + for (c = selmon->clients; c; c = c->next) { + if (ISVISIBLE(c)) + showwin(c); + } + if (!selmon->sel) { + for (c = selmon->clients; c && !ISVISIBLE(c); c = c->next); + if (c) + focus(c); + } + restack(selmon); +} + +void +showwin(Client *c) +{ + if (!c || !HIDDEN(c)) + return; + + XMapWindow(dpy, c->win); + setclientstate(c, NormalState); + arrange(c->mon); +} + void showhide(Client *c) { @@ -2481,6 +2824,25 @@ toggleview(const Arg *arg) } } +void +togglewin(const Arg *arg) +{ + Client *c = (Client*)arg->v; + + if (!c) + return; + if (c == selmon->sel) { + hidewin(c); + focus(NULL); + arrange(c->mon); + } else { + if (HIDDEN(c)) + showwin(c); + focus(c); + restack(selmon); + } +} + void unfocus(Client *c, int setfocus) { @@ -2502,6 +2864,7 @@ unmanage(Client *c, int destroyed) detach(c); detachstack(c); + freeicon(c); if (!destroyed) { wc.border_width = c->oldbw; XGrabServer(dpy); /* avoid race conditions */ @@ -2604,6 +2967,13 @@ void updatecurrentdesktop(void){ XChangeProperty(dpy, root, netatom[NetCurrentDesktop], XA_CARDINAL, 32, PropModeReplace, (unsigned char *)data, 1); } +void +updateicon(Client *c) +{ + freeicon(c); + c->icon = geticonprop(dpy, c->win, iconsize, &c->icw, &c->ich); +} + int updategeom(void) { diff --git a/dwm.c.rej b/dwm.c.rej index fc2a28a..e8b02c3 100644 --- a/dwm.c.rej +++ b/dwm.c.rej @@ -1,226 +1,46 @@ --- dwm.c +++ dwm.c -@@ -50,6 +50,7 @@ - #define INTERSECT(x,y,w,h,m) (MAX(0, MIN((x)+(w),(m)->wx+(m)->ww) - MAX((x),(m)->wx)) \ - * MAX(0, MIN((y)+(h),(m)->wy+(m)->wh) - MAX((y),(m)->wy))) - #define ISVISIBLE(C) ((C->tags & C->mon->tagset[C->mon->seltags])) -+#define HIDDEN(C) ((getstate(C->win) == IconicState)) - #define MOUSEMASK (BUTTONMASK|PointerMotionMask) - #define WIDTH(X) ((X)->w + 2 * (X)->bw) - #define HEIGHT(X) ((X)->h + 2 * (X)->bw) -@@ -170,13 +174,17 @@ static void expose(XEvent *e); - static void focus(Client *c); +@@ -59,7 +58,7 @@ + /* enums */ + enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */ + enum { SchemeNorm, SchemeSel }; /* color schemes */ +-enum { NetSupported, NetWMName, NetWMIcon, NetWMState, NetWMCheck, ++enum { NetSupported, NetWMName, NetWMState, NetWMCheck, + NetWMFullscreen, NetActiveWindow, NetWMWindowType, + NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH atoms */ + enum { WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast }; /* default atoms */ +@@ -92,8 +91,6 @@ struct Client { + int bw, oldbw; + unsigned int tags; + int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen; +- unsigned int icw, ich; +- Picture icon; + Client *next; + Client *snext; + Monitor *mon; +@@ -170,11 +166,9 @@ static void focus(Client *c); static void focusin(XEvent *e); static void focusmon(const Arg *arg); --static void focusstack(const Arg *arg); -+static void focusstackvis(const Arg *arg); -+static void focusstackhid(const Arg *arg); -+static void focusstack(int inc, int vis); + static void focusstack(const Arg *arg); +-static void freeicon(Client *c); static Atom getatomprop(Client *c, Atom prop); static int getrootptr(int *x, int *y); static long getstate(Window w); +-static Picture geticonprop(Display *dpy, Window w, int iconsize, unsigned int *icw, unsigned int *ich); static int gettextprop(Window w, Atom atom, char *text, unsigned int size); static void grabbuttons(Client *c, int focused); static void grabkeys(void); -+static void hide(const Arg *arg); -+static void hidewin(Client *c); - static void incnmaster(const Arg *arg); - static void keypress(XEvent *e); - static void killclient(const Arg *arg); -@@ -447,10 +459,25 @@ buttonpress(XEvent *e) - arg.ui = 1 << i; - } else if (ev->x < x + TEXTW(selmon->ltsymbol)) - click = ClkLtSymbol; -- else if (ev->x > selmon->ww - (int)TEXTW(stext)) -+ /* 2px right padding */ -+ else if (ev->x > selmon->ww - TEXTW(stext) + lrpad - 2) - click = ClkStatusText; -- else -- click = ClkWinTitle; -+ else { -+ x += TEXTW(selmon->ltsymbol); -+ c = m->clients; -+ -+ if (c) { -+ do { -+ if (!ISVISIBLE(c)) -+ continue; -+ else -+ x +=(1.0 / (double)m->bt) * m->btw; -+ } while (ev->x > x && (c = c->next)); -+ -+ click = ClkWinTitle; -+ arg.v = c; -+ } -+ } - } else if ((c = wintoclient(ev->window))) { - focus(c); - restack(selmon); -@@ -704,7 +731,7 @@ dirtomon(int dir) - void - drawbar(Monitor *m) - { -- int x, w, tw = 0; -+ int x, w, tw = 0, n = 0, scm; - int boxs = drw->fonts->h / 9; - int boxw = drw->fonts->h / 6 + 2; - unsigned int i, occ = 0, urg = 0; -@@ -743,16 +772,36 @@ drawbar(Monitor *m) - x = drw_text(drw, x, 0, w, bh, lrpad / 2, m->ltsymbol, 0); - +@@ -740,12 +681,7 @@ drawbar(Monitor *m) if ((w = m->ww - tw - x) > bh) { -- if (m->sel) { -- drw_setscheme(drw, scheme[m == selmon ? SchemeSel : SchemeNorm]); -- drw_text(drw, x, 0, w, bh, lrpad / 2, m->sel->name, 0); -- if (m->sel->isfloating) -- drw_rect(drw, x + boxs, boxs, boxw, boxw, m->sel->isfixed, 0); -+ if (n > 0) { -+ int remainder = w % n; -+ int tabw = (1.0 / (double)n) * w + 1; -+ for (c = m->clients; c; c = c->next) { -+ if (!ISVISIBLE(c)) -+ continue; -+ if (m->sel == c) -+ scm = SchemeSel; -+ else if (HIDDEN(c)) -+ scm = SchemeHid; -+ else -+ scm = SchemeNorm; -+ drw_setscheme(drw, scheme[scm]); -+ -+ if (remainder >= 0) { -+ if (remainder == 0) { -+ tabw--; -+ } -+ remainder--; -+ } -+ drw_text(drw, x, 0, tabw, bh, lrpad / 2, c->name, 0); -+ x += tabw; -+ } + if (m->sel) { + drw_setscheme(drw, scheme[m == selmon ? SchemeSel : SchemeNorm]); +- if (m->sel->icon) { +- drw_text(drw, x, 0, w, bh, lrpad / 2 + m->sel->icw + iconspacing, m->sel->name, 0); +- drw_pic(drw, x + lrpad / 2, (bh - m->sel->ich) / 2, m->sel->icw, m->sel->ich, m->sel->icon); +- } else { +- drw_text(drw, x, 0, w, bh, lrpad / 2, m->sel->name, 0); +- } ++ drw_text(drw, x, 0, w, bh, lrpad / 2, m->sel->name, 0); + if (m->sel->isfloating) + drw_rect(drw, x + boxs, boxs, boxw, boxw, m->sel->isfixed, 0); } else { - drw_setscheme(drw, scheme[SchemeNorm]); - drw_rect(drw, x, 0, w, bh, 1, 1); - } - } -+ m->bt = n; -+ m->btw = w; - drw_map(drw, m->barwin, 0, 0, m->ww, bh); - } - -@@ -798,9 +847,17 @@ void - focus(Client *c) - { - if (!c || !ISVISIBLE(c)) -- for (c = selmon->stack; c && !ISVISIBLE(c); c = c->snext); -- if (selmon->sel && selmon->sel != c) -+ for (c = selmon->stack; c && (!ISVISIBLE(c) || HIDDEN(c)); c = c->snext); -+ if (selmon->sel && selmon->sel != c) { - unfocus(selmon->sel, 0); -+ -+ if (selmon->hidsel) { -+ hidewin(selmon->sel); -+ if (c) -+ arrange(c->mon); -+ selmon->hidsel = 0; -+ } -+ } - if (c) { - if (c->mon != selmon) - selmon = c->mon; -@@ -844,28 +901,52 @@ focusmon(const Arg *arg) - } - - void --focusstack(const Arg *arg) -+focusstackvis(const Arg *arg) { -+ focusstack(arg->i, 0); -+} -+ -+void -+focusstackhid(const Arg *arg) { -+ focusstack(arg->i, 1); -+} -+ -+void -+focusstack(int inc, int hid) - { - Client *c = NULL, *i; -- -- if (!selmon->sel || (selmon->sel->isfullscreen && lockfullscreen)) -+ // if no client selected AND exclude hidden client; if client selected but fullscreened -+ if ((!selmon->sel && !hid) || (selmon->sel && selmon->sel->isfullscreen && lockfullscreen)) - return; -- if (arg->i > 0) { -- for (c = selmon->sel->next; c && !ISVISIBLE(c); c = c->next); -+ if (!selmon->clients) -+ return; -+ if (inc > 0) { -+ if (selmon->sel) -+ for (c = selmon->sel->next; -+ c && (!ISVISIBLE(c) || (!hid && HIDDEN(c))); -+ c = c->next); - if (!c) -- for (c = selmon->clients; c && !ISVISIBLE(c); c = c->next); -+ for (c = selmon->clients; -+ c && (!ISVISIBLE(c) || (!hid && HIDDEN(c))); -+ c = c->next); - } else { -- for (i = selmon->clients; i != selmon->sel; i = i->next) -- if (ISVISIBLE(i)) -- c = i; -+ if (selmon->sel) { -+ for (i = selmon->clients; i != selmon->sel; i = i->next) -+ if (ISVISIBLE(i) && !(!hid && HIDDEN(i))) -+ c = i; -+ } else -+ c = selmon->clients; - if (!c) - for (; i; i = i->next) -- if (ISVISIBLE(i)) -+ if (ISVISIBLE(i) && !(!hid && HIDDEN(i))) - c = i; - } - if (c) { - focus(c); - restack(selmon); -+ if (HIDDEN(c)) { -+ showwin(c); -+ c->mon->hidsel = 1; -+ } - } - } - -@@ -1117,12 +1228,14 @@ manage(Window w, XWindowAttributes *wa) - XChangeProperty(dpy, root, netatom[NetClientList], XA_WINDOW, 32, PropModeAppend, - (unsigned char *) &(c->win), 1); - XMoveResizeWindow(dpy, c->win, c->x + 2 * sw, c->y, c->w, c->h); /* some windows require this */ -- setclientstate(c, NormalState); -+ if (!HIDDEN(c)) -+ setclientstate(c, NormalState); - if (c->mon == selmon) - unfocus(selmon->sel, 0); - c->mon->sel = c; - arrange(c->mon); -- XMapWindow(dpy, c->win); -+ if (!HIDDEN(c)) -+ XMapWindow(dpy, c->win); - focus(NULL); - } - -@@ -1296,6 +1409,16 @@ propertynotify(XEvent *e) - void - quit(const Arg *arg) - { -+ // fix: reloading dwm keeps all the hidden clients hidden -+ Monitor *m; -+ Client *c; -+ for (m = mons; m; m = m->next) { -+ if (m) { -+ for (c = m->stack; c; c = c->next) -+ if (c && HIDDEN(c)) showwin(c); -+ } -+ } -+ - running = 0; - } - diff --git a/dwm.o b/dwm.o index b07d6d59596138fe38dc3618c24f085337228625..9ec1f01f3e771e5272b66bb9a4fddecb739a94d9 100644 GIT binary patch delta 17946 zcmZ{r4P2B}_Q$!1DW<@vIX=FmlUN`UjEYK{I)VyG

$RGp+fOWlV}%YC2&djh5rh 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 delta 17824 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 G_5T11LpFQ> diff --git a/patches/dwm-winicon-6.6.diff b/patches/dwm-winicon-6.6.diff deleted file mode 100644 index 2667572..0000000 --- a/patches/dwm-winicon-6.6.diff +++ /dev/null @@ -1,429 +0,0 @@ -From 6aafee64cace33c1afc02c087397593350194866 Mon Sep 17 00:00:00 2001 -From: Bakkeby -Date: Thu, 18 Sep 2025 22:29:40 +0200 -Subject: [PATCH] Winicon patch (without imlib2 dependency) - ---- - config.def.h | 2 + - config.mk | 4 +- - drw.c | 11 +++ - drw.h | 3 + - dwm.c | 198 ++++++++++++++++++++++++++++++++++++++++++++++++++- - 5 files changed, 215 insertions(+), 3 deletions(-) - -diff --git a/config.def.h b/config.def.h -index 9efa774..c2a6e47 100644 ---- a/config.def.h -+++ b/config.def.h -@@ -5,6 +5,8 @@ static const unsigned int borderpx = 1; /* border pixel of windows */ - static const unsigned int snap = 32; /* snap pixel */ - static const int showbar = 1; /* 0 means no bar */ - static const int topbar = 1; /* 0 means bottom bar */ -+static int iconsize = 16; /* icon size */ -+static int iconspacing = 5; /* space between icon and title */ - static const char *fonts[] = { "monospace:size=10" }; - static const char dmenufont[] = "monospace:size=10"; - static const char col_gray1[] = "#222222"; -diff --git a/config.mk b/config.mk -index b469a2b..bbea09f 100644 ---- a/config.mk -+++ b/config.mk -@@ -10,6 +10,8 @@ MANPREFIX = ${PREFIX}/share/man - X11INC = /usr/X11R6/include - X11LIB = /usr/X11R6/lib - -+XRENDER = -lXrender -+ - # Xinerama, comment if you don't want it - XINERAMALIBS = -lXinerama - XINERAMAFLAGS = -DXINERAMA -@@ -23,7 +25,7 @@ FREETYPEINC = /usr/include/freetype2 - - # includes and libs - INCS = -I${X11INC} -I${FREETYPEINC} --LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} -+LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} ${XRENDER} - - # flags - CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_XOPEN_SOURCE=700L -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS} -diff --git a/drw.c b/drw.c -index c41e6af..cfa769f 100644 ---- a/drw.c -+++ b/drw.c -@@ -57,6 +57,7 @@ drw_create(Display *dpy, int screen, Window root, unsigned int w, unsigned int h - drw->w = w; - drw->h = h; - drw->drawable = XCreatePixmap(dpy, root, w, h, DefaultDepth(dpy, screen)); -+ drw->picture = XRenderCreatePicture(dpy, drw->drawable, XRenderFindVisualFormat(dpy, DefaultVisual(dpy, screen)), 0, NULL); - drw->gc = XCreateGC(dpy, root, 0, NULL); - XSetLineAttributes(dpy, drw->gc, 1, LineSolid, CapButt, JoinMiter); - -@@ -71,6 +72,8 @@ drw_resize(Drw *drw, unsigned int w, unsigned int h) - - drw->w = w; - drw->h = h; -+ if (drw->picture) -+ XRenderFreePicture(drw->dpy, drw->picture); - if (drw->drawable) - XFreePixmap(drw->dpy, drw->drawable); - drw->drawable = XCreatePixmap(drw->dpy, drw->root, w, h, DefaultDepth(drw->dpy, drw->screen)); -@@ -392,6 +395,14 @@ drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h) - XSync(drw->dpy, False); - } - -+void -+drw_pic(Drw *drw, int x, int y, unsigned int w, unsigned int h, Picture pic) -+{ -+ if (!drw) -+ return; -+ XRenderComposite(drw->dpy, PictOpOver, pic, None, drw->picture, 0, 0, 0, 0, x, y, w, h); -+} -+ - unsigned int - drw_fontset_getwidth(Drw *drw, const char *text) - { -diff --git a/drw.h b/drw.h -index 6471431..ff75898 100644 ---- a/drw.h -+++ b/drw.h -@@ -21,6 +21,7 @@ typedef struct { - int screen; - Window root; - Drawable drawable; -+ Picture picture; - GC gc; - Clr *scheme; - Fnt *fonts; -@@ -56,3 +57,5 @@ int drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned in - - /* Map functions */ - void drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h); -+void drw_pic(Drw *drw, int x, int y, unsigned int w, unsigned int h, Picture pic); -+ -diff --git a/dwm.c b/dwm.c -index 1443802..62ea0e6 100644 ---- a/dwm.c -+++ b/dwm.c -@@ -25,6 +25,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -59,7 +60,7 @@ - /* enums */ - enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */ - enum { SchemeNorm, SchemeSel }; /* color schemes */ --enum { NetSupported, NetWMName, NetWMState, NetWMCheck, -+enum { NetSupported, NetWMName, NetWMIcon, NetWMState, NetWMCheck, - NetWMFullscreen, NetActiveWindow, NetWMWindowType, - NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH atoms */ - enum { WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast }; /* default atoms */ -@@ -92,6 +93,8 @@ struct Client { - int bw, oldbw; - unsigned int tags; - int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen; -+ unsigned int icw, ich; -+ Picture icon; - Client *next; - Client *snext; - Monitor *mon; -@@ -147,6 +150,7 @@ static void arrange(Monitor *m); - static void arrangemon(Monitor *m); - static void attach(Client *c); - static void attachstack(Client *c); -+static uint32_t *bilinear_scale(const uint32_t *src, int sw, int sh, uint32_t dw, uint32_t dh); - static void buttonpress(XEvent *e); - static void checkotherwm(void); - static void cleanup(void); -@@ -168,9 +172,11 @@ static void focus(Client *c); - static void focusin(XEvent *e); - static void focusmon(const Arg *arg); - static void focusstack(const Arg *arg); -+static void freeicon(Client *c); - static Atom getatomprop(Client *c, Atom prop); - static int getrootptr(int *x, int *y); - static long getstate(Window w); -+static Picture geticonprop(Display *dpy, Window w, int iconsize, unsigned int *icw, unsigned int *ich); - static int gettextprop(Window w, Atom atom, char *text, unsigned int size); - static void grabbuttons(Client *c, int focused); - static void grabkeys(void); -@@ -185,6 +191,7 @@ static void motionnotify(XEvent *e); - static void movemouse(const Arg *arg); - static Client *nexttiled(Client *c); - static void pop(Client *c); -+static uint32_t prealpha(uint32_t p); - static void propertynotify(XEvent *e); - static void quit(const Arg *arg); - static Monitor *recttomon(int x, int y, int w, int h); -@@ -219,6 +226,7 @@ static void updatebarpos(Monitor *m); - static void updatebars(void); - static void updateclientlist(void); - static int updategeom(void); -+static void updateicon(Client *c); - static void updatenumlockmask(void); - static void updatesizehints(Client *c); - static void updatestatus(void); -@@ -414,6 +422,57 @@ attachstack(Client *c) - c->mon->stack = c; - } - -+uint32_t * -+bilinear_scale(const uint32_t *src, int sw, int sh, unsigned int dw, unsigned int dh) -+{ -+ uint32_t *dst = calloc(dw * dh, sizeof(uint32_t)); -+ if (!dst) return NULL; -+ -+ for (int y = 0; y < dh; y++) { -+ /* Source position (in fixed-point) */ -+ float sy = (y + 0.5f) * sh / (float)dh - 0.5f; -+ int y0 = (sy < 0) ? (int)(sy - 1) : (int)(sy);; -+ int y1 = y0 + 1; -+ float fy = sy - y0; -+ if (y0 < 0) { y0 = 0; y1 = 0; fy = 0; } -+ if (y1 >= sh) { y1 = sh-1; y0 = y1; fy = 0; } -+ -+ for (int x = 0; x < dw; x++) { -+ float sx = (x + 0.5f) * sw / (float)dw - 0.5f; -+ int x0 = (sx < 0) ? (int)(sx - 1) : (int)(sx); -+ int x1 = x0 + 1; -+ float fx = sx - x0; -+ if (x0 < 0) { x0 = 0; x1 = 0; fx = 0; } -+ if (x1 >= sw) { x1 = sw-1; x0 = x1; fx = 0; } -+ -+ uint32_t p00 = prealpha(src[y0*sw + x0]); -+ uint32_t p10 = prealpha(src[y0*sw + x1]); -+ uint32_t p01 = prealpha(src[y1*sw + x0]); -+ uint32_t p11 = prealpha(src[y1*sw + x1]); -+ -+ /* Extract premultiplied channels */ -+ int a00 = p00 >> 24, r00 = (p00 >> 16) & 0xFF, g00 = (p00 >> 8) & 0xFF, b00 = p00 & 0xFF; -+ int a10 = p10 >> 24, r10 = (p10 >> 16) & 0xFF, g10 = (p10 >> 8) & 0xFF, b10 = p10 & 0xFF; -+ int a01 = p01 >> 24, r01 = (p01 >> 16) & 0xFF, g01 = (p01 >> 8) & 0xFF, b01 = p01 & 0xFF; -+ int a11 = p11 >> 24, r11 = (p11 >> 16) & 0xFF, g11 = (p11 >> 8) & 0xFF, b11 = p11 & 0xFF; -+ -+ /* Bilinear weights */ -+ float w00 = (1.0f - fx) * (1.0f - fy); -+ float w10 = fx * (1.0f - fy); -+ float w01 = (1.0f - fx) * fy; -+ float w11 = fx * fy; -+ -+ int a = (int)(a00*w00 + a10*w10 + a01*w01 + a11*w11 + 0.5f); -+ int r = (int)(r00*w00 + r10*w10 + r01*w01 + r11*w11 + 0.5f); -+ int g = (int)(g00*w00 + g10*w10 + g01*w01 + g11*w11 + 0.5f); -+ int b = (int)(b00*w00 + b10*w10 + b01*w01 + b11*w11 + 0.5f); -+ -+ dst[y*dw + x] = (a << 24) | (r << 16) | (g << 8) | b; -+ } -+ } -+ return dst; -+} -+ - void - buttonpress(XEvent *e) - { -@@ -736,7 +795,12 @@ drawbar(Monitor *m) - if ((w = m->ww - tw - x) > bh) { - if (m->sel) { - drw_setscheme(drw, scheme[m == selmon ? SchemeSel : SchemeNorm]); -- drw_text(drw, x, 0, w, bh, lrpad / 2, m->sel->name, 0); -+ if (m->sel->icon) { -+ drw_text(drw, x, 0, w, bh, lrpad / 2 + m->sel->icw + iconspacing, m->sel->name, 0); -+ drw_pic(drw, x + lrpad / 2, (bh - m->sel->ich) / 2, m->sel->icw, m->sel->ich, m->sel->icon); -+ } else { -+ drw_text(drw, x, 0, w, bh, lrpad / 2, m->sel->name, 0); -+ } - if (m->sel->isfloating) - drw_rect(drw, x + boxs, boxs, boxw, boxw, m->sel->isfixed, 0); - } else { -@@ -860,6 +924,15 @@ focusstack(const Arg *arg) - } - } - -+void -+freeicon(Client *c) -+{ -+ if (c->icon) { -+ XRenderFreePicture(dpy, c->icon); -+ c->icon = None; -+ } -+} -+ - Atom - getatomprop(Client *c, Atom prop) - { -@@ -904,6 +977,104 @@ getstate(Window w) - return result; - } - -+/* geticonprop: read, scale, and return an XRender Picture */ -+Picture -+geticonprop(Display *dpy, Window win, int iconsize, unsigned int *icw, unsigned int *ich) { -+ Atom net_wm_icon = XInternAtom(dpy, "_NET_WM_ICON", False); -+ Atom actual_type; -+ int actual_format; -+ unsigned long nitems, bytes_after; -+ unsigned char *data = NULL; -+ Picture pict = None; -+ -+ if (XGetWindowProperty(dpy, win, net_wm_icon, 0, LONG_MAX, False, AnyPropertyType, -+ &actual_type, &actual_format, &nitems, &bytes_after, &data) != Success || !data) { -+ return None; -+ } -+ -+ unsigned long *p = (unsigned long *)data; -+ unsigned long *end = p + nitems; -+ -+ /* Pick icon closest to desired size */ -+ unsigned long *best = NULL; -+ unsigned long best_w = 0, best_h = 0; -+ unsigned long best_diff = ~0UL; -+ -+ while (p + 2 < end) { -+ unsigned long w0 = *p++; -+ unsigned long h0 = *p++; -+ if (w0 == 0 || h0 == 0 || p + w0*h0 > end) break; -+ -+ unsigned long diff = (w0 > (unsigned long)iconsize ? w0 - iconsize : iconsize - w0) -+ + (h0 > (unsigned long)iconsize ? h0 - iconsize : iconsize - h0); -+ -+ if (diff < best_diff) { -+ best_diff = diff; -+ best_w = w0; -+ best_h = h0; -+ best = p; -+ } -+ p += w0 * h0; -+ } -+ -+ if (!best) { -+ XFree(data); -+ return None; -+ } -+ -+ /* Copy into fixed 32-bit array */ -+ uint32_t *src = malloc(best_w * best_h * sizeof(uint32_t)); -+ for (size_t i = 0; i < best_w * best_h; i++) -+ src[i] = (uint32_t)best[i]; -+ -+ /* Scale */ -+ int dst_w, dst_h; -+ if (best_w > best_h) { -+ dst_w = iconsize; -+ dst_h = best_h * iconsize / best_w; -+ } else { -+ dst_h = iconsize; -+ dst_w = best_w * iconsize / best_h; -+ } -+ -+ uint32_t *scaled = bilinear_scale(src, best_w, best_h, dst_w, dst_h); -+ free(src); -+ XFree(data); -+ if (!scaled) return None; -+ -+ /* Create pixmap and upload pixels */ -+ Pixmap pm = XCreatePixmap(dpy, root, dst_w, dst_h, 32); -+ -+ XImage img; -+ memset(&img, 0, sizeof img); -+ img.width = dst_w; -+ img.height = dst_h; -+ img.format = ZPixmap; -+ img.data = (char*)scaled; -+ img.byte_order = LSBFirst; -+ img.bitmap_unit = 32; -+ img.bitmap_bit_order = LSBFirst; -+ img.bitmap_pad = 32; -+ img.depth = 32; -+ img.bits_per_pixel = 32; -+ img.bytes_per_line = dst_w * 4; -+ -+ XInitImage(&img); -+ GC gc = XCreateGC(dpy, pm, 0, NULL); -+ XPutImage(dpy, pm, gc, &img, 0, 0, 0, 0, dst_w, dst_h); -+ XFreeGC(dpy, gc); -+ -+ XRenderPictFormat *fmt = XRenderFindStandardFormat(dpy, PictStandardARGB32); -+ pict = XRenderCreatePicture(dpy, pm, fmt, 0, NULL); -+ XFreePixmap(dpy, pm); -+ -+ free(scaled); -+ -+ *icw = dst_w; -+ *ich = dst_h; -+ return pict; -+} -+ - int - gettextprop(Window w, Atom atom, char *text, unsigned int size) - { -@@ -1043,6 +1214,7 @@ manage(Window w, XWindowAttributes *wa) - c->h = c->oldh = wa->height; - c->oldbw = wa->border_width; - -+ updateicon(c); - updatetitle(c); - if (XGetTransientForHint(dpy, w, &trans) && (t = wintoclient(trans))) { - c->mon = t->mon; -@@ -1217,6 +1389,14 @@ pop(Client *c) - arrange(c->mon); - } - -+uint32_t -+prealpha(uint32_t p) { -+ uint8_t a = p >> 24u; -+ uint32_t rb = (a * (p & 0xFF00FFu)) >> 8u; -+ uint32_t g = (a * (p & 0x00FF00u)) >> 8u; -+ return (rb & 0xFF00FFu) | (g & 0x00FF00u) | (a << 24u); -+} -+ - void - propertynotify(XEvent *e) - { -@@ -1249,6 +1429,11 @@ propertynotify(XEvent *e) - if (c == c->mon->sel) - drawbar(c->mon); - } -+ if (ev->atom == netatom[NetWMIcon]) { -+ updateicon(c); -+ if (c == c->mon->sel) -+ drawbar(c->mon); -+ } - if (ev->atom == netatom[NetWMWindowType]) - updatewindowtype(c); - } -@@ -1572,6 +1757,7 @@ setup(void) - netatom[NetActiveWindow] = XInternAtom(dpy, "_NET_ACTIVE_WINDOW", False); - netatom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False); - netatom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False); -+ netatom[NetWMIcon] = XInternAtom(dpy, "_NET_WM_ICON", False); - netatom[NetWMState] = XInternAtom(dpy, "_NET_WM_STATE", False); - netatom[NetWMCheck] = XInternAtom(dpy, "_NET_SUPPORTING_WM_CHECK", False); - netatom[NetWMFullscreen] = XInternAtom(dpy, "_NET_WM_STATE_FULLSCREEN", False); -@@ -1782,6 +1968,7 @@ unmanage(Client *c, int destroyed) - - detach(c); - detachstack(c); -+ freeicon(c); - if (!destroyed) { - wc.border_width = c->oldbw; - XGrabServer(dpy); /* avoid race conditions */ -@@ -1863,6 +2050,13 @@ updateclientlist(void) - (unsigned char *) &(c->win), 1); - } - -+void -+updateicon(Client *c) -+{ -+ freeicon(c); -+ c->icon = geticonprop(dpy, c->win, iconsize, &c->icw, &c->ich); -+} -+ - int - updategeom(void) - { --- -2.51.0 -