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