nyxwm
Owner: IIIlllIIIllI URL: git@github.com:nyangkosense/nyxwm.git
nyxwmblocks.c
// nyxwmblocks.c
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <X11/Xlib.h>
#include <X11/Xft/Xft.h>
#include "nyxwm.h"
#include "nyxwmblocks.h"
#include "blocks.h"
#define LENGTH(X) (sizeof(X) / sizeof (X[0]))
#define CMDLENGTH 100
#define MIN(a, b) ((a < b) ? a : b)
#define STATUSLENGTH (LENGTH(blocks) * CMDLENGTH + 1)
void getcmd(const Block *block, char *output);
void getsigcmds(unsigned int signal);
void getstatus(char *str);
void setupsignals(void);
void update_status(void);
void statusloop(void);
void termhandler(int signum);
void pstdout(void);
void sighandler(int signum);
static char statusbar[LENGTH(blocks)][CMDLENGTH] = {0};
static char statusstr[STATUSLENGTH];
static int statusContinue = 1;
extern Display *d;
extern Window root;
extern Window bar;
extern XftDraw *xft_draw;
extern XftColor xft_color;
extern XftFont *xft_font;
void getcmd(const Block *block, char *output) {
char tempstatus[CMDLENGTH] = {0};
strcpy(tempstatus, block->icon);
FILE *cmdf = popen(block->command, "r");
if (!cmdf)
return;
int i = strlen(block->icon);
if (fgets(tempstatus + i, CMDLENGTH - i, cmdf) != NULL) {
i = strlen(tempstatus);
if (i > 0 && tempstatus[i-1] == '\n') {
tempstatus[--i] = '\0';
}
if (delim[0] != '\0' && i + delimLen < CMDLENGTH) {
strncpy(tempstatus + i, delim, CMDLENGTH - i - 1);
tempstatus[CMDLENGTH - 1] = '\0';
}
}
strcpy(output, tempstatus);
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]);
}
}
void setupsignals() {
for (unsigned int i = 0; i < LENGTH(blocks); i++) {
if (blocks[i].signal > 0)
signal(SIGRTMIN+blocks[i].signal, sighandler);
}
}
void getstatus(char *str)
{
str[0] = '\0';
for (unsigned int i = 0; i < LENGTH(blocks); i++)
strcat(str, statusbar[i]);
str[strlen(str)-strlen(delim)] = '\0';
}
void update_status() {
if (!d || !bar || !xft_draw || !xft_font)
return;
getstatus(statusstr);
XClearWindow(d, bar);
int bar_width = DisplayWidth(d, DefaultScreen(d));
XGlyphInfo extents;
XftTextExtentsUtf8(d, xft_font, (XftChar8*)statusstr, strlen(statusstr), &extents);
int x = (bar_width - extents.width) / 2;
int y = BAR_HEIGHT / 2 + xft_font->ascent / 2;
// Ensure x is not negative and has a minimum padding
x = (x < 10) ? 10 : x;
XftDrawStringUtf8(xft_draw, &xft_color, xft_font, x, y, (XftChar8*)statusstr, strlen(statusstr));
XFlush(d);
}
void statusloop()
{
setupsignals();
int i = 0;
getcmds(-1);
while (statusContinue) {
getcmds(i++);
update_status();
sleep(1.0);
}
}
void sighandler(int signum)
{
getsigcmds(signum-SIGRTMIN);
update_status();
}
void termhandler(int signum) {
statusContinue = 0;
(void)signum; // To avoid unused parameter warning
}
void pstdout()
{
getstatus(statusstr);
printf("%s\n", statusstr);
fflush(stdout);
}
// This function should be called from nyxwm's main loop
void run_nyxwmblocks(char *status, size_t size) {
static int time = 0;
getcmds(time);
getstatus(status);
time++;
if (time == 60) time = 0; // Reset every minute to avoid potential overflow
}