#include <stdlib.h>
#include <X11/X.h>
#include <X11/Xlib.h>
#include <X11/XKBlib.h>
#include <X11/Intrinsic.h>
#include <X11/StringDefs.h>
#include <X11/Shell.h>
#include <X11/Xaw/Cardinals.h>
#include <X11/Xaw/Box.h>
#define OPAQUE_DEFINED
#define BOOLEAN_DEFINED
#define DEBUG_VAR_NOT_LOCAL
#define DEBUG_VAR debugFlags
#include "utils.h"
#include "LED.h"
#define YES 1
#define NO 0
#define DONT_CARE -1
Display * inDpy,*outDpy;
static unsigned long wanted,real,named,explicit,automatic,virtual;
static char * inDpyName;
int wantNamed= DONT_CARE;
int wantExplicit= DONT_CARE;
int wantAutomatic= DONT_CARE;
int wantReal= DONT_CARE;
int wantVirtual= DONT_CARE;
int evBase,errBase;
Bool synch;
Bool useUnion= True;
static void
usage(char *program)
{
uInformation("Usage: %s <options>\n",program);
uInformation("Legal options include the usual X toolkit options plus:\n");
uInformation(" -help Print this message\n");
uInformation(" -indpy <name> Name of display to watch\n");
uInformation(" -watch <leds> Mask of LEDs to watch\n");
uInformation(" [-+]automatic (Don't) watch automatic LEDs\n");
uInformation(" [-+]explicit (Don't) watch explicit LEDs\n");
uInformation(" [-+]name (Don't) watch named LEDs\n");
uInformation(" [-+]real (Don't) watch real LEDs\n");
uInformation(" [-+]virtual (Don't) watch virtual LEDs\n");
uInformation(" -intersection Watch only LEDs in all desired sets\n");
uInformation(" -union Watch LEDs in any desired sets\n");
uInformation("The default set of LEDs is -union +name +automatic +real\n");
return;
}
static Bool
parseArgs(int argc, char *argv[])
{
register int i;
for (i=1;i<argc;i++) {
if (uStrCaseEqual(argv[i],"-indpy")) {
if (i<argc-1) inDpyName= argv[++i];
else {
uWarning("No name specified for input display\n");
uAction("Ignoring trailing -indpy argument\n");
}
}
else if (uStrCaseEqual(argv[i],"-watch")) {
if (i<argc-1) {
int tmp;
if (sscanf(argv[++i],"%i",&tmp)!=1) {
uWarning("Set of LEDs must be specified as an integer\n");
uAction("Ignoring bogus value \"%s\" for -watch flag\n",
argv[i]);
}
else wanted= tmp;
}
else {
uWarning("Didn't specify any LEDs to watch\n");
uAction("Ignoring trailing -watch argument\n");
}
}
else if (uStrCaseEqual(argv[i],"-union")) {
useUnion= True;
}
else if (uStrCaseEqual(argv[i],"-intersection")) {
useUnion= False;
}
else if (uStrCaseEqual(argv[i],"-help")) {
usage(argv[0]);
exit(0);
}
else if ((argv[i][0]=='+')||(argv[i][0]=='-')) {
Bool onoff;
int * which;
onoff= (argv[i][0]=='+');
which= NULL;
if (uStrCaseEqual(&argv[i][1],"name"))
which= &wantNamed;
else if (uStrCaseEqual(&argv[i][1],"explicit"))
which= &wantExplicit;
else if (uStrCaseEqual(&argv[i][1],"automatic"))
which= &wantAutomatic;
else if (uStrCaseEqual(&argv[i][1],"real"))
which= &wantReal;
else if (uStrCaseEqual(&argv[i][1],"virtual"))
which= &wantVirtual;
if (which!=NULL) {
if (*which!=DONT_CARE) {
uWarning("Multiple settings for [+-]%s\n",&argv[i][1]);
uAction("Using %c%s, ignoring %c%s\n",
(onoff?'+':'-'),&argv[i][1],
(onoff?'-':'+'),&argv[i][1]);
}
*which= (onoff?YES:NO);
}
}
}
return True;
}
static Display *
GetDisplay(char *program, char *dpyName)
{
int mjr,mnr,error;
Display * dpy;
mjr= XkbMajorVersion;
mnr= XkbMinorVersion;
dpy= XkbOpenDisplay(dpyName,&evBase,&errBase,&mjr,&mnr,&error);
if (dpy==NULL) {
switch (error) {
case XkbOD_BadLibraryVersion:
uInformation("%s was compiled with XKB version %d.%02d\n",
program,XkbMajorVersion,XkbMinorVersion);
uError("X library supports incompatible version %d.%02d\n",
mjr,mnr);
break;
case XkbOD_ConnectionRefused:
uError("Cannot open display \"%s\"\n",dpyName);
break;
case XkbOD_NonXkbServer:
uError("XKB extension not present on %s\n",dpyName);
break;
case XkbOD_BadServerVersion:
uInformation("%s was compiled with XKB version %d.%02d\n",
program,XkbMajorVersion,XkbMinorVersion);
uError("Server %s uses incompatible version %d.%02d\n",
dpyName,mjr,mnr);
break;
default:
uInternalError("Unknown error %d from XkbOpenDisplay\n",error);
}
}
else if (synch)
XSynchronize(dpy,True);
return dpy;
}
int
main(int argc, char *argv[])
{
Widget toplevel;
XtAppContext app_con;
Widget panel;
Widget leds[XkbNumIndicators];
register int i;
unsigned bit;
unsigned n;
XkbDescPtr xkb;
XkbEvent ev;
static Arg boxArgs[]= {{ XtNorientation, (XtArgVal)XtorientHorizontal }};
static Arg onArgs[]= {{ XtNon, (XtArgVal)True }};
static Arg offArgs[]= {{ XtNon, (XtArgVal)False }};
static char * fallback_resources[] = {
"*Box*background: grey40",
NULL
};
uSetEntryFile(NullString);
uSetDebugFile(NullString);
uSetErrorFile(NullString);
bzero(leds,XkbNumIndicators*sizeof(Widget));
toplevel = XtOpenApplication(&app_con, "XkbLEDPanel", NULL, 0, &argc, argv,
fallback_resources,
sessionShellWidgetClass, NULL, ZERO);
if (toplevel==NULL) {
uFatalError("Couldn't create application top level\n");
return 1;
}
if ((argc>1)&&(!parseArgs(argc,argv))) {
usage(argv[0]);
return 1;
}
if ((wanted==0)&&(wantNamed==DONT_CARE)&&(wantExplicit==DONT_CARE)&&
(wantAutomatic==DONT_CARE)&&(wantReal==DONT_CARE)) {
wantNamed= YES;
wantReal= YES;
wantAutomatic= YES;
}
outDpy= XtDisplay(toplevel);
if (inDpyName!=NULL) {
inDpy= GetDisplay(argv[0],inDpyName);
if (!inDpy)
return 1;
}
else {
inDpy= outDpy;
}
if (inDpy) {
int i1,mn,mj;
mj= XkbMajorVersion;
mn= XkbMinorVersion;
if (!XkbLibraryVersion(&mj,&mn)) {
uInformation("%s was compiled with XKB version %d.%02d\n",
argv[0],XkbMajorVersion,XkbMinorVersion);
uError("X library supports incompatible version %d.%02d\n",
mj,mn);
}
if (!XkbQueryExtension(inDpy,&i1,&evBase,&errBase,&mj,&mn)) {
uFatalError("Server doesn't support a compatible XKB\n");
return 1;
}
}
else {
uFatalError("No input display\n");
return 1;
}
panel= XtCreateManagedWidget("xkbleds",boxWidgetClass,toplevel,boxArgs,1);
if (panel==NULL) {
uFatalError("Couldn't create list of leds\n");
return 1;
}
real= virtual= named= explicit= automatic= 0;
if (wantReal || wantNamed || wantAutomatic || wantExplicit || wantVirtual) {
register int i,bit;
xkb= XkbGetMap(inDpy,0,XkbUseCoreKbd);
if (!xkb) {
uFatalError("Couldn't read keymap\n");
return 1;
}
if (XkbGetIndicatorMap(inDpy,XkbAllIndicatorsMask,xkb)!=Success) {
uFatalError("Couldn't read indicator map\n");
return 1;
}
if (XkbGetNames(inDpy,XkbAllNamesMask,xkb)!=Success) {
uFatalError("Couldn't read indicator names\n");
return 1;
}
for (i=0,bit=1;i<XkbNumIndicators;i++,bit<<=1) {
XkbIndicatorMapPtr map= &xkb->indicators->maps[i];
if (xkb->names->indicators[i]!=None)
named|= bit;
if (xkb->indicators->phys_indicators&bit)
real|= bit;
if ((((map->which_groups!=0)&&(map->groups!=0))||
((map->which_mods!=0)&&
((map->mods.real_mods!=0)||(map->mods.vmods!=0)))||
(map->ctrls!=0))&&
((map->flags&XkbIM_NoAutomatic)==0)) {
automatic|= bit;
}
else explicit|= bit;
}
virtual= ~real;
if (wantReal==NO) real= ~real;
else if (wantReal==DONT_CARE) real= (useUnion?0:~0);
if (wantVirtual==NO) virtual= ~virtual;
else if (wantVirtual==DONT_CARE) virtual= (useUnion?0:~0);
if (wantNamed==NO) named= ~named;
else if (wantNamed==DONT_CARE) named= (useUnion?0:~0);
if (wantAutomatic==NO) automatic= ~automatic;
else if (wantAutomatic==DONT_CARE) automatic= (useUnion?0:~0);
if (wantExplicit==NO) explicit= ~explicit;
else if (wantExplicit==DONT_CARE) explicit= (useUnion?0:~0);
if (useUnion)
wanted|= real|virtual|named|automatic|explicit;
else wanted&= real&virtual&named&automatic&explicit;
}
else xkb= NULL;
if (wanted==0) {
uError("No indicator maps match the selected criteria\n");
uAction("Exiting\n");
return 1;
}
XkbSelectEvents(inDpy,XkbUseCoreKbd,XkbIndicatorStateNotifyMask,
XkbIndicatorStateNotifyMask);
XkbGetIndicatorState(inDpy,XkbUseCoreKbd,&n);
bit= (1<<(XkbNumIndicators-1));
for (i=XkbNumIndicators-1;i>=0;i--,bit>>=1) {
if (wanted&bit) {
char buf[12];
ArgList list;
sprintf(buf,"led%d",i+1);
if (n&bit) list= onArgs;
else list= offArgs;
leds[i]= XtCreateManagedWidget(buf,ledWidgetClass,panel,list,1);
}
}
XtRealizeWidget(toplevel);
while (1) {
XtAppNextEvent(app_con,&ev.core);
if (ev.core.type==evBase+XkbEventCode) {
if (ev.any.xkb_type==XkbIndicatorStateNotify) {
for (i=0,bit=1;i<XkbNumIndicators;i++,bit<<=1) {
if ((ev.indicators.changed&bit)&&(leds[i])) {
ArgList list;
if (ev.indicators.state&bit) list= onArgs;
else list= offArgs;
XtSetValues(leds[i],list,1);
}
}
}
}
else XtDispatchEvent(&ev.core);
}
if (inDpy)
XCloseDisplay(inDpy);
if (outDpy!=inDpy)
XCloseDisplay(outDpy);
inDpy= outDpy= NULL;
return 0;
}