commit 264e458cc4ad82c1615cafd6b8f240312044dffd Author: Wessel Tip Date: Thu Sep 4 10:20:59 2025 +0200 feat: Add initial config files diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..5cfbb5a --- /dev/null +++ b/Makefile @@ -0,0 +1,19 @@ +.POSIX: + +PREFIX = /usr/local +CC = gcc + +dwmblocks: dwmblocks.o + $(CC) dwmblocks.o -lX11 -o dwmblocks +dwmblocks.o: dwmblocks.c config.h + $(CC) -c dwmblocks.c +clean: + rm -f *.o *.gch dwmblocks +install: dwmblocks + mkdir -p $(DESTDIR)$(PREFIX)/bin + cp -f dwmblocks $(DESTDIR)$(PREFIX)/bin + chmod 755 $(DESTDIR)$(PREFIX)/bin/dwmblocks +uninstall: + rm -f $(DESTDIR)$(PREFIX)/bin/dwmblocks + +.PHONY: clean install uninstall diff --git a/config.def.h b/config.def.h new file mode 100644 index 0000000..a54a0a6 --- /dev/null +++ b/config.def.h @@ -0,0 +1,19 @@ +//Modify this file to change what commands output to your statusbar, and recompile using the make command. +static const Block blocks[] = { + /*Icon Command [...] Update Interval Update Signal */ + { "", "sb-internet", 5, 4 }, + { "", "sb-nettraf", 5, 11 }, + { "", "sb-volume", 0, 3 }, + { "", "sb-battery", 15, 2 }, + { "", "sb-clock", 30, 1 }, +}; + +// Sets delimiter between status commands. NULL character ('\0') means no delimiter. +// static char *delim = " | "; +// static char *delim = " "; +static char *delim = ""; + +// Have dwmblocks automatically recompile and run when you edit this file in +// vim with the following line in your vimrc/init.vim: + +// autocmd BufWritePost ~/.local/src/dwmblocks/config.h !cd ~/.local/src/dwmblocks/; sudo make install && { killall -q dwmblocks;setsid dwmblocks & } diff --git a/config.h b/config.h new file mode 100644 index 0000000..bd1e8ae --- /dev/null +++ b/config.h @@ -0,0 +1,34 @@ +//Modify this file to change what commands output to your statusbar, and recompile using the make command. +static const Block blocks[] = { + /*Icon Command [...] Update Interval Update Signal */ + /* {"⌨", "sb-kbselect", 0, 30}, */ + { " ", "cat /tmp/recordingicon 2>/dev/null", 0, 9}, + { "", "sb-internet", 5, 4 }, + { "", "sb-nettraf", 5, 11 }, + { "", "sb-volume", 0, 3 }, + { "", "sb-backlight", 0, 5 }, + { "", "sb-battery", 15, 2 }, + { "", "sb-clock", 30, 1 }, + // { "", "sb-news", 0, 6 }, + // { " ", "sb-pacpackages", 0, 8 }, + // {"", "sb-tasks", 10, 26}, /* Background tasks */ + // {"", "sb-music", 0, 11}, + // {"", "sb-price btc Bitcoin 💰", 9000, 21}, + // {"", "sb-torrent", 20, 7}, + // {"", "sb-memory", 10, 14}, + // {"", "sb-cpu", 10, 18}, + // {"", "sb-moonphase", 18000, 17}, + // {"", "sb-forecast", 18000, 5}, + // {"", "sb-mailbox", 180, 12}, + // {"", "sb-help-icon", 0, 15}, +}; + +// Sets delimiter between status commands. NULL character ('\0') means no delimiter. +// static char *delim = " | "; +// static char *delim = " "; +static char *delim = ""; + +// Have dwmblocks automatically recompile and run when you edit this file in +// vim with the following line in your vimrc/init.vim: + +// autocmd BufWritePost ~/.local/src/dwmblocks/config.h !cd ~/.local/src/dwmblocks/; sudo make install && { killall -q dwmblocks;setsid dwmblocks & } diff --git a/dwmblocks.c b/dwmblocks.c new file mode 100644 index 0000000..f373507 --- /dev/null +++ b/dwmblocks.c @@ -0,0 +1,295 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#define LENGTH(X) (sizeof(X) / sizeof (X[0])) +#define CMDLENGTH 50 + +typedef struct { + char* icon; + char* command; + unsigned int interval; + unsigned int signal; +} Block; +void sighandler(int num); +void buttonhandler(int sig, siginfo_t *si, void *ucontext); +void replace(char *str, char old, char new); +void remove_all(char *str, char to_remove); +void getcmds(int time); +#ifndef __OpenBSD__ +void getsigcmds(int signal); +void setupsignals(); +void sighandler(int signum); +#endif +int getstatus(char *str, char *last); +void setroot(); +void statusloop(); +void termhandler(int signum); + + +#include "config.h" + +static Display *dpy; +static int screen; +static Window root; +static char statusbar[LENGTH(blocks)][CMDLENGTH] = {0}; +static char statusstr[2][256]; +static int statusContinue = 1; +static void (*writestatus) () = setroot; + +void replace(char *str, char old, char new) +{ + for(char * c = str; *c; c++) + if(*c == old) + *c = new; +} + +// the previous function looked nice but unfortunately it didnt work if +// to_remove was in any position other than the last character +// theres probably still a better way of doing this +void remove_all(char *str, char to_remove) { + char *read = str; + char *write = str; + while (*read) { + if (*read != to_remove) { + *write++ = *read; + } + ++read; + } + *write = '\0'; +} + +int gcd(int a, int b) +{ + int temp; + while (b > 0){ + temp = a % b; + + a = b; + b = temp; + } + return a; +} + + +//opens process *cmd and stores output in *output +void getcmd(const Block *block, char *output) +{ + if (block->signal) + { + output[0] = block->signal; + output++; + } + char *cmd = block->command; + FILE *cmdf = popen(cmd,"r"); + if (!cmdf){ + //printf("failed to run: %s, %d\n", block->command, errno); + return; + } + char tmpstr[CMDLENGTH] = ""; + // TODO decide whether its better to use the last value till next time or just keep trying while the error was the interrupt + // this keeps trying to read if it got nothing and the error was an interrupt + // could also just read to a separate buffer and not move the data over if interrupted + // this way will take longer trying to complete 1 thing but will get it done + // the other way will move on to keep going with everything and the part that failed to read will be wrong till its updated again + // either way you have to save the data to a temp buffer because when it fails it writes nothing and then then it gets displayed before this finishes + char * s; + int e; + do { + errno = 0; + s = fgets(tmpstr, CMDLENGTH-(strlen(delim)+1), cmdf); + e = errno; + } while (!s && e == EINTR); + pclose(cmdf); + int i = strlen(block->icon); + strcpy(output, block->icon); + strcpy(output+i, tmpstr); + remove_all(output, '\n'); + i = strlen(output); + if ((i > 0 && block != &blocks[LENGTH(blocks) - 1])){ + strcat(output, delim); + } + i+=strlen(delim); + output[i++] = '\0'; +} + +void getcmds(int time) +{ + const Block* current; + for(int i = 0; i < LENGTH(blocks); i++) + { + current = blocks + i; + if ((current->interval != 0 && time % current->interval == 0) || time == -1){ + getcmd(current,statusbar[i]); + } + } +} + +#ifndef __OpenBSD__ +void getsigcmds(int signal) +{ + const Block *current; + for (int i = 0; i < LENGTH(blocks); i++) + { + current = blocks + i; + if (current->signal == signal){ + getcmd(current,statusbar[i]); + } + } +} + +void setupsignals() +{ + struct sigaction sa; + + for(int i = SIGRTMIN; i <= SIGRTMAX; i++) + signal(i, SIG_IGN); + + for(int i = 0; i < LENGTH(blocks); i++) + { + if (blocks[i].signal > 0) + { + signal(SIGRTMIN+blocks[i].signal, sighandler); + sigaddset(&sa.sa_mask, SIGRTMIN+blocks[i].signal); + } + } + sa.sa_sigaction = buttonhandler; + sa.sa_flags = SA_SIGINFO; + sigaction(SIGUSR1, &sa, NULL); + struct sigaction sigchld_action = { + .sa_handler = SIG_DFL, + .sa_flags = SA_NOCLDWAIT + }; + sigaction(SIGCHLD, &sigchld_action, NULL); + +} +#endif + +int getstatus(char *str, char *last) +{ + strcpy(last, str); + str[0] = '\0'; + for(int i = 0; i < LENGTH(blocks); i++) { + strcat(str, statusbar[i]); + if (i == LENGTH(blocks) - 1) + strcat(str, " "); + } + str[strlen(str)-1] = '\0'; + return strcmp(str, last);//0 if they are the same +} + +void setroot() +{ + if (!getstatus(statusstr[0], statusstr[1]))//Only set root if text has changed. + return; + Display *d = XOpenDisplay(NULL); + if (d) { + dpy = d; + } + screen = DefaultScreen(dpy); + root = RootWindow(dpy, screen); + XStoreName(dpy, root, statusstr[0]); + XCloseDisplay(dpy); +} + +void pstdout() +{ + if (!getstatus(statusstr[0], statusstr[1]))//Only write out if text has changed. + return; + printf("%s\n",statusstr[0]); + fflush(stdout); +} + + +void statusloop() +{ +#ifndef __OpenBSD__ + setupsignals(); +#endif + // first figure out the default wait interval by finding the + // greatest common denominator of the intervals + unsigned int interval = -1; + for(int i = 0; i < LENGTH(blocks); i++){ + if(blocks[i].interval){ + interval = gcd(blocks[i].interval, interval); + } + } + unsigned int i = 0; + int interrupted = 0; + const struct timespec sleeptime = {interval, 0}; + struct timespec tosleep = sleeptime; + getcmds(-1); + while(statusContinue) + { + // sleep for tosleep (should be a sleeptime of interval seconds) and put what was left if interrupted back into tosleep + interrupted = nanosleep(&tosleep, &tosleep); + // if interrupted then just go sleep again for the remaining time + if(interrupted == -1){ + continue; + } + // if not interrupted then do the calling and writing + getcmds(i); + writestatus(); + // then increment since its actually been a second (plus the time it took the commands to run) + i += interval; + // set the time to sleep back to the sleeptime of 1s + tosleep = sleeptime; + } +} + +#ifndef __OpenBSD__ +void sighandler(int signum) +{ + getsigcmds(signum-SIGRTMIN); + writestatus(); +} + +void buttonhandler(int sig, siginfo_t *si, void *ucontext) +{ + char button[2] = {'0' + si->si_value.sival_int & 0xff, '\0'}; + pid_t process_id = getpid(); + sig = si->si_value.sival_int >> 8; + if (fork() == 0) + { + const Block *current; + for (int i = 0; i < LENGTH(blocks); i++) + { + current = blocks + i; + if (current->signal == sig) + break; + } + char shcmd[1024]; + sprintf(shcmd,"%s && kill -%d %d",current->command, current->signal+34,process_id); + char *command[] = { "/bin/sh", "-c", shcmd, NULL }; + setenv("BLOCK_BUTTON", button, 1); + setsid(); + execvp(command[0], command); + exit(EXIT_SUCCESS); + } +} + +#endif + +void termhandler(int signum) +{ + statusContinue = 0; + exit(0); +} + +int main(int argc, char** argv) +{ + for(int i = 0; i < argc; i++) + { + if (!strcmp("-d",argv[i])) + delim = argv[++i]; + else if(!strcmp("-p",argv[i])) + writestatus = pstdout; + } + signal(SIGTERM, termhandler); + signal(SIGINT, termhandler); + statusloop(); +} diff --git a/patches/dwmblocks-statuscmd-b6b0be4.diff b/patches/dwmblocks-statuscmd-b6b0be4.diff new file mode 100644 index 0000000..96bfc53 --- /dev/null +++ b/patches/dwmblocks-statuscmd-b6b0be4.diff @@ -0,0 +1,75 @@ +diff -up a/dwmblocks.c b/dwmblocks.c +--- a/dwmblocks.c 2020-12-22 14:25:05.289247774 +0200 ++++ b/dwmblocks.c 2020-12-22 14:29:39.744943965 +0200 +@@ -28,6 +28,7 @@ typedef struct { + void dummysighandler(int num); + #endif + void sighandler(int num); ++void buttonhandler(int sig, siginfo_t *si, void *ucontext); + void getcmds(int time); + void getsigcmds(unsigned int signal); + void setupsignals(); +@@ -52,14 +53,31 @@ static void (*writestatus) () = pstdout; + + static char statusbar[LENGTH(blocks)][CMDLENGTH] = {0}; + static char statusstr[2][STATUSLENGTH]; ++static char button[] = "\0"; + static int statusContinue = 1; + static int returnStatus = 0; + + //opens process *cmd and stores output in *output + void getcmd(const Block *block, char *output) + { ++ if (block->signal) ++ { ++ output[0] = block->signal; ++ output++; ++ } + strcpy(output, block->icon); +- FILE *cmdf = popen(block->command, "r"); ++ FILE *cmdf; ++ if (*button) ++ { ++ setenv("BUTTON", button, 1); ++ cmdf = popen(block->command,"r"); ++ *button = '\0'; ++ unsetenv("BUTTON"); ++ } ++ else ++ { ++ cmdf = popen(block->command,"r"); ++ } + if (!cmdf) + return; + int i = strlen(block->icon); +@@ -105,9 +123,15 @@ void setupsignals() + signal(i, dummysighandler); + #endif + ++ struct sigaction sa; + for (unsigned int i = 0; i < LENGTH(blocks); i++) { +- if (blocks[i].signal > 0) ++ if (blocks[i].signal > 0) { + signal(SIGMINUS+blocks[i].signal, sighandler); ++ sigaddset(&sa.sa_mask, SIGRTMIN+blocks[i].signal); // ignore signal when handling SIGUSR1 ++ } ++ sa.sa_sigaction = buttonhandler; ++ sa.sa_flags = SA_SIGINFO; ++ sigaction(SIGUSR1, &sa, NULL); + } + + } +@@ -173,6 +197,13 @@ void dummysighandler(int signum) + { + return; + } ++ ++void buttonhandler(int sig, siginfo_t *si, void *ucontext) ++{ ++ *button = '0' + si->si_value.sival_int & 0xff; ++ getsigcmds(si->si_value.sival_int >> 8); ++ writestatus(); ++} + #endif + + void sighandler(int signum)