1/************************************************************
2 Copyright (c) 1995 by Silicon Graphics Computer Systems, Inc.
3
4 Permission to use, copy, modify, and distribute this
5 software and its documentation for any purpose and without
6 fee is hereby granted, provided that the above copyright
7 notice appear in all copies and that both that copyright
8 notice and this permission notice appear in supporting
9 documentation, and that the name of Silicon Graphics not be
10 used in advertising or publicity pertaining to distribution
11 of the software without specific prior written permission.
12 Silicon Graphics makes no representation about the suitability
13 of this software for any purpose. It is provided "as is"
14 without any express or implied warranty.
15
16 SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
17 SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
18 AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
19 GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
20 DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
21 DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
22 OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
23 THE USE OR PERFORMANCE OF THIS SOFTWARE.
24
25 ********************************************************/
26
27#include "xkbevd.h"
28#include <X11/Xutil.h>
29
30#define	Yes	"yes"
31#define	No	"no"
32#define	Unknown	"unknown"
33#define	ynText(v)	((v)?Yes:No)
34
35static const char *
36eventTypeToString(int evType)
37{
38    switch (evType) {
39    case KeyPress:
40        return "KeyPress";
41        break;
42    case KeyRelease:
43        return "KeyRelease";
44        break;
45    default:
46        return "unknown";
47        break;
48    }
49}
50
51static void
52xkb_prologue(FILE *file, XkbEvent *ev, const char *name)
53{
54    XkbAnyEvent *e = &ev->any;
55
56    fprintf(file,
57            "\n%s event, serial %ld, synthetic %s, device %d, time %ld,\n",
58            name, e->serial, ynText(e->send_event), e->device, e->time);
59    return;
60}
61
62static void
63do_XkbStateNotify(FILE *file, XkbEvent *xkbev)
64{
65    XkbStateNotifyEvent *state = &xkbev->state;
66
67    if (state->keycode != 0)
68        fprintf(file, "    keycode %d, eventType %s,\n",
69                state->keycode, eventTypeToString(state->event_type));
70    else
71        fprintf(file, "    request %d/%d,\n", state->req_minor,
72                state->req_minor);
73    fprintf(file, "    group= %d%s, base= %d%s, latched= %d%s, locked= %d%s,\n",
74            state->group, (state->changed & XkbGroupStateMask ? "*" : ""),
75            state->base_group, (state->changed & XkbGroupBaseMask ? "*" : ""),
76            state->latched_group,
77            (state->changed & XkbGroupLatchMask ? "*" : ""),
78            state->locked_group,
79            (state->changed & XkbGroupLockMask ? "*" : ""));
80    fprintf(file,
81    "    mods= 0x%02x%s, base= 0x%02x%s, latched= 0x%02x%s, locked= 0x%02x%s\n",
82            state->mods, (state->changed & XkbModifierStateMask ? "*" : ""),
83            state->base_mods, (state->changed & XkbModifierBaseMask ? "*" : ""),
84            state->latched_mods,
85            (state->changed & XkbModifierLatchMask ? "*" : ""),
86            state->locked_mods,
87            (state->changed & XkbModifierLockMask ? "*" : ""));
88    fprintf(file, "    grab mods= 0x%02x%s, compat grab mods= 0x%02x%s\n",
89            state->grab_mods, (state->changed & XkbGrabModsMask ? "*" : ""),
90            state->compat_grab_mods,
91            (state->changed & XkbCompatGrabModsMask ? "*" : ""));
92    fprintf(file, "    lookup mods= 0x%02x%s, compat lookup mods= 0x%02x%s\n",
93            state->lookup_mods, (state->changed & XkbLookupModsMask ? "*" : ""),
94            state->compat_lookup_mods,
95            (state->changed & XkbCompatLookupModsMask ? "*" : ""));
96    fprintf(file, "    compatState = 0x%02x%s, ", state->compat_state,
97            (state->changed & XkbCompatStateMask ? "*" : ""));
98    fprintf(file, "ptr_buttons= 0x%04x%s\n", state->ptr_buttons,
99            (state->changed & XkbPointerButtonMask ? "*" : ""));
100    return;
101}
102
103static void
104do_map_message(const char *what, int first, int num, int eol)
105{
106    if (num > 1)
107        printf("%ss %d..%d changed%s", what, first, first + num - 1,
108               (eol ? "\n" : ""));
109    else
110        printf("%s %d changed%s", what, first, (eol ? "\n" : ""));
111}
112
113static void
114do_XkbMapNotify(FILE *file, XkbEvent *xkbev)
115{
116    XkbMapNotifyEvent *map = &xkbev->map;
117
118    if (map->changed & XkbKeyTypesMask) {
119        do_map_message("key type", map->first_type, map->num_types, 0);
120    }
121    if (map->changed & XkbKeySymsMask) {
122        do_map_message("symbols for key", map->first_key_sym, map->num_key_syms,
123                       1);
124    }
125    if (map->changed & XkbKeyActionsMask) {
126        do_map_message("acts for key", map->first_key_act,
127                       map->num_key_acts, 1);
128    }
129    if (map->changed & XkbKeyBehaviorsMask) {
130        do_map_message("behavior for key", map->first_key_behavior,
131                       map->num_key_behaviors, 1);
132    }
133    if (map->changed & XkbVirtualModsMask) {
134        fprintf(file, "    virtual modifiers changed (0x%04x)\n", map->vmods);
135    }
136    if (map->changed & XkbExplicitComponentsMask) {
137        do_map_message("explicit components for key", map->first_key_explicit,
138                       map->num_key_explicit, 1);
139    }
140    if (map->changed & XkbModifierMapMask) {
141        do_map_message("modifier map for key", map->first_modmap_key,
142                       map->num_modmap_keys, 1);
143    }
144    return;
145}
146
147static void
148do_XkbControlsNotify(FILE *file, XkbEvent *xkbev)
149{
150    XkbControlsNotifyEvent *ctrls = &xkbev->ctrls;
151
152    fprintf(file, "    changed= 0x%x, enabled= 0x%x, enabledChanges= 0x%x\n",
153            ctrls->changed_ctrls, ctrls->enabled_ctrls,
154            ctrls->enabled_ctrl_changes);
155    fprintf(file, "    num_groups= %d\n", ctrls->num_groups);
156    if (ctrls->keycode != 0)
157        fprintf(file, "    keycode %d, eventType %s,",
158                ctrls->keycode, eventTypeToString(ctrls->event_type));
159    else
160        fprintf(file, "    request %d/%d%s\n", ctrls->req_major,
161                ctrls->req_minor,
162                (ctrls->req_major != xkbOpcode ? " (NON-XKB)" : ""));
163    return;
164}
165
166static void
167do_XkbIndicatorNotify(FILE *file, XkbEvent *xkbev)
168{
169    XkbIndicatorNotifyEvent *leds = &xkbev->indicators;
170
171    if (leds->xkb_type == XkbIndicatorStateNotify)
172        fprintf(file, "    state changes= 0x%08x, new state= 0x%08x\n",
173                leds->changed, leds->state);
174    else
175        fprintf(file, "    map changes= 0x%08x, state= 0x%08x\n",
176                leds->changed, leds->state);
177    return;
178}
179
180static void
181do_XkbBellNotify(FILE *file, XkbEvent *xkbev)
182{
183    XkbBellNotifyEvent *bell = &xkbev->bell;
184
185    fprintf(file, "    bell class= %d, id= %d\n", bell->bell_class,
186            bell->bell_id);
187    fprintf(file, "    percent= %d, pitch= %d, duration= %d", bell->percent,
188            bell->pitch, bell->duration);
189    if (bell->name != None) {
190        char *name = XGetAtomName(dpy, bell->name);
191
192        fprintf(file, "\n    name= \"%s\"\n", (name ? name : ""));
193        if (name)
194            XFree(name);
195    }
196    else
197        fprintf(file, ", no name\n");
198    fprintf(file, "    window= 0x%x, %sevent_only\n",
199            (unsigned int) bell->window, (bell->event_only ? "" : "!"));
200    return;
201}
202
203static void
204do_XkbAccessXNotify(FILE *file, XkbEvent *xkbev)
205{
206    XkbAccessXNotifyEvent *sk = &xkbev->accessx;
207    const char *detail;
208
209    switch (sk->detail) {
210    case XkbAXN_SKPress:
211        detail = "skpress";
212        break;
213    case XkbAXN_SKAccept:
214        detail = "skaccept";
215        break;
216    case XkbAXN_SKReject:
217        detail = "skreject";
218        break;
219    case XkbAXN_SKRelease:
220        detail = "skrelease";
221        break;
222    case XkbAXN_BKAccept:
223        detail = "bkaccept";
224        break;
225    case XkbAXN_BKReject:
226        detail = "bkreject";
227        break;
228    case XkbAXN_AXKWarning:
229        detail = "warning";
230        break;
231    default:{
232        static char buf[20];
233
234        snprintf(buf, sizeof(buf), "unknown(%d)", sk->detail);
235        detail = buf;
236        break;
237    }
238    }
239    fprintf(file,
240            "    keycode= %d,detail= %s,slow keys delay= %d,debounce delay= %d\n",
241            sk->keycode, detail, sk->sk_delay, sk->debounce_delay);
242    return;
243}
244
245static void
246do_XkbNamesNotify(FILE *file, XkbEvent *xkbev)
247{
248    XkbNamesNotifyEvent *names = &xkbev->names;
249
250    if (names->changed &
251        (XkbKeycodesNameMask | XkbGeometryNameMask | XkbSymbolsNameMask)) {
252        int needComma = 0;
253
254        fprintf(file, "    ");
255        if (names->changed & XkbKeycodesNameMask) {
256            fprintf(file, "keycodes");
257            needComma++;
258        }
259        if (names->changed & XkbGeometryNameMask) {
260            fprintf(file, "%sgeometry", (needComma ? ", " : ""));
261            needComma++;
262        }
263        if (names->changed & XkbSymbolsNameMask) {
264            fprintf(file, "%ssymbols", (needComma ? ", " : ""));
265            needComma++;
266        }
267        if (names->changed & XkbPhysSymbolsNameMask) {
268            fprintf(file, "%sphysical symbols", (needComma ? ", " : ""));
269            needComma++;
270        }
271        fprintf(file, " name%s changed\n", (needComma > 1 ? "s" : ""));
272    }
273    if (names->changed & XkbKeyTypeNamesMask) {
274        do_map_message("key type name", names->first_type, names->num_types, 1);
275    }
276    if (names->changed & XkbKTLevelNamesMask) {
277        do_map_message("level names for key type",
278                       names->first_lvl, names->num_lvls, 1);
279    }
280    if (names->changed & XkbIndicatorNamesMask) {
281        fprintf(file, "    names of indicators in 0x%08x changed\n",
282                names->changed_indicators);
283    }
284    if (names->changed & XkbVirtualModNamesMask) {
285        fprintf(file, "    names of virtual modifiers in 0x%04x changed\n",
286                names->changed_vmods);
287    }
288    if (names->changed & XkbGroupNamesMask) {
289        fprintf(file, "    names of groups in 0x%x changed\n",
290                names->changed_groups);
291    }
292    if (names->changed & XkbKeyNamesMask) {
293        do_map_message("names for key", names->first_key, names->num_keys, 1);
294    }
295    if (names->changed & XkbKeyAliasesMask) {
296        fprintf(file, "key aliases changed (%d aliases total)\n",
297                names->num_aliases);
298    }
299    if (names->changed & XkbRGNamesMask) {
300        fprintf(file, "radio group names changed (%d radio groups total)\n",
301                names->num_radio_groups);
302    }
303    return;
304}
305
306static void
307do_XkbCompatMapNotify(FILE *file, XkbEvent *xkbev)
308{
309    XkbCompatMapNotifyEvent *map = &xkbev->compat;
310
311    if (map->changed_groups)
312        fprintf(file, "    compat maps for groups in 0x%02x changed\n",
313                map->changed_groups);
314    if (map->num_si > 0) {
315        fprintf(file, "    symbol interpretations %d..%d (of %d) changed\n",
316                map->first_si, map->first_si + map->num_si - 1,
317                map->num_total_si);
318    }
319    else
320        fprintf(file, "   keyboard has %d symbol interpretations\n",
321                map->num_total_si);
322    return;
323}
324
325static void
326do_XkbActionMessage(FILE *file, XkbEvent *xkbev)
327{
328    XkbActionMessageEvent *msg = &xkbev->message;
329
330    fprintf(file, "    message: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n",
331            msg->message[0], msg->message[1],
332            msg->message[2], msg->message[3], msg->message[4], msg->message[5]);
333    fprintf(file, "    key %d, event: %s,  follows: %s\n", msg->keycode,
334            (msg->press ? "press" : "release"),
335            (msg->key_event_follows ? "yes" : "no"));
336    return;
337}
338
339static void
340do_XkbNewKeyboardNotify(FILE *file, XkbEvent *xkbev)
341{
342    XkbNewKeyboardNotifyEvent *nk = &xkbev->new_kbd;
343
344    fprintf(file, "    new device: %d min_keycode: %d, max_keycode %d\n",
345            nk->device, nk->min_key_code, nk->max_key_code);
346    fprintf(file, "    old device: %d min_keycode: %d, max_keycode %d\n",
347            nk->old_device, nk->old_min_key_code, nk->old_max_key_code);
348    return;
349}
350
351static void
352do_XkbExtensionDeviceNotify(FILE *file, XkbEvent *xkbev)
353{
354    XkbExtensionDeviceNotifyEvent *edn = &xkbev->device;
355
356    fprintf(file, "    device= %d, class= %d, id= %d\n", edn->device,
357            edn->led_class, edn->led_id);
358    fprintf(file, "    reason= 0x%0x\n", edn->reason);
359    fprintf(file, "    supported= 0x%0x, unsupported= 0x%0x\n", edn->supported,
360            edn->unsupported);
361    fprintf(file, "    first button= %d, num buttons= %d\n", edn->first_btn,
362            edn->num_btns);
363    fprintf(file, "    leds defined= 0x%08x, led state= 0x%08x\n",
364            edn->leds_defined, edn->led_state);
365    return;
366}
367
368void
369PrintXkbEvent(FILE *file, XkbEvent *ev)
370{
371    if (ev->type == xkbEventCode) {
372        switch (ev->any.xkb_type) {
373        case XkbStateNotify:
374            xkb_prologue(file, ev, "XkbStateNotify");
375            do_XkbStateNotify(file, ev);
376            break;
377        case XkbMapNotify:
378            xkb_prologue(file, ev, "XkbMapNotify");
379            do_XkbMapNotify(file, ev);
380            break;
381        case XkbControlsNotify:
382            xkb_prologue(file, ev, "XkbControlsNotify");
383            do_XkbControlsNotify(file, ev);
384            break;
385        case XkbIndicatorMapNotify:
386            xkb_prologue(file, ev, "XkbIndicatorMapNotify");
387            do_XkbIndicatorNotify(file, ev);
388            break;
389        case XkbIndicatorStateNotify:
390            xkb_prologue(file, ev, "XkbIndicatorStateNotify");
391            do_XkbIndicatorNotify(file, ev);
392            break;
393        case XkbBellNotify:
394            xkb_prologue(file, ev, "XkbBellNotify");
395            do_XkbBellNotify(file, ev);
396            break;
397        case XkbAccessXNotify:
398            xkb_prologue(file, ev, "XkbAccessXNotify");
399            do_XkbAccessXNotify(file, ev);
400            break;
401        case XkbNamesNotify:
402            xkb_prologue(file, ev, "XkbNamesNotify");
403            do_XkbNamesNotify(file, ev);
404            break;
405        case XkbCompatMapNotify:
406            xkb_prologue(file, ev, "XkbCompatMapNotify");
407            do_XkbCompatMapNotify(file, ev);
408            break;
409        case XkbActionMessage:
410            xkb_prologue(file, ev, "XkbActionMessage");
411            do_XkbActionMessage(file, ev);
412            break;
413        case XkbNewKeyboardNotify:
414            xkb_prologue(file, ev, "XkbNewKeyboard");
415            do_XkbNewKeyboardNotify(file, ev);
416            break;
417        case XkbExtensionDeviceNotify:
418            xkb_prologue(file, ev, "XkbExtensionDeviceNotify");
419            do_XkbExtensionDeviceNotify(file, ev);
420            break;
421        default:
422            xkb_prologue(file, ev, "XKB_UNKNOWN!!!");
423            break;
424        }
425    }
426    return;
427}
428