1: #include <X/mit-copyright.h> 2: 3: /* Copyright Massachusetts Institute of Technology 1985 */ 4: 5: /* Routines for dealing with input devices and events: 6: * 7: * Register_cursor, Unregister_cursor, Interpret_locator, 8: * Grab_mouse, Ungrab_mouse, Grab_button, Ungrab_button, Warp_mouse, 9: * Focus_keyboard, Unbutton_window, Ungrab_client, Select_input, 10: * Set_shiftlock, Startup_mouse, 11: * Deal_with_movement, Deal_with_input, 12: * Stash_changes, Stash_misses, Stash_simple 13: */ 14: 15: #ifndef lint 16: static char *rcsid_input_c = "$Header: input.c,v 10.11 86/02/01 15:16:07 tony Rel $"; 17: #endif 18: 19: 20: #include "Xint.h" 21: 22: extern u_char Xstatus; 23: extern DEVICE device; 24: extern WINDOW *rootwindow; 25: extern RECTANGLE *free_rectangles; 26: #ifdef DUALTCP 27: extern int swapped[]; 28: #endif 29: 30: typedef struct grab_info { 31: int client; /* Grabbing client */ 32: WINDOW *window; /* Event window */ 33: long mask; /* Event mask */ 34: CURSOR *cursor; /* Cursor info */ 35: } GRAB_INFO; 36: 37: static short mouse_x = 0, mouse_y = 0; /* The mouse state */ 38: CURSOR *cursor = NULL; /* Current cursor */ 39: static WINDOW *cursor_window = NULL; /* Where cursor came from */ 40: static WINDOW *mouse_window; /* Where mouse currently is */ 41: RASTER mbox; /* Mouse motion bounding box */ 42: WINDOW *button_window = NULL; /* Where button was pressed */ 43: int mouse_grabber = 0; /* Who has grabbed the mouse */ 44: WINDOW *mouse_grab_window; /* Window for grab events */ 45: static long mouse_grab_mask; /* Grab events of interest */ 46: static unsigned mouse_grab_button; /* Button that caused grab */ 47: WINDOW *key_window; /* Keyboard focus window */ 48: static ushort key_level; /* key_window->level */ 49: static unsigned state_mask = 0; /* key and button state mask */ 50: static int lock_mode = 1; /* shiftlock mode */ 51: static unsigned lock_mask = 0; /* shiftlock shadow mask */ 52: static long motion_mask = MouseMoved; /* motion events */ 53: #define GRABS 48 54: static GRAB_INFO bgrabs[GRABS]; /* button grab info */ 55: #define GRABIDX(but,mask) ((but << 4) + FullKeyState(mask)) 56: #define grabbits (ControlMask|MetaMask|ShiftMask|ShiftLockMask|LeftMask|MiddleMask|RightMask) 57: 58: #define ShiftKeyCode 0256 59: #define ControlKeyCode 0257 60: #define LockKeyCode 0260 61: #define MetaKeyCode 0261 62: 63: /* Search down the heirarchy for the smallest enclosing window. 64: * This usually should be faster than doing a linear search of mapped_list, 65: * and should be fast enough that we don't need to maintain extra, complicated 66: * data structures like a layered dag. 67: */ 68: 69: #define SEARCH(x,y,w,ww) \ 70: ww = rootwindow;\ 71: w = ww->last_child;\ 72: while (w) {\ 73: if (TRUE(w->mapped) &&\ 74: x >= w->vs.left && y >= w->vs.top &&\ 75: x < w->vs.right && y < w->vs.bottom) {\ 76: ww = w;\ 77: w = ww->last_child;\ 78: } else\ 79: w = w->prev_sib;\ 80: }\ 81: if (w == NULL)\ 82: w = ww 83: 84: /* Define the mouse cursor for a window */ 85: 86: Register_cursor (w, curs) 87: register WINDOW *w; 88: register CURSOR *curs; 89: { 90: register CURSOR *ocurs; 91: 92: ocurs = w->cursor; 93: curs->refcnt++; 94: w->cursor = curs; 95: if (mouse_grabber == 0) 96: Check_cursor (w); 97: if (ocurs && --ocurs->refcnt == 0) 98: FreeCursor (ocurs); 99: } 100: 101: /* Undefine the mouse cursor for a window */ 102: 103: Unregister_cursor (w) 104: register WINDOW *w; 105: { 106: register CURSOR *curs; 107: 108: if ((curs = w->cursor) == NULL || w == rootwindow) 109: return; 110: w->cursor = NULL; 111: if (mouse_grabber == 0) 112: Check_cursor (w); 113: if (--curs->refcnt == 0) 114: FreeCursor (curs); 115: } 116: 117: /* Start up the mouse. */ 118: 119: Startup_mouse () 120: { 121: vsCursor mcursor; 122: 123: cursor = rootwindow->cursor; 124: LoadCursor (cursor); 125: InitMouse (); 126: mcursor.x = (mouse_x = (device.width >> 1)) - cursor->xoff; 127: mcursor.y = (mouse_y = (device.height >> 1)) - cursor->yoff; 128: SetCursorPosition (&mcursor); 129: mouse_window = rootwindow; 130: mbox.bottom = 0; 131: Set_mbox (); 132: } 133: 134: /* The cursor in the given window has changed. Check if it is/was the cursor 135: * window, and update the cursor if it is. 136: */ 137: 138: Check_cursor (w) 139: register WINDOW *w; 140: { 141: register WINDOW *ww; 142: 143: if ((ww = mouse_window) == NULL) return; 144: for (; ww->cursor == NULL; ww = ww->parent) ; 145: if (ww != cursor_window || ww == w) { 146: New_cursor (0, 0); 147: Deal_with_movement (); 148: } 149: } 150: 151: /* Change the cursor. The deltas give the physical adjustment from the old 152: * cursor to keep the "point" from moving. 153: */ 154: 155: New_cursor (deltax, deltay) 156: int deltax, deltay; 157: { 158: vsCursor mcursor; 159: register CURSOR *curs = cursor; 160: short x, y; 161: register WINDOW *w, *ww; 162: int old = 0; 163: 164: mcursor = *device.mouse; 165: x = mcursor.x + cursor->xoff + deltax; 166: y = mcursor.y + cursor->yoff + deltay; 167: 168: while (1) { 169: /* force cursor to stay in bounds */ 170: if (x < curs->xmin) 171: x = curs->xmin; 172: else if (x > curs->xmax) 173: x = curs->xmax; 174: 175: if (y < curs->ymin) 176: y = curs->ymin; 177: else if (y > curs->ymax) 178: y = curs->ymax; 179: 180: if (mouse_grabber) break; 181: SEARCH(x, y, w, ww); 182: while (w->cursor == NULL) 183: w = w->parent; 184: if (old && w == cursor_window) 185: break; 186: cursor_window = w; 187: cursor = curs = w->cursor; 188: old = 1; 189: } 190: 191: if ((x - curs->xoff) != mcursor.x || 192: (y - curs->yoff) != mcursor.y) { 193: mcursor.x = x - curs->xoff; 194: mcursor.y = y - curs->yoff; 195: SetCursorPosition (&mcursor); 196: } 197: LoadCursor (curs); 198: } 199: 200: /* Deal with mouse motion or window changes */ 201: 202: Deal_with_movement () 203: { 204: vsCursor mcursor; 205: register CURSOR *curs = cursor; 206: register WINDOW *w, *ww, *oldw; 207: short x, y; 208: int new; 209: 210: /* read current mouse coordinates */ 211: mcursor = *device.mouse; 212: x = mcursor.x + curs->xoff; 213: y = mcursor.y + curs->yoff; 214: 215: oldw = mouse_window; 216: 217: /* fast check to see if we are still in box */ 218: if (y < mbox.bottom && y >= mbox.top && 219: x < mbox.right && x >= mbox.left) { 220: if (x != mouse_x || y != mouse_y) { 221: mouse_x = x; 222: mouse_y = y; 223: Stash_event (oldw, motion_mask, 0, x, y, 0); 224: } 225: /* may need to reset device mbox */ 226: Set_mbox (); 227: return; 228: } 229: mbox.bottom = 0; 230: 231: new = 0; 232: while (1) { 233: /* force cursor to stay in bounds */ 234: if (x < curs->xmin) 235: x = curs->xmin; 236: else if (x > curs->xmax) 237: x = curs->xmax; 238: 239: if (y < curs->ymin) 240: y = curs->ymin; 241: else if (y > curs->ymax) 242: y = curs->ymax; 243: 244: SEARCH(x, y, w, ww); 245: if (w == mouse_window) break; 246: mouse_window = w; 247: if (mouse_grabber) break; 248: while (w->cursor == NULL) 249: w = w->parent; 250: if (w != cursor_window) { 251: cursor_window = w; 252: cursor = curs = w->cursor; 253: new = 1; 254: } 255: } 256: 257: if ((x - curs->xoff) != mcursor.x || 258: (y - curs->yoff) != mcursor.y) { 259: mcursor.x = x - curs->xoff; 260: mcursor.y = y - curs->yoff; 261: SetCursorPosition (&mcursor); 262: } 263: if TRUE(new) 264: LoadCursor (curs); 265: 266: w = mouse_window; 267: if (w != oldw) { 268: mouse_x = x; 269: mouse_y = y; 270: while (oldw->level < w->level) 271: w = w->parent; 272: if (w == oldw) 273: Stash_event (oldw, (long) LeaveWindow, 274: IntoOrFromSubwindow, x, y, 0); 275: else { 276: if TRUE(oldw->mapped) 277: Stash_event (oldw, (long) LeaveWindow, 0, x, y, 0); 278: while (oldw->level > w->level) { 279: oldw = oldw->parent; 280: if (oldw == w) { 281: Stash_event (oldw, (long) EnterWindow, 282: IntoOrFromSubwindow, x, y, 0); 283: goto done; /* grot */ 284: } else if ((oldw->mask & LeaveWindow) && TRUE(oldw->mapped)) 285: Stash_event (oldw, (long) LeaveWindow, 286: VirtualCrossing, x, y, 0); 287: } 288: while (1) { 289: oldw = oldw->parent; 290: w = w->parent; 291: if (oldw == w) 292: break; 293: if ((oldw->mask & LeaveWindow) && TRUE(oldw->mapped)) 294: Stash_event (oldw, (long) LeaveWindow, 295: VirtualCrossing, x, y, 0); 296: } 297: } 298: w = mouse_window; 299: if (oldw != w->parent) 300: Stash_enters (oldw, w->parent, 0); 301: Stash_event (w, (long) EnterWindow, 0, x, y, 0); 302: } else if (x != mouse_x || y != mouse_y) { 303: Stash_event (w, motion_mask, 0, x, y, 0); 304: mouse_x = x; 305: mouse_y = y; 306: } 307: done: Set_mbox (); 308: } 309: 310: /* Select events */ 311: 312: Select_input (w, client, mask) 313: register WINDOW *w; 314: int client; 315: long mask; 316: { 317: long omask = w->mask; 318: 319: /* stop a button grab in progress if no longer interested in release */ 320: if (w == button_window && 321: (client != w->client || !(mask & ButtonReleased))) 322: button_window = NULL; 323: w->mask = mask; 324: w->client = client; 325: 326: /* recompute motion box if movement interest changes */ 327: if (mouse_grabber == 0 && ((omask ^ mask) & motion_mask)) 328: Set_mbox (); 329: } 330: 331: /* Change the ShiftLock mode */ 332: 333: Set_shiftlock (mode) 334: register int mode; 335: { 336: register unsigned mask; 337: 338: if (lock_mode != mode) { 339: lock_mode = mode; 340: mask = state_mask; 341: state_mask &= ~ShiftLockMask; 342: state_mask |= lock_mask; 343: lock_mask = mask & ShiftLockMask; 344: } 345: SetLockLED((lock_mode && (state_mask & ShiftLockMask)) ? 1 : 0); 346: } 347: 348: /* Set motion box */ 349: 350: Set_mbox () 351: { 352: register WINDOW *w, *sw; 353: register RECTANGLE *r; 354: register CURSOR *curs; 355: vsBox b; 356: 357: /* recalculate if need be */ 358: if (mbox.bottom <= mbox.top) { 359: w = mouse_window; 360: /* use containing visible rectangle if any */ 361: for (r = w->visible; 362: r && (mouse_x < r->left || mouse_x >= r->right || 363: mouse_y < r->top || mouse_y >= r->bottom); 364: r = r->next) ; 365: if (r) 366: mbox = *(RASTER *) r; 367: else 368: mbox = w->vs; 369: if (sw = w->first_child) 370: w = sw; 371: else 372: sw = w->next_sib; 373: /* clip with obscuring windows */ 374: while (1) { 375: if (sw == NULL) { 376: if ((w = w->parent) == NULL) 377: break; 378: sw = w->next_sib; 379: continue; 380: } else if (FALSE(sw->mapped) || (r && sw->kind != IsTransparent)) { 381: sw = sw->next_sib; 382: continue; 383: } 384: if (sw->vs.top < mbox.bottom && sw->vs.bottom > mbox.top) { 385: if (sw->vs.right > mbox.left && sw->vs.right <= mouse_x) 386: mbox.left = sw->vs.right; 387: else if (sw->vs.left < mbox.right && sw->vs.left >= mouse_x) 388: mbox.right = sw->vs.left; 389: } 390: if (sw->vs.left < mbox.right && sw->vs.right > mbox.left) { 391: if (sw->vs.bottom > mbox.top && sw->vs.bottom <= mouse_y) 392: mbox.top = sw->vs.bottom; 393: else if (sw->vs.top < mbox.bottom && sw->vs.top >= mouse_y) 394: mbox.bottom = sw->vs.top; 395: } 396: sw = sw->next_sib; 397: } 398: } 399: 400: /* if anyone wants motion events, we lose */ 401: if ((mouse_grabber && (mouse_grab_mask & motion_mask)) || 402: (button_window && (button_window->mask & motion_mask))) { 403: device.mbox->bottom = 0; 404: return; 405: } 406: for (w = mouse_window; w; w = w->parent) { 407: if (w->mask & motion_mask) { 408: device.mbox->bottom = 0; 409: return; 410: } 411: } 412: curs = cursor; 413: b.left = mbox.left - curs->xoff; 414: b.right = mbox.right - curs->xoff; 415: b.top = mbox.top - curs->yoff; 416: b.bottom = mbox.bottom - curs->yoff; 417: *device.mbox = b; 418: } 419: 420: /* Deal with a button/key transition */ 421: 422: Deal_with_input (ev) 423: register vsEvent *ev; 424: { 425: register WINDOW *w, *ww; 426: short x = ev->vse_x + cursor->xoff; 427: short y = ev->vse_y + cursor->yoff; 428: 429: w = mouse_window; 430: /* lightning usually strikes twice */ 431: if (y >= mbox.bottom || y < mbox.top || 432: x >= mbox.right || x < mbox.left) { 433: /* but not this time */ 434: SEARCH(x, y, w, ww); 435: } 436: if (ev->vse_device == VSE_DKB) { 437: if (ev->vse_direction == VSE_KBTUP) { 438: Stash_event (w, (long) KeyReleased, ev->vse_key, 439: x, y, ev->vse_time); 440: switch (ev->vse_key) { 441: case ShiftKeyCode: 442: state_mask &= ~ShiftMask; 443: break; 444: case ControlKeyCode: 445: state_mask &= ~ControlMask; 446: break; 447: case LockKeyCode: 448: if TRUE(lock_mode) 449: lock_mask = 0; 450: else 451: state_mask &= ~ShiftLockMask; 452: break; 453: case MetaKeyCode: 454: state_mask &= ~MetaMask; 455: break; 456: } 457: } else { 458: Stash_event (w, (long) KeyPressed, ev->vse_key, 459: x, y, ev->vse_time); 460: switch (ev->vse_key) { 461: case ShiftKeyCode: 462: state_mask |= ShiftMask; 463: break; 464: case ControlKeyCode: 465: state_mask |= ControlMask; 466: break; 467: case LockKeyCode: 468: if TRUE(lock_mode) { 469: state_mask ^= ShiftLockMask; 470: lock_mask = ShiftLockMask; 471: SetLockLED (state_mask & ShiftLockMask ? 1 : 0); 472: } else { 473: state_mask |= ShiftLockMask; 474: lock_mask ^= ShiftLockMask; 475: } 476: break; 477: case MetaKeyCode: 478: state_mask |= MetaMask; 479: break; 480: } 481: } 482: } else { 483: if (ev->vse_direction == VSE_KBTUP) { 484: Stash_event (w, (long) ButtonReleased, 2 - ev->vse_key, 485: x, y, ev->vse_time); 486: motion_mask &= ~(LeftDownMotion >> ev->vse_key); 487: state_mask &= ~(LeftMask >> ev->vse_key); 488: if (!(state_mask & (LeftMask|MiddleMask|RightMask))) { 489: /* check for end of grab */ 490: if (button_window || (mouse_grabber && mouse_grab_button)) 491: Stash_ungrabs (); 492: } 493: } else { 494: if (button_window == NULL && mouse_grabber == 0) { 495: /* check for start of grab */ 496: if (bgrabs[GRABIDX(ev->vse_key, state_mask)].client) 497: Button_grab (ev->vse_key, state_mask); 498: else { 499: ww = w; 500: while (!(ww->mask & ButtonPressed)) { 501: if ((ww = ww->parent) == NULL) break; 502: } 503: if (ww && (ww->mask & ButtonReleased)) { 504: Stash_grabs (ww->client); 505: button_window = ww; 506: } 507: } 508: } 509: Stash_event (w, (long) ButtonPressed, 2 - ev->vse_key, 510: x, y, ev->vse_time); 511: motion_mask |= (LeftDownMotion >> ev->vse_key); 512: state_mask |= (LeftMask >> ev->vse_key); 513: } 514: Deal_with_movement (); 515: } 516: } 517: 518: /* Give the client sole possession of the mouse */ 519: 520: Grab_mouse (w, curs, mask, client) 521: register WINDOW *w; 522: register CURSOR *curs; 523: long mask; 524: int client; 525: { 526: register CURSOR *ocurs; 527: int deltax, deltay; 528: 529: if ((button_window && button_window->client != client) || 530: (mouse_grabber && mouse_grabber != client)) { 531: Xstatus = BadGrab; 532: return; 533: } 534: ocurs = cursor; 535: deltax = ocurs->xoff - curs->xoff; 536: deltay = ocurs->yoff - curs->yoff; 537: button_window = NULL; 538: if (mouse_grabber == 0) { 539: Stash_grabs (client); 540: mouse_grabber = client; 541: ocurs = NULL; 542: } else if (mouse_grab_button) 543: ocurs = NULL; 544: mouse_grab_window = w; 545: mouse_grab_mask = mask; 546: mouse_grab_button = 0; 547: 548: curs->refcnt++; 549: cursor = curs; 550: New_cursor (deltax, deltay); 551: cursor_window = NULL; 552: Deal_with_movement (); 553: if (ocurs && --ocurs->refcnt == 0) 554: FreeCursor (ocurs); 555: } 556: 557: /* Ungrab the mouse */ 558: 559: Ungrab_mouse (client) 560: int client; 561: { 562: if (client == mouse_grabber && mouse_grab_button == 0) { 563: Stash_ungrabs (); 564: Deal_with_movement (); 565: } 566: } 567: 568: /* Indicates that a client wants sole possession of the mouse when the 569: * specified button is down. 570: */ 571: 572: Grab_button (w, curs, button, mask, client) 573: register WINDOW *w; 574: CURSOR *curs; 575: unsigned button; 576: long mask; 577: int client; 578: { 579: register int i; 580: register GRAB_INFO *grab; 581: register CURSOR *ocurs; 582: 583: i = ButtonState(button); 584: if (i == 0 || (i & (i - 1))) { 585: Xstatus = BadValue; 586: return; 587: } else if (i == 4) 588: i = 3; 589: grab = &bgrabs[GRABIDX(3 - i, button)]; 590: if (grab->client && grab->client != client) { 591: Xstatus = BadGrab; 592: return; 593: } 594: if (grab->client) { 595: ocurs = grab->cursor; 596: grab->window->bgrabs--; 597: } else 598: ocurs = NULL; 599: 600: grab->client = client; 601: grab->window = w; 602: grab->mask = mask; 603: grab->cursor = curs; 604: curs->refcnt++; 605: w->bgrabs++; 606: 607: /* check if this is an in-progress update */ 608: if (mouse_grabber && mouse_grab_button == (button & grabbits)) { 609: Button_grab ((unsigned) 3 - i, button); 610: Deal_with_movement (); 611: } 612: if (ocurs && --ocurs->refcnt == 0) 613: FreeCursor (ocurs); 614: } 615: 616: /* Ungrab a button */ 617: 618: Ungrab_button (button, client) 619: unsigned button; 620: int client; 621: { 622: register int i; 623: register GRAB_INFO *grab; 624: 625: i = ButtonState(button); 626: if (i == 0 || (i & (i - 1))) { 627: Xstatus = BadValue; 628: return; 629: } else if (i == 4) 630: i = 3; 631: grab = &bgrabs[GRABIDX(3 - i, button)]; 632: if (grab->client != client) 633: return; 634: grab->client = 0; 635: grab->window->bgrabs--; 636: /* check if aborting */ 637: if (client == mouse_grabber && mouse_grab_button == (button & grabbits)) 638: Stash_ungrabs (); 639: Deal_with_movement (); 640: if (--grab->cursor->refcnt == 0) 641: FreeCursor (grab->cursor); 642: } 643: 644: /* Start a button grab */ 645: 646: Button_grab (key, mask) 647: register unsigned key, mask; 648: { 649: register GRAB_INFO *grab; 650: int deltax, deltay; 651: 652: grab = &bgrabs[GRABIDX(key, mask)]; 653: if (mouse_grabber == 0) { 654: Stash_grabs (grab->client); 655: mouse_grabber = grab->client; 656: } 657: mouse_grab_window = grab->window; 658: mouse_grab_mask = grab->mask; 659: mouse_grab_button = (mask & (ControlMask|MetaMask|ShiftMask|ShiftLockMask)) | 660: (LeftMask >> key); 661: deltax = cursor->xoff - grab->cursor->xoff; 662: deltay = cursor->yoff - grab->cursor->yoff; 663: cursor = grab->cursor; 664: New_cursor (deltax, deltay); 665: cursor_window = NULL; 666: } 667: 668: /* Conditionally warp mouse to new position */ 669: 670: Warp_mouse (dstw, dstx, dsty, srcw, src) 671: WINDOW *dstw, *srcw; 672: int dstx, dsty; 673: register REGION *src; 674: { 675: int x, y, width, height; 676: register int cx, cy; 677: register RECTANGLE *v; 678: register WINDOW *w; 679: vsCursor mcursor; 680: 681: w = srcw; 682: if FALSE(w->mapped) return; 683: /* get absolute coordinates */ 684: x = w->full.left + src->left; 685: y = w->full.top + src->top; 686: if ((width = src->width) == 0) 687: width = w->full.right - x; 688: if ((height = src->height) == 0) 689: height = w->full.bottom - y; 690: mcursor = *device.mouse; 691: cx = mcursor.x + cursor->xoff; 692: cy = mcursor.y + cursor->yoff; 693: if (cx < x || cy < y || cx >= x + width || cy >= y + height) 694: return; 695: for (v = w->cmvisible; v; v = v->next) { 696: if (cx < v->left || cy < v->top || 697: cx >= v->right || cy >= v->bottom) 698: continue; 699: cx = dstx; 700: cy = dsty; 701: w = dstw; 702: /* get absolute coordinates */ 703: while (1) { 704: cx += w->full.left; 705: cy += w->full.top; 706: if TRUE(w->mapped) break; 707: w = w->parent; 708: } 709: mcursor = *device.mouse; 710: New_cursor (cx - cursor->xoff - mcursor.x, 711: cy - cursor->yoff - mcursor.y); 712: Deal_with_movement (); 713: } 714: } 715: 716: /* Change keyboard focus */ 717: 718: Focus_keyboard (w) 719: register WINDOW *w; 720: { 721: if (key_window != w) { 722: if (key_window) 723: Stash_simple (key_window, (long) FocusChange, LeaveWindow); 724: key_window = w; 725: key_level = w->level; 726: Stash_simple (w, (long) FocusChange, EnterWindow); 727: } 728: } 729: 730: /* Remove grabs that use this window */ 731: 732: Unbutton_window (w) 733: register WINDOW *w; 734: { 735: register GRAB_INFO *grab; 736: 737: for (grab = &bgrabs[0]; ; grab++) { 738: if (w == grab->window && grab->client) { 739: grab->client = 0; 740: if (--grab->cursor->refcnt == 0) 741: FreeCursor (grab->cursor); 742: if (--w->bgrabs == 0) 743: return; 744: } 745: } 746: } 747: 748: /* Remove grabs by this client */ 749: 750: Ungrab_client (client) 751: int client; 752: { 753: register GRAB_INFO *grab; 754: 755: if (client == mouse_grabber || 756: (button_window && client == button_window->client)) 757: Stash_ungrabs (); 758: for (grab = &bgrabs[0]; grab != &bgrabs[GRABS]; grab++) { 759: if (client == grab->client) { 760: grab->client = 0; 761: grab->window->bgrabs--; 762: if (--grab->cursor->refcnt == 0) 763: FreeCursor (grab->cursor); 764: } 765: } 766: } 767: 768: /* Generate leave events at mouse grab */ 769: 770: Stash_grabs (client) 771: register int client; 772: { 773: register WINDOW *w; 774: 775: w = mouse_window; 776: if (w == rootwindow) return; 777: if (w->client != client) { 778: while (!(w->mask & LeaveWindow) && (w = w->parent) && 779: w->client != client) ; 780: if (w && w->client != client) 781: Stash_event (mouse_window, (long) LeaveWindow, 782: 0, mouse_x, mouse_y, 0); 783: w = mouse_window; 784: } 785: while ((w = w->parent) != rootwindow) { 786: if (w->client != client && (w->mask & LeaveWindow)) 787: Stash_event (w, (long) LeaveWindow, VirtualCrossing, 788: mouse_x, mouse_y, 0); 789: } 790: } 791: 792: /* Restore cursor and generate enter events at mouse ungrab */ 793: 794: Stash_ungrabs () 795: { 796: register WINDOW *w; 797: register int client; 798: CURSOR *curs; 799: 800: if (button_window) { 801: client = button_window->client; 802: button_window = NULL; 803: } else { 804: client = mouse_grabber; 805: mouse_grabber = 0; 806: if (mouse_grab_button) 807: New_cursor (0, 0); 808: else { 809: curs = cursor; 810: New_cursor (0, 0); 811: if (--curs->refcnt == 0) 812: FreeCursor (curs); 813: } 814: } 815: w = mouse_window; 816: while (w != rootwindow && 817: (w->client == client || !(w->mask & EnterWindow))) 818: w = w->parent; 819: if (w != rootwindow) { 820: w = mouse_window; 821: if (rootwindow != w->parent) 822: Stash_enters (rootwindow, w->parent, client); 823: if (w->client != client) { 824: while (!(w->mask & EnterWindow) && (w = w->parent) && 825: w->client != client) ; 826: if (w && w->client != client) 827: Stash_event (mouse_window, (long) EnterWindow, 828: 0, mouse_x, mouse_y, 0); 829: } 830: } 831: } 832: 833: /* Stash enter events in windows */ 834: 835: Stash_enters (p, c, client) 836: WINDOW *p, *c; 837: int client; 838: { 839: if (p != c->parent) 840: Stash_enters (p, c->parent, client); 841: if (c->client != client && (c->mask & EnterWindow)) 842: Stash_event (c, (long) EnterWindow, VirtualCrossing, 843: mouse_x, mouse_y, 0); 844: } 845: 846: /* Place an event in the event queue of a window */ 847: 848: Stash_event (w, event, detail, x, y, time) 849: register WINDOW *w; 850: register long event; 851: short x, y; 852: unsigned detail, time; 853: { 854: register WINDOW *sub = NULL; 855: WINDOW *ww; 856: XRep rep; 857: int client; 858: #ifdef DUALTCP 859: register swaptype n; 860: #endif 861: 862: /* Find someone who is interested in dealing with this event 863: * and set w to the window lowest in the hierarchy at or 864: * above the original event window that is interested. 865: */ 866: 867: if (event & (KeyPressed|KeyReleased)) { 868: while (1) { 869: if (!(w->mask & event)) { 870: sub = w; 871: if (w->level > key_level) { 872: w = w->parent; 873: continue; 874: } 875: } else if (key_level == 0) { 876: break; 877: } else { 878: ww = w; 879: while (ww->level > key_level) 880: ww = ww->parent; 881: if (ww == key_window) 882: break; 883: } 884: w = key_window; 885: if (!(w->mask & event)) 886: return; 887: sub = NULL; 888: break; 889: } 890: client = w->client; 891: } else if (button_window) { 892: while (w && !(w->mask & event)) { 893: sub = w; 894: w = w->parent; 895: } 896: client = button_window->client; 897: if (w == NULL || w->client != client) { 898: sub = w; 899: w = button_window; 900: if (!((w->mask & event) & ~(EnterWindow|LeaveWindow))) 901: return; 902: while (sub && sub->parent != w) 903: sub = sub->parent; 904: } 905: } else if (mouse_grabber) { 906: while (w && 907: !(event & ((w == mouse_grab_window) ? mouse_grab_mask : 908: w->mask))) { 909: sub = w; 910: w = w->parent; 911: } 912: client = mouse_grabber; 913: if (w == NULL || (w != mouse_grab_window && w->client != client)) { 914: if (!((mouse_grab_mask & event) & ~(EnterWindow|LeaveWindow))) 915: return; 916: sub = w; 917: w = mouse_grab_window; 918: while (sub && sub->parent != w) 919: sub = sub->parent; 920: } 921: } else { 922: while (!(w->mask & event)) { 923: sub = w; 924: if ((w = w->parent) == NULL) return; 925: } 926: client = w->client; 927: } 928: 929: rep.code = event & ~(LeftDownMotion|MiddleDownMotion|RightDownMotion); 930: rep.param.l[0] = w->rid; 931: rep.param.s[2] = time; 932: rep.param.s[3] = state_mask | detail; 933: rep.param.s[4] = x - w->full.left; 934: rep.param.s[5] = y - w->full.top; 935: rep.param.l[3] = (sub ? sub->rid : 0); 936: #ifdef vax 937: rep.param.s[8] = y; 938: rep.param.s[9] = x; 939: #else 940: #ifdef mc68000 941: rep.param.s[9] = y; 942: rep.param.s[8] = x; 943: #else 944: rep.param.l[4] = (x << 16) | y; 945: #endif 946: #endif 947: #ifdef DUALTCP 948: if (swapped[client]) { 949: swapl(&rep.code); 950: pswapl(&rep, 0); 951: pswaps(&rep, 2); 952: pswaps(&rep, 3); 953: pswaps(&rep, 4); 954: pswaps(&rep, 5); 955: pswapl(&rep, 3); 956: pswapl(&rep, 4); 957: } 958: #endif 959: Write (client, (caddr_t) &rep, sizeof (XRep)); 960: } 961: 962: /* Place window changes in the event queue of a window. 963: * If not_just_new, generate an ExposeWindow, else update visible list and 964: * generate ExposeRegions (or ExposeWindow). 965: */ 966: 967: Stash_changes (w, not_just_new) 968: register WINDOW *w; 969: register int not_just_new; 970: { 971: register WINDOW *ew = w; 972: register RECTANGLE *r, **prev; 973: RECTANGLE *changed = NULL; 974: XRep rep; 975: #ifdef DUALTCP 976: register swaptype n; 977: #endif 978: 979: while (!(ew->mask & (ExposeWindow|ExposeRegion))) { 980: if (ew = ew->parent) 981: continue; 982: if TRUE(not_just_new) 983: return; 984: /* nobody interested, just update */ 985: prev = &w->visible; 986: while (r = *prev) { 987: if (r->type == new_rec) { 988: r->type = contents_rec; 989: *prev = r->next; 990: r->next = changed; 991: changed = r; 992: } else 993: prev = &r->next; 994: } 995: if (changed) { 996: Merge_rectangles (changed, &w->visible); 997: Windex (w); 998: } 999: return; 1000: } 1001: 1002: rep.param.l[0] = ew->rid; 1003: rep.param.s[3] = 0; 1004: rep.param.l[3] = (w == ew) ? 0 : w->rid; 1005: #ifdef DUALTCP 1006: if (swapped[ew->client]) { 1007: rep.code = lswapl(ExposeRegion); 1008: pswapl(&rep, 0); 1009: pswapl(&rep, 3); 1010: } else 1011: #endif 1012: rep.code = ExposeRegion; 1013: 1014: if FALSE(not_just_new) { 1015: prev = &w->visible; 1016: while (r = *prev) { 1017: if (r->type == new_rec) { 1018: r->type = contents_rec; 1019: *prev = r->next; 1020: r->next = changed; 1021: changed = r; 1022: if (ew->mask & ExposeRegion) { 1023: rep.param.s[4] = r->right - r->left; 1024: rep.param.s[5] = r->bottom - r->top; 1025: rep.param.s[8] = r->top - w->full.top; 1026: rep.param.s[9] = r->left - w->full.left; 1027: #ifdef DUALTCP 1028: if (swapped[ew->client]) { 1029: pswaps(&rep, 4); 1030: pswaps(&rep, 5); 1031: pswaps(&rep, 8); 1032: pswaps(&rep, 9); 1033: } 1034: #endif 1035: Write (ew->client, (caddr_t) &rep, sizeof (XRep)); 1036: } else 1037: not_just_new = 1; 1038: } else 1039: prev = &r->next; 1040: } 1041: if (changed) { 1042: Merge_rectangles (changed, &w->visible); 1043: Windex (w); 1044: } 1045: } 1046: if TRUE(not_just_new) { 1047: rep.param.s[4] = w->full.right - w->full.left; 1048: rep.param.s[5] = w->full.bottom - w->full.top; 1049: rep.param.s[8] = 0; 1050: rep.param.s[9] = 0; 1051: #ifdef DUALTCP 1052: if (swapped[ew->client]) { 1053: rep.code = lswapl(ExposeWindow); 1054: pswaps(&rep, 4); 1055: pswaps(&rep, 5); 1056: } else 1057: #endif 1058: rep.code = ExposeWindow; 1059: Write (ew->client, (caddr_t) &rep, sizeof (XRep)); 1060: } 1061: } 1062: 1063: /* Stash CopyArea misses in the event queue of a window */ 1064: 1065: Stash_misses (w, vis) 1066: register WINDOW *w; 1067: register RECTANGLE *vis; 1068: { 1069: register RECTANGLE *rec; 1070: register WINDOW *ew = w; 1071: XRep rep; 1072: #ifdef DUALTCP 1073: register swaptype n; 1074: #endif 1075: 1076: while (!(ew->mask & ExposeCopy)) { 1077: if ((ew = ew->parent) == NULL) 1078: return; 1079: } 1080: 1081: rep.param.l[0] = ew->rid; 1082: rep.param.l[3] = (w == ew) ? 0 : w->rid; 1083: #ifdef DUALTCP 1084: if (swapped[ew->client]) { 1085: rep.code = lswapl(ExposeRegion); 1086: pswapl(&rep, 0); 1087: rep.param.s[3] = lswaps(ExposeCopy); 1088: pswapl(&rep, 3); 1089: } else { 1090: #endif 1091: rep.code = ExposeRegion; 1092: rep.param.s[3] = ExposeCopy; 1093: #ifdef DUALTCP 1094: } 1095: #endif 1096: while (rec = vis) { 1097: rep.param.s[4] = rec->right - rec->left; 1098: rep.param.s[5] = rec->bottom - rec->top; 1099: rep.param.s[8] = rec->top - w->full.top; 1100: rep.param.s[9] = rec->left - w->full.left; 1101: #ifdef DUALTCP 1102: if (swapped[ew->client]) { 1103: pswaps(&rep, 4); 1104: pswaps(&rep, 5); 1105: pswaps(&rep, 8); 1106: pswaps(&rep, 9); 1107: } 1108: #endif 1109: Write (ew->client, (caddr_t) &rep, sizeof (XRep)); 1110: vis = rec->next; 1111: FREERECT(rec); 1112: } 1113: 1114: #ifdef DUALTCP 1115: if (swapped[ew->client]) 1116: rep.code = lswapl(ExposeCopy); 1117: else 1118: #endif 1119: rep.code = ExposeCopy; 1120: Write (ew->client, (caddr_t) &rep, sizeof (XRep)); 1121: } 1122: 1123: /* Stash unmap or focus event in the event queue of a window */ 1124: 1125: Stash_simple (w, event, detail) 1126: register WINDOW *w; 1127: register long event; 1128: unsigned detail; 1129: { 1130: register WINDOW *ew = w; 1131: XRep rep; 1132: #ifdef DUALTCP 1133: register swaptype n; 1134: #endif 1135: 1136: while (!(ew->mask & event)) { 1137: if ((ew = ew->parent) == NULL) 1138: return; 1139: } 1140: 1141: rep.code = event; 1142: rep.param.l[0] = ew->rid; 1143: rep.param.s[3] = detail; 1144: rep.param.l[3] = (w == ew) ? 0 : w->rid; 1145: #ifdef DUALTCP 1146: if (swapped[ew->client]) { 1147: swapl(&rep.code); 1148: pswapl(&rep, 0); 1149: pswaps(&rep, 3); 1150: pswapl(&rep, 3); 1151: } 1152: #endif 1153: Write (ew->client, (caddr_t) &rep, sizeof (XRep)); 1154: } 1155: 1156: /* Find out coordinates of a point relative to a window. */ 1157: 1158: Interpret_locator (w, x, y, rep) 1159: register WINDOW *w; 1160: short x, y; 1161: register XRep *rep; 1162: { 1163: register WINDOW *sw; 1164: 1165: rep->param.l[0] = 0; 1166: if (x >= w->vs.left && y >= w->vs.top && 1167: x < w->vs.right && y < w->vs.bottom) { 1168: /* see if it is in a subwindow */ 1169: for (sw = w->last_child; sw; sw = sw->prev_sib) { 1170: if (TRUE(sw->mapped) && 1171: x >= sw->full.left && y >= sw->full.top && 1172: x < sw->full.right && y < sw->full.bottom) { 1173: rep->param.l[0] = sw->rid; 1174: break; 1175: } 1176: } 1177: } 1178: rep->param.s[2] = x - w->full.left; 1179: rep->param.s[3] = y - w->full.top; 1180: rep->param.s[4] = state_mask; 1181: }