nyxwm

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

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 }