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} };
75affd2f3fSmrg    static String 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    toplevel = XtOpenApplication(&app_con, "XkbWatch",
90b4485a66Smrg                                 options, XtNumber(options), &argc, argv,
91b4485a66Smrg                                 fallback_resources,
92b4485a66Smrg                                 sessionShellWidgetClass, NULL, ZERO);
93b4485a66Smrg    if (toplevel == NULL) {
94b4485a66Smrg        uFatalError("Couldn't create application top level\n");
95b4485a66Smrg        exit(1);
96010cdda0Smrg    }
97b4485a66Smrg    inDpy = outDpy = XtDisplay(toplevel);
98010cdda0Smrg    if (inDpy) {
99b4485a66Smrg        int i1, mn, mj;
100b4485a66Smrg
101b4485a66Smrg        mj = XkbMajorVersion;
102b4485a66Smrg        mn = XkbMinorVersion;
103b4485a66Smrg        if (!XkbQueryExtension(inDpy, &i1, &evBase, &errBase, &mj, &mn)) {
104b4485a66Smrg            uFatalError("Server doesn't support a compatible XKB\n");
105b4485a66Smrg            exit(1);
106b4485a66Smrg        }
107010cdda0Smrg    }
108b4485a66Smrg    panel =
109b4485a66Smrg        XtCreateManagedWidget("xkbwatch", boxWidgetClass, toplevel, vArgs, 1);
110b4485a66Smrg    if (panel == NULL) {
111b4485a66Smrg        uFatalError("Couldn't create top level box\n");
112b4485a66Smrg        exit(1);
113010cdda0Smrg    }
114b4485a66Smrg    baseBox = XtCreateManagedWidget("base", boxWidgetClass, panel, hArgs, 1);
115b4485a66Smrg    if (baseBox == NULL)
116b4485a66Smrg        uFatalError("Couldn't create base modifiers box\n");
117b4485a66Smrg    latchBox =
118b4485a66Smrg        XtCreateManagedWidget("latched", boxWidgetClass, panel, hArgs, 1);
119b4485a66Smrg    if (latchBox == NULL)
120b4485a66Smrg        uFatalError("Couldn't create latched modifiers box\n");
121b4485a66Smrg    lockBox = XtCreateManagedWidget("locked", boxWidgetClass, panel, hArgs, 1);
122b4485a66Smrg    if (lockBox == NULL)
123b4485a66Smrg        uFatalError("Couldn't create locked modifiers box\n");
124b4485a66Smrg    effBox =
125b4485a66Smrg        XtCreateManagedWidget("effective", boxWidgetClass, panel, hArgs, 1);
126b4485a66Smrg    if (effBox == NULL)
127b4485a66Smrg        uFatalError("Couldn't create effective modifiers box\n");
128b4485a66Smrg    compatBox =
129b4485a66Smrg        XtCreateManagedWidget("compat", boxWidgetClass, panel, hArgs, 1);
130b4485a66Smrg    if (compatBox == NULL)
131b4485a66Smrg        uFatalError("Couldn't create compatibility state box\n");
132b4485a66Smrg    XkbSelectEvents(inDpy, XkbUseCoreKbd, XkbStateNotifyMask,
133b4485a66Smrg                    XkbStateNotifyMask);
134b4485a66Smrg    XkbGetState(inDpy, XkbUseCoreKbd, &state);
135b4485a66Smrg    for (i = XkbNumModifiers - 1, bit = 0x80; i >= 0; i--, bit >>= 1) {
136b4485a66Smrg        ArgList list;
137b4485a66Smrg
138b4485a66Smrg        char buf[30];
139b4485a66Smrg
140affd2f3fSmrg        snprintf(buf, sizeof(buf), "base%d", i);
141b4485a66Smrg        if (state.base_mods & bit)
142b4485a66Smrg            list = onArgs;
143b4485a66Smrg        else
144b4485a66Smrg            list = offArgs;
145b4485a66Smrg        base[i] = XtCreateManagedWidget(buf, ledWidgetClass, baseBox, list, 1);
146affd2f3fSmrg        snprintf(buf, sizeof(buf), "latched%d", i);
147b4485a66Smrg        if (state.latched_mods & bit)
148b4485a66Smrg            list = onArgs;
149b4485a66Smrg        else
150b4485a66Smrg            list = offArgs;
151b4485a66Smrg        latched[i] =
152b4485a66Smrg            XtCreateManagedWidget(buf, ledWidgetClass, latchBox, list, 1);
153affd2f3fSmrg        snprintf(buf, sizeof(buf), "locked%d", i);
154b4485a66Smrg        if (state.locked_mods & bit)
155b4485a66Smrg            list = onArgs;
156b4485a66Smrg        else
157b4485a66Smrg            list = offArgs;
158b4485a66Smrg        locked[i] =
159b4485a66Smrg            XtCreateManagedWidget(buf, ledWidgetClass, lockBox, list, 1);
160affd2f3fSmrg        snprintf(buf, sizeof(buf), "effective%d", i);
161b4485a66Smrg        if (state.mods & bit)
162b4485a66Smrg            list = onArgs;
163b4485a66Smrg        else
164b4485a66Smrg            list = offArgs;
165b4485a66Smrg        effective[i] =
166b4485a66Smrg            XtCreateManagedWidget(buf, ledWidgetClass, effBox, list, 1);
167affd2f3fSmrg        snprintf(buf, sizeof(buf), "compat%d", i);
168b4485a66Smrg        if (state.compat_state & bit)
169b4485a66Smrg            list = onArgs;
170b4485a66Smrg        else
171b4485a66Smrg            list = offArgs;
172b4485a66Smrg        compat[i] =
173b4485a66Smrg            XtCreateManagedWidget(buf, ledWidgetClass, compatBox, list, 1);
174010cdda0Smrg    }
175010cdda0Smrg    XtRealizeWidget(toplevel);
176010cdda0Smrg    while (1) {
177b4485a66Smrg        XtAppNextEvent(app_con, &ev.core);
178b4485a66Smrg        if (ev.core.type == evBase + XkbEventCode) {
179b4485a66Smrg            if (ev.any.xkb_type == XkbStateNotify) {
180b4485a66Smrg                unsigned changed;
181b4485a66Smrg
182b4485a66Smrg                if (ev.state.changed & XkbModifierBaseMask) {
183b4485a66Smrg                    changed = ev.state.base_mods ^ state.base_mods;
184b4485a66Smrg                    state.base_mods = ev.state.base_mods;
185b4485a66Smrg                    for (i = 0, bit = 1; i < XkbNumModifiers; i++, bit <<= 1) {
186b4485a66Smrg                        if (changed & bit) {
187b4485a66Smrg                            ArgList list;
188b4485a66Smrg
189b4485a66Smrg                            if (state.base_mods & bit)
190b4485a66Smrg                                list = onArgs;
191b4485a66Smrg                            else
192b4485a66Smrg                                list = offArgs;
193b4485a66Smrg                            XtSetValues(base[i], list, 1);
194b4485a66Smrg                        }
195b4485a66Smrg                    }
196b4485a66Smrg                }
197b4485a66Smrg                if (ev.state.changed & XkbModifierLatchMask) {
198b4485a66Smrg                    changed = ev.state.latched_mods ^ state.latched_mods;
199b4485a66Smrg                    state.latched_mods = ev.state.latched_mods;
200b4485a66Smrg                    for (i = 0, bit = 1; i < XkbNumModifiers; i++, bit <<= 1) {
201b4485a66Smrg                        if (changed & bit) {
202b4485a66Smrg                            ArgList list;
203b4485a66Smrg
204b4485a66Smrg                            if (state.latched_mods & bit)
205b4485a66Smrg                                list = onArgs;
206b4485a66Smrg                            else
207b4485a66Smrg                                list = offArgs;
208b4485a66Smrg                            XtSetValues(latched[i], list, 1);
209b4485a66Smrg                        }
210b4485a66Smrg                    }
211b4485a66Smrg                }
212b4485a66Smrg                if (ev.state.changed & XkbModifierLockMask) {
213b4485a66Smrg                    changed = ev.state.locked_mods ^ state.locked_mods;
214b4485a66Smrg                    state.locked_mods = ev.state.locked_mods;
215b4485a66Smrg                    for (i = 0, bit = 1; i < XkbNumModifiers; i++, bit <<= 1) {
216b4485a66Smrg                        if (changed & bit) {
217b4485a66Smrg                            ArgList list;
218b4485a66Smrg
219b4485a66Smrg                            if (state.locked_mods & bit)
220b4485a66Smrg                                list = onArgs;
221b4485a66Smrg                            else
222b4485a66Smrg                                list = offArgs;
223b4485a66Smrg                            XtSetValues(locked[i], list, 1);
224b4485a66Smrg                        }
225b4485a66Smrg                    }
226b4485a66Smrg                }
227b4485a66Smrg                if (ev.state.changed & XkbModifierStateMask) {
228b4485a66Smrg                    changed = ev.state.mods ^ state.mods;
229b4485a66Smrg                    state.mods = ev.state.mods;
230b4485a66Smrg                    for (i = 0, bit = 1; i < XkbNumModifiers; i++, bit <<= 1) {
231b4485a66Smrg                        if (changed & bit) {
232b4485a66Smrg                            ArgList list;
233b4485a66Smrg
234b4485a66Smrg                            if (state.mods & bit)
235b4485a66Smrg                                list = onArgs;
236b4485a66Smrg                            else
237b4485a66Smrg                                list = offArgs;
238b4485a66Smrg                            XtSetValues(effective[i], list, 1);
239b4485a66Smrg                        }
240b4485a66Smrg                    }
241b4485a66Smrg                }
242b4485a66Smrg                if (ev.state.changed & XkbCompatStateMask) {
243b4485a66Smrg                    changed = ev.state.compat_state ^ state.compat_state;
244b4485a66Smrg                    state.compat_state = ev.state.compat_state;
245b4485a66Smrg                    for (i = 0, bit = 1; i < XkbNumModifiers; i++, bit <<= 1) {
246b4485a66Smrg                        if (changed & bit) {
247b4485a66Smrg                            ArgList list;
248b4485a66Smrg
249b4485a66Smrg                            if (state.compat_state & bit)
250b4485a66Smrg                                list = onArgs;
251b4485a66Smrg                            else
252b4485a66Smrg                                list = offArgs;
253b4485a66Smrg                            XtSetValues(compat[i], list, 1);
254b4485a66Smrg                        }
255b4485a66Smrg                    }
256b4485a66Smrg                }
257b4485a66Smrg            }
258b4485a66Smrg        }
259b4485a66Smrg        else
260b4485a66Smrg            XtDispatchEvent(&ev.core);
261010cdda0Smrg    }
262010cdda0Smrg/* BAIL: */
263b4485a66Smrg    if (inDpy)
264b4485a66Smrg        XCloseDisplay(inDpy);
265b4485a66Smrg    if (outDpy != inDpy)
266b4485a66Smrg        XCloseDisplay(outDpy);
267b4485a66Smrg    inDpy = outDpy = NULL;
268010cdda0Smrg    return 0;
269010cdda0Smrg}
270