sites

public wiki contents of suckless.org
git clone git://git.suckless.org/sites
Log | Files | Refs

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