xev.c revision da39bf31
1/*
2
3Copyright (c) 1988  X Consortium
4
5Permission is hereby granted, free of charge, to any person obtaining
6a copy of this software and associated documentation files (the
7"Software"), to deal in the Software without restriction, including
8without limitation the rights to use, copy, modify, merge, publish,
9distribute, sublicense, and/or sell copies of the Software, and to
10permit persons to whom the Software is furnished to do so, subject to
11the following conditions:
12
13The above copyright notice and this permission notice shall be included
14in all copies or substantial portions of the Software.
15
16THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR
20OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22OTHER DEALINGS IN THE SOFTWARE.
23
24Except as contained in this notice, the name of the X Consortium shall
25not be used in advertising or otherwise to promote the sale, use or
26other dealings in this Software without prior written authorization
27from the X Consortium.
28
29*/
30
31/*
32 * Author:  Jim Fulton, MIT X Consortium
33 */
34
35#ifdef HAVE_CONFIG_H
36# include "config.h"
37#endif
38#include <stdio.h>
39#include <stdlib.h>
40#include <ctype.h>
41#include <X11/Xlocale.h>
42#include <X11/Xos.h>
43#include <X11/Xlib.h>
44#include <X11/Xutil.h>
45#include <X11/Xproto.h>
46#include <X11/extensions/Xrandr.h>
47
48#define INNER_WINDOW_WIDTH 50
49#define INNER_WINDOW_HEIGHT 50
50#define INNER_WINDOW_BORDER 4
51#define INNER_WINDOW_X 10
52#define INNER_WINDOW_Y 10
53#define OUTER_WINDOW_MIN_WIDTH (INNER_WINDOW_WIDTH + \
54				2 * (INNER_WINDOW_BORDER + INNER_WINDOW_X))
55#define OUTER_WINDOW_MIN_HEIGHT (INNER_WINDOW_HEIGHT + \
56				2 * (INNER_WINDOW_BORDER + INNER_WINDOW_Y))
57#define OUTER_WINDOW_DEF_WIDTH (OUTER_WINDOW_MIN_WIDTH + 100)
58#define OUTER_WINDOW_DEF_HEIGHT (OUTER_WINDOW_MIN_HEIGHT + 100)
59#define OUTER_WINDOW_DEF_X 100
60#define OUTER_WINDOW_DEF_Y 100
61
62
63typedef unsigned long Pixel;
64
65const char *Yes = "YES";
66const char *No = "NO";
67const char *Unknown = "unknown";
68
69const char *ProgramName;
70Display *dpy;
71int screen;
72
73XIC xic = NULL;
74
75Atom wm_delete_window;
76Atom wm_protocols;
77
78Bool have_rr;
79int rr_event_base, rr_error_base;
80
81enum EventMaskIndex {
82    EVENT_MASK_INDEX_CORE,
83    EVENT_MASK_INDEX_RANDR,
84    NUM_EVENT_MASKS
85};
86
87static void usage(const char *errmsg) _X_NORETURN;
88
89static void
90prologue(XEvent *eventp, const char *event_name)
91{
92    XAnyEvent *e = (XAnyEvent *) eventp;
93
94    printf("\n%s event, serial %ld, synthetic %s, window 0x%lx,\n",
95           event_name, e->serial, e->send_event ? Yes : No, e->window);
96}
97
98static void
99dump(char *str, int len)
100{
101    printf("(");
102    len--;
103    while (len-- > 0)
104        printf("%02x ", (unsigned char) *str++);
105    printf("%02x)", (unsigned char) *str++);
106}
107
108static void
109do_KeyPress(XEvent *eventp)
110{
111    XKeyEvent *e = (XKeyEvent *) eventp;
112    KeySym ks;
113    KeyCode kc = 0;
114    Bool kc_set = False;
115    const char *ksname;
116    int nbytes, nmbbytes = 0;
117    char str[256 + 1];
118    static char *buf = NULL;
119    static int bsize = 8;
120    Status status;
121
122    if (buf == NULL)
123        buf = malloc(bsize);
124
125    nbytes = XLookupString(e, str, 256, &ks, NULL);
126
127    /* not supposed to call XmbLookupString on a key release event */
128    if (e->type == KeyPress && xic) {
129        do {
130            nmbbytes = XmbLookupString(xic, e, buf, bsize - 1, &ks, &status);
131            buf[nmbbytes] = '\0';
132
133            if (status == XBufferOverflow) {
134                bsize = nmbbytes + 1;
135                buf = realloc(buf, bsize);
136            }
137        } while (status == XBufferOverflow);
138    }
139
140    if (ks == NoSymbol)
141        ksname = "NoSymbol";
142    else {
143        if (!(ksname = XKeysymToString(ks)))
144            ksname = "(no name)";
145        kc = XKeysymToKeycode(dpy, ks);
146        kc_set = True;
147    }
148
149    printf("    root 0x%lx, subw 0x%lx, time %lu, (%d,%d), root:(%d,%d),\n",
150           e->root, e->subwindow, e->time, e->x, e->y, e->x_root, e->y_root);
151    printf("    state 0x%x, keycode %u (keysym 0x%lx, %s), same_screen %s,\n",
152           e->state, e->keycode, (unsigned long) ks, ksname,
153           e->same_screen ? Yes : No);
154    if (kc_set && e->keycode != kc)
155        printf("    XKeysymToKeycode returns keycode: %u\n", kc);
156    if (nbytes < 0)
157        nbytes = 0;
158    if (nbytes > 256)
159        nbytes = 256;
160    str[nbytes] = '\0';
161    printf("    XLookupString gives %d bytes: ", nbytes);
162    if (nbytes > 0) {
163        dump(str, nbytes);
164        printf(" \"%s\"\n", str);
165    }
166    else {
167        printf("\n");
168    }
169
170    /* not supposed to call XmbLookupString on a key release event */
171    if (e->type == KeyPress && xic) {
172        printf("    XmbLookupString gives %d bytes: ", nmbbytes);
173        if (nmbbytes > 0) {
174            dump(buf, nmbbytes);
175            printf(" \"%s\"\n", buf);
176        }
177        else {
178            printf("\n");
179        }
180    }
181
182    printf("    XFilterEvent returns: %s\n",
183           XFilterEvent(eventp, e->window) ? "True" : "False");
184}
185
186static void
187do_KeyRelease(XEvent *eventp)
188{
189    do_KeyPress(eventp);        /* since it has the same info */
190}
191
192static void
193do_ButtonPress(XEvent *eventp)
194{
195    XButtonEvent *e = (XButtonEvent *) eventp;
196
197    printf("    root 0x%lx, subw 0x%lx, time %lu, (%d,%d), root:(%d,%d),\n",
198           e->root, e->subwindow, e->time, e->x, e->y, e->x_root, e->y_root);
199    printf("    state 0x%x, button %u, same_screen %s\n",
200           e->state, e->button, e->same_screen ? Yes : No);
201}
202
203static void
204do_ButtonRelease(XEvent *eventp)
205{
206    do_ButtonPress(eventp);     /* since it has the same info */
207}
208
209static void
210do_MotionNotify(XEvent *eventp)
211{
212    XMotionEvent *e = (XMotionEvent *) eventp;
213
214    printf("    root 0x%lx, subw 0x%lx, time %lu, (%d,%d), root:(%d,%d),\n",
215           e->root, e->subwindow, e->time, e->x, e->y, e->x_root, e->y_root);
216    printf("    state 0x%x, is_hint %u, same_screen %s\n",
217           e->state, e->is_hint, e->same_screen ? Yes : No);
218}
219
220static void
221do_EnterNotify(XEvent *eventp)
222{
223    XCrossingEvent *e = (XCrossingEvent *) eventp;
224    const char *mode, *detail;
225    char dmode[10], ddetail[10];
226
227    switch (e->mode) {
228    case NotifyNormal:
229        mode = "NotifyNormal";
230        break;
231    case NotifyGrab:
232        mode = "NotifyGrab";
233        break;
234    case NotifyUngrab:
235        mode = "NotifyUngrab";
236        break;
237    case NotifyWhileGrabbed:
238        mode = "NotifyWhileGrabbed";
239        break;
240    default:
241        mode = dmode;
242        snprintf(dmode, sizeof(dmode), "%u", e->mode);
243        break;
244    }
245
246    switch (e->detail) {
247    case NotifyAncestor:
248        detail = "NotifyAncestor";
249        break;
250    case NotifyVirtual:
251        detail = "NotifyVirtual";
252        break;
253    case NotifyInferior:
254        detail = "NotifyInferior";
255        break;
256    case NotifyNonlinear:
257        detail = "NotifyNonlinear";
258        break;
259    case NotifyNonlinearVirtual:
260        detail = "NotifyNonlinearVirtual";
261        break;
262    case NotifyPointer:
263        detail = "NotifyPointer";
264        break;
265    case NotifyPointerRoot:
266        detail = "NotifyPointerRoot";
267        break;
268    case NotifyDetailNone:
269        detail = "NotifyDetailNone";
270        break;
271    default:
272        detail = ddetail;
273        snprintf(ddetail, sizeof(ddetail), "%u", e->detail);
274        break;
275    }
276
277    printf("    root 0x%lx, subw 0x%lx, time %lu, (%d,%d), root:(%d,%d),\n",
278           e->root, e->subwindow, e->time, e->x, e->y, e->x_root, e->y_root);
279    printf("    mode %s, detail %s, same_screen %s,\n",
280           mode, detail, e->same_screen ? Yes : No);
281    printf("    focus %s, state %u\n", e->focus ? Yes : No, e->state);
282}
283
284static void
285do_LeaveNotify(XEvent *eventp)
286{
287    do_EnterNotify(eventp);     /* since it has same information */
288}
289
290static void
291do_FocusIn(XEvent *eventp)
292{
293    XFocusChangeEvent *e = (XFocusChangeEvent *) eventp;
294    const char *mode, *detail;
295    char dmode[10], ddetail[10];
296
297    switch (e->mode) {
298    case NotifyNormal:
299        mode = "NotifyNormal";
300        break;
301    case NotifyGrab:
302        mode = "NotifyGrab";
303        break;
304    case NotifyUngrab:
305        mode = "NotifyUngrab";
306        break;
307    case NotifyWhileGrabbed:
308        mode = "NotifyWhileGrabbed";
309        break;
310    default:
311        mode = dmode;
312        snprintf(dmode, sizeof(dmode), "%u", e->mode);
313        break;
314    }
315
316    switch (e->detail) {
317    case NotifyAncestor:
318        detail = "NotifyAncestor";
319        break;
320    case NotifyVirtual:
321        detail = "NotifyVirtual";
322        break;
323    case NotifyInferior:
324        detail = "NotifyInferior";
325        break;
326    case NotifyNonlinear:
327        detail = "NotifyNonlinear";
328        break;
329    case NotifyNonlinearVirtual:
330        detail = "NotifyNonlinearVirtual";
331        break;
332    case NotifyPointer:
333        detail = "NotifyPointer";
334        break;
335    case NotifyPointerRoot:
336        detail = "NotifyPointerRoot";
337        break;
338    case NotifyDetailNone:
339        detail = "NotifyDetailNone";
340        break;
341    default:
342        detail = ddetail;
343        snprintf(ddetail, sizeof(ddetail), "%u", e->detail);
344        break;
345    }
346
347    printf("    mode %s, detail %s\n", mode, detail);
348}
349
350static void
351do_FocusOut(XEvent *eventp)
352{
353    do_FocusIn(eventp);         /* since it has same information */
354}
355
356static void
357do_KeymapNotify(XEvent *eventp)
358{
359    XKeymapEvent *e = (XKeymapEvent *) eventp;
360    int i;
361
362    printf("    keys:  ");
363    for (i = 0; i < 32; i++) {
364        if (i == 16)
365            printf("\n           ");
366        printf("%-3u ", (unsigned int) e->key_vector[i]);
367    }
368    printf("\n");
369}
370
371static void
372do_Expose(XEvent *eventp)
373{
374    XExposeEvent *e = (XExposeEvent *) eventp;
375
376    printf("    (%d,%d), width %d, height %d, count %d\n",
377           e->x, e->y, e->width, e->height, e->count);
378}
379
380static void
381do_GraphicsExpose(XEvent *eventp)
382{
383    XGraphicsExposeEvent *e = (XGraphicsExposeEvent *) eventp;
384    const char *m;
385    char mdummy[10];
386
387    switch (e->major_code) {
388    case X_CopyArea:
389        m = "CopyArea";
390        break;
391    case X_CopyPlane:
392        m = "CopyPlane";
393        break;
394    default:
395        m = mdummy;
396        snprintf(mdummy, sizeof(mdummy), "%d", e->major_code);
397        break;
398    }
399
400    printf("    (%d,%d), width %d, height %d, count %d,\n",
401           e->x, e->y, e->width, e->height, e->count);
402    printf("    major %s, minor %d\n", m, e->minor_code);
403}
404
405static void
406do_NoExpose(XEvent *eventp)
407{
408    XNoExposeEvent *e = (XNoExposeEvent *) eventp;
409    const char *m;
410    char mdummy[10];
411
412    switch (e->major_code) {
413    case X_CopyArea:
414        m = "CopyArea";
415        break;
416    case X_CopyPlane:
417        m = "CopyPlane";
418        break;
419    default:
420        m = mdummy;
421        snprintf(mdummy, sizeof(mdummy), "%d", e->major_code);
422        break;
423    }
424
425    printf("    major %s, minor %d\n", m, e->minor_code);
426    return;
427}
428
429static void
430do_VisibilityNotify(XEvent *eventp)
431{
432    XVisibilityEvent *e = (XVisibilityEvent *) eventp;
433    const char *v;
434    char vdummy[10];
435
436    switch (e->state) {
437    case VisibilityUnobscured:
438        v = "VisibilityUnobscured";
439        break;
440    case VisibilityPartiallyObscured:
441        v = "VisibilityPartiallyObscured";
442        break;
443    case VisibilityFullyObscured:
444        v = "VisibilityFullyObscured";
445        break;
446    default:
447        v = vdummy;
448        snprintf(vdummy, sizeof(vdummy), "%d", e->state);
449        break;
450    }
451
452    printf("    state %s\n", v);
453}
454
455static void
456do_CreateNotify(XEvent *eventp)
457{
458    XCreateWindowEvent *e = (XCreateWindowEvent *) eventp;
459
460    printf("    parent 0x%lx, window 0x%lx, (%d,%d), width %d, height %d\n",
461           e->parent, e->window, e->x, e->y, e->width, e->height);
462    printf("border_width %d, override %s\n",
463           e->border_width, e->override_redirect ? Yes : No);
464}
465
466static void
467do_DestroyNotify(XEvent *eventp)
468{
469    XDestroyWindowEvent *e = (XDestroyWindowEvent *) eventp;
470
471    printf("    event 0x%lx, window 0x%lx\n", e->event, e->window);
472}
473
474static void
475do_UnmapNotify(XEvent *eventp)
476{
477    XUnmapEvent *e = (XUnmapEvent *) eventp;
478
479    printf("    event 0x%lx, window 0x%lx, from_configure %s\n",
480           e->event, e->window, e->from_configure ? Yes : No);
481}
482
483static void
484do_MapNotify(XEvent *eventp)
485{
486    XMapEvent *e = (XMapEvent *) eventp;
487
488    printf("    event 0x%lx, window 0x%lx, override %s\n",
489           e->event, e->window, e->override_redirect ? Yes : No);
490}
491
492static void
493do_MapRequest(XEvent *eventp)
494{
495    XMapRequestEvent *e = (XMapRequestEvent *) eventp;
496
497    printf("    parent 0x%lx, window 0x%lx\n", e->parent, e->window);
498}
499
500static void
501do_ReparentNotify(XEvent *eventp)
502{
503    XReparentEvent *e = (XReparentEvent *) eventp;
504
505    printf("    event 0x%lx, window 0x%lx, parent 0x%lx,\n",
506           e->event, e->window, e->parent);
507    printf("    (%d,%d), override %s\n", e->x, e->y,
508           e->override_redirect ? Yes : No);
509}
510
511static void
512do_ConfigureNotify(XEvent *eventp)
513{
514    XConfigureEvent *e = (XConfigureEvent *) eventp;
515
516    printf("    event 0x%lx, window 0x%lx, (%d,%d), width %d, height %d,\n",
517           e->event, e->window, e->x, e->y, e->width, e->height);
518    printf("    border_width %d, above 0x%lx, override %s\n",
519           e->border_width, e->above, e->override_redirect ? Yes : No);
520}
521
522static void
523do_ConfigureRequest(XEvent *eventp)
524{
525    XConfigureRequestEvent *e = (XConfigureRequestEvent *) eventp;
526    const char *detail;
527    char ddummy[10];
528
529    switch (e->detail) {
530    case Above:
531        detail = "Above";
532        break;
533    case Below:
534        detail = "Below";
535        break;
536    case TopIf:
537        detail = "TopIf";
538        break;
539    case BottomIf:
540        detail = "BottomIf";
541        break;
542    case Opposite:
543        detail = "Opposite";
544        break;
545    default:
546        detail = ddummy;
547        snprintf(ddummy, sizeof(ddummy), "%d", e->detail);
548        break;
549    }
550
551    printf("    parent 0x%lx, window 0x%lx, (%d,%d), width %d, height %d,\n",
552           e->parent, e->window, e->x, e->y, e->width, e->height);
553    printf("    border_width %d, above 0x%lx, detail %s, value 0x%lx\n",
554           e->border_width, e->above, detail, e->value_mask);
555}
556
557static void
558do_GravityNotify(XEvent *eventp)
559{
560    XGravityEvent *e = (XGravityEvent *) eventp;
561
562    printf("    event 0x%lx, window 0x%lx, (%d,%d)\n",
563           e->event, e->window, e->x, e->y);
564}
565
566static void
567do_ResizeRequest(XEvent *eventp)
568{
569    XResizeRequestEvent *e = (XResizeRequestEvent *) eventp;
570
571    printf("    width %d, height %d\n", e->width, e->height);
572}
573
574static void
575do_CirculateNotify(XEvent *eventp)
576{
577    XCirculateEvent *e = (XCirculateEvent *) eventp;
578    const char *p;
579    char pdummy[10];
580
581    switch (e->place) {
582    case PlaceOnTop:
583        p = "PlaceOnTop";
584        break;
585    case PlaceOnBottom:
586        p = "PlaceOnBottom";
587        break;
588    default:
589        p = pdummy;
590        snprintf(pdummy, sizeof(pdummy), "%d", e->place);
591        break;
592    }
593
594    printf("    event 0x%lx, window 0x%lx, place %s\n", e->event, e->window, p);
595}
596
597static void
598do_CirculateRequest(XEvent *eventp)
599{
600    XCirculateRequestEvent *e = (XCirculateRequestEvent *) eventp;
601    const char *p;
602    char pdummy[10];
603
604    switch (e->place) {
605    case PlaceOnTop:
606        p = "PlaceOnTop";
607        break;
608    case PlaceOnBottom:
609        p = "PlaceOnBottom";
610        break;
611    default:
612        p = pdummy;
613        snprintf(pdummy, sizeof(pdummy), "%d", e->place);
614        break;
615    }
616
617    printf("    parent 0x%lx, window 0x%lx, place %s\n",
618           e->parent, e->window, p);
619}
620
621static void
622do_PropertyNotify(XEvent *eventp)
623{
624    XPropertyEvent *e = (XPropertyEvent *) eventp;
625    char *aname = XGetAtomName(dpy, e->atom);
626    const char *s;
627    char sdummy[10];
628
629    switch (e->state) {
630    case PropertyNewValue:
631        s = "PropertyNewValue";
632        break;
633    case PropertyDelete:
634        s = "PropertyDelete";
635        break;
636    default:
637        s = sdummy;
638        snprintf(sdummy, sizeof(sdummy), "%d", e->state);
639        break;
640    }
641
642    printf("    atom 0x%lx (%s), time %lu, state %s\n",
643           e->atom, aname ? aname : Unknown, e->time, s);
644
645    XFree(aname);
646}
647
648static void
649do_SelectionClear(XEvent *eventp)
650{
651    XSelectionClearEvent *e = (XSelectionClearEvent *) eventp;
652    char *sname = XGetAtomName(dpy, e->selection);
653
654    printf("    selection 0x%lx (%s), time %lu\n",
655           e->selection, sname ? sname : Unknown, e->time);
656
657    XFree(sname);
658}
659
660static void
661do_SelectionRequest(XEvent *eventp)
662{
663    XSelectionRequestEvent *e = (XSelectionRequestEvent *) eventp;
664    char *sname = XGetAtomName(dpy, e->selection);
665    char *tname = XGetAtomName(dpy, e->target);
666    char *pname = XGetAtomName(dpy, e->property);
667
668    printf("    owner 0x%lx, requestor 0x%lx, selection 0x%lx (%s),\n",
669           e->owner, e->requestor, e->selection, sname ? sname : Unknown);
670    printf("    target 0x%lx (%s), property 0x%lx (%s), time %lu\n",
671           e->target, tname ? tname : Unknown, e->property,
672           pname ? pname : Unknown, e->time);
673
674    XFree(sname);
675    XFree(tname);
676    XFree(pname);
677}
678
679static void
680do_SelectionNotify(XEvent *eventp)
681{
682    XSelectionEvent *e = (XSelectionEvent *) eventp;
683    char *sname = XGetAtomName(dpy, e->selection);
684    char *tname = XGetAtomName(dpy, e->target);
685    char *pname = XGetAtomName(dpy, e->property);
686
687    printf("    selection 0x%lx (%s), target 0x%lx (%s),\n",
688           e->selection, sname ? sname : Unknown, e->target,
689           tname ? tname : Unknown);
690    printf("    property 0x%lx (%s), time %lu\n",
691           e->property, pname ? pname : Unknown, e->time);
692
693    XFree(sname);
694    XFree(tname);
695    XFree(pname);
696}
697
698static void
699do_ColormapNotify(XEvent *eventp)
700{
701    XColormapEvent *e = (XColormapEvent *) eventp;
702    const char *s;
703    char sdummy[10];
704
705    switch (e->state) {
706    case ColormapInstalled:
707        s = "ColormapInstalled";
708        break;
709    case ColormapUninstalled:
710        s = "ColormapUninstalled";
711        break;
712    default:
713        s = sdummy;
714        snprintf(sdummy, sizeof(sdummy), "%d", e->state);
715        break;
716    }
717
718    printf("    colormap 0x%lx, new %s, state %s\n",
719           e->colormap, e->new ? Yes : No, s);
720}
721
722static void
723do_ClientMessage(XEvent *eventp)
724{
725    XClientMessageEvent *e = (XClientMessageEvent *) eventp;
726
727    char *mname = XGetAtomName(dpy, e->message_type);
728
729    if (e->message_type == wm_protocols) {
730        char *message = XGetAtomName(dpy, e->data.l[0]);
731
732        printf("    message_type 0x%lx (%s), format %d, message 0x%lx (%s)\n",
733               e->message_type, mname ? mname : Unknown, e->format,
734               e->data.l[0], message);
735        XFree(message);
736    }
737    else {
738        printf("    message_type 0x%lx (%s), format %d\n",
739               e->message_type, mname ? mname : Unknown, e->format);
740    }
741
742    XFree(mname);
743
744    if (e->format == 32
745        && e->message_type == wm_protocols
746        && (Atom) e->data.l[0] == wm_delete_window)
747        exit(0);
748}
749
750static void
751do_MappingNotify(XEvent *eventp)
752{
753    XMappingEvent *e = (XMappingEvent *) eventp;
754    const char *r;
755    char rdummy[10];
756
757    switch (e->request) {
758    case MappingModifier:
759        r = "MappingModifier";
760        break;
761    case MappingKeyboard:
762        r = "MappingKeyboard";
763        break;
764    case MappingPointer:
765        r = "MappingPointer";
766        break;
767    default:
768        r = rdummy;
769        snprintf(rdummy, sizeof(rdummy), "%d", e->request);
770        break;
771    }
772
773    printf("    request %s, first_keycode %d, count %d\n",
774           r, e->first_keycode, e->count);
775    XRefreshKeyboardMapping(e);
776}
777
778static void
779print_SubPixelOrder(SubpixelOrder subpixel_order)
780{
781    switch (subpixel_order) {
782    case SubPixelUnknown:
783        printf("SubPixelUnknown");
784        return;
785    case SubPixelHorizontalRGB:
786        printf("SubPixelHorizontalRGB");
787        return;
788    case SubPixelHorizontalBGR:
789        printf("SubPixelHorizontalBGR");
790        return;
791    case SubPixelVerticalRGB:
792        printf("SubPixelVerticalRGB");
793        return;
794    case SubPixelVerticalBGR:
795        printf("SubPixelVerticalBGR");
796        return;
797    case SubPixelNone:
798        printf("SubPixelNone");
799        return;
800    default:
801        printf("%d", subpixel_order);
802    }
803}
804
805static void
806print_Rotation(Rotation rotation)
807{
808    if (rotation & RR_Rotate_0)
809        printf("RR_Rotate_0");
810    else if (rotation & RR_Rotate_90)
811        printf("RR_Rotate_90");
812    else if (rotation & RR_Rotate_180)
813        printf("RR_Rotate_180");
814    else if (rotation & RR_Rotate_270)
815        printf("RR_Rotate_270");
816    else {
817        printf("%d", rotation);
818        return;
819    }
820    if (rotation & RR_Reflect_X)
821        printf(", RR_Reflect_X");
822    if (rotation & RR_Reflect_Y)
823        printf(", RR_Reflect_Y");
824}
825
826static void
827print_Connection(Connection connection)
828{
829    switch (connection) {
830    case RR_Connected:
831        printf("RR_Connected");
832        return;
833    case RR_Disconnected:
834        printf("RR_Disconnected");
835        return;
836    case RR_UnknownConnection:
837        printf("RR_UnknownConnection");
838        return;
839    default:
840        printf("%d", connection);
841    }
842}
843
844static void
845do_RRScreenChangeNotify(XEvent *eventp)
846{
847    XRRScreenChangeNotifyEvent *e = (XRRScreenChangeNotifyEvent *) eventp;
848
849    XRRUpdateConfiguration(eventp);
850    printf("    root 0x%lx, timestamp %lu, config_timestamp %lu\n",
851           e->root, e->timestamp, e->config_timestamp);
852    printf("    size_index %hu", e->size_index);
853    printf(", subpixel_order ");
854    print_SubPixelOrder(e->subpixel_order);
855    printf("\n    rotation ");
856    print_Rotation(e->rotation);
857    printf("\n    width %d, height %d, mwidth %d, mheight %d\n",
858           e->width, e->height, e->mwidth, e->mheight);
859}
860
861static void
862do_RRNotify_OutputChange(XEvent *eventp, XRRScreenResources *screen_resources)
863{
864    XRROutputChangeNotifyEvent *e = (XRROutputChangeNotifyEvent *) eventp;
865    XRROutputInfo *output_info = NULL;
866    XRRModeInfo *mode_info = NULL;
867
868    if (screen_resources) {
869        int i;
870
871        output_info = XRRGetOutputInfo(dpy, screen_resources, e->output);
872        for (i = 0; i < screen_resources->nmode; i++)
873            if (screen_resources->modes[i].id == e->mode) {
874                mode_info = &screen_resources->modes[i];
875                break;
876            }
877    }
878    printf("    subtype XRROutputChangeNotifyEvent\n");
879    if (output_info)
880        printf("    output %s, ", output_info->name);
881    else
882        printf("    output %lu, ", e->output);
883    if (e->crtc)
884        printf("crtc %lu, ", e->crtc);
885    else
886        printf("crtc None, ");
887    if (mode_info)
888        printf("mode %s (%dx%d)\n", mode_info->name, mode_info->width,
889               mode_info->height);
890    else if (e->mode)
891        printf("mode %lu\n", e->mode);
892    else
893        printf("mode None\n");
894    printf("    rotation ");
895    print_Rotation(e->rotation);
896    printf("\n    connection ");
897    print_Connection(e->connection);
898    printf(", subpixel_order ");
899    print_SubPixelOrder(e->subpixel_order);
900    printf("\n");
901    XRRFreeOutputInfo(output_info);
902}
903
904static void
905do_RRNotify_CrtcChange(XEvent *eventp, XRRScreenResources *screen_resources)
906{
907    XRRCrtcChangeNotifyEvent *e = (XRRCrtcChangeNotifyEvent *) eventp;
908    XRRModeInfo *mode_info = NULL;
909
910    if (screen_resources) {
911        int i;
912
913        for (i = 0; i < screen_resources->nmode; i++)
914            if (screen_resources->modes[i].id == e->mode) {
915                mode_info = &screen_resources->modes[i];
916                break;
917            }
918    }
919    printf("    subtype XRRCrtcChangeNotifyEvent\n");
920    if (e->crtc)
921        printf("    crtc %lu, ", e->crtc);
922    else
923        printf("    crtc None, ");
924    if (mode_info)
925        printf("mode %s, ", mode_info->name);
926    else if (e->mode)
927        printf("mode %lu, ", e->mode);
928    else
929        printf("mode None, ");
930    printf("rotation ");
931    print_Rotation(e->rotation);
932    printf("\n    x %d, y %d, width %d, height %d\n",
933           e->x, e->y, e->width, e->height);
934}
935
936static void
937do_RRNotify_OutputProperty(XEvent *eventp,
938                           XRRScreenResources *screen_resources)
939{
940    XRROutputPropertyNotifyEvent *e = (XRROutputPropertyNotifyEvent *) eventp;
941    XRROutputInfo *output_info = NULL;
942    char *property = XGetAtomName(dpy, e->property);
943
944    if (screen_resources)
945        output_info = XRRGetOutputInfo(dpy, screen_resources, e->output);
946    printf("    subtype XRROutputPropertyChangeNotifyEvent\n");
947    if (output_info)
948        printf("    output %s, ", output_info->name);
949    else
950        printf("    output %lu, ", e->output);
951    printf("property %s, timestamp %lu, state ", property, e->timestamp);
952    if (e->state == PropertyNewValue)
953        printf("NewValue\n");
954    else if (e->state == PropertyDelete)
955        printf("Delete\n");
956    else
957        printf("%d\n", e->state);
958    XRRFreeOutputInfo(output_info);
959    XFree(property);
960}
961
962static void
963do_RRNotify(XEvent *eventp)
964{
965    XRRNotifyEvent *e = (XRRNotifyEvent *) eventp;
966    XRRScreenResources *screen_resources;
967
968    XRRUpdateConfiguration(eventp);
969    screen_resources = XRRGetScreenResources(dpy, e->window);
970    prologue(eventp, "RRNotify");
971    switch (e->subtype) {
972    case RRNotify_OutputChange:
973        do_RRNotify_OutputChange(eventp, screen_resources);
974        break;
975    case RRNotify_CrtcChange:
976        do_RRNotify_CrtcChange(eventp, screen_resources);
977        break;
978    case RRNotify_OutputProperty:
979        do_RRNotify_OutputProperty(eventp, screen_resources);
980        break;
981    default:
982        printf("    subtype %d\n", e->subtype);
983    }
984    XRRFreeScreenResources(screen_resources);
985}
986
987static void
988set_sizehints(XSizeHints *hintp, int min_width, int min_height,
989              int defwidth, int defheight, int defx, int defy, char *geom)
990{
991    int geom_result;
992
993    /* set the size hints, algorithm from xlib xbiff */
994
995    hintp->width = hintp->min_width = min_width;
996    hintp->height = hintp->min_height = min_height;
997    hintp->flags = PMinSize;
998    hintp->x = hintp->y = 0;
999    geom_result = NoValue;
1000    if (geom != NULL) {
1001        geom_result = XParseGeometry(geom, &hintp->x, &hintp->y,
1002                                     (unsigned int *) &hintp->width,
1003                                     (unsigned int *) &hintp->height);
1004        if ((geom_result & WidthValue) && (geom_result & HeightValue)) {
1005#ifndef max
1006#define max(a,b) ((a) > (b) ? (a) : (b))
1007#endif
1008            hintp->width = max(hintp->width, hintp->min_width);
1009            hintp->height = max(hintp->height, hintp->min_height);
1010            hintp->flags |= USSize;
1011        }
1012        if ((geom_result & XValue) && (geom_result & YValue)) {
1013            hintp->flags += USPosition;
1014        }
1015    }
1016    if (!(hintp->flags & USSize)) {
1017        hintp->width = defwidth;
1018        hintp->height = defheight;
1019        hintp->flags |= PSize;
1020    }
1021/*
1022    if (!(hintp->flags & USPosition)) {
1023	hintp->x = defx;
1024	hintp->y = defy;
1025	hintp->flags |= PPosition;
1026    }
1027 */
1028    if (geom_result & XNegative) {
1029        hintp->x = DisplayWidth(dpy, DefaultScreen(dpy)) + hintp->x -
1030            hintp->width;
1031    }
1032    if (geom_result & YNegative) {
1033        hintp->y = DisplayHeight(dpy, DefaultScreen(dpy)) + hintp->y -
1034            hintp->height;
1035    }
1036}
1037
1038static void
1039usage(const char *errmsg)
1040{
1041    const char *msg =
1042"    -display displayname                X server to contact\n"
1043"    -geometry geom                      size and location of window\n"
1044"    -bw pixels                          border width in pixels\n"
1045"    -bs {NotUseful,WhenMapped,Always}   backingstore attribute\n"
1046"    -id windowid                        use existing window\n"
1047"    -root                               use root window\n"
1048"    -s                                  set save-unders attribute\n"
1049"    -name string                        window name\n"
1050"    -rv                                 reverse video\n"
1051"    -event event_mask                   select 'event_mask' events\n"
1052"           Supported event masks: keyboard mouse expose visibility structure\n"
1053"                                  substructure focus property colormap\n"
1054"                                  owner_grab_button randr button\n"
1055"           This option can be specified multiple times to select multiple\n"
1056"           event masks.\n"
1057"    -version                            print version and exit\n"
1058"\n";
1059
1060    if (errmsg != NULL)
1061        fprintf(stderr, "%s: %s\n", ProgramName, errmsg);
1062
1063    fprintf(stderr, "usage:  %s [-options ...]\n", ProgramName);
1064    fprintf(stderr, "where options include:\n");
1065    fputs(msg, stderr);
1066
1067    exit(1);
1068}
1069
1070static int
1071parse_backing_store(const char *s)
1072{
1073    size_t len = strlen(s);
1074
1075    if (strncasecmp(s, "NotUseful", len) == 0)
1076        return (NotUseful);
1077    if (strncasecmp(s, "WhenMapped", len) == 0)
1078        return (WhenMapped);
1079    if (strncasecmp(s, "Always", len) == 0)
1080        return (Always);
1081
1082    fprintf(stderr, "%s: unrecognized argument '%s' for -bs\n", ProgramName, s);
1083    usage(NULL);
1084}
1085
1086static Bool
1087parse_event_mask(const char *s, long event_masks[])
1088{
1089    const struct {
1090        const char *name;
1091        enum EventMaskIndex mask_index;
1092        long mask;
1093    } events[] = {
1094        { "keyboard",
1095          EVENT_MASK_INDEX_CORE,
1096          KeyPressMask | KeyReleaseMask | KeymapStateMask },
1097        { "mouse",
1098          EVENT_MASK_INDEX_CORE,
1099          ButtonPressMask | ButtonReleaseMask | EnterWindowMask |
1100          LeaveWindowMask | PointerMotionMask | Button1MotionMask |
1101          Button2MotionMask | Button3MotionMask | Button4MotionMask |
1102          Button5MotionMask | ButtonMotionMask },
1103        { "button",
1104          EVENT_MASK_INDEX_CORE,
1105          ButtonPressMask | ButtonReleaseMask },
1106        { "expose",
1107          EVENT_MASK_INDEX_CORE,
1108          ExposureMask },
1109        { "visibility",
1110          EVENT_MASK_INDEX_CORE,
1111          VisibilityChangeMask },
1112        { "structure",
1113          EVENT_MASK_INDEX_CORE,
1114          StructureNotifyMask },
1115        { "substructure",
1116          EVENT_MASK_INDEX_CORE,
1117          SubstructureNotifyMask | SubstructureRedirectMask },
1118        { "focus",
1119          EVENT_MASK_INDEX_CORE,
1120          FocusChangeMask },
1121        { "property",
1122          EVENT_MASK_INDEX_CORE,
1123          PropertyChangeMask },
1124        { "colormap",
1125          EVENT_MASK_INDEX_CORE,
1126          ColormapChangeMask },
1127        { "owner_grab_button",
1128          EVENT_MASK_INDEX_CORE,
1129          OwnerGrabButtonMask },
1130        { "randr",
1131          EVENT_MASK_INDEX_RANDR,
1132          RRScreenChangeNotifyMask | RRCrtcChangeNotifyMask |
1133          RROutputChangeNotifyMask | RROutputPropertyNotifyMask },
1134        { NULL, 0, 0 }
1135    };
1136    int i;
1137
1138    for (i = 0; events[i].name; i++) {
1139        if (!s || !strcmp(s, events[i].name)) {
1140            event_masks[events[i].mask_index] |= events[i].mask;
1141            if (s)
1142                return True;
1143        }
1144    }
1145
1146    if (s != NULL)
1147        fprintf(stderr, "%s: unrecognized event mask '%s'\n", ProgramName, s);
1148
1149    return False;
1150}
1151
1152int
1153main(int argc, char **argv)
1154{
1155    char *displayname = NULL;
1156    char *geom = NULL;
1157    int i;
1158    XSizeHints hints;
1159    int borderwidth = 2;
1160    Window w, subw;
1161    XSetWindowAttributes attr;
1162    XWindowAttributes wattr;
1163    unsigned long mask = 0L;
1164    int done;
1165    const char *name = "Event Tester";
1166    Bool reverse = False;
1167    Bool use_root = False;
1168    unsigned long back, fore;
1169    XIM xim;
1170    XIMStyles *xim_styles;
1171    XIMStyle xim_style = 0;
1172    char *modifiers;
1173    char *imvalret;
1174    long event_masks[NUM_EVENT_MASKS];
1175    Bool event_mask_specified = False;
1176
1177    ProgramName = argv[0];
1178
1179    if (setlocale(LC_ALL, "") == NULL) {
1180        fprintf(stderr, "%s: warning: could not set default locale\n",
1181                ProgramName);
1182    }
1183
1184    memset(event_masks, 0, sizeof(event_masks));
1185
1186    w = 0;
1187    for (i = 1; i < argc; i++) {
1188        char *arg = argv[i];
1189
1190        if (arg[0] == '-') {
1191            switch (arg[1]) {
1192            case 'd':          /* -display host:dpy */
1193                if (++i >= argc)
1194                    usage("-display requires an argument");
1195                displayname = argv[i];
1196                continue;
1197            case 'g':          /* -geometry geom */
1198                if (++i >= argc)
1199                    usage("-geometry requires an argument");
1200                geom = argv[i];
1201                continue;
1202            case 'b':
1203                switch (arg[2]) {
1204                case 'w':      /* -bw pixels */
1205                    if (++i >= argc)
1206                        usage("-bw requires an argument");
1207                    borderwidth = atoi(argv[i]);
1208                    continue;
1209                case 's':      /* -bs type */
1210                    if (++i >= argc)
1211                        usage("-bs requires an argument");
1212                    attr.backing_store = parse_backing_store(argv[i]);
1213                    mask |= CWBackingStore;
1214                    continue;
1215                default:
1216                    goto unrecognized;
1217                }
1218            case 'i':          /* -id */
1219                if (++i >= argc)
1220                    usage("-id requires an argument");
1221                sscanf(argv[i], "0x%lx", &w);
1222                if (!w)
1223                    sscanf(argv[i], "%lu", &w);
1224                if (!w) {
1225                    fprintf(stderr,
1226                            "%s: unable to parse argument '%s' for -id\n",
1227                            ProgramName, argv[i]);
1228                    usage(NULL);
1229                }
1230                continue;
1231            case 'n':          /* -name */
1232                if (++i >= argc)
1233                    usage("-name requires an argument");
1234                name = argv[i];
1235                continue;
1236            case 'r':
1237                switch (arg[2]) {
1238                case 'o':      /* -root */
1239                    use_root = True;
1240                    continue;
1241                case 'v':      /* -rv */
1242                    reverse = True;
1243                    continue;
1244                default:
1245                    goto unrecognized;
1246                }
1247                continue;
1248            case 's':          /* -s */
1249                attr.save_under = True;
1250                mask |= CWSaveUnder;
1251                continue;
1252            case 'e':          /* -event */
1253                if (++i >= argc)
1254                    usage("-event requires an argument");
1255                if (!parse_event_mask(argv[i], event_masks))
1256                    usage(NULL);
1257                event_mask_specified = True;
1258                continue;
1259            case 'v':
1260                puts(PACKAGE_STRING);
1261                exit(0);
1262            default:
1263                goto unrecognized;
1264            }                   /* end switch on - */
1265        }
1266        else {
1267 unrecognized:
1268            fprintf(stderr, "%s: unrecognized argument '%s'\n",
1269                    ProgramName, arg);
1270            usage(NULL);
1271        }
1272    }                           /* end for over argc */
1273
1274    /* if no -event options were specified, pretend all of them were */
1275    if (!event_mask_specified)
1276        parse_event_mask(NULL, event_masks);
1277
1278    dpy = XOpenDisplay(displayname);
1279    if (!dpy) {
1280        fprintf(stderr, "%s:  unable to open display '%s'\n",
1281                ProgramName, XDisplayName(displayname));
1282        exit(1);
1283    }
1284
1285    /* we're testing the default input method */
1286    modifiers = XSetLocaleModifiers("@im=none");
1287    if (modifiers == NULL) {
1288        fprintf(stderr, "%s:  XSetLocaleModifiers failed\n", ProgramName);
1289    }
1290
1291    xim = XOpenIM(dpy, NULL, NULL, NULL);
1292    if (xim == NULL) {
1293        fprintf(stderr, "%s:  XOpenIM failed\n", ProgramName);
1294    }
1295
1296    if (xim) {
1297        imvalret = XGetIMValues(xim, XNQueryInputStyle, &xim_styles, NULL);
1298        if (imvalret != NULL || xim_styles == NULL) {
1299            fprintf(stderr, "%s:  input method doesn't support any styles\n",
1300                    ProgramName);
1301        }
1302
1303        if (xim_styles) {
1304            xim_style = 0;
1305            for (i = 0; i < xim_styles->count_styles; i++) {
1306                if (xim_styles->supported_styles[i] ==
1307                    (XIMPreeditNothing | XIMStatusNothing)) {
1308                    xim_style = xim_styles->supported_styles[i];
1309                    break;
1310                }
1311            }
1312
1313            if (xim_style == 0) {
1314                fprintf(stderr,
1315                        "%s: input method doesn't support the style we support\n",
1316                        ProgramName);
1317            }
1318            XFree(xim_styles);
1319        }
1320    }
1321
1322    screen = DefaultScreen(dpy);
1323
1324    attr.event_mask = event_masks[EVENT_MASK_INDEX_CORE];
1325
1326    if (use_root)
1327        w = RootWindow(dpy, screen);
1328
1329    if (w) {
1330        XGetWindowAttributes(dpy, w, &wattr);
1331        if (wattr.all_event_masks & ButtonPressMask)
1332            attr.event_mask &= ~ButtonPressMask;
1333        attr.event_mask &= ~SubstructureRedirectMask;
1334        XSelectInput(dpy, w, attr.event_mask);
1335    }
1336    else {
1337        set_sizehints(&hints, OUTER_WINDOW_MIN_WIDTH, OUTER_WINDOW_MIN_HEIGHT,
1338                      OUTER_WINDOW_DEF_WIDTH, OUTER_WINDOW_DEF_HEIGHT,
1339                      OUTER_WINDOW_DEF_X, OUTER_WINDOW_DEF_Y, geom);
1340
1341        if (reverse) {
1342            back = BlackPixel(dpy, screen);
1343            fore = WhitePixel(dpy, screen);
1344        }
1345        else {
1346            back = WhitePixel(dpy, screen);
1347            fore = BlackPixel(dpy, screen);
1348        }
1349
1350        attr.background_pixel = back;
1351        attr.border_pixel = fore;
1352        mask |= (CWBackPixel | CWBorderPixel | CWEventMask);
1353
1354        w = XCreateWindow(dpy, RootWindow(dpy, screen), hints.x, hints.y,
1355                          hints.width, hints.height, borderwidth, 0,
1356                          InputOutput, (Visual *) CopyFromParent, mask, &attr);
1357
1358        XSetStandardProperties(dpy, w, name, NULL, (Pixmap) 0,
1359                               argv, argc, &hints);
1360
1361        subw = XCreateSimpleWindow(dpy, w, INNER_WINDOW_X, INNER_WINDOW_Y,
1362                                   INNER_WINDOW_WIDTH, INNER_WINDOW_HEIGHT,
1363                                   INNER_WINDOW_BORDER,
1364                                   attr.border_pixel, attr.background_pixel);
1365
1366        wm_protocols = XInternAtom(dpy, "WM_PROTOCOLS", False);
1367        wm_delete_window = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
1368        XSetWMProtocols(dpy, w, &wm_delete_window, 1);
1369
1370        XMapWindow(dpy, subw);  /* map before w so that it appears */
1371        XMapWindow(dpy, w);
1372
1373        printf("Outer window is 0x%lx, inner window is 0x%lx\n", w, subw);
1374    }
1375
1376    if (xim && xim_style) {
1377        xic = XCreateIC(xim,
1378                        XNInputStyle, xim_style,
1379                        XNClientWindow, w, XNFocusWindow, w, NULL);
1380
1381        if (xic == NULL) {
1382            fprintf(stderr, "XCreateIC failed\n");
1383        }
1384    }
1385
1386    have_rr = XRRQueryExtension(dpy, &rr_event_base, &rr_error_base);
1387    if (have_rr) {
1388        int rr_major, rr_minor;
1389
1390        if (XRRQueryVersion(dpy, &rr_major, &rr_minor)) {
1391            int rr_mask = event_masks[EVENT_MASK_INDEX_RANDR];
1392
1393            if (rr_major == 1 && rr_minor <= 1) {
1394                rr_mask &= ~(RRCrtcChangeNotifyMask |
1395                             RROutputChangeNotifyMask |
1396                             RROutputPropertyNotifyMask);
1397            }
1398
1399            XRRSelectInput(dpy, w, rr_mask);
1400        }
1401    }
1402
1403    for (done = 0; !done;) {
1404        XEvent event;
1405
1406        XNextEvent(dpy, &event);
1407
1408        switch (event.type) {
1409        case KeyPress:
1410            prologue(&event, "KeyPress");
1411            do_KeyPress(&event);
1412            break;
1413        case KeyRelease:
1414            prologue(&event, "KeyRelease");
1415            do_KeyRelease(&event);
1416            break;
1417        case ButtonPress:
1418            prologue(&event, "ButtonPress");
1419            do_ButtonPress(&event);
1420            break;
1421        case ButtonRelease:
1422            prologue(&event, "ButtonRelease");
1423            do_ButtonRelease(&event);
1424            break;
1425        case MotionNotify:
1426            prologue(&event, "MotionNotify");
1427            do_MotionNotify(&event);
1428            break;
1429        case EnterNotify:
1430            prologue(&event, "EnterNotify");
1431            do_EnterNotify(&event);
1432            break;
1433        case LeaveNotify:
1434            prologue(&event, "LeaveNotify");
1435            do_LeaveNotify(&event);
1436            break;
1437        case FocusIn:
1438            prologue(&event, "FocusIn");
1439            do_FocusIn(&event);
1440            break;
1441        case FocusOut:
1442            prologue(&event, "FocusOut");
1443            do_FocusOut(&event);
1444            break;
1445        case KeymapNotify:
1446            prologue(&event, "KeymapNotify");
1447            do_KeymapNotify(&event);
1448            break;
1449        case Expose:
1450            prologue(&event, "Expose");
1451            do_Expose(&event);
1452            break;
1453        case GraphicsExpose:
1454            prologue(&event, "GraphicsExpose");
1455            do_GraphicsExpose(&event);
1456            break;
1457        case NoExpose:
1458            prologue(&event, "NoExpose");
1459            do_NoExpose(&event);
1460            break;
1461        case VisibilityNotify:
1462            prologue(&event, "VisibilityNotify");
1463            do_VisibilityNotify(&event);
1464            break;
1465        case CreateNotify:
1466            prologue(&event, "CreateNotify");
1467            do_CreateNotify(&event);
1468            break;
1469        case DestroyNotify:
1470            prologue(&event, "DestroyNotify");
1471            do_DestroyNotify(&event);
1472            break;
1473        case UnmapNotify:
1474            prologue(&event, "UnmapNotify");
1475            do_UnmapNotify(&event);
1476            break;
1477        case MapNotify:
1478            prologue(&event, "MapNotify");
1479            do_MapNotify(&event);
1480            break;
1481        case MapRequest:
1482            prologue(&event, "MapRequest");
1483            do_MapRequest(&event);
1484            break;
1485        case ReparentNotify:
1486            prologue(&event, "ReparentNotify");
1487            do_ReparentNotify(&event);
1488            break;
1489        case ConfigureNotify:
1490            prologue(&event, "ConfigureNotify");
1491            do_ConfigureNotify(&event);
1492            break;
1493        case ConfigureRequest:
1494            prologue(&event, "ConfigureRequest");
1495            do_ConfigureRequest(&event);
1496            break;
1497        case GravityNotify:
1498            prologue(&event, "GravityNotify");
1499            do_GravityNotify(&event);
1500            break;
1501        case ResizeRequest:
1502            prologue(&event, "ResizeRequest");
1503            do_ResizeRequest(&event);
1504            break;
1505        case CirculateNotify:
1506            prologue(&event, "CirculateNotify");
1507            do_CirculateNotify(&event);
1508            break;
1509        case CirculateRequest:
1510            prologue(&event, "CirculateRequest");
1511            do_CirculateRequest(&event);
1512            break;
1513        case PropertyNotify:
1514            prologue(&event, "PropertyNotify");
1515            do_PropertyNotify(&event);
1516            break;
1517        case SelectionClear:
1518            prologue(&event, "SelectionClear");
1519            do_SelectionClear(&event);
1520            break;
1521        case SelectionRequest:
1522            prologue(&event, "SelectionRequest");
1523            do_SelectionRequest(&event);
1524            break;
1525        case SelectionNotify:
1526            prologue(&event, "SelectionNotify");
1527            do_SelectionNotify(&event);
1528            break;
1529        case ColormapNotify:
1530            prologue(&event, "ColormapNotify");
1531            do_ColormapNotify(&event);
1532            break;
1533        case ClientMessage:
1534            prologue(&event, "ClientMessage");
1535            do_ClientMessage(&event);
1536            break;
1537        case MappingNotify:
1538            prologue(&event, "MappingNotify");
1539            do_MappingNotify(&event);
1540            break;
1541        default:
1542            if (have_rr) {
1543                if (event.type == rr_event_base + RRScreenChangeNotify) {
1544                    prologue(&event, "RRScreenChangeNotify");
1545                    do_RRScreenChangeNotify(&event);
1546                    break;
1547                }
1548                if (event.type == rr_event_base + RRNotify) {
1549                    do_RRNotify(&event);
1550                    break;
1551                }
1552            }
1553            printf("Unknown event type %d\n", event.type);
1554            break;
1555        }
1556        fflush(stdout);
1557    }
1558
1559    XCloseDisplay(dpy);
1560    return 0;
1561}
1562