xev.c revision 625f88be
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#include <stdio.h> 36#include <stdlib.h> 37#include <ctype.h> 38#include <X11/Xlocale.h> 39#include <X11/Xos.h> 40#include <X11/Xlib.h> 41#include <X11/Xutil.h> 42#include <X11/Xproto.h> 43 44#define INNER_WINDOW_WIDTH 50 45#define INNER_WINDOW_HEIGHT 50 46#define INNER_WINDOW_BORDER 4 47#define INNER_WINDOW_X 10 48#define INNER_WINDOW_Y 10 49#define OUTER_WINDOW_MIN_WIDTH (INNER_WINDOW_WIDTH + \ 50 2 * (INNER_WINDOW_BORDER + INNER_WINDOW_X)) 51#define OUTER_WINDOW_MIN_HEIGHT (INNER_WINDOW_HEIGHT + \ 52 2 * (INNER_WINDOW_BORDER + INNER_WINDOW_Y)) 53#define OUTER_WINDOW_DEF_WIDTH (OUTER_WINDOW_MIN_WIDTH + 100) 54#define OUTER_WINDOW_DEF_HEIGHT (OUTER_WINDOW_MIN_HEIGHT + 100) 55#define OUTER_WINDOW_DEF_X 100 56#define OUTER_WINDOW_DEF_Y 100 57 58 59typedef unsigned long Pixel; 60 61const char *Yes = "YES"; 62const char *No = "NO"; 63const char *Unknown = "unknown"; 64 65const char *ProgramName; 66Display *dpy; 67int screen; 68 69XIC xic = NULL; 70 71Atom wm_delete_window; 72Atom wm_protocols; 73 74static void 75prologue (XEvent *eventp, char *event_name) 76{ 77 XAnyEvent *e = (XAnyEvent *) eventp; 78 79 printf ("\n%s event, serial %ld, synthetic %s, window 0x%lx,\n", 80 event_name, e->serial, e->send_event ? Yes : No, e->window); 81} 82 83static void 84dump (char *str, int len) 85{ 86 printf("("); 87 len--; 88 while (len-- > 0) 89 printf("%02x ", (unsigned char) *str++); 90 printf("%02x)", (unsigned char) *str++); 91} 92 93static void 94do_KeyPress (XEvent *eventp) 95{ 96 XKeyEvent *e = (XKeyEvent *) eventp; 97 KeySym ks; 98 KeyCode kc = 0; 99 Bool kc_set = False; 100 char *ksname; 101 int nbytes, nmbbytes = 0; 102 char str[256+1]; 103 static char *buf = NULL; 104 static int bsize = 8; 105 Status status; 106 107 if (buf == NULL) 108 buf = malloc (bsize); 109 110 nbytes = XLookupString (e, str, 256, &ks, NULL); 111 112 /* not supposed to call XmbLookupString on a key release event */ 113 if (e->type == KeyPress && xic) { 114 do { 115 nmbbytes = XmbLookupString (xic, e, buf, bsize - 1, &ks, &status); 116 buf[nmbbytes] = '\0'; 117 118 if (status == XBufferOverflow) { 119 bsize = nmbbytes + 1; 120 buf = realloc (buf, bsize); 121 } 122 } while (status == XBufferOverflow); 123 } 124 125 if (ks == NoSymbol) 126 ksname = "NoSymbol"; 127 else { 128 if (!(ksname = XKeysymToString (ks))) 129 ksname = "(no name)"; 130 kc = XKeysymToKeycode(dpy, ks); 131 kc_set = True; 132 } 133 134 printf (" root 0x%lx, subw 0x%lx, time %lu, (%d,%d), root:(%d,%d),\n", 135 e->root, e->subwindow, e->time, e->x, e->y, e->x_root, e->y_root); 136 printf (" state 0x%x, keycode %u (keysym 0x%lx, %s), same_screen %s,\n", 137 e->state, e->keycode, (unsigned long) ks, ksname, 138 e->same_screen ? Yes : No); 139 if (kc_set && e->keycode != kc) 140 printf (" XKeysymToKeycode returns keycode: %u\n",kc); 141 if (nbytes < 0) nbytes = 0; 142 if (nbytes > 256) nbytes = 256; 143 str[nbytes] = '\0'; 144 printf (" XLookupString gives %d bytes: ", nbytes); 145 if (nbytes > 0) { 146 dump (str, nbytes); 147 printf (" \"%s\"\n", str); 148 } else { 149 printf ("\n"); 150 } 151 152 /* not supposed to call XmbLookupString on a key release event */ 153 if (e->type == KeyPress && xic) { 154 printf (" XmbLookupString gives %d bytes: ", nmbbytes); 155 if (nmbbytes > 0) { 156 dump (buf, nmbbytes); 157 printf (" \"%s\"\n", buf); 158 } else { 159 printf ("\n"); 160 } 161 } 162 163 printf (" XFilterEvent returns: %s\n", 164 XFilterEvent (eventp, e->window) ? "True" : "False"); 165} 166 167static void 168do_KeyRelease (XEvent *eventp) 169{ 170 do_KeyPress (eventp); /* since it has the same info */ 171} 172 173static void 174do_ButtonPress (XEvent *eventp) 175{ 176 XButtonEvent *e = (XButtonEvent *) eventp; 177 178 printf (" root 0x%lx, subw 0x%lx, time %lu, (%d,%d), root:(%d,%d),\n", 179 e->root, e->subwindow, e->time, e->x, e->y, e->x_root, e->y_root); 180 printf (" state 0x%x, button %u, same_screen %s\n", 181 e->state, e->button, e->same_screen ? Yes : No); 182} 183 184static void 185do_ButtonRelease (XEvent *eventp) 186{ 187 do_ButtonPress (eventp); /* since it has the same info */ 188} 189 190static void 191do_MotionNotify (XEvent *eventp) 192{ 193 XMotionEvent *e = (XMotionEvent *) eventp; 194 195 printf (" root 0x%lx, subw 0x%lx, time %lu, (%d,%d), root:(%d,%d),\n", 196 e->root, e->subwindow, e->time, e->x, e->y, e->x_root, e->y_root); 197 printf (" state 0x%x, is_hint %u, same_screen %s\n", 198 e->state, e->is_hint, e->same_screen ? Yes : No); 199} 200 201static void 202do_EnterNotify (XEvent *eventp) 203{ 204 XCrossingEvent *e = (XCrossingEvent *) eventp; 205 char *mode, *detail; 206 char dmode[10], ddetail[10]; 207 208 switch (e->mode) { 209 case NotifyNormal: mode = "NotifyNormal"; break; 210 case NotifyGrab: mode = "NotifyGrab"; break; 211 case NotifyUngrab: mode = "NotifyUngrab"; break; 212 case NotifyWhileGrabbed: mode = "NotifyWhileGrabbed"; break; 213 default: mode = dmode, sprintf (dmode, "%u", e->mode); break; 214 } 215 216 switch (e->detail) { 217 case NotifyAncestor: detail = "NotifyAncestor"; break; 218 case NotifyVirtual: detail = "NotifyVirtual"; break; 219 case NotifyInferior: detail = "NotifyInferior"; break; 220 case NotifyNonlinear: detail = "NotifyNonlinear"; break; 221 case NotifyNonlinearVirtual: detail = "NotifyNonlinearVirtual"; break; 222 case NotifyPointer: detail = "NotifyPointer"; break; 223 case NotifyPointerRoot: detail = "NotifyPointerRoot"; break; 224 case NotifyDetailNone: detail = "NotifyDetailNone"; break; 225 default: detail = ddetail; sprintf (ddetail, "%u", e->detail); break; 226 } 227 228 printf (" root 0x%lx, subw 0x%lx, time %lu, (%d,%d), root:(%d,%d),\n", 229 e->root, e->subwindow, e->time, e->x, e->y, e->x_root, e->y_root); 230 printf (" mode %s, detail %s, same_screen %s,\n", 231 mode, detail, e->same_screen ? Yes : No); 232 printf (" focus %s, state %u\n", e->focus ? Yes : No, e->state); 233} 234 235static void 236do_LeaveNotify (XEvent *eventp) 237{ 238 do_EnterNotify (eventp); /* since it has same information */ 239} 240 241static void 242do_FocusIn (XEvent *eventp) 243{ 244 XFocusChangeEvent *e = (XFocusChangeEvent *) eventp; 245 char *mode, *detail; 246 char dmode[10], ddetail[10]; 247 248 switch (e->mode) { 249 case NotifyNormal: mode = "NotifyNormal"; break; 250 case NotifyGrab: mode = "NotifyGrab"; break; 251 case NotifyUngrab: mode = "NotifyUngrab"; break; 252 case NotifyWhileGrabbed: mode = "NotifyWhileGrabbed"; break; 253 default: mode = dmode, sprintf (dmode, "%u", e->mode); break; 254 } 255 256 switch (e->detail) { 257 case NotifyAncestor: detail = "NotifyAncestor"; break; 258 case NotifyVirtual: detail = "NotifyVirtual"; break; 259 case NotifyInferior: detail = "NotifyInferior"; break; 260 case NotifyNonlinear: detail = "NotifyNonlinear"; break; 261 case NotifyNonlinearVirtual: detail = "NotifyNonlinearVirtual"; break; 262 case NotifyPointer: detail = "NotifyPointer"; break; 263 case NotifyPointerRoot: detail = "NotifyPointerRoot"; break; 264 case NotifyDetailNone: detail = "NotifyDetailNone"; break; 265 default: detail = ddetail; sprintf (ddetail, "%u", e->detail); break; 266 } 267 268 printf (" mode %s, detail %s\n", mode, detail); 269} 270 271static void 272do_FocusOut (XEvent *eventp) 273{ 274 do_FocusIn (eventp); /* since it has same information */ 275} 276 277static void 278do_KeymapNotify (XEvent *eventp) 279{ 280 XKeymapEvent *e = (XKeymapEvent *) eventp; 281 int i; 282 283 printf (" keys: "); 284 for (i = 0; i < 32; i++) { 285 if (i == 16) printf ("\n "); 286 printf ("%-3u ", (unsigned int) e->key_vector[i]); 287 } 288 printf ("\n"); 289} 290 291static void 292do_Expose (XEvent *eventp) 293{ 294 XExposeEvent *e = (XExposeEvent *) eventp; 295 296 printf (" (%d,%d), width %d, height %d, count %d\n", 297 e->x, e->y, e->width, e->height, e->count); 298} 299 300static void 301do_GraphicsExpose (XEvent *eventp) 302{ 303 XGraphicsExposeEvent *e = (XGraphicsExposeEvent *) eventp; 304 char *m; 305 char mdummy[10]; 306 307 switch (e->major_code) { 308 case X_CopyArea: m = "CopyArea"; break; 309 case X_CopyPlane: m = "CopyPlane"; break; 310 default: m = mdummy; sprintf (mdummy, "%d", e->major_code); break; 311 } 312 313 printf (" (%d,%d), width %d, height %d, count %d,\n", 314 e->x, e->y, e->width, e->height, e->count); 315 printf (" major %s, minor %d\n", m, e->minor_code); 316} 317 318static void 319do_NoExpose (XEvent *eventp) 320{ 321 XNoExposeEvent *e = (XNoExposeEvent *) eventp; 322 char *m; 323 char mdummy[10]; 324 325 switch (e->major_code) { 326 case X_CopyArea: m = "CopyArea"; break; 327 case X_CopyPlane: m = "CopyPlane"; break; 328 default: m = mdummy; sprintf (mdummy, "%d", e->major_code); break; 329 } 330 331 printf (" major %s, minor %d\n", m, e->minor_code); 332 return; 333} 334 335static void 336do_VisibilityNotify (XEvent *eventp) 337{ 338 XVisibilityEvent *e = (XVisibilityEvent *) eventp; 339 char *v; 340 char vdummy[10]; 341 342 switch (e->state) { 343 case VisibilityUnobscured: v = "VisibilityUnobscured"; break; 344 case VisibilityPartiallyObscured: v = "VisibilityPartiallyObscured"; break; 345 case VisibilityFullyObscured: v = "VisibilityFullyObscured"; break; 346 default: v = vdummy; sprintf (vdummy, "%d", e->state); break; 347 } 348 349 printf (" state %s\n", v); 350} 351 352static void 353do_CreateNotify (XEvent *eventp) 354{ 355 XCreateWindowEvent *e = (XCreateWindowEvent *) eventp; 356 357 printf (" parent 0x%lx, window 0x%lx, (%d,%d), width %d, height %d\n", 358 e->parent, e->window, e->x, e->y, e->width, e->height); 359 printf ("border_width %d, override %s\n", 360 e->border_width, e->override_redirect ? Yes : No); 361} 362 363static void 364do_DestroyNotify (XEvent *eventp) 365{ 366 XDestroyWindowEvent *e = (XDestroyWindowEvent *) eventp; 367 368 printf (" event 0x%lx, window 0x%lx\n", e->event, e->window); 369} 370 371static void 372do_UnmapNotify (XEvent *eventp) 373{ 374 XUnmapEvent *e = (XUnmapEvent *) eventp; 375 376 printf (" event 0x%lx, window 0x%lx, from_configure %s\n", 377 e->event, e->window, e->from_configure ? Yes : No); 378} 379 380static void 381do_MapNotify (XEvent *eventp) 382{ 383 XMapEvent *e = (XMapEvent *) eventp; 384 385 printf (" event 0x%lx, window 0x%lx, override %s\n", 386 e->event, e->window, e->override_redirect ? Yes : No); 387} 388 389static void 390do_MapRequest (XEvent *eventp) 391{ 392 XMapRequestEvent *e = (XMapRequestEvent *) eventp; 393 394 printf (" parent 0x%lx, window 0x%lx\n", e->parent, e->window); 395} 396 397static void 398do_ReparentNotify (XEvent *eventp) 399{ 400 XReparentEvent *e = (XReparentEvent *) eventp; 401 402 printf (" event 0x%lx, window 0x%lx, parent 0x%lx,\n", 403 e->event, e->window, e->parent); 404 printf (" (%d,%d), override %s\n", e->x, e->y, 405 e->override_redirect ? Yes : No); 406} 407 408static void 409do_ConfigureNotify (XEvent *eventp) 410{ 411 XConfigureEvent *e = (XConfigureEvent *) eventp; 412 413 printf (" event 0x%lx, window 0x%lx, (%d,%d), width %d, height %d,\n", 414 e->event, e->window, e->x, e->y, e->width, e->height); 415 printf (" border_width %d, above 0x%lx, override %s\n", 416 e->border_width, e->above, e->override_redirect ? Yes : No); 417} 418 419static void 420do_ConfigureRequest (XEvent *eventp) 421{ 422 XConfigureRequestEvent *e = (XConfigureRequestEvent *) eventp; 423 char *detail; 424 char ddummy[10]; 425 426 switch (e->detail) { 427 case Above: detail = "Above"; break; 428 case Below: detail = "Below"; break; 429 case TopIf: detail = "TopIf"; break; 430 case BottomIf: detail = "BottomIf"; break; 431 case Opposite: detail = "Opposite"; break; 432 default: detail = ddummy; sprintf (ddummy, "%d", e->detail); break; 433 } 434 435 printf (" parent 0x%lx, window 0x%lx, (%d,%d), width %d, height %d,\n", 436 e->parent, e->window, e->x, e->y, e->width, e->height); 437 printf (" border_width %d, above 0x%lx, detail %s, value 0x%lx\n", 438 e->border_width, e->above, detail, e->value_mask); 439} 440 441static void 442do_GravityNotify (XEvent *eventp) 443{ 444 XGravityEvent *e = (XGravityEvent *) eventp; 445 446 printf (" event 0x%lx, window 0x%lx, (%d,%d)\n", 447 e->event, e->window, e->x, e->y); 448} 449 450static void 451do_ResizeRequest (XEvent *eventp) 452{ 453 XResizeRequestEvent *e = (XResizeRequestEvent *) eventp; 454 455 printf (" width %d, height %d\n", e->width, e->height); 456} 457 458static void 459do_CirculateNotify (XEvent *eventp) 460{ 461 XCirculateEvent *e = (XCirculateEvent *) eventp; 462 char *p; 463 char pdummy[10]; 464 465 switch (e->place) { 466 case PlaceOnTop: p = "PlaceOnTop"; break; 467 case PlaceOnBottom: p = "PlaceOnBottom"; break; 468 default: p = pdummy; sprintf (pdummy, "%d", e->place); break; 469 } 470 471 printf (" event 0x%lx, window 0x%lx, place %s\n", 472 e->event, e->window, p); 473} 474 475static void 476do_CirculateRequest (XEvent *eventp) 477{ 478 XCirculateRequestEvent *e = (XCirculateRequestEvent *) eventp; 479 char *p; 480 char pdummy[10]; 481 482 switch (e->place) { 483 case PlaceOnTop: p = "PlaceOnTop"; break; 484 case PlaceOnBottom: p = "PlaceOnBottom"; break; 485 default: p = pdummy; sprintf (pdummy, "%d", e->place); break; 486 } 487 488 printf (" parent 0x%lx, window 0x%lx, place %s\n", 489 e->parent, e->window, p); 490} 491 492static void 493do_PropertyNotify (XEvent *eventp) 494{ 495 XPropertyEvent *e = (XPropertyEvent *) eventp; 496 char *aname = XGetAtomName (dpy, e->atom); 497 char *s; 498 char sdummy[10]; 499 500 switch (e->state) { 501 case PropertyNewValue: s = "PropertyNewValue"; break; 502 case PropertyDelete: s = "PropertyDelete"; break; 503 default: s = sdummy; sprintf (sdummy, "%d", e->state); break; 504 } 505 506 printf (" atom 0x%lx (%s), time %lu, state %s\n", 507 e->atom, aname ? aname : Unknown, e->time, s); 508 509 if (aname) XFree (aname); 510} 511 512static void 513do_SelectionClear (XEvent *eventp) 514{ 515 XSelectionClearEvent *e = (XSelectionClearEvent *) eventp; 516 char *sname = XGetAtomName (dpy, e->selection); 517 518 printf (" selection 0x%lx (%s), time %lu\n", 519 e->selection, sname ? sname : Unknown, e->time); 520 521 if (sname) XFree (sname); 522} 523 524static void 525do_SelectionRequest (XEvent *eventp) 526{ 527 XSelectionRequestEvent *e = (XSelectionRequestEvent *) eventp; 528 char *sname = XGetAtomName (dpy, e->selection); 529 char *tname = XGetAtomName (dpy, e->target); 530 char *pname = XGetAtomName (dpy, e->property); 531 532 printf (" owner 0x%lx, requestor 0x%lx, selection 0x%lx (%s),\n", 533 e->owner, e->requestor, e->selection, sname ? sname : Unknown); 534 printf (" target 0x%lx (%s), property 0x%lx (%s), time %lu\n", 535 e->target, tname ? tname : Unknown, e->property, 536 pname ? pname : Unknown, e->time); 537 538 if (sname) XFree (sname); 539 if (tname) XFree (tname); 540 if (pname) XFree (pname); 541} 542 543static void 544do_SelectionNotify (XEvent *eventp) 545{ 546 XSelectionEvent *e = (XSelectionEvent *) eventp; 547 char *sname = XGetAtomName (dpy, e->selection); 548 char *tname = XGetAtomName (dpy, e->target); 549 char *pname = XGetAtomName (dpy, e->property); 550 551 printf (" selection 0x%lx (%s), target 0x%lx (%s),\n", 552 e->selection, sname ? sname : Unknown, e->target, 553 tname ? tname : Unknown); 554 printf (" property 0x%lx (%s), time %lu\n", 555 e->property, pname ? pname : Unknown, e->time); 556 557 if (sname) XFree (sname); 558 if (tname) XFree (tname); 559 if (pname) XFree (pname); 560} 561 562static void 563do_ColormapNotify (XEvent *eventp) 564{ 565 XColormapEvent *e = (XColormapEvent *) eventp; 566 char *s; 567 char sdummy[10]; 568 569 switch (e->state) { 570 case ColormapInstalled: s = "ColormapInstalled"; break; 571 case ColormapUninstalled: s = "ColormapUninstalled"; break; 572 default: s = sdummy; sprintf (sdummy, "%d", e->state); break; 573 } 574 575 printf (" colormap 0x%lx, new %s, state %s\n", 576 e->colormap, e->new ? Yes : No, s); 577} 578 579static void 580do_ClientMessage (XEvent *eventp) 581{ 582 XClientMessageEvent *e = (XClientMessageEvent *) eventp; 583 char *mname = XGetAtomName (dpy, e->message_type); 584 585 if (e->message_type == wm_protocols) { 586 char *message = XGetAtomName (dpy, e->data.l[0]); 587 printf (" message_type 0x%lx (%s), format %d, message 0x%lx (%s)\n", 588 e->message_type, mname ? mname : Unknown, e->format, e->data.l[0], message); 589 if (message) XFree (message); 590 } 591 else { 592 printf (" message_type 0x%lx (%s), format %d\n", 593 e->message_type, mname ? mname : Unknown, e->format); 594 } 595 596 if (mname) XFree (mname); 597 598 if (e->format == 32 599 && e->message_type == wm_protocols 600 && (Atom) e->data.l[0] == wm_delete_window) 601 exit (0); 602} 603 604static void 605do_MappingNotify (XEvent *eventp) 606{ 607 XMappingEvent *e = (XMappingEvent *) eventp; 608 char *r; 609 char rdummy[10]; 610 611 switch (e->request) { 612 case MappingModifier: r = "MappingModifier"; break; 613 case MappingKeyboard: r = "MappingKeyboard"; break; 614 case MappingPointer: r = "MappingPointer"; break; 615 default: r = rdummy; sprintf (rdummy, "%d", e->request); break; 616 } 617 618 printf (" request %s, first_keycode %d, count %d\n", 619 r, e->first_keycode, e->count); 620 XRefreshKeyboardMapping(e); 621} 622 623 624 625static void 626set_sizehints (XSizeHints *hintp, int min_width, int min_height, 627 int defwidth, int defheight, int defx, int defy, 628 char *geom) 629{ 630 int geom_result; 631 632 /* set the size hints, algorithm from xlib xbiff */ 633 634 hintp->width = hintp->min_width = min_width; 635 hintp->height = hintp->min_height = min_height; 636 hintp->flags = PMinSize; 637 hintp->x = hintp->y = 0; 638 geom_result = NoValue; 639 if (geom != NULL) { 640 geom_result = XParseGeometry (geom, &hintp->x, &hintp->y, 641 (unsigned int *)&hintp->width, 642 (unsigned int *)&hintp->height); 643 if ((geom_result & WidthValue) && (geom_result & HeightValue)) { 644#ifndef max 645#define max(a,b) ((a) > (b) ? (a) : (b)) 646#endif 647 hintp->width = max (hintp->width, hintp->min_width); 648 hintp->height = max (hintp->height, hintp->min_height); 649 hintp->flags |= USSize; 650 } 651 if ((geom_result & XValue) && (geom_result & YValue)) { 652 hintp->flags += USPosition; 653 } 654 } 655 if (!(hintp->flags & USSize)) { 656 hintp->width = defwidth; 657 hintp->height = defheight; 658 hintp->flags |= PSize; 659 } 660/* 661 if (!(hintp->flags & USPosition)) { 662 hintp->x = defx; 663 hintp->y = defy; 664 hintp->flags |= PPosition; 665 } 666 */ 667 if (geom_result & XNegative) { 668 hintp->x = DisplayWidth (dpy, DefaultScreen (dpy)) + hintp->x - 669 hintp->width; 670 } 671 if (geom_result & YNegative) { 672 hintp->y = DisplayHeight (dpy, DefaultScreen (dpy)) + hintp->y - 673 hintp->height; 674 } 675} 676 677 678#if defined(__GNUC__) && \ 679 ((__GNUC__ > 2) || ((__GNUC__ == 2) && (__GNUC_MINOR__ >= 7))) 680static void usage (void) __attribute__((__noreturn__)); 681#endif 682static void 683usage (void) 684{ 685 static const char *msg[] = { 686" -display displayname X server to contact", 687" -geometry geom size and location of window", 688" -bw pixels border width in pixels", 689" -bs {NotUseful,WhenMapped,Always} backingstore attribute", 690" -id windowid use existing window", 691" -root use root window", 692" -s set save-unders attribute", 693" -name string window name", 694" -rv reverse video", 695"", 696NULL}; 697 const char **cpp; 698 699 fprintf (stderr, "usage: %s [-options ...]\n", ProgramName); 700 fprintf (stderr, "where options include:\n"); 701 702 for (cpp = msg; *cpp; cpp++) 703 fprintf (stderr, "%s\n", *cpp); 704 705 exit (1); 706} 707 708static int 709parse_backing_store (char *s) 710{ 711 int len = strlen (s); 712 char *cp; 713 714 for (cp = s; *cp; cp++) { 715 if (isascii (*cp) && isupper (*cp)) 716 *cp = tolower (*cp); 717 } 718 719 if (strncmp (s, "notuseful", len) == 0) return (NotUseful); 720 if (strncmp (s, "whenmapped", len) == 0) return (WhenMapped); 721 if (strncmp (s, "always", len) == 0) return (Always); 722 723 usage (); 724} 725 726int 727main (int argc, char **argv) 728{ 729 char *displayname = NULL; 730 char *geom = NULL; 731 int i; 732 XSizeHints hints; 733 int borderwidth = 2; 734 Window w, subw; 735 XSetWindowAttributes attr; 736 XWindowAttributes wattr; 737 unsigned long mask = 0L; 738 int done; 739 char *name = "Event Tester"; 740 Bool reverse = False; 741 Bool use_root = False; 742 unsigned long back, fore; 743 XIM xim; 744 XIMStyles *xim_styles; 745 XIMStyle xim_style = 0; 746 char *modifiers; 747 char *imvalret; 748 749 ProgramName = argv[0]; 750 751 if (setlocale(LC_ALL,"") == NULL) { 752 fprintf(stderr, "%s: warning: could not set default locale\n", 753 ProgramName); 754 } 755 756 w = 0; 757 for (i = 1; i < argc; i++) { 758 char *arg = argv[i]; 759 760 if (arg[0] == '-') { 761 switch (arg[1]) { 762 case 'd': /* -display host:dpy */ 763 if (++i >= argc) usage (); 764 displayname = argv[i]; 765 continue; 766 case 'g': /* -geometry geom */ 767 if (++i >= argc) usage (); 768 geom = argv[i]; 769 continue; 770 case 'b': 771 switch (arg[2]) { 772 case 'w': /* -bw pixels */ 773 if (++i >= argc) usage (); 774 borderwidth = atoi (argv[i]); 775 continue; 776 case 's': /* -bs type */ 777 if (++i >= argc) usage (); 778 attr.backing_store = parse_backing_store (argv[i]); 779 mask |= CWBackingStore; 780 continue; 781 default: 782 usage (); 783 } 784 case 'i': /* -id */ 785 if (++i >= argc) usage (); 786 sscanf(argv[i], "0x%lx", &w); 787 if (!w) 788 sscanf(argv[i], "%lu", &w); 789 if (!w) 790 usage (); 791 continue; 792 case 'n': /* -name */ 793 if (++i >= argc) usage (); 794 name = argv[i]; 795 continue; 796 case 'r': 797 switch (arg[2]) { 798 case 'o': /* -root */ 799 use_root = True; 800 continue; 801 case 'v': /* -rv */ 802 reverse = True; 803 continue; 804 default: 805 usage (); 806 } 807 continue; 808 case 's': /* -s */ 809 attr.save_under = True; 810 mask |= CWSaveUnder; 811 continue; 812 default: 813 usage (); 814 } /* end switch on - */ 815 } else 816 usage (); 817 } /* end for over argc */ 818 819 dpy = XOpenDisplay (displayname); 820 if (!dpy) { 821 fprintf (stderr, "%s: unable to open display '%s'\n", 822 ProgramName, XDisplayName (displayname)); 823 exit (1); 824 } 825 826 /* we're testing the default input method */ 827 modifiers = XSetLocaleModifiers ("@im=none"); 828 if (modifiers == NULL) { 829 fprintf (stderr, "%s: XSetLocaleModifiers failed\n", ProgramName); 830 } 831 832 xim = XOpenIM (dpy, NULL, NULL, NULL); 833 if (xim == NULL) { 834 fprintf (stderr, "%s: XOpenIM failed\n", ProgramName); 835 } 836 837 if (xim) { 838 imvalret = XGetIMValues (xim, XNQueryInputStyle, &xim_styles, NULL); 839 if (imvalret != NULL || xim_styles == NULL) { 840 fprintf (stderr, "%s: input method doesn't support any styles\n", ProgramName); 841 } 842 843 if (xim_styles) { 844 xim_style = 0; 845 for (i = 0; i < xim_styles->count_styles; i++) { 846 if (xim_styles->supported_styles[i] == 847 (XIMPreeditNothing | XIMStatusNothing)) { 848 xim_style = xim_styles->supported_styles[i]; 849 break; 850 } 851 } 852 853 if (xim_style == 0) { 854 fprintf (stderr, "%s: input method doesn't support the style we support\n", 855 ProgramName); 856 } 857 XFree (xim_styles); 858 } 859 } 860 861 screen = DefaultScreen (dpy); 862 863 /* select for all events */ 864 attr.event_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | 865 ButtonReleaseMask | EnterWindowMask | 866 LeaveWindowMask | PointerMotionMask | 867 Button1MotionMask | 868 Button2MotionMask | Button3MotionMask | 869 Button4MotionMask | Button5MotionMask | 870 ButtonMotionMask | KeymapStateMask | 871 ExposureMask | VisibilityChangeMask | 872 StructureNotifyMask | /* ResizeRedirectMask | */ 873 SubstructureNotifyMask | SubstructureRedirectMask | 874 FocusChangeMask | PropertyChangeMask | 875 ColormapChangeMask | OwnerGrabButtonMask; 876 877 if (use_root) 878 w = RootWindow(dpy, screen); 879 880 if (w) { 881 XGetWindowAttributes(dpy, w, &wattr); 882 if (wattr.all_event_masks & ButtonPressMask) 883 attr.event_mask &= ~ButtonPressMask; 884 attr.event_mask &= ~SubstructureRedirectMask; 885 XSelectInput(dpy, w, attr.event_mask); 886 } else { 887 set_sizehints (&hints, OUTER_WINDOW_MIN_WIDTH, OUTER_WINDOW_MIN_HEIGHT, 888 OUTER_WINDOW_DEF_WIDTH, OUTER_WINDOW_DEF_HEIGHT, 889 OUTER_WINDOW_DEF_X, OUTER_WINDOW_DEF_Y, geom); 890 891 if (reverse) { 892 back = BlackPixel(dpy,screen); 893 fore = WhitePixel(dpy,screen); 894 } else { 895 back = WhitePixel(dpy,screen); 896 fore = BlackPixel(dpy,screen); 897 } 898 899 attr.background_pixel = back; 900 attr.border_pixel = fore; 901 mask |= (CWBackPixel | CWBorderPixel | CWEventMask); 902 903 w = XCreateWindow (dpy, RootWindow (dpy, screen), hints.x, hints.y, 904 hints.width, hints.height, borderwidth, 0, 905 InputOutput, (Visual *)CopyFromParent, 906 mask, &attr); 907 908 XSetStandardProperties (dpy, w, name, NULL, (Pixmap) 0, 909 argv, argc, &hints); 910 911 subw = XCreateSimpleWindow (dpy, w, INNER_WINDOW_X, INNER_WINDOW_Y, 912 INNER_WINDOW_WIDTH, INNER_WINDOW_HEIGHT, 913 INNER_WINDOW_BORDER, 914 attr.border_pixel, attr.background_pixel); 915 916 wm_protocols = XInternAtom(dpy, "WM_PROTOCOLS", False); 917 wm_delete_window = XInternAtom(dpy, "WM_DELETE_WINDOW", False); 918 XSetWMProtocols(dpy, w, &wm_delete_window, 1); 919 920 XMapWindow (dpy, subw); /* map before w so that it appears */ 921 XMapWindow (dpy, w); 922 923 printf ("Outer window is 0x%lx, inner window is 0x%lx\n", w, subw); 924 } 925 926 if (xim && xim_style) { 927 xic = XCreateIC (xim, 928 XNInputStyle, xim_style, 929 XNClientWindow, w, 930 XNFocusWindow, w, 931 NULL); 932 933 if (xic == NULL) { 934 fprintf (stderr, "XCreateIC failed\n"); 935 } 936 } 937 938 for (done = 0; !done; ) { 939 XEvent event; 940 941 XNextEvent (dpy, &event); 942 943 switch (event.type) { 944 case KeyPress: 945 prologue (&event, "KeyPress"); 946 do_KeyPress (&event); 947 break; 948 case KeyRelease: 949 prologue (&event, "KeyRelease"); 950 do_KeyRelease (&event); 951 break; 952 case ButtonPress: 953 prologue (&event, "ButtonPress"); 954 do_ButtonPress (&event); 955 break; 956 case ButtonRelease: 957 prologue (&event, "ButtonRelease"); 958 do_ButtonRelease (&event); 959 break; 960 case MotionNotify: 961 prologue (&event, "MotionNotify"); 962 do_MotionNotify (&event); 963 break; 964 case EnterNotify: 965 prologue (&event, "EnterNotify"); 966 do_EnterNotify (&event); 967 break; 968 case LeaveNotify: 969 prologue (&event, "LeaveNotify"); 970 do_LeaveNotify (&event); 971 break; 972 case FocusIn: 973 prologue (&event, "FocusIn"); 974 do_FocusIn (&event); 975 break; 976 case FocusOut: 977 prologue (&event, "FocusOut"); 978 do_FocusOut (&event); 979 break; 980 case KeymapNotify: 981 prologue (&event, "KeymapNotify"); 982 do_KeymapNotify (&event); 983 break; 984 case Expose: 985 prologue (&event, "Expose"); 986 do_Expose (&event); 987 break; 988 case GraphicsExpose: 989 prologue (&event, "GraphicsExpose"); 990 do_GraphicsExpose (&event); 991 break; 992 case NoExpose: 993 prologue (&event, "NoExpose"); 994 do_NoExpose (&event); 995 break; 996 case VisibilityNotify: 997 prologue (&event, "VisibilityNotify"); 998 do_VisibilityNotify (&event); 999 break; 1000 case CreateNotify: 1001 prologue (&event, "CreateNotify"); 1002 do_CreateNotify (&event); 1003 break; 1004 case DestroyNotify: 1005 prologue (&event, "DestroyNotify"); 1006 do_DestroyNotify (&event); 1007 break; 1008 case UnmapNotify: 1009 prologue (&event, "UnmapNotify"); 1010 do_UnmapNotify (&event); 1011 break; 1012 case MapNotify: 1013 prologue (&event, "MapNotify"); 1014 do_MapNotify (&event); 1015 break; 1016 case MapRequest: 1017 prologue (&event, "MapRequest"); 1018 do_MapRequest (&event); 1019 break; 1020 case ReparentNotify: 1021 prologue (&event, "ReparentNotify"); 1022 do_ReparentNotify (&event); 1023 break; 1024 case ConfigureNotify: 1025 prologue (&event, "ConfigureNotify"); 1026 do_ConfigureNotify (&event); 1027 break; 1028 case ConfigureRequest: 1029 prologue (&event, "ConfigureRequest"); 1030 do_ConfigureRequest (&event); 1031 break; 1032 case GravityNotify: 1033 prologue (&event, "GravityNotify"); 1034 do_GravityNotify (&event); 1035 break; 1036 case ResizeRequest: 1037 prologue (&event, "ResizeRequest"); 1038 do_ResizeRequest (&event); 1039 break; 1040 case CirculateNotify: 1041 prologue (&event, "CirculateNotify"); 1042 do_CirculateNotify (&event); 1043 break; 1044 case CirculateRequest: 1045 prologue (&event, "CirculateRequest"); 1046 do_CirculateRequest (&event); 1047 break; 1048 case PropertyNotify: 1049 prologue (&event, "PropertyNotify"); 1050 do_PropertyNotify (&event); 1051 break; 1052 case SelectionClear: 1053 prologue (&event, "SelectionClear"); 1054 do_SelectionClear (&event); 1055 break; 1056 case SelectionRequest: 1057 prologue (&event, "SelectionRequest"); 1058 do_SelectionRequest (&event); 1059 break; 1060 case SelectionNotify: 1061 prologue (&event, "SelectionNotify"); 1062 do_SelectionNotify (&event); 1063 break; 1064 case ColormapNotify: 1065 prologue (&event, "ColormapNotify"); 1066 do_ColormapNotify (&event); 1067 break; 1068 case ClientMessage: 1069 prologue (&event, "ClientMessage"); 1070 do_ClientMessage (&event); 1071 break; 1072 case MappingNotify: 1073 prologue (&event, "MappingNotify"); 1074 do_MappingNotify (&event); 1075 break; 1076 default: 1077 printf ("Unknown event type %d\n", event.type); 1078 break; 1079 } 1080 fflush(stdout); 1081 } 1082 1083 XCloseDisplay (dpy); 1084 return 0; 1085} 1086