Add missing U to unicode keysym in symbols/us intl-unicode
[xorg/xkeyboard-config] / tests / mxkbledpanel / mxkbledpanel.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <X11/Xlib.h>
4 #include <X11/Intrinsic.h>
5 #include <X11/XKBlib.h>
6 #include <Xm/MainW.h>
7 #include <Xm/RowColumn.h>
8 #include <Xm/ToggleB.h>
9
10 Display         *theDisplay;
11 XtAppContext    appContext;
12 int             xkbEventBase;
13 Widget          topLevel;
14 Widget          leds[XkbNumIndicators];
15 Atom            ledAtoms[XkbNumIndicators];
16 XmString        ledNames[XkbNumIndicators];
17 XkbDescPtr      xkb_desc;
18
19 void            valueChangedProc(Widget,XtPointer,XmToggleButtonCallbackStruct *);
20 XtCallbackRec   valueChangedCB[2]={(XtCallbackProc)valueChangedProc,NULL};
21
22 /************************************************************************/
23 /*                                                                      */
24 /* Application Resources                                                */
25 /*                                                                      */
26 /************************************************************************/
27 #define YES             1
28 #define NO              0
29 #define DONT_CARE       -1
30
31 typedef struct 
32 {
33     int         wanted;
34     int         wantAutomatic;
35     int         wantExplicit;
36     int         wantNamed;
37     int         wantReal;
38     int         wantVirtual;
39     int         useUnion;
40 } OptionsRec;
41
42 OptionsRec options;
43
44 #define Offset(field) XtOffsetOf(OptionsRec,field)
45 XtResource resources[] = 
46 {
47     {"wanted", "Wanted", XtRInt, sizeof(int),
48      Offset(wanted), XtRImmediate, (XtPointer) DONT_CARE },
49     {"wantAutomatic", "WantAutomatic", XtRInt, sizeof(int),
50      Offset(wantAutomatic), XtRImmediate, (XtPointer)   DONT_CARE},
51     {"wantExplicit", "WantExplicit", XtRInt, sizeof(int),
52      Offset(wantExplicit), XtRImmediate, (XtPointer)    DONT_CARE},
53     {"wantNamed", "WantNamed", XtRInt, sizeof(int),
54      Offset(wantNamed), XtRImmediate, (XtPointer)       DONT_CARE},
55     {"wantReal", "WantReal", XtRInt, sizeof(int),
56      Offset(wantReal), XtRImmediate, (XtPointer)        DONT_CARE},
57     {"wantVirtual", "WantVirtual", XtRInt, sizeof(int),
58      Offset(wantVirtual), XtRImmediate, (XtPointer)     DONT_CARE},
59     {"useUnion", "UseUnion", XtRInt, sizeof(int),
60      Offset(useUnion), XtRImmediate, (XtPointer)        YES},
61     NULL
62 };
63 #undef Offset
64
65 String fallbackResources[] = 
66 {
67     "*mainWindow.width: 100",
68     "*mainWindow.height: 50",
69     NULL
70 };
71
72 XrmOptionDescRec optionDesc[] = 
73 {
74     {"-watch", "*wanted", XrmoptionSepArg, (XtPointer) "0"},
75     {"-automatic", "*wantAutomatic", XrmoptionNoArg, (XtPointer) "0"},
76     {"+automatic", "*wantAutomatic", XrmoptionNoArg, (XtPointer) "1"},
77     {"-explicit", "*wantExplicit", XrmoptionNoArg, (XtPointer) "0"},
78     {"+explicit", "*wantExplicit", XrmoptionNoArg, (XtPointer) "1"},
79     {"-named", "*wantNamed", XrmoptionNoArg, (XtPointer) "0"},
80     {"+named", "*wantNamed", XrmoptionNoArg, (XtPointer) "1"},
81     {"-real", "*wantReal", XrmoptionNoArg, (XtPointer) "0"},
82     {"+real", "*wantReal", XrmoptionNoArg, (XtPointer) "1"},
83     {"-virtual", "*wantVirtual", XrmoptionNoArg, (XtPointer) "0"},
84     {"+virtual", "*wantVirtual", XrmoptionNoArg, (XtPointer) "1"},
85     {"-intersection", "*useUnion", XrmoptionNoArg, (XtPointer) "0"},
86     {"-union", "*useUnion", XrmoptionNoArg, (XtPointer) "1"}
87 };
88
89 /************************************************************************/
90 /*                                                                      */
91 /* usage                                                                */
92 /*                                                                      */
93 /************************************************************************/
94 void usage(char *program)
95 {
96     printf("Usage: %s <options>\n",program);
97     printf("Legal options include the usual X toolkit options plus:\n");
98     printf("  -help           Print this message\n");
99     printf("  -indpy <name>   Name of display to watch\n");
100     printf("  -watch <leds>   Mask of LEDs to watch\n");
101     printf("  [-+]automatic   (Don't) watch automatic LEDs\n");
102     printf("  [-+]explicit    (Don't) watch explicit LEDs\n");
103     printf("  [-+]named       (Don't) watch named LEDs\n");
104     printf("  [-+]real        (Don't) watch real LEDs\n");
105     printf("  [-+]virtual     (Don't) watch virtual LEDs\n");
106     printf("  -intersection   Watch only LEDs in all desired sets\n");
107     printf("  -union          Watch LEDs in any desired sets\n");
108     printf("The default set of LEDs is -intersection +named +virtual\n");
109     return;
110 }
111 /************************************************************************/
112 /*                                                                      */
113 /*  XkbEventHandler                                                     */
114 /*                                                                      */
115 /*  DESCRIPTION:                                                        */
116 /*                                                                      */
117 /*      Handles events generated by the Xkb server extension.           */
118 /*                                                                      */
119 /************************************************************************/
120 Boolean XkbEventHandler(XEvent *event)
121 {
122     XkbEvent            *xkbEv = (XkbEvent *) event;
123     
124     if (xkbEv->any.xkb_type==XkbIndicatorStateNotify)  {
125         register int            i;
126         register unsigned       bit;
127         for (i=0,bit=1;i<XkbNumIndicators;i++,bit<<=1)
128             if ((xkbEv->indicators.changed&bit)&&(leds[i])) 
129             {
130                 if (xkbEv->indicators.state&bit)
131                     XmToggleButtonSetState(leds[i],True,False);
132                 else
133                     XmToggleButtonSetState(leds[i],False,False);
134             }
135     }
136     else if (xkbEv->any.xkb_type==XkbIndicatorMapNotify) {
137             unsigned change= xkbEv->indicators.changed;
138
139             if (XkbGetIndicatorMap(theDisplay,change,xkb_desc)!=Success) 
140                 fprintf(stderr,"Couldn't get changed indicator maps\n");
141     }
142       
143     return True;
144     
145 } /* XkbEventHandler */
146
147 /************************************************************************/
148 /*                                                                      */
149 /* InitXkb                                                              */
150 /*                                                                      */
151 /************************************************************************/
152 Boolean InitXkb(Display *theDisplay)
153 {
154     int                 i,opcode,errorBase,major,minor;
155     XkbDescPtr          xkb;
156     unsigned int        bit;
157     unsigned int        real,virtual,named,explicit,automatic;
158     char                *name;
159
160     if (!XkbQueryExtension(theDisplay,
161                            &opcode,
162                            &xkbEventBase,
163                            &errorBase,
164                            &major,
165                            &minor))
166         return False;
167
168     if (!XkbUseExtension(theDisplay,&major,&minor))
169         return False;
170
171     XkbSelectEvents(theDisplay,
172                     XkbUseCoreKbd,
173                     XkbIndicatorStateNotifyMask|XkbIndicatorMapNotifyMask,
174                     XkbIndicatorStateNotifyMask|XkbIndicatorMapNotifyMask);
175
176     XtSetEventDispatcher(theDisplay,
177                          xkbEventBase+XkbEventCode,
178                          XkbEventHandler);
179
180     xkb=XkbGetMap(theDisplay,0,XkbUseCoreKbd);
181     real=virtual=named=explicit=automatic=0;
182
183     if (!xkb) 
184     {
185         fprintf(stderr,"Couldn't get keymap\n");
186         return False;
187     }
188     if (XkbGetIndicatorMap(theDisplay,XkbAllIndicatorsMask,xkb)!=Success) 
189     {
190         fprintf(stderr,"Couldn't read indicator map\n");
191         XkbFreeKeyboard(xkb,XkbAllComponentsMask,True);
192         return False;
193     }
194     real=virtual=named=explicit=automatic=0;
195
196     if (XkbGetNames(theDisplay,XkbIndicatorNamesMask,xkb)!=Success) 
197     {
198         fprintf(stderr,"Couldn't read indicator names\n");
199         XkbFreeKeyboard(xkb,XkbAllComponentsMask,True);
200         return False;
201     }
202     real=virtual=named=explicit=automatic=0;
203
204     for (i=0,bit=1;i<XkbNumIndicators;i++,bit<<=1) 
205     {
206         XkbIndicatorMapPtr map= &xkb->indicators->maps[i];
207         name = NULL;
208         if (xkb->names->indicators[i]!=None)
209         {
210             named|= bit;
211             name = XGetAtomName(theDisplay,xkb->names->indicators[i]);
212         }
213         if (name != NULL)
214         {
215             ledAtoms[i] = xkb->names->indicators[i];
216             ledNames[i] = XmStringCreate(name,XmSTRING_DEFAULT_CHARSET);
217         }
218         else
219         {
220             char temp[12];      
221             sprintf(temp,"led%d\0",i+1);
222             ledAtoms[i] = None;
223             ledNames[i] = XmStringCreate(temp,XmSTRING_DEFAULT_CHARSET);
224         }
225         if (xkb->indicators->phys_indicators&bit)
226             real|= bit;
227         if ((((map->which_groups!=0)&&(map->groups!=0))||
228              ((map->which_mods!=0)&&
229                         ((map->mods.real_mods!=0)||(map->mods.vmods!=0)))||
230              (map->ctrls!=0))&&
231             ((map->flags&XkbIM_NoAutomatic)==0)) {
232             automatic|= bit;
233         }
234         else explicit|= bit;
235     }
236
237     virtual = ~real;
238
239     if (options.useUnion)
240     {
241         if ((options.wantReal==NO)      || (options.wantReal==DONT_CARE))
242             real = 0;
243         if ((options.wantVirtual==NO)   || (options.wantVirtual==DONT_CARE))
244             virtual = 0;
245         if ((options.wantNamed==NO)     || (options.wantNamed==DONT_CARE))
246             named = 0;
247         if ((options.wantAutomatic==NO) || (options.wantAutomatic==DONT_CARE))
248             automatic = 0;
249         if ((options.wantExplicit==NO)  || (options.wantExplicit==DONT_CARE))
250             explicit = 0;
251
252         options.wanted |= real|virtual|named|automatic|explicit;
253     } 
254     else 
255     {
256         if (options.wanted == DONT_CARE)
257             options.wanted = ~0;
258
259         if (options.wantReal==NO)
260             real = ~real;
261         else if (options.wantReal==DONT_CARE)
262             real = ~0;
263
264         if (options.wantVirtual==NO)
265             virtual = ~virtual;
266         else if (options.wantVirtual==DONT_CARE)
267             virtual = ~0;
268
269         if (options.wantNamed==NO)
270             named = ~named;
271         else if (options.wantNamed==DONT_CARE)
272             named = ~0;
273
274         if (options.wantAutomatic==NO)
275             automatic = ~automatic;
276         else if (options.wantAutomatic==DONT_CARE)
277             automatic = ~0;
278
279         if (options.wantExplicit==NO)
280             explicit = ~explicit;
281         else if (options.wantExplicit==DONT_CARE)
282             explicit = ~0;
283
284         options.wanted &= real&virtual&named&automatic&explicit;
285     }
286
287     XkbFreeKeyboard(xkb,XkbAllComponentsMask,True);
288     return True;
289     
290 } /* InitXkb */
291
292 /************************************************************************/
293 /*                                                                      */
294 /* valueChangedProc - called when a toggle button is pressed.           */
295 /*                                                                      */
296 /************************************************************************/
297 void valueChangedProc(Widget                            w, 
298                       XtPointer                         clientData, 
299                       XmToggleButtonCallbackStruct      *callbackData)
300 {
301     int                 led = (int) clientData;
302     XkbDescPtr          xkb;
303
304     xkb = XkbGetMap(theDisplay,0,XkbUseCoreKbd);
305     if (!xkb)
306     {
307         fprintf(stderr,"XkbGetMap failed\n");
308         return;
309     }
310     
311     if (XkbGetIndicatorMap(theDisplay,XkbAllIndicatorsMask,xkb)!=Success)
312     {
313         fprintf(stderr,"GetIndicatorMap failed\n");
314         XkbFreeKeyboard(xkb,XkbAllComponentsMask,True);
315         return;
316     }
317
318     /* The 'flags' field tells whether this indicator is automatic
319      * (XkbIM_NoExplicit - 0x80), explicit (XkbIM_NoAutomatic - 0x40),
320      * or neither (both - 0xC0).
321      *
322      * If NoAutomatic is set, the server ignores the rest of the 
323      * fields in the indicator map (i.e. it disables automatic control 
324      * of the LED).   If NoExplicit is set, the server prevents clients 
325      * from explicitly changing the value of the LED (using the core 
326      * protocol *or* XKB).   If NoAutomatic *and* NoExplicit are set, 
327      * the LED cannot be changed (unless you change the map first).   
328      * If neither NoAutomatic nor NoExplicit are set, the server will 
329      * change the LED according to the indicator map, but clients can 
330      * override that (until the next automatic change) using the core 
331      * protocol or XKB.
332      */
333     switch (xkb->indicators->maps[led].flags &
334             (XkbIM_NoExplicit|XkbIM_NoAutomatic)) 
335     {
336         case XkbIM_NoExplicit|XkbIM_NoAutomatic:
337         {
338             XmToggleButtonSetState(w,!callbackData->set,FALSE);
339             XkbFreeKeyboard(xkb,XkbAllComponentsMask,True);
340             return;
341         }
342
343         case XkbIM_NoAutomatic:
344         {
345             if (ledAtoms[led] != None)
346                 XkbSetNamedIndicator(theDisplay,XkbUseCoreKbd,
347                                      ledAtoms[led],callbackData->set,
348                                      FALSE,NULL);
349             else
350             {
351                 XKeyboardControl        xkc;
352                 xkc.led= led;
353                 if (callbackData->set)
354                      xkc.led_mode= LedModeOn;
355                 else xkc.led_mode= LedModeOff;
356                 XChangeKeyboardControl(theDisplay,KBLed|KBLedMode,&xkc);
357                 XSync(theDisplay,0);
358             }
359
360             XkbFreeKeyboard(xkb,XkbAllComponentsMask,True);
361             return;
362         }
363         
364         case XkbIM_NoExplicit:
365         break;
366     }
367     
368     /* The 'ctrls' field tells what controls tell this indicator to
369      * to turn on:  RepeatKeys (0x1), SlowKeys (0x2), BounceKeys (0x4),
370      *              StickyKeys (0x8), MouseKeys (0x10), AccessXKeys (0x20),
371      *              TimeOut (0x40), Feedback (0x80), ToggleKeys (0x100),
372      *              Overlay1 (0x200), Overlay2 (0x400), GroupsWrap (0x800),
373      *              InternalMods (0x1000), IgnoreLockMods (0x2000),
374      *              PerKeyRepeat (0x3000), or ControlsEnabled (0x4000)
375      */
376     if (xkb->indicators->maps[led].ctrls)
377     {
378         unsigned long which = xkb->indicators->maps[led].ctrls;
379
380         XkbGetControls(theDisplay,XkbAllControlsMask,xkb);
381         if (callbackData->set)
382             xkb->ctrls->enabled_ctrls |= which;
383         else
384             xkb->ctrls->enabled_ctrls &= ~which;
385         XkbSetControls(theDisplay,which|XkbControlsEnabledMask,xkb);
386     }
387     
388     /* The 'which_groups' field tells when this indicator turns on
389      * for the 'groups' field:  base (0x1), latched (0x2), locked (0x4),
390      *                          or effective (0x8).
391      */
392     if (xkb->indicators->maps[led].groups)
393     {
394         int             i;
395         unsigned int    group = 1;
396
397         /* Turning on a group indicator is kind of tricky.  For
398          * now, we will just Latch or Lock the first group we find
399          * if that is what this indicator does.  Otherwise, we're
400          * just going to punt and get out of here.
401          */
402         if (callbackData->set)
403         {
404             for (i = XkbNumKbdGroups-1; i >= 0; i--)
405                 if ((1 << i) & 
406                     xkb->indicators->maps[led].groups)
407                     group = i;
408             if (xkb->indicators->maps[led].which_groups &
409                 (XkbIM_UseLocked | XkbIM_UseEffective))
410                 XkbLockGroup(theDisplay,XkbUseCoreKbd,group);
411             else if (xkb->indicators->maps[led].which_groups&XkbIM_UseLatched)
412                 XkbLatchGroup(theDisplay,XkbUseCoreKbd,group);
413             else
414             {
415                 XmToggleButtonSetState(w,!callbackData->set,FALSE);
416                 XkbFreeKeyboard(xkb,XkbAllComponentsMask,True);
417                 return;
418             }
419         }
420         /* Turning off a group indicator will mean that we just
421          * Lock the first group that this indicator doesn't watch.
422          */
423         else
424         {
425             for (i = XkbNumKbdGroups-1; i >= 0; i--)
426                 if (!((1 << i) & 
427                       xkb->indicators->maps[led].groups))
428                     group = i;
429             XkbLockGroup(theDisplay,XkbUseCoreKbd,group);
430         }
431     }
432     
433     /* The 'which_mods' field tells when this indicator turns on
434      * for the modifiers:  base (0x1), latched (0x2), locked (0x4),
435      *                     or effective (0x8).
436      *
437      * The 'real_mods' field tells whether this turns on when one of 
438      * the real X modifiers is set:  Shift (0x1), Lock (0x2), Control (0x4),
439      * Mod1 (0x8), Mod2 (0x10), Mod3 (0x20), Mod4 (0x40), or Mod5 (0x80). 
440      *
441      * The 'virtual_mods' field tells whether this turns on when one of
442      * the virtual modifiers is set.
443      *
444      * The 'mask' field tells what real X modifiers the virtual_modifiers
445      * map to?
446      */
447     if (xkb->indicators->maps[led].mods.real_mods ||
448         xkb->indicators->maps[led].mods.mask)
449     {
450         XkbStateRec     state;
451         unsigned int    affect,mods;
452         
453         affect = (xkb->indicators->maps[led].mods.real_mods |
454                   xkb->indicators->maps[led].mods.mask);
455         
456         if (callbackData->set)
457             mods = affect;
458         else
459             mods = 0;
460         
461         if (xkb->indicators->maps[led].which_mods &
462             (XkbIM_UseLocked | XkbIM_UseEffective))
463             XkbLockModifiers(theDisplay,XkbUseCoreKbd,affect,mods);
464         else if (xkb->indicators->maps[led].which_mods &
465                  XkbIM_UseLatched)
466             XkbLatchModifiers(theDisplay,XkbUseCoreKbd,affect,mods);
467         else
468         {
469             XmToggleButtonSetState(w,!callbackData->set,FALSE);
470             XkbFreeKeyboard(xkb,XkbAllComponentsMask,True);
471             return;
472         }
473     }
474
475     XkbFreeKeyboard(xkb,XkbAllComponentsMask,True);
476
477 } /* valueChangedProc */
478
479 /************************************************************************/
480 /*                                                                      */
481 /* InitializeUI                                                         */
482 /*                                                                      */
483 /************************************************************************/
484 void InitializeUI(Widget topLevel)
485 {
486     Arg                 argList[3];
487     char                buf[256];
488     int                 i;
489     unsigned int        bit,n;
490     Widget              mainWindow,rowColumn;
491     XmString            tempString;
492
493     mainWindow = (Widget) XmCreateMainWindow(topLevel,"mainWindow",NULL,0);
494     XtManageChild(mainWindow);
495     rowColumn  = (Widget) XmCreateRowColumn(mainWindow,"rowColumn",NULL,0);
496     XtManageChild(rowColumn);
497
498     XkbGetIndicatorState(theDisplay,XkbUseCoreKbd,&n);
499     for (i=0,bit=1;i<XkbNumIndicators;i++,bit<<=1) 
500     {
501         if (options.wanted&bit) 
502         {
503             /* [[[ WDW - If we wanted to be really fancy, we
504              *     would look for a "*ledxx.labelString" value
505              *     in the resource database so the I18N dudes
506              *     can see localized strings. ]]]
507              */
508             XtSetArg(argList[0], XmNlabelString,ledNames[i]);
509             if (n&bit) XtSetArg(argList[1], XmNset, True);
510             else       XtSetArg(argList[1], XmNset, False);
511             sprintf(buf,"led%d\0",i);
512             valueChangedCB[0].closure = (XtPointer) i;
513             XtSetArg(argList[2], XmNvalueChangedCallback, valueChangedCB);
514             leds[i]= XmCreateToggleButton(rowColumn,buf,argList,3);
515             XtManageChild(leds[i]);
516         }
517         else        
518             leds[i]=0;
519     }
520
521 } /* InitializeUI */
522
523 /************************************************************************/
524 /*                                                                      */
525 /* main                                                                 */
526 /*                                                                      */
527 /************************************************************************/
528 #if NeedFunctionPrototypes
529 int main(int    argc, 
530           char  *argv[])
531 #else
532 int main(argc, argv)
533     int         argc;
534     char        *argv[];
535 #endif
536 {
537     /********************************************************************/
538     /*                                                                  */
539     /* Initialize the toolkit                                           */
540     /*                                                                  */
541     /********************************************************************/
542     Arg argList[2];
543     topLevel = XtAppInitialize(&appContext, "xkbleds", 
544                                optionDesc, XtNumber(optionDesc), 
545                                &argc, argv, 
546                                fallbackResources,
547                                NULL, 0);
548     XtSetArg(argList[0], XtNallowShellResize, TRUE);
549     XtSetValues(topLevel,argList,1);
550     XtGetApplicationResources(topLevel, (XtPointer)&options, resources,
551                               XtNumber(resources), NULL, 0);
552
553     if (argc > 1)
554     {
555         usage(argv[0]);
556         exit(0);
557     }
558
559     /* Defaults
560      */
561     if ((options.wanted == DONT_CARE) &&
562         (options.wantReal == DONT_CARE) &&
563         (options.wantVirtual == DONT_CARE) &&
564         (options.wantNamed == DONT_CARE) &&
565         (options.wantAutomatic == DONT_CARE) &&
566         (options.wantExplicit == DONT_CARE) &&
567         (options.useUnion == YES))
568     {
569         options.wanted          = 0;
570         options.wantReal        = YES;
571         options.wantNamed       = YES;
572         options.wantAutomatic   = YES;
573     }
574
575     /********************************************************************/
576     /*                                                                  */
577     /* See if the server has XKB.                                       */
578     /*                                                                  */
579     /********************************************************************/
580     theDisplay = XtDisplay(topLevel);
581     if (!InitXkb(theDisplay))
582     {
583         fprintf(stderr,"Could not initialize XKB extension.\n");
584         exit(0);
585     }
586
587     if (options.wanted == 0)
588     {
589         fprintf(stderr,"No LED's were selected.\n\n");
590         usage(argv[0]);
591         exit(0);
592     }
593
594     /********************************************************************/
595     /*                                                                  */
596     /* Set up the UI and go.                                            */
597     /*                                                                  */
598     /********************************************************************/
599     XtRealizeWidget(topLevel);
600     InitializeUI(topLevel);
601     XtAppMainLoop(appContext);
602     
603     /* NOT REACHED */
604     exit(0L);
605 }