1010cdda0Smrg/************************************************************ 2010cdda0Smrg Copyright (c) 1995 by Silicon Graphics Computer Systems, Inc. 3010cdda0Smrg 4010cdda0Smrg Permission to use, copy, modify, and distribute this 5010cdda0Smrg software and its documentation for any purpose and without 6010cdda0Smrg fee is hereby granted, provided that the above copyright 7010cdda0Smrg notice appear in all copies and that both that copyright 8010cdda0Smrg notice and this permission notice appear in supporting 9010cdda0Smrg documentation, and that the name of Silicon Graphics not be 10010cdda0Smrg used in advertising or publicity pertaining to distribution 11010cdda0Smrg of the software without specific prior written permission. 12010cdda0Smrg Silicon Graphics makes no representation about the suitability 13010cdda0Smrg of this software for any purpose. It is provided "as is" 14010cdda0Smrg without any express or implied warranty. 15010cdda0Smrg 16010cdda0Smrg SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS 17010cdda0Smrg SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 18010cdda0Smrg AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON 19010cdda0Smrg GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL 20010cdda0Smrg DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 21010cdda0Smrg DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 22010cdda0Smrg OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH 23010cdda0Smrg THE USE OR PERFORMANCE OF THIS SOFTWARE. 24010cdda0Smrg 25010cdda0Smrg ********************************************************/ 26010cdda0Smrg 27010cdda0Smrg#include <stdlib.h> 28010cdda0Smrg#include <X11/X.h> 29010cdda0Smrg#include <X11/Xlib.h> 30010cdda0Smrg#include <X11/XKBlib.h> 31010cdda0Smrg#include <X11/Intrinsic.h> 32010cdda0Smrg#include <X11/StringDefs.h> 33010cdda0Smrg#include <X11/Shell.h> 34010cdda0Smrg#include <X11/Xaw/Cardinals.h> 35010cdda0Smrg#include <X11/Xaw/Box.h> 36010cdda0Smrg 37010cdda0Smrg#define BOOLEAN_DEFINED 38010cdda0Smrg#include "utils.h" 39010cdda0Smrg#include "LED.h" 40010cdda0Smrg 41010cdda0Smrg/***====================================================================***/ 42010cdda0Smrg 43010cdda0Smrg#define YES 1 44010cdda0Smrg#define NO 0 45010cdda0Smrg#define DONT_CARE -1 46010cdda0Smrg 47b4485a66Smrgstatic Display *inDpy, *outDpy; 48b4485a66Smrgstatic unsigned long wanted, real, named, explicit, automatic, virtual; 49b4485a66Smrgstatic char *inDpyName; 50b4485a66Smrgstatic int wantNamed = DONT_CARE; 51b4485a66Smrgstatic int wantExplicit = DONT_CARE; 52b4485a66Smrgstatic int wantAutomatic = DONT_CARE; 53b4485a66Smrgstatic int wantReal = DONT_CARE; 54b4485a66Smrgstatic int wantVirtual = DONT_CARE; 55b4485a66Smrgstatic int evBase, errBase; 56b4485a66Smrgstatic Bool synch; 57b4485a66Smrgstatic Bool useUnion = True; 58010cdda0Smrg 59010cdda0Smrg/***====================================================================***/ 60010cdda0Smrg 61010cdda0Smrgstatic void 62010cdda0Smrgusage(char *program) 63010cdda0Smrg{ 64b4485a66Smrg uInformation("Usage: %s <options>\n", program); 65b4485a66Smrg uInformation("Legal options include the usual X toolkit options plus:\n" 66b4485a66Smrg " -help Print this message\n" 67b4485a66Smrg " -version Print the program version\n" 68b4485a66Smrg " -indpy <name> Name of display to watch\n" 69b4485a66Smrg " -watch <leds> Mask of LEDs to watch\n" 70b4485a66Smrg " [-+]automatic (Don't) watch automatic LEDs\n" 71b4485a66Smrg " [-+]explicit (Don't) watch explicit LEDs\n" 72b4485a66Smrg " [-+]name (Don't) watch named LEDs\n" 73b4485a66Smrg " [-+]real (Don't) watch real LEDs\n" 74b4485a66Smrg " [-+]virtual (Don't) watch virtual LEDs\n" 75b4485a66Smrg " -intersection Watch only LEDs in all desired sets\n" 76b4485a66Smrg " -union Watch LEDs in any desired sets\n" 77b4485a66Smrg "The default set of LEDs is -union +name +automatic +real\n"); 78010cdda0Smrg return; 79010cdda0Smrg} 80010cdda0Smrg 81010cdda0Smrgstatic Bool 82010cdda0SmrgparseArgs(int argc, char *argv[]) 83010cdda0Smrg{ 84b4485a66Smrg register int i; 85010cdda0Smrg 86b4485a66Smrg for (i = 1; i < argc; i++) { 87b4485a66Smrg if (uStrCaseEqual(argv[i], "-indpy")) { 88b4485a66Smrg if (i < argc - 1) 89b4485a66Smrg inDpyName = argv[++i]; 90b4485a66Smrg else { 91b4485a66Smrg uWarning("No name specified for input display\n"); 92b4485a66Smrg uAction("Ignoring trailing -indpy argument\n"); 93b4485a66Smrg } 94b4485a66Smrg } 95b4485a66Smrg else if (uStrCaseEqual(argv[i], "-watch")) { 96b4485a66Smrg if (i < argc - 1) { 97b4485a66Smrg int tmp; 98b4485a66Smrg 99b4485a66Smrg if (sscanf(argv[++i], "%i", &tmp) != 1) { 100b4485a66Smrg uWarning("Set of LEDs must be specified as an integer\n"); 101b4485a66Smrg uAction("Ignoring bogus value \"%s\" for -watch flag\n", 102b4485a66Smrg argv[i]); 103b4485a66Smrg } 104b4485a66Smrg else 105b4485a66Smrg wanted = tmp; 106b4485a66Smrg } 107b4485a66Smrg else { 108b4485a66Smrg uWarning("Didn't specify any LEDs to watch\n"); 109b4485a66Smrg uAction("Ignoring trailing -watch argument\n"); 110b4485a66Smrg } 111b4485a66Smrg } 112b4485a66Smrg else if (uStrCaseEqual(argv[i], "-union")) { 113b4485a66Smrg useUnion = True; 114b4485a66Smrg } 115b4485a66Smrg else if (uStrCaseEqual(argv[i], "-intersection")) { 116b4485a66Smrg useUnion = False; 117b4485a66Smrg } 118b4485a66Smrg else if (uStrCaseEqual(argv[i], "-help")) { 119b4485a66Smrg usage(argv[0]); 120b4485a66Smrg exit(0); 121b4485a66Smrg } 122b4485a66Smrg else if (uStrCaseEqual(argv[i], "-version")) { 123b4485a66Smrg printf("xkbvleds (%s) %s\n", PACKAGE_NAME, PACKAGE_VERSION); 124b4485a66Smrg exit(0); 125b4485a66Smrg } 126b4485a66Smrg else if ((argv[i][0] == '+') || (argv[i][0] == '-')) { 127b4485a66Smrg Bool onoff; 128b4485a66Smrg int *which; 129b4485a66Smrg 130b4485a66Smrg onoff = (argv[i][0] == '+'); 131b4485a66Smrg which = NULL; 132b4485a66Smrg if (uStrCaseEqual(&argv[i][1], "name")) 133b4485a66Smrg which = &wantNamed; 134b4485a66Smrg else if (uStrCaseEqual(&argv[i][1], "explicit")) 135b4485a66Smrg which = &wantExplicit; 136b4485a66Smrg else if (uStrCaseEqual(&argv[i][1], "automatic")) 137b4485a66Smrg which = &wantAutomatic; 138b4485a66Smrg else if (uStrCaseEqual(&argv[i][1], "real")) 139b4485a66Smrg which = &wantReal; 140b4485a66Smrg else if (uStrCaseEqual(&argv[i][1], "virtual")) 141b4485a66Smrg which = &wantVirtual; 142b4485a66Smrg if (which != NULL) { 143b4485a66Smrg if (*which != DONT_CARE) { 144b4485a66Smrg uWarning("Multiple settings for [+-]%s\n", &argv[i][1]); 145b4485a66Smrg uAction("Using %c%s, ignoring %c%s\n", 146b4485a66Smrg (onoff ? '+' : '-'), &argv[i][1], 147b4485a66Smrg (onoff ? '-' : '+'), &argv[i][1]); 148b4485a66Smrg } 149b4485a66Smrg *which = (onoff ? YES : NO); 150b4485a66Smrg } 151b4485a66Smrg } 152010cdda0Smrg } 153010cdda0Smrg return True; 154010cdda0Smrg} 155010cdda0Smrg 156010cdda0Smrg/***====================================================================***/ 157010cdda0Smrg 158010cdda0Smrgstatic Display * 159010cdda0SmrgGetDisplay(char *program, char *dpyName) 160010cdda0Smrg{ 161b4485a66Smrg int mjr, mnr, error; 162b4485a66Smrg Display *dpy; 163010cdda0Smrg 164b4485a66Smrg mjr = XkbMajorVersion; 165b4485a66Smrg mnr = XkbMinorVersion; 166b4485a66Smrg dpy = XkbOpenDisplay(dpyName, &evBase, &errBase, &mjr, &mnr, &error); 167b4485a66Smrg if (dpy == NULL) { 168b4485a66Smrg switch (error) { 169b4485a66Smrg case XkbOD_BadLibraryVersion: 170b4485a66Smrg uInformation("%s was compiled with XKB version %d.%02d\n", 171b4485a66Smrg program, XkbMajorVersion, XkbMinorVersion); 172b4485a66Smrg uError("X library supports incompatible version %d.%02d\n", 173b4485a66Smrg mjr, mnr); 174b4485a66Smrg break; 175b4485a66Smrg case XkbOD_ConnectionRefused: 176b4485a66Smrg uError("Cannot open display \"%s\"\n", dpyName); 177b4485a66Smrg break; 178b4485a66Smrg case XkbOD_NonXkbServer: 179b4485a66Smrg uError("XKB extension not present on %s\n", dpyName); 180b4485a66Smrg break; 181b4485a66Smrg case XkbOD_BadServerVersion: 182b4485a66Smrg uInformation("%s was compiled with XKB version %d.%02d\n", 183b4485a66Smrg program, XkbMajorVersion, XkbMinorVersion); 184b4485a66Smrg uError("Server %s uses incompatible version %d.%02d\n", 185b4485a66Smrg dpyName, mjr, mnr); 186b4485a66Smrg break; 187b4485a66Smrg default: 188b4485a66Smrg uInternalError("Unknown error %d from XkbOpenDisplay\n", error); 189b4485a66Smrg } 190010cdda0Smrg } 191010cdda0Smrg else if (synch) 192b4485a66Smrg XSynchronize(dpy, True); 193010cdda0Smrg return dpy; 194010cdda0Smrg} 195010cdda0Smrg 196010cdda0Smrg/***====================================================================***/ 197010cdda0Smrg 198010cdda0Smrgint 199010cdda0Smrgmain(int argc, char *argv[]) 200010cdda0Smrg{ 201b4485a66Smrg Widget toplevel; 202b4485a66Smrg XtAppContext app_con; 203b4485a66Smrg Widget panel; 204b4485a66Smrg Widget leds[XkbNumIndicators]; 205b4485a66Smrg register int i; 206b4485a66Smrg unsigned bit; 207b4485a66Smrg unsigned n; 208b4485a66Smrg XkbDescPtr xkb; 209b4485a66Smrg XkbEvent ev; 210b4485a66Smrg static Arg boxArgs[] = { {XtNorientation, (XtArgVal) XtorientHorizontal} }; 211b4485a66Smrg static Arg onArgs[] = { {XtNon, (XtArgVal) True} }; 212b4485a66Smrg static Arg offArgs[] = { {XtNon, (XtArgVal) False} }; 213945aa7e3Smrg static String fallback_resources[] = { 214b4485a66Smrg "*Box*background: grey40", 215b4485a66Smrg NULL 216b4485a66Smrg }; 217010cdda0Smrg 218b4485a66Smrg bzero(leds, XkbNumIndicators * sizeof(Widget)); 219b4485a66Smrg toplevel = XtOpenApplication(&app_con, "XkbLEDPanel", NULL, 0, &argc, argv, 220b4485a66Smrg fallback_resources, 221b4485a66Smrg sessionShellWidgetClass, NULL, ZERO); 222b4485a66Smrg if (toplevel == NULL) { 223b4485a66Smrg uFatalError("Couldn't create application top level\n"); 224b4485a66Smrg return 1; 225010cdda0Smrg } 226b4485a66Smrg if ((argc > 1) && (!parseArgs(argc, argv))) { 227b4485a66Smrg usage(argv[0]); 228b4485a66Smrg return 1; 229010cdda0Smrg } 230b4485a66Smrg if ((wanted == 0) && (wantNamed == DONT_CARE) && (wantExplicit == DONT_CARE) 231b4485a66Smrg && (wantAutomatic == DONT_CARE) && (wantReal == DONT_CARE)) { 232b4485a66Smrg wantNamed = YES; 233b4485a66Smrg wantReal = YES; 234b4485a66Smrg wantAutomatic = YES; 235010cdda0Smrg } 236b4485a66Smrg outDpy = XtDisplay(toplevel); 237b4485a66Smrg if (inDpyName != NULL) { 238b4485a66Smrg inDpy = GetDisplay(argv[0], inDpyName); 239b4485a66Smrg if (!inDpy) 240b4485a66Smrg return 1; 241010cdda0Smrg } 242010cdda0Smrg else { 243b4485a66Smrg inDpy = outDpy; 244010cdda0Smrg } 245010cdda0Smrg if (inDpy) { 246b4485a66Smrg int i1, mn, mj; 247b4485a66Smrg 248b4485a66Smrg mj = XkbMajorVersion; 249b4485a66Smrg mn = XkbMinorVersion; 250b4485a66Smrg if (!XkbLibraryVersion(&mj, &mn)) { 251b4485a66Smrg uInformation("%s was compiled with XKB version %d.%02d\n", 252b4485a66Smrg argv[0], XkbMajorVersion, XkbMinorVersion); 253b4485a66Smrg uError("X library supports incompatible version %d.%02d\n", mj, mn); 254b4485a66Smrg } 255b4485a66Smrg if (!XkbQueryExtension(inDpy, &i1, &evBase, &errBase, &mj, &mn)) { 256b4485a66Smrg uFatalError("Server doesn't support a compatible XKB\n"); 257b4485a66Smrg return 1; 258b4485a66Smrg } 259010cdda0Smrg } 260010cdda0Smrg else { 261b4485a66Smrg uFatalError("No input display\n"); 262b4485a66Smrg return 1; 263010cdda0Smrg } 264b4485a66Smrg panel = 265b4485a66Smrg XtCreateManagedWidget("xkbleds", boxWidgetClass, toplevel, boxArgs, 1); 266b4485a66Smrg if (panel == NULL) { 267b4485a66Smrg uFatalError("Couldn't create list of leds\n"); 268b4485a66Smrg return 1; 269010cdda0Smrg } 270b4485a66Smrg real = virtual = named = explicit = automatic = 0; 271010cdda0Smrg if (wantReal || wantNamed || wantAutomatic || wantExplicit || wantVirtual) { 272b4485a66Smrg register int i, bit; 273b4485a66Smrg 274b4485a66Smrg xkb = XkbGetMap(inDpy, 0, XkbUseCoreKbd); 275b4485a66Smrg if (!xkb) { 276b4485a66Smrg uFatalError("Couldn't read keymap\n"); 277b4485a66Smrg return 1; 278b4485a66Smrg } 279b4485a66Smrg if (XkbGetIndicatorMap(inDpy, XkbAllIndicatorsMask, xkb) != Success) { 280b4485a66Smrg uFatalError("Couldn't read indicator map\n"); 281b4485a66Smrg return 1; 282b4485a66Smrg } 283b4485a66Smrg if (XkbGetNames(inDpy, XkbAllNamesMask, xkb) != Success) { 284b4485a66Smrg uFatalError("Couldn't read indicator names\n"); 285b4485a66Smrg return 1; 286b4485a66Smrg } 287b4485a66Smrg for (i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) { 288b4485a66Smrg XkbIndicatorMapPtr map = &xkb->indicators->maps[i]; 289b4485a66Smrg 290b4485a66Smrg if (xkb->names->indicators[i] != None) 291b4485a66Smrg named |= bit; 292b4485a66Smrg if (xkb->indicators->phys_indicators & bit) 293b4485a66Smrg real |= bit; 294b4485a66Smrg if ((((map->which_groups != 0) && (map->groups != 0)) || 295b4485a66Smrg ((map->which_mods != 0) && 296b4485a66Smrg ((map->mods.real_mods != 0) || (map->mods.vmods != 0))) || 297b4485a66Smrg (map->ctrls != 0)) && 298b4485a66Smrg ((map->flags & XkbIM_NoAutomatic) == 0)) { 299b4485a66Smrg automatic |= bit; 300b4485a66Smrg } 301b4485a66Smrg else 302b4485a66Smrg explicit |= bit; 303b4485a66Smrg } 304b4485a66Smrg virtual = ~real; 305b4485a66Smrg if (wantReal == NO) 306b4485a66Smrg real = ~real; 307b4485a66Smrg else if (wantReal == DONT_CARE) 308b4485a66Smrg real = (useUnion ? 0 : ~0); 309b4485a66Smrg if (wantVirtual == NO) 310b4485a66Smrg virtual = ~virtual; 311b4485a66Smrg else if (wantVirtual == DONT_CARE) 312b4485a66Smrg virtual = (useUnion ? 0 : ~0); 313b4485a66Smrg if (wantNamed == NO) 314b4485a66Smrg named = ~named; 315b4485a66Smrg else if (wantNamed == DONT_CARE) 316b4485a66Smrg named = (useUnion ? 0 : ~0); 317b4485a66Smrg if (wantAutomatic == NO) 318b4485a66Smrg automatic = ~automatic; 319b4485a66Smrg else if (wantAutomatic == DONT_CARE) 320b4485a66Smrg automatic = (useUnion ? 0 : ~0); 321b4485a66Smrg if (wantExplicit == NO) 322b4485a66Smrg explicit = ~explicit; 323b4485a66Smrg else if (wantExplicit == DONT_CARE) 324b4485a66Smrg explicit = (useUnion ? 0 : ~0); 325b4485a66Smrg if (useUnion) 326b4485a66Smrg wanted |= real | virtual | named | automatic | explicit; 327b4485a66Smrg else 328b4485a66Smrg wanted &= real & virtual & named & automatic & explicit; 329010cdda0Smrg } 330b4485a66Smrg else 331b4485a66Smrg xkb = NULL; 332b4485a66Smrg if (wanted == 0) { 333b4485a66Smrg uError("No indicator maps match the selected criteria\n"); 334b4485a66Smrg uAction("Exiting\n"); 335b4485a66Smrg return 1; 336010cdda0Smrg } 337010cdda0Smrg 338b4485a66Smrg XkbSelectEvents(inDpy, XkbUseCoreKbd, XkbIndicatorStateNotifyMask, 339b4485a66Smrg XkbIndicatorStateNotifyMask); 340b4485a66Smrg XkbGetIndicatorState(inDpy, XkbUseCoreKbd, &n); 341b4485a66Smrg bit = (1U << (XkbNumIndicators - 1)); 342b4485a66Smrg for (i = XkbNumIndicators - 1; i >= 0; i--, bit >>= 1) { 343b4485a66Smrg if (wanted & bit) { 344b4485a66Smrg char buf[12]; 345b4485a66Smrg ArgList list; 346010cdda0Smrg 347affd2f3fSmrg snprintf(buf, sizeof(buf), "led%d", i + 1); 348b4485a66Smrg if (n & bit) 349b4485a66Smrg list = onArgs; 350b4485a66Smrg else 351b4485a66Smrg list = offArgs; 352b4485a66Smrg leds[i] = 353b4485a66Smrg XtCreateManagedWidget(buf, ledWidgetClass, panel, list, 1); 354b4485a66Smrg } 355010cdda0Smrg } 356010cdda0Smrg XtRealizeWidget(toplevel); 357010cdda0Smrg while (1) { 358b4485a66Smrg XtAppNextEvent(app_con, &ev.core); 359b4485a66Smrg if (ev.core.type == evBase + XkbEventCode) { 360b4485a66Smrg if (ev.any.xkb_type == XkbIndicatorStateNotify) { 361b4485a66Smrg for (i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) { 362b4485a66Smrg if ((ev.indicators.changed & bit) && (leds[i])) { 363b4485a66Smrg ArgList list; 364b4485a66Smrg 365b4485a66Smrg if (ev.indicators.state & bit) 366b4485a66Smrg list = onArgs; 367b4485a66Smrg else 368b4485a66Smrg list = offArgs; 369b4485a66Smrg XtSetValues(leds[i], list, 1); 370b4485a66Smrg } 371b4485a66Smrg } 372b4485a66Smrg } 373b4485a66Smrg } 374b4485a66Smrg else 375b4485a66Smrg XtDispatchEvent(&ev.core); 376010cdda0Smrg } 377010cdda0Smrg/* BAIL: */ 378b4485a66Smrg if (inDpy) 379b4485a66Smrg XCloseDisplay(inDpy); 380b4485a66Smrg if (outDpy != inDpy) 381b4485a66Smrg XCloseDisplay(outDpy); 382b4485a66Smrg inDpy = outDpy = NULL; 383010cdda0Smrg return 0; 384010cdda0Smrg} 385