dwm-chargecolor-20250918-2d2fd29.diff (8192B)
1 From 2d2fd29361c1e521fb74ef825d75135ad5da8482 Mon Sep 17 00:00:00 2001 2 From: elbachir-one <bachiralfa@gmail.com> 3 Date: Thu, 18 Sep 2025 12:32:15 +0100 4 Subject: [PATCH] Dynamically switches between predefined color schemes 5 depending on whether the AC is plugged in or unplugged 6 7 --- 8 config.def.h | 19 ++++---- 9 dwm.c | 133 ++++++++++++++++++++++++++++++++++++++++++++++++--- 10 2 files changed, 136 insertions(+), 16 deletions(-) 11 12 diff --git a/config.def.h b/config.def.h 13 index 3836510..8075450 100644 14 --- a/config.def.h 15 +++ b/config.def.h 16 @@ -6,18 +6,17 @@ static const unsigned int snap = 32; /* snap pixel */ 17 static const int showbar = 1; /* 0 means no bar */ 18 static const int topbar = 1; /* 0 means bottom bar */ 19 static const char *fonts[] = { "monospace:size=10" }; 20 -static const char dmenufont[] = "monospace:size=10"; 21 -static const char col_gray1[] = "#222222"; 22 -static const char col_gray2[] = "#444444"; 23 -static const char col_gray3[] = "#bbbbbb"; 24 -static const char col_gray4[] = "#eeeeee"; 25 -static const char col_cyan[] = "#005577"; 26 -static const char *colors[][3] = { 27 + 28 +char *colors[][3] = { 29 /* fg bg border */ 30 - [SchemeNorm] = { col_gray3, col_gray1, col_gray2 }, 31 - [SchemeSel] = { col_gray4, col_cyan, col_cyan }, 32 + [SchemeNorm] = { "#ffffff", "#222222", "#444444" }, 33 + [SchemeSel] = { "#ffffff", "#005577", "#005577" }, 34 }; 35 36 +static const char **current_theme = NULL; 37 +static const char *blue[] = { "#ffffff", "#0E1C4A", "#3E54BD" }; 38 +static const char *red[] = { "#ffffff", "#430B07", "#73493D" }; 39 + 40 /* tagging */ 41 static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" }; 42 43 @@ -58,7 +57,7 @@ static const Layout layouts[] = { 44 45 /* commands */ 46 static char dmenumon[2] = "0"; /* component of dmenucmd, manipulated in spawn() */ 47 -static const char *dmenucmd[] = { "dmenu_run", "-m", dmenumon, "-fn", dmenufont, "-nb", col_gray1, "-nf", col_gray3, "-sb", col_cyan, "-sf", col_gray4, NULL }; 48 +static const char *dmenucmd[] = { "dmenu_run", NULL }; 49 static const char *termcmd[] = { "st", NULL }; 50 51 static const Key keys[] = { 52 diff --git a/dwm.c b/dwm.c 53 index 4cf07eb..87c3ae0 100644 54 --- a/dwm.c 55 +++ b/dwm.c 56 @@ -22,14 +22,17 @@ 57 */ 58 #include <errno.h> 59 #include <locale.h> 60 +#include <limits.h> 61 #include <signal.h> 62 #include <stdarg.h> 63 #include <stdio.h> 64 #include <stdlib.h> 65 #include <string.h> 66 +#include <dirent.h> 67 #include <unistd.h> 68 #include <sys/types.h> 69 #include <sys/wait.h> 70 +#include <pthread.h> 71 #include <X11/cursorfont.h> 72 #include <X11/keysym.h> 73 #include <X11/Xatom.h> 74 @@ -175,6 +178,7 @@ static int gettextprop(Window w, Atom atom, char *text, unsigned int size); 75 static void grabbuttons(Client *c, int focused); 76 static void grabkeys(void); 77 static void incnmaster(const Arg *arg); 78 +static int ischarging(void); 79 static void keypress(XEvent *e); 80 static void killclient(const Arg *arg); 81 static void manage(Window w, XWindowAttributes *wa); 82 @@ -215,6 +219,7 @@ static void toggleview(const Arg *arg); 83 static void unfocus(Client *c, int setfocus); 84 static void unmanage(Client *c, int destroyed); 85 static void unmapnotify(XEvent *e); 86 +static void updatecolors(void); 87 static void updatebarpos(Monitor *m); 88 static void updatebars(void); 89 static void updateclientlist(void); 90 @@ -240,6 +245,7 @@ static int screen; 91 static int sw, sh; /* X display screen geometry width, height */ 92 static int bh; /* bar height */ 93 static int lrpad; /* sum of left and right padding for text */ 94 +static int colorpipe[2]; /* pipe for notifying main thread about color changes */ 95 static int (*xerrorxlib)(Display *, XErrorEvent *); 96 static unsigned int numlockmask = 0; 97 static void (*handler[LASTEvent]) (XEvent *) = { 98 @@ -493,6 +499,8 @@ cleanup(void) 99 XSync(dpy, False); 100 XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime); 101 XDeleteProperty(dpy, root, netatom[NetActiveWindow]); 102 + close(colorpipe[0]); 103 + close(colorpipe[1]); 104 } 105 106 void 107 @@ -983,6 +991,43 @@ incnmaster(const Arg *arg) 108 arrange(selmon); 109 } 110 111 +int ischarging(void) { 112 + const char *base = "/sys/class/power_supply/"; 113 + DIR *dir = opendir(base); 114 + if (!dir) return 0; 115 + 116 + struct dirent *entry; 117 + char path[PATH_MAX]; 118 + FILE *f; 119 + int status = 0; 120 + 121 + while ((entry = readdir(dir))) { 122 + if (entry->d_type != DT_DIR && entry->d_type != DT_LNK) 123 + continue; 124 + 125 + snprintf(path, sizeof(path), "%s%s/type", base, entry->d_name); 126 + f = fopen(path, "r"); 127 + if (!f) continue; 128 + 129 + char type[32]; 130 + if (fgets(type, sizeof(type), f)) { 131 + if (strncmp(type, "Mains", 5) == 0) { 132 + fclose(f); 133 + snprintf(path, sizeof(path), "%s%s/online", base, entry->d_name); 134 + f = fopen(path, "r"); 135 + if (!f) break; 136 + fscanf(f, "%d", &status); 137 + fclose(f); 138 + break; 139 + } 140 + } 141 + fclose(f); 142 + } 143 + 144 + closedir(dir); 145 + return status; 146 +} 147 + 148 #ifdef XINERAMA 149 static int 150 isuniquegeom(XineramaScreenInfo *unique, size_t n, XineramaScreenInfo *info) 151 @@ -1382,11 +1427,36 @@ void 152 run(void) 153 { 154 XEvent ev; 155 - /* main event loop */ 156 - XSync(dpy, False); 157 - while (running && !XNextEvent(dpy, &ev)) 158 - if (handler[ev.type]) 159 - handler[ev.type](&ev); /* call handler */ 160 + int x11_fd = ConnectionNumber(dpy); 161 + int maxfd = (colorpipe[0] > x11_fd) ? colorpipe[0] : x11_fd; 162 + 163 + fd_set rfds; 164 + 165 + while (running) { 166 + FD_ZERO(&rfds); 167 + FD_SET(x11_fd, &rfds); 168 + FD_SET(colorpipe[0], &rfds); 169 + 170 + if (select(maxfd + 1, &rfds, NULL, NULL, NULL) < 0) { 171 + if (errno == EINTR) 172 + continue; 173 + die("select failed"); 174 + } 175 + 176 + if (FD_ISSET(colorpipe[0], &rfds)) { 177 + char buf[1]; 178 + read(colorpipe[0], buf, 1); /* clear pipe */ 179 + updatecolors(); /* safe update in main thread */ 180 + } 181 + 182 + if (FD_ISSET(x11_fd, &rfds)) { 183 + while (XPending(dpy)) { 184 + XNextEvent(dpy, &ev); 185 + if (handler[ev.type]) 186 + handler[ev.type](&ev); 187 + } 188 + } 189 + } 190 } 191 192 void 193 @@ -1582,10 +1652,13 @@ setup(void) 194 cursor[CurNormal] = drw_cur_create(drw, XC_left_ptr); 195 cursor[CurResize] = drw_cur_create(drw, XC_sizing); 196 cursor[CurMove] = drw_cur_create(drw, XC_fleur); 197 + if (pipe(colorpipe) == -1) { 198 + die("Failed to create pipe"); 199 + } 200 /* init appearance */ 201 scheme = ecalloc(LENGTH(colors), sizeof(Clr *)); 202 for (i = 0; i < LENGTH(colors); i++) 203 - scheme[i] = drw_scm_create(drw, colors[i], 3); 204 + scheme[i] = drw_scm_create(drw, (const char **)colors[i], 3); 205 /* init bars */ 206 updatebars(); 207 updatestatus(); 208 @@ -1711,6 +1784,21 @@ tile(Monitor *m) 209 } 210 } 211 212 +void * 213 +themechecker(void *arg) { 214 + int last_status = -1; 215 + for (;;) { 216 + int charging = ischarging(); 217 + if (charging != last_status) { 218 + current_theme = charging ? blue : red; 219 + updatecolors(); 220 + last_status = charging; 221 + } 222 + usleep(1000000); 223 + } 224 + return NULL; 225 +} 226 + 227 void 228 togglebar(const Arg *arg) 229 { 230 @@ -1814,6 +1902,34 @@ unmapnotify(XEvent *e) 231 } 232 } 233 234 +void 235 +updatecolors(void) { 236 + colors[SchemeNorm][0] = (char *)current_theme[0]; 237 + colors[SchemeNorm][1] = (char *)current_theme[1]; 238 + colors[SchemeNorm][2] = (char *)current_theme[1]; 239 + 240 + colors[SchemeSel][0] = (char *)current_theme[0]; 241 + colors[SchemeSel][1] = (char *)current_theme[2]; 242 + colors[SchemeSel][2] = (char *)current_theme[2]; 243 + 244 + for (int i = 0; i < LENGTH(colors); i++) { 245 + if (scheme[i]) 246 + free(scheme[i]); 247 + scheme[i] = drw_scm_create(drw, (const char **)colors[i], 3); 248 + } 249 + 250 + for (Monitor *m = mons; m; m = m->next) { 251 + drawbar(m); 252 + arrange(m); 253 + 254 + /* Update borders of all clients on this monitor */ 255 + for (Client *c = m->clients; c; c = c->next) { 256 + XSetWindowBorder(dpy, c->win, 257 + scheme[c == m->sel ? SchemeSel : SchemeNorm][2].pixel); 258 + } 259 + } 260 +} 261 + 262 void 263 updatebars(void) 264 { 265 @@ -2152,12 +2268,17 @@ main(int argc, char *argv[]) 266 die("dwm: cannot open display"); 267 checkotherwm(); 268 setup(); 269 + 270 + pthread_t theme_thread; 271 + pthread_create(&theme_thread, NULL, themechecker, NULL); 272 + 273 #ifdef __OpenBSD__ 274 if (pledge("stdio rpath proc exec", NULL) == -1) 275 die("pledge"); 276 #endif /* __OpenBSD__ */ 277 scan(); 278 run(); 279 + pthread_join(theme_thread, NULL); 280 cleanup(); 281 XCloseDisplay(dpy); 282 return EXIT_SUCCESS; 283 -- 284 2.50.1 285