Initial commit

This commit is contained in:
Alexander Rosenberg 2023-02-21 12:15:57 -08:00
commit a8d9901a57
Signed by: Zander671
GPG Key ID: 5FD0394ADBD72730
9 changed files with 436 additions and 0 deletions

56
.gitignore vendored Normal file
View File

@ -0,0 +1,56 @@
# Custom blocks file
blocks.h
# Prerequisites
*.d
# Object files
*.o
*.ko
*.obj
*.elf
# Linker output
*.ilk
*.map
*.exp
# Precompiled Headers
*.gch
*.pch
# Libraries
*.lib
*.a
*.la
*.lo
# Shared objects (inc. Windows DLLs)
*.dll
*.so
*.so.*
*.dylib
# Executables
*.exe
*.out
*.app
*.i*86
*.x86_64
*.hex
dwmblocks
# Debug files
*.dSYM/
*.su
*.idb
*.pdb
# Kernel Module Compile Results
*.mod*
*.cmd
.tmp_versions/
modules.order
Module.symvers
Mkfile.old
dkms.conf

7
LICENSE Normal file
View File

@ -0,0 +1,7 @@
ISC License (ISC)
Copyright 2020 torrinfail
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.
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.

37
Makefile Normal file
View File

@ -0,0 +1,37 @@
PREFIX := /usr/local
CC := cc
CFLAGS := -pedantic -Wall -Wno-deprecated-declarations -Os
LDFLAGS := -lX11
# FreeBSD (uncomment)
#LDFLAGS += -L/usr/local/lib -I/usr/local/include
# # OpenBSD (uncomment)
#LDFLAGS += -L/usr/X11R6/lib -I/usr/X11R6/include
all: options dwmblocks
options:
@echo dwmblocks build options:
@echo "CFLAGS = ${CFLAGS}"
@echo "LDFLAGS = ${LDFLAGS}"
@echo "CC = ${CC}"
dwmblocks: dwmblocks.c blocks.def.h blocks.h
${CC} -o dwmblocks dwmblocks.c ${CFLAGS} ${LDFLAGS}
blocks.h:
cp blocks.def.h $@
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
install -m0755 scripts/* ${DESTDIR}${PREFIX}/bin
uninstall:
rm -f ${DESTDIR}${PREFIX}/bin/dwmblocks
.PHONY: all options clean install uninstall

15
README.md Normal file
View File

@ -0,0 +1,15 @@
# dwmblocks
Modular status bar for dwm written in c.
# usage
To use dwmblocks first run 'make' and then install it with 'sudo make install'.
After that you can put dwmblocks in your xinitrc or other startup script to have it start with dwm.
# modifying blocks
The statusbar is made from text output from commandline programs.
Blocks are added and removed by editing the blocks.h header file.
By default the blocks.h header file is created the first time you run make which copies the default config from blocks.def.h.
This is so you can edit your status bar commands and they will not get overwritten in a future update.
# patches
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.
I do not maintain these but I will take pull requests to update them.
<br>
<a href=https://gist.github.com/IGeraGera/e4a5583b91b3eec2e81fdceb44dea717>dwmblocks-statuscmd-b6b0be4.diff</a>

11
blocks.def.h Normal file
View File

@ -0,0 +1,11 @@
//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*/
{"Mem:", "free -h | awk '/^Mem/ { print $3\"/\"$2 }' | sed s/i//g", 30, 0},
{"", "date '+%b %d (%a) %I:%M%p'", 5, 0},
};
//sets delimeter between status commands. NULL character ('\0') means no delimeter.
static char delim[] = " | ";
static unsigned int delimLen = 5;

229
dwmblocks.c Normal file
View File

