2 From: mikew@wyse.wyse.com (Mike Wexler)
3 Newsgroups: comp.sources.x
4 Subject: v02i056: subroutine to print events in human readable form, Part01/01
5 Message-ID: <1935@wyse.wyse.com>
6 Date: 22 Dec 88 19:28:25 GMT
7 Organization: Wyse Technology, San Jose
9 Approved: mikew@wyse.com
11 Submitted-by: richsun!darkstar!ken
12 Posting-number: Volume 2, Issue 56
13 Archive-name: showevent/part01
17 Following is a shar file of a debugging aid along with a sample program to
18 show how it is used. The README contains more details.
23 # This is a shell archive, meaning:
24 # 1. Remove everything above the #! /bin/sh line.
25 # 2. Save the resulting text in a file.
26 # 3. Execute the file with /bin/sh (not csh) to create the files:
33 # This archive created: Thu Dec 22 12:13:46 1988
34 export PATH; PATH=/bin:$PATH
37 echo shar: will not over-write existing file "'Makefile'"
39 cat << \SHAR_EOF > 'Makefile'
41 INCLUDE = -I/global/include
42 LFLAGS = -L/global/lib
43 OBJS = ShowEvent.o sample.o
49 $(CC) $(INCLUDE) $(CFLAGS) -c $<
52 $(CC) $(LFLAGS) $(OBJS) $(LIBS) -o sample
54 fi # end of overwriting check
57 echo shar: will not over-write existing file "'README'"
59 cat << \SHAR_EOF > 'README'
60 There are times during debugging when it would be real useful to be able to
61 print the fields of an event in a human readable form. Too many times I found
62 myself scrounging around in section 8 of the Xlib manual looking for the valid
63 fields for the events I wanted to see, then adding printf's to display the
64 numeric values of the fields, and then scanning through X.h trying to decode
65 the cryptic detail and state fields. After playing with xev, I decided to
66 write a couple of standard functions that I could keep in a library and call
67 on whenever I needed a little debugging verbosity. The first function,
68 GetType(), is useful for returning the string representation of the type of
69 an event. The second function, ShowEvent(), is used to display all the fields
70 of an event in a readable format. The functions are not complicated, in fact,
71 they are mind-numbingly boring - but that's just the point nobody wants to
72 spend the time writing functions like this, they just want to have them when
75 A simple, sample program is included which does little else but to demonstrate
76 the use of these two functions. These functions have saved me many an hour
77 during debugging and I hope you find some benefit to these. If you have any
78 comments, suggestions, improvements, or if you find any blithering errors you
79 can get it touch with me at the following location:
83 fi # end of overwriting check
84 if test -f 'ShowEvent.c'
86 echo shar: will not over-write existing file "'ShowEvent.c'"
88 cat << \SHAR_EOF > 'ShowEvent.c'
89 #include <X11/Intrinsic.h>
90 #include <X11/Xproto.h>
92 Boolean use_separate_lines = True;
95 /******************************************************************************/
96 /**** Miscellaneous routines to convert values to their string equivalents ****/
97 /******************************************************************************/
99 /* Returns the string equivalent of a boolean parameter */
100 static char *TorF(bool)
115 /* Returns the string equivalent of a property notify state */
116 static char *PropertyState(state)
120 case PropertyNewValue:
121 return ("PropertyNewValue");
124 return ("PropertyDelete");
131 /* Returns the string equivalent of a visibility notify state */
132 static char *VisibilityState(state)
136 case VisibilityUnobscured:
137 return ("VisibilityUnobscured");
139 case VisibilityPartiallyObscured:
140 return ("VisibilityPartiallyObscured");
142 case VisibilityFullyObscured:
143 return ("VisibilityFullyObscured");
150 /* Returns the string equivalent of a timestamp */
151 static char *ServerTime(time)
171 sprintf(buffer, "%d day%s %02d:%02d:%02d.%03d",
172 day, day == 1 ? "" : "(s)", hr, min, sec, msec);
176 /* Simple structure to ease the interpretation of masks */
177 typedef struct _MaskType {
182 /* Returns the string equivalent of a mask of buttons and/or modifier keys */
183 static char *ButtonAndOrModifierState(state)
187 static MaskType masks[] = {
188 {Button1Mask, "Button1Mask"},
189 {Button2Mask, "Button2Mask"},
190 {Button3Mask, "Button3Mask"},
191 {Button4Mask, "Button4Mask"},
192 {Button5Mask, "Button5Mask"},
193 {ShiftMask, "ShiftMask"},
194 {LockMask, "LockMask"},
195 {ControlMask, "ControlMask"},
196 {Mod1Mask, "Mod1Mask"},
197 {Mod2Mask, "Mod2Mask"},
198 {Mod3Mask, "Mod3Mask"},
199 {Mod4Mask, "Mod4Mask"},
200 {Mod5Mask, "Mod5Mask"},
202 int num_masks = sizeof(masks) / sizeof(MaskType);
204 Boolean first = True;
208 for (i = 0; i < num_masks; i++)
209 if (state & masks[i].value)
212 strcpy(buffer, masks[i].string);
214 strcat(buffer, " | ");
215 strcat(buffer, masks[i].string);
220 /* Returns the string equivalent of a mask of configure window values */
221 static char *ConfigureValueMask(valuemask)
222 unsigned int valuemask;
225 static MaskType masks[] = {
228 {CWWidth, "CWWidth"},
229 {CWHeight, "CWHeight"},
230 {CWBorderWidth, "CWBorderWidth"},
231 {CWSibling, "CWSibling"},
232 {CWStackMode, "CWStackMode"},
234 int num_masks = sizeof(masks) / sizeof(MaskType);
236 Boolean first = True;
240 for (i = 0; i < num_masks; i++)
241 if (valuemask & masks[i].value)
244 strcpy(buffer, masks[i].string);
246 strcat(buffer, " | ");
247 strcat(buffer, masks[i].string);
253 /* Returns the string equivalent of a motion hint */
254 static char *IsHint(is_hint)
259 return ("NotifyNormal");
262 return ("NotifyHint");
269 /* Returns the string equivalent of an id or the value "None" */
270 static char *MaybeNone(value)
278 sprintf(buffer, "0x%x", value);
283 /* Returns the string equivalent of a colormap state */
284 static char *ColormapState(state)
288 case ColormapInstalled:
289 return ("ColormapInstalled");
291 case ColormapUninstalled:
292 return ("ColormapUninstalled");
299 /* Returns the string equivalent of a crossing detail */
300 static char *CrossingDetail(detail)
305 return ("NotifyAncestor");
308 return ("NotifyInferior");
311 return ("NotifyVirtual");
313 case NotifyNonlinear:
314 return ("NotifyNonlinear");
316 case NotifyNonlinearVirtual:
317 return ("NotifyNonlinearVirtual");
324 /* Returns the string equivalent of a focus change detail */
325 static char *FocusChangeDetail(detail)
330 return ("NotifyAncestor");
333 return ("NotifyInferior");
336 return ("NotifyVirtual");
338 case NotifyNonlinear:
339 return ("NotifyNonlinear");
341 case NotifyNonlinearVirtual:
342 return ("NotifyNonlinearVirtual");
345 return ("NotifyPointer");
347 case NotifyPointerRoot:
348 return ("NotifyPointerRoot");
350 case NotifyDetailNone:
351 return ("NotifyDetailNone");
358 /* Returns the string equivalent of a configure detail */
359 static char *ConfigureDetail(detail)
383 /* Returns the string equivalent of a grab mode */
384 static char *GrabMode(mode)
389 return ("NotifyNormal");
392 return ("NotifyGrab");
395 return ("NotifyUngrab");
397 case NotifyWhileGrabbed:
398 return ("NotifyWhileGrabbed");
405 /* Returns the string equivalent of a mapping request */
406 static char *MappingRequest(request)
410 case MappingModifier:
411 return ("MappingModifier");
413 case MappingKeyboard:
414 return ("MappingKeyboard");
417 return ("MappingPointer");
424 /* Returns the string equivalent of a stacking order place */
425 static char *Place(place)
430 return ("PlaceOnTop");
433 return ("PlaceOnBottom");
440 /* Returns the string equivalent of a major code */
441 static char *MajorCode(code)
448 return ("X_CopyArea");
451 return ("X_CopyPlane");
454 sprintf(buffer, "0x%x", code);
459 /* Returns the string equivalent the keycode contained in the key event */
460 static char *Keycode(ev)
468 XLookupString(ev, string, 64, &keysym_str, NULL);
470 if (keysym_str == NoSymbol)
471 keysym_name = "NoSymbol";
472 else if (!(keysym_name = XKeysymToString(keysym_str)))
473 keysym_name = "(no name)";
474 sprintf(buffer, "%u (keysym 0x%x \"%s\")",
475 ev->keycode, keysym_str, keysym_name);
479 /* Returns the string equivalent of an atom or "None"*/
480 static char *AtomName(dpy, atom)
490 atom_name = XGetAtomName(dpy, atom);
491 strncpy(buffer, atom_name, 256);
496 /******************************************************************************/
497 /**** Routines to print out readable values for the field of various events ***/
498 /******************************************************************************/
500 static void VerbMotion(ev)
503 printf("window=0x%x%s", ev->window, sep);
504 printf("root=0x%x%s", ev->root, sep);
505 printf("subwindow=0x%x%s", ev->subwindow, sep);
506 printf("time=%s%s", ServerTime(ev->time), sep);
507 printf("x=%d y=%d%s", ev->x, ev->y, sep);
508 printf("x_root=%d y_root=%d%s", ev->x_root, ev->y_root, sep);
509 printf("state=%s%s", ButtonAndOrModifierState(ev->state), sep);
510 printf("is_hint=%s%s", IsHint(ev->is_hint), sep);
511 printf("same_screen=%s\n", TorF(ev->same_screen));
514 static void VerbButton(ev)
517 printf("window=0x%x%s", ev->window, sep);
518 printf("root=0x%x%s", ev->root, sep);
519 printf("subwindow=0x%x%s", ev->subwindow, sep);
520 printf("time=%s%s", ServerTime(ev->time), sep);
521 printf("x=%d y=%d%s", ev->x, ev->y, sep);
522 printf("x_root=%d y_root=%d%s", ev->x_root, ev->y_root, sep);
523 printf("state=%s%s", ButtonAndOrModifierState(ev->state), sep);
524 printf("button=%s%s", ButtonAndOrModifierState(ev->button), sep);
525 printf("same_screen=%s\n", TorF(ev->same_screen));
528 static void VerbColormap(ev)
531 printf("window=0x%x%s", ev->window, sep);
532 printf("colormap=%s%s", MaybeNone(ev->colormap), sep);
533 printf("new=%s%s", TorF(ev->new), sep);
534 printf("state=%s\n", ColormapState(ev->state));
537 static void VerbCrossing(ev)
540 printf("window=0x%x%s", ev->window, sep);
541 printf("root=0x%x%s", ev->root, sep);
542 printf("subwindow=0x%x%s", ev->subwindow, sep);
543 printf("time=%s%s", ServerTime(ev->time), sep);
544 printf("x=%d y=%d%s", ev->x, ev->y, sep);
545 printf("x_root=%d y_root=%d%s", ev->x_root, ev->y_root, sep);
546 printf("mode=%s%s", GrabMode(ev->mode), sep);
547 printf("detail=%s%s", CrossingDetail(ev->detail), sep);
548 printf("same_screen=%s%s", TorF(ev->same_screen), sep);
549 printf("focus=%s%s", TorF(ev->focus), sep);
550 printf("state=%s\n", ButtonAndOrModifierState(ev->state));
553 static void VerbExpose(ev)
556 printf("window=0x%x%s", ev->window, sep);
557 printf("x=%d y=%d%s", ev->x, ev->y, sep);
558 printf("width=%d height=%d%s", ev->width, ev->height, sep);
559 printf("count=%d\n", ev->count);
562 static void VerbGraphicsExpose(ev)
563 XGraphicsExposeEvent *ev;
565 printf("drawable=0x%x%s", ev->drawable, sep);
566 printf("x=%d y=%d%s", ev->x, ev->y, sep);
567 printf("width=%d height=%d%s", ev->width, ev->height, sep);
568 printf("major_code=%s%s", MajorCode(ev->major_code), sep);
569 printf("minor_code=%d\n", ev->minor_code);
572 static void VerbNoExpose(ev)
575 printf("drawable=0x%x%s", ev->drawable, sep);
576 printf("major_code=%s%s", MajorCode(ev->major_code), sep);
577 printf("minor_code=%d\n", ev->minor_code);
580 static void VerbFocus(ev)
581 XFocusChangeEvent *ev;
583 printf("window=0x%x%s", ev->window, sep);
584 printf("mode=%s%s", GrabMode(ev->mode), sep);
585 printf("detail=%s\n", FocusChangeDetail(ev->detail));
588 static void VerbKeymap(ev)
593 printf("window=0x%x%s", ev->window, sep);
594 printf("key_vector=");
595 for (i = 0; i < 32; i++)
596 printf("%02x", ev->key_vector[i]);
600 static void VerbKey(ev)
603 printf("window=0x%x%s", ev->window, sep);
604 printf("root=0x%x%s", ev->root, sep);
605 printf("subwindow=0x%x%s", ev->subwindow, sep);
606 printf("time=%s%s", ServerTime(ev->time), sep);
607 printf("x=%d y=%d%s", ev->x, ev->y, sep);
608 printf("x_root=%d y_root=%d%s", ev->x_root, ev->y_root, sep);
609 printf("state=%s%s", ButtonAndOrModifierState(ev->state), sep);
610 printf("keycode=%s%s", Keycode(ev), sep);
611 printf("same_screen=%s\n", TorF(ev->same_screen));
614 static void VerbProperty(ev)
617 printf("window=0x%x%s", ev->window, sep);
618 printf("atom=%s%s", AtomName(ev->display, ev->atom), sep);
619 printf("time=%s%s", ServerTime(ev->time), sep);
620 printf("state=%s\n", PropertyState(ev->state));
623 static void VerbResizeRequest(ev)
624 XResizeRequestEvent *ev;
626 printf("window=0x%x%s", ev->window, sep);
627 printf("width=%d height=%d\n", ev->width, ev->height);
630 static void VerbCirculate(ev)
633 printf("event=0x%x%s", ev->event, sep);
634 printf("window=0x%x%s", ev->window, sep);
635 printf("place=%s\n", Place(ev->place));
638 static void VerbConfigure(ev)
641 printf("event=0x%x%s", ev->event, sep);
642 printf("window=0x%x%s", ev->window, sep);
643 printf("x=%d y=%d%s", ev->x, ev->y, sep);
644 printf("width=%d height=%d%s", ev->width, ev->height, sep);
645 printf("border_width=%d%s", ev->border_width, sep);
646 printf("above=%s%s", MaybeNone(ev->above), sep);
647 printf("override_redirect=%s\n", TorF(ev->override_redirect));
650 static void VerbCreateWindow(ev)
651 XCreateWindowEvent *ev;
653 printf("parent=0x%x%s", ev->parent, sep);
654 printf("window=0x%x%s", ev->window, sep);
655 printf("x=%d y=%d%s", ev->x, ev->y, sep);
656 printf("width=%d height=%d%s", ev->width, ev->height, sep);
657 printf("border_width=%d%s", ev->border_width, sep);
658 printf("override_redirect=%s\n", TorF(ev->override_redirect));
661 static void VerbDestroyWindow(ev)
662 XDestroyWindowEvent *ev;
664 printf("event=0x%x%s", ev->event, sep);
665 printf("window=0x%x\n", ev->window);
668 static void VerbGravity(ev)
671 printf("event=0x%x%s", ev->event, sep);
672 printf("window=0x%x%s", ev->window, sep);
673 printf("x=%d y=%d\n", ev->x, ev->y);
676 static void VerbMap(ev)
679 printf("event=0x%x%s", ev->event, sep);
680 printf("window=0x%x%s", ev->window, sep);
681 printf("override_redirect=%s\n", TorF(ev->override_redirect));
684 static void VerbReparent(ev)
687 printf("event=0x%x%s", ev->event, sep);
688 printf("window=0x%x%s", ev->window, sep);
689 printf("parent=0x%x%s", ev->parent, sep);
690 printf("x=%d y=%d%s", ev->x, ev->y, sep);
691 printf("override_redirect=%s\n", TorF(ev->override_redirect));
694 static void VerbUnmap(ev)
697 printf("event=0x%x%s", ev->event, sep);
698 printf("window=0x%x%s", ev->window, sep);
699 printf("from_configure=%s\n", TorF(ev->from_configure));
702 static void VerbCirculateRequest(ev)
703 XCirculateRequestEvent *ev;
705 printf("parent=0x%x%s", ev->parent, sep);
706 printf("window=0x%x%s", ev->window, sep);
707 printf("place=%s\n", Place(ev->place));
710 static void VerbConfigureRequest(ev)
711 XConfigureRequestEvent *ev;
713 printf("parent=0x%x%s", ev->parent, sep);
714 printf("window=0x%x%s", ev->window, sep);
715 printf("x=%d y=%d%s", ev->x, ev->y, sep);
716 printf("width=%d height=%d%s", ev->width, ev->height, sep);
717 printf("border_width=%d%s", ev->border_width, sep);
718 printf("above=%s%s", MaybeNone(ev->above), sep);
719 printf("detail=0x%x%s", ConfigureDetail(ev->detail), sep);
720 printf("value_mask=%s\n", ConfigureValueMask(ev->value_mask));
723 static void VerbMapRequest(ev)
724 XMapRequestEvent *ev;
726 printf("parent=0x%x%s", ev->parent, sep);
727 printf("window=0x%x\n", ev->window);
730 static void VerbClient(ev)
731 XClientMessageEvent *ev;
735 printf("window=0x%x%s", ev->window, sep);
736 printf("message_type=%s%s", AtomName(ev->display, ev->message_type), sep);
737 printf("format=%d\n", ev->format);
738 printf("data (shown as longs)=");
739 for (i = 0; i < 5; i++)
740 printf(" 0x%08x", ev->data.l[i]);
744 static void VerbMapping(ev)
747 printf("window=0x%x%s", ev->window, sep);
748 printf("request=0x%x%s", MappingRequest(ev->request), sep);
749 printf("first_keycode=0x%x%s", ev->first_keycode, sep);
750 printf("count=0x%x\n", ev->count);
753 static void VerbSelectionClear(ev)
754 XSelectionClearEvent *ev;
756 printf("window=0x%x%s", ev->window, sep);
757 printf("selection=%s%s", AtomName(ev->display, ev->selection), sep);
758 printf("time=%s\n", ServerTime(ev->time));
761 static void VerbSelection(ev)
764 printf("requestor=0x%x%s", ev->requestor, sep);
765 printf("selection=%s%s", AtomName(ev->display, ev->selection), sep);
766 printf("target=%s%s", AtomName(ev->display, ev->target), sep);
767 printf("property=%s%s", AtomName(ev->display, ev->property), sep);
768 printf("time=%s\n", ServerTime(ev->time));
771 static void VerbSelectionRequest(ev)
772 XSelectionRequestEvent *ev;
774 printf("owner=0x%x%s", ev->owner, sep);
775 printf("requestor=0x%x%s", ev->requestor, sep);
776 printf("selection=%s%s", AtomName(ev->display, ev->selection), sep);
777 printf("target=%s%s", AtomName(ev->display, ev->target), sep);
778 printf("property=%s%s", AtomName(ev->display, ev->property), sep);
779 printf("time=%s\n", ServerTime(ev->time));
782 static void VerbVisibility(ev)
783 XVisibilityEvent *ev;
785 printf("window=0x%x%s", ev->window, sep);
786 printf("state=%s\n", VisibilityState(ev->state));
789 /******************************************************************************/
790 /************ Return the string representation for type of an event ***********/
791 /******************************************************************************/
800 return ("KeyRelease");
802 return ("ButtonPress");
804 return ("ButtonRelease");
806 return ("MotionNotify");
808 return ("EnterNotify");
810 return ("LeaveNotify");
816 return ("KeymapNotify");
820 return ("GraphicsExpose");
823 case VisibilityNotify:
824 return ("VisibilityNotify");
826 return ("CreateNotify");
828 return ("DestroyNotify");
830 return ("UnmapNotify");
832 return ("MapNotify");
834 return ("MapRequest");
836 return ("ReparentNotify");
837 case ConfigureNotify:
838 return ("ConfigureNotify");
839 case ConfigureRequest:
840 return ("ConfigureRequest");
842 return ("GravityNotify");
844 return ("ResizeRequest");
845 case CirculateNotify:
846 return ("CirculateNotify");
847 case CirculateRequest:
848 return ("CirculateRequest");
850 return ("PropertyNotify");
852 return ("SelectionClear");
853 case SelectionRequest:
854 return ("SelectionRequest");
855 case SelectionNotify:
856 return ("SelectionNotify");
858 return ("ColormapNotify");
860 return ("ClientMessage");
862 return ("MappingNotify");
866 /******************************************************************************/
867 /**************** Print the values of all fields for any event ****************/
868 /******************************************************************************/
873 /* determine which field separator to use */
874 if (use_separate_lines)
879 printf("type=%s%s", GetType(ev), sep);
880 printf("serial=%d%s", ev->serial, sep);
881 printf("send_event=%s%s", TorF(ev->send_event), sep);
882 printf("display=0x%x%s", ev->display, sep);
908 VerbGraphicsExpose(ev);
934 VerbResizeRequest(ev);
937 case CirculateNotify:
941 case ConfigureNotify:
946 VerbCreateWindow(ev);
950 VerbDestroyWindow(ev);
969 case CirculateRequest:
970 VerbCirculateRequest(ev);
973 case ConfigureRequest:
974 VerbConfigureRequest(ev);
990 VerbSelectionClear(ev);
993 case SelectionNotify:
997 case SelectionRequest:
998 VerbSelectionRequest(ev);
1001 case VisibilityNotify:
1008 fi # end of overwriting check
1009 if test -f 'ShowEvent.man'
1011 echo shar: will not over-write existing file "'ShowEvent.man'"
1013 cat << \SHAR_EOF > 'ShowEvent.man'
1014 .TH ShowEvent 3X11 "December 1988"
1016 .B ShowEvent \- display the fields of an event
1018 .B GetType - get a string representation of an event type
1021 .B void ShowEvent(event)
1025 .B char *GetType(event)
1030 ShowEvent displays the fields of the specified event in a readable form.
1032 GetType returns the string representation of the specified event type.
1035 fi # end of overwriting check
1036 if test -f 'patchlevel.h'
1038 echo shar: will not over-write existing file "'patchlevel.h'"
1040 cat << \SHAR_EOF > 'patchlevel.h'
1041 #define PATCHLEVEL 0
1043 fi # end of overwriting check
1044 if test -f 'sample.c'
1046 echo shar: will not over-write existing file "'sample.c'"
1048 cat << \SHAR_EOF > 'sample.c'
1049 #include <X11/Intrinsic.h>
1052 * Disclaimer: No I don't actually code like this but this is a simple,
1053 * "Quick-n-Dirty", plain, vanilla, "No ups, No extras" piece of code.
1064 extern Boolean use_separate_lines;
1066 if (!(dpy = XOpenDisplay(""))) {
1067 printf("Failed to open display...\n");
1070 screen = DefaultScreen(dpy);
1072 window = XCreateSimpleWindow(dpy, RootWindow(dpy, screen), 100, 100,
1073 300, 200, 2, BlackPixel(dpy, screen), WhitePixel(dpy, screen));
1075 XSelectInput(dpy, window, KeyPressMask | KeyReleaseMask | ButtonPressMask |
1076 ButtonReleaseMask | EnterWindowMask | LeaveWindowMask |
1077 PointerMotionMask | PointerMotionHintMask | Button1MotionMask |
1078 Button2MotionMask | Button3MotionMask | Button4MotionMask |
1079 Button5MotionMask | ButtonMotionMask | KeymapStateMask |
1080 ExposureMask | VisibilityChangeMask | StructureNotifyMask |
1081 SubstructureNotifyMask | SubstructureRedirectMask | FocusChangeMask |
1082 PropertyChangeMask | ColormapChangeMask | OwnerGrabButtonMask);
1084 XMapWindow(dpy, window);
1086 /* set this to false to make ShowEvent take up less vertival space */
1087 use_separate_lines = True;
1090 XNextEvent(dpy, &event);
1091 printf("Detail of %s event:\n", GetType(&event));
1098 fi # end of overwriting check
1099 # End of shell archive
1102 Mike Wexler(wyse!mikew) Phone: (408)433-1000 x1330
1103 Moderator of comp.sources.x