├── .gitignore ├── LICENSE ├── Makefile ├── README.md ├── blocks.def.h └── dwmblocks.c /.gitignore: -------------------------------------------------------------------------------- 1 | # Custom blocks file 2 | blocks.h 3 | 4 | # Prerequisites 5 | *.d 6 | 7 | # Object files 8 | *.o 9 | *.ko 10 | *.obj 11 | *.elf 12 | 13 | # Linker output 14 | *.ilk 15 | *.map 16 | *.exp 17 | 18 | # Precompiled Headers 19 | *.gch 20 | *.pch 21 | 22 | # Libraries 23 | *.lib 24 | *.a 25 | *.la 26 | *.lo 27 | 28 | # Shared objects (inc. Windows DLLs) 29 | *.dll 30 | *.so 31 | *.so.* 32 | *.dylib 33 | 34 | # Executables 35 | *.exe 36 | *.out 37 | *.app 38 | *.i*86 39 | *.x86_64 40 | *.hex 41 | dwmblocks 42 | 43 | # Debug files 44 | *.dSYM/ 45 | *.su 46 | *.idb 47 | *.pdb 48 | 49 | # Kernel Module Compile Results 50 | *.mod* 51 | *.cmd 52 | .tmp_versions/ 53 | modules.order 54 | Module.symvers 55 | Mkfile.old 56 | dkms.conf 57 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | ISC License (ISC) 2 | 3 | Copyright 2020 torrinfail 4 | 5 | Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 8 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | PREFIX := /usr/local 2 | CC := cc 3 | CFLAGS := -pedantic -Wall -Wno-deprecated-declarations -Os 4 | LDFLAGS := -lX11 5 | 6 | # FreeBSD (uncomment) 7 | #LDFLAGS += -L/usr/local/lib -I/usr/local/include 8 | # # OpenBSD (uncomment) 9 | #LDFLAGS += -L/usr/X11R6/lib -I/usr/X11R6/include 10 | 11 | all: options dwmblocks 12 | 13 | options: 14 | @echo dwmblocks build options: 15 | @echo "CFLAGS = ${CFLAGS}" 16 | @echo "LDFLAGS = ${LDFLAGS}" 17 | @echo "CC = ${CC}" 18 | 19 | dwmblocks: dwmblocks.c blocks.def.h blocks.h 20 | ${CC} -o dwmblocks dwmblocks.c ${CFLAGS} ${LDFLAGS} 21 | 22 | blocks.h: 23 | cp blocks.def.h $@ 24 | 25 | clean: 26 | rm -f *.o *.gch dwmblocks 27 | 28 | install: dwmblocks 29 | mkdir -p ${DESTDIR}${PREFIX}/bin 30 | cp -f dwmblocks ${DESTDIR}${PREFIX}/bin 31 | chmod 755 ${DESTDIR}${PREFIX}/bin/dwmblocks 32 | 33 | uninstall: 34 | rm -f ${DESTDIR}${PREFIX}/bin/dwmblocks 35 | 36 | .PHONY: all options clean install uninstall 37 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # dwmblocks 2 | Modular status bar for dwm written in c. 3 | # usage 4 | To use dwmblocks first run 'make' and then install it with 'sudo make install'. 5 | After that you can put dwmblocks in your xinitrc or other startup script to have it start with dwm. 6 | # modifying blocks 7 | The statusbar is made from text output from commandline programs. 8 | Blocks are added and removed by editing the blocks.h header file. 9 | By default the blocks.h header file is created the first time you run make which copies the default config from blocks.def.h. 10 | This is so you can edit your status bar commands and they will not get overwritten in a future update. 11 | # patches 12 | Here are some patches to dwmblocks that add features that I either don't want to merge in, or that require a dwm patch to work. 13 | I do not maintain these but I will take pull requests to update them. 14 |
15 | dwmblocks-statuscmd-b6b0be4.diff 16 | -------------------------------------------------------------------------------- /blocks.def.h: -------------------------------------------------------------------------------- 1 | //Modify this file to change what commands output to your statusbar, and recompile using the make command. 2 | static const Block blocks[] = { 3 | /*Icon*/ /*Command*/ /*Update Interval*/ /*Update Signal*/ 4 | {"Mem:", "free -h | awk '/^Mem/ { print $3\"/\"$2 }' | sed s/i//g", 30, 0}, 5 | 6 | {"", "date '+%b %d (%a) %I:%M%p'", 5, 0}, 7 | }; 8 | 9 | //sets delimiter between status commands. NULL character ('\0') means no delimiter. 10 | static char delim[] = " | "; 11 | static unsigned int delimLen = 5; 12 | -------------------------------------------------------------------------------- /dwmblocks.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #ifndef NO_X 7 | #include 8 | #endif 9 | #ifdef __OpenBSD__ 10 | #define SIGPLUS SIGUSR1+1 11 | #define SIGMINUS SIGUSR1-1 12 | #else 13 | #define SIGPLUS SIGRTMIN 14 | #define SIGMINUS SIGRTMIN 15 | #endif 16 | #define LENGTH(X) (sizeof(X) / sizeof (X[0])) 17 | #define CMDLENGTH 50 18 | #define MIN( a, b ) ( ( a < b) ? a : b ) 19 | #define STATUSLENGTH (LENGTH(blocks) * CMDLENGTH + 1) 20 | 21 | typedef struct { 22 | char* icon; 23 | char* command; 24 | unsigned int interval; 25 | unsigned int signal; 26 | } Block; 27 | #ifndef __OpenBSD__ 28 | void dummysighandler(int num); 29 | #endif 30 | void sighandler(int num); 31 | void getcmds(int time); 32 | void getsigcmds(unsigned int signal); 33 | void setupsignals(); 34 | void sighandler(int signum); 35 | int getstatus(char *str, char *last); 36 | void statusloop(); 37 | void termhandler(); 38 | void pstdout(); 39 | #ifndef NO_X 40 | void setroot(); 41 | static void (*writestatus) () = setroot; 42 | static int setupX(); 43 | static Display *dpy; 44 | static int screen; 45 | static Window root; 46 | #else 47 | static void (*writestatus) () = pstdout; 48 | #endif 49 | 50 | 51 | #include "blocks.h" 52 | 53 | static char statusbar[LENGTH(blocks)][CMDLENGTH] = {0}; 54 | static char statusstr[2][STATUSLENGTH]; 55 | static int statusContinue = 1; 56 | static int returnStatus = 0; 57 | 58 | //opens process *cmd and stores output in *output 59 | void getcmd(const Block *block, char *output) 60 | { 61 | //make sure status is same until output is ready 62 | char tempstatus[CMDLENGTH] = {0}; 63 | strcpy(tempstatus, block->icon); 64 | FILE *cmdf = popen(block->command, "r"); 65 | if (!cmdf) 66 | return; 67 | int i = strlen(block->icon); 68 | fgets(tempstatus+i, CMDLENGTH-i-delimLen, cmdf); 69 | i = strlen(tempstatus); 70 | //if block and command output are both not empty 71 | if (i != 0) { 72 | //only chop off newline if one is present at the end 73 | i = tempstatus[i-1] == '\n' ? i-1 : i; 74 | if (delim[0] != '\0') { 75 | strncpy(tempstatus+i, delim, delimLen); 76 | } 77 | else 78 | tempstatus[i++] = '\0'; 79 | } 80 | strcpy(output, tempstatus); 81 | pclose(cmdf); 82 | } 83 | 84 | void getcmds(int time) 85 | { 86 | const Block* current; 87 | for (unsigned int i = 0; i < LENGTH(blocks); i++) { 88 | current = blocks + i; 89 | if ((current->interval != 0 && time % current->interval == 0) || time == -1) 90 | getcmd(current,statusbar[i]); 91 | } 92 | } 93 | 94 | void getsigcmds(unsigned int signal) 95 | { 96 | const Block *current; 97 | for (unsigned int i = 0; i < LENGTH(blocks); i++) { 98 | current = blocks + i; 99 | if (current->signal == signal) 100 | getcmd(current,statusbar[i]); 101 | } 102 | } 103 | 104 | void setupsignals() 105 | { 106 | #ifndef __OpenBSD__ 107 | /* initialize all real time signals with dummy handler */ 108 | for (int i = SIGRTMIN; i <= SIGRTMAX; i++) 109 | signal(i, dummysighandler); 110 | #endif 111 | 112 | for (unsigned int i = 0; i < LENGTH(blocks); i++) { 113 | if (blocks[i].signal > 0) 114 | signal(SIGMINUS+blocks[i].signal, sighandler); 115 | } 116 | 117 | } 118 | 119 | int getstatus(char *str, char *last) 120 | { 121 | strcpy(last, str); 122 | str[0] = '\0'; 123 | for (unsigned int i = 0; i < LENGTH(blocks); i++) 124 | strcat(str, statusbar[i]); 125 | str[strlen(str)-strlen(delim)] = '\0'; 126 | return strcmp(str, last);//0 if they are the same 127 | } 128 | 129 | #ifndef NO_X 130 | void setroot() 131 | { 132 | if (!getstatus(statusstr[0], statusstr[1]))//Only set root if text has changed. 133 | return; 134 | XStoreName(dpy, root, statusstr[0]); 135 | XFlush(dpy); 136 | } 137 | 138 | int setupX() 139 | { 140 | dpy = XOpenDisplay(NULL); 141 | if (!dpy) { 142 | fprintf(stderr, "dwmblocks: Failed to open display\n"); 143 | return 0; 144 | } 145 | screen = DefaultScreen(dpy); 146 | root = RootWindow(dpy, screen); 147 | return 1; 148 | } 149 | #endif 150 | 151 | void pstdout() 152 | { 153 | if (!getstatus(statusstr[0], statusstr[1]))//Only write out if text has changed. 154 | return; 155 | printf("%s\n",statusstr[0]); 156 | fflush(stdout); 157 | } 158 | 159 | 160 | void statusloop() 161 | { 162 | setupsignals(); 163 | int i = 0; 164 | getcmds(-1); 165 | while (1) { 166 | getcmds(i++); 167 | writestatus(); 168 | if (!statusContinue) 169 | break; 170 | sleep(1.0); 171 | } 172 | } 173 | 174 | #ifndef __OpenBSD__ 175 | /* this signal handler should do nothing */ 176 | void dummysighandler(int signum) 177 | { 178 | return; 179 | } 180 | #endif 181 | 182 | void sighandler(int signum) 183 | { 184 | getsigcmds(signum-SIGPLUS); 185 | writestatus(); 186 | } 187 | 188 | void termhandler() 189 | { 190 | statusContinue = 0; 191 | } 192 | 193 | int main(int argc, char** argv) 194 | { 195 | for (int i = 0; i < argc; i++) {//Handle command line arguments 196 | if (!strcmp("-d",argv[i])) 197 | strncpy(delim, argv[++i], delimLen); 198 | else if (!strcmp("-p",argv[i])) 199 | writestatus = pstdout; 200 | } 201 | #ifndef NO_X 202 | if (!setupX()) 203 | return 1; 204 | #endif 205 | delimLen = MIN(delimLen, strlen(delim)); 206 | delim[delimLen++] = '\0'; 207 | signal(SIGTERM, termhandler); 208 | signal(SIGINT, termhandler); 209 | statusloop(); 210 | #ifndef NO_X 211 | XCloseDisplay(dpy); 212 | #endif 213 | return 0; 214 | } 215 | --------------------------------------------------------------------------------