dwm-clientopacity-6.4.diff (12855B)
1 From 10dd5df95f551d81d0a814dcdb2bde20e405fb91 Mon Sep 17 00:00:00 2001 2 From: sympodius <mail@sympodius.net> 3 Date: Mon, 13 Mar 2023 16:28:16 +0000 4 Subject: [PATCH] [dwm][patch][clientopacity] Adds opacity on a per client 5 basis 6 7 --- 8 config.def.h | 80 ++++++++++++++++++++++++++++------------------------ 9 dwm.c | 61 ++++++++++++++++++++++++++++++++++++++- 10 2 files changed, 103 insertions(+), 38 deletions(-) 11 12 diff --git a/config.def.h b/config.def.h 13 index 9efa774..9ca812d 100644 14 --- a/config.def.h 15 +++ b/config.def.h 16 @@ -5,6 +5,8 @@ static const unsigned int borderpx = 1; /* border pixel of windows */ 17 static const unsigned int snap = 32; /* snap pixel */ 18 static const int showbar = 1; /* 0 means no bar */ 19 static const int topbar = 1; /* 0 means bottom bar */ 20 +static const double activeopacity = 0.9f; /* Window opacity when it's focused (0 <= opacity <= 1) */ 21 +static const double inactiveopacity = 0.7f; /* Window opacity when it's inactive (0 <= opacity <= 1) */ 22 static const char *fonts[] = { "monospace:size=10" }; 23 static const char dmenufont[] = "monospace:size=10"; 24 static const char col_gray1[] = "#222222"; 25 @@ -26,9 +28,9 @@ static const Rule rules[] = { 26 * WM_CLASS(STRING) = instance, class 27 * WM_NAME(STRING) = title 28 */ 29 - /* class instance title tags mask isfloating monitor */ 30 - { "Gimp", NULL, NULL, 0, 1, -1 }, 31 - { "Firefox", NULL, NULL, 1 << 8, 0, -1 }, 32 + /* class instance title tags mask isfloating focusopacity unfocusopacity monitor */ 33 + { "Gimp", NULL, NULL, 0, 1, 1.0, inactiveopacity, -1 }, 34 + { "Firefox", NULL, NULL, 1 << 8, 0, activeopacity, inactiveopacity, -1 }, 35 }; 36 37 /* layout(s) */ 38 @@ -61,40 +63,44 @@ static const char *dmenucmd[] = { "dmenu_run", "-m", dmenumon, "-fn", dmenufont, 39 static const char *termcmd[] = { "st", NULL }; 40 41 static const Key keys[] = { 42 - /* modifier key function argument */ 43 - { MODKEY, XK_p, spawn, {.v = dmenucmd } }, 44 - { MODKEY|ShiftMask, XK_Return, spawn, {.v = termcmd } }, 45 - { MODKEY, XK_b, togglebar, {0} }, 46 - { MODKEY, XK_j, focusstack, {.i = +1 } }, 47 - { MODKEY, XK_k, focusstack, {.i = -1 } }, 48 - { MODKEY, XK_i, incnmaster, {.i = +1 } }, 49 - { MODKEY, XK_d, incnmaster, {.i = -1 } }, 50 - { MODKEY, XK_h, setmfact, {.f = -0.05} }, 51 - { MODKEY, XK_l, setmfact, {.f = +0.05} }, 52 - { MODKEY, XK_Return, zoom, {0} }, 53 - { MODKEY, XK_Tab, view, {0} }, 54 - { MODKEY|ShiftMask, XK_c, killclient, {0} }, 55 - { MODKEY, XK_t, setlayout, {.v = &layouts[0]} }, 56 - { MODKEY, XK_f, setlayout, {.v = &layouts[1]} }, 57 - { MODKEY, XK_m, setlayout, {.v = &layouts[2]} }, 58 - { MODKEY, XK_space, setlayout, {0} }, 59 - { MODKEY|ShiftMask, XK_space, togglefloating, {0} }, 60 - { MODKEY, XK_0, view, {.ui = ~0 } }, 61 - { MODKEY|ShiftMask, XK_0, tag, {.ui = ~0 } }, 62 - { MODKEY, XK_comma, focusmon, {.i = -1 } }, 63 - { MODKEY, XK_period, focusmon, {.i = +1 } }, 64 - { MODKEY|ShiftMask, XK_comma, tagmon, {.i = -1 } }, 65 - { MODKEY|ShiftMask, XK_period, tagmon, {.i = +1 } }, 66 - TAGKEYS( XK_1, 0) 67 - TAGKEYS( XK_2, 1) 68 - TAGKEYS( XK_3, 2) 69 - TAGKEYS( XK_4, 3) 70 - TAGKEYS( XK_5, 4) 71 - TAGKEYS( XK_6, 5) 72 - TAGKEYS( XK_7, 6) 73 - TAGKEYS( XK_8, 7) 74 - TAGKEYS( XK_9, 8) 75 - { MODKEY|ShiftMask, XK_q, quit, {0} }, 76 + /* modifier key function argument */ 77 + { MODKEY, XK_p, spawn, {.v = dmenucmd } }, 78 + { MODKEY|ShiftMask, XK_Return, spawn, {.v = termcmd } }, 79 + { MODKEY, XK_b, togglebar, {0} }, 80 + { MODKEY, XK_j, focusstack, {.i = +1 } }, 81 + { MODKEY, XK_k, focusstack, {.i = -1 } }, 82 + { MODKEY, XK_i, incnmaster, {.i = +1 } }, 83 + { MODKEY, XK_d, incnmaster, {.i = -1 } }, 84 + { MODKEY, XK_h, setmfact, {.f = -0.05} }, 85 + { MODKEY, XK_l, setmfact, {.f = +0.05} }, 86 + { MODKEY, XK_Return, zoom, {0} }, 87 + { MODKEY, XK_Tab, view, {0} }, 88 + { MODKEY|ShiftMask, XK_c, killclient, {0} }, 89 + { MODKEY, XK_t, setlayout, {.v = &layouts[0]} }, 90 + { MODKEY, XK_f, setlayout, {.v = &layouts[1]} }, 91 + { MODKEY, XK_m, setlayout, {.v = &layouts[2]} }, 92 + { MODKEY, XK_space, setlayout, {0} }, 93 + { MODKEY|ShiftMask, XK_space, togglefloating, {0} }, 94 + { MODKEY, XK_0, view, {.ui = ~0 } }, 95 + { MODKEY|ShiftMask, XK_0, tag, {.ui = ~0 } }, 96 + { MODKEY, XK_comma, focusmon, {.i = -1 } }, 97 + { MODKEY, XK_period, focusmon, {.i = +1 } }, 98 + { MODKEY|ShiftMask, XK_comma, tagmon, {.i = -1 } }, 99 + { MODKEY|ShiftMask, XK_period, tagmon, {.i = +1 } }, 100 + { MODKEY|ShiftMask, XK_a, changefocusopacity, {.f = +0.025}}, 101 + { MODKEY|ShiftMask, XK_s, changefocusopacity, {.f = -0.025}}, 102 + { MODKEY|ShiftMask, XK_z, changeunfocusopacity, {.f = +0.025}}, 103 + { MODKEY|ShiftMask, XK_x, changeunfocusopacity, {.f = -0.025}}, 104 + TAGKEYS( XK_1, 0) 105 + TAGKEYS( XK_2, 1) 106 + TAGKEYS( XK_3, 2) 107 + TAGKEYS( XK_4, 3) 108 + TAGKEYS( XK_5, 4) 109 + TAGKEYS( XK_6, 5) 110 + TAGKEYS( XK_7, 6) 111 + TAGKEYS( XK_8, 7) 112 + TAGKEYS( XK_9, 8) 113 + { MODKEY|ShiftMask, XK_q, quit, {0} }, 114 }; 115 116 /* button definitions */ 117 diff --git a/dwm.c b/dwm.c 118 index c2bd871..71cf33c 100644 119 --- a/dwm.c 120 +++ b/dwm.c 121 @@ -62,7 +62,7 @@ enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */ 122 enum { SchemeNorm, SchemeSel }; /* color schemes */ 123 enum { NetSupported, NetWMName, NetWMState, NetWMCheck, 124 NetWMFullscreen, NetActiveWindow, NetWMWindowType, 125 - NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH atoms */ 126 + NetWMWindowTypeDialog, NetClientList, NetWMWindowsOpacity, NetLast }; /* EWMH atoms */ 127 enum { WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast }; /* default atoms */ 128 enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, 129 ClkClientWin, ClkRootWin, ClkLast }; /* clicks */ 130 @@ -95,6 +95,8 @@ struct Client { 131 int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen; 132 Client *next; 133 Client *snext; 134 + double opacity; 135 + double unfocusopacity; 136 Monitor *mon; 137 Window win; 138 }; 139 @@ -138,6 +140,8 @@ typedef struct { 140 const char *title; 141 unsigned int tags; 142 int isfloating; 143 + double opacity; 144 + double unfocusopacity; 145 int monitor; 146 } Rule; 147 148 @@ -149,6 +153,8 @@ static void arrangemon(Monitor *m); 149 static void attach(Client *c); 150 static void attachstack(Client *c); 151 static void buttonpress(XEvent *e); 152 +static void changefocusopacity(const Arg *arg); 153 +static void changeunfocusopacity(const Arg *arg); 154 static void checkotherwm(void); 155 static void cleanup(void); 156 static void cleanupmon(Monitor *mon); 157 @@ -185,6 +191,7 @@ static void monocle(Monitor *m); 158 static void motionnotify(XEvent *e); 159 static void movemouse(const Arg *arg); 160 static Client *nexttiled(Client *c); 161 +static void opacity(Client *c, double opacity); 162 static void pop(Client *c); 163 static void propertynotify(XEvent *e); 164 static void quit(const Arg *arg); 165 @@ -287,6 +294,8 @@ applyrules(Client *c) 166 /* rule matching */ 167 c->isfloating = 0; 168 c->tags = 0; 169 + c->opacity = activeopacity; 170 + c->unfocusopacity = inactiveopacity; 171 XGetClassHint(dpy, c->win, &ch); 172 class = ch.res_class ? ch.res_class : broken; 173 instance = ch.res_name ? ch.res_name : broken; 174 @@ -299,6 +308,8 @@ applyrules(Client *c) 175 { 176 c->isfloating = r->isfloating; 177 c->tags |= r->tags; 178 + c->opacity = r->opacity; 179 + c->unfocusopacity = r->unfocusopacity; 180 for (m = mons; m && m->num != r->monitor; m = m->next); 181 if (m) 182 c->mon = m; 183 @@ -457,6 +468,36 @@ buttonpress(XEvent *e) 184 buttons[i].func(click == ClkTagBar && buttons[i].arg.i == 0 ? &arg : &buttons[i].arg); 185 } 186 187 +void 188 +changefocusopacity(const Arg *arg) 189 +{ 190 + if (!selmon->sel) 191 + return; 192 + selmon->sel->opacity+=arg->f; 193 + if(selmon->sel->opacity > 1.0) 194 + selmon->sel->opacity = 1.0; 195 + 196 + if(selmon->sel->opacity < 0.1) 197 + selmon->sel->opacity = 0.1; 198 + 199 + opacity(selmon->sel, selmon->sel->opacity); 200 +} 201 + 202 +void 203 +changeunfocusopacity(const Arg *arg) 204 +{ 205 + if (!selmon->sel) 206 + return; 207 + selmon->sel->unfocusopacity+=arg->f; 208 + if(selmon->sel->unfocusopacity > 1.0) 209 + selmon->sel->unfocusopacity = 1.0; 210 + 211 + if(selmon->sel->unfocusopacity < 0.1) 212 + selmon->sel->unfocusopacity = 0.1; 213 + 214 + opacity(selmon->sel, selmon->sel->unfocusopacity); 215 +} 216 + 217 void 218 checkotherwm(void) 219 { 220 @@ -803,6 +844,8 @@ focus(Client *c) 221 grabbuttons(c, 1); 222 XSetWindowBorder(dpy, c->win, scheme[SchemeSel][ColBorder].pixel); 223 setfocus(c); 224 + c->opacity = MIN(1.0, MAX(0, c->opacity)); 225 + opacity(c, c->opacity); 226 } else { 227 XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime); 228 XDeleteProperty(dpy, root, netatom[NetActiveWindow]); 229 @@ -1052,6 +1095,7 @@ manage(Window w, XWindowAttributes *wa) 230 c->mon = selmon; 231 applyrules(c); 232 } 233 + opacity(c, c->opacity); 234 235 if (c->x + WIDTH(c) > c->mon->wx + c->mon->ww) 236 c->x = c->mon->wx + c->mon->ww - WIDTH(c); 237 @@ -1209,6 +1253,18 @@ nexttiled(Client *c) 238 return c; 239 } 240 241 +void 242 +opacity(Client *c, double opacity) 243 +{ 244 + if(opacity > 0 && opacity < 1) { 245 + unsigned long real_opacity[] = { opacity * 0xffffffff }; 246 + XChangeProperty(dpy, c->win, netatom[NetWMWindowsOpacity], XA_CARDINAL, 247 + 32, PropModeReplace, (unsigned char *)real_opacity, 248 + 1); 249 + } else 250 + XDeleteProperty(dpy, c->win, netatom[NetWMWindowsOpacity]); 251 +} 252 + 253 void 254 pop(Client *c) 255 { 256 @@ -1579,6 +1635,7 @@ setup(void) 257 netatom[NetWMWindowType] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE", False); 258 netatom[NetWMWindowTypeDialog] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DIALOG", False); 259 netatom[NetClientList] = XInternAtom(dpy, "_NET_CLIENT_LIST", False); 260 + netatom[NetWMWindowsOpacity] = XInternAtom(dpy, "_NET_WM_WINDOW_OPACITY", False); 261 /* init cursors */ 262 cursor[CurNormal] = drw_cur_create(drw, XC_left_ptr); 263 cursor[CurResize] = drw_cur_create(drw, XC_sizing); 264 @@ -1760,6 +1817,8 @@ unfocus(Client *c, int setfocus) 265 if (!c) 266 return; 267 grabbuttons(c, 0); 268 + c->unfocusopacity = MIN(1.0, MAX(0, c->unfocusopacity)); 269 + opacity(c, c->unfocusopacity); 270 XSetWindowBorder(dpy, c->win, scheme[SchemeNorm][ColBorder].pixel); 271 if (setfocus) { 272 XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime); 273 -- 274 2.39.2 275