@ -0,0 +1,229 @@
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
#include<unistd.h>
#include<signal.h>
#include <time.h>
#ifndef NO_X
#include<X11/Xlib.h>
#endif
#ifdef __OpenBSD__
#define SIGPLUS SIGUSR1+1
#define SIGMINUS SIGUSR1-1
#else
#define SIGPLUS SIGRTMIN
#define SIGMINUS SIGRTMIN
#endif
#define LENGTH(X) (sizeof(X) / sizeof(X[0]))
#define CMDLENGTH 50
#define SDIRLENGTH 256
#define MIN( a, b ) (a < b ? a : b)
#define STATUSLENGTH (LENGTH(blocks) * CMDLENGTH + 1)
typedef struct {
char* icon;
char* command;
unsigned int interval;
unsigned int signal;
} Block;
void getcmd(const Block *block, char *output);
void getcmds(int time);
void getsigcmds(unsigned int signal);
#ifndef __OpenBSD__
void dummysighandler(int signum);
#endif
void sighandler(int signum);
void setupsignals(void);
int getstatus(char *str, char *last);
void pstdout(void);
int gcd(int n1, int n2);
void statusloop(void);
void termhandler(void);
#ifndef NO_X
void setroot(void);
static void (*writestatus) (void) = setroot;
static int setupx(void);
static Display *dpy;
static int screen;
static Window root;
#else
static void (*writestatus) (void) = pstdout;
#endif
#include "blocks.h"
static char statusbar[LENGTH(blocks)][CMDLENGTH] = {0};
static char statusstr[2][STATUSLENGTH];
static int statuscontinue = 1;
//opens process *cmd and stores output in *output
void getcmd(const Block *block, char *output) {
strcpy(output, block->icon);
FILE *cmdf = popen(block->command, "r");
if (!cmdf) {
return;
}
int i = strlen(block->icon);
fgets(output+i, CMDLENGTH-i-delimLen, cmdf);
i = strlen(output);
if (i == 0) {
//return if block and command output are both empty
pclose(cmdf);
return;
}
//only chop off newline if one is present at the end
i = output[i-1] == '\n' ? i-1 : i;
if (delim[0] != '\0') {
strncpy(output+i, delim, delimLen);
} else {
output[i++] = '\0';
}
pclose(cmdf);
}
void getcmds(int time) {
const Block* current;
for (unsigned int i = 0; i < LENGTH(blocks); i++) {
current = blocks + i;
if ((current->interval != 0 && time % current->interval == 0) || time == -1) {
getcmd(current,statusbar[i]);
}
}
}
void getsigcmds(unsigned int signal) {
const Block *current;
for (unsigned int i = 0; i < LENGTH(blocks); i++) {
current = blocks + i;
if (current->signal == signal) {
getcmd(current,statusbar[i]);
}
}
}
#ifndef __OpenBSD__
/* this signal handler should do nothing */
void dummysighandler(int signum) {
return;
}
#endif
void sighandler(int signum) {
getsigcmds(signum-SIGPLUS);
writestatus();
}
void setupsignals() {
#ifndef __OpenBSD__
/* initialize all real time signals with dummy handler */
for (int i = SIGRTMIN; i <= SIGRTMAX; i++) {
signal(i, dummysighandler);
}
#endif
for (unsigned int i = 0; i < LENGTH(blocks); i++) {
if (blocks[i].signal > 0) {
signal(SIGMINUS+blocks[i].signal, sighandler);
}
}
}
int getstatus(char *str, char *last) {
strcpy(last, str);
str[0] = '\0';
for (unsigned int i = 0; i < LENGTH(blocks); i++) {
strcat(str, statusbar[i]);
}
str[strlen(str)-strlen(delim)] = '\0';
return strcmp(str, last); //0 if they are the same
}
void pstdout() {
if (!getstatus(statusstr[0], statusstr[1])) { //Only write out if text has changed.
return;
}
printf("%s\n",statusstr[0]);
fflush(stdout);
}
int gcd(int n1, int n2) {
int temp;
while (n2 > 0){
temp = n1 % n2;
n1 = n2;
n2 = temp;
}
return n1;
}
void statusloop() {
setupsignals();
unsigned int interval = -1;
for (int i = 0; i < LENGTH(blocks); i++){
if (blocks[i].interval){
interval = gcd(blocks[i].interval, interval);
}
}
int i = 0;
getcmds(-1);
const struct timespec sleeptime = { 0, interval * 1000000 };
struct timespec tosleep = sleeptime;
while (statuscontinue) {
if (nanosleep(&tosleep, &tosleep) < 0) {
continue;
}
getcmds((i++) * interval);
writestatus();
tosleep = sleeptime;
}
}
void termhandler() {
statuscontinue = 0;
}
#ifndef NO_X
void setroot() {
if (!getstatus(statusstr[0], statusstr[1])) { //Only set root if text has changed.
return;
}
XStoreName(dpy, root, statusstr[0]);
XFlush(dpy);
}
int setupx() {
dpy = XOpenDisplay(NULL);
if (!dpy) {
fprintf(stderr, "dwmblocks: Failed to open display\n");
return 0;
}
screen = DefaultScreen(dpy);
root = RootWindow(dpy, screen);
return 1;
}
#endif
int main(int argc, char** argv) {
for (int i = 0; i < argc; ++i) { //Handle command line arguments
if (strcmp("-d", argv[i]) == 0) {
strncpy(delim, argv[++i], delimLen);
} else if (strcmp("-p", argv[i]) == 0) {
writestatus = pstdout;
}
}
#ifndef NO_X
if (!setupx()) {
return 1;
}
#endif
delimLen = MIN(delimLen, strlen(delim));
delim[delimLen++] = '\0';
signal(SIGTERM, (void(*)(int))termhandler);
signal(SIGINT, (void(*)(int))termhandler);
statusloop();
#ifndef NO_X
XCloseDisplay(dpy);
#endif
return 0;
}

