xkbvleds.c revision b4485a66
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} }; 213b4485a66Smrg static char *fallback_resources[] = { 214b4485a66Smrg "*Box*background: grey40", 215b4485a66Smrg NULL 216b4485a66Smrg }; 217010cdda0Smrg 218010cdda0Smrg uSetErrorFile(NullString); 219b4485a66Smrg bzero(leds, XkbNumIndicators * sizeof(Widget)); 220b4485a66Smrg toplevel = XtOpenApplication(&app_con, "XkbLEDPanel", NULL, 0, &argc, argv, 221b4485a66Smrg fallback_resources, 222b4485a66Smrg sessionShellWidgetClass, NULL, ZERO); 223b4485a66Smrg if (toplevel == NULL) { 224b4485a66Smrg uFatalError("Couldn't create application top level\n"); 225b4485a66Smrg return 1; 226010cdda0Smrg } 227b4485a66Smrg if ((argc > 1) && (!parseArgs(argc, argv))) { 228b4485a66Smrg usage(argv[0]); 229b4485a66Smrg return 1; 230010cdda0Smrg } 231b4485a66Smrg if ((wanted == 0) && (wantNamed == DONT_CARE) && (wantExplicit == DONT_CARE) 232b4485a66Smrg && (wantAutomatic == DONT_CARE) && (wantReal == DONT_CARE)) { 233b4485a66Smrg wantNamed = YES; 234b4485a66Smrg wantReal = YES; 235b4485a66Smrg wantAutomatic = YES; 236010cdda0Smrg } 237b4485a66Smrg outDpy = XtDisplay(toplevel); 238b4485a66Smrg if (inDpyName != NULL) { 239b4485a66Smrg inDpy = GetDisplay(argv[0], inDpyName); 240b4485a66Smrg if (!inDpy) 241b4485a66Smrg return 1; 242010cdda0Smrg } 243010cdda0Smrg else { 244b4485a66Smrg inDpy = outDpy; 245010cdda0Smrg } 246010cdda0Smrg if (inDpy) { 247b4485a66Smrg int i1, mn, mj; 248b4485a66Smrg 249b4485a66Smrg mj = XkbMajorVersion; 250b4485a66Smrg mn = XkbMinorVersion; 251b4485a66Smrg if (!XkbLibraryVersion(&mj, &mn)) { 252b4485a66Smrg uInformation("%s was compiled with XKB version %d.%02d\n", 253b4485a66Smrg argv[0], XkbMajorVersion, XkbMinorVersion); 254b4485a66Smrg uError("X library supports incompatible version %d.%02d\n", mj, mn); 255b4485a66Smrg } 256b4485a66Smrg if (!XkbQueryExtension(inDpy, &i1, &evBase, &errBase, &mj, &mn)) { 257b4485a66Smrg uFatalError("Server doesn't support a compatible XKB\n"); 258b4485a66Smrg return 1; 259b4485a66Smrg } 260010cdda0Smrg } 261010cdda0Smrg else { 262b4485a66Smrg uFatalError("No input display\n"); 263b4485a66Smrg return 1; 264010cdda0Smrg } 265b4485a66Smrg panel = 266b4485a66Smrg XtCreateManagedWidget("xkbleds", boxWidgetClass, toplevel, boxArgs, 1); 267b4485a66Smrg if (panel == NULL) { 268b4485a66Smrg uFatalError("Couldn't create list of leds\n"); 269b4485a66Smrg return 1; 270010cdda0Smrg } 271b4485a66Smrg real = virtual = named = explicit = automatic = 0; 272010cdda0Smrg if (wantReal || wantNamed || wantAutomatic || wantExplicit || wantVirtual) { 273b4485a66Smrg register int i, bit; 274b4485a66Smrg 275b4485a66Smrg xkb = XkbGetMap(inDpy, 0, XkbUseCoreKbd); 276b4485a66Smrg if (!xkb) { 277b4485a66Smrg uFatalError("Couldn't read keymap\n"); 278b4485a66Smrg return 1; 279b4485a66Smrg } 280b4485a66Smrg if (XkbGetIndicatorMap(inDpy, XkbAllIndicatorsMask, xkb) != Success) { 281b4485a66Smrg uFatalError("Couldn't read indicator map\n"); 282b4485a66Smrg return 1; 283b4485a66Smrg } 284b4485a66Smrg if (XkbGetNames(inDpy, XkbAllNamesMask, xkb) != Success) { 285b4485a66Smrg uFatalError("Couldn't read indicator names\n"); 286b4485a66Smrg return 1; 287b4485a66Smrg } 288b4485a66Smrg for (i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) { 289b4485a66Smrg XkbIndicatorMapPtr map = &xkb->indicators->maps[i]; 290b4485a66Smrg 291b4485a66Smrg if (xkb->names->indicators[i] != None) 292b4485a66Smrg named |= bit; 293b4485a66Smrg if (xkb->indicators->phys_indicators & bit) 294b4485a66Smrg real |= bit; 295b4485a66Smrg if ((((map->which_groups != 0) && (map->groups != 0)) || 296b4485a66Smrg ((map->which_mods != 0) && 297b4485a66Smrg ((map->mods.real_mods != 0) || (map->mods.vmods != 0))) || 298b4485a66Smrg (map->ctrls != 0)) && 299b4485a66Smrg ((map->flags & XkbIM_NoAutomatic) == 0)) { 300b4485a66Smrg automatic |= bit; 301b4485a66Smrg } 302b4485a66Smrg else 303b4485a66Smrg explicit |= bit; 304b4485a66Smrg } 305b4485a66Smrg virtual = ~real; 306b4485a66Smrg if (wantReal == NO) 307b4485a66Smrg real = ~real; 308b4485a66Smrg else if (wantReal == DONT_CARE) 309b4485a66Smrg real = (useUnion ? 0 : ~0); 310b4485a66Smrg if (wantVirtual == NO) 311b4485a66Smrg virtual = ~virtual; 312b4485a66Smrg else if (wantVirtual == DONT_CARE) 313b4485a66Smrg virtual = (useUnion ? 0 : ~0); 314b4485a66Smrg if (wantNamed == NO) 315b4485a66Smrg named = ~named; 316b4485a66Smrg else if (wantNamed == DONT_CARE) 317b4485a66Smrg named = (useUnion ? 0 : ~0); 318b4485a66Smrg if (wantAutomatic == NO) 319b4485a66Smrg automatic = ~automatic; 320b4485a66Smrg else if (wantAutomatic == DONT_CARE) 321b4485a66Smrg automatic = (useUnion ? 0 : ~0); 322b4485a66Smrg if (wantExplicit == NO) 323b4485a66Smrg explicit = ~explicit; 324b4485a66Smrg else if (wantExplicit == DONT_CARE) 325b4485a66Smrg explicit = (useUnion ? 0 : ~0); 326b4485a66Smrg if (useUnion) 327b4485a66Smrg wanted |= real | virtual | named | automatic | explicit; 328b4485a66Smrg else 329b4485a66Smrg wanted &= real & virtual & named & automatic & explicit; 330010cdda0Smrg } 331b4485a66Smrg else 332b4485a66Smrg xkb = NULL; 333b4485a66Smrg if (wanted == 0) { 334b4485a66Smrg uError("No indicator maps match the selected criteria\n"); 335b4485a66Smrg uAction("Exiting\n"); 336b4485a66Smrg return 1; 337010cdda0Smrg } 338010cdda0Smrg 339b4485a66Smrg XkbSelectEvents(inDpy, XkbUseCoreKbd, XkbIndicatorStateNotifyMask, 340b4485a66Smrg XkbIndicatorStateNotifyMask); 341b4485a66Smrg XkbGetIndicatorState(inDpy, XkbUseCoreKbd, &n); 342b4485a66Smrg bit = (1U << (XkbNumIndicators - 1)); 343b4485a66Smrg for (i = XkbNumIndicators - 1; i >= 0; i--, bit >>= 1) { 344b4485a66Smrg if (wanted & bit) { 345b4485a66Smrg char buf[12]; 346b4485a66Smrg ArgList list; 347010cdda0Smrg 348b4485a66Smrg sprintf(buf, "led%d", i + 1); 349b4485a66Smrg if (n & bit) 350b4485a66Smrg list = onArgs; 351b4485a66Smrg else 352b4485a66Smrg list = offArgs; 353b4485a66Smrg leds[i] = 354b4485a66Smrg XtCreateManagedWidget(buf, ledWidgetClass, panel, list, 1); 355b4485a66Smrg } 356010cdda0Smrg } 357010cdda0Smrg XtRealizeWidget(toplevel); 358010cdda0Smrg while (1) { 359b4485a66Smrg XtAppNextEvent(app_con, &ev.core); 360b4485a66Smrg if (ev.core.type == evBase + XkbEventCode) { 361b4485a66Smrg if (ev.any.xkb_type == XkbIndicatorStateNotify) { 362b4485a66Smrg for (i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) { 363b4485a66Smrg if ((ev.indicators.changed & bit) && (leds[i])) { 364b4485a66Smrg ArgList list; 365b4485a66Smrg 366b4485a66Smrg if (ev.indicators.state & bit) 367b4485a66Smrg list = onArgs; 368b4485a66Smrg else 369b4485a66Smrg list = offArgs; 370b4485a66Smrg XtSetValues(leds[i], list, 1); 371b4485a66Smrg } 372b4485a66Smrg } 373b4485a66Smrg } 374b4485a66Smrg } 375b4485a66Smrg else 376b4485a66Smrg XtDispatchEvent(&ev.core); 377010cdda0Smrg } 378010cdda0Smrg/* BAIL: */ 379b4485a66Smrg if (inDpy) 380b4485a66Smrg XCloseDisplay(inDpy); 381b4485a66Smrg if (outDpy != inDpy) 382b4485a66Smrg XCloseDisplay(outDpy); 383b4485a66Smrg inDpy = outDpy = NULL; 384010cdda0Smrg return 0; 385010cdda0Smrg} 386