From 27145a85dab4cc493a9621903da8ecbdc2e83a14 Mon Sep 17 00:00:00 2001 From: Martin Mares Date: Wed, 5 Mar 2008 12:17:11 +0100 Subject: [PATCH] Added support for lighting keyboard LEDs via the XKB protocol. Released as version 1.3. --- ChangeLog | 7 +++++ Makefile | 10 ++++++- README | 4 ++- cm.c | 89 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 108 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index b7fac24..9562c63 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2008-03-05 Martin Mares + + * 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 * Added support for gzipped mailboxes, based on a patch by diff --git a/Makefile b/Makefile index 571e62d..9a26d0a 100644 --- 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 3873dbc..aedd814 100644 --- 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 e56b463..a574e7f 100644 --- 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 + +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\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; } -- 2.39.2