aboutsummaryrefslogtreecommitdiff
path: root/xbattext.ms
blob: 44cdde8ba5039559387cf76a30cc5e443d0a2ba2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
.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 .