xkeyboard-config (1.8-2) tests/mxkbledpanel/mxkbledpanel.c

Summary

 tests/mxkbledpanel/mxkbledpanel.c |  605 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 605 insertions(+)

    
download this patch

Patch contents

--- xkeyboard-config-1.8.orig/tests/mxkbledpanel/mxkbledpanel.c
+++ xkeyboard-config-1.8/tests/mxkbledpanel/mxkbledpanel.c
@@ -0,0 +1,605 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <X11/Xlib.h>
+#include <X11/Intrinsic.h>
+#include <X11/XKBlib.h>
+#include <Xm/MainW.h>
+#include <Xm/RowColumn.h>
+#include <Xm/ToggleB.h>
+
+Display         *theDisplay;
+XtAppContext    appContext;
+int		xkbEventBase;
+Widget		topLevel;
+Widget		leds[XkbNumIndicators];
+Atom		ledAtoms[XkbNumIndicators];
+XmString	ledNames[XkbNumIndicators];
+XkbDescPtr	xkb_desc;
+
+void            valueChangedProc(Widget,XtPointer,XmToggleButtonCallbackStruct *);
+XtCallbackRec   valueChangedCB[2]={(XtCallbackProc)valueChangedProc,NULL};
+
+/************************************************************************/
+/*									*/
+/* Application Resources						*/
+/*									*/
+/************************************************************************/
+#define	YES		1
+#define	NO		0
+#define	DONT_CARE	-1
+
+typedef struct 
+{
+    int		wanted;
+    int		wantAutomatic;
+    int		wantExplicit;
+    int		wantNamed;
+    int		wantReal;
+    int		wantVirtual;
+    int		useUnion;
+} OptionsRec;
+
+OptionsRec options;
+
+#define Offset(field) XtOffsetOf(OptionsRec,field)
+XtResource resources[] = 
+{
+    {"wanted", "Wanted", XtRInt, sizeof(int),
+     Offset(wanted), XtRImmediate, (XtPointer) DONT_CARE },
+    {"wantAutomatic", "WantAutomatic", XtRInt, sizeof(int),
+     Offset(wantAutomatic), XtRImmediate, (XtPointer)   DONT_CARE},
+    {"wantExplicit", "WantExplicit", XtRInt, sizeof(int),
+     Offset(wantExplicit), XtRImmediate, (XtPointer)    DONT_CARE},
+    {"wantNamed", "WantNamed", XtRInt, sizeof(int),
+     Offset(wantNamed), XtRImmediate, (XtPointer)       DONT_CARE},
+    {"wantReal", "WantReal", XtRInt, sizeof(int),
+     Offset(wantReal), XtRImmediate, (XtPointer)        DONT_CARE},
+    {"wantVirtual", "WantVirtual", XtRInt, sizeof(int),
+     Offset(wantVirtual), XtRImmediate, (XtPointer)     DONT_CARE},
+    {"useUnion", "UseUnion", XtRInt, sizeof(int),
+     Offset(useUnion), XtRImmediate, (XtPointer)        YES},
+    NULL
+};
+#undef Offset
+
+String fallbackResources[] = 
+{
+    "*mainWindow.width: 100",
+    "*mainWindow.height: 50",
+    NULL
+};
+
+XrmOptionDescRec optionDesc[] = 
+{
+    {"-watch", "*wanted", XrmoptionSepArg, (XtPointer) "0"},
+    {"-automatic", "*wantAutomatic", XrmoptionNoArg, (XtPointer) "0"},
+    {"+automatic", "*wantAutomatic", XrmoptionNoArg, (XtPointer) "1"},
+    {"-explicit", "*wantExplicit", XrmoptionNoArg, (XtPointer) "0"},
+    {"+explicit", "*wantExplicit", XrmoptionNoArg, (XtPointer) "1"},
+    {"-named", "*wantNamed", XrmoptionNoArg, (XtPointer) "0"},
+    {"+named", "*wantNamed", XrmoptionNoArg, (XtPointer) "1"},
+    {"-real", "*wantReal", XrmoptionNoArg, (XtPointer) "0"},
+    {"+real", "*wantReal", XrmoptionNoArg, (XtPointer) "1"},
+    {"-virtual", "*wantVirtual", XrmoptionNoArg, (XtPointer) "0"},
+    {"+virtual", "*wantVirtual", XrmoptionNoArg, (XtPointer) "1"},
+    {"-intersection", "*useUnion", XrmoptionNoArg, (XtPointer) "0"},
+    {"-union", "*useUnion", XrmoptionNoArg, (XtPointer) "1"}
+};
+
+/************************************************************************/
+/*									*/
+/* usage								*/
+/*									*/
+/************************************************************************/
+void usage(char *program)
+{
+    printf("Usage: %s <options>\n",program);
+    printf("Legal options include the usual X toolkit options plus:\n");
+    printf("  -help           Print this message\n");
+    printf("  -indpy <name>   Name of display to watch\n");
+    printf("  -watch <leds>   Mask of LEDs to watch\n");
+    printf("  [-+]automatic   (Don't) watch automatic LEDs\n");
+    printf("  [-+]explicit    (Don't) watch explicit LEDs\n");
+    printf("  [-+]named       (Don't) watch named LEDs\n");
+    printf("  [-+]real        (Don't) watch real LEDs\n");
+    printf("  [-+]virtual     (Don't) watch virtual LEDs\n");
+    printf("  -intersection   Watch only LEDs in all desired sets\n");
+    printf("  -union          Watch LEDs in any desired sets\n");
+    printf("The default set of LEDs is -intersection +named +virtual\n");
+    return;
+}
+/************************************************************************/
+/*									*/
+/*  XkbEventHandler	 						*/
+/*									*/
+/*  DESCRIPTION:							*/
+/*									*/
+/*      Handles events generated by the Xkb server extension.		*/
+/*									*/
+/************************************************************************/
+Boolean XkbEventHandler(XEvent *event)
+{
+    XkbEvent 		*xkbEv = (XkbEvent *) event;
+    
+    if (xkbEv->any.xkb_type==XkbIndicatorStateNotify)  {
+	register int 		i;
+	register unsigned	bit;
+	for (i=0,bit=1;i<XkbNumIndicators;i++,bit<<=1)
+	    if ((xkbEv->indicators.changed&bit)&&(leds[i])) 
+	    {
+		if (xkbEv->indicators.state&bit)
+		    XmToggleButtonSetState(leds[i],True,False);
+		else
+		    XmToggleButtonSetState(leds[i],False,False);
+	    }
+    }
+    else if (xkbEv->any.xkb_type==XkbIndicatorMapNotify) {
+	    unsigned change= xkbEv->indicators.changed;
+
+	    if (XkbGetIndicatorMap(theDisplay,change,xkb_desc)!=Success) 
+		fprintf(stderr,"Couldn't get changed indicator maps\n");
+    }
+      
+    return True;
+    
+} /* XkbEventHandler */
+
+/************************************************************************/
+/*									*/
+/* InitXkb								*/
+/*									*/
+/************************************************************************/
+Boolean InitXkb(Display *theDisplay)
+{
+    int			i,opcode,errorBase,major,minor;
+    XkbDescPtr 		xkb;
+    unsigned int	bit;
+    unsigned int	real,virtual,named,explicit,automatic;
+    char 		*name;
+
+    if (!XkbQueryExtension(theDisplay,
+			   &opcode,
+			   &xkbEventBase,
+			   &errorBase,
+			   &major,
+			   &minor))
+	return False;
+
+    if (!XkbUseExtension(theDisplay,&major,&minor))
+	return False;
+
+    XkbSelectEvents(theDisplay,
+		    XkbUseCoreKbd,
+		    XkbIndicatorStateNotifyMask|XkbIndicatorMapNotifyMask,
+		    XkbIndicatorStateNotifyMask|XkbIndicatorMapNotifyMask);
+
+    XtSetEventDispatcher(theDisplay,
+			 xkbEventBase+XkbEventCode,
+			 XkbEventHandler);
+
+    xkb=XkbGetMap(theDisplay,0,XkbUseCoreKbd);
+    real=virtual=named=explicit=automatic=0;
+
+    if (!xkb) 
+    {
+	fprintf(stderr,"Couldn't get keymap\n");
+	return False;
+    }
+    if (XkbGetIndicatorMap(theDisplay,XkbAllIndicatorsMask,xkb)!=Success) 
+    {
+	fprintf(stderr,"Couldn't read indicator map\n");
+	XkbFreeKeyboard(xkb,XkbAllComponentsMask,True);
+	return False;
+    }
+    real=virtual=named=explicit=automatic=0;
+
+    if (XkbGetNames(theDisplay,XkbIndicatorNamesMask,xkb)!=Success) 
+    {
+	fprintf(stderr,"Couldn't read indicator names\n");
+	XkbFreeKeyboard(xkb,XkbAllComponentsMask,True);
+	return False;
+    }
+    real=virtual=named=explicit=automatic=0;
+
+    for (i=0,bit=1;i<XkbNumIndicators;i++,bit<<=1) 
+    {
+	XkbIndicatorMapPtr map= &xkb->indicators->maps[i];
+	name = NULL;
+	if (xkb->names->indicators[i]!=None)
+	{
+	    named|= bit;
+	    name = XGetAtomName(theDisplay,xkb->names->indicators[i]);
+	}
+	if (name != NULL)
+        {
+	    ledAtoms[i] = xkb->names->indicators[i];
+	    ledNames[i] = XmStringCreate(name,XmSTRING_DEFAULT_CHARSET);
+	}
+	else
+	{
+	    char temp[12];	
+	    sprintf(temp,"led%d\0",i+1);
+	    ledAtoms[i] = None;
+	    ledNames[i] = XmStringCreate(temp,XmSTRING_DEFAULT_CHARSET);
+	}
+	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 (options.useUnion)
+    {
+        if ((options.wantReal==NO)      || (options.wantReal==DONT_CARE))
+	    real = 0;
+        if ((options.wantVirtual==NO)   || (options.wantVirtual==DONT_CARE))
+	    virtual = 0;
+        if ((options.wantNamed==NO)     || (options.wantNamed==DONT_CARE))
+	    named = 0;
+        if ((options.wantAutomatic==NO) || (options.wantAutomatic==DONT_CARE))
+	    automatic = 0;
+        if ((options.wantExplicit==NO)  || (options.wantExplicit==DONT_CARE))
+	    explicit = 0;
+
+	options.wanted |= real|virtual|named|automatic|explicit;
+    } 
+    else 
+    {
+	if (options.wanted == DONT_CARE)
+	    options.wanted = ~0;
+
+        if (options.wantReal==NO)
+	    real = ~real;
+	else if (options.wantReal==DONT_CARE)
+	    real = ~0;
+
+        if (options.wantVirtual==NO)
+	    virtual = ~virtual;
+        else if (options.wantVirtual==DONT_CARE)
+	    virtual = ~0;
+
+        if (options.wantNamed==NO)
+	    named = ~named;
+        else if (options.wantNamed==DONT_CARE)
+	    named = ~0;
+
+        if (options.wantAutomatic==NO)
+	    automatic = ~automatic;
+        else if (options.wantAutomatic==DONT_CARE)
+	    automatic = ~0;
+
+        if (options.wantExplicit==NO)
+	    explicit = ~explicit;
+        else if (options.wantExplicit==DONT_CARE)
+	    explicit = ~0;
+
+        options.wanted &= real&virtual&named&automatic&explicit;
+    }
+
+    XkbFreeKeyboard(xkb,XkbAllComponentsMask,True);
+    return True;
+    
+} /* InitXkb */
+
+/************************************************************************/
+/*                                                                      */
+/* valueChangedProc - called when a toggle button is pressed.           */
+/*                                                                      */
+/************************************************************************/
+void valueChangedProc(Widget                    	w, 
+                      XtPointer                 	clientData, 
+                      XmToggleButtonCallbackStruct      *callbackData)
+{
+    int         	led = (int) clientData;
+    XkbDescPtr		xkb;
+
+    xkb = XkbGetMap(theDisplay,0,XkbUseCoreKbd);
+    if (!xkb)
+    {
+	fprintf(stderr,"XkbGetMap failed\n");
+        return;
+    }
+    
+    if (XkbGetIndicatorMap(theDisplay,XkbAllIndicatorsMask,xkb)!=Success)
+    {
+	fprintf(stderr,"GetIndicatorMap failed\n");
+	XkbFreeKeyboard(xkb,XkbAllComponentsMask,True);
+	return;
+    }
+
+    /* The 'flags' field tells whether this indicator is automatic
+     * (XkbIM_NoExplicit - 0x80), explicit (XkbIM_NoAutomatic - 0x40),
+     * or neither (both - 0xC0).
+     *
+     * If NoAutomatic is set, the server ignores the rest of the 
+     * fields in the indicator map (i.e. it disables automatic control 
+     * of the LED).   If NoExplicit is set, the server prevents clients 
+     * from explicitly changing the value of the LED (using the core 
+     * protocol *or* XKB).   If NoAutomatic *and* NoExplicit are set, 
+     * the LED cannot be changed (unless you change the map first).   
+     * If neither NoAutomatic nor NoExplicit are set, the server will 
+     * change the LED according to the indicator map, but clients can 
+     * override that (until the next automatic change) using the core 
+     * protocol or XKB.
+     */
+    switch (xkb->indicators->maps[led].flags &
+	    (XkbIM_NoExplicit|XkbIM_NoAutomatic)) 
+    {
+	case XkbIM_NoExplicit|XkbIM_NoAutomatic:
+	{
+	    XmToggleButtonSetState(w,!callbackData->set,FALSE);
+	    XkbFreeKeyboard(xkb,XkbAllComponentsMask,True);
+	    return;
+	}
+
+	case XkbIM_NoAutomatic:
+	{
+	    if (ledAtoms[led] != None)
+		XkbSetNamedIndicator(theDisplay,XkbUseCoreKbd,
+				     ledAtoms[led],callbackData->set,
+				     FALSE,NULL);
+	    else
+	    {
+		XKeyboardControl	xkc;
+		xkc.led= led;
+		if (callbackData->set)
+		     xkc.led_mode= LedModeOn;
+		else xkc.led_mode= LedModeOff;
+		XChangeKeyboardControl(theDisplay,KBLed|KBLedMode,&xkc);
+		XSync(theDisplay,0);
+	    }
+
+	    XkbFreeKeyboard(xkb,XkbAllComponentsMask,True);
+	    return;
+	}
+	
+	case XkbIM_NoExplicit:
+	break;
+    }
+    
+    /* The 'ctrls' field tells what controls tell this indicator to
+     * to turn on:  RepeatKeys (0x1), SlowKeys (0x2), BounceKeys (0x4),
+     *              StickyKeys (0x8), MouseKeys (0x10), AccessXKeys (0x20),
+     *		    TimeOut (0x40), Feedback (0x80), ToggleKeys (0x100),
+     *		    Overlay1 (0x200), Overlay2 (0x400), GroupsWrap (0x800),
+     *		    InternalMods (0x1000), IgnoreLockMods (0x2000),
+     *		    PerKeyRepeat (0x3000), or ControlsEnabled (0x4000)
+     */
+    if (xkb->indicators->maps[led].ctrls)
+    {
+	unsigned long which = xkb->indicators->maps[led].ctrls;
+
+	XkbGetControls(theDisplay,XkbAllControlsMask,xkb);
+	if (callbackData->set)
+	    xkb->ctrls->enabled_ctrls |= which;
+	else
+	    xkb->ctrls->enabled_ctrls &= ~which;
+	XkbSetControls(theDisplay,which|XkbControlsEnabledMask,xkb);
+    }
+    
+    /* The 'which_groups' field tells when this indicator turns on
+     * for the 'groups' field:  base (0x1), latched (0x2), locked (0x4),
+     *                          or effective (0x8).
+     */
+    if (xkb->indicators->maps[led].groups)
+    {
+	int		i;
+       	unsigned int	group = 1;
+
+	/* Turning on a group indicator is kind of tricky.  For
+	 * now, we will just Latch or Lock the first group we find
+	 * if that is what this indicator does.  Otherwise, we're
+	 * just going to punt and get out of here.
+	 */
+	if (callbackData->set)
+	{
+	    for (i = XkbNumKbdGroups-1; i >= 0; i--)
+		if ((1 << i) & 
+		    xkb->indicators->maps[led].groups)
+		    group = i;
+	    if (xkb->indicators->maps[led].which_groups &
+		(XkbIM_UseLocked | XkbIM_UseEffective))
+		XkbLockGroup(theDisplay,XkbUseCoreKbd,group);
+	    else if (xkb->indicators->maps[led].which_groups&XkbIM_UseLatched)
+		XkbLatchGroup(theDisplay,XkbUseCoreKbd,group);
+	    else
+	    {
+		XmToggleButtonSetState(w,!callbackData->set,FALSE);
+		XkbFreeKeyboard(xkb,XkbAllComponentsMask,True);
+		return;
+	    }
+	}
+	/* Turning off a group indicator will mean that we just
+	 * Lock the first group that this indicator doesn't watch.
+	 */
+	else
+	{
+	    for (i = XkbNumKbdGroups-1; i >= 0; i--)
+		if (!((1 << i) & 
+		      xkb->indicators->maps[led].groups))
+		    group = i;
+	    XkbLockGroup(theDisplay,XkbUseCoreKbd,group);
+	}
+    }
+    
+    /* The 'which_mods' field tells when this indicator turns on
+     * for the modifiers:  base (0x1), latched (0x2), locked (0x4),
+     *                     or effective (0x8).
+     *
+     * The 'real_mods' field tells whether this turns on when one of 
+     * the real X modifiers is set:  Shift (0x1), Lock (0x2), Control (0x4),
+     * Mod1 (0x8), Mod2 (0x10), Mod3 (0x20), Mod4 (0x40), or Mod5 (0x80). 
+     *
+     * The 'virtual_mods' field tells whether this turns on when one of
+     * the virtual modifiers is set.
+     *
+     * The 'mask' field tells what real X modifiers the virtual_modifiers
+     * map to?
+     */
+    if (xkb->indicators->maps[led].mods.real_mods ||
+	xkb->indicators->maps[led].mods.mask)
+    {
+	XkbStateRec 	state;
+	unsigned int	affect,mods;
+	
+	affect = (xkb->indicators->maps[led].mods.real_mods |
+		  xkb->indicators->maps[led].mods.mask);
+	
+	if (callbackData->set)
+	    mods = affect;
+	else
+	    mods = 0;
+	
+	if (xkb->indicators->maps[led].which_mods &
+	    (XkbIM_UseLocked | XkbIM_UseEffective))
+	    XkbLockModifiers(theDisplay,XkbUseCoreKbd,affect,mods);
+	else if (xkb->indicators->maps[led].which_mods &
+		 XkbIM_UseLatched)
+	    XkbLatchModifiers(theDisplay,XkbUseCoreKbd,affect,mods);
+	else
+	{
+	    XmToggleButtonSetState(w,!callbackData->set,FALSE);
+	    XkbFreeKeyboard(xkb,XkbAllComponentsMask,True);
+	    return;
+	}
+    }
+
+    XkbFreeKeyboard(xkb,XkbAllComponentsMask,True);
+
+} /* valueChangedProc */
+
+/************************************************************************/
+/*									*/
+/* InitializeUI								*/
+/*									*/
+/************************************************************************/
+void InitializeUI(Widget topLevel)
+{
+    Arg 		argList[3];
+    char 		buf[256];
+    int 		i;
+    unsigned int	bit,n;
+    Widget 		mainWindow,rowColumn;
+    XmString		tempString;
+
+    mainWindow = (Widget) XmCreateMainWindow(topLevel,"mainWindow",NULL,0);
+    XtManageChild(mainWindow);
+    rowColumn  = (Widget) XmCreateRowColumn(mainWindow,"rowColumn",NULL,0);
+    XtManageChild(rowColumn);
+
+    XkbGetIndicatorState(theDisplay,XkbUseCoreKbd,&n);
+    for (i=0,bit=1;i<XkbNumIndicators;i++,bit<<=1) 
+    {
+	if (options.wanted&bit) 
+	{
+            /* [[[ WDW - If we wanted to be really fancy, we
+	     *     would look for a "*ledxx.labelString" value
+	     *     in the resource database so the I18N dudes
+	     *	   can see localized strings. ]]]
+	     */
+	    XtSetArg(argList[0], XmNlabelString,ledNames[i]);
+	    if (n&bit) XtSetArg(argList[1], XmNset, True);
+	    else       XtSetArg(argList[1], XmNset, False);
+	    sprintf(buf,"led%d\0",i);
+            valueChangedCB[0].closure = (XtPointer) i;
+	    XtSetArg(argList[2], XmNvalueChangedCallback, valueChangedCB);
+	    leds[i]= XmCreateToggleButton(rowColumn,buf,argList,3);
+	    XtManageChild(leds[i]);
+	}
+	else	    
+	    leds[i]=0;
+    }
+
+} /* InitializeUI */
+
+/************************************************************************/
+/*									*/
+/* main									*/
+/*									*/
+/************************************************************************/
+#if NeedFunctionPrototypes
+int main(int	argc, 
+	  char	*argv[])
+#else
+int main(argc, argv)
+    int		argc;
+    char	*argv[];
+#endif
+{
+    /********************************************************************/
+    /*									*/
+    /* Initialize the toolkit 						*/
+    /*									*/
+    /********************************************************************/
+    Arg argList[2];
+    topLevel = XtAppInitialize(&appContext, "xkbleds", 
+			       optionDesc, XtNumber(optionDesc), 
+			       &argc, argv, 
+			       fallbackResources,
+			       NULL, 0);
+    XtSetArg(argList[0], XtNallowShellResize, TRUE);
+    XtSetValues(topLevel,argList,1);
+    XtGetApplicationResources(topLevel, (XtPointer)&options, resources,
+			      XtNumber(resources), NULL, 0);
+
+    if (argc > 1)
+    {
+	usage(argv[0]);
+	exit(0);
+    }
+
+    /* Defaults
+     */
+    if ((options.wanted == DONT_CARE) &&
+	(options.wantReal == DONT_CARE) &&
+	(options.wantVirtual == DONT_CARE) &&
+	(options.wantNamed == DONT_CARE) &&
+	(options.wantAutomatic == DONT_CARE) &&
+	(options.wantExplicit == DONT_CARE) &&
+	(options.useUnion == YES))
+    {
+	options.wanted 		= 0;
+	options.wantReal	= YES;
+	options.wantNamed 	= YES;
+	options.wantAutomatic	= YES;
+    }
+
+    /********************************************************************/
+    /*									*/
+    /* See if the server has XKB.					*/
+    /*									*/
+    /********************************************************************/
+    theDisplay = XtDisplay(topLevel);
+    if (!InitXkb(theDisplay))
+    {
+	fprintf(stderr,"Could not initialize XKB extension.\n");
+	exit(0);
+    }
+
+    if (options.wanted == 0)
+    {
+	fprintf(stderr,"No LED's were selected.\n\n");
+	usage(argv[0]);
+	exit(0);
+    }
+
+    /********************************************************************/
+    /*									*/
+    /* Set up the UI and go.						*/
+    /*									*/
+    /********************************************************************/
+    XtRealizeWidget(topLevel);
+    InitializeUI(topLevel);
+    XtAppMainLoop(appContext);
+    
+    /* NOT REACHED */
+    exit(0L);
+}