/* * This is a simple X11 program that displays the battery percentage * on NetBSD. * * It should be compiled with the following flags: * * CFLAGS = -I/usr/X11R7/include -I/usr/pkg/include * LDFLAGS = -lXm -L/usr/X11R7/lib -L/usr/pkg/lib * LDFLAGS += -Wl,-R/usr/X11R7/lib -Wl,-R/usr/pkg/lib * * It requires x11/motif to be installed. * * The program uses the following resources: * * xbattext*fontList = normal font * xbattext*foreground = normal text color * xbattext*alertFontList = font when battery is low * xbattext*alertForeground = text color when battery is low * xbattext*chargeFontList = font when charging * xbattext*chargeForeground = text color when charging * * Set their values in ~/.Xdefaults to customize xbattext. * * xbattext is written by John Ankarstr\xf6m and * is released into the public domain; do whatever you want with it. */ #include #include #include #include #include #include #include /* interval in seconds */ #define INTERVAL 10 /* low battery level */ #define ALERT 30 void update(XtPointer, XtIntervalId *); /* resources */ struct res { XmFontList font_list; XmFontList alert_font_list; XmFontList charge_font_list; Pixel foreground; Pixel alert_foreground; Pixel charge_foreground; } res; static XtResource res_opts[] = { {"fontList", "FontList", XmRFontList, sizeof(XmFontList), XtOffset(struct res*, font_list), XtRImmediate, (caddr_t)NULL}, {"alertFontList", "AlertFontList", XmRFontList, sizeof(XmFontList), XtOffset(struct res*, alert_font_list), XtRImmediate, (caddr_t)NULL}, {"chargeFontList", "ChargeFontList", XmRFontList, sizeof(XmFontList), XtOffset(struct res*, charge_font_list), XtRImmediate, (caddr_t)NULL}, {"foreground", "foreground", XmRPixel, sizeof(Pixel), XtOffset(struct res*, foreground), XtRImmediate, (caddr_t)NULL}, {"alertForeground", "AlertForeground", XmRPixel, sizeof(Pixel), XtOffset(struct res*, alert_foreground), XtRImmediate, (caddr_t)NULL}, {"chargeForeground", "ChargeForeground", XmRPixel, sizeof(Pixel), XtOffset(struct res*, charge_foreground), XtRImmediate, (caddr_t)NULL}, }; /* application state */ Arg wargs[10]; char *s; int apmfd, alert, charge; struct apm_power_info info; Widget toplevel, label; XmString xms; XtAppContext app_context; int main(int argc, char* argv[]) { toplevel = XtVaAppInitialize( &app_context, "XBat", NULL, 0, &argc, argv, NULL, NULL); if ((apmfd = open("/dev/apm", O_RDONLY)) == -1) err(1, "open"); if ((s = malloc(5*sizeof(char))) == NULL) err(1, "malloc"); /* load application resources */ XtGetApplicationResources(toplevel, &res, res_opts, XtNumber(res_opts), NULL, 0); /* create motif label */ label = XtVaCreateManagedWidget("label", xmLabelWidgetClass, toplevel, XmNlabel, "", NULL); alert = 0; charge = 0; update(NULL, NULL); XtRealizeWidget(toplevel); XtAppMainLoop(app_context); } /* update battery status and (re-)add timer */ void update(XtPointer client_data, XtIntervalId *t) { int i; /* get battery info */ memset(&info, 0, sizeof(info)); if (ioctl(apmfd, APM_IOC_GETPOWER, &info) == -1) { fprintf(stderr, "ioctl APM_IOC_GETPOWER failed\n"); sprintf(s, "?"); goto end; } /* put battery status into label */ sprintf(s, "%d%%", info.battery_life); xms = XmStringCreate(s, XmFONTLIST_DEFAULT_TAG); /* set color and font depending on battery status */ i = 0; XtSetArg(wargs[i], XmNlabelString, xms); i++; /* check if the ac adapter has been plugged in */ if (!charge && info.ac_state == APM_AC_ON) { charge = 1; XtSetArg(wargs[i], XtNforeground, res.charge_foreground); i++; if (res.charge_font_list != NULL) { XtSetArg(wargs[i], XmNfontList, res.charge_font_list); i++; } else if (res.font_list != NULL) { XtSetArg(wargs[i], XmNfontList, res.font_list); i++; } goto set; /* skip further checks */ } /* check low battery */ #ifdef ALERT if (!alert && info.battery_life < ALERT) { alert = 1; XtSetArg(wargs[i], XtNforeground, res.alert_foreground); i++; if (res.alert_font_list != NULL) { XtSetArg(wargs[i], XmNfontList, res.alert_font_list); i++; } } else if (alert && info.battery_life >= ALERT) { alert = 0; XtSetArg(wargs[i], XtNforeground, res.foreground); i++; if (res.font_list != NULL) { XtSetArg(wargs[i], XmNfontList, res.font_list); i++; } } #endif /* check if the ac adapter has been plugged out */ if (charge && info.ac_state != APM_AC_ON) { charge = 0; if (i > 1) goto set; /* don't overwrite alert */ XtSetArg(wargs[i], XtNforeground, res.foreground); i++; if (res.font_list != NULL) { XtSetArg(wargs[i], XmNfontList, res.font_list); i++; } } set: XtSetValues(label, wargs, i); XmStringFree(xms); /* add new timer */ end: XtAppAddTimeOut(app_context, INTERVAL * 1000, update, NULL); }