From dda82b48a321db0f2240d88420992bcfef11844f Mon Sep 17 00:00:00 2001 From: Sasha Koshka Date: Fri, 10 Nov 2023 17:36:45 -0500 Subject: [PATCH] Battery monitor shows percentage on icon --- xmbattery/src/main.c | 107 ++++++++++++++++++++++++++----------------- 1 file changed, 64 insertions(+), 43 deletions(-) diff --git a/xmbattery/src/main.c b/xmbattery/src/main.c index ad474a0..8bde106 100644 --- a/xmbattery/src/main.c +++ b/xmbattery/src/main.c @@ -1,17 +1,20 @@ -/* C99 */ - #define _XOPEN_SOURCE #include +#include #include #include #include #include #include #include + #include +#include + #include #include #include +#include #include "icons/level0.xbm" #include "icons/level1.xbm" @@ -39,34 +42,39 @@ typedef struct { } BatteryInfo; BatteryInfo getBatteryInfo (void); -Pixmap selectBatteryIcon (BatteryInfo); -void loadAllPixmaps (Widget); +Pixmap selectBatteryIcon (BatteryInfo, Pixmap[8]); +void loadAllPixmaps (Widget, Pixmap[8]); void batteryPoll (XtPointer, XtIntervalId *); void resetBatteryPollTimeout(void); void batteryInfoDialog (Widget, XtPointer, XtPointer); -Pixmap levels[8] = { 0 }; +Pixmap levels[8] = { 0 }; +Pixmap iconLevels[8] = { 0 }; XtAppContext application; Widget icon; Widget text; Widget layout; -Widget window; +Widget topLevel; int main (int argc, char *argv[]) { - window = XtVaAppInitialize ( + topLevel = XtVaAppInitialize ( &application, "Battery", NULL, 0, &argc, argv, NULL, XmNtitle, "Battery", + XmNiconName, "Battery", + NULL); + Widget window = XtVaCreateManagedWidget ( + "window", xmMainWindowWidgetClass, topLevel, NULL); - layout = XtVaCreateWidget ( "layout", xmRowColumnWidgetClass, window, XmNorientation, XmHORIZONTAL, NULL); - loadAllPixmaps(layout); + loadAllPixmaps(topLevel, iconLevels); + loadAllPixmaps(layout, levels); icon = XtVaCreateManagedWidget ( "batteryIcon", xmPushButtonWidgetClass, layout, XmNleftAttachment, XmATTACH_FORM, @@ -87,7 +95,7 @@ int main (int argc, char *argv[]) { batteryPoll(NULL, NULL); XtManageChild(layout); - XtRealizeWidget(window); + XtRealizeWidget(topLevel); XtAppMainLoop(application); } @@ -96,7 +104,11 @@ BatteryInfo getBatteryInfo (void) { char charging[16] = { 0 }; int battery; - FILE *stream = popen("acpi -b", "r"); + pid_t child; + FILE *stream = XmdVaPipedExecPath ( + "acpi", &child, "r", + "acpi", "-b", + NULL); if (stream == NULL) { result.state = BatteryStateError; return result; @@ -113,13 +125,14 @@ BatteryInfo getBatteryInfo (void) { case 'F': result.state = BatteryStateFull; break; default: result.state = BatteryStateError; break; } - if (pclose(stream) != 0) { + if (fclose(stream) != 0) { result.state = BatteryStateError; } + waitpid(child, NULL, 0); return result; } -Pixmap selectBatteryIcon (BatteryInfo info) { +Pixmap selectBatteryIcon (BatteryInfo info, Pixmap levels[8]) { if (info.state == BatteryStateCharging) { return levels[5]; } else if (info.state == BatteryStateNotCharging) { @@ -139,15 +152,15 @@ Pixmap selectBatteryIcon (BatteryInfo info) { } } -void loadAllPixmaps (Widget widget) { - levels[0] = XmdLoadBitmapIcon(widget, level0); - levels[1] = XmdLoadBitmapIcon(widget, level1); - levels[2] = XmdLoadBitmapIcon(widget, level2); - levels[3] = XmdLoadBitmapIcon(widget, level3); - levels[4] = XmdLoadBitmapIcon(widget, level4); - levels[5] = XmdLoadBitmapIcon(widget, charging); - levels[6] = XmdLoadBitmapIcon(widget, error); - levels[7] = XmdLoadBitmapIcon(widget, not); +void loadAllPixmaps (Widget widget, Pixmap destination[8]) { + destination[0] = XmdLoadBitmapIcon(widget, level0); + destination[1] = XmdLoadBitmapIcon(widget, level1); + destination[2] = XmdLoadBitmapIcon(widget, level2); + destination[3] = XmdLoadBitmapIcon(widget, level3); + destination[4] = XmdLoadBitmapIcon(widget, level4); + destination[5] = XmdLoadBitmapIcon(widget, charging); + destination[6] = XmdLoadBitmapIcon(widget, error); + destination[7] = XmdLoadBitmapIcon(widget, not); } void batteryPoll (XtPointer clientData, XtIntervalId *timer) { @@ -158,17 +171,15 @@ void batteryPoll (XtPointer clientData, XtIntervalId *timer) { XtVaSetValues ( icon, XmNlabelType, XmPIXMAP, - XmNlabelPixmap, selectBatteryIcon(info), + XmNlabelPixmap, selectBatteryIcon(info, levels), NULL); XtVaSetValues ( - window, - XmNiconPixmap, selectBatteryIcon(info), + topLevel, + XmNiconPixmap, selectBatteryIcon(info, iconLevels), NULL); - #define BUFFER_LEN 32 - char buffer[BUFFER_LEN]; - snprintf(buffer, BUFFER_LEN, "%d%%", info.level); - #undef BUFFER_LEN + char buffer[32]; + snprintf(buffer, XtNumber(buffer), "%d%%", info.level); /* if we don't unmanage and then re-manage the child, the text flies to * the top which is rather annoying. this little quirk bent me over and @@ -182,6 +193,11 @@ void batteryPoll (XtPointer clientData, XtIntervalId *timer) { XmStringFree(string); XtManageChild(text); + XtVaSetValues ( + topLevel, + XmNiconName, buffer, + NULL); + resetBatteryPollTimeout(); } @@ -195,35 +211,40 @@ void batteryInfoDialog (Widget button, XtPointer clientData, XtPointer callData) BatteryInfo info = getBatteryInfo(); - static const char *states[] = { + static const String states[] = { "Charging", + "Not charging", "Full", "Discharging", "Error" }; - #define BUFFER_LEN 48 - char timeBuffer[BUFFER_LEN] = { 0 }; + String messageBuffer = NULL; switch (info.state) { case BatteryStateCharging: - snprintf ( - timeBuffer, BUFFER_LEN, "\n%d:%02d:%02d until charged.", + XtAsprintf ( + &messageBuffer, + "%d%%, %s\n" + "%d:%02d:%02d until charged.", + info.level, states[info.state], info.hours, info.minutes, info.seconds); break; case BatteryStateDischarging: - snprintf ( - timeBuffer, BUFFER_LEN, "\n%d:%02d:%02d until empty.", + XtAsprintf ( + &messageBuffer, + "%d%%, %s\n" + "%d:%02d:%02d until empty.", + info.level, states[info.state], info.hours, info.minutes, info.seconds); break; + default: + XtAsprintf ( + &messageBuffer, + "%d%%, %s", + info.level, states[info.state]); + break; } - #undef BUFFER_LEN - #define BUFFER_LEN 128 - char messageBuffer[BUFFER_LEN]; - snprintf ( - messageBuffer, BUFFER_LEN, "%d%%, %s%s", - info.level, states[info.state], timeBuffer); - #undef BUFFER_LEN Arg args[5] = { 0 }; int n = 0;