wmload: Incorporate changes from asload-0.9.3.
[dockapps.git] / wmload / wmload.c
blob78ee55885c3db74b6b20d19065570d57a61c4233
1 #include <ctype.h>
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include <unistd.h>
6 #include <X11/Xlib.h>
7 #include <X11/xpm.h>
8 #include <X11/extensions/shape.h>
9 #include <time.h>
10 #include <math.h>
11 #include <fcntl.h>
12 #include <X11/Xatom.h>
14 #include "back.xpm"
15 #include "mask2.xbm"
16 #include "mask.xpm"
18 #define major_VER 0
19 #define minor_VER 9
20 #define patch_VER 3
21 #define MW_EVENTS (ExposureMask | ButtonPressMask | StructureNotifyMask)
22 #define FALSE 0
23 #define Shape(num) (ONLYSHAPE ? num-5 : num)
24 #define NCPUSTATES 4
26 /* Global Data storage/structures ********************************************/
27 static long cp_time[NCPUSTATES];
28 static long last[NCPUSTATES];
29 int ONLYSHAPE=0; /* default value is noshape */
30 int updatespeed = 4;
31 static char *help_message[] = {
32 "where options include:",
33 " -u <secs> updatespeed",
34 " -exe <program> program to start on click",
35 " -led <color> color of the led",
36 " -position [+|-]x[+|-]y position of wmload",
37 " -shape without groundplate",
38 " -iconic start up as icon",
39 " -withdrawn start up withdrawn",
40 " -ver output version",
41 NULL
44 /* X11 Variables *************************************************************/
45 Display *dpy; /* welches DISPLAY */
46 Window Root; /* Hintergrund-Drawable */
47 int screen;
48 int x_fd;
49 int d_depth;
50 XSizeHints mysizehints;
51 XWMHints mywmhints;
52 Pixel back_pix, fore_pix;
53 GC NormalGC;
54 Window iconwin, win; /* My home is my window */
55 char *ProgName;
56 char *Geometry;
57 char *LedColor = "LightSeaGreen";
58 char Execute[] = "echo no program has been specified >/dev/console";
59 char *ERR_colorcells = "not enough free color cells\n";
60 char *ampers = " &";
62 /* XPM Structures & Variables ************************************************/
63 typedef struct _XpmIcon {
64 Pixmap pixmap;
65 Pixmap mask;
66 XpmAttributes attributes;
67 } XpmIcon;
69 XpmIcon wmload;
70 XpmIcon visible;
71 time_t actualtime;
72 long actualmin;
74 /* Function definitions ******************************************************/
75 void GetXPM(void);
76 Pixel GetColor(char *name);
77 void RedrawWindow( XpmIcon *v);
78 void InitLoad();
79 void InsertLoad();
81 /*****************************************************************************/
82 /* Source Code <--> Function Implementations */
83 /*****************************************************************************/
84 void usage()
86 char **cpp;
88 fprintf(stderr,"\nusage: %s [-options ...] \n", ProgName);
89 for (cpp = help_message; *cpp; cpp++) {
90 fprintf(stderr, "%s\n", *cpp);
92 fprintf(stderr,"\n");
93 exit(1);
96 int main(int argc,char *argv[])
98 int i;
99 unsigned int borderwidth ;
100 char *display_name = NULL;
101 char *wname = "wmload";
102 XGCValues gcv;
103 unsigned long gcm;
104 XEvent Event;
105 XTextProperty name;
106 XClassHint classHint;
107 Pixmap pixmask;
108 Atom _XA_WM_DELETE_WINDOW = None;
109 Geometry = "";
110 mywmhints.initial_state = NormalState;
112 /* Parse command line options */
113 ProgName = argv[0];
115 for(i=1;i<argc;i++) {
116 char *arg= argv[i];
118 if (arg[0] == '-') {
119 switch(arg[1]) {
120 case 'u':
121 if(++i >=argc) usage();
122 sscanf(argv[i], "%d", &updatespeed);
123 continue;
124 case 'e':
125 if(++i >=argc) usage();
126 strcpy(&Execute[0], argv[i]);
127 strcat(&Execute[0], " &");
128 continue;
129 case 's':
130 ONLYSHAPE=1;
131 continue;
132 case 'p':
133 if(++i >=argc) usage();
134 Geometry = argv[i];
135 continue;
136 case 'i':
137 mywmhints.initial_state = IconicState;
138 continue;
139 case 'w':
140 mywmhints.initial_state = WithdrawnState;
141 continue;
142 case 'l':
143 if(++i >=argc) usage();
144 LedColor = argv[i];
145 continue;
146 case 'v':
147 fprintf(stdout, "\nwmload version: %i.%i.%i\n", major_VER, minor_VER, patch_VER);
148 if(argc == 2) exit(0);
149 continue;
150 default:
151 usage();
154 else
156 fprintf(stderr, "\nInvalid argument: %s\n", arg);
157 usage();
161 /* Open the display */
162 if (!(dpy = XOpenDisplay(display_name)))
164 fprintf(stderr,"wmload: can't open display %s\n",
165 XDisplayName(display_name));
166 exit (1);
169 screen= DefaultScreen(dpy);
170 Root = RootWindow(dpy, screen);
171 d_depth = DefaultDepth(dpy, screen);
172 x_fd = XConnectionNumber(dpy);
173 _XA_WM_DELETE_WINDOW = XInternAtom (dpy, "WM_DELETE_WINDOW", False);
175 /* Convert XPM Data to XImage */
176 GetXPM();
178 /* Create a window to hold the banner */
179 mysizehints.flags= USSize|USPosition;
180 mysizehints.x = 0;
181 mysizehints.y = 0;
183 back_pix = GetColor("white");
184 fore_pix = GetColor("black");
186 XWMGeometry(dpy, screen, Geometry, NULL, (borderwidth =1), &mysizehints,
187 &mysizehints.x,&mysizehints.y,&mysizehints.width,&mysizehints.height, &i);
189 mysizehints.width = wmload.attributes.width;
190 mysizehints.height= wmload.attributes.height;
192 win = XCreateSimpleWindow(dpy,Root,mysizehints.x,mysizehints.y,
193 mysizehints.width,mysizehints.height,
194 borderwidth,fore_pix,back_pix);
195 iconwin = XCreateSimpleWindow(dpy,win,mysizehints.x,mysizehints.y,
196 mysizehints.width,mysizehints.height,
197 borderwidth,fore_pix,back_pix);
199 /* activate hints */
200 XSetWMNormalHints(dpy, win, &mysizehints);
201 classHint.res_name = "wmload";
202 classHint.res_class = "WMLoad";
203 XSetClassHint(dpy, win, &classHint);
205 XSelectInput(dpy,win,MW_EVENTS);
206 XSelectInput(dpy,iconwin,MW_EVENTS);
207 XSetCommand(dpy,win,argv,argc);
209 if (XStringListToTextProperty(&wname, 1, &name) ==0) {
210 fprintf(stderr, "wmload: can't allocate window name\n");
211 exit(-1);
213 XSetWMName(dpy, win, &name);
215 /* Create a GC for drawing */
216 gcm = GCForeground|GCBackground|GCGraphicsExposures;
217 gcv.foreground = fore_pix;
218 gcv.background = back_pix;
219 gcv.graphics_exposures = FALSE;
220 NormalGC = XCreateGC(dpy, Root, gcm, &gcv);
222 if (ONLYSHAPE) { /* try to make shaped window here */
223 pixmask = XCreateBitmapFromData(dpy, win, (char *)mask2_bits, mask2_width,
224 mask2_height);
225 XShapeCombineMask(dpy, win, ShapeBounding, 0, 0, pixmask, ShapeSet);
226 XShapeCombineMask(dpy, iconwin, ShapeBounding, 0, 0, pixmask, ShapeSet);
229 mywmhints.icon_window = iconwin;
230 mywmhints.icon_x = mysizehints.x;
231 mywmhints.icon_y = mysizehints.y;
232 mywmhints.window_group = win;
233 mywmhints.flags = StateHint | IconWindowHint | IconPositionHint
234 | WindowGroupHint;
235 XSetWMHints(dpy, win, &mywmhints);
236 XSetWMProtocols (dpy, win, &_XA_WM_DELETE_WINDOW, 1);
238 XMapWindow(dpy,win);
239 InitLoad();
240 InsertLoad();
241 RedrawWindow(&visible);
242 while(1)
244 if (actualtime != time(0))
246 actualtime = time(0);
248 if(actualtime % updatespeed == 0)
249 InsertLoad();
251 RedrawWindow(&visible);
254 /* read a packet */
255 while (XPending(dpy))
257 XNextEvent(dpy,&Event);
258 switch(Event.type)
260 case Expose:
261 if(Event.xexpose.count == 0 )
262 RedrawWindow(&visible);
263 break;
264 case ButtonPress:
265 system(Execute);
266 break;
267 case ClientMessage:
268 if ((Event.xclient.format != 32) ||
269 (Event.xclient.data.l[0] != _XA_WM_DELETE_WINDOW))
270 break;
271 case DestroyNotify:
272 XFreeGC(dpy, NormalGC);
273 XDestroyWindow(dpy, iconwin);
274 XDestroyWindow(dpy, win);
275 XCloseDisplay(dpy);
276 exit(0);
277 break ;
278 default:
279 break;
282 XFlush(dpy);
283 #ifdef SYSV
284 poll((struct poll *) 0, (size_t) 0, 50);
285 #else
286 usleep(50000L); /* 5/100 sec */
287 #endif
289 return 0;
292 /*****************************************************************************/
293 void nocolor(char *a, char *b)
295 fprintf(stderr,"wmload: can't %s %s\n", a,b);
298 /*****************************************************************************/
299 /* convert the XPMIcons to XImage */
300 void GetXPM(void)
302 static char **alt_xpm;
303 XColor col;
304 XWindowAttributes attributes;
305 int ret;
306 char tempc1[12],tempc2[12],tempc3[12];
307 float colr,colg,colb;
309 alt_xpm =ONLYSHAPE ? mask_xpm : back_xpm;
311 /* for the colormap */
312 XGetWindowAttributes(dpy,Root,&attributes);
314 /* get user-defined color or validate the default */
315 if (!XParseColor (dpy, attributes.colormap, LedColor, &col))
317 nocolor("parse",LedColor);
319 else
321 /* scale down the Xcolor values */
322 colr = col.red / 257;
323 colg = col.green / 257;
324 colb = col.blue / 257;
325 /* the brightest color */
326 sprintf(tempc1, "S c #%.2x%.2x%.2x", (int)colr, (int)colg, (int)colb);
327 back_xpm[47] = tempc1;
329 /* make medium color */
330 colr = (colr /100) *89;
331 colg = (colg /100) *89;
332 colb = (colb /100) *89;
333 sprintf(tempc2, "R c #%.2x%.2x%.2x", (int)colr, (int)colg, (int)colb);
334 back_xpm[46] = tempc2;
336 /* make darkest color */
337 colr = (colr /100) *89;
338 colg = (colg /100) *89;
339 colb = (colb /100) *89;
340 sprintf(tempc3, "Q c #%.2x%.2x%.2x", (int)colr, (int)colg, (int)colb);
341 back_xpm[45] = tempc3;
344 wmload.attributes.valuemask |= (XpmReturnPixels | XpmReturnExtensions);
345 ret = XpmCreatePixmapFromData(dpy, Root, alt_xpm, &wmload.pixmap,
346 &wmload.mask, &wmload.attributes);
347 if(ret != XpmSuccess)
348 {fprintf(stderr, "%s\n", ERR_colorcells);exit(1);}
350 visible.attributes.valuemask |= (XpmReturnPixels | XpmReturnExtensions);
351 ret = XpmCreatePixmapFromData(dpy, Root, back_xpm, &visible.pixmap,
352 &visible.mask, &visible.attributes);
353 if(ret != XpmSuccess)
354 {fprintf(stderr, "%s\n", ERR_colorcells);exit(1);}
358 /*****************************************************************************/
359 /* Removes expose events for a specific window from the queue */
360 int flush_expose (Window w)
362 XEvent dummy;
363 int i=0;
365 while (XCheckTypedWindowEvent (dpy, w, Expose, &dummy))i++;
366 return i;
369 /*****************************************************************************/
370 /* Draws the icon window */
371 void RedrawWindow( XpmIcon *v)
373 flush_expose (iconwin);
374 XCopyArea(dpy,v->pixmap,iconwin,NormalGC,
375 0,0,v->attributes.width, v->attributes.height,0,0);
376 flush_expose (win);
377 XCopyArea(dpy,v->pixmap,win,NormalGC,
378 0,0,v->attributes.width, v->attributes.height,0,0);
382 /*****************************************************************************/
383 Pixel GetColor(char *name)
385 XColor color;
386 XWindowAttributes attributes;
388 XGetWindowAttributes(dpy,Root,&attributes);
389 color.pixel = 0;
390 if (!XParseColor (dpy, attributes.colormap, name, &color))
392 nocolor("parse",name);
394 else if(!XAllocColor (dpy, attributes.colormap, &color))
396 nocolor("alloc",name);
398 return color.pixel;
401 /*****************************************************************************/
402 void InitLoad()
404 /* Save the 4 base colors in wmload */
405 XCopyArea(dpy, visible.pixmap, wmload.pixmap, NormalGC,
406 6,6,3,52, Shape(6), Shape(6));
408 /* Copy the base panel to visible */
409 XCopyArea(dpy, wmload.pixmap, visible.pixmap, NormalGC,
410 0,0,mysizehints.width, mysizehints.height, 0 ,0);
412 /* Remove the 4 base colors from visible */
413 XCopyArea(dpy, visible.pixmap, visible.pixmap, NormalGC,
414 Shape(9),Shape(6),3,52, Shape(6), Shape(6));
417 static char *
418 skip_token(const char *p)
420 while (isspace(*p)) p++;
421 while (*p && !isspace(*p)) p++;
422 return (char *)p;
425 void GetLoad(int Maximum, int *usr, int *nice, int *sys, int *free)
427 char buffer[100];/*[4096+1];*/
428 int fd, len;
429 int total;
430 char *p;
432 fd = open("/proc/stat", O_RDONLY);
433 len = read(fd, buffer, sizeof(buffer)-1);
434 close(fd);
435 buffer[len] = '\0';
437 p = skip_token(buffer); /* "cpu" */
439 cp_time[0] = strtoul(p, &p, 0); /* user */
440 cp_time[1] = strtoul(p, &p, 0); /* nice */
441 cp_time[2] = strtoul(p, &p, 0); /* system */
442 cp_time[3] = strtoul(p, &p, 0); /* idle */
444 if( (*usr = cp_time[0] - last[0]) < 0 ) *usr = 0 ;
445 if( (*nice = cp_time[1] - last[1]) < 0 ) *nice = 0 ;
446 if( (*sys = cp_time[2] - last[2]) < 0 ) *sys = 0 ;
447 if( (*free = cp_time[3] - last[3]) < 0 ) *free = 0 ;
449 total = *usr + *nice + *sys + *free;
451 last[0] = cp_time[0];
452 last[1] = cp_time[1];
453 last[2] = cp_time[2];
454 last[3] = cp_time[3];
456 *usr = rint(Maximum * (float)(*usr) /total);
457 *nice =rint(Maximum * (float)(*nice) /total);
458 *sys = rint(Maximum * (float)(*sys) /total);
459 *free = rint(Maximum * (float)(*free) /total);
462 void InsertLoad()
464 int UserTime, NiceTime, SystemTime, FreeTime, act, constrain;
465 GetLoad( 52, &UserTime, &NiceTime, &SystemTime, &FreeTime);
467 constrain = (UserTime + NiceTime + SystemTime + FreeTime);
468 if(constrain == 53)
470 if(FreeTime > 0) FreeTime--;
471 else if(SystemTime > 0) SystemTime--;
472 else if(NiceTime > 0) NiceTime--;
473 else if(UserTime > 0) UserTime--;
475 else if(constrain == 51) FreeTime++;
477 /* Move the area */
478 XCopyArea(dpy, visible.pixmap, visible.pixmap, NormalGC,
479 Shape(7), Shape(6), 51, 52, Shape(6), Shape(6));
482 /* User Time */
483 act = 58 - UserTime;
484 if(UserTime > 0)
485 XCopyArea(dpy, wmload.pixmap, visible.pixmap, NormalGC,
486 Shape(6), Shape(6), 1, UserTime, Shape(57), Shape(act));
488 /* Nice Time */
489 act = act - NiceTime;
490 if(NiceTime > 0)
491 XCopyArea(dpy, wmload.pixmap, visible.pixmap, NormalGC,
492 Shape(7), Shape(6), 1, NiceTime, Shape(57), Shape(act));
494 /* System Time */
495 act = act - SystemTime;
496 if(SystemTime > 0)
497 XCopyArea(dpy, wmload.pixmap, visible.pixmap, NormalGC,
498 Shape(8), Shape(6), 1, SystemTime, Shape(57), Shape(act));
500 /* Free Time */
501 if(FreeTime > 0)
502 XCopyArea(dpy, wmload.pixmap, visible.pixmap, NormalGC,
503 Shape(9), Shape(6), 1, FreeTime, Shape(57), Shape(6));