xev.c revision 1a2dd139
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 (void) _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) nbytes = 0;
157    if (nbytes > 256) nbytes = 256;
158    str[nbytes] = '\0';
159    printf ("    XLookupString gives %d bytes: ", nbytes);
160    if (nbytes > 0) {
161        dump (str, nbytes);
162        printf (" \"%s\"\n", str);
163    } else {
164    	printf ("\n");
165    }
166
167    /* not supposed to call XmbLookupString on a key release event */
168    if (e->type == KeyPress && xic) {
169        printf ("    XmbLookupString gives %d bytes: ", nmbbytes);
170        if (nmbbytes > 0) {
171           dump (buf, nmbbytes);
172           printf (" \"%s\"\n", buf);
173        } else {
174    	   printf ("\n");
175        }
176    }
177
178    printf ("    XFilterEvent returns: %s\n",
179	    XFilterEvent (eventp, e->window) ? "True" : "False");
180}
181
182static void
183do_KeyRelease (XEvent *eventp)
184{
185    do_KeyPress (eventp);		/* since it has the same info */
186}
187
188static void
189do_ButtonPress (XEvent *eventp)
190{
191    XButtonEvent *e = (XButtonEvent *) eventp;
192
193    printf ("    root 0x%lx, subw 0x%lx, time %lu, (%d,%d), root:(%d,%d),\n",
194	    e->root, e->subwindow, e->time, e->x, e->y, e->x_root, e->y_root);
195    printf ("    state 0x%x, button %u, same_screen %s\n",
196	    e->state, e->button, e->same_screen ? Yes : No);
197}
198
199static void
200do_ButtonRelease (XEvent *eventp)
201{
202    do_ButtonPress (eventp);		/* since it has the same info */
203}
204
205static void
206do_MotionNotify (XEvent *eventp)
207{
208    XMotionEvent *e = (XMotionEvent *) eventp;
209
210    printf ("    root 0x%lx, subw 0x%lx, time %lu, (%d,%d), root:(%d,%d),\n",
211	    e->root, e->subwindow, e->time, e->x, e->y, e->x_root, e->y_root);
212    printf ("    state 0x%x, is_hint %u, same_screen %s\n",
213	    e->state, e->is_hint, e->same_screen ? Yes : No);
214}
215
216static void
217do_EnterNotify (XEvent *eventp)
218{
219    XCrossingEvent *e = (XCrossingEvent *) eventp;
220    const char *mode, *detail;
221    char dmode[10], ddetail[10];
222
223    switch (e->mode) {
224      case NotifyNormal:  mode = "NotifyNormal"; break;
225      case NotifyGrab:  mode = "NotifyGrab"; break;
226      case NotifyUngrab:  mode = "NotifyUngrab"; break;
227      case NotifyWhileGrabbed:  mode = "NotifyWhileGrabbed"; break;
228      default:  mode = dmode, sprintf (dmode, "%u", e->mode); break;
229    }
230
231    switch (e->detail) {
232      case NotifyAncestor:  detail = "NotifyAncestor"; break;
233      case NotifyVirtual:  detail = "NotifyVirtual"; break;
234      case NotifyInferior:  detail = "NotifyInferior"; break;
235      case NotifyNonlinear:  detail = "NotifyNonlinear"; break;
236      case NotifyNonlinearVirtual:  detail = "NotifyNonlinearVirtual"; break;
237      case NotifyPointer:  detail = "NotifyPointer"; break;
238      case NotifyPointerRoot:  detail = "NotifyPointerRoot"; break;
239      case NotifyDetailNone:  detail = "NotifyDetailNone"; break;
240      default:  detail = ddetail; sprintf (ddetail, "%u", e->detail); break;
241    }
242
243    printf ("    root 0x%lx, subw 0x%lx, time %lu, (%d,%d), root:(%d,%d),\n",
244	    e->root, e->subwindow, e->time, e->x, e->y, e->x_root, e->y_root);
245    printf ("    mode %s, detail %s, same_screen %s,\n",
246	    mode, detail, e->same_screen ? Yes : No);
247    printf ("    focus %s, state %u\n", e->focus ? Yes : No, e->state);
248}
249
250static void
251do_LeaveNotify (XEvent *eventp)
252{
253    do_EnterNotify (eventp);		/* since it has same information */
254}
255
256static void
257do_FocusIn (XEvent *eventp)
258{
259    XFocusChangeEvent *e = (XFocusChangeEvent *) eventp;
260    const char *mode, *detail;
261    char dmode[10], ddetail[10];
262
263    switch (e->mode) {
264      case NotifyNormal:  mode = "NotifyNormal"; break;
265      case NotifyGrab:  mode = "NotifyGrab"; break;
266      case NotifyUngrab:  mode = "NotifyUngrab"; break;
267      case NotifyWhileGrabbed:  mode = "NotifyWhileGrabbed"; break;
268      default:  mode = dmode, sprintf (dmode, "%u", e->mode); break;
269    }
270
271    switch (e->detail) {
272      case NotifyAncestor:  detail = "NotifyAncestor"; break;
273      case NotifyVirtual:  detail = "NotifyVirtual"; break;
274      case NotifyInferior:  detail = "NotifyInferior"; break;
275      case NotifyNonlinear:  detail = "NotifyNonlinear"; break;
276      case NotifyNonlinearVirtual:  detail = "NotifyNonlinearVirtual"; break;
277      case NotifyPointer:  detail = "NotifyPointer"; break;
278      case NotifyPointerRoot:  detail = "NotifyPointerRoot"; break;
279      case NotifyDetailNone:  detail = "NotifyDetailNone"; break;
280      default:  detail = ddetail; sprintf (ddetail, "%u", e->detail); break;
281    }
282
283    printf ("    mode %s, detail %s\n", mode, detail);
284}
285
286static void
287do_FocusOut (XEvent *eventp)
288{
289    do_FocusIn (eventp);		/* since it has same information */
290}
291
292static void
293do_KeymapNotify (XEvent *eventp)
294{
295    XKeymapEvent *e = (XKeymapEvent *) eventp;
296    int i;
297
298    printf ("    keys:  ");
299    for (i = 0; i < 32; i++) {
300	if (i == 16) printf ("\n           ");
301	printf ("%-3u ", (unsigned int) e->key_vector[i]);
302    }
303    printf ("\n");
304}
305
306static void
307do_Expose (XEvent *eventp)
308{
309    XExposeEvent *e = (XExposeEvent *) eventp;
310
311    printf ("    (%d,%d), width %d, height %d, count %d\n",
312	    e->x, e->y, e->width, e->height, e->count);
313}
314
315static void
316do_GraphicsExpose (XEvent *eventp)
317{
318    XGraphicsExposeEvent *e = (XGraphicsExposeEvent *) eventp;
319    const char *m;
320    char mdummy[10];
321
322    switch (e->major_code) {
323      case X_CopyArea:  m = "CopyArea";  break;
324      case X_CopyPlane:  m = "CopyPlane";  break;
325      default:  m = mdummy; sprintf (mdummy, "%d", e->major_code); break;
326    }
327
328    printf ("    (%d,%d), width %d, height %d, count %d,\n",
329	    e->x, e->y, e->width, e->height, e->count);
330    printf ("    major %s, minor %d\n", m, e->minor_code);
331}
332
333static void
334do_NoExpose (XEvent *eventp)
335{
336    XNoExposeEvent *e = (XNoExposeEvent *) eventp;
337    const char *m;
338    char mdummy[10];
339
340    switch (e->major_code) {
341      case X_CopyArea:  m = "CopyArea";  break;
342      case X_CopyPlane:  m = "CopyPlane";  break;
343      default:  m = mdummy; sprintf (mdummy, "%d", e->major_code); break;
344    }
345
346    printf ("    major %s, minor %d\n", m, e->minor_code);
347    return;
348}
349
350static void
351do_VisibilityNotify (XEvent *eventp)
352{
353    XVisibilityEvent *e = (XVisibilityEvent *) eventp;
354    const char *v;
355    char vdummy[10];
356
357    switch (e->state) {
358      case VisibilityUnobscured:  v = "VisibilityUnobscured"; break;
359      case VisibilityPartiallyObscured:  v = "VisibilityPartiallyObscured"; break;
360      case VisibilityFullyObscured:  v = "VisibilityFullyObscured"; break;
361      default:  v = vdummy; sprintf (vdummy, "%d", e->state); break;
362    }
363
364    printf ("    state %s\n", v);
365}
366
367static void
368do_CreateNotify (XEvent *eventp)
369{
370    XCreateWindowEvent *e = (XCreateWindowEvent *) eventp;
371
372    printf ("    parent 0x%lx, window 0x%lx, (%d,%d), width %d, height %d\n",
373	    e->parent, e->window, e->x, e->y, e->width, e->height);
374    printf ("border_width %d, override %s\n",
375	    e->border_width, e->override_redirect ? Yes : No);
376}
377
378static void
379do_DestroyNotify (XEvent *eventp)
380{
381    XDestroyWindowEvent *e = (XDestroyWindowEvent *) eventp;
382
383    printf ("    event 0x%lx, window 0x%lx\n", e->event, e->window);
384}
385
386static void
387do_UnmapNotify (XEvent *eventp)
388{
389    XUnmapEvent *e = (XUnmapEvent *) eventp;
390
391    printf ("    event 0x%lx, window 0x%lx, from_configure %s\n",
392	    e->event, e->window, e->from_configure ? Yes : No);
393}
394
395static void
396do_MapNotify (XEvent *eventp)
397{
398    XMapEvent *e = (XMapEvent *) eventp;
399
400    printf ("    event 0x%lx, window 0x%lx, override %s\n",
401	    e->event, e->window, e->override_redirect ? Yes : No);
402}
403
404static void
405do_MapRequest (XEvent *eventp)
406{
407    XMapRequestEvent *e = (XMapRequestEvent *) eventp;
408
409    printf ("    parent 0x%lx, window 0x%lx\n", e->parent, e->window);
410}
411
412static void
413do_ReparentNotify (XEvent *eventp)
414{
415    XReparentEvent *e = (XReparentEvent *) eventp;
416
417    printf ("    event 0x%lx, window 0x%lx, parent 0x%lx,\n",
418	    e->event, e->window, e->parent);
419    printf ("    (%d,%d), override %s\n", e->x, e->y,
420	    e->override_redirect ? Yes : No);
421}
422
423static void
424do_ConfigureNotify (XEvent *eventp)
425{
426    XConfigureEvent *e = (XConfigureEvent *) eventp;
427
428    printf ("    event 0x%lx, window 0x%lx, (%d,%d), width %d, height %d,\n",
429	    e->event, e->window, e->x, e->y, e->width, e->height);
430    printf ("    border_width %d, above 0x%lx, override %s\n",
431	    e->border_width, e->above, e->override_redirect ? Yes : No);
432}
433
434static void
435do_ConfigureRequest (XEvent *eventp)
436{
437    XConfigureRequestEvent *e = (XConfigureRequestEvent *) eventp;
438    const char *detail;
439    char ddummy[10];
440
441    switch (e->detail) {
442      case Above:  detail = "Above";  break;
443      case Below:  detail = "Below";  break;
444      case TopIf:  detail = "TopIf";  break;
445      case BottomIf:  detail = "BottomIf"; break;
446      case Opposite:  detail = "Opposite"; break;
447      default:  detail = ddummy; sprintf (ddummy, "%d", e->detail); break;
448    }
449
450    printf ("    parent 0x%lx, window 0x%lx, (%d,%d), width %d, height %d,\n",
451	    e->parent, e->window, e->x, e->y, e->width, e->height);
452    printf ("    border_width %d, above 0x%lx, detail %s, value 0x%lx\n",
453	    e->border_width, e->above, detail, e->value_mask);
454}
455
456static void
457do_GravityNotify (XEvent *eventp)
458{
459    XGravityEvent *e = (XGravityEvent *) eventp;
460
461    printf ("    event 0x%lx, window 0x%lx, (%d,%d)\n",
462	    e->event, e->window, e->x, e->y);
463}
464
465static void
466do_ResizeRequest (XEvent *eventp)
467{
468    XResizeRequestEvent *e = (XResizeRequestEvent *) eventp;
469
470    printf ("    width %d, height %d\n", e->width, e->height);
471}
472
473static void
474do_CirculateNotify (XEvent *eventp)
475{
476    XCirculateEvent *e = (XCirculateEvent *) eventp;
477    const char *p;
478    char pdummy[10];
479
480    switch (e->place) {
481      case PlaceOnTop:  p = "PlaceOnTop"; break;
482      case PlaceOnBottom:  p = "PlaceOnBottom"; break;
483      default:  p = pdummy; sprintf (pdummy, "%d", e->place); break;
484    }
485
486    printf ("    event 0x%lx, window 0x%lx, place %s\n",
487	    e->event, e->window, p);
488}
489
490static void
491do_CirculateRequest (XEvent *eventp)
492{
493    XCirculateRequestEvent *e = (XCirculateRequestEvent *) eventp;
494    const char *p;
495    char pdummy[10];
496
497    switch (e->place) {
498      case PlaceOnTop:  p = "PlaceOnTop"; break;
499      case PlaceOnBottom:  p = "PlaceOnBottom"; break;
500      default:  p = pdummy; sprintf (pdummy, "%d", e->place); break;
501    }
502
503    printf ("    parent 0x%lx, window 0x%lx, place %s\n",
504	    e->parent, e->window, p);
505}
506
507static void
508do_PropertyNotify (XEvent *eventp)
509{
510    XPropertyEvent *e = (XPropertyEvent *) eventp;
511    char *aname = XGetAtomName (dpy, e->atom);
512    const char *s;
513    char sdummy[10];
514
515    switch (e->state) {
516      case PropertyNewValue:  s = "PropertyNewValue"; break;
517      case PropertyDelete:  s = "PropertyDelete"; break;
518      default:  s = sdummy; sprintf (sdummy, "%d", e->state); break;
519    }
520
521    printf ("    atom 0x%lx (%s), time %lu, state %s\n",
522	   e->atom, aname ? aname : Unknown, e->time,  s);
523
524    XFree (aname);
525}
526
527static void
528do_SelectionClear (XEvent *eventp)
529{
530    XSelectionClearEvent *e = (XSelectionClearEvent *) eventp;
531    char *sname = XGetAtomName (dpy, e->selection);
532
533    printf ("    selection 0x%lx (%s), time %lu\n",
534	    e->selection, sname ? sname : Unknown, e->time);
535
536    XFree (sname);
537}
538
539static void
540do_SelectionRequest (XEvent *eventp)
541{
542    XSelectionRequestEvent *e = (XSelectionRequestEvent *) eventp;
543    char *sname = XGetAtomName (dpy, e->selection);
544    char *tname = XGetAtomName (dpy, e->target);
545    char *pname = XGetAtomName (dpy, e->property);
546
547    printf ("    owner 0x%lx, requestor 0x%lx, selection 0x%lx (%s),\n",
548	    e->owner, e->requestor, e->selection, sname ? sname : Unknown);
549    printf ("    target 0x%lx (%s), property 0x%lx (%s), time %lu\n",
550	    e->target, tname ? tname : Unknown, e->property,
551	    pname ? pname : Unknown, e->time);
552
553    XFree (sname);
554    XFree (tname);
555    XFree (pname);
556}
557
558static void
559do_SelectionNotify (XEvent *eventp)
560{
561    XSelectionEvent *e = (XSelectionEvent *) eventp;
562    char *sname = XGetAtomName (dpy, e->selection);
563    char *tname = XGetAtomName (dpy, e->target);
564    char *pname = XGetAtomName (dpy, e->property);
565
566    printf ("    selection 0x%lx (%s), target 0x%lx (%s),\n",
567	    e->selection, sname ? sname : Unknown, e->target,
568	    tname ? tname : Unknown);
569    printf ("    property 0x%lx (%s), time %lu\n",
570	    e->property, pname ? pname : Unknown, e->time);
571
572    XFree (sname);
573    XFree (tname);
574    XFree (pname);
575}
576
577static void
578do_ColormapNotify (XEvent *eventp)
579{
580    XColormapEvent *e = (XColormapEvent *) eventp;
581    const char *s;
582    char sdummy[10];
583
584    switch (e->state) {
585      case ColormapInstalled:  s = "ColormapInstalled"; break;
586      case ColormapUninstalled:  s = "ColormapUninstalled"; break;
587      default:  s = sdummy; sprintf (sdummy, "%d", e->state); break;
588    }
589
590    printf ("    colormap 0x%lx, new %s, state %s\n",
591	    e->colormap, e->new ? Yes : No, s);
592}
593
594static void
595do_ClientMessage (XEvent *eventp)
596{
597    XClientMessageEvent *e = (XClientMessageEvent *) eventp;
598    char *mname = XGetAtomName (dpy, e->message_type);
599
600    if (e->message_type == wm_protocols) {
601        char *message = XGetAtomName (dpy, e->data.l[0]);
602        printf ("    message_type 0x%lx (%s), format %d, message 0x%lx (%s)\n",
603                e->message_type, mname ? mname : Unknown, e->format, e->data.l[0], message);
604        XFree (message);
605    }
606    else {
607        printf ("    message_type 0x%lx (%s), format %d\n",
608                e->message_type, mname ? mname : Unknown, e->format);
609    }
610
611    XFree (mname);
612
613    if (e->format == 32
614        && e->message_type == wm_protocols
615        && (Atom) e->data.l[0] == wm_delete_window)
616        exit (0);
617}
618
619static void
620do_MappingNotify (XEvent *eventp)
621{
622    XMappingEvent *e = (XMappingEvent *) eventp;
623    const char *r;
624    char rdummy[10];
625
626    switch (e->request) {
627      case MappingModifier:  r = "MappingModifier"; break;
628      case MappingKeyboard:  r = "MappingKeyboard"; break;
629      case MappingPointer:  r = "MappingPointer"; break;
630      default:  r = rdummy; sprintf (rdummy, "%d", e->request); break;
631    }
632
633    printf ("    request %s, first_keycode %d, count %d\n",
634	    r, e->first_keycode, e->count);
635    XRefreshKeyboardMapping(e);
636}
637
638static void
639print_SubPixelOrder (SubpixelOrder subpixel_order)
640{
641    switch (subpixel_order) {
642      case SubPixelUnknown:        printf ("SubPixelUnknown"); return;
643      case SubPixelHorizontalRGB:  printf ("SubPixelHorizontalRGB"); return;
644      case SubPixelHorizontalBGR:  printf ("SubPixelHorizontalBGR"); return;
645      case SubPixelVerticalRGB:    printf ("SubPixelVerticalRGB"); return;
646      case SubPixelVerticalBGR:    printf ("SubPixelVerticalBGR"); return;
647      case SubPixelNone:           printf ("SubPixelNone"); return;
648      default:                     printf ("%d", subpixel_order);
649    }
650}
651
652static void
653print_Rotation (Rotation rotation)
654{
655    if (rotation & RR_Rotate_0)
656        printf ("RR_Rotate_0");
657    else if (rotation & RR_Rotate_90)
658        printf ("RR_Rotate_90");
659    else if (rotation & RR_Rotate_180)
660        printf ("RR_Rotate_180");
661    else if (rotation & RR_Rotate_270)
662        printf ("RR_Rotate_270");
663    else {
664        printf ("%d", rotation);
665        return;
666    }
667    if (rotation & RR_Reflect_X)
668        printf (", RR_Reflect_X");
669    if (rotation & RR_Reflect_Y)
670        printf (", RR_Reflect_Y");
671}
672
673static void
674print_Connection (Connection connection)
675{
676    switch (connection) {
677      case RR_Connected:          printf ("RR_Connected"); return;
678      case RR_Disconnected:       printf ("RR_Disconnected"); return;
679      case RR_UnknownConnection:  printf ("RR_UnknownConnection"); return;
680      default:                    printf ("%d", connection);
681    }
682}
683
684static void
685do_RRScreenChangeNotify (XEvent *eventp)
686{
687    XRRScreenChangeNotifyEvent *e = (XRRScreenChangeNotifyEvent *) eventp;
688
689    XRRUpdateConfiguration (eventp);
690    printf ("    root 0x%lx, timestamp %lu, config_timestamp %lu\n",
691            e->root, e->timestamp, e->config_timestamp);
692    printf ("    size_index %hu", e->size_index);
693    printf (", subpixel_order ");
694    print_SubPixelOrder (e->subpixel_order);
695    printf ("\n    rotation ");
696    print_Rotation (e->rotation);
697    printf("\n    width %d, height %d, mwidth %d, mheight %d\n",
698           e->width, e->height, e->mwidth, e->mheight);
699}
700
701static void
702do_RRNotify_OutputChange (XEvent *eventp, XRRScreenResources *screen_resources)
703{
704    XRROutputChangeNotifyEvent *e = (XRROutputChangeNotifyEvent *) eventp;
705    XRROutputInfo *output_info = NULL;
706    XRRModeInfo *mode_info = NULL;
707
708    if (screen_resources) {
709        int i;
710
711        output_info = XRRGetOutputInfo (dpy, screen_resources, e->output);
712        for (i = 0; i < screen_resources->nmode; i++)
713            if (screen_resources->modes[i].id == e->mode) {
714                mode_info = &screen_resources->modes[i]; break;
715            }
716    }
717    printf ("    subtype XRROutputChangeNotifyEvent\n");
718    if (output_info)
719        printf ("    output %s, ", output_info->name);
720    else
721        printf ("    output %lu, ", e->output);
722    if (e->crtc)
723        printf("crtc %lu, ", e->crtc);
724    else
725        printf("crtc None, ");
726    if (mode_info)
727        printf ("mode %s (%dx%d)\n", mode_info->name, mode_info->width,
728                mode_info->height);
729    else if (e->mode)
730        printf ("mode %lu\n", e->mode);
731    else
732        printf("mode None\n");
733    printf ("    rotation ");
734    print_Rotation (e->rotation);
735    printf ("\n    connection ");
736    print_Connection (e->connection);
737    printf (", subpixel_order ");
738    print_SubPixelOrder (e->subpixel_order);
739    printf ("\n");
740    XRRFreeOutputInfo (output_info);
741}
742
743static void
744do_RRNotify_CrtcChange (XEvent *eventp, XRRScreenResources *screen_resources)
745{
746    XRRCrtcChangeNotifyEvent *e = (XRRCrtcChangeNotifyEvent *) eventp;
747    XRRModeInfo *mode_info = NULL;
748
749    if (screen_resources) {
750        int i;
751
752        for (i = 0; i < screen_resources->nmode; i++)
753            if (screen_resources->modes[i].id == e->mode) {
754                mode_info = &screen_resources->modes[i]; break;
755            }
756    }
757    printf ("    subtype XRRCrtcChangeNotifyEvent\n");
758    if (e->crtc)
759        printf("    crtc %lu, ", e->crtc);
760    else
761        printf("    crtc None, ");
762    if (mode_info)
763        printf ("mode %s, ", mode_info->name);
764    else if (e->mode)
765        printf ("mode %lu, ", e->mode);
766    else
767        printf("mode None, ");
768    printf ("rotation ");
769    print_Rotation (e->rotation);
770    printf ("\n    x %d, y %d, width %d, height %d\n",
771            e->x, e->y, e->width, e->height);
772}
773
774static void
775do_RRNotify_OutputProperty (XEvent *eventp,
776                            XRRScreenResources *screen_resources)
777{
778    XRROutputPropertyNotifyEvent *e = (XRROutputPropertyNotifyEvent *) eventp;
779    XRROutputInfo *output_info = NULL;
780    char *property = XGetAtomName (dpy, e->property);
781
782    if (screen_resources)
783        output_info = XRRGetOutputInfo (dpy, screen_resources, e->output);
784    printf ("    subtype XRROutputPropertyChangeNotifyEvent\n");
785    if (output_info)
786        printf ("    output %s, ", output_info->name);
787    else
788        printf ("    output %lu, ", e->output);
789    printf ("property %s, timestamp %lu, state ",
790            property, e->timestamp);
791    if (e->state == PropertyNewValue)
792        printf ("NewValue\n");
793    else if (e->state == PropertyDelete)
794        printf ("Delete\n");
795    else
796        printf ("%d\n", e->state);
797    XRRFreeOutputInfo (output_info);
798    XFree (property);
799}
800
801static void
802do_RRNotify (XEvent *eventp)
803{
804    XRRNotifyEvent *e = (XRRNotifyEvent *) eventp;
805    XRRScreenResources *screen_resources;
806
807    XRRUpdateConfiguration (eventp);
808    screen_resources = XRRGetScreenResources (dpy, e->window);
809    prologue (eventp, "RRNotify");
810    switch (e->subtype) {
811      case RRNotify_OutputChange:
812          do_RRNotify_OutputChange (eventp, screen_resources); break;
813      case RRNotify_CrtcChange:
814          do_RRNotify_CrtcChange (eventp, screen_resources); break;
815      case RRNotify_OutputProperty:
816          do_RRNotify_OutputProperty (eventp, screen_resources); break;
817      default:
818          printf ("    subtype %d\n", e->subtype);
819    }
820    XRRFreeScreenResources (screen_resources);
821}
822
823
824
825static void
826set_sizehints (XSizeHints *hintp, int min_width, int min_height,
827	       int defwidth, int defheight, int defx, int defy,
828	       char *geom)
829{
830    int geom_result;
831
832    /* set the size hints, algorithm from xlib xbiff */
833
834    hintp->width = hintp->min_width = min_width;
835    hintp->height = hintp->min_height = min_height;
836    hintp->flags = PMinSize;
837    hintp->x = hintp->y = 0;
838    geom_result = NoValue;
839    if (geom != NULL) {
840        geom_result = XParseGeometry (geom, &hintp->x, &hintp->y,
841				      (unsigned int *)&hintp->width,
842				      (unsigned int *)&hintp->height);
843	if ((geom_result & WidthValue) && (geom_result & HeightValue)) {
844#ifndef max
845#define max(a,b) ((a) > (b) ? (a) : (b))
846#endif
847	    hintp->width = max (hintp->width, hintp->min_width);
848	    hintp->height = max (hintp->height, hintp->min_height);
849	    hintp->flags |= USSize;
850	}
851	if ((geom_result & XValue) && (geom_result & YValue)) {
852	    hintp->flags += USPosition;
853	}
854    }
855    if (!(hintp->flags & USSize)) {
856	hintp->width = defwidth;
857	hintp->height = defheight;
858	hintp->flags |= PSize;
859    }
860/*
861    if (!(hintp->flags & USPosition)) {
862	hintp->x = defx;
863	hintp->y = defy;
864	hintp->flags |= PPosition;
865    }
866 */
867    if (geom_result & XNegative) {
868	hintp->x = DisplayWidth (dpy, DefaultScreen (dpy)) + hintp->x -
869		    hintp->width;
870    }
871    if (geom_result & YNegative) {
872	hintp->y = DisplayHeight (dpy, DefaultScreen (dpy)) + hintp->y -
873		    hintp->height;
874    }
875}
876
877static void
878usage (void)
879{
880    static const char *msg[] = {
881"    -display displayname                X server to contact",
882"    -geometry geom                      size and location of window",
883"    -bw pixels                          border width in pixels",
884"    -bs {NotUseful,WhenMapped,Always}   backingstore attribute",
885"    -id windowid                        use existing window",
886"    -root                               use root window",
887"    -s                                  set save-unders attribute",
888"    -name string                        window name",
889"    -rv                                 reverse video",
890"    -event event_mask                   select 'event_mask' events",
891"           Supported event masks: keyboard mouse expose visibility structure",
892"                                  substructure focus property colormap",
893"                                  owner_grab_button randr",
894"           This option can be specified multiple times to select multiple",
895"           event masks.",
896"",
897NULL};
898    const char **cpp;
899
900    fprintf (stderr, "usage:  %s [-options ...]\n", ProgramName);
901    fprintf (stderr, "where options include:\n");
902
903    for (cpp = msg; *cpp; cpp++)
904	fprintf (stderr, "%s\n", *cpp);
905
906    exit (1);
907}
908
909static int
910parse_backing_store (char *s)
911{
912    size_t len = strlen (s);
913
914    if (strncasecmp (s, "NotUseful", len) == 0) return (NotUseful);
915    if (strncasecmp (s, "WhenMapped", len) == 0) return (WhenMapped);
916    if (strncasecmp (s, "Always", len) == 0) return (Always);
917
918    usage ();
919}
920
921static Bool
922parse_event_mask (const char *s, long event_masks[])
923{
924    const struct {
925        const char *name;
926        enum EventMaskIndex mask_index;
927        long mask;
928    } events[] = {
929        { "keyboard",
930          EVENT_MASK_INDEX_CORE,
931          KeyPressMask | KeyReleaseMask | KeymapStateMask },
932        { "mouse",
933          EVENT_MASK_INDEX_CORE,
934          ButtonPressMask | ButtonReleaseMask | EnterWindowMask |
935          LeaveWindowMask | PointerMotionMask | Button1MotionMask |
936          Button2MotionMask | Button3MotionMask | Button4MotionMask |
937          Button5MotionMask | ButtonMotionMask },
938        { "expose",
939          EVENT_MASK_INDEX_CORE,
940          ExposureMask },
941        { "visibility",
942          EVENT_MASK_INDEX_CORE,
943          VisibilityChangeMask },
944        { "structure",
945          EVENT_MASK_INDEX_CORE,
946          StructureNotifyMask },
947        { "substructure",
948          EVENT_MASK_INDEX_CORE,
949          SubstructureNotifyMask | SubstructureRedirectMask },
950        { "focus",
951          EVENT_MASK_INDEX_CORE,
952          FocusChangeMask },
953        { "property",
954          EVENT_MASK_INDEX_CORE,
955          PropertyChangeMask },
956        { "colormap",
957          EVENT_MASK_INDEX_CORE,
958          ColormapChangeMask },
959        { "owner_grab_button",
960          EVENT_MASK_INDEX_CORE,
961          OwnerGrabButtonMask },
962        { "randr",
963          EVENT_MASK_INDEX_RANDR,
964          RRScreenChangeNotifyMask | RRCrtcChangeNotifyMask |
965          RROutputChangeNotifyMask | RROutputPropertyNotifyMask },
966        { NULL, 0, 0 }
967    };
968    int i;
969
970    for (i = 0; events[i].name; i++) {
971        if (!s || !strcmp(s, events[i].name)) {
972            event_masks[events[i].mask_index] |= events[i].mask;
973            if (s)
974                return True;
975        }
976    }
977
978    return False;
979}
980
981int
982main (int argc, char **argv)
983{
984    char *displayname = NULL;
985    char *geom = NULL;
986    int i;
987    XSizeHints hints;
988    int borderwidth = 2;
989    Window w, subw;
990    XSetWindowAttributes attr;
991    XWindowAttributes wattr;
992    unsigned long mask = 0L;
993    int done;
994    const char *name = "Event Tester";
995    Bool reverse = False;
996    Bool use_root = False;
997    unsigned long back, fore;
998    XIM xim;
999    XIMStyles *xim_styles;
1000    XIMStyle xim_style = 0;
1001    char *modifiers;
1002    char *imvalret;
1003    long event_masks[NUM_EVENT_MASKS];
1004    Bool event_mask_specified = False;
1005
1006    ProgramName = argv[0];
1007
1008    if (setlocale(LC_ALL,"") == NULL) {
1009	fprintf(stderr, "%s: warning: could not set default locale\n",
1010		ProgramName);
1011    }
1012
1013    memset(event_masks, 0, sizeof(event_masks));
1014
1015    w = 0;
1016    for (i = 1; i < argc; i++) {
1017	char *arg = argv[i];
1018
1019	if (arg[0] == '-') {
1020	    switch (arg[1]) {
1021	      case 'd':			/* -display host:dpy */
1022		if (++i >= argc) usage ();
1023		displayname = argv[i];
1024		continue;
1025	      case 'g':			/* -geometry geom */
1026		if (++i >= argc) usage ();
1027		geom = argv[i];
1028		continue;
1029	      case 'b':
1030		switch (arg[2]) {
1031		  case 'w':		/* -bw pixels */
1032		    if (++i >= argc) usage ();
1033		    borderwidth = atoi (argv[i]);
1034		    continue;
1035		  case 's':		/* -bs type */
1036		    if (++i >= argc) usage ();
1037		    attr.backing_store = parse_backing_store (argv[i]);
1038		    mask |= CWBackingStore;
1039		    continue;
1040		  default:
1041		    usage ();
1042		}
1043	      case 'i':			/* -id */
1044		if (++i >= argc) usage ();
1045		sscanf(argv[i], "0x%lx", &w);
1046		if (!w)
1047		    sscanf(argv[i], "%lu", &w);
1048		if (!w)
1049		    usage ();
1050		continue;
1051	      case 'n':			/* -name */
1052		if (++i >= argc) usage ();
1053		name = argv[i];
1054		continue;
1055	      case 'r':
1056		switch (arg[2]) {
1057		  case 'o':		/* -root */
1058		    use_root = True;
1059		    continue;
1060		  case 'v':		/* -rv */
1061		    reverse = True;
1062		    continue;
1063		  default:
1064		    usage ();
1065		}
1066		continue;
1067	      case 's':			/* -s */
1068		attr.save_under = True;
1069		mask |= CWSaveUnder;
1070		continue;
1071	      case 'e':			/* -event */
1072		if (++i >= argc) usage ();
1073		if (!parse_event_mask (argv[i], event_masks))
1074		    usage ();
1075		event_mask_specified = True;
1076		continue;
1077	      default:
1078		usage ();
1079	    }				/* end switch on - */
1080	} else
1081	  usage ();
1082    }					/* end for over argc */
1083
1084    /* if no -event options were specified, pretend all of them were */
1085    if (!event_mask_specified)
1086        parse_event_mask (NULL, event_masks);
1087
1088    dpy = XOpenDisplay (displayname);
1089    if (!dpy) {
1090	fprintf (stderr, "%s:  unable to open display '%s'\n",
1091		 ProgramName, XDisplayName (displayname));
1092	exit (1);
1093    }
1094
1095    /* we're testing the default input method */
1096    modifiers = XSetLocaleModifiers ("@im=none");
1097    if (modifiers == NULL) {
1098        fprintf (stderr, "%s:  XSetLocaleModifiers failed\n", ProgramName);
1099    }
1100
1101    xim = XOpenIM (dpy, NULL, NULL, NULL);
1102    if (xim == NULL) {
1103        fprintf (stderr, "%s:  XOpenIM failed\n", ProgramName);
1104    }
1105
1106    if (xim) {
1107        imvalret = XGetIMValues (xim, XNQueryInputStyle, &xim_styles, NULL);
1108        if (imvalret != NULL || xim_styles == NULL) {
1109            fprintf (stderr, "%s:  input method doesn't support any styles\n", ProgramName);
1110        }
1111
1112        if (xim_styles) {
1113            xim_style = 0;
1114            for (i = 0;  i < xim_styles->count_styles;  i++) {
1115                if (xim_styles->supported_styles[i] ==
1116                    (XIMPreeditNothing | XIMStatusNothing)) {
1117                    xim_style = xim_styles->supported_styles[i];
1118                    break;
1119                }
1120            }
1121
1122            if (xim_style == 0) {
1123                fprintf (stderr, "%s: input method doesn't support the style we support\n",
1124                         ProgramName);
1125            }
1126            XFree (xim_styles);
1127        }
1128    }
1129
1130    screen = DefaultScreen (dpy);
1131
1132    attr.event_mask = event_masks[EVENT_MASK_INDEX_CORE];
1133
1134    if (use_root)
1135	w = RootWindow(dpy, screen);
1136
1137    if (w) {
1138	XGetWindowAttributes(dpy, w, &wattr);
1139	if (wattr.all_event_masks & ButtonPressMask)
1140	    attr.event_mask &= ~ButtonPressMask;
1141	attr.event_mask &= ~SubstructureRedirectMask;
1142	XSelectInput(dpy, w, attr.event_mask);
1143    } else {
1144	set_sizehints (&hints, OUTER_WINDOW_MIN_WIDTH, OUTER_WINDOW_MIN_HEIGHT,
1145		       OUTER_WINDOW_DEF_WIDTH, OUTER_WINDOW_DEF_HEIGHT,
1146		       OUTER_WINDOW_DEF_X, OUTER_WINDOW_DEF_Y, geom);
1147
1148	if (reverse) {
1149	    back = BlackPixel(dpy,screen);
1150	    fore = WhitePixel(dpy,screen);
1151	} else {
1152	    back = WhitePixel(dpy,screen);
1153	    fore = BlackPixel(dpy,screen);
1154	}
1155
1156	attr.background_pixel = back;
1157	attr.border_pixel = fore;
1158	mask |= (CWBackPixel | CWBorderPixel | CWEventMask);
1159
1160	w = XCreateWindow (dpy, RootWindow (dpy, screen), hints.x, hints.y,
1161			   hints.width, hints.height, borderwidth, 0,
1162			   InputOutput, (Visual *)CopyFromParent,
1163			   mask, &attr);
1164
1165	XSetStandardProperties (dpy, w, name, NULL, (Pixmap) 0,
1166				argv, argc, &hints);
1167
1168	subw = XCreateSimpleWindow (dpy, w, INNER_WINDOW_X, INNER_WINDOW_Y,
1169				    INNER_WINDOW_WIDTH, INNER_WINDOW_HEIGHT,
1170				    INNER_WINDOW_BORDER,
1171				    attr.border_pixel, attr.background_pixel);
1172
1173        wm_protocols = XInternAtom(dpy, "WM_PROTOCOLS", False);
1174        wm_delete_window = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
1175        XSetWMProtocols(dpy, w, &wm_delete_window, 1);
1176
1177	XMapWindow (dpy, subw);		/* map before w so that it appears */
1178	XMapWindow (dpy, w);
1179
1180	printf ("Outer window is 0x%lx, inner window is 0x%lx\n", w, subw);
1181    }
1182
1183    if (xim && xim_style) {
1184        xic = XCreateIC (xim,
1185                         XNInputStyle, xim_style,
1186                         XNClientWindow, w,
1187                         XNFocusWindow, w,
1188                         NULL);
1189
1190        if (xic == NULL) {
1191            fprintf (stderr, "XCreateIC failed\n");
1192        }
1193    }
1194
1195    have_rr = XRRQueryExtension (dpy, &rr_event_base, &rr_error_base);
1196    if (have_rr) {
1197        int rr_major, rr_minor;
1198
1199        if (XRRQueryVersion (dpy, &rr_major, &rr_minor)) {
1200            int rr_mask = event_masks[EVENT_MASK_INDEX_RANDR];
1201
1202            if (rr_major == 1 && rr_minor <= 1) {
1203                rr_mask &= ~(RRCrtcChangeNotifyMask |
1204                             RROutputChangeNotifyMask |
1205                             RROutputPropertyNotifyMask);
1206            }
1207
1208            XRRSelectInput (dpy, w, rr_mask);
1209        }
1210    }
1211
1212    for (done = 0; !done; ) {
1213	XEvent event;
1214
1215	XNextEvent (dpy, &event);
1216
1217	switch (event.type) {
1218	  case KeyPress:
1219	    prologue (&event, "KeyPress");
1220	    do_KeyPress (&event);
1221	    break;
1222	  case KeyRelease:
1223	    prologue (&event, "KeyRelease");
1224	    do_KeyRelease (&event);
1225	    break;
1226	  case ButtonPress:
1227	    prologue (&event, "ButtonPress");
1228	    do_ButtonPress (&event);
1229	    break;
1230	  case ButtonRelease:
1231	    prologue (&event, "ButtonRelease");
1232	    do_ButtonRelease (&event);
1233	    break;
1234	  case MotionNotify:
1235	    prologue (&event, "MotionNotify");
1236	    do_MotionNotify (&event);
1237	    break;
1238	  case EnterNotify:
1239	    prologue (&event, "EnterNotify");
1240	    do_EnterNotify (&event);
1241	    break;
1242	  case LeaveNotify:
1243	    prologue (&event, "LeaveNotify");
1244	    do_LeaveNotify (&event);
1245	    break;
1246	  case FocusIn:
1247	    prologue (&event, "FocusIn");
1248	    do_FocusIn (&event);
1249	    break;
1250	  case FocusOut:
1251	    prologue (&event, "FocusOut");
1252	    do_FocusOut (&event);
1253	    break;
1254	  case KeymapNotify:
1255	    prologue (&event, "KeymapNotify");
1256	    do_KeymapNotify (&event);
1257	    break;
1258	  case Expose:
1259	    prologue (&event, "Expose");
1260	    do_Expose (&event);
1261	    break;
1262	  case GraphicsExpose:
1263	    prologue (&event, "GraphicsExpose");
1264	    do_GraphicsExpose (&event);
1265	    break;
1266	  case NoExpose:
1267	    prologue (&event, "NoExpose");
1268	    do_NoExpose (&event);
1269	    break;
1270	  case VisibilityNotify:
1271	    prologue (&event, "VisibilityNotify");
1272	    do_VisibilityNotify (&event);
1273	    break;
1274	  case CreateNotify:
1275	    prologue (&event, "CreateNotify");
1276	    do_CreateNotify (&event);
1277	    break;
1278	  case DestroyNotify:
1279	    prologue (&event, "DestroyNotify");
1280	    do_DestroyNotify (&event);
1281	    break;
1282	  case UnmapNotify:
1283	    prologue (&event, "UnmapNotify");
1284	    do_UnmapNotify (&event);
1285	    break;
1286	  case MapNotify:
1287	    prologue (&event, "MapNotify");
1288	    do_MapNotify (&event);
1289	    break;
1290	  case MapRequest:
1291	    prologue (&event, "MapRequest");
1292	    do_MapRequest (&event);
1293	    break;
1294	  case ReparentNotify:
1295	    prologue (&event, "ReparentNotify");
1296	    do_ReparentNotify (&event);
1297	    break;
1298	  case ConfigureNotify:
1299	    prologue (&event, "ConfigureNotify");
1300	    do_ConfigureNotify (&event);
1301	    break;
1302	  case ConfigureRequest:
1303	    prologue (&event, "ConfigureRequest");
1304	    do_ConfigureRequest (&event);
1305	    break;
1306	  case GravityNotify:
1307	    prologue (&event, "GravityNotify");
1308	    do_GravityNotify (&event);
1309	    break;
1310	  case ResizeRequest:
1311	    prologue (&event, "ResizeRequest");
1312	    do_ResizeRequest (&event);
1313	    break;
1314	  case CirculateNotify:
1315	    prologue (&event, "CirculateNotify");
1316	    do_CirculateNotify (&event);
1317	    break;
1318	  case CirculateRequest:
1319	    prologue (&event, "CirculateRequest");
1320	    do_CirculateRequest (&event);
1321	    break;
1322	  case PropertyNotify:
1323	    prologue (&event, "PropertyNotify");
1324	    do_PropertyNotify (&event);
1325	    break;
1326	  case SelectionClear:
1327	    prologue (&event, "SelectionClear");
1328	    do_SelectionClear (&event);
1329	    break;
1330	  case SelectionRequest:
1331	    prologue (&event, "SelectionRequest");
1332	    do_SelectionRequest (&event);
1333	    break;
1334	  case SelectionNotify:
1335	    prologue (&event, "SelectionNotify");
1336	    do_SelectionNotify (&event);
1337	    break;
1338	  case ColormapNotify:
1339	    prologue (&event, "ColormapNotify");
1340	    do_ColormapNotify (&event);
1341	    break;
1342	  case ClientMessage:
1343	    prologue (&event, "ClientMessage");
1344	    do_ClientMessage (&event);
1345	    break;
1346	  case MappingNotify:
1347	    prologue (&event, "MappingNotify");
1348	    do_MappingNotify (&event);
1349	    break;
1350	  default:
1351	    if (have_rr) {
1352	        if (event.type == rr_event_base + RRScreenChangeNotify) {
1353	            prologue (&event, "RRScreenChangeNotify");
1354	            do_RRScreenChangeNotify (&event);
1355	            break;
1356	        }
1357	        if (event.type == rr_event_base + RRNotify) {
1358	            do_RRNotify (&event);
1359	            break;
1360	        }
1361	    }
1362	    printf ("Unknown event type %d\n", event.type);
1363	    break;
1364	}
1365	fflush(stdout);
1366    }
1367
1368    XCloseDisplay (dpy);
1369    return 0;
1370}
1371