1f299d47fSmrg/*
2f299d47fSmrg
3f299d47fSmrgCopyright (c) 1988  X Consortium
4f299d47fSmrg
5f299d47fSmrgPermission is hereby granted, free of charge, to any person obtaining
6f299d47fSmrga copy of this software and associated documentation files (the
7f299d47fSmrg"Software"), to deal in the Software without restriction, including
8f299d47fSmrgwithout limitation the rights to use, copy, modify, merge, publish,
9f299d47fSmrgdistribute, sublicense, and/or sell copies of the Software, and to
10f299d47fSmrgpermit persons to whom the Software is furnished to do so, subject to
11f299d47fSmrgthe following conditions:
12f299d47fSmrg
13f299d47fSmrgThe above copyright notice and this permission notice shall be included
14f299d47fSmrgin all copies or substantial portions of the Software.
15f299d47fSmrg
16f299d47fSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17f299d47fSmrgOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18f299d47fSmrgMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19f299d47fSmrgIN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR
20f299d47fSmrgOTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21f299d47fSmrgARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22f299d47fSmrgOTHER DEALINGS IN THE SOFTWARE.
23f299d47fSmrg
24f299d47fSmrgExcept as contained in this notice, the name of the X Consortium shall
25f299d47fSmrgnot be used in advertising or otherwise to promote the sale, use or
26f299d47fSmrgother dealings in this Software without prior written authorization
27f299d47fSmrgfrom the X Consortium.
28f299d47fSmrg
29f299d47fSmrg*/
30f299d47fSmrg
31f299d47fSmrg/*
32f299d47fSmrg * Author:  Jim Fulton, MIT X Consortium
33f299d47fSmrg */
34f299d47fSmrg
351a2dd139Smrg#ifdef HAVE_CONFIG_H
361a2dd139Smrg# include "config.h"
371a2dd139Smrg#endif
3898d75b17Smrg#include <stdarg.h>
39f299d47fSmrg#include <stdio.h>
40f299d47fSmrg#include <stdlib.h>
41f299d47fSmrg#include <ctype.h>
42f299d47fSmrg#include <X11/Xlocale.h>
43f299d47fSmrg#include <X11/Xos.h>
44f299d47fSmrg#include <X11/Xlib.h>
45f299d47fSmrg#include <X11/Xutil.h>
46f299d47fSmrg#include <X11/Xproto.h>
471a2dd139Smrg#include <X11/extensions/Xrandr.h>
48f299d47fSmrg
49f299d47fSmrg#define INNER_WINDOW_WIDTH 50
50f299d47fSmrg#define INNER_WINDOW_HEIGHT 50
51f299d47fSmrg#define INNER_WINDOW_BORDER 4
52f299d47fSmrg#define INNER_WINDOW_X 10
53f299d47fSmrg#define INNER_WINDOW_Y 10
54f299d47fSmrg#define OUTER_WINDOW_MIN_WIDTH (INNER_WINDOW_WIDTH + \
55f299d47fSmrg				2 * (INNER_WINDOW_BORDER + INNER_WINDOW_X))
56f299d47fSmrg#define OUTER_WINDOW_MIN_HEIGHT (INNER_WINDOW_HEIGHT + \
57f299d47fSmrg				2 * (INNER_WINDOW_BORDER + INNER_WINDOW_Y))
58f299d47fSmrg#define OUTER_WINDOW_DEF_WIDTH (OUTER_WINDOW_MIN_WIDTH + 100)
59f299d47fSmrg#define OUTER_WINDOW_DEF_HEIGHT (OUTER_WINDOW_MIN_HEIGHT + 100)
60f299d47fSmrg#define OUTER_WINDOW_DEF_X 100
61f299d47fSmrg#define OUTER_WINDOW_DEF_Y 100
621a2dd139Smrg
63f299d47fSmrg
64f299d47fSmrgtypedef unsigned long Pixel;
65f299d47fSmrg
6699999d39Smrgstatic const char *Yes = "YES";
6799999d39Smrgstatic const char *No = "NO";
6899999d39Smrgstatic const char *Unknown = "unknown";
69f299d47fSmrg
7099999d39Smrgstatic const char *ProgramName;
7199999d39Smrgstatic Display *dpy;
7299999d39Smrgstatic int screen;
73f299d47fSmrg
7499999d39Smrgstatic XIC xic = NULL;
75f299d47fSmrg
7699999d39Smrgstatic Atom wm_delete_window;
7799999d39Smrgstatic Atom wm_protocols;
78f299d47fSmrg
7999999d39Smrgstatic Bool have_rr;
8099999d39Smrgstatic int rr_event_base, rr_error_base;
811a2dd139Smrg
8299999d39Smrgstatic Bool single_line = False;
8398d75b17Smrg
841a2dd139Smrgenum EventMaskIndex {
851a2dd139Smrg    EVENT_MASK_INDEX_CORE,
861a2dd139Smrg    EVENT_MASK_INDEX_RANDR,
871a2dd139Smrg    NUM_EVENT_MASKS
881a2dd139Smrg};
891a2dd139Smrg
9098d75b17Smrgenum OutputFlags {
9198d75b17Smrg    InitialNewLine = 1,
9298d75b17Smrg    Indent         = 2,
9398d75b17Smrg    NewLine        = 4,
9498d75b17Smrg};
9598d75b17Smrg
96da39bf31Smrgstatic void usage(const char *errmsg) _X_NORETURN;
971a2dd139Smrg
9898d75b17Smrgstatic void
9998d75b17Smrgoutput_new_line(void)
10098d75b17Smrg{
10198d75b17Smrg    if (!single_line) {
10298d75b17Smrg        printf("\n");
10398d75b17Smrg    }
10498d75b17Smrg}
10598d75b17Smrg
10698d75b17Smrgstatic void
10798d75b17Smrg_X_ATTRIBUTE_PRINTF(2, 3)
10898d75b17Smrgoutput(enum OutputFlags flags, const char* format, ...)
10998d75b17Smrg{
11098d75b17Smrg    va_list args;
11198d75b17Smrg
11298d75b17Smrg    if (flags & InitialNewLine) {
11398d75b17Smrg        output_new_line();
11498d75b17Smrg    }
11598d75b17Smrg    if (flags & Indent) {
11698d75b17Smrg        printf(single_line ? " " : "    ");
11798d75b17Smrg    }
11898d75b17Smrg
11998d75b17Smrg    va_start(args, format);
12098d75b17Smrg    vprintf(format, args);
12198d75b17Smrg    va_end(args);
12298d75b17Smrg
12398d75b17Smrg    if (flags & NewLine) {
12498d75b17Smrg        output_new_line();
12598d75b17Smrg    }
12698d75b17Smrg}
12798d75b17Smrg
12899999d39Smrgstatic void _X_NORETURN
12998d75b17Smrggraceful_exit(int status)
13098d75b17Smrg{
13198d75b17Smrg    if (single_line) {
13298d75b17Smrg        printf("\n");
13398d75b17Smrg    }
13498d75b17Smrg    fflush(stdout);
13598d75b17Smrg    exit(status);
13698d75b17Smrg}
13798d75b17Smrg
138f299d47fSmrgstatic void
139da39bf31Smrgprologue(XEvent *eventp, const char *event_name)
140f299d47fSmrg{
141f299d47fSmrg    XAnyEvent *e = (XAnyEvent *) eventp;
142f299d47fSmrg
14398d75b17Smrg    output(InitialNewLine | NewLine,
14498d75b17Smrg           "%s event, serial %ld, synthetic %s, window 0x%lx,",
145da39bf31Smrg           event_name, e->serial, e->send_event ? Yes : No, e->window);
146f299d47fSmrg}
147f299d47fSmrg
148f299d47fSmrgstatic void
149da39bf31Smrgdump(char *str, int len)
150f299d47fSmrg{
15198d75b17Smrg    output(0, "(");
152f299d47fSmrg    len--;
153f299d47fSmrg    while (len-- > 0)
15498d75b17Smrg        output(0, "%02x ", (unsigned char) *str++);
15598d75b17Smrg    output(0, "%02x)", (unsigned char) *str++);
156f299d47fSmrg}
157f299d47fSmrg
158f299d47fSmrgstatic void
159da39bf31Smrgdo_KeyPress(XEvent *eventp)
160f299d47fSmrg{
161f299d47fSmrg    XKeyEvent *e = (XKeyEvent *) eventp;
162f299d47fSmrg    KeySym ks;
163f299d47fSmrg    KeyCode kc = 0;
164f299d47fSmrg    Bool kc_set = False;
1651a2dd139Smrg    const char *ksname;
166f299d47fSmrg    int nbytes, nmbbytes = 0;
167da39bf31Smrg    char str[256 + 1];
168f299d47fSmrg    static char *buf = NULL;
169f299d47fSmrg    static int bsize = 8;
170f299d47fSmrg    Status status;
171f299d47fSmrg
172f299d47fSmrg    if (buf == NULL)
173da39bf31Smrg        buf = malloc(bsize);
174f299d47fSmrg
175da39bf31Smrg    nbytes = XLookupString(e, str, 256, &ks, NULL);
176f299d47fSmrg
177f299d47fSmrg    /* not supposed to call XmbLookupString on a key release event */
178f299d47fSmrg    if (e->type == KeyPress && xic) {
179f299d47fSmrg        do {
180da39bf31Smrg            nmbbytes = XmbLookupString(xic, e, buf, bsize - 1, &ks, &status);
181f299d47fSmrg
182f299d47fSmrg            if (status == XBufferOverflow) {
183f299d47fSmrg                bsize = nmbbytes + 1;
184da39bf31Smrg                buf = realloc(buf, bsize);
185f299d47fSmrg            }
186f299d47fSmrg        } while (status == XBufferOverflow);
18799999d39Smrg        buf[nmbbytes] = '\0';
188f299d47fSmrg    }
189f299d47fSmrg
190f299d47fSmrg    if (ks == NoSymbol)
191da39bf31Smrg        ksname = "NoSymbol";
192f299d47fSmrg    else {
193da39bf31Smrg        if (!(ksname = XKeysymToString(ks)))
194da39bf31Smrg            ksname = "(no name)";
195da39bf31Smrg        kc = XKeysymToKeycode(dpy, ks);
196da39bf31Smrg        kc_set = True;
197f299d47fSmrg    }
1981a2dd139Smrg
19998d75b17Smrg    output(Indent | NewLine,
20098d75b17Smrg           "root 0x%lx, subw 0x%lx, time %lu, (%d,%d), root:(%d,%d),",
201da39bf31Smrg           e->root, e->subwindow, e->time, e->x, e->y, e->x_root, e->y_root);
20298d75b17Smrg    output(Indent | NewLine,
20398d75b17Smrg           "state 0x%x, keycode %u (keysym 0x%lx, %s), same_screen %s,",
204da39bf31Smrg           e->state, e->keycode, (unsigned long) ks, ksname,
205da39bf31Smrg           e->same_screen ? Yes : No);
206f299d47fSmrg    if (kc_set && e->keycode != kc)
20798d75b17Smrg        output(Indent | NewLine, "XKeysymToKeycode returns keycode: %u", kc);
208da39bf31Smrg    if (nbytes < 0)
209da39bf31Smrg        nbytes = 0;
210da39bf31Smrg    if (nbytes > 256)
211da39bf31Smrg        nbytes = 256;
212f299d47fSmrg    str[nbytes] = '\0';
21398d75b17Smrg    output(Indent, "XLookupString gives %d bytes: ", nbytes);
214f299d47fSmrg    if (nbytes > 0) {
215da39bf31Smrg        dump(str, nbytes);
21698d75b17Smrg        output(NewLine, " \"%s\"", str);
217da39bf31Smrg    }
218da39bf31Smrg    else {
21998d75b17Smrg        output_new_line();
220f299d47fSmrg    }
221f299d47fSmrg
222f299d47fSmrg    /* not supposed to call XmbLookupString on a key release event */
223f299d47fSmrg    if (e->type == KeyPress && xic) {
22498d75b17Smrg        output(Indent, "XmbLookupString gives %d bytes: ", nmbbytes);
225f299d47fSmrg        if (nmbbytes > 0) {
226da39bf31Smrg            dump(buf, nmbbytes);
22798d75b17Smrg            output(NewLine, " \"%s\"", buf);
228da39bf31Smrg        }
229da39bf31Smrg        else {
23098d75b17Smrg            output_new_line();
231f299d47fSmrg        }
232f299d47fSmrg    }
233f299d47fSmrg
23498d75b17Smrg    output(Indent | NewLine, "XFilterEvent returns: %s",
235da39bf31Smrg           XFilterEvent(eventp, e->window) ? "True" : "False");
236f299d47fSmrg}
237f299d47fSmrg
238f299d47fSmrgstatic void
239da39bf31Smrgdo_KeyRelease(XEvent *eventp)
240f299d47fSmrg{
241da39bf31Smrg    do_KeyPress(eventp);        /* since it has the same info */
242f299d47fSmrg}
243f299d47fSmrg
244f299d47fSmrgstatic void
245da39bf31Smrgdo_ButtonPress(XEvent *eventp)
246f299d47fSmrg{
247f299d47fSmrg    XButtonEvent *e = (XButtonEvent *) eventp;
248f299d47fSmrg
24998d75b17Smrg    output(Indent | NewLine,
25098d75b17Smrg           "root 0x%lx, subw 0x%lx, time %lu, (%d,%d), root:(%d,%d),",
251da39bf31Smrg           e->root, e->subwindow, e->time, e->x, e->y, e->x_root, e->y_root);
25298d75b17Smrg    output(Indent | NewLine, "state 0x%x, button %u, same_screen %s",
253da39bf31Smrg           e->state, e->button, e->same_screen ? Yes : No);
254f299d47fSmrg}
255f299d47fSmrg
256f299d47fSmrgstatic void
257da39bf31Smrgdo_ButtonRelease(XEvent *eventp)
258f299d47fSmrg{
259da39bf31Smrg    do_ButtonPress(eventp);     /* since it has the same info */
260f299d47fSmrg}
261f299d47fSmrg
262f299d47fSmrgstatic void
263da39bf31Smrgdo_MotionNotify(XEvent *eventp)
264f299d47fSmrg{
265f299d47fSmrg    XMotionEvent *e = (XMotionEvent *) eventp;
266f299d47fSmrg
26798d75b17Smrg    output(Indent | NewLine,
26898d75b17Smrg           "root 0x%lx, subw 0x%lx, time %lu, (%d,%d), root:(%d,%d),",
269da39bf31Smrg           e->root, e->subwindow, e->time, e->x, e->y, e->x_root, e->y_root);
27098d75b17Smrg    output(Indent | NewLine, "state 0x%x, is_hint %u, same_screen %s",
271da39bf31Smrg           e->state, e->is_hint, e->same_screen ? Yes : No);
272f299d47fSmrg}
273f299d47fSmrg
274f299d47fSmrgstatic void
275da39bf31Smrgdo_EnterNotify(XEvent *eventp)
276f299d47fSmrg{
277f299d47fSmrg    XCrossingEvent *e = (XCrossingEvent *) eventp;
2781a2dd139Smrg    const char *mode, *detail;
279f299d47fSmrg    char dmode[10], ddetail[10];
280f299d47fSmrg
281f299d47fSmrg    switch (e->mode) {
282da39bf31Smrg    case NotifyNormal:
283da39bf31Smrg        mode = "NotifyNormal";
284da39bf31Smrg        break;
285da39bf31Smrg    case NotifyGrab:
286da39bf31Smrg        mode = "NotifyGrab";
287da39bf31Smrg        break;
288da39bf31Smrg    case NotifyUngrab:
289da39bf31Smrg        mode = "NotifyUngrab";
290da39bf31Smrg        break;
291da39bf31Smrg    case NotifyWhileGrabbed:
292da39bf31Smrg        mode = "NotifyWhileGrabbed";
293da39bf31Smrg        break;
294da39bf31Smrg    default:
295da39bf31Smrg        mode = dmode;
296da39bf31Smrg        snprintf(dmode, sizeof(dmode), "%u", e->mode);
297da39bf31Smrg        break;
298f299d47fSmrg    }
299f299d47fSmrg
300f299d47fSmrg    switch (e->detail) {
301da39bf31Smrg    case NotifyAncestor:
302da39bf31Smrg        detail = "NotifyAncestor";
303da39bf31Smrg        break;
304da39bf31Smrg    case NotifyVirtual:
305da39bf31Smrg        detail = "NotifyVirtual";
306da39bf31Smrg        break;
307da39bf31Smrg    case NotifyInferior:
308da39bf31Smrg        detail = "NotifyInferior";
309da39bf31Smrg        break;
310da39bf31Smrg    case NotifyNonlinear:
311da39bf31Smrg        detail = "NotifyNonlinear";
312da39bf31Smrg        break;
313da39bf31Smrg    case NotifyNonlinearVirtual:
314da39bf31Smrg        detail = "NotifyNonlinearVirtual";
315da39bf31Smrg        break;
316da39bf31Smrg    case NotifyPointer:
317da39bf31Smrg        detail = "NotifyPointer";
318da39bf31Smrg        break;
319da39bf31Smrg    case NotifyPointerRoot:
320da39bf31Smrg        detail = "NotifyPointerRoot";
321da39bf31Smrg        break;
322da39bf31Smrg    case NotifyDetailNone:
323da39bf31Smrg        detail = "NotifyDetailNone";
324da39bf31Smrg        break;
325da39bf31Smrg    default:
326da39bf31Smrg        detail = ddetail;
327da39bf31Smrg        snprintf(ddetail, sizeof(ddetail), "%u", e->detail);
328da39bf31Smrg        break;
329f299d47fSmrg    }
330f299d47fSmrg
33198d75b17Smrg    output(Indent | NewLine,
33298d75b17Smrg           "root 0x%lx, subw 0x%lx, time %lu, (%d,%d), root:(%d,%d),",
333da39bf31Smrg           e->root, e->subwindow, e->time, e->x, e->y, e->x_root, e->y_root);
33498d75b17Smrg    output(Indent | NewLine, "mode %s, detail %s, same_screen %s,",
335da39bf31Smrg           mode, detail, e->same_screen ? Yes : No);
33698d75b17Smrg    output(Indent | NewLine, "focus %s, state %u",
33798d75b17Smrg           e->focus ? Yes : No, e->state);
338f299d47fSmrg}
339f299d47fSmrg
340f299d47fSmrgstatic void
341da39bf31Smrgdo_LeaveNotify(XEvent *eventp)
342f299d47fSmrg{
343da39bf31Smrg    do_EnterNotify(eventp);     /* since it has same information */
344f299d47fSmrg}
345f299d47fSmrg
346f299d47fSmrgstatic void
347da39bf31Smrgdo_FocusIn(XEvent *eventp)
348f299d47fSmrg{
349f299d47fSmrg    XFocusChangeEvent *e = (XFocusChangeEvent *) eventp;
3501a2dd139Smrg    const char *mode, *detail;
351f299d47fSmrg    char dmode[10], ddetail[10];
352f299d47fSmrg
353f299d47fSmrg    switch (e->mode) {
354da39bf31Smrg    case NotifyNormal:
355da39bf31Smrg        mode = "NotifyNormal";
356da39bf31Smrg        break;
357da39bf31Smrg    case NotifyGrab:
358da39bf31Smrg        mode = "NotifyGrab";
359da39bf31Smrg        break;
360da39bf31Smrg    case NotifyUngrab:
361da39bf31Smrg        mode = "NotifyUngrab";
362da39bf31Smrg        break;
363da39bf31Smrg    case NotifyWhileGrabbed:
364da39bf31Smrg        mode = "NotifyWhileGrabbed";
365da39bf31Smrg        break;
366da39bf31Smrg    default:
367da39bf31Smrg        mode = dmode;
368da39bf31Smrg        snprintf(dmode, sizeof(dmode), "%u", e->mode);
369da39bf31Smrg        break;
370f299d47fSmrg    }
371f299d47fSmrg
372f299d47fSmrg    switch (e->detail) {
373da39bf31Smrg    case NotifyAncestor:
374da39bf31Smrg        detail = "NotifyAncestor";
375da39bf31Smrg        break;
376da39bf31Smrg    case NotifyVirtual:
377da39bf31Smrg        detail = "NotifyVirtual";
378da39bf31Smrg        break;
379da39bf31Smrg    case NotifyInferior:
380da39bf31Smrg        detail = "NotifyInferior";
381da39bf31Smrg        break;
382da39bf31Smrg    case NotifyNonlinear:
383da39bf31Smrg        detail = "NotifyNonlinear";
384da39bf31Smrg        break;
385da39bf31Smrg    case NotifyNonlinearVirtual:
386da39bf31Smrg        detail = "NotifyNonlinearVirtual";
387da39bf31Smrg        break;
388da39bf31Smrg    case NotifyPointer:
389da39bf31Smrg        detail = "NotifyPointer";
390da39bf31Smrg        break;
391da39bf31Smrg    case NotifyPointerRoot:
392da39bf31Smrg        detail = "NotifyPointerRoot";
393da39bf31Smrg        break;
394da39bf31Smrg    case NotifyDetailNone:
395da39bf31Smrg        detail = "NotifyDetailNone";
396da39bf31Smrg        break;
397da39bf31Smrg    default:
398da39bf31Smrg        detail = ddetail;
399da39bf31Smrg        snprintf(ddetail, sizeof(ddetail), "%u", e->detail);
400da39bf31Smrg        break;
401f299d47fSmrg    }
402f299d47fSmrg
40398d75b17Smrg    output(Indent | NewLine, "mode %s, detail %s", mode, detail);
404f299d47fSmrg}
405f299d47fSmrg
406f299d47fSmrgstatic void
407da39bf31Smrgdo_FocusOut(XEvent *eventp)
408f299d47fSmrg{
409da39bf31Smrg    do_FocusIn(eventp);         /* since it has same information */
410f299d47fSmrg}
411f299d47fSmrg
412f299d47fSmrgstatic void
413da39bf31Smrgdo_KeymapNotify(XEvent *eventp)
414f299d47fSmrg{
415f299d47fSmrg    XKeymapEvent *e = (XKeymapEvent *) eventp;
416f299d47fSmrg    int i;
417f299d47fSmrg
41898d75b17Smrg    output(Indent, "keys:  ");
419f299d47fSmrg    for (i = 0; i < 32; i++) {
42098d75b17Smrg        if (i == 16 && !single_line) {
42198d75b17Smrg            output(InitialNewLine | Indent, "       ");
42298d75b17Smrg        }
42398d75b17Smrg        output(0, "%-3u ", (unsigned char) e->key_vector[i]);
424f299d47fSmrg    }
42598d75b17Smrg    output_new_line();
426f299d47fSmrg}
427f299d47fSmrg
428f299d47fSmrgstatic void
429da39bf31Smrgdo_Expose(XEvent *eventp)
430f299d47fSmrg{
431f299d47fSmrg    XExposeEvent *e = (XExposeEvent *) eventp;
432f299d47fSmrg
43398d75b17Smrg    output(Indent | NewLine, "(%d,%d), width %d, height %d, count %d",
434da39bf31Smrg           e->x, e->y, e->width, e->height, e->count);
435f299d47fSmrg}
436f299d47fSmrg
437f299d47fSmrgstatic void
438da39bf31Smrgdo_GraphicsExpose(XEvent *eventp)
439f299d47fSmrg{
440f299d47fSmrg    XGraphicsExposeEvent *e = (XGraphicsExposeEvent *) eventp;
4411a2dd139Smrg    const char *m;
442f299d47fSmrg    char mdummy[10];
443f299d47fSmrg
444f299d47fSmrg    switch (e->major_code) {
445da39bf31Smrg    case X_CopyArea:
446da39bf31Smrg        m = "CopyArea";
447da39bf31Smrg        break;
448da39bf31Smrg    case X_CopyPlane:
449da39bf31Smrg        m = "CopyPlane";
450da39bf31Smrg        break;
451da39bf31Smrg    default:
452da39bf31Smrg        m = mdummy;
453da39bf31Smrg        snprintf(mdummy, sizeof(mdummy), "%d", e->major_code);
454da39bf31Smrg        break;
455f299d47fSmrg    }
456f299d47fSmrg
45798d75b17Smrg    output(Indent | NewLine, "(%d,%d), width %d, height %d, count %d,",
458da39bf31Smrg           e->x, e->y, e->width, e->height, e->count);
45998d75b17Smrg    output(Indent | NewLine, "major %s, minor %d", m, e->minor_code);
460f299d47fSmrg}
461f299d47fSmrg
462f299d47fSmrgstatic void
463da39bf31Smrgdo_NoExpose(XEvent *eventp)
464f299d47fSmrg{
465f299d47fSmrg    XNoExposeEvent *e = (XNoExposeEvent *) eventp;
4661a2dd139Smrg    const char *m;
467f299d47fSmrg    char mdummy[10];
468f299d47fSmrg
469f299d47fSmrg    switch (e->major_code) {
470da39bf31Smrg    case X_CopyArea:
471da39bf31Smrg        m = "CopyArea";
472da39bf31Smrg        break;
473da39bf31Smrg    case X_CopyPlane:
474da39bf31Smrg        m = "CopyPlane";
475da39bf31Smrg        break;
476da39bf31Smrg    default:
477da39bf31Smrg        m = mdummy;
478da39bf31Smrg        snprintf(mdummy, sizeof(mdummy), "%d", e->major_code);
479da39bf31Smrg        break;
480f299d47fSmrg    }
481f299d47fSmrg
48298d75b17Smrg    output(Indent | NewLine, "major %s, minor %d", m, e->minor_code);
483f299d47fSmrg    return;
484f299d47fSmrg}
485f299d47fSmrg
486f299d47fSmrgstatic void
487da39bf31Smrgdo_VisibilityNotify(XEvent *eventp)
488f299d47fSmrg{
489f299d47fSmrg    XVisibilityEvent *e = (XVisibilityEvent *) eventp;
4901a2dd139Smrg    const char *v;
491f299d47fSmrg    char vdummy[10];
492f299d47fSmrg
493f299d47fSmrg    switch (e->state) {
494da39bf31Smrg    case VisibilityUnobscured:
495da39bf31Smrg        v = "VisibilityUnobscured";
496da39bf31Smrg        break;
497da39bf31Smrg    case VisibilityPartiallyObscured:
498da39bf31Smrg        v = "VisibilityPartiallyObscured";
499da39bf31Smrg        break;
500da39bf31Smrg    case VisibilityFullyObscured:
501da39bf31Smrg        v = "VisibilityFullyObscured";
502da39bf31Smrg        break;
503da39bf31Smrg    default:
504da39bf31Smrg        v = vdummy;
505da39bf31Smrg        snprintf(vdummy, sizeof(vdummy), "%d", e->state);
506da39bf31Smrg        break;
507f299d47fSmrg    }
508f299d47fSmrg
50998d75b17Smrg    output(Indent | NewLine, "state %s", v);
510f299d47fSmrg}
511f299d47fSmrg
512f299d47fSmrgstatic void
513da39bf31Smrgdo_CreateNotify(XEvent *eventp)
514f299d47fSmrg{
515f299d47fSmrg    XCreateWindowEvent *e = (XCreateWindowEvent *) eventp;
516f299d47fSmrg
51798d75b17Smrg    output(Indent | NewLine,
51898d75b17Smrg           "parent 0x%lx, window 0x%lx, (%d,%d), width %d, height %d",
519da39bf31Smrg           e->parent, e->window, e->x, e->y, e->width, e->height);
52098d75b17Smrg    output(NewLine, "border_width %d, override %s",
521da39bf31Smrg           e->border_width, e->override_redirect ? Yes : No);
522f299d47fSmrg}
523f299d47fSmrg
524f299d47fSmrgstatic void
525da39bf31Smrgdo_DestroyNotify(XEvent *eventp)
526f299d47fSmrg{
527f299d47fSmrg    XDestroyWindowEvent *e = (XDestroyWindowEvent *) eventp;
528f299d47fSmrg
52998d75b17Smrg    output(Indent | NewLine, "event 0x%lx, window 0x%lx", e->event, e->window);
530f299d47fSmrg}
531f299d47fSmrg
532f299d47fSmrgstatic void
533da39bf31Smrgdo_UnmapNotify(XEvent *eventp)
534f299d47fSmrg{
535f299d47fSmrg    XUnmapEvent *e = (XUnmapEvent *) eventp;
536f299d47fSmrg
53798d75b17Smrg    output(Indent | NewLine, "event 0x%lx, window 0x%lx, from_configure %s",
538da39bf31Smrg           e->event, e->window, e->from_configure ? Yes : No);
539f299d47fSmrg}
540f299d47fSmrg
541f299d47fSmrgstatic void
542da39bf31Smrgdo_MapNotify(XEvent *eventp)
543f299d47fSmrg{
544f299d47fSmrg    XMapEvent *e = (XMapEvent *) eventp;
545f299d47fSmrg
54698d75b17Smrg    output(Indent | NewLine, "event 0x%lx, window 0x%lx, override %s",
547da39bf31Smrg           e->event, e->window, e->override_redirect ? Yes : No);
548f299d47fSmrg}
549f299d47fSmrg
550f299d47fSmrgstatic void
551da39bf31Smrgdo_MapRequest(XEvent *eventp)
552f299d47fSmrg{
553f299d47fSmrg    XMapRequestEvent *e = (XMapRequestEvent *) eventp;
554f299d47fSmrg
55598d75b17Smrg    output(Indent | NewLine, "parent 0x%lx, window 0x%lx",
55698d75b17Smrg           e->parent, e->window);
557f299d47fSmrg}
558f299d47fSmrg
559f299d47fSmrgstatic void
560da39bf31Smrgdo_ReparentNotify(XEvent *eventp)
561f299d47fSmrg{
562f299d47fSmrg    XReparentEvent *e = (XReparentEvent *) eventp;
563f299d47fSmrg
56498d75b17Smrg    output(Indent | NewLine, "event 0x%lx, window 0x%lx, parent 0x%lx,",
565da39bf31Smrg           e->event, e->window, e->parent);
56698d75b17Smrg    output(Indent | NewLine, "(%d,%d), override %s", e->x, e->y,
567da39bf31Smrg           e->override_redirect ? Yes : No);
568f299d47fSmrg}
569f299d47fSmrg
570f299d47fSmrgstatic void
571da39bf31Smrgdo_ConfigureNotify(XEvent *eventp)
572f299d47fSmrg{
573f299d47fSmrg    XConfigureEvent *e = (XConfigureEvent *) eventp;
574f299d47fSmrg
57598d75b17Smrg    output(Indent | NewLine,
57698d75b17Smrg           "event 0x%lx, window 0x%lx, (%d,%d), width %d, height %d,",
577da39bf31Smrg           e->event, e->window, e->x, e->y, e->width, e->height);
57898d75b17Smrg    output(Indent | NewLine, "border_width %d, above 0x%lx, override %s",
579da39bf31Smrg           e->border_width, e->above, e->override_redirect ? Yes : No);
580f299d47fSmrg}
581f299d47fSmrg
582f299d47fSmrgstatic void
583da39bf31Smrgdo_ConfigureRequest(XEvent *eventp)
584f299d47fSmrg{
585f299d47fSmrg    XConfigureRequestEvent *e = (XConfigureRequestEvent *) eventp;
5861a2dd139Smrg    const char *detail;
587f299d47fSmrg    char ddummy[10];
588f299d47fSmrg
589f299d47fSmrg    switch (e->detail) {
590da39bf31Smrg    case Above:
591da39bf31Smrg        detail = "Above";
592da39bf31Smrg        break;
593da39bf31Smrg    case Below:
594da39bf31Smrg        detail = "Below";
595da39bf31Smrg        break;
596da39bf31Smrg    case TopIf:
597da39bf31Smrg        detail = "TopIf";
598da39bf31Smrg        break;
599da39bf31Smrg    case BottomIf:
600da39bf31Smrg        detail = "BottomIf";
601da39bf31Smrg        break;
602da39bf31Smrg    case Opposite:
603da39bf31Smrg        detail = "Opposite";
604da39bf31Smrg        break;
605da39bf31Smrg    default:
606da39bf31Smrg        detail = ddummy;
607da39bf31Smrg        snprintf(ddummy, sizeof(ddummy), "%d", e->detail);
608da39bf31Smrg        break;
609f299d47fSmrg    }
610f299d47fSmrg
61198d75b17Smrg    output(Indent | NewLine,
61298d75b17Smrg           "parent 0x%lx, window 0x%lx, (%d,%d), width %d, height %d,",
613da39bf31Smrg           e->parent, e->window, e->x, e->y, e->width, e->height);
61498d75b17Smrg    output(Indent | NewLine,
61598d75b17Smrg           "border_width %d, above 0x%lx, detail %s, value 0x%lx",
616da39bf31Smrg           e->border_width, e->above, detail, e->value_mask);
617f299d47fSmrg}
618f299d47fSmrg
619f299d47fSmrgstatic void
620da39bf31Smrgdo_GravityNotify(XEvent *eventp)
621f299d47fSmrg{
622f299d47fSmrg    XGravityEvent *e = (XGravityEvent *) eventp;
623f299d47fSmrg
62498d75b17Smrg    output(Indent | NewLine, "event 0x%lx, window 0x%lx, (%d,%d)",
625da39bf31Smrg           e->event, e->window, e->x, e->y);
626f299d47fSmrg}
627f299d47fSmrg
628f299d47fSmrgstatic void
629da39bf31Smrgdo_ResizeRequest(XEvent *eventp)
630f299d47fSmrg{
631f299d47fSmrg    XResizeRequestEvent *e = (XResizeRequestEvent *) eventp;
632f299d47fSmrg
63398d75b17Smrg    output(Indent | NewLine, "width %d, height %d", e->width, e->height);
634f299d47fSmrg}
635f299d47fSmrg
636f299d47fSmrgstatic void
637da39bf31Smrgdo_CirculateNotify(XEvent *eventp)
638f299d47fSmrg{
639f299d47fSmrg    XCirculateEvent *e = (XCirculateEvent *) eventp;
6401a2dd139Smrg    const char *p;
641f299d47fSmrg    char pdummy[10];
642f299d47fSmrg
643f299d47fSmrg    switch (e->place) {
644da39bf31Smrg    case PlaceOnTop:
645da39bf31Smrg        p = "PlaceOnTop";
646da39bf31Smrg        break;
647da39bf31Smrg    case PlaceOnBottom:
648da39bf31Smrg        p = "PlaceOnBottom";
649da39bf31Smrg        break;
650da39bf31Smrg    default:
651da39bf31Smrg        p = pdummy;
652da39bf31Smrg        snprintf(pdummy, sizeof(pdummy), "%d", e->place);
653da39bf31Smrg        break;
654f299d47fSmrg    }
655f299d47fSmrg
65698d75b17Smrg    output(Indent | NewLine, "event 0x%lx, window 0x%lx, place %s",
65798d75b17Smrg           e->event, e->window, p);
658f299d47fSmrg}
659f299d47fSmrg
660f299d47fSmrgstatic void
661da39bf31Smrgdo_CirculateRequest(XEvent *eventp)
662f299d47fSmrg{
663f299d47fSmrg    XCirculateRequestEvent *e = (XCirculateRequestEvent *) eventp;
6641a2dd139Smrg    const char *p;
665f299d47fSmrg    char pdummy[10];
666f299d47fSmrg
667f299d47fSmrg    switch (e->place) {
668da39bf31Smrg    case PlaceOnTop:
669da39bf31Smrg        p = "PlaceOnTop";
670da39bf31Smrg        break;
671da39bf31Smrg    case PlaceOnBottom:
672da39bf31Smrg        p = "PlaceOnBottom";
673da39bf31Smrg        break;
674da39bf31Smrg    default:
675da39bf31Smrg        p = pdummy;
676da39bf31Smrg        snprintf(pdummy, sizeof(pdummy), "%d", e->place);
677da39bf31Smrg        break;
678f299d47fSmrg    }
679f299d47fSmrg
68098d75b17Smrg    output(Indent | NewLine, "parent 0x%lx, window 0x%lx, place %s",
681da39bf31Smrg           e->parent, e->window, p);
682f299d47fSmrg}
683f299d47fSmrg
684f299d47fSmrgstatic void
685da39bf31Smrgdo_PropertyNotify(XEvent *eventp)
686f299d47fSmrg{
687f299d47fSmrg    XPropertyEvent *e = (XPropertyEvent *) eventp;
688da39bf31Smrg    char *aname = XGetAtomName(dpy, e->atom);
6891a2dd139Smrg    const char *s;
690f299d47fSmrg    char sdummy[10];
691f299d47fSmrg
692f299d47fSmrg    switch (e->state) {
693da39bf31Smrg    case PropertyNewValue:
694da39bf31Smrg        s = "PropertyNewValue";
695da39bf31Smrg        break;
696da39bf31Smrg    case PropertyDelete:
697da39bf31Smrg        s = "PropertyDelete";
698da39bf31Smrg        break;
699da39bf31Smrg    default:
700da39bf31Smrg        s = sdummy;
701da39bf31Smrg        snprintf(sdummy, sizeof(sdummy), "%d", e->state);
702da39bf31Smrg        break;
703f299d47fSmrg    }
704f299d47fSmrg
70598d75b17Smrg    output(Indent | NewLine, "atom 0x%lx (%s), time %lu, state %s",
706da39bf31Smrg           e->atom, aname ? aname : Unknown, e->time, s);
707f299d47fSmrg
708da39bf31Smrg    XFree(aname);
709f299d47fSmrg}
710f299d47fSmrg
711f299d47fSmrgstatic void
712da39bf31Smrgdo_SelectionClear(XEvent *eventp)
713f299d47fSmrg{
714f299d47fSmrg    XSelectionClearEvent *e = (XSelectionClearEvent *) eventp;
715da39bf31Smrg    char *sname = XGetAtomName(dpy, e->selection);
716f299d47fSmrg
71798d75b17Smrg    output(Indent | NewLine, "selection 0x%lx (%s), time %lu",
718da39bf31Smrg           e->selection, sname ? sname : Unknown, e->time);
719f299d47fSmrg
720da39bf31Smrg    XFree(sname);
721f299d47fSmrg}
722f299d47fSmrg
723f299d47fSmrgstatic void
724da39bf31Smrgdo_SelectionRequest(XEvent *eventp)
725f299d47fSmrg{
726f299d47fSmrg    XSelectionRequestEvent *e = (XSelectionRequestEvent *) eventp;
727da39bf31Smrg    char *sname = XGetAtomName(dpy, e->selection);
728da39bf31Smrg    char *tname = XGetAtomName(dpy, e->target);
729da39bf31Smrg    char *pname = XGetAtomName(dpy, e->property);
730da39bf31Smrg
73198d75b17Smrg    output(Indent | NewLine,
73298d75b17Smrg           "owner 0x%lx, requestor 0x%lx, selection 0x%lx (%s),",
733da39bf31Smrg           e->owner, e->requestor, e->selection, sname ? sname : Unknown);
73498d75b17Smrg    output(Indent | NewLine,
73598d75b17Smrg           "target 0x%lx (%s), property 0x%lx (%s), time %lu",
736da39bf31Smrg           e->target, tname ? tname : Unknown, e->property,
737da39bf31Smrg           pname ? pname : Unknown, e->time);
738da39bf31Smrg
739da39bf31Smrg    XFree(sname);
740da39bf31Smrg    XFree(tname);
741da39bf31Smrg    XFree(pname);
742f299d47fSmrg}
743f299d47fSmrg
744f299d47fSmrgstatic void
745da39bf31Smrgdo_SelectionNotify(XEvent *eventp)
746f299d47fSmrg{
747f299d47fSmrg    XSelectionEvent *e = (XSelectionEvent *) eventp;
748da39bf31Smrg    char *sname = XGetAtomName(dpy, e->selection);
749da39bf31Smrg    char *tname = XGetAtomName(dpy, e->target);
750da39bf31Smrg    char *pname = XGetAtomName(dpy, e->property);
751da39bf31Smrg
75298d75b17Smrg    output(Indent | NewLine, "selection 0x%lx (%s), target 0x%lx (%s),",
753da39bf31Smrg           e->selection, sname ? sname : Unknown, e->target,
754da39bf31Smrg           tname ? tname : Unknown);
75598d75b17Smrg    output(Indent | NewLine, "property 0x%lx (%s), time %lu",
756da39bf31Smrg           e->property, pname ? pname : Unknown, e->time);
757da39bf31Smrg
758da39bf31Smrg    XFree(sname);
759da39bf31Smrg    XFree(tname);
760da39bf31Smrg    XFree(pname);
761f299d47fSmrg}
762f299d47fSmrg
763f299d47fSmrgstatic void
764da39bf31Smrgdo_ColormapNotify(XEvent *eventp)
765f299d47fSmrg{
766f299d47fSmrg    XColormapEvent *e = (XColormapEvent *) eventp;
7671a2dd139Smrg    const char *s;
768f299d47fSmrg    char sdummy[10];
769f299d47fSmrg
770f299d47fSmrg    switch (e->state) {
771da39bf31Smrg    case ColormapInstalled:
772da39bf31Smrg        s = "ColormapInstalled";
773da39bf31Smrg        break;
774da39bf31Smrg    case ColormapUninstalled:
775da39bf31Smrg        s = "ColormapUninstalled";
776da39bf31Smrg        break;
777da39bf31Smrg    default:
778da39bf31Smrg        s = sdummy;
779da39bf31Smrg        snprintf(sdummy, sizeof(sdummy), "%d", e->state);
780da39bf31Smrg        break;
781f299d47fSmrg    }
782f299d47fSmrg
78398d75b17Smrg    output(Indent | NewLine, "colormap 0x%lx, new %s, state %s",
784da39bf31Smrg           e->colormap, e->new ? Yes : No, s);
785f299d47fSmrg}
786f299d47fSmrg
787f299d47fSmrgstatic void
788da39bf31Smrgdo_ClientMessage(XEvent *eventp)
789f299d47fSmrg{
790f299d47fSmrg    XClientMessageEvent *e = (XClientMessageEvent *) eventp;
791da39bf31Smrg
792da39bf31Smrg    char *mname = XGetAtomName(dpy, e->message_type);
793f299d47fSmrg
794f299d47fSmrg    if (e->message_type == wm_protocols) {
795da39bf31Smrg        char *message = XGetAtomName(dpy, e->data.l[0]);
796da39bf31Smrg
79798d75b17Smrg        output(Indent | NewLine,
79898d75b17Smrg               "message_type 0x%lx (%s), format %d, message 0x%lx (%s)",
799da39bf31Smrg               e->message_type, mname ? mname : Unknown, e->format,
800da39bf31Smrg               e->data.l[0], message);
801da39bf31Smrg        XFree(message);
802f299d47fSmrg    }
803f299d47fSmrg    else {
80498d75b17Smrg        output(Indent | NewLine, "message_type 0x%lx (%s), format %d",
805da39bf31Smrg               e->message_type, mname ? mname : Unknown, e->format);
806f299d47fSmrg    }
807f299d47fSmrg
808da39bf31Smrg    XFree(mname);
809f299d47fSmrg
8101a2dd139Smrg    if (e->format == 32
8111a2dd139Smrg        && e->message_type == wm_protocols
81298d75b17Smrg        && (Atom) e->data.l[0] == wm_delete_window
81398d75b17Smrg    ) {
81498d75b17Smrg        graceful_exit(0);
81598d75b17Smrg    }
816f299d47fSmrg}
817f299d47fSmrg
818f299d47fSmrgstatic void
819da39bf31Smrgdo_MappingNotify(XEvent *eventp)
820f299d47fSmrg{
821f299d47fSmrg    XMappingEvent *e = (XMappingEvent *) eventp;
8221a2dd139Smrg    const char *r;
823f299d47fSmrg    char rdummy[10];
824f299d47fSmrg
825f299d47fSmrg    switch (e->request) {
826da39bf31Smrg    case MappingModifier:
827da39bf31Smrg        r = "MappingModifier";
828da39bf31Smrg        break;
829da39bf31Smrg    case MappingKeyboard:
830da39bf31Smrg        r = "MappingKeyboard";
831da39bf31Smrg        break;
832da39bf31Smrg    case MappingPointer:
833da39bf31Smrg        r = "MappingPointer";
834da39bf31Smrg        break;
835da39bf31Smrg    default:
836da39bf31Smrg        r = rdummy;
837da39bf31Smrg        snprintf(rdummy, sizeof(rdummy), "%d", e->request);
838da39bf31Smrg        break;
839f299d47fSmrg    }
840f299d47fSmrg
84198d75b17Smrg    output(Indent | NewLine, "request %s, first_keycode %d, count %d",
842da39bf31Smrg           r, e->first_keycode, e->count);
843f299d47fSmrg    XRefreshKeyboardMapping(e);
844f299d47fSmrg}
845f299d47fSmrg
8461a2dd139Smrgstatic void
847da39bf31Smrgprint_SubPixelOrder(SubpixelOrder subpixel_order)
8481a2dd139Smrg{
8491a2dd139Smrg    switch (subpixel_order) {
850da39bf31Smrg    case SubPixelUnknown:
85198d75b17Smrg        output(0, "SubPixelUnknown");
852da39bf31Smrg        return;
853da39bf31Smrg    case SubPixelHorizontalRGB:
85498d75b17Smrg        output(0, "SubPixelHorizontalRGB");
855da39bf31Smrg        return;
856da39bf31Smrg    case SubPixelHorizontalBGR:
85798d75b17Smrg        output(0, "SubPixelHorizontalBGR");
858da39bf31Smrg        return;
859da39bf31Smrg    case SubPixelVerticalRGB:
86098d75b17Smrg        output(0, "SubPixelVerticalRGB");
861da39bf31Smrg        return;
862da39bf31Smrg    case SubPixelVerticalBGR:
86398d75b17Smrg        output(0, "SubPixelVerticalBGR");
864da39bf31Smrg        return;
865da39bf31Smrg    case SubPixelNone:
86698d75b17Smrg        output(0, "SubPixelNone");
867da39bf31Smrg        return;
868da39bf31Smrg    default:
86998d75b17Smrg        output(0, "%d", subpixel_order);
8701a2dd139Smrg    }
8711a2dd139Smrg}
8721a2dd139Smrg
8731a2dd139Smrgstatic void
874da39bf31Smrgprint_Rotation(Rotation rotation)
8751a2dd139Smrg{
8761a2dd139Smrg    if (rotation & RR_Rotate_0)
87798d75b17Smrg        output(0, "RR_Rotate_0");
8781a2dd139Smrg    else if (rotation & RR_Rotate_90)
87998d75b17Smrg        output(0, "RR_Rotate_90");
8801a2dd139Smrg    else if (rotation & RR_Rotate_180)
88198d75b17Smrg        output(0, "RR_Rotate_180");
8821a2dd139Smrg    else if (rotation & RR_Rotate_270)
88398d75b17Smrg        output(0, "RR_Rotate_270");
8841a2dd139Smrg    else {
88598d75b17Smrg        output(0, "%d", rotation);
8861a2dd139Smrg        return;
8871a2dd139Smrg    }
8881a2dd139Smrg    if (rotation & RR_Reflect_X)
88998d75b17Smrg        output(0, ", RR_Reflect_X");
8901a2dd139Smrg    if (rotation & RR_Reflect_Y)
89198d75b17Smrg        output(0, ", RR_Reflect_Y");
8921a2dd139Smrg}
893f299d47fSmrg
8941a2dd139Smrgstatic void
895da39bf31Smrgprint_Connection(Connection connection)
8961a2dd139Smrg{
8971a2dd139Smrg    switch (connection) {
898da39bf31Smrg    case RR_Connected:
89998d75b17Smrg        output(0, "RR_Connected");
900da39bf31Smrg        return;
901da39bf31Smrg    case RR_Disconnected:
90298d75b17Smrg        output(0, "RR_Disconnected");
903da39bf31Smrg        return;
904da39bf31Smrg    case RR_UnknownConnection:
90598d75b17Smrg        output(0, "RR_UnknownConnection");
906da39bf31Smrg        return;
907da39bf31Smrg    default:
90898d75b17Smrg        output(0, "%d", connection);
9091a2dd139Smrg    }
9101a2dd139Smrg}
911f299d47fSmrg
912f299d47fSmrgstatic void
913da39bf31Smrgdo_RRScreenChangeNotify(XEvent *eventp)
9141a2dd139Smrg{
9151a2dd139Smrg    XRRScreenChangeNotifyEvent *e = (XRRScreenChangeNotifyEvent *) eventp;
9161a2dd139Smrg
917da39bf31Smrg    XRRUpdateConfiguration(eventp);
91898d75b17Smrg    output(Indent | NewLine, "root 0x%lx, timestamp %lu, config_timestamp %lu",
919da39bf31Smrg           e->root, e->timestamp, e->config_timestamp);
92098d75b17Smrg    output(Indent, "size_index %hu", e->size_index);
92198d75b17Smrg    output(0, ", subpixel_order ");
922da39bf31Smrg    print_SubPixelOrder(e->subpixel_order);
92398d75b17Smrg    output(InitialNewLine | Indent, "rotation ");
924da39bf31Smrg    print_Rotation(e->rotation);
92598d75b17Smrg    output(InitialNewLine | Indent | NewLine,
92698d75b17Smrg           "width %d, height %d, mwidth %d, mheight %d",
9271a2dd139Smrg           e->width, e->height, e->mwidth, e->mheight);
9281a2dd139Smrg}
9291a2dd139Smrg
9301a2dd139Smrgstatic void
931da39bf31Smrgdo_RRNotify_OutputChange(XEvent *eventp, XRRScreenResources *screen_resources)
9321a2dd139Smrg{
9331a2dd139Smrg    XRROutputChangeNotifyEvent *e = (XRROutputChangeNotifyEvent *) eventp;
9341a2dd139Smrg    XRROutputInfo *output_info = NULL;
9351a2dd139Smrg    XRRModeInfo *mode_info = NULL;
9361a2dd139Smrg
9371a2dd139Smrg    if (screen_resources) {
9381a2dd139Smrg        int i;
9391a2dd139Smrg
940da39bf31Smrg        output_info = XRRGetOutputInfo(dpy, screen_resources, e->output);
9411a2dd139Smrg        for (i = 0; i < screen_resources->nmode; i++)
9421a2dd139Smrg            if (screen_resources->modes[i].id == e->mode) {
943da39bf31Smrg                mode_info = &screen_resources->modes[i];
944da39bf31Smrg                break;
9451a2dd139Smrg            }
9461a2dd139Smrg    }
94798d75b17Smrg    output(Indent | NewLine, "subtype XRROutputChangeNotifyEvent");
9481a2dd139Smrg    if (output_info)
94998d75b17Smrg        output(Indent, "output %s, ", output_info->name);
9501a2dd139Smrg    else
95198d75b17Smrg        output(Indent, "output %lu, ", e->output);
9521a2dd139Smrg    if (e->crtc)
95398d75b17Smrg        output(0, "crtc %lu, ", e->crtc);
9541a2dd139Smrg    else
95598d75b17Smrg        output(0, "crtc None, ");
9561a2dd139Smrg    if (mode_info)
95798d75b17Smrg        output(NewLine, "mode %s (%dx%d)", mode_info->name, mode_info->width,
958da39bf31Smrg               mode_info->height);
9591a2dd139Smrg    else if (e->mode)
96098d75b17Smrg        output(NewLine, "mode %lu", e->mode);
9611a2dd139Smrg    else
96298d75b17Smrg        output(NewLine, "mode None");
96398d75b17Smrg    output(Indent, "rotation ");
964da39bf31Smrg    print_Rotation(e->rotation);
96598d75b17Smrg    output(InitialNewLine | Indent, "connection ");
966da39bf31Smrg    print_Connection(e->connection);
96798d75b17Smrg    output(0, ", subpixel_order ");
968da39bf31Smrg    print_SubPixelOrder(e->subpixel_order);
96998d75b17Smrg    output_new_line();
970da39bf31Smrg    XRRFreeOutputInfo(output_info);
9711a2dd139Smrg}
9721a2dd139Smrg
9731a2dd139Smrgstatic void
974da39bf31Smrgdo_RRNotify_CrtcChange(XEvent *eventp, XRRScreenResources *screen_resources)
9751a2dd139Smrg{
9761a2dd139Smrg    XRRCrtcChangeNotifyEvent *e = (XRRCrtcChangeNotifyEvent *) eventp;
9771a2dd139Smrg    XRRModeInfo *mode_info = NULL;
9781a2dd139Smrg
9791a2dd139Smrg    if (screen_resources) {
9801a2dd139Smrg        int i;
9811a2dd139Smrg
9821a2dd139Smrg        for (i = 0; i < screen_resources->nmode; i++)
9831a2dd139Smrg            if (screen_resources->modes[i].id == e->mode) {
984da39bf31Smrg                mode_info = &screen_resources->modes[i];
985da39bf31Smrg                break;
9861a2dd139Smrg            }
9871a2dd139Smrg    }
98898d75b17Smrg    output(Indent | NewLine, "subtype XRRCrtcChangeNotifyEvent");
9891a2dd139Smrg    if (e->crtc)
99098d75b17Smrg        output(Indent, "crtc %lu, ", e->crtc);
9911a2dd139Smrg    else
99298d75b17Smrg        output(Indent, "crtc None, ");
9931a2dd139Smrg    if (mode_info)
99498d75b17Smrg        output(0, "mode %s, ", mode_info->name);
9951a2dd139Smrg    else if (e->mode)
99698d75b17Smrg        output(0, "mode %lu, ", e->mode);
9971a2dd139Smrg    else
99898d75b17Smrg        output(0, "mode None, ");
99998d75b17Smrg    output(0, "rotation ");
1000da39bf31Smrg    print_Rotation(e->rotation);
100198d75b17Smrg    output(InitialNewLine | Indent | NewLine, "x %d, y %d, width %d, height %d",
1002da39bf31Smrg           e->x, e->y, e->width, e->height);
10031a2dd139Smrg}
10041a2dd139Smrg
10051a2dd139Smrgstatic void
1006da39bf31Smrgdo_RRNotify_OutputProperty(XEvent *eventp,
1007da39bf31Smrg                           XRRScreenResources *screen_resources)
10081a2dd139Smrg{
10091a2dd139Smrg    XRROutputPropertyNotifyEvent *e = (XRROutputPropertyNotifyEvent *) eventp;
10101a2dd139Smrg    XRROutputInfo *output_info = NULL;
1011da39bf31Smrg    char *property = XGetAtomName(dpy, e->property);
10121a2dd139Smrg
10131a2dd139Smrg    if (screen_resources)
1014da39bf31Smrg        output_info = XRRGetOutputInfo(dpy, screen_resources, e->output);
101598d75b17Smrg    output(Indent | NewLine, "subtype XRROutputPropertyChangeNotifyEvent");
10161a2dd139Smrg    if (output_info)
101798d75b17Smrg        output(Indent, "output %s, ", output_info->name);
10181a2dd139Smrg    else
101998d75b17Smrg        output(Indent, "output %lu, ", e->output);
102098d75b17Smrg    output(0, "property %s, timestamp %lu, state ", property, e->timestamp);
10211a2dd139Smrg    if (e->state == PropertyNewValue)
102298d75b17Smrg        output(NewLine, "NewValue");
10231a2dd139Smrg    else if (e->state == PropertyDelete)
102498d75b17Smrg        output(NewLine, "Delete");
10251a2dd139Smrg    else
102698d75b17Smrg        output(NewLine, "%d", e->state);
1027da39bf31Smrg    XRRFreeOutputInfo(output_info);
1028da39bf31Smrg    XFree(property);
10291a2dd139Smrg}
10301a2dd139Smrg
10311a2dd139Smrgstatic void
1032da39bf31Smrgdo_RRNotify(XEvent *eventp)
10331a2dd139Smrg{
10341a2dd139Smrg    XRRNotifyEvent *e = (XRRNotifyEvent *) eventp;
10351a2dd139Smrg    XRRScreenResources *screen_resources;
10361a2dd139Smrg
1037da39bf31Smrg    XRRUpdateConfiguration(eventp);
1038da39bf31Smrg    screen_resources = XRRGetScreenResources(dpy, e->window);
1039da39bf31Smrg    prologue(eventp, "RRNotify");
10401a2dd139Smrg    switch (e->subtype) {
1041da39bf31Smrg    case RRNotify_OutputChange:
1042da39bf31Smrg        do_RRNotify_OutputChange(eventp, screen_resources);
1043da39bf31Smrg        break;
1044da39bf31Smrg    case RRNotify_CrtcChange:
1045da39bf31Smrg        do_RRNotify_CrtcChange(eventp, screen_resources);
1046da39bf31Smrg        break;
1047da39bf31Smrg    case RRNotify_OutputProperty:
1048da39bf31Smrg        do_RRNotify_OutputProperty(eventp, screen_resources);
1049da39bf31Smrg        break;
1050da39bf31Smrg    default:
105198d75b17Smrg        output(Indent | NewLine, "subtype %d", e->subtype);
10521a2dd139Smrg    }
1053da39bf31Smrg    XRRFreeScreenResources(screen_resources);
10541a2dd139Smrg}
10551a2dd139Smrg
10561a2dd139Smrgstatic void
1057da39bf31Smrgset_sizehints(XSizeHints *hintp, int min_width, int min_height,
1058da39bf31Smrg              int defwidth, int defheight, int defx, int defy, char *geom)
1059f299d47fSmrg{
1060f299d47fSmrg    int geom_result;
1061f299d47fSmrg
1062f299d47fSmrg    /* set the size hints, algorithm from xlib xbiff */
1063f299d47fSmrg
1064f299d47fSmrg    hintp->width = hintp->min_width = min_width;
1065f299d47fSmrg    hintp->height = hintp->min_height = min_height;
1066f299d47fSmrg    hintp->flags = PMinSize;
1067f299d47fSmrg    hintp->x = hintp->y = 0;
1068f299d47fSmrg    geom_result = NoValue;
1069f299d47fSmrg    if (geom != NULL) {
1070da39bf31Smrg        geom_result = XParseGeometry(geom, &hintp->x, &hintp->y,
1071da39bf31Smrg                                     (unsigned int *) &hintp->width,
1072da39bf31Smrg                                     (unsigned int *) &hintp->height);
1073da39bf31Smrg        if ((geom_result & WidthValue) && (geom_result & HeightValue)) {
1074f299d47fSmrg#ifndef max
1075f299d47fSmrg#define max(a,b) ((a) > (b) ? (a) : (b))
1076f299d47fSmrg#endif
1077da39bf31Smrg            hintp->width = max(hintp->width, hintp->min_width);
1078da39bf31Smrg            hintp->height = max(hintp->height, hintp->min_height);
1079da39bf31Smrg            hintp->flags |= USSize;
1080da39bf31Smrg        }
1081da39bf31Smrg        if ((geom_result & XValue) && (geom_result & YValue)) {
1082da39bf31Smrg            hintp->flags += USPosition;
1083da39bf31Smrg        }
1084f299d47fSmrg    }
1085f299d47fSmrg    if (!(hintp->flags & USSize)) {
1086da39bf31Smrg        hintp->width = defwidth;
1087da39bf31Smrg        hintp->height = defheight;
1088da39bf31Smrg        hintp->flags |= PSize;
1089f299d47fSmrg    }
1090f299d47fSmrg/*
1091f299d47fSmrg    if (!(hintp->flags & USPosition)) {
1092f299d47fSmrg	hintp->x = defx;
1093f299d47fSmrg	hintp->y = defy;
1094f299d47fSmrg	hintp->flags |= PPosition;
1095f299d47fSmrg    }
1096f299d47fSmrg */
1097f299d47fSmrg    if (geom_result & XNegative) {
1098da39bf31Smrg        hintp->x = DisplayWidth(dpy, DefaultScreen(dpy)) + hintp->x -
1099da39bf31Smrg            hintp->width;
1100f299d47fSmrg    }
1101f299d47fSmrg    if (geom_result & YNegative) {
1102da39bf31Smrg        hintp->y = DisplayHeight(dpy, DefaultScreen(dpy)) + hintp->y -
1103da39bf31Smrg            hintp->height;
1104f299d47fSmrg    }
1105f299d47fSmrg}
1106f299d47fSmrg
1107f299d47fSmrgstatic void
1108da39bf31Smrgusage(const char *errmsg)
1109f299d47fSmrg{
1110da39bf31Smrg    const char *msg =
1111da39bf31Smrg"    -display displayname                X server to contact\n"
1112da39bf31Smrg"    -geometry geom                      size and location of window\n"
1113da39bf31Smrg"    -bw pixels                          border width in pixels\n"
1114da39bf31Smrg"    -bs {NotUseful,WhenMapped,Always}   backingstore attribute\n"
1115da39bf31Smrg"    -id windowid                        use existing window\n"
1116da39bf31Smrg"    -root                               use root window\n"
1117da39bf31Smrg"    -s                                  set save-unders attribute\n"
1118da39bf31Smrg"    -name string                        window name\n"
1119da39bf31Smrg"    -rv                                 reverse video\n"
1120da39bf31Smrg"    -event event_mask                   select 'event_mask' events\n"
1121da39bf31Smrg"           Supported event masks: keyboard mouse expose visibility structure\n"
1122da39bf31Smrg"                                  substructure focus property colormap\n"
1123da39bf31Smrg"                                  owner_grab_button randr button\n"
1124da39bf31Smrg"           This option can be specified multiple times to select multiple\n"
1125da39bf31Smrg"           event masks.\n"
112698d75b17Smrg"    -1                                  display only a single line per event\n"
1127da39bf31Smrg"    -version                            print version and exit\n"
1128da39bf31Smrg"\n";
1129f299d47fSmrg
113005641e18Smrg    if (errmsg != NULL)
1131da39bf31Smrg        fprintf(stderr, "%s: %s\n", ProgramName, errmsg);
113205641e18Smrg
1133da39bf31Smrg    fprintf(stderr, "usage:  %s [-options ...]\n", ProgramName);
1134da39bf31Smrg    fprintf(stderr, "where options include:\n");
1135da39bf31Smrg    fputs(msg, stderr);
1136f299d47fSmrg
1137da39bf31Smrg    exit(1);
1138f299d47fSmrg}
1139f299d47fSmrg
1140f299d47fSmrgstatic int
1141da39bf31Smrgparse_backing_store(const char *s)
1142f299d47fSmrg{
1143da39bf31Smrg    size_t len = strlen(s);
1144f299d47fSmrg
1145da39bf31Smrg    if (strncasecmp(s, "NotUseful", len) == 0)
1146da39bf31Smrg        return (NotUseful);
1147da39bf31Smrg    if (strncasecmp(s, "WhenMapped", len) == 0)
1148da39bf31Smrg        return (WhenMapped);
1149da39bf31Smrg    if (strncasecmp(s, "Always", len) == 0)
1150da39bf31Smrg        return (Always);
1151f299d47fSmrg
1152da39bf31Smrg    fprintf(stderr, "%s: unrecognized argument '%s' for -bs\n", ProgramName, s);
1153da39bf31Smrg    usage(NULL);
1154f299d47fSmrg}
1155f299d47fSmrg
11561a2dd139Smrgstatic Bool
1157da39bf31Smrgparse_event_mask(const char *s, long event_masks[])
11581a2dd139Smrg{
11591a2dd139Smrg    const struct {
11601a2dd139Smrg        const char *name;
11611a2dd139Smrg        enum EventMaskIndex mask_index;
11621a2dd139Smrg        long mask;
11631a2dd139Smrg    } events[] = {
11641a2dd139Smrg        { "keyboard",
11651a2dd139Smrg          EVENT_MASK_INDEX_CORE,
11661a2dd139Smrg          KeyPressMask | KeyReleaseMask | KeymapStateMask },
11671a2dd139Smrg        { "mouse",
11681a2dd139Smrg          EVENT_MASK_INDEX_CORE,
11691a2dd139Smrg          ButtonPressMask | ButtonReleaseMask | EnterWindowMask |
11701a2dd139Smrg          LeaveWindowMask | PointerMotionMask | Button1MotionMask |
11711a2dd139Smrg          Button2MotionMask | Button3MotionMask | Button4MotionMask |
11721a2dd139Smrg          Button5MotionMask | ButtonMotionMask },
1173da39bf31Smrg        { "button",
117405641e18Smrg          EVENT_MASK_INDEX_CORE,
117505641e18Smrg          ButtonPressMask | ButtonReleaseMask },
11761a2dd139Smrg        { "expose",
11771a2dd139Smrg          EVENT_MASK_INDEX_CORE,
11781a2dd139Smrg          ExposureMask },
11791a2dd139Smrg        { "visibility",
11801a2dd139Smrg          EVENT_MASK_INDEX_CORE,
11811a2dd139Smrg          VisibilityChangeMask },
11821a2dd139Smrg        { "structure",
11831a2dd139Smrg          EVENT_MASK_INDEX_CORE,
11841a2dd139Smrg          StructureNotifyMask },
11851a2dd139Smrg        { "substructure",
11861a2dd139Smrg          EVENT_MASK_INDEX_CORE,
11871a2dd139Smrg          SubstructureNotifyMask | SubstructureRedirectMask },
11881a2dd139Smrg        { "focus",
11891a2dd139Smrg          EVENT_MASK_INDEX_CORE,
11901a2dd139Smrg          FocusChangeMask },
11911a2dd139Smrg        { "property",
11921a2dd139Smrg          EVENT_MASK_INDEX_CORE,
11931a2dd139Smrg          PropertyChangeMask },
11941a2dd139Smrg        { "colormap",
11951a2dd139Smrg          EVENT_MASK_INDEX_CORE,
11961a2dd139Smrg          ColormapChangeMask },
11971a2dd139Smrg        { "owner_grab_button",
11981a2dd139Smrg          EVENT_MASK_INDEX_CORE,
11991a2dd139Smrg          OwnerGrabButtonMask },
12001a2dd139Smrg        { "randr",
12011a2dd139Smrg          EVENT_MASK_INDEX_RANDR,
12021a2dd139Smrg          RRScreenChangeNotifyMask | RRCrtcChangeNotifyMask |
12031a2dd139Smrg          RROutputChangeNotifyMask | RROutputPropertyNotifyMask },
12041a2dd139Smrg        { NULL, 0, 0 }
12051a2dd139Smrg    };
12061a2dd139Smrg    int i;
12071a2dd139Smrg
12081a2dd139Smrg    for (i = 0; events[i].name; i++) {
12091a2dd139Smrg        if (!s || !strcmp(s, events[i].name)) {
12101a2dd139Smrg            event_masks[events[i].mask_index] |= events[i].mask;
12111a2dd139Smrg            if (s)
12121a2dd139Smrg                return True;
12131a2dd139Smrg        }
12141a2dd139Smrg    }
12151a2dd139Smrg
121605641e18Smrg    if (s != NULL)
1217da39bf31Smrg        fprintf(stderr, "%s: unrecognized event mask '%s'\n", ProgramName, s);
121805641e18Smrg
12191a2dd139Smrg    return False;
12201a2dd139Smrg}
12211a2dd139Smrg
1222f299d47fSmrgint
1223da39bf31Smrgmain(int argc, char **argv)
1224f299d47fSmrg{
1225f299d47fSmrg    char *displayname = NULL;
1226f299d47fSmrg    char *geom = NULL;
1227f299d47fSmrg    int i;
1228f299d47fSmrg    XSizeHints hints;
1229f299d47fSmrg    int borderwidth = 2;
1230f299d47fSmrg    Window w, subw;
1231f299d47fSmrg    XSetWindowAttributes attr;
1232f299d47fSmrg    XWindowAttributes wattr;
1233f299d47fSmrg    unsigned long mask = 0L;
1234f299d47fSmrg    int done;
12351a2dd139Smrg    const char *name = "Event Tester";
1236f299d47fSmrg    Bool reverse = False;
1237625f88beSmrg    Bool use_root = False;
1238f299d47fSmrg    unsigned long back, fore;
1239f299d47fSmrg    XIM xim;
1240f299d47fSmrg    XIMStyles *xim_styles;
1241f299d47fSmrg    XIMStyle xim_style = 0;
1242f299d47fSmrg    char *modifiers;
1243f299d47fSmrg    char *imvalret;
12441a2dd139Smrg    long event_masks[NUM_EVENT_MASKS];
12451a2dd139Smrg    Bool event_mask_specified = False;
1246f299d47fSmrg
1247f299d47fSmrg    ProgramName = argv[0];
1248f299d47fSmrg
1249da39bf31Smrg    if (setlocale(LC_ALL, "") == NULL) {
1250da39bf31Smrg        fprintf(stderr, "%s: warning: could not set default locale\n",
1251da39bf31Smrg                ProgramName);
1252f299d47fSmrg    }
1253f299d47fSmrg
12541a2dd139Smrg    memset(event_masks, 0, sizeof(event_masks));
12551a2dd139Smrg
1256f299d47fSmrg    w = 0;
1257f299d47fSmrg    for (i = 1; i < argc; i++) {
1258da39bf31Smrg        char *arg = argv[i];
1259da39bf31Smrg
1260da39bf31Smrg        if (arg[0] == '-') {
1261da39bf31Smrg            switch (arg[1]) {
1262da39bf31Smrg            case 'd':          /* -display host:dpy */
1263da39bf31Smrg                if (++i >= argc)
1264da39bf31Smrg                    usage("-display requires an argument");
1265da39bf31Smrg                displayname = argv[i];
1266da39bf31Smrg                continue;
1267da39bf31Smrg            case 'g':          /* -geometry geom */
1268da39bf31Smrg                if (++i >= argc)
1269da39bf31Smrg                    usage("-geometry requires an argument");
1270da39bf31Smrg                geom = argv[i];
1271da39bf31Smrg                continue;
1272da39bf31Smrg            case 'b':
1273da39bf31Smrg                switch (arg[2]) {
1274da39bf31Smrg                case 'w':      /* -bw pixels */
1275da39bf31Smrg                    if (++i >= argc)
1276da39bf31Smrg                        usage("-bw requires an argument");
1277da39bf31Smrg                    borderwidth = atoi(argv[i]);
1278da39bf31Smrg                    continue;
1279da39bf31Smrg                case 's':      /* -bs type */
1280da39bf31Smrg                    if (++i >= argc)
1281da39bf31Smrg                        usage("-bs requires an argument");
1282da39bf31Smrg                    attr.backing_store = parse_backing_store(argv[i]);
1283da39bf31Smrg                    mask |= CWBackingStore;
1284da39bf31Smrg                    continue;
1285da39bf31Smrg                default:
1286da39bf31Smrg                    goto unrecognized;
1287da39bf31Smrg                }
1288da39bf31Smrg            case 'i':          /* -id */
1289da39bf31Smrg                if (++i >= argc)
1290da39bf31Smrg                    usage("-id requires an argument");
1291da39bf31Smrg                sscanf(argv[i], "0x%lx", &w);
1292da39bf31Smrg                if (!w)
1293da39bf31Smrg                    sscanf(argv[i], "%lu", &w);
1294da39bf31Smrg                if (!w) {
1295da39bf31Smrg                    fprintf(stderr,
1296da39bf31Smrg                            "%s: unable to parse argument '%s' for -id\n",
1297da39bf31Smrg                            ProgramName, argv[i]);
1298da39bf31Smrg                    usage(NULL);
1299da39bf31Smrg                }
1300da39bf31Smrg                continue;
1301da39bf31Smrg            case 'n':          /* -name */
1302da39bf31Smrg                if (++i >= argc)
1303da39bf31Smrg                    usage("-name requires an argument");
1304da39bf31Smrg                name = argv[i];
1305da39bf31Smrg                continue;
1306da39bf31Smrg            case 'r':
1307da39bf31Smrg                switch (arg[2]) {
1308da39bf31Smrg                case 'o':      /* -root */
1309da39bf31Smrg                    use_root = True;
1310da39bf31Smrg                    continue;
1311da39bf31Smrg                case 'v':      /* -rv */
1312da39bf31Smrg                    reverse = True;
1313da39bf31Smrg                    continue;
1314da39bf31Smrg                default:
1315da39bf31Smrg                    goto unrecognized;
1316da39bf31Smrg                }
1317da39bf31Smrg                continue;
1318da39bf31Smrg            case 's':          /* -s */
1319da39bf31Smrg                attr.save_under = True;
1320da39bf31Smrg                mask |= CWSaveUnder;
1321da39bf31Smrg                continue;
1322da39bf31Smrg            case 'e':          /* -event */
1323da39bf31Smrg                if (++i >= argc)
1324da39bf31Smrg                    usage("-event requires an argument");
1325da39bf31Smrg                if (!parse_event_mask(argv[i], event_masks))
1326da39bf31Smrg                    usage(NULL);
1327da39bf31Smrg                event_mask_specified = True;
1328da39bf31Smrg                continue;
132998d75b17Smrg            case '1':
133098d75b17Smrg                single_line = True;
133198d75b17Smrg                continue;
1332da39bf31Smrg            case 'v':
1333da39bf31Smrg                puts(PACKAGE_STRING);
1334da39bf31Smrg                exit(0);
1335da39bf31Smrg            default:
1336da39bf31Smrg                goto unrecognized;
1337da39bf31Smrg            }                   /* end switch on - */
1338da39bf31Smrg        }
1339da39bf31Smrg        else {
1340da39bf31Smrg unrecognized:
1341da39bf31Smrg            fprintf(stderr, "%s: unrecognized argument '%s'\n",
1342da39bf31Smrg                    ProgramName, arg);
1343da39bf31Smrg            usage(NULL);
1344da39bf31Smrg        }
1345da39bf31Smrg    }                           /* end for over argc */
1346f299d47fSmrg
13471a2dd139Smrg    /* if no -event options were specified, pretend all of them were */
13481a2dd139Smrg    if (!event_mask_specified)
1349da39bf31Smrg        parse_event_mask(NULL, event_masks);
13501a2dd139Smrg
1351da39bf31Smrg    dpy = XOpenDisplay(displayname);
1352f299d47fSmrg    if (!dpy) {
1353da39bf31Smrg        fprintf(stderr, "%s:  unable to open display '%s'\n",
1354da39bf31Smrg                ProgramName, XDisplayName(displayname));
1355da39bf31Smrg        exit(1);
1356f299d47fSmrg    }
1357f299d47fSmrg
1358f299d47fSmrg    /* we're testing the default input method */
1359da39bf31Smrg    modifiers = XSetLocaleModifiers("@im=none");
1360f299d47fSmrg    if (modifiers == NULL) {
1361da39bf31Smrg        fprintf(stderr, "%s:  XSetLocaleModifiers failed\n", ProgramName);
1362f299d47fSmrg    }
1363f299d47fSmrg
1364da39bf31Smrg    xim = XOpenIM(dpy, NULL, NULL, NULL);
1365f299d47fSmrg    if (xim == NULL) {
1366da39bf31Smrg        fprintf(stderr, "%s:  XOpenIM failed\n", ProgramName);
1367f299d47fSmrg    }
1368f299d47fSmrg
1369f299d47fSmrg    if (xim) {
1370da39bf31Smrg        imvalret = XGetIMValues(xim, XNQueryInputStyle, &xim_styles, NULL);
1371f299d47fSmrg        if (imvalret != NULL || xim_styles == NULL) {
1372da39bf31Smrg            fprintf(stderr, "%s:  input method doesn't support any styles\n",
1373da39bf31Smrg                    ProgramName);
1374f299d47fSmrg        }
1375f299d47fSmrg
1376f299d47fSmrg        if (xim_styles) {
1377f299d47fSmrg            xim_style = 0;
1378da39bf31Smrg            for (i = 0; i < xim_styles->count_styles; i++) {
1379f299d47fSmrg                if (xim_styles->supported_styles[i] ==
1380f299d47fSmrg                    (XIMPreeditNothing | XIMStatusNothing)) {
1381f299d47fSmrg                    xim_style = xim_styles->supported_styles[i];
1382f299d47fSmrg                    break;
1383f299d47fSmrg                }
1384f299d47fSmrg            }
1385f299d47fSmrg
1386f299d47fSmrg            if (xim_style == 0) {
1387da39bf31Smrg                fprintf(stderr,
1388da39bf31Smrg                        "%s: input method doesn't support the style we support\n",
1389da39bf31Smrg                        ProgramName);
1390f299d47fSmrg            }
1391da39bf31Smrg            XFree(xim_styles);
1392f299d47fSmrg        }
13931a2dd139Smrg    }
1394f299d47fSmrg
1395da39bf31Smrg    screen = DefaultScreen(dpy);
1396f299d47fSmrg
13971a2dd139Smrg    attr.event_mask = event_masks[EVENT_MASK_INDEX_CORE];
1398f299d47fSmrg
1399625f88beSmrg    if (use_root)
1400da39bf31Smrg        w = RootWindow(dpy, screen);
1401625f88beSmrg
1402f299d47fSmrg    if (w) {
1403da39bf31Smrg        XGetWindowAttributes(dpy, w, &wattr);
1404da39bf31Smrg        if (wattr.all_event_masks & ButtonPressMask)
1405da39bf31Smrg            attr.event_mask &= ~ButtonPressMask;
1406da39bf31Smrg        attr.event_mask &= ~SubstructureRedirectMask;
1407da39bf31Smrg        XSelectInput(dpy, w, attr.event_mask);
1408da39bf31Smrg    }
1409da39bf31Smrg    else {
1410da39bf31Smrg        set_sizehints(&hints, OUTER_WINDOW_MIN_WIDTH, OUTER_WINDOW_MIN_HEIGHT,
1411da39bf31Smrg                      OUTER_WINDOW_DEF_WIDTH, OUTER_WINDOW_DEF_HEIGHT,
1412da39bf31Smrg                      OUTER_WINDOW_DEF_X, OUTER_WINDOW_DEF_Y, geom);
1413da39bf31Smrg
1414da39bf31Smrg        if (reverse) {
1415da39bf31Smrg            back = BlackPixel(dpy, screen);
1416da39bf31Smrg            fore = WhitePixel(dpy, screen);
1417da39bf31Smrg        }
1418da39bf31Smrg        else {
1419da39bf31Smrg            back = WhitePixel(dpy, screen);
1420da39bf31Smrg            fore = BlackPixel(dpy, screen);
1421da39bf31Smrg        }
1422da39bf31Smrg
1423da39bf31Smrg        attr.background_pixel = back;
1424da39bf31Smrg        attr.border_pixel = fore;
1425da39bf31Smrg        mask |= (CWBackPixel | CWBorderPixel | CWEventMask);
1426da39bf31Smrg
1427da39bf31Smrg        w = XCreateWindow(dpy, RootWindow(dpy, screen), hints.x, hints.y,
1428da39bf31Smrg                          hints.width, hints.height, borderwidth, 0,
1429da39bf31Smrg                          InputOutput, (Visual *) CopyFromParent, mask, &attr);
1430da39bf31Smrg
1431da39bf31Smrg        XSetStandardProperties(dpy, w, name, NULL, (Pixmap) 0,
1432da39bf31Smrg                               argv, argc, &hints);
1433da39bf31Smrg
1434da39bf31Smrg        subw = XCreateSimpleWindow(dpy, w, INNER_WINDOW_X, INNER_WINDOW_Y,
1435da39bf31Smrg                                   INNER_WINDOW_WIDTH, INNER_WINDOW_HEIGHT,
1436da39bf31Smrg                                   INNER_WINDOW_BORDER,
1437da39bf31Smrg                                   attr.border_pixel, attr.background_pixel);
1438f299d47fSmrg
1439f299d47fSmrg        wm_protocols = XInternAtom(dpy, "WM_PROTOCOLS", False);
1440f299d47fSmrg        wm_delete_window = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
1441f299d47fSmrg        XSetWMProtocols(dpy, w, &wm_delete_window, 1);
1442f299d47fSmrg
1443da39bf31Smrg        XMapWindow(dpy, subw);  /* map before w so that it appears */
1444da39bf31Smrg        XMapWindow(dpy, w);
1445f299d47fSmrg
1446da39bf31Smrg        printf("Outer window is 0x%lx, inner window is 0x%lx\n", w, subw);
1447f299d47fSmrg    }
1448f299d47fSmrg
1449f299d47fSmrg    if (xim && xim_style) {
1450da39bf31Smrg        xic = XCreateIC(xim,
1451da39bf31Smrg                        XNInputStyle, xim_style,
1452da39bf31Smrg                        XNClientWindow, w, XNFocusWindow, w, NULL);
1453f299d47fSmrg
1454f299d47fSmrg        if (xic == NULL) {
1455da39bf31Smrg            fprintf(stderr, "XCreateIC failed\n");
1456f299d47fSmrg        }
1457f299d47fSmrg    }
1458f299d47fSmrg
1459da39bf31Smrg    have_rr = XRRQueryExtension(dpy, &rr_event_base, &rr_error_base);
14601a2dd139Smrg    if (have_rr) {
14611a2dd139Smrg        int rr_major, rr_minor;
14621a2dd139Smrg
1463da39bf31Smrg        if (XRRQueryVersion(dpy, &rr_major, &rr_minor)) {
14641a2dd139Smrg            int rr_mask = event_masks[EVENT_MASK_INDEX_RANDR];
14651a2dd139Smrg
14661a2dd139Smrg            if (rr_major == 1 && rr_minor <= 1) {
14671a2dd139Smrg                rr_mask &= ~(RRCrtcChangeNotifyMask |
14681a2dd139Smrg                             RROutputChangeNotifyMask |
14691a2dd139Smrg                             RROutputPropertyNotifyMask);
14701a2dd139Smrg            }
14711a2dd139Smrg
1472da39bf31Smrg            XRRSelectInput(dpy, w, rr_mask);
14731a2dd139Smrg        }
14741a2dd139Smrg    }
14751a2dd139Smrg
1476da39bf31Smrg    for (done = 0; !done;) {
1477da39bf31Smrg        XEvent event;
1478da39bf31Smrg
1479da39bf31Smrg        XNextEvent(dpy, &event);
1480da39bf31Smrg
1481da39bf31Smrg        switch (event.type) {
1482da39bf31Smrg        case KeyPress:
1483da39bf31Smrg            prologue(&event, "KeyPress");
1484da39bf31Smrg            do_KeyPress(&event);
1485da39bf31Smrg            break;
1486da39bf31Smrg        case KeyRelease:
1487da39bf31Smrg            prologue(&event, "KeyRelease");
1488da39bf31Smrg            do_KeyRelease(&event);
1489da39bf31Smrg            break;
1490da39bf31Smrg        case ButtonPress:
1491da39bf31Smrg            prologue(&event, "ButtonPress");
1492da39bf31Smrg            do_ButtonPress(&event);
1493da39bf31Smrg            break;
1494da39bf31Smrg        case ButtonRelease:
1495da39bf31Smrg            prologue(&event, "ButtonRelease");
1496da39bf31Smrg            do_ButtonRelease(&event);
1497da39bf31Smrg            break;
1498da39bf31Smrg        case MotionNotify:
1499da39bf31Smrg            prologue(&event, "MotionNotify");
1500da39bf31Smrg            do_MotionNotify(&event);
1501da39bf31Smrg            break;
1502da39bf31Smrg        case EnterNotify:
1503da39bf31Smrg            prologue(&event, "EnterNotify");
1504da39bf31Smrg            do_EnterNotify(&event);
1505da39bf31Smrg            break;
1506da39bf31Smrg        case LeaveNotify:
1507da39bf31Smrg            prologue(&event, "LeaveNotify");
1508da39bf31Smrg            do_LeaveNotify(&event);
1509da39bf31Smrg            break;
1510da39bf31Smrg        case FocusIn:
1511da39bf31Smrg            prologue(&event, "FocusIn");
1512da39bf31Smrg            do_FocusIn(&event);
1513da39bf31Smrg            break;
1514da39bf31Smrg        case FocusOut:
1515da39bf31Smrg            prologue(&event, "FocusOut");
1516da39bf31Smrg            do_FocusOut(&event);
1517da39bf31Smrg            break;
1518da39bf31Smrg        case KeymapNotify:
1519da39bf31Smrg            prologue(&event, "KeymapNotify");
1520da39bf31Smrg            do_KeymapNotify(&event);
1521da39bf31Smrg            break;
1522da39bf31Smrg        case Expose:
1523da39bf31Smrg            prologue(&event, "Expose");
1524da39bf31Smrg            do_Expose(&event);
1525da39bf31Smrg            break;
1526da39bf31Smrg        case GraphicsExpose:
1527da39bf31Smrg            prologue(&event, "GraphicsExpose");
1528da39bf31Smrg            do_GraphicsExpose(&event);
1529da39bf31Smrg            break;
1530da39bf31Smrg        case NoExpose:
1531da39bf31Smrg            prologue(&event, "NoExpose");
1532da39bf31Smrg            do_NoExpose(&event);
1533da39bf31Smrg            break;
1534da39bf31Smrg        case VisibilityNotify:
1535da39bf31Smrg            prologue(&event, "VisibilityNotify");
1536da39bf31Smrg            do_VisibilityNotify(&event);
1537da39bf31Smrg            break;
1538da39bf31Smrg        case CreateNotify:
1539da39bf31Smrg            prologue(&event, "CreateNotify");
1540da39bf31Smrg            do_CreateNotify(&event);
1541da39bf31Smrg            break;
1542da39bf31Smrg        case DestroyNotify:
1543da39bf31Smrg            prologue(&event, "DestroyNotify");
1544da39bf31Smrg            do_DestroyNotify(&event);
1545da39bf31Smrg            break;
1546da39bf31Smrg        case UnmapNotify:
1547da39bf31Smrg            prologue(&event, "UnmapNotify");
1548da39bf31Smrg            do_UnmapNotify(&event);
1549da39bf31Smrg            break;
1550da39bf31Smrg        case MapNotify:
1551da39bf31Smrg            prologue(&event, "MapNotify");
1552da39bf31Smrg            do_MapNotify(&event);
1553da39bf31Smrg            break;
1554da39bf31Smrg        case MapRequest:
1555da39bf31Smrg            prologue(&event, "MapRequest");
1556da39bf31Smrg            do_MapRequest(&event);
1557da39bf31Smrg            break;
1558da39bf31Smrg        case ReparentNotify:
1559da39bf31Smrg            prologue(&event, "ReparentNotify");
1560da39bf31Smrg            do_ReparentNotify(&event);
1561da39bf31Smrg            break;
1562da39bf31Smrg        case ConfigureNotify:
1563da39bf31Smrg            prologue(&event, "ConfigureNotify");
1564da39bf31Smrg            do_ConfigureNotify(&event);
1565da39bf31Smrg            break;
1566da39bf31Smrg        case ConfigureRequest:
1567da39bf31Smrg            prologue(&event, "ConfigureRequest");
1568da39bf31Smrg            do_ConfigureRequest(&event);
1569da39bf31Smrg            break;
1570da39bf31Smrg        case GravityNotify:
1571da39bf31Smrg            prologue(&event, "GravityNotify");
1572da39bf31Smrg            do_GravityNotify(&event);
1573da39bf31Smrg            break;
1574da39bf31Smrg        case ResizeRequest:
1575da39bf31Smrg            prologue(&event, "ResizeRequest");
1576da39bf31Smrg            do_ResizeRequest(&event);
1577da39bf31Smrg            break;
1578da39bf31Smrg        case CirculateNotify:
1579da39bf31Smrg            prologue(&event, "CirculateNotify");
1580da39bf31Smrg            do_CirculateNotify(&event);
1581da39bf31Smrg            break;
1582da39bf31Smrg        case CirculateRequest:
1583da39bf31Smrg            prologue(&event, "CirculateRequest");
1584da39bf31Smrg            do_CirculateRequest(&event);
1585da39bf31Smrg            break;
1586da39bf31Smrg        case PropertyNotify:
1587da39bf31Smrg            prologue(&event, "PropertyNotify");
1588da39bf31Smrg            do_PropertyNotify(&event);
1589da39bf31Smrg            break;
1590da39bf31Smrg        case SelectionClear:
1591da39bf31Smrg            prologue(&event, "SelectionClear");
1592da39bf31Smrg            do_SelectionClear(&event);
1593da39bf31Smrg            break;
1594da39bf31Smrg        case SelectionRequest:
1595da39bf31Smrg            prologue(&event, "SelectionRequest");
1596da39bf31Smrg            do_SelectionRequest(&event);
1597da39bf31Smrg            break;
1598da39bf31Smrg        case SelectionNotify:
1599da39bf31Smrg            prologue(&event, "SelectionNotify");
1600da39bf31Smrg            do_SelectionNotify(&event);
1601da39bf31Smrg            break;
1602da39bf31Smrg        case ColormapNotify:
1603da39bf31Smrg            prologue(&event, "ColormapNotify");
1604da39bf31Smrg            do_ColormapNotify(&event);
1605da39bf31Smrg            break;
1606da39bf31Smrg        case ClientMessage:
1607da39bf31Smrg            prologue(&event, "ClientMessage");
1608da39bf31Smrg            do_ClientMessage(&event);
1609da39bf31Smrg            break;
1610da39bf31Smrg        case MappingNotify:
1611da39bf31Smrg            prologue(&event, "MappingNotify");
1612da39bf31Smrg            do_MappingNotify(&event);
1613da39bf31Smrg            break;
1614da39bf31Smrg        default:
1615da39bf31Smrg            if (have_rr) {
1616da39bf31Smrg                if (event.type == rr_event_base + RRScreenChangeNotify) {
1617da39bf31Smrg                    prologue(&event, "RRScreenChangeNotify");
1618da39bf31Smrg                    do_RRScreenChangeNotify(&event);
1619da39bf31Smrg                    break;
1620da39bf31Smrg                }
1621da39bf31Smrg                if (event.type == rr_event_base + RRNotify) {
1622da39bf31Smrg                    do_RRNotify(&event);
1623da39bf31Smrg                    break;
1624da39bf31Smrg                }
1625da39bf31Smrg            }
162698d75b17Smrg            output(NewLine, "Unknown event type %d", event.type);
1627da39bf31Smrg            break;
1628da39bf31Smrg        }
162998d75b17Smrg        if (single_line) {
163098d75b17Smrg            printf("\n");
163198d75b17Smrg        }
1632da39bf31Smrg        fflush(stdout);
1633f299d47fSmrg    }
1634f299d47fSmrg
1635da39bf31Smrg    XCloseDisplay(dpy);
16361a2dd139Smrg    return 0;
1637f299d47fSmrg}
1638