]> mj.ucw.cz Git - checkmail.git/commitdiff
Added support for lighting keyboard LEDs via the XKB protocol.
authorMartin Mares <mj@ucw.cz>
Wed, 5 Mar 2008 11:17:11 +0000 (12:17 +0100)
committerMartin Mares <mj@ucw.cz>
Wed, 5 Mar 2008 11:17:11 +0000 (12:17 +0100)
Released as version 1.3.

ChangeLog
Makefile
README
cm.c

index b7fac2409ee53d8fce46b142a47ca343223fcdb1..9562c635abc09d7482efb83173800819b2e51cbc 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2008-03-05  Martin Mares <mj@ucw.cz>
+
+       * Added support for lighting keyboard LEDs via the XKB protocol
+       if a connection to the X server is available.
+
+       * Released as 1.3.
+
 2008-02-13  Martin Mares <mj@ucw.cz>
 
        * Added support for gzipped mailboxes, based on a patch by
index 571e62d1344492c65bc723ec4de65a4778a18d3b..9a26d0ac75ca0aba87f470c5b618bce59df82f53 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,9 @@
 # Define if you want support for wide characters (needs libncursesw)
 CONFIG_WIDE_CURSES=1
 
+# Define if you want XKB led controls
+CONFIG_X_LEDS=1
+
 #DEBUG=-ggdb
 CFLAGS=-O2 -Wall -W -Wno-parentheses -Wstrict-prototypes -Wmissing-prototypes -Winline $(DEBUG) -std=gnu99 -DVERSION=$(VERSION) -DYEAR=$(YEAR)
 
@@ -11,7 +14,12 @@ else
 LDFLAGS=-lncurses
 endif
 
-VERSION=1.2
+ifdef CONFIG_X_LEDS
+LDFLAGS+=-lX11
+CFLAGS+=-DCONFIG_X_LEDS=1
+endif
+
+VERSION=1.3
 YEAR=2008
 
 all: cm
diff --git a/README b/README
index 3873dbca5e2db0b33a996c2f8e9dfaa767f45bd5..aedd8142b8b063c06d0b6e29f0ea6df309399be2 100644 (file)
--- a/README
+++ b/README
@@ -14,7 +14,9 @@ It can be freely used and distributed according to the terms of the GNU General
 Public License version 2, as published by the Free Software Foundation.
 
 Build requirements: libncurses, locales and iconv and a decent C99 compiler
-(preferably GCC).
+(preferably GCC). For full UTF-8 support libncursesw is necessary, options
+for controlling XKB leds need libX11. See Makefile for several build-time
+switches.
 
 Usage:
        see `cm --help'
diff --git a/cm.c b/cm.c
index e56b4637127bd853721ea3c60de1ca1fd7701c1c..a574e7f2b11767ccca15f2a5ca60eb4c966a8b2a 100644 (file)
--- a/cm.c
+++ b/cm.c
@@ -49,6 +49,7 @@ struct options {
   int sender_personal;
   int sender_mbox;
   int hotkey;
+  int led;
 };
 
 struct option_node {
@@ -132,6 +133,7 @@ init_options(struct options *o)
   o->sender_personal = -1;
   o->sender_mbox = -1;
   o->hotkey = -1;
+  o->led = -1;
 }
 
 static void
@@ -153,6 +155,7 @@ setup_options(struct mbox *b)
        MERGE(sender_personal);
        MERGE(sender_mbox);
        MERGE(hotkey);
+       MERGE(led);
       }
 }
 
@@ -574,6 +577,86 @@ scan(void)
   rethink_display();
 }
 
+#ifdef CONFIG_X_LEDS
+
+#include <X11/Xlib.h>
+
+static Display *leds_dpy;
+static unsigned leds_care, leds_have, leds_want;
+
+static void
+leds_init(void)
+{
+  leds_care = 0;
+  CLIST_FOR_EACH(struct option_node *, o, options)
+    if (o->o.led > 0)
+      leds_care |= (1 << o->o.led);
+  if (!leds_care)
+    {
+      debug("LEDS: No mailbox wants them\n");
+      return;
+    }
+  if (!getenv("DISPLAY"))
+    {
+      debug("LEDS: Do not have X display\n");
+      return;
+    }
+  if (!(leds_dpy = XOpenDisplay(NULL)))
+    die("Cannot open X display, although the DISPLAY variable is set");
+
+  leds_have = ~0U;
+}
+
+static void
+sync_leds(void)
+{
+  if (leds_want == leds_have)
+    return;
+
+  debug("LEDS: have %02x, want %02x, care %02x\n", leds_have, leds_want, leds_care);
+  for (int i=1; i<10; i++)
+    if (leds_care & (leds_have ^ leds_want) & (1 << i))
+      {
+       XKeyboardControl cc;
+       cc.led = i;
+       cc.led_mode = (leds_want & (1 << i)) ? LedModeOn : LedModeOff;
+       XChangeKeyboardControl(leds_dpy, KBLed | KBLedMode, &cc);
+      }
+  XFlush(leds_dpy);
+  leds_have = leds_want;
+}
+
+static void
+rethink_leds(void)
+{
+  if (!leds_dpy)
+    return;
+
+  leds_want = 0;
+  CLIST_FOR_EACH(struct mbox *, b, mboxes)
+    if (b->o.led > 0 && b->new)
+      leds_want |= (1 << b->o.led);
+  sync_leds();
+}
+
+static void
+leds_cleanup(void)
+{
+  if (!leds_dpy)
+    return;
+
+  leds_want = 0;
+  sync_leds();
+}
+
+#else
+
+static void leds_init(void) { }
+static void rethink_leds(void) { }
+static void leds_cleanup(void) { }
+
+#endif
+
 static int cursor_at, cursor_max;
 
 enum {
@@ -730,6 +813,7 @@ rethink_display(void)
       redraw_all();
       refresh();
     }
+  rethink_leds();
   if (beeeep && allow_bells)
     beep();
 }
@@ -877,6 +961,7 @@ b\t\t\tBeep when a message arrives\n\
 e\t\t\tHide from display if empty\n\
 f\t\t\tShow flagged messages if there are no new ones\n\
 h\t\t\tHide from display\n\
+l<led>\t\t\tLight a keyboard led (1-9) if running on X display\n\
 m\t\t\tShow mailbox name of the sender\n\
 p\t\t\tShow personal info (full name) of the sender\n\
 s\t\t\tShow message snippets\n\
@@ -913,6 +998,8 @@ parse_options(char *c)
       o->priority = x - '0';
     else if (x == '!' && *c)
       o->hotkey = *c++;
+    else if (x == 'l' && *c >= '1' && *c <= '9')
+      o->led = *c++ - '0';
     else
       {
        int value = !!islower(x);
@@ -988,6 +1075,7 @@ main(int argc, char **argv)
 
   charset_init();
   term_init();
+  leds_init();
   scan_and_redraw();
   next_active(0, 1);
 
@@ -1075,6 +1163,7 @@ restart:
        }
     }
 
+  leds_cleanup();
   term_cleanup();
   return 0;
 }