chiark / gitweb /
internal connection numbers thing which does not work - but much other works
authorianmdlvl <ianmdlvl>
Sun, 12 Dec 2004 00:39:04 +0000 (00:39 +0000)
committerianmdlvl <ianmdlvl>
Sun, 12 Dec 2004 00:39:04 +0000 (00:39 +0000)
cprogs/xacpi-simple.c

index 1b80df70dd292bf648ff28e7b8656bee85a8af74..37a2e31d2f4368eaf620ee6212546162903312b0 100644 (file)
 #include <unistd.h>
 #include <ctype.h>
 
+#include <sys/poll.h>
 #include <sys/types.h>
 #include <dirent.h>
 
 #include <X11/Xlib.h>
 
+#define TIMEOUT 5000 /* milliseconds */
+
 /*---------- general utility stuff and declarations ----------*/
 
 static void fail(const char *m) {
@@ -300,8 +303,10 @@ static void initacquire(void) {
   C(green)                                     \
   C(cyan)                                      \
   C(grey)                                      \
-  C(darkmagenta)                                       \
+  C(darkmagenta)                               \
+  C(white)                                     \
   GC(remain)                                   \
+  GC(white)                                    \
   GC(empty)
 
 static Display *disp;
@@ -354,7 +359,7 @@ static void setforeground(Gcstate *g, unsigned long px) {
 
 static void show(void) {
   double elap, then;
-  int i, leftmost_lit, leftmost_nondeg;
+  int i, leftmost_lit, leftmost_nondeg, beyond, first_beyond;
 
   if (!charging_state_mask) {
     setbackground(pix_darkmagenta);
@@ -373,23 +378,33 @@ static void show(void) {
                
   setforeground(&gc_empty, alarm_level ? pix_red : pix_black);
 
-  for (i=0; i<height; i++) {
+  for (i=0, first_beyond=1; i<height; i++) {
     elap= !i ? 0 :
       height==2 ? BOTTOM :
       TOP * exp( (double)i / (height-2) * log( (double)BOTTOM/TOP ) );
     
     then= fill_norm + ratepersec_norm * elap;
+
+    beyond=
+      ((charging_state_mask & (1u<<CHGST_DISCHARGING) && then <= 0.0) ||
+       (charging_state_mask & (1u<<CHGST_CHARGING) && then>=nondegraded_norm));
+
     if (then <= 0.0) then= 0.0;
     else if (then >= nondegraded_norm) then= nondegraded_norm;
 
     leftmost_lit= width * then;
     leftmost_nondeg= width * nondegraded_norm;
 
-    if (leftmost_lit < leftmost_nondeg)
-      XDrawLine(disp, win, gc_empty.gc,
-               leftmost_lit,i, leftmost_nondeg,i);
-    if (leftmost_lit >= 0)
-      XDrawLine(disp, win, gc_remain.gc, 0,i, leftmost_lit,i);
+    if (beyond && first_beyond) {
+      XDrawLine(disp, win, gc_white.gc, 0,i, leftmost_nondeg,i);
+      first_beyond= 0;
+    } else {
+      if (leftmost_lit < leftmost_nondeg)
+       XDrawLine(disp, win, gc_empty.gc,
+                 leftmost_lit,i, leftmost_nondeg,i);
+      if (leftmost_lit >= 0)
+       XDrawLine(disp, win, gc_remain.gc, 0,i, leftmost_lit,i);
+    }
   }
 }
 
@@ -399,7 +414,7 @@ static void initgc(Gcstate *gc_r) {
   memset(&gcv,0,sizeof(gcv));
   gcv.function= GXcopy;
   gcv.line_width= 1;
-  gc_r->lastfg= gcv.foreground= pix_dimgrey;
+  gc_r->lastfg= gcv.foreground= pix_white;
   gc_r->gc= XCreateGC(disp,win, GCFunction|GCLineWidth|GCForeground, &gcv);
 }
 
@@ -446,17 +461,51 @@ static void newgeometry(void) {
   Window dummyw;
   
   XGetGeometry(disp,win, &dummyw,&dummy,&dummy, &width,&height, &dummy,&dummy);
-  refresh();
 }
 
 static void eventloop(void) {
   XEvent ev;
+  int *fds, nfds, npfds, *fdp, i, r;
+  struct pollfd *pfds, *pfd;
   
   newgeometry();
-  
+
+  npfds= 0;
+  pfds= 0;
   for (;;) {
-    XNextEvent(disp,&ev);
-    newgeometry();
+    r= XInternalConnectionNumbers(disp, &fds, &nfds);
+    if (!r) fail("XInternalConnectionNumbers");
+
+    if (npfds != nfds) {
+      pfds= realloc(pfds, sizeof(*pfds) * nfds);
+      if (!pfds) failr("realloc for pollfds",errno);
+      npfds= nfds;
+    }
+    for (i=0, pfd=pfds, fdp=fds;
+        i<nfds;
+        i++, pfd++, fdp++) {
+      pfd->fd= *fdp;
+      pfd->events= POLLIN|POLLERR;
+    }
+    XFree(fds);
+
+    r= poll(pfds,npfds,TIMEOUT);
+    if (r==-1) failr("poll",errno);
+
+    for (i=0, pfd=pfds;
+        i<nfds;
+        i++, pfd++) {
+      if (pfd->revents)
+       XProcessInternalConnection(disp,pfd->fd);
+    }
+
+    while (XPending(disp)) {
+      XNextEvent(disp,&ev);
+      if (ev.type == ConfigureNotify)
+       newgeometry();
+    }
+    
+    refresh();
   }
 }