xkbvleds.c revision b3eb03f3
1/* $Xorg: xkbvleds.c,v 1.4 2000/08/17 19:54:51 cpqbld Exp $ */ 2/************************************************************ 3 Copyright (c) 1995 by Silicon Graphics Computer Systems, Inc. 4 5 Permission to use, copy, modify, and distribute this 6 software and its documentation for any purpose and without 7 fee is hereby granted, provided that the above copyright 8 notice appear in all copies and that both that copyright 9 notice and this permission notice appear in supporting 10 documentation, and that the name of Silicon Graphics not be 11 used in advertising or publicity pertaining to distribution 12 of the software without specific prior written permission. 13 Silicon Graphics makes no representation about the suitability 14 of this software for any purpose. It is provided "as is" 15 without any express or implied warranty. 16 17 SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS 18 SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 19 AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON 20 GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL 21 DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 22 DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 23 OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH 24 THE USE OR PERFORMANCE OF THIS SOFTWARE. 25 26 ********************************************************/ 27/* $XFree86: xc/programs/xkbutils/xkbvleds.c,v 3.4 2001/01/17 23:46:14 dawes Exp $ */ 28 29#include <stdlib.h> 30#include <X11/X.h> 31#include <X11/Xlib.h> 32#include <X11/XKBlib.h> 33#include <X11/Intrinsic.h> 34#include <X11/StringDefs.h> 35#include <X11/Shell.h> 36#include <X11/Xaw/Cardinals.h> 37#include <X11/Xaw/Box.h> 38 39#define OPAQUE_DEFINED 40#define BOOLEAN_DEFINED 41#define DEBUG_VAR_NOT_LOCAL 42#define DEBUG_VAR debugFlags 43#include "utils.h" 44#include "LED.h" 45 46/***====================================================================***/ 47 48#define YES 1 49#define NO 0 50#define DONT_CARE -1 51 52static Display * inDpy,*outDpy; 53static unsigned long wanted,real,named,explicit,automatic,virtual; 54static char * inDpyName; 55static int wantNamed= DONT_CARE; 56static int wantExplicit= DONT_CARE; 57static int wantAutomatic= DONT_CARE; 58static int wantReal= DONT_CARE; 59static int wantVirtual= DONT_CARE; 60static int evBase,errBase; 61static Bool synch; 62static Bool useUnion= True; 63 64/***====================================================================***/ 65 66static void 67usage(char *program) 68{ 69 uInformation("Usage: %s <options>\n",program); 70 uInformation("Legal options include the usual X toolkit options plus:\n"); 71 uInformation(" -help Print this message\n"); 72 uInformation(" -indpy <name> Name of display to watch\n"); 73 uInformation(" -watch <leds> Mask of LEDs to watch\n"); 74 uInformation(" [-+]automatic (Don't) watch automatic LEDs\n"); 75 uInformation(" [-+]explicit (Don't) watch explicit LEDs\n"); 76 uInformation(" [-+]name (Don't) watch named LEDs\n"); 77 uInformation(" [-+]real (Don't) watch real LEDs\n"); 78 uInformation(" [-+]virtual (Don't) watch virtual LEDs\n"); 79 uInformation(" -intersection Watch only LEDs in all desired sets\n"); 80 uInformation(" -union Watch LEDs in any desired sets\n"); 81 uInformation("The default set of LEDs is -union +name +automatic +real\n"); 82 return; 83} 84 85static Bool 86parseArgs(int argc, char *argv[]) 87{ 88register int i; 89 90 for (i=1;i<argc;i++) { 91 if (uStrCaseEqual(argv[i],"-indpy")) { 92 if (i<argc-1) inDpyName= argv[++i]; 93 else { 94 uWarning("No name specified for input display\n"); 95 uAction("Ignoring trailing -indpy argument\n"); 96 } 97 } 98 else if (uStrCaseEqual(argv[i],"-watch")) { 99 if (i<argc-1) { 100 int tmp; 101 if (sscanf(argv[++i],"%i",&tmp)!=1) { 102 uWarning("Set of LEDs must be specified as an integer\n"); 103 uAction("Ignoring bogus value \"%s\" for -watch flag\n", 104 argv[i]); 105 } 106 else wanted= tmp; 107 } 108 else { 109 uWarning("Didn't specify any LEDs to watch\n"); 110 uAction("Ignoring trailing -watch argument\n"); 111 } 112 } 113 else if (uStrCaseEqual(argv[i],"-union")) { 114 useUnion= True; 115 } 116 else if (uStrCaseEqual(argv[i],"-intersection")) { 117 useUnion= False; 118 } 119 else if (uStrCaseEqual(argv[i],"-help")) { 120 usage(argv[0]); 121 exit(0); 122 } 123 else if ((argv[i][0]=='+')||(argv[i][0]=='-')) { 124 Bool onoff; 125 int * which; 126 onoff= (argv[i][0]=='+'); 127 which= NULL; 128 if (uStrCaseEqual(&argv[i][1],"name")) 129 which= &wantNamed; 130 else if (uStrCaseEqual(&argv[i][1],"explicit")) 131 which= &wantExplicit; 132 else if (uStrCaseEqual(&argv[i][1],"automatic")) 133 which= &wantAutomatic; 134 else if (uStrCaseEqual(&argv[i][1],"real")) 135 which= &wantReal; 136 else if (uStrCaseEqual(&argv[i][1],"virtual")) 137 which= &wantVirtual; 138 if (which!=NULL) { 139 if (*which!=DONT_CARE) { 140 uWarning("Multiple settings for [+-]%s\n",&argv[i][1]); 141 uAction("Using %c%s, ignoring %c%s\n", 142 (onoff?'+':'-'),&argv[i][1], 143 (onoff?'-':'+'),&argv[i][1]); 144 } 145 *which= (onoff?YES:NO); 146 } 147 } 148 } 149 return True; 150} 151 152/***====================================================================***/ 153 154static Display * 155GetDisplay(char *program, char *dpyName) 156{ 157int mjr,mnr,error; 158Display * dpy; 159 160 mjr= XkbMajorVersion; 161 mnr= XkbMinorVersion; 162 dpy= XkbOpenDisplay(dpyName,&evBase,&errBase,&mjr,&mnr,&error); 163 if (dpy==NULL) { 164 switch (error) { 165 case XkbOD_BadLibraryVersion: 166 uInformation("%s was compiled with XKB version %d.%02d\n", 167 program,XkbMajorVersion,XkbMinorVersion); 168 uError("X library supports incompatible version %d.%02d\n", 169 mjr,mnr); 170 break; 171 case XkbOD_ConnectionRefused: 172 uError("Cannot open display \"%s\"\n",dpyName); 173 break; 174 case XkbOD_NonXkbServer: 175 uError("XKB extension not present on %s\n",dpyName); 176 break; 177 case XkbOD_BadServerVersion: 178 uInformation("%s was compiled with XKB version %d.%02d\n", 179 program,XkbMajorVersion,XkbMinorVersion); 180 uError("Server %s uses incompatible version %d.%02d\n", 181 dpyName,mjr,mnr); 182 break; 183 default: 184 uInternalError("Unknown error %d from XkbOpenDisplay\n",error); 185 } 186 } 187 else if (synch) 188 XSynchronize(dpy,True); 189 return dpy; 190} 191 192/***====================================================================***/ 193 194int 195main(int argc, char *argv[]) 196{ 197Widget toplevel; 198XtAppContext app_con; 199Widget panel; 200Widget leds[XkbNumIndicators]; 201register int i; 202unsigned bit; 203unsigned n; 204XkbDescPtr xkb; 205XkbEvent ev; 206static Arg boxArgs[]= {{ XtNorientation, (XtArgVal)XtorientHorizontal }}; 207static Arg onArgs[]= {{ XtNon, (XtArgVal)True }}; 208static Arg offArgs[]= {{ XtNon, (XtArgVal)False }}; 209static char * fallback_resources[] = { 210 "*Box*background: grey40", 211 NULL 212}; 213 214 uSetEntryFile(NullString); 215 uSetDebugFile(NullString); 216 uSetErrorFile(NullString); 217 bzero(leds,XkbNumIndicators*sizeof(Widget)); 218 toplevel = XtOpenApplication(&app_con, "XkbLEDPanel", NULL, 0, &argc, argv, 219 fallback_resources, 220 sessionShellWidgetClass, NULL, ZERO); 221 if (toplevel==NULL) { 222 uFatalError("Couldn't create application top level\n"); 223 return 1; 224 } 225 if ((argc>1)&&(!parseArgs(argc,argv))) { 226 usage(argv[0]); 227 return 1; 228 } 229 if ((wanted==0)&&(wantNamed==DONT_CARE)&&(wantExplicit==DONT_CARE)&& 230 (wantAutomatic==DONT_CARE)&&(wantReal==DONT_CARE)) { 231 wantNamed= YES; 232 wantReal= YES; 233 wantAutomatic= YES; 234 } 235 outDpy= XtDisplay(toplevel); 236 if (inDpyName!=NULL) { 237 inDpy= GetDisplay(argv[0],inDpyName); 238 if (!inDpy) 239 return 1; 240 } 241 else { 242 inDpy= outDpy; 243 } 244 if (inDpy) { 245 int i1,mn,mj; 246 mj= XkbMajorVersion; 247 mn= XkbMinorVersion; 248 if (!XkbLibraryVersion(&mj,&mn)) { 249 uInformation("%s was compiled with XKB version %d.%02d\n", 250 argv[0],XkbMajorVersion,XkbMinorVersion); 251 uError("X library supports incompatible version %d.%02d\n", 252 mj,mn); 253 } 254 if (!XkbQueryExtension(inDpy,&i1,&evBase,&errBase,&mj,&mn)) { 255 uFatalError("Server doesn't support a compatible XKB\n"); 256 return 1; 257 } 258 } 259 else { 260 uFatalError("No input display\n"); 261 return 1; 262 } 263 panel= XtCreateManagedWidget("xkbleds",boxWidgetClass,toplevel,boxArgs,1); 264 if (panel==NULL) { 265 uFatalError("Couldn't create list of leds\n"); 266 return 1; 267 } 268 real= virtual= named= explicit= automatic= 0; 269 if (wantReal || wantNamed || wantAutomatic || wantExplicit || wantVirtual) { 270 register int i,bit; 271 xkb= XkbGetMap(inDpy,0,XkbUseCoreKbd); 272 if (!xkb) { 273 uFatalError("Couldn't read keymap\n"); 274 return 1; 275 } 276 if (XkbGetIndicatorMap(inDpy,XkbAllIndicatorsMask,xkb)!=Success) { 277 uFatalError("Couldn't read indicator map\n"); 278 return 1; 279 } 280 if (XkbGetNames(inDpy,XkbAllNamesMask,xkb)!=Success) { 281 uFatalError("Couldn't read indicator names\n"); 282 return 1; 283 } 284 for (i=0,bit=1;i<XkbNumIndicators;i++,bit<<=1) { 285 XkbIndicatorMapPtr map= &xkb->indicators->maps[i]; 286 if (xkb->names->indicators[i]!=None) 287 named|= bit; 288 if (xkb->indicators->phys_indicators&bit) 289 real|= bit; 290 if ((((map->which_groups!=0)&&(map->groups!=0))|| 291 ((map->which_mods!=0)&& 292 ((map->mods.real_mods!=0)||(map->mods.vmods!=0)))|| 293 (map->ctrls!=0))&& 294 ((map->flags&XkbIM_NoAutomatic)==0)) { 295 automatic|= bit; 296 } 297 else explicit|= bit; 298 } 299 virtual= ~real; 300 if (wantReal==NO) real= ~real; 301 else if (wantReal==DONT_CARE) real= (useUnion?0:~0); 302 if (wantVirtual==NO) virtual= ~virtual; 303 else if (wantVirtual==DONT_CARE) virtual= (useUnion?0:~0); 304 if (wantNamed==NO) named= ~named; 305 else if (wantNamed==DONT_CARE) named= (useUnion?0:~0); 306 if (wantAutomatic==NO) automatic= ~automatic; 307 else if (wantAutomatic==DONT_CARE) automatic= (useUnion?0:~0); 308 if (wantExplicit==NO) explicit= ~explicit; 309 else if (wantExplicit==DONT_CARE) explicit= (useUnion?0:~0); 310 if (useUnion) 311 wanted|= real|virtual|named|automatic|explicit; 312 else wanted&= real&virtual&named&automatic&explicit; 313 } 314 else xkb= NULL; 315 if (wanted==0) { 316 uError("No indicator maps match the selected criteria\n"); 317 uAction("Exiting\n"); 318 return 1; 319 } 320 321 XkbSelectEvents(inDpy,XkbUseCoreKbd,XkbIndicatorStateNotifyMask, 322 XkbIndicatorStateNotifyMask); 323 XkbGetIndicatorState(inDpy,XkbUseCoreKbd,&n); 324 bit= (1<<(XkbNumIndicators-1)); 325 for (i=XkbNumIndicators-1;i>=0;i--,bit>>=1) { 326 if (wanted&bit) { 327 char buf[12]; 328 ArgList list; 329 330 sprintf(buf,"led%d",i+1); 331 if (n&bit) list= onArgs; 332 else list= offArgs; 333 leds[i]= XtCreateManagedWidget(buf,ledWidgetClass,panel,list,1); 334 } 335 } 336 XtRealizeWidget(toplevel); 337 while (1) { 338 XtAppNextEvent(app_con,&ev.core); 339 if (ev.core.type==evBase+XkbEventCode) { 340 if (ev.any.xkb_type==XkbIndicatorStateNotify) { 341 for (i=0,bit=1;i<XkbNumIndicators;i++,bit<<=1) { 342 if ((ev.indicators.changed&bit)&&(leds[i])) { 343 ArgList list; 344 if (ev.indicators.state&bit) list= onArgs; 345 else list= offArgs; 346 XtSetValues(leds[i],list,1); 347 } 348 } 349 } 350 } 351 else XtDispatchEvent(&ev.core); 352 } 353/* BAIL: */ 354 if (inDpy) 355 XCloseDisplay(inDpy); 356 if (outDpy!=inDpy) 357 XCloseDisplay(outDpy); 358 inDpy= outDpy= NULL; 359 return 0; 360} 361