53
scripts/dwmblocks-battery Executable file
View File

@ -0,0 +1,53 @@
#!/usr/bin/env zsh
if [[ "$(uname)" = 'Linux' ]]; then
let charge_full="$(cat '/sys/class/power_supply/BAT0/charge_full')."
function get_battery_percent {
let charge_now="$(cat '/sys/class/power_supply/BAT0/charge_now')."
printf '%.0f' "$((charge_now / charge_full * 100))"
}
function is_adapted_connected {
let connected="$(cat /sys/class/power_supply/ADP1/online)"
if ((${connected} == 1)); then
echo 'true'
else
echo 'false'
fi
}
function get_battery_icon {
let charge_percent="${1}"
if "$(is_adapted_connected)"; then
echo -n ''
elif ((${charge_percent} <= 10)); then
echo -n ''
elif ((${charge_percent} <= 20)); then
echo -n ''
elif ((${charge_percent} <= 30)); then
echo -n ''
elif ((${charge_percent} <= 40)); then
echo -n ''
elif ((${charge_percent} <= 50)); then
echo -n ''
elif ((${charge_percent} <= 60)); then
echo -n ''
elif ((${charge_percent} <= 70)); then
echo -n ''
elif ((${charge_percent} <= 80)); then
echo -n ''
elif ((${charge_percent} < 100)); then
echo -n ''
else
echo -n ''
fi
}
let cp="$(get_battery_percent)"
get_battery_icon "${cp}"
printf '%3d%%\n' "${cp}"
# Linux ends here
else
echo "${0}: error: unknown os: \"$(uname)\"" >&2
exit 1
fi

14
scripts/dwmblocks-network Executable file
View File

@ -0,0 +1,14 @@
#!/usr/bin/env zsh
if [[ "$(uname)" = 'Linux' ]]; then
local active_networks="$(nmcli c s --active)"
local output=''
[[ "${active_networks}" = *' wifi '* ]] && output="${output}直 "
[[ "${active_networks}" = *' wireguard '* ]] && output="${output}嬨 "
(( ${#output} == 0 )) && output=''
bluetoothctl show | grep 'Powered: yes' >/dev/null && output="${output} "
printf '%s\n' "${output}"
else
echo "${0}: error: unknown os: \"$(uname)\"" >&2
exit 1
fi

14
scripts/dwmblocks-volume Executable file
View File

@ -0,0 +1,14 @@
#!/usr/bin/env zsh
let volume="$(pamixer --get-volume)"
local icon
if [[ "$(pamixer --get-mute)" = "true" ]]; then
icon='ﱝ'
elif ((${volume} > 50)); then
icon='墳'
elif ((${volume} > 0)); then
icon='奔'
else
icon='奄'
fi
printf '%s%3d%%\n' "${icon}" "${volume}"