2 * Copyright (c) 2007 Daniel Borca All rights reserved.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
46 #define NELEM(tab) (const int)(sizeof(tab) / sizeof((tab)[0]))
48 #define INSIDE(x, y, xmin, ymin, xmax, ymax) ((x) >= (xmin) && (x) <= (xmax) && (y) >= (ymin) && (y) <= (ymax))
50 #define SWITCH_FRAME(a, n) \
52 if ((a)->frames[n].v) { \
54 (a)->millis = (a)->frames[n].u; \
55 (a)->handle = handle_frame##n; \
56 (a)->update = update_frame##n; \
57 (a)->frames[n].p = 0; \
62 #define SCROLL_START(start, num_items, max_items) \
64 if ((start) > (num_items) - (max_items)) { \
65 (start) = (num_items) - (max_items); \
72 #define MAX_DISPLAY_CPU 2
73 #define MAX_DISPLAY_NET 2
74 #define MAX_DISPLAY_TEMP 5
102 void (*handle
) (struct APP
*a
, XEvent
*event
);
103 void (*update
) (const struct APP
*a
, int full
);
110 draw_text (const APP
*a
, const FONT
*font
, const char *str
, int dx
, int dy
)
112 const DOCKAPP
*d
= (DOCKAPP
*)a
;
116 while ((ch
= *(unsigned char *)str
++)) {
117 int w
= font
->width
[ch
];
118 dockapp_copy_area(d
, a
->font
, font
->offset
[ch
], font
->row
, w
, font
->height
, dx
, dy
);
122 /*printf("dx = %d\n", dx);*/
128 draw_meter (const APP
*a
, const FONT
*meter
, int num
, int den
, int dx
, int dy
)
130 const DOCKAPP
*d
= (DOCKAPP
*)a
;
132 const int w
= meter
->width
[0];
133 const int h
= meter
->height
;
137 int ratio
= w
* num
/ den
;
139 XCopyArea(d
->display
, a
->font
, a
->font
, d
->gc
,
143 XCopyArea(d
->display
, a
->font
, a
->font
, d
->gc
,
149 dockapp_copy_area(d
, a
->font
, col
, meter
->row
, w
, h
, dx
, dy
);
153 static void handle_frame0 (APP
*a
, XEvent
*event
);
154 #define handle_frame1 handle_frameN
155 #define handle_frame2 handle_frameN
156 #define handle_frame3 handle_frameN
157 #define handle_frame4 handle_frameN
158 #define handle_frame5 handle_frameN
159 static void handle_frameN (APP
*a
, XEvent
*event
);
160 static void update_frame0 (const APP
*a
, int full
);
161 static void update_frame1 (const APP
*a
, int full
);
162 static void update_frame2 (const APP
*a
, int full
);
163 static void update_frame3 (const APP
*a
, int full
);
164 static void update_frame4 (const APP
*a
, int full
);
165 static void update_frame5 (const APP
*a
, int full
);
169 handle_frame0 (APP
*a
, XEvent
*event
)
171 XButtonPressedEvent
*bevent
;
173 switch (event
->type
) {
175 bevent
= (XButtonPressedEvent
*)event
;
176 switch (bevent
->button
& 0xFF) {
178 /*printf("handle0: b1\n");*/
179 if (INSIDE(bevent
->x
, bevent
->y
, 4, 4, 10, 10)) {
180 /*printf("next: %d %d\n", bevent->x, bevent->y);*/
183 if (INSIDE(bevent
->x
, bevent
->y
, 50, 4, 56, 10)) {
184 /*printf("quit: %d %d\n", bevent->x, bevent->y);*/
185 ((DOCKAPP
*)a
)->quit
= True
;
188 if (INSIDE(bevent
->x
, bevent
->y
, 1, 1, 59, 13)) {
189 /*printf("time: %d %d\n", bevent->x, bevent->y);*/
193 if (INSIDE(bevent
->x
, bevent
->y
, 1, 16, 59, 27)) {
194 /*printf("cpu : %d %d\n", bevent->x, bevent->y);*/
198 if (INSIDE(bevent
->x
, bevent
->y
, 1, 30, 29, 41)) {
199 /*printf("wifi: %d %d\n", bevent->x, bevent->y);*/
203 if (INSIDE(bevent
->x
, bevent
->y
, 32, 30, 59, 41)) {
204 /*printf("temp: %d %d\n", bevent->x, bevent->y);*/
208 if (INSIDE(bevent
->x
, bevent
->y
, 1, 44, 59, 59)) {
209 /*printf("batt: %d %d\n", bevent->x, bevent->y);*/
215 /*printf("handle0: b2\n");*/
218 /*printf("handle0: b3\n");*/
227 handle_frameN (APP
*a
, XEvent
*event
)
229 XButtonPressedEvent
*bevent
;
231 switch (event
->type
) {
233 bevent
= (XButtonPressedEvent
*)event
;
234 switch (bevent
->button
& 0xFF) {
236 /*printf("handleN: b1\n");*/
240 /*printf("handleN: b2\n");*/
243 /*printf("handleN: b3\n");*/
246 /*printf("handle0: b4\n");*/
247 a
->frames
[a
->page
].p
--;
251 /*printf("handle0: b5\n");*/
252 a
->frames
[a
->page
].p
++;
262 update_frame0 (const APP
*a
, int full
)
264 const DOCKAPP
*d
= (DOCKAPP
*)a
;
265 const FRAME
*frame
= &a
->frames
[0];
284 if (!d
->iswindowed
) {
285 dockapp_set_shape(d
, frame
->m
);
288 dockapp_copy_area(d
, frame
->f
, 0, 0, d
->width
, d
->height
, 0, 0);
293 sprintf(buf
, "%2d:%02d", bt
->tm_hour
, bt
->tm_min
);
294 draw_text(a
, &a
->fontx9
, buf
, 15, 2);
296 if (system_get_cpu_load(0, &avg
, NULL
) > 0) {
297 sprintf(buf
, "__CPU__%3d%%", avg
.used
);
299 strcpy(buf
, " _____");
301 draw_text(a
, &a
->fontx8
, buf
, 1, 17);
303 if (system_get_best_wifi(&wifi
)) {
304 sprintf(buf
, "%3d\xF7", wifi
);
306 strcpy(buf
, " \xF7");
308 draw_text(a
, &a
->fontx8
, buf
, 0, 31);
310 if (system_get_max_temp(a
->list
, &temp
, &crit
)) {
311 sprintf(buf
, "%3d\xF8", temp
);
313 strcpy(buf
, " \xF8");
315 draw_text(a
, &a
->fontx8
, buf
, 31, 31);
317 battery
= system_get_battery(a
->list
, 0, &total
, NULL
);
318 on_line
= system_get_ac_adapter(a
->list
);
320 int ratio
= 100 * total
.curr_cap
/ total
.full_cap
;
331 int estimate
= 60 * (total
.full_cap
- total
.curr_cap
) / total
.rate
;
332 int hours
= estimate
/ 60;
336 sprintf(buf
, "%c__%2d:%02d\xAE\x98", ch
, hours
, estimate
% 60);
339 int estimate
= 60 * total
.curr_cap
/ total
.rate
;
340 int hours
= estimate
/ 60;
344 sprintf(buf
, "%c__%2d:%02d__ ", ch
, hours
, estimate
% 60);
349 sprintf(buf
, "%c__%3d%%___\x98", ch
, ratio
);
352 sprintf(buf
, "%c__%3d%%___ ", ch
, ratio
);
355 draw_meter(a
, &a
->meter2
, total
.curr_cap
, total
.full_cap
, 3, 55);
359 strcpy(buf
, " _____\x98");
362 strcpy(buf
, " _____ ");
364 draw_meter(a
, &a
->meter2
, 0, 0, 3, 55);
366 draw_text(a
, &a
->fontx9
, buf
, 2, 44);
373 update_frame1 (const APP
*a
, int full
)
375 const DOCKAPP
*d
= (DOCKAPP
*)a
;
376 const FRAME
*frame
= &a
->frames
[1];
383 int days
, hours
, mins
;
385 static const char *dow
[] = {
394 static const char *mon
[] = {
395 "JAN", "FEB", "MAR", "APR",
396 "MAY", "JUN", "JUL", "AUG",
397 "SEP", "OCT", "NOV", "DEC"
401 if (!d
->iswindowed
) {
402 dockapp_set_shape(d
, frame
->m
);
405 dockapp_copy_area(d
, frame
->f
, 0, 0, d
->width
, d
->height
, 0, 0);
410 draw_text(a
, &a
->fontx9
, dow
[bt
->tm_wday
], 3, 2);
412 sprintf(buf
, "%-2d %s", bt
->tm_mday
, mon
[bt
->tm_mon
]);
413 draw_text(a
, &a
->fontx9
, buf
, 10, 13);
415 sprintf(buf
, "%d", 1900 + bt
->tm_year
);
416 draw_text(a
, &a
->fontx9
, buf
, 16, 24);
418 draw_text(a
, &a
->fontx7
, "UPTIME", 15, 39);
419 strcpy(buf
, " _ _ ");
420 if (system_get_uptime(&days
, &hours
, &mins
)) {
424 sprintf(buf
, "%03d_%02d:%02d", days
, hours
, mins
);
426 draw_text(a
, &a
->fontx8
, buf
, 2, 48);
433 update_frame2 (const APP
*a
, int full
)
435 const DOCKAPP
*d
= (DOCKAPP
*)a
;
436 FRAME
*frame
= &a
->frames
[2];
441 static CPUSTAT load
[8];
442 int mem_free
, mem_total
, swp_free
, swp_total
;
446 if (!d
->iswindowed
) {
447 dockapp_set_shape(d
, frame
->m
);
450 dockapp_copy_area(d
, frame
->f
, 0, 0, d
->width
, d
->height
, 0, 0);
453 n
= system_get_cpu_speed(NELEM(speed
), speed
);
454 system_get_cpu_load(NELEM(load
), NULL
, load
);
456 SCROLL_START(frame
->p
, n
, MAX_DISPLAY_CPU
);
457 j
= frame
->p
+ MAX_DISPLAY_CPU
;
458 if (n
< MAX_DISPLAY_CPU
) {
461 draw_text(a
, &a
->fontx7
, " ", 2, 2 + j
* 20);
462 draw_text(a
, &a
->fontx7
, " ", 2, 10 + j
* 20);
466 for (k
= 0, i
= 0; k
< j
; i
++, k
++) {
481 sprintf(buf
, "CPU%d %4d M", i
, speed
[i
]);
482 draw_text(a
, &a
->fontx7
, buf
, 2, 2 + r
* 20);
485 if (load
[i
].used
>= 0) {
486 sprintf(buf
, "%3d%%", load
[i
].used
);
488 draw_text(a
, &a
->fontx7
, buf
, 2, 10 + r
* 20);
491 if (system_get_cpu_gov(i
, sizeof(buf
), buf
)) {
492 if (!strcmp(buf
, "performance")) {
494 } else if (!strcmp(buf
, "powersave")) {
496 } else if (!strcmp(buf
, "userspace")) {
498 } else if (!strcmp(buf
, "ondemand")) {
500 } else if (!strcmp(buf
, "conservative")) {
504 draw_text(a
, &a
->fontx7
, gov
, 27, 10 + r
* 20);
507 if (system_get_mem_stat(&mem_free
, &mem_total
, &swp_free
, &swp_total
)) {
510 sprintf(buf
, "MEM %3d%%", 100 * (mem_total
- mem_free
) / mem_total
);
512 draw_text(a
, &a
->fontx7
, buf
, 7, 42);
515 sprintf(buf
, "SWP %3d%%", 100 * (swp_total
- swp_free
) / swp_total
);
517 draw_text(a
, &a
->fontx7
, buf
, 7, 50);
525 update_frame3 (const APP
*a
, int full
)
527 const DOCKAPP
*d
= (DOCKAPP
*)a
;
528 FRAME
*frame
= &a
->frames
[3];
536 if (!d
->iswindowed
) {
537 dockapp_set_shape(d
, frame
->m
);
540 dockapp_copy_area(d
, frame
->f
, 0, 0, d
->width
, d
->height
, 0, 0);
543 n
= system_get_netif(NELEM(ifs
), ifs
);
545 SCROLL_START(frame
->p
, n
, MAX_DISPLAY_NET
);
546 j
= frame
->p
+ MAX_DISPLAY_NET
;
547 if (n
< MAX_DISPLAY_NET
) {
550 draw_text(a
, &a
->fontx7
, " ", 2, 2 + j
* 30);
551 draw_text(a
, &a
->fontx7
, " ", 2, 2 + j
* 30 + 9);
552 draw_text(a
, &a
->fontx6
, " _ _ _ ", 2, 2 + j
* 30 + 18);
556 for (i
= frame
->p
; i
< j
; i
++) {
557 int r
= i
- frame
->p
;
559 strupr(ifs
[i
].name
, ifs
[i
].name
);
560 ifs
[i
].name
[6] = '\0';
561 if (ifs
[i
].wlink
>= 0) {
562 sprintf(buf
, "%-6s_%3d\xF7", ifs
[i
].name
, ifs
[i
].wlink
);
563 draw_text(a
, &a
->fontx7
, buf
, 2, 2 + r
* 30);
564 strupr(buf
, ifs
[i
].essid
);
567 sprintf(buf
, "%-6s_ _", ifs
[i
].name
);
568 draw_text(a
, &a
->fontx7
, buf
, 2, 2 + r
* 30);
571 draw_text(a
, &a
->fontx7
, buf
, 2, 2 + r
* 30 + 9);
572 if (ifs
[i
].ipv4
!= -1) {
573 int addr
= ifs
[i
].ipv4
;
574 sprintf(buf
, "%3d.%3d.%3d.%3d", (addr
>> 24) & 0xFF, (addr
>> 16) & 0xFF, (addr
>> 8) & 0xFF, addr
& 0xFF);
576 strcpy(buf
, " _ _ _ ");
578 draw_text(a
, &a
->fontx6
, buf
, 2, 2 + r
* 30 + 18);
586 update_frame4 (const APP
*a
, int full
)
588 const DOCKAPP
*d
= (DOCKAPP
*)a
;
589 FRAME
*frame
= &a
->frames
[4];
597 if (!d
->iswindowed
) {
598 dockapp_set_shape(d
, frame
->m
);
601 dockapp_copy_area(d
, frame
->f
, 0, 0, d
->width
, d
->height
, 0, 0);
604 n
= system_get_temperature(a
->list
, NELEM(temp
), temp
);
606 SCROLL_START(frame
->p
, n
, MAX_DISPLAY_TEMP
);
607 j
= frame
->p
+ MAX_DISPLAY_TEMP
;
608 if (n
< MAX_DISPLAY_TEMP
) {
611 draw_text(a
, &a
->fontx7
, " _ ", 1, 1 + j
* 12);
615 for (i
= frame
->p
; i
< j
; i
++) {
616 int r
= i
- frame
->p
;
618 if (!strncmp(temp
[i
].name
, "Core ", 5) && isdigit(temp
[i
].name
[5]) && !temp
[i
].name
[6]) {
619 temp
[i
].name
[3] = temp
[i
].name
[5];
621 temp
[i
].name
[4] = '\0';
622 strupr(temp
[i
].name
, temp
[i
].name
);
623 sprintf(buf
, "%-4s:%3d\xA7%3d", temp
[i
].name
, temp
[i
].temp
, temp
[i
].max
);
630 draw_text(a
, &a
->fontx7
, buf
, 1, 1 + r
* 12);
638 update_frame5 (const APP
*a
, int full
)
640 const DOCKAPP
*d
= (DOCKAPP
*)a
;
641 const FRAME
*frame
= &a
->frames
[5];
647 BATSTAT total
, batt
[2];
652 if (!d
->iswindowed
) {
653 dockapp_set_shape(d
, frame
->m
);
656 dockapp_copy_area(d
, frame
->f
, 0, 0, d
->width
, d
->height
, 0, 0);
659 on_line
= system_get_ac_adapter(a
->list
);
660 battery
= system_get_battery(a
->list
, NELEM(batt
), &total
, batt
);
662 for (i
= 0; i
< battery
; i
++) {
664 int ratio
= 100 * batt
[i
].curr_cap
/ batt
[i
].full_cap
;
669 estimate
= 60 * (batt
[i
].full_cap
- batt
[i
].curr_cap
) / batt
[i
].rate
;
672 estimate
= 60 * batt
[i
].curr_cap
/ batt
[i
].rate
;
673 state
= "DISCHARGING";
675 hours
= estimate
/ 60;
679 sprintf(buf
, "%3d%% %2d:%02d", ratio
, hours
, estimate
% 60);
681 sprintf(buf
, "%3d%% _ ", ratio
);
684 draw_text(a
, &a
->fontx7
, batt
[i
].name
, 2, 1 + i
* 30);
685 draw_text(a
, &a
->fontx7
, state
, 2, 9 + i
* 30);
686 draw_text(a
, &a
->fontx7
, buf
, 2, 17 + i
* 30);
687 draw_meter(a
, &a
->meter2
, batt
[i
].curr_cap
, batt
[i
].full_cap
, 3, 25 + i
* 30);
690 draw_text(a
, &a
->fontx7
, " ", 2, 1 + i
* 30);
691 draw_text(a
, &a
->fontx7
, " ", 2, 9 + i
* 30);
692 draw_text(a
, &a
->fontx7
, " _ ", 2, 17 + i
* 30);
693 draw_text(a
, &a
->fontx7
, " ", 2, 20 + i
* 30);
701 update_text (SENSOR
*list
)
704 /* XXX cool stuff here */
709 run_text (SENSOR
*list
, unsigned long millis
)
711 struct timeval timeout
;
715 int redir
= fstat(STDOUT_FILENO
, &buf
) == 0 &&
716 (S_ISREG(buf
.st_mode
) || S_ISFIFO(buf
.st_mode
));
725 printf("not yet implemented -- press Enter to quit\n");
727 timeout
.tv_sec
= millis
/ 1000;
728 timeout
.tv_usec
= (millis
% 1000) * 1000;
732 if (select(0 + 1, &rset
, NULL
, NULL
, &timeout
) > 0) {
742 args (int argc
, char **argv
, int *iswindowed
, const char **display_name
, int *textmode
)
744 const char *myself
= argv
[0];
747 *display_name
= NULL
;
751 const char *p
= *++argv
;
752 if (!strcmp(p
, "-h") || !strcmp(p
, "--help")) {
753 printf("wmfu v1.0 (c) 2007 Daniel Borca\n");
754 printf("wmfu is distributed under GNU GPL v2\n\n");
755 printf("usage: %s [OPTIONS]\n", myself
);
756 printf(" -display <name> use specified display\n");
757 printf(" --windowed run in regular window\n");
758 printf(" --textmode run in text mode\n");
761 if (!strcmp(p
, "-display")) {
763 fprintf(stderr
, "%s: argument to `%s' is missing\n", myself
, p
);
767 *display_name
= *++argv
;
769 if (!strcmp(p
, "--windowed")) {
772 if (!strcmp(p
, "--textmode")) {
780 main (int argc
, char **argv
)
788 const char *display_name
;
791 args(argc
, argv
, &iswindowed
, &display_name
, &textmode
);
793 App
.list
= sensors_init();
794 if (App
.list
== NULL
) {
795 fprintf(stderr
, "Error allocating sensor structure\n");
800 int rv
= run_text(App
.list
, 1000);
801 sensors_free(App
.list
);
805 rv
= dockapp_open_window(&DockApp
, display_name
, "wmfu", iswindowed
, argc
, argv
);
807 fprintf(stderr
, "Could not open display `%s'\n", display_name
);
808 sensors_free(App
.list
);
812 frames
[0].v
= dockapp_xpm2pixmap(&DockApp
, frame0_xpm
, &frames
[0].f
, &frames
[0].m
, NULL
, 0);
814 fprintf(stderr
, "Error initializing frame\n");
815 sensors_free(App
.list
);
819 if (!dockapp_xpm2pixmap(&DockApp
, font_xpm
, &App
.font
, NULL
, NULL
, 0)) {
820 fprintf(stderr
, "Error initializing font\n");
821 sensors_free(App
.list
);
825 App
.fontx9
.row
= FONTX9_ROW
;
826 App
.fontx9
.height
= 9;
827 App
.fontx9
.width
= fontx9_width
;
828 App
.fontx9
.offset
= fontx9_offset
;
830 App
.fontx8
.row
= FONTX8_ROW
;
831 App
.fontx8
.height
= 8;
832 App
.fontx8
.width
= fontx8_width
;
833 App
.fontx8
.offset
= fontx8_offset
;
835 App
.fontx7
.row
= FONTX7_ROW
;
836 App
.fontx7
.height
= 7;
837 App
.fontx7
.width
= fontx7_width
;
838 App
.fontx7
.offset
= fontx7_offset
;
840 App
.fontx6
.row
= FONTX6_ROW
;
841 App
.fontx6
.height
= 6;
842 App
.fontx6
.width
= fontx6_width
;
843 App
.fontx6
.offset
= fontx6_offset
;
845 App
.meter2
.row
= METER2_ROW
;
846 App
.meter2
.height
= 2;
847 App
.meter2
.width
= meter2_width
;
848 App
.meter2
.offset
= NULL
;
850 frames
[1].v
= dockapp_xpm2pixmap(&DockApp
, frame1_xpm
, &frames
[1].f
, &frames
[1].m
, NULL
, 0);
851 frames
[2].v
= dockapp_xpm2pixmap(&DockApp
, frame2_xpm
, &frames
[2].f
, &frames
[2].m
, NULL
, 0);
852 frames
[3].v
= dockapp_xpm2pixmap(&DockApp
, frame3_xpm
, &frames
[3].f
, &frames
[3].m
, NULL
, 0);
853 frames
[4].v
= dockapp_xpm2pixmap(&DockApp
, frame4_xpm
, &frames
[4].f
, &frames
[4].m
, NULL
, 0);
854 frames
[5].v
= dockapp_xpm2pixmap(&DockApp
, frame5_xpm
, &frames
[5].f
, &frames
[5].m
, NULL
, 0);
864 SWITCH_FRAME(&App
, 0);
866 dockapp_set_eventmask(&DockApp
, ButtonPressMask
);
869 while (!DockApp
.quit
) {
871 if (dockapp_nextevent_or_timeout(&DockApp
, &event
, App
.millis
)) {
872 App
.handle(&App
, &event
);
880 for (i
= 0; i
< 1000; i
++) {
886 XCloseDisplay(DockApp
.display
);
888 sensors_free(App
.list
);