.so /home/john/prj/re/re.tmac .ds Sf MR .de Q \\$3\(lq\\$1\(rq\\$2 .. .TL .BI xbattext , an X11 battery monitor for NetBSD .AU John Ankarström .AB .LP .I xbattext is a simple X11 program that displays, in text, the current battery level. Its source code serves as a good introduction to X11 programnming. It is short, simple and easy to follow, as it accounts only for a single system \(en NetBSD. It makes use of both Xt (X toolkit intrinsics) and Xm (Motif), two of the most popular X libraries. It demonstrates how to access resources from .I ~/.Xdefaults , how to display text in various colors and fonts and how to set timers outside of the main event loop to perform asynchronous tasks that are not triggered by user interaction. .PP This document is a commented version of the .I xbattext source code. It is generated with .I re , a reference-based literate programming system available at the WWW address http://git.\:ankarstrom.se/re/. .PP If you want to see a screenshot of .I xbattext , skip ahead to the last page. .AE .Re xbattext.c:/^#include/ .LP .I Xm/Label.h contains the definitions for Motif's label widget, which is used to display the text. That file, in turn, includes .I X11/Xlib.h for us. .PP .I machine/apmvar.h has definitions needed in order to inspect the battery status on NetBSD. .Re xbattext.c:/^\/\* interval in seconds/ .LP By default, the battery status is checked every five seconds. .Re xbattext.c:/^\/\* low battery level/ .LP By default, the battery level is considered to be low if it is below 30 percent. .Re xbattext.c:/^struct res/ .LP Two structures are created to access the application's resources: .I res , which will hold the values of the resources, and .I res_opts , which defines how those resources should be retrieved. .PP The .I res structure is going to be filled by the function .I XtGetApp\%licationResources using the information defined in .I res_opts .\** .FS For more information about resource management and the structure of the .I XtResource type, see .nh http://lesstif.\:sourceforge.net/doc/super-ux/g1ae03e/part1/chap9.html. .hy .FE .Re xbattext.c:/"alertFontList"/ \& .Re xbattext.c:/^\/\* state changes/ .LP The .I change variable represents the possible changes in battery state. .I xbattext updates the font and color of the battery display whenever one of these state changes occur. .Re xbattext.c:/^\/\* application state/ .LP There is not space to explain the function of all variables used by the program, but some of them deserve a special mention: .PP .ps -1p .vs -1p .I wargs is an array used by .I XtSet\%Arg , which stores arguments in it, and .I XtSetValues , which applies new settings to a given widget according to the arguments stored in it. .PP .ps -1p .vs -1p The boolean values .I alerting and .I charging that are set to true whenever .I xbattext detects that the battery is low or that the AC adapter is plugged in. .Re xbattext.c:/XtVaAppInitialize(/ .LP Many Xt functions have two variants: a non-variadic variant, which uses .I XtSetArg to collect arguments, and a variadic variant, marked by the .I Va component of its name. .PP .I toplevel is the .Q main widget that contains all actual widgets. .Re xbattext.c:/open("\/dev\/apm"/ .LP The battery level is queried through .I ioctl requests to .I /dev/apm . The file descriptor is closed by the kernel when the program exits. .bp .Re xbattext.c:/^ \/\* load application resources/ .LP As mentioned above, .I XtGetApplicationResources uses the .I XtResour\%ce list defined earlier to fill the .I res structure with the corresponding resources. .Re xbattext.c:/^ \/\* create motif label/ .LP The battery level is displayed in a Motif label widget. It starts out containing an empty string. .Re xbattext.c:/^ update(/ .LP Before starting the main event loop, the .I update function is called, which creates a timer that will run independently of the event loop.\** .FS For more information about timeouts, see http://motifdeveloper.com/tips/tip16.html. .FE .Re xbattext.c:/^\/\* update battery status and (re-)add timer/ .LP The .I update function, which is also called at the end of each timeout, is responsible for checking the battery status and updating the label. .PP The first argument is a pointer to a value set by the user when the timeout is registered. The second argument contains a pointer to the timeout ID. Neither argument is used in this program. .Re xbattext.c:/^ \/\* get battery info/ .LP As mentioned above, the battery status is retrieved through an .I ioctl request, .CW APM_IOC_GETPOWER . It returns an .I apm_power_info structure (which must be zeroed first). .Re xbattext.c:/^ \/\* put battery status into label/ .LP The battery percentage, contained in .I info.battery_life , is written to an .I XmString , a special type of string used by Motif. It is associated with a .Q "font list element tag" , containing information about the visual characteristics of the text. We just use the default. .Re xbattext.c:/^ XtSetArg(/ .LP The .I wargs array mentioned above starts to be filled with arguments that determine the state of the label widget. The number of arguments set is kept track of in the .I i variable. To begin with, the widget's label string is set to the .I XmString value defined earlier. .Re xbattext.c:/^ \/\* check charging status/ .LP The bits .CW SET_CHARGE and .CW SET_\:NOCHARGE are added to the .I charge bitmap when a change in .I info.ac_\:state is detected. .PP Note that the value of .I charging is used in order to prevent these font and color changes from unnecessarily being applied every timeout regardless of whether the charging status has changed. .Re xbattext.c:/^ \/\* check low battery/ .LP The same applies when the program checks whether the battery level is below .CW ALERT , which is set to 30 by default. .Re xbattext.c:/^ \/\* prioritize/ .LP Before the bits in .I change are acted upon, some prioritization is necessary. The charging indication overrides any other indication. The low battery indication is activated if the AC adapter is plugged out, but the battery is still low. Likewise, the charging indication is activated if the battery rises above the .CW ALERT threshold, but the AC adapter is still plugged in. .Re xbattext.c:/^ \/\* act on state changes/ .LP After collecting and prioritizing the state changes, the foreground color and font of the label widget is set accordingly. .PP Note that if a .I Pixel (color) resource is not defined, .I XtGetApplicationResources gives it the integer value zero, which also signifies the color black (thus, the program cannot differentiate between a missing value and a value of .I black ). Font lists, however, are set to null if undefined. If a font list resource is undefined, .I xbattext uses the default font list instead. .Re xbattext.c:/^ case SET_CHARGE:/ \& .Re xbattext.c:/^set:/ .LP Finally, the values collected in .I wargs are associated with the label widget through the .I XtSetValues function. The .I XmString is freed, as a new one will be created on the next call to .I update , which at the end is registered through the .I Xt\%AppAddTimeOut function to occur in .CW INTERVAL seconds. .Rr .sp \(PN .LP That is the totality of the .I xbattext source (almost; a long comment at the beginning of the file, explaining what the program does and how it should be compiled, was excluded). Hopefully, it shows that graphical UNIX programming is nothing to be scared of. While Xlib, Xt and Xm tend nowadays not to be considered .Q "best practice" , they have a low barrier to entry, require little resources from the computer and are often installed by default on UNIX systems. It is better to use worse practices to create .I something than to use best practices and create nothing at all; if those are the alternatives, then perhaps best practices aren't. .PP If, after reading the source code, you are still wondering why anyone would want a small window displaying the current battery level, then you should get acquainted with the X11 window manager .I jwm \\* .FS .I jwm is available at https://joewing.net/projects/jwm/. My personal fork of .I jwm 1.8, which has a more traditional visual appearance, is available at http://git.ankarstrom.se/jwm/. .FE and its .Q swallowing feature, which removes the border from a given X11 program and displays it in the tray. You can look at it as tray icons according to the UNIX philosophy. In my tray, .I xbattext sits right beside .I xclock and .I xload . .sp 0.6v .PSPIC tray.eps .sp 0.2v .ad c .ps -1p .B "Figure 1." .I xload , .I xbattext and .I xclock .