From 5465c43cff4f0f09a499fab9da469153df4b2fdd Mon Sep 17 00:00:00 2001 From: Utkarsh Verma Date: Tue, 13 Apr 2021 11:05:21 +0530 Subject: [PATCH] Improve sleep mechanism. --- config.h | 4 +- main.c | 166 +++++++++++++++++++++++++++++-------------------------- 2 files changed, 90 insertions(+), 80 deletions(-) diff --git a/config.h b/config.h index 58e51e3..80ba080 100644 --- a/config.h +++ b/config.h @@ -1,5 +1,5 @@ #define CMDLENGTH 50 -#define delimiter " " +#define delimiter "  " static const Block blocks[] = { {"sb-mail", 1800, 1}, @@ -9,6 +9,6 @@ static const Block blocks[] = { {"sb-loadavg", 10, 9}, {"sb-volume", 0, 5}, {"sb-battery", 5, 6}, - {"sb-date", 60, 7}, + {"sb-date", 20, 7}, {"sb-network", 5, 8}, }; diff --git a/main.c b/main.c index 3b57cf7..a3449f0 100644 --- a/main.c +++ b/main.c @@ -15,19 +15,8 @@ typedef struct { } Block; #include "config.h" -void getCommand(const Block *, char *); -void getCommands(int); -int getStatus(char *, char *); -void setRoot(); void debug(); -void statusLoop(); -void termHandler(int); -void signalHandler(int num); -void buttonHandler(int sig, siginfo_t *si, void *ucontext); -void getSignalCommands(int signal); -void setupSignals(); -void signalHandler(int signum); -void sleepMillis(unsigned long); +void setRoot(); static Display *dpy; static int screen; @@ -37,48 +26,22 @@ static char statusbar[len(blocks)][CMDLENGTH]; static char statusStr[2][len(blocks) * CMDLENGTH + (len(delimiter) - 1) * (len(blocks) - 1) + 1]; static int statusContinue = 1; -static void (*writestatus)() = setRoot; +static void (*writeStatus)() = setRoot; + +int gcd(int a, int b) { + int temp; + while (b > 0) { + temp = a % b; + a = b; + b = temp; + } + return a; +} void replace(char *str, char old, char new) { - int i = 0; - while (str[i] != '\0') { - if (str[i] == old) { - str[i] = new; - return; - } - i++; - } -} - -void getSignalCommands(int signal) { - const Block *current; - for (int i = 0; i < len(blocks); i++) { - current = blocks + i; - if (current->signal == signal) - getCommand(current, statusbar[i]); - } -} - -void setupSignals() { - struct sigaction sa; - - // Handle block update signals - for (int i = 0; i < len(blocks); i++) { - if (blocks[i].signal > 0) { - signal(SIGRTMIN + blocks[i].signal, signalHandler); - sigaddset(&sa.sa_mask, SIGRTMIN + blocks[i].signal); - } - } - - // Handle mouse events - 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); + for (char *ch = str; *ch; ch++) + if (*ch == old) + *ch = new; } // Open process *command and store output in *output @@ -113,9 +76,19 @@ void getCommands(int time) { } } +void getSignalCommands(int signal) { + const Block *current; + for (int i = 0; i < len(blocks); i++) { + current = blocks + i; + if (current->signal == signal) + getCommand(current, statusbar[i]); + } +} + int getStatus(char *new, char *old) { strcpy(old, new); new[0] = '\0'; + strcat(new, delimiter); for (int i = 0; i < len(blocks); i++) { strcat(new, statusbar[i]); if (strlen(statusbar[i]) > (blocks[i].signal != 0) && @@ -126,6 +99,14 @@ int getStatus(char *new, char *old) { return strcmp(new, old); } +void debug() { + // Only write out if text has changed + if (!getStatus(statusStr[0], statusStr[1])) return; + + write(STDOUT_FILENO, statusStr[0], strlen(statusStr[0])); + write(STDOUT_FILENO, "\n", 1); +} + void setRoot() { // Only set root if text has changed if (!getStatus(statusStr[0], statusStr[1])) return; @@ -138,31 +119,6 @@ void setRoot() { XCloseDisplay(dpy); } -void debug() { - // Only write out if text has changed - if (!getStatus(statusStr[0], statusStr[1])) return; - - write(STDOUT_FILENO, statusStr[0], strlen(statusStr[0])); - write(STDOUT_FILENO, "\n", 1); -} - -void statusLoop() { - setupSignals(); - unsigned long int i = 0; - getCommands(-1); - while (statusContinue) { - getCommands(i); - writestatus(); - sleep(1.0); - i++; - } -} - -void signalHandler(int signum) { - getSignalCommands(signum - SIGRTMIN); - writestatus(); -} - void buttonHandler(int sig, siginfo_t *si, void *ucontext) { char button[2] = {'0' + si->si_value.sival_int & 0xff, '\0'}; sig = si->si_value.sival_int >> 8; @@ -187,11 +143,65 @@ void buttonHandler(int sig, siginfo_t *si, void *ucontext) { } } +void signalHandler(int signum) { + getSignalCommands(signum - SIGRTMIN); + writeStatus(); +} + void termHandler(int sigNum) { statusContinue = 0; exit(0); } +void setupSignals() { + struct sigaction sa; + + // Handle block update signals + for (int i = 0; i < len(blocks); i++) { + if (blocks[i].signal > 0) { + signal(SIGRTMIN + blocks[i].signal, signalHandler); + sigaddset(&sa.sa_mask, SIGRTMIN + blocks[i].signal); + } + } + + // Handle mouse events + 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); +} + +void statusLoop() { + setupSignals(); + + unsigned int sleepInterval = -1; + for (int i = 0; i < len(blocks); i++) + if (blocks[i].interval) + sleepInterval = gcd(blocks[i].interval, sleepInterval); + + unsigned int i = 0; + struct timespec sleepTime = {sleepInterval, 0}; + struct timespec toSleep = sleepTime; + getCommands(-1); + + while (statusContinue) { + // Sleep for `sleepTime` even on being interrupted + if (nanosleep(&toSleep, &toSleep) == -1) continue; + + // Write to status after sleeping + getCommands(i); + writeStatus(); + + // After sleep, reset timer and update counter + toSleep = sleepTime; + i += sleepInterval; + } +} + int main(int argc, char **argv) { const int processID = getpid(); for (int i = 0; i < len(blocks); i++) @@ -199,7 +209,7 @@ int main(int argc, char **argv) { SIGRTMIN + blocks[i].signal, processID); for (int i = 0; i < argc; i++) - if (!strcmp("-d", argv[i])) writestatus = debug; + if (!strcmp("-d", argv[i])) writeStatus = debug; signal(SIGTERM, termHandler); signal(SIGINT, termHandler);