├── .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 |
--------------------------------------------------------------------------------