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