Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.unix.programmer > #17204
| Path | csiph.com!eternal-september.org!feeder.eternal-september.org!nntp.eternal-september.org!.POSTED!not-for-mail |
|---|---|
| From | Anton Antimo <anton@safunu.org> |
| Newsgroups | comp.unix.programmer, comp.windows.x, comp.lang.c |
| Subject | a battery monitor |
| Followup-To | comp.windows.x |
| Date | Tue, 01 Sep 2026 14:28:40 -0300 |
| Organization | A noiseless patient Spider |
| Lines | 233 |
| Message-ID | <87v78oop87.fsf@safunu.org> (permalink) |
| MIME-Version | 1.0 |
| Content-Type | text/plain |
| Injection-Date | Tue, 01 Sep 2026 19:00:10 +0000 (UTC) |
| Injection-Info | dont-email.me; logging-data="2214531"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX19/c8LIk3pdFcxmU9HlSTvx3H/5dR1Yd6Q="; posting-host="096bfd470eba0b3a7539610fba0ea137" |
| Cancel-Lock | sha1:MwsXo+KLxMX4TJxUZxVGSQeJdm0= sha1:wz0ez5RSgP7xo6OTQgrQIcNZ6sM= sha256:JeBSxUFwk/dhqSA9sTTSCN46Ng1XVQW11kAHejZ2k4g= sha1:LyaKokaI7vGv+bwQ4yoOIAqL0FA= sha256:ou06T9EiZTBfAZbY1sRG/dt3kbf1c2Xk3Pti2mU5KTg= |
| Xref | csiph.com comp.unix.programmer:17204 comp.windows.x:623 comp.lang.c:401581 |
Cross-posted to 3 groups.
Followups directed to: comp.windows.x
Show key headers only | View raw
I wrote a battery monitor. The program watches its stdin for lines
containing numbers that tell what is the current percentage of the
battery. You can see a picture of it on the lower right of the image at
https://archive.org/details/x11-battery-monitor
If you compile it, then how you can see a demonstration of it running
(using bash):
for i in $(seq 100 -5 0); do echo $i && sleep 0.5 ; done | ./xbattery
So, yes, the program is more like a progress bar to be used by some kind
of shell program. Here's how I've been using it. My system has this
program called acpi, which gives me battery information:
%acpi -b
Battery 0: Charging, 91%, 00:18:43 until charged
I run CWM, the calm window manager. So from my ~/xinitrc, I run:
while true; \
do acpi -b | awk '{printf("%d\n",$4)}' | tr -d '%,' && sleep 60; \
done | xbattery 220x40-0-0 &
So, yes, xbattery.c (source code below) is able to read the desired
window geometry from the command line (as it's typical of X programs).
Be kind with criticism---that's my first one.
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/keysym.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/select.h>
#include <errno.h>
void draw(Display *d, Window w, GC gc, int p,
unsigned int width, unsigned int height,
unsigned long green, unsigned long red) {
XClearWindow(d, w);
if (p < 0) p = 0;
if (p > 100) p = 100;
int howmuch;
if (p >= 100)
howmuch = width;
else
howmuch = (width * p) / 100;
if (howmuch > 0) {
if (p <= 10) XSetForeground(d, gc, red); else XSetForeground(d, gc, green);
XFillRectangle(d, w, gc, 0, 0, howmuch, width);
}
}
int main(int argc, char *argv[]) {
Display *d = NULL; Window w = 0; GC gc = NULL;
XClassHint *ch = NULL; XSizeHints *hs = NULL; int exit_code = 0;
d = XOpenDisplay(NULL);
if (!d) {
fprintf(stderr, "cannot open X display\n");
return 1;
}
int s = DefaultScreen(d);
/* Variables x, y store the position of the window on the screen.
Variables width and height store the size of the window.
Variable g stores the bitmask produced by XParseGeometry. */
int x = 10, y = 10; unsigned int width = 300, height = 50; int g = 0;
if (argc > 1) {
g = XParseGeometry(argv[1], &x, &y, &width, &height);
if ((g & XValue) && (g & XNegative)) {
x = DisplayWidth(d, s) - width - abs(x);
}
if ((g & YValue) && (g & YNegative)) {
y = DisplayHeight(d, s) - height - abs(y);
}
}
/* We've decided to use no border. But if you were to specify a
border tomorrow, it would be black. */
w = XCreateSimpleWindow(d, RootWindow(d, s), x, y, width, height, 0,
BlackPixel(d, s), WhitePixel(d, s));
if (!w) {
fprintf(stderr, "cannot create window\n");
exit_code = 1;
goto cleanup;
}
/* The name of the window. That's relevant to CWM, for example, so
that it can ignore the window and let it stand an applet. */
XStoreName(d, w, "xbattery");
ch = XAllocClassHint();
if (!ch) {
fprintf(stderr, "no memory for XClassHint\n");
exit_code = 1;
goto cleanup;
}
ch->res_name = "xbattery";
ch->res_class = "XBattery";
XSetClassHint(d, w, ch);
XFree(ch);
ch = NULL;
/* Here we annotate information to be read by the system's window
manager. It says for example what position we wish the window
to have. */
hs = XAllocSizeHints();
if (!hs) {
fprintf(stderr, "no memory for XSizeHints\n");
exit_code = 1;
goto cleanup;
}
if (g & XValue) hs->flags |= USPosition;
if (g & YValue) hs->flags |= USPosition;
if ((g & WidthValue) || (g & HeightValue)) hs->flags |= USSize;
hs->x = x;
hs->y = y;
hs->width = width;
hs->height = height;
XSetWMNormalHints(d, w, hs);
XFree(hs);
hs = NULL;
/* Here we set the events we are interested in getting. */
XSelectInput(d, w, ExposureMask | KeyPressMask | StructureNotifyMask);
/* This tells X to actually paint the window on screen for the first time. */
XMapWindow(d, w);
/* The graphics context is memory the X server keeps for knowing
how to draw elements on windows such as the size of the pen, the
color of paint and so on. */
gc = XCreateGC(d, w, 0, NULL);
if (!gc) {
fprintf(stderr, "no memory for XCreateGC\n");
exit_code = 1;
goto cleanup;
}
/* The use of a color map here exposes a bit of the design of X. */
Colormap cmap = DefaultColormap(d, s);
XColor screen_col, exact_col;
unsigned long green, red;
if (XAllocNamedColor(d, cmap, "green", &screen_col, &exact_col))
green = screen_col.pixel;
else
green = BlackPixel(d, s);
if (XAllocNamedColor(d, cmap, "red", &screen_col, &exact_col))
red = screen_col.pixel;
else
red = BlackPixel(d, s);
int x11_fd = ConnectionNumber(d);
int percentage = 90;
draw(d, w, gc, percentage, width, height, green, red); XFlush(d);
for (;;) {
fd_set in_fds; FD_ZERO(&in_fds);
FD_SET(STDIN_FILENO, &in_fds); FD_SET(x11_fd, &in_fds);
int max_fd = (STDIN_FILENO > x11_fd) ? STDIN_FILENO : x11_fd;
if (select(max_fd + 1, &in_fds, NULL, NULL, NULL) < 0) {
perror("select: "); exit_code = 1; goto cleanup;
}
if (FD_ISSET(STDIN_FILENO, &in_fds)) {
char buf[16]; int val;
if (fgets(buf, sizeof buf, stdin) != NULL) {
char *endptr; errno = 0;
unsigned long ulval = strtoul(buf, &endptr, 10);
if (endptr == buf || errno == ERANGE || ulval > 100) {
fprintf(stderr, "Oops; invalid input or out of range (0--100); trying again...\n");
continue;
}
val = (int) ulval;
percentage = val;
fprintf(stderr, "Read a line with number %d.\n", val);
draw(d, w, gc, percentage, width, height, green, red);
XFlush(d);
} else {
fprintf(stderr, "EOF; exiting gracefully...\n");
exit_code = 0;
goto cleanup;
}
}
if (FD_ISSET(x11_fd, &in_fds)) {
/* X is notifying us of something. We keep on extracting events
with XNextEvent while XPending says there's more. */
while (XPending(d)) {
XEvent e;
XNextEvent(d, &e);
if (e.type == ConfigureNotify) {
width = e.xconfigure.width;
height = e.xconfigure.height;
}
if (e.type == Expose || e.type == ConfigureNotify) {
draw(d, w, gc, percentage, width, height, green, red);
}
if (e.type == KeyPress) {
KeySym keysym = XLookupKeysym(&e.xkey, 0);
if (keysym == 'q') {
fprintf(stderr, "Quitting...\n");
goto cleanup;
}
}
}
}
}
cleanup:
if (hs) XFree(hs);
if (ch) XFree(ch);
if (gc) XFreeGC(d, gc);
if (w) XDestroyWindow(d, w);
if (d) XCloseDisplay(d);
return exit_code;
}
Followup-To: comp.windows.x
Back to comp.unix.programmer | Previous | Next — Next in thread | Find similar | Unroll thread
a battery monitor Anton Antimo <anton@safunu.org> - 2026-09-01 14:28 -0300
Re: a battery monitor Lawrence D’Oliveiro <ldo@nz.invalid> - 2026-09-02 21:45 +0000
Re: a battery monitor Johann 'Myrkraverk' Oskarsson <johann@myrkraverk.invalid> - 2026-09-03 12:34 +0800
Re: a battery monitor Lawrence D’Oliveiro <ldo@nz.invalid> - 2026-09-03 21:24 +0000
Re: a battery monitor Eli the Bearded <*@eli.users.panix.com> - 2026-09-04 02:51 +0000
Re: a battery monitor David Brown <david.brown@hesbynett.no> - 2026-09-03 09:28 +0200
Re: a battery monitor boltar@caprica.universe - 2026-09-03 15:55 +0000
Re: a battery monitor David Brown <david.brown@hesbynett.no> - 2026-09-04 09:07 +0200
Re: a battery monitor Johann 'Myrkraverk' Oskarsson <johann@myrkraverk.invalid> - 2026-09-04 15:14 +0800
Re: a battery monitor Lane W <cactus_DAC@yahoo.com> - 2026-09-04 05:32 -0600
Re: a battery monitor scott@slp53.sl.home (Scott Lurndal) - 2026-09-04 14:29 +0000
Re: a battery monitor Johann 'Myrkraverk' Oskarsson <johann@myrkraverk.invalid> - 2026-09-04 23:17 +0800
Re: a battery monitor gazelle@shell.xmission.com (Kenny McCormack) - 2026-09-04 12:05 +0000
csiph-web