nyxwmblocks.c (3809B)
1 // nyxwmblocks.c 2 #include <stdlib.h> 3 #include <stdio.h> 4 #include <string.h> 5 #include <unistd.h> 6 #include <signal.h> 7 #include <X11/Xlib.h> 8 #include <X11/Xft/Xft.h> 9 #include "nyxwm.h" 10 #include "nyxwmblocks.h" 11 #include "blocks.h" 12 13 #define LENGTH(X) (sizeof(X) / sizeof (X[0])) 14 #define CMDLENGTH 100 15 #define MIN(a, b) ((a < b) ? a : b) 16 #define STATUSLENGTH (LENGTH(blocks) * CMDLENGTH + 1) 17 18 void getcmd(const Block *block, char *output); 19 void getsigcmds(unsigned int signal); 20 void getstatus(char *str); 21 void setupsignals(void); 22 void update_status(void); 23 void statusloop(void); 24 void termhandler(int signum); 25 void pstdout(void); 26 void sighandler(int signum); 27 28 static char statusbar[LENGTH(blocks)][CMDLENGTH] = {0}; 29 static char statusstr[STATUSLENGTH]; 30 static int statusContinue = 1; 31 32 extern Display *d; 33 extern Window root; 34 extern Window bar; 35 extern XftDraw *xft_draw; 36 extern XftColor xft_color; 37 extern XftFont *xft_font; 38 39 void getcmd(const Block *block, char *output) { 40 char tempstatus[CMDLENGTH] = {0}; 41 strcpy(tempstatus, block->icon); 42 FILE *cmdf = popen(block->command, "r"); 43 if (!cmdf) 44 return; 45 int i = strlen(block->icon); 46 if (fgets(tempstatus + i, CMDLENGTH - i, cmdf) != NULL) { 47 i = strlen(tempstatus); 48 if (i > 0 && tempstatus[i-1] == '\n') { 49 tempstatus[--i] = '\0'; 50 } 51 if (delim[0] != '\0' && i + delimLen < CMDLENGTH) { 52 strncpy(tempstatus + i, delim, CMDLENGTH - i - 1); 53 tempstatus[CMDLENGTH - 1] = '\0'; 54 } 55 } 56 strcpy(output, tempstatus); 57 pclose(cmdf); 58 } 59 60 void getcmds(int time) 61 { 62 const Block* current; 63 for (unsigned int i = 0; i < LENGTH(blocks); i++) { 64 current = blocks + i; 65 if ((current->interval != 0 && time % current->interval == 0) || time == -1) 66 getcmd(current, statusbar[i]); 67 } 68 } 69 70 void getsigcmds(unsigned int signal) 71 { 72 const Block *current; 73 for (unsigned int i = 0; i < LENGTH(blocks); i++) { 74 current = blocks + i; 75 if (current->signal == signal) 76 getcmd(current, statusbar[i]); 77 } 78 } 79 80 void setupsignals() { 81 for (unsigned int i = 0; i < LENGTH(blocks); i++) { 82 if (blocks[i].signal > 0) 83 signal(SIGRTMIN+blocks[i].signal, sighandler); 84 } 85 } 86 87 void getstatus(char *str) 88 { 89 str[0] = '\0'; 90 for (unsigned int i = 0; i < LENGTH(blocks); i++) 91 strcat(str, statusbar[i]); 92 str[strlen(str)-strlen(delim)] = '\0'; 93 } 94 95 void update_status() { 96 if (!d || !bar || !xft_draw || !xft_font) 97 return; 98 99 getstatus(statusstr); 100 101 XClearWindow(d, bar); 102 103 int bar_width = DisplayWidth(d, DefaultScreen(d)); 104 XGlyphInfo extents; 105 XftTextExtentsUtf8(d, xft_font, (XftChar8*)statusstr, strlen(statusstr), &extents); 106 107 int x = (bar_width - extents.width) / 2; 108 int y = BAR_HEIGHT / 2 + xft_font->ascent / 2; 109 110 // Ensure x is not negative and has a minimum padding 111 x = (x < 10) ? 10 : x; 112 113 XftDrawStringUtf8(xft_draw, &xft_color, xft_font, x, y, (XftChar8*)statusstr, strlen(statusstr)); 114 XFlush(d); 115 } 116 117 void statusloop() 118 { 119 setupsignals(); 120 int i = 0; 121 getcmds(-1); 122 while (statusContinue) { 123 getcmds(i++); 124 update_status(); 125 sleep(1.0); 126 } 127 } 128 129 void sighandler(int signum) 130 { 131 getsigcmds(signum-SIGRTMIN); 132 update_status(); 133 } 134 135 void termhandler(int signum) { 136 statusContinue = 0; 137 (void)signum; // To avoid unused parameter warning 138 } 139 140 void pstdout() 141 { 142 getstatus(statusstr); 143 printf("%s\n", statusstr); 144 fflush(stdout); 145 } 146 147 // This function should be called from nyxwm's main loop 148 void run_nyxwmblocks(char *status, size_t size) { 149 static int time = 0; 150 151 getcmds(time); 152 getstatus(status); 153 154 time++; 155 if (time == 60) time = 0; // Reset every minute to avoid potential overflow 156 }