xkbwatch.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
43b4485a66Smrgstatic Display *inDpy, *outDpy;
44b4485a66Smrgstatic int evBase, errBase;
45010cdda0Smrg
46010cdda0Smrg/***====================================================================***/
47010cdda0Smrg
48010cdda0Smrgstatic XrmOptionDescRec options[] = {
49b4485a66Smrg    {"-off", "*on.on", XrmoptionNoArg, "FALSE"},
50b4485a66Smrg    {"-on", "*on.on", XrmoptionNoArg, "TRUE"}
51010cdda0Smrg};
52010cdda0Smrg
53010cdda0Smrg/***====================================================================***/
54010cdda0Smrg
55010cdda0Smrgint
56010cdda0Smrgmain(int argc, char *argv[])
57010cdda0Smrg{
58b4485a66Smrg    Widget toplevel;
59b4485a66Smrg    XtAppContext app_con;
60b4485a66Smrg    Widget panel;
61b4485a66Smrg    Widget base[XkbNumModifiers];
62b4485a66Smrg    Widget latched[XkbNumModifiers];
63b4485a66Smrg    Widget locked[XkbNumModifiers];
64b4485a66Smrg    Widget effective[XkbNumModifiers];
65b4485a66Smrg    Widget compat[XkbNumModifiers];
66b4485a66Smrg    Widget baseBox, latchBox, lockBox, effBox, compatBox;
67b4485a66Smrg    register int i;
68b4485a66Smrg    unsigned bit;
69b4485a66Smrg    XkbEvent ev;
70b4485a66Smrg    XkbStateRec state;
71b4485a66Smrg    static Arg hArgs[] = { {XtNorientation, (XtArgVal) XtorientHorizontal} };
72b4485a66Smrg    static Arg vArgs[] = { {XtNorientation, (XtArgVal) XtorientVertical} };
73b4485a66Smrg    static Arg onArgs[] = { {XtNon, (XtArgVal) True} };
74b4485a66Smrg    static Arg offArgs[] = { {XtNon, (XtArgVal) False} };
75b4485a66Smrg    static char *fallback_resources[] = {
76b4485a66Smrg        "*Box*background: grey50",
77b4485a66Smrg        "*Box*borderWidth: 0",
78b4485a66Smrg        "*Box*vSpace: 1",
79b4485a66Smrg        NULL
80b4485a66Smrg    };
81b4485a66Smrg
82b4485a66Smrg    for (i = 1; i < argc; i++) {
83b4485a66Smrg        if (strcmp(argv[i], "-version") == 0) {
84b4485a66Smrg            printf("xkbwatch (%s) %s\n", PACKAGE_NAME, PACKAGE_VERSION);
85b4485a66Smrg            exit(0);
86b4485a66Smrg        }
87b4485a66Smrg    }
88010cdda0Smrg
89010cdda0Smrg    uSetErrorFile(NullString);
90010cdda0Smrg    toplevel = XtOpenApplication(&app_con, "XkbWatch",
91b4485a66Smrg                                 options, XtNumber(options), &argc, argv,
92b4485a66Smrg                                 fallback_resources,
93b4485a66Smrg                                 sessionShellWidgetClass, NULL, ZERO);
94b4485a66Smrg    if (toplevel == NULL) {
95b4485a66Smrg        uFatalError("Couldn't create application top level\n");
96b4485a66Smrg        exit(1);
97010cdda0Smrg    }
98b4485a66Smrg    inDpy = outDpy = XtDisplay(toplevel);
99010cdda0Smrg    if (inDpy) {
100b4485a66Smrg        int i1, mn, mj;
101b4485a66Smrg
102b4485a66Smrg        mj = XkbMajorVersion;
103b4485a66Smrg        mn = XkbMinorVersion;
104b4485a66Smrg        if (!XkbQueryExtension(inDpy, &i1, &evBase, &errBase, &mj, &mn)) {
105b4485a66Smrg            uFatalError("Server doesn't support a compatible XKB\n");
106b4485a66Smrg            exit(1);
107b4485a66Smrg        }
108010cdda0Smrg    }
109b4485a66Smrg    panel =
110b4485a66Smrg        XtCreateManagedWidget("xkbwatch", boxWidgetClass, toplevel, vArgs, 1);
111b4485a66Smrg    if (panel == NULL) {
112b4485a66Smrg        uFatalError("Couldn't create top level box\n");
113b4485a66Smrg        exit(1);
114010cdda0Smrg    }
115b4485a66Smrg    baseBox = XtCreateManagedWidget("base", boxWidgetClass, panel, hArgs, 1);
116b4485a66Smrg    if (baseBox == NULL)
117b4485a66Smrg        uFatalError("Couldn't create base modifiers box\n");
118b4485a66Smrg    latchBox =
119b4485a66Smrg        XtCreateManagedWidget("latched", boxWidgetClass, panel, hArgs, 1);
120b4485a66Smrg    if (latchBox == NULL)
121b4485a66Smrg        uFatalError("Couldn't create latched modifiers box\n");
122b4485a66Smrg    lockBox = XtCreateManagedWidget("locked", boxWidgetClass, panel, hArgs, 1);
123b4485a66Smrg    if (lockBox == NULL)
124b4485a66Smrg        uFatalError("Couldn't create locked modifiers box\n");
125b4485a66Smrg    effBox =
126b4485a66Smrg        XtCreateManagedWidget("effective", boxWidgetClass, panel, hArgs, 1);
127b4485a66Smrg    if (effBox == NULL)
128b4485a66Smrg        uFatalError("Couldn't create effective modifiers box\n");
129b4485a66Smrg    compatBox =
130b4485a66Smrg        XtCreateManagedWidget("compat", boxWidgetClass, panel, hArgs, 1);
131b4485a66Smrg    if (compatBox == NULL)
132b4485a66Smrg        uFatalError("Couldn't create compatibility state box\n");
133b4485a66Smrg    XkbSelectEvents(inDpy, XkbUseCoreKbd, XkbStateNotifyMask,
134b4485a66Smrg                    XkbStateNotifyMask);
135b4485a66Smrg    XkbGetState(inDpy, XkbUseCoreKbd, &state);
136b4485a66Smrg    for (i = XkbNumModifiers - 1, bit = 0x80; i >= 0; i--, bit >>= 1) {
137b4485a66Smrg        ArgList list;
138b4485a66Smrg
139b4485a66Smrg        char buf[30];
140b4485a66Smrg
141b4485a66Smrg        sprintf(buf, "base%d", i);
142b4485a66Smrg        if (state.base_mods & bit)
143b4485a66Smrg            list = onArgs;
144b4485a66Smrg        else
145b4485a66Smrg            list = offArgs;
146b4485a66Smrg        base[i] = XtCreateManagedWidget(buf, ledWidgetClass, baseBox, list, 1);
147b4485a66Smrg        sprintf(buf, "latched%d", i);
148b4485a66Smrg        if (state.latched_mods & bit)
149b4485a66Smrg            list = onArgs;
150b4485a66Smrg        else
151b4485a66Smrg            list = offArgs;
152b4485a66Smrg        latched[i] =
153b4485a66Smrg            XtCreateManagedWidget(buf, ledWidgetClass, latchBox, list, 1);
154b4485a66Smrg        sprintf(buf, "locked%d", i);
155b4485a66Smrg        if (state.locked_mods & bit)
156b4485a66Smrg            list = onArgs;
157b4485a66Smrg        else
158b4485a66Smrg            list = offArgs;
159b4485a66Smrg        locked[i] =
160b4485a66Smrg            XtCreateManagedWidget(buf, ledWidgetClass, lockBox, list, 1);
161b4485a66Smrg        sprintf(buf, "effective%d", i);
162b4485a66Smrg        if (state.mods & bit)
163b4485a66Smrg            list = onArgs;
164b4485a66Smrg        else
165b4485a66Smrg            list = offArgs;
166b4485a66Smrg        effective[i] =
167b4485a66Smrg            XtCreateManagedWidget(buf, ledWidgetClass, effBox, list, 1);
168b4485a66Smrg        sprintf(buf, "compat%d", i);
169b4485a66Smrg        if (state.compat_state & bit)
170b4485a66Smrg            list = onArgs;
171b4485a66Smrg        else
172b4485a66Smrg            list = offArgs;
173b4485a66Smrg        compat[i] =
174b4485a66Smrg            XtCreateManagedWidget(buf, ledWidgetClass, compatBox, list, 1);
175010cdda0Smrg    }
176010cdda0Smrg    XtRealizeWidget(toplevel);
177010cdda0Smrg    while (1) {
178b4485a66Smrg        XtAppNextEvent(app_con, &ev.core);
179b4485a66Smrg        if (ev.core.type == evBase + XkbEventCode) {
180b4485a66Smrg            if (ev.any.xkb_type == XkbStateNotify) {
181b4485a66Smrg                unsigned changed;
182b4485a66Smrg
183b4485a66Smrg                if (ev.state.changed & XkbModifierBaseMask) {
184b4485a66Smrg                    changed = ev.state.base_mods ^ state.base_mods;
185b4485a66Smrg                    state.base_mods = ev.state.base_mods;
186b4485a66Smrg                    for (i = 0, bit = 1; i < XkbNumModifiers; i++, bit <<= 1) {
187b4485a66Smrg                        if (changed & bit) {
188b4485a66Smrg                            ArgList list;
189b4485a66Smrg
190b4485a66Smrg                            if (state.base_mods & bit)
191b4485a66Smrg                                list = onArgs;
192b4485a66Smrg                            else
193b4485a66Smrg                                list = offArgs;
194b4485a66Smrg                            XtSetValues(base[i], list, 1);
195b4485a66Smrg                        }
196b4485a66Smrg                    }
197b4485a66Smrg                }
198b4485a66Smrg                if (ev.state.changed & XkbModifierLatchMask) {
199b4485a66Smrg                    changed = ev.state.latched_mods ^ state.latched_mods;
200b4485a66Smrg                    state.latched_mods = ev.state.latched_mods;
201b4485a66Smrg                    for (i = 0, bit = 1; i < XkbNumModifiers; i++, bit <<= 1) {
202b4485a66Smrg                        if (changed & bit) {
203b4485a66Smrg                            ArgList list;
204b4485a66Smrg
205b4485a66Smrg                            if (state.latched_mods & bit)
206b4485a66Smrg                                list = onArgs;
207b4485a66Smrg                            else
208b4485a66Smrg                                list = offArgs;
209b4485a66Smrg                            XtSetValues(latched[i], list, 1);
210b4485a66Smrg                        }
211b4485a66Smrg                    }
212b4485a66Smrg                }
213b4485a66Smrg                if (ev.state.changed & XkbModifierLockMask) {
214b4485a66Smrg                    changed = ev.state.locked_mods ^ state.locked_mods;
215b4485a66Smrg                    state.locked_mods = ev.state.locked_mods;
216b4485a66Smrg                    for (i = 0, bit = 1; i < XkbNumModifiers; i++, bit <<= 1) {
217b4485a66Smrg                        if (changed & bit) {
218b4485a66Smrg                            ArgList list;
219b4485a66Smrg
220b4485a66Smrg                            if (state.locked_mods & bit)
221b4485a66Smrg                                list = onArgs;
222b4485a66Smrg                            else
223b4485a66Smrg                                list = offArgs;
224b4485a66Smrg                            XtSetValues(locked[i], list, 1);
225b4485a66Smrg                        }
226b4485a66Smrg                    }
227b4485a66Smrg                }
228b4485a66Smrg                if (ev.state.changed & XkbModifierStateMask) {
229b4485a66Smrg                    changed = ev.state.mods ^ state.mods;
230b4485a66Smrg                    state.mods = ev.state.mods;
231b4485a66Smrg                    for (i = 0, bit = 1; i < XkbNumModifiers; i++, bit <<= 1) {
232b4485a66Smrg                        if (changed & bit) {
233b4485a66Smrg                            ArgList list;
234b4485a66Smrg
235b4485a66Smrg                            if (state.mods & bit)
236b4485a66Smrg                                list = onArgs;
237b4485a66Smrg                            else
238b4485a66Smrg                                list = offArgs;
239b4485a66Smrg                            XtSetValues(effective[i], list, 1);
240b4485a66Smrg                        }
241b4485a66Smrg                    }
242b4485a66Smrg                }
243b4485a66Smrg                if (ev.state.changed & XkbCompatStateMask) {
244b4485a66Smrg                    changed = ev.state.compat_state ^ state.compat_state;
245b4485a66Smrg                    state.compat_state = ev.state.compat_state;
246b4485a66Smrg                    for (i = 0, bit = 1; i < XkbNumModifiers; i++, bit <<= 1) {
247b4485a66Smrg                        if (changed & bit) {
248b4485a66Smrg                            ArgList list;
249b4485a66Smrg
250b4485a66Smrg                            if (state.compat_state & bit)
251b4485a66Smrg                                list = onArgs;
252b4485a66Smrg                            else
253b4485a66Smrg                                list = offArgs;
254b4485a66Smrg                            XtSetValues(compat[i], list, 1);
255b4485a66Smrg                        }
256b4485a66Smrg                    }
257b4485a66Smrg                }
258b4485a66Smrg            }
259b4485a66Smrg        }
260b4485a66Smrg        else
261b4485a66Smrg            XtDispatchEvent(&ev.core);
262010cdda0Smrg    }
263010cdda0Smrg/* BAIL: */
264b4485a66Smrg    if (inDpy)
265b4485a66Smrg        XCloseDisplay(inDpy);
266b4485a66Smrg    if (outDpy != inDpy)
267b4485a66Smrg        XCloseDisplay(outDpy);
268b4485a66Smrg    inDpy = outDpy = NULL;
269010cdda0Smrg    return 0;
270010cdda0Smrg}
271