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