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: }

Defined functions

Button_grab defined in line 646; used 2 times
Check_cursor defined in line 138; used 2 times
Deal_with_input defined in line 422; used 4 times
Deal_with_movement defined in line 202; used 23 times
Grab_button defined in line 572; used 1 times
Grab_mouse defined in line 520; used 1 times
Interpret_locator defined in line 1158; used 2 times
New_cursor defined in line 155; used 6 times
Register_cursor defined in line 86; used 3 times
Select_input defined in line 312; used 1 times
Set_mbox defined in line 350; used 4 times
Set_shiftlock defined in line 333; used 2 times
Startup_mouse defined in line 119; used 1 times
Stash_changes defined in line 967; used 2 times
Stash_enters defined in line 835; used 3 times
Stash_event defined in line 848; used 16 times
Stash_grabs defined in line 770; used 3 times
Stash_misses defined in line 1065; used 3 times
Stash_simple defined in line 1125; used 5 times
Stash_ungrabs defined in line 794; used 5 times
Unbutton_window defined in line 732; used 1 times
Ungrab_button defined in line 618; used 1 times
Ungrab_client defined in line 750; used 1 times
Ungrab_mouse defined in line 559; used 1 times
Unregister_cursor defined in line 103; used 2 times
Warp_mouse defined in line 670; used 1 times

Defined variables

bgrabs defined in line 54; used 12 times
button_window defined in line 42; used 19 times
cursor defined in line 38; used 48 times
cursor_window defined in line 39; used 7 times
key_window defined in line 47; used 8 times
lock_mask defined in line 51; used 5 times
lock_mode defined in line 50; used 5 times
motion_mask defined in line 52; used 8 times
mouse_grab_button defined in line 46; used 8 times
mouse_grab_mask defined in line 45; used 5 times
mouse_grab_window defined in line 44; used 6 times
mouse_grabber defined in line 43; used 23 times
mouse_window defined in line 40; used 16 times
mouse_x defined in line 37; used 14 times
rcsid_input_c defined in line 16; never used
state_mask defined in line 49; used 21 times

Defined struct's

grab_info defined in line 30; never used

Defined typedef's

GRAB_INFO defined in line 35; used 6 times

Defined macros

ControlKeyCode defined in line 59; never used
GRABIDX defined in line 55; used 4 times
GRABS defined in line 53; used 2 times
LockKeyCode defined in line 60; never used
MetaKeyCode defined in line 61; never used
SEARCH defined in line 69; used 3 times
ShiftKeyCode defined in line 58; never used
grabbits defined in line 56; used 2 times
Last modified: 1986-02-01
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 3106
Valid CSS Valid XHTML 1.0 Strict