home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / X / mit / lib / Xt / PassivGrab.c.orig < prev    next >
Encoding:
Text File  |  1993-07-21  |  27.4 KB  |  1,033 lines

  1. /* $XConsortium: PassivGrab.c,v 1.20 92/05/11 17:44:00 converse Exp $ */
  2.  
  3. /********************************************************
  4.  
  5. Copyright (c) 1988 by Hewlett-Packard Company
  6. Copyright (c) 1987, 1988, 1989,1990 by Digital Equipment Corporation, Maynard, 
  7.               Massachusetts, and the Massachusetts Institute of Technology, 
  8.               Cambridge, Massachusetts
  9.  
  10. Permission to use, copy, modify, and distribute this software 
  11. and its documentation for any purpose and without fee is hereby 
  12. granted, provided that the above copyright notice appear in all 
  13. copies and that both that copyright notice and this permission 
  14. notice appear in supporting documentation, and that the names of 
  15. Hewlett-Packard, Digital or  M.I.T.  not be used in advertising or 
  16. publicity pertaining to distribution of the software without specific, 
  17. written prior permission.
  18.  
  19. DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  20. ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
  21. DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
  22. ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  23. WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
  24. ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  25. SOFTWARE.
  26.  
  27. ********************************************************/
  28.  
  29. #include "IntrinsicI.h"
  30. #include "StringDefs.h"
  31. #include "PassivGraI.h"
  32.  
  33. static String XtNinvalidWidget = "invalidWidget";
  34.  
  35. /* typedef unsigned long Mask; */
  36. #define BITMASK(i) (((Mask)1) << ((i) & 31))
  37. #define MASKIDX(i) ((i) >> 5)
  38. #define MASKWORD(buf, i) buf[MASKIDX(i)]
  39. #define BITSET(buf, i) MASKWORD(buf, i) |= BITMASK(i)
  40. #define BITCLEAR(buf, i) MASKWORD(buf, i) &= ~BITMASK(i)
  41. #define GETBIT(buf, i) (MASKWORD(buf, i) & BITMASK(i))
  42. #define MasksPerDetailMask 8
  43.  
  44. #define pDisplay(grabPtr) (((grabPtr)->widget)->core.screen->display)
  45. #define pWindow(grabPtr) (((grabPtr)->widget)->core.window)
  46.  
  47.  
  48. /***************************************************************************/
  49. /*********************** Internal Support Routines *************************/
  50. /***************************************************************************/
  51.  
  52. /*
  53.  * Turn off (clear) the bit in the specified detail mask which is associated
  54.  * with the detail.
  55.  */
  56.  
  57. static void DeleteDetailFromMask(ppDetailMask, detail)
  58.     Mask **ppDetailMask;
  59.     unsigned short detail;
  60. {
  61.     Mask *pDetailMask = *ppDetailMask;
  62.  
  63.     if (!pDetailMask) {
  64.     int i;
  65.     pDetailMask = (Mask *)XtMalloc(sizeof(Mask) * MasksPerDetailMask);
  66.     for (i = MasksPerDetailMask; --i >= 0; )
  67.         pDetailMask[i] = ~0;
  68.     *ppDetailMask = pDetailMask;
  69.     }
  70.     BITCLEAR((pDetailMask), detail);
  71. }
  72.  
  73.  
  74. /*
  75.  * Make an exact copy of the specified detail mask.
  76.  */
  77.  
  78. static Mask *CopyDetailMask(pOriginalDetailMask)
  79.     Mask *pOriginalDetailMask;
  80. {
  81.     Mask *pTempMask;
  82.     int i;
  83.     
  84.     if (!pOriginalDetailMask)
  85.     return NULL;
  86.     
  87.     pTempMask = (Mask *)XtMalloc(sizeof(Mask) * MasksPerDetailMask);
  88.     
  89.     for ( i = 0; i < MasksPerDetailMask; i++)
  90.       pTempMask[i]= pOriginalDetailMask[i];
  91.     
  92.     return pTempMask;
  93. }
  94.  
  95.  
  96. /*
  97.  * Allocate a new grab entry, and fill in all of the fields using the
  98.  * specified parameters.
  99.  */
  100.  
  101. static XtServerGrabPtr CreateGrab(widget, ownerEvents, modifiers,
  102.                   keybut, pointer_mode, keyboard_mode,
  103.                   event_mask, confine_to, cursor, need_ext)
  104.     Widget    widget;
  105.     Boolean    ownerEvents;
  106.     Modifiers    modifiers;
  107.     KeyCode     keybut;
  108.     int        pointer_mode, keyboard_mode;
  109.     Mask    event_mask;
  110.     Window     confine_to;
  111.     Cursor     cursor;
  112.     Boolean    need_ext;
  113. {
  114.     XtServerGrabPtr grab;
  115.     
  116.     if (confine_to || cursor)
  117.     need_ext = True;
  118.     grab = (XtServerGrabPtr)XtMalloc(sizeof(XtServerGrabRec) +
  119.                      (need_ext ? sizeof(XtServerGrabExtRec)
  120.                       : 0));
  121.     grab->next = NULL;
  122.     grab->widget = widget;
  123.     grab->ownerEvents = ownerEvents;
  124.     grab->pointerMode = pointer_mode;
  125.     grab->keyboardMode = keyboard_mode;
  126.     grab->eventMask = event_mask;
  127.     grab->hasExt = need_ext;
  128.     grab->modifiers = modifiers;
  129.     grab->keybut = keybut;
  130.     if (need_ext) {
  131.     XtServerGrabExtPtr ext = GRABEXT(grab);
  132.     ext->pModifiersMask = NULL;
  133.     ext->pKeyButMask = NULL;
  134.     ext->confineTo = confine_to;
  135.     ext->cursor = cursor;
  136.     }
  137.     return grab;
  138. }
  139.  
  140.  
  141. /*
  142.  * Free up the space occupied by a grab entry.
  143.  */
  144.  
  145. static void FreeGrab(pGrab)
  146.     XtServerGrabPtr pGrab;
  147. {
  148.     if (pGrab->hasExt) {
  149.     XtServerGrabExtPtr ext = GRABEXT(pGrab);
  150.     if (ext->pModifiersMask)
  151.         XtFree((char *)ext->pModifiersMask);
  152.     if (ext->pKeyButMask)
  153.         XtFree((char *)ext->pKeyButMask);
  154.     }
  155.     XtFree((char *)pGrab);
  156. }
  157.  
  158. typedef struct _DetailRec {
  159.     unsigned short     exact;
  160.     Mask          *pMask;
  161. } DetailRec, *DetailPtr;
  162.  
  163. /*
  164.  * If the first detail is set to 'exception' and the second detail
  165.  * is contained in the mask of the first, then TRUE is returned.
  166.  */
  167.  
  168. static Bool IsInGrabMask(firstDetail, secondDetail, exception)
  169.     register DetailPtr firstDetail, secondDetail;
  170.     unsigned short exception;
  171. {
  172.     if (firstDetail->exact == exception) {
  173.     if (!firstDetail->pMask)
  174.         return TRUE;
  175.       
  176.     /* (at present) never called with two non-null pMasks */
  177.     if (secondDetail->exact == exception)
  178.         return FALSE;
  179.       
  180.     if (GETBIT(firstDetail->pMask, secondDetail->exact))
  181.         return TRUE;
  182.     }
  183.     
  184.     return FALSE;
  185. }
  186.  
  187.  
  188. /*
  189.  * If neither of the details is set to 'exception', and they match
  190.  * exactly, then TRUE is returned.
  191.  */
  192.  
  193. static Bool IdenticalExactDetails(firstExact, secondExact, exception)
  194.     unsigned short firstExact, secondExact, exception;
  195. {
  196.     if ((firstExact == exception) || (secondExact == exception))
  197.     return FALSE;
  198.     
  199.     if (firstExact == secondExact)
  200.     return TRUE;
  201.     
  202.     return FALSE;
  203. }
  204.  
  205.  
  206. /*
  207.  * If the first detail is set to 'exception', and its mask has the bit
  208.  * enabled which corresponds to the second detail, OR if neither of the
  209.  * details is set to 'exception' and the details match exactly, then
  210.  * TRUE is returned.
  211.  */
  212.  
  213. static Bool DetailSupersedesSecond(firstDetail, secondDetail, exception)
  214.     register DetailPtr firstDetail, secondDetail;
  215.     unsigned short exception;
  216. {
  217.     if (IsInGrabMask(firstDetail, secondDetail, exception))
  218.     return TRUE;
  219.     
  220.     if (IdenticalExactDetails(firstDetail->exact, secondDetail->exact,
  221.                   exception))
  222.     return TRUE;
  223.     
  224.     return FALSE;
  225. }
  226.  
  227.  
  228. /*
  229.  * If the two grab events match exactly, or if the first grab entry
  230.  * 'encompasses' the second grab entry, then TRUE is returned.
  231.  */
  232.  
  233. static Bool GrabSupersedesSecond(pFirstGrab, pSecondGrab)
  234.     register XtServerGrabPtr pFirstGrab, pSecondGrab;
  235. {
  236.     DetailRec first, second;
  237.  
  238.     first.exact = pFirstGrab->modifiers;
  239.     if (pFirstGrab->hasExt)
  240.     first.pMask = GRABEXT(pFirstGrab)->pModifiersMask;
  241.     else
  242.     first.pMask = NULL;
  243.     second.exact = pSecondGrab->modifiers;
  244.     if (pSecondGrab->hasExt)
  245.     second.pMask = GRABEXT(pSecondGrab)->pModifiersMask;
  246.     else
  247.     second.pMask = NULL;
  248.     if (!DetailSupersedesSecond(&first, &second, (unsigned short)AnyModifier))
  249.       return FALSE;
  250.     
  251.     first.exact = pFirstGrab->keybut;
  252.     if (pFirstGrab->hasExt)
  253.     first.pMask = GRABEXT(pFirstGrab)->pKeyButMask;
  254.     else
  255.     first.pMask = NULL;
  256.     second.exact = pSecondGrab->keybut;
  257.     if (pSecondGrab->hasExt)
  258.     second.pMask = GRABEXT(pSecondGrab)->pKeyButMask;
  259.     else
  260.     second.pMask = NULL;
  261.     if (DetailSupersedesSecond(&first, &second, (unsigned short)AnyKey))
  262.       return TRUE;
  263.     
  264.     return FALSE;
  265. }
  266.  
  267.  
  268. /*
  269.  * Two grabs are considered to be matching if either of the following are true:
  270.  *
  271.  * 1) The two grab entries match exactly, or the first grab entry
  272.  *    encompasses the second grab entry.
  273.  * 2) The second grab entry encompasses the first grab entry.
  274.  * 3) The keycodes match exactly, and one entry's modifiers encompasses
  275.  *    the others.
  276.  * 4) The keycode for one entry encompasses the other, and the detail
  277.  *    for the other entry encompasses the first.
  278.  */
  279.  
  280. static Bool GrabMatchesSecond(pFirstGrab, pSecondGrab)
  281.     register XtServerGrabPtr pFirstGrab, pSecondGrab;
  282. {
  283.     DetailRec firstD, firstM, secondD, secondM;
  284.  
  285.     if (pDisplay(pFirstGrab) != pDisplay(pSecondGrab))
  286.     return FALSE;
  287.     
  288.     if (GrabSupersedesSecond(pFirstGrab, pSecondGrab))
  289.     return TRUE;
  290.     
  291.     if (GrabSupersedesSecond(pSecondGrab, pFirstGrab))
  292.     return TRUE;
  293.     
  294.     firstD.exact = pFirstGrab->keybut;
  295.     firstM.exact = pFirstGrab->modifiers;
  296.     if (pFirstGrab->hasExt) {
  297.     firstD.pMask = GRABEXT(pFirstGrab)->pKeyButMask;
  298.     firstM.pMask = GRABEXT(pFirstGrab)->pModifiersMask;
  299.     } else {
  300.     firstD.pMask = NULL;
  301.     firstM.pMask = NULL;
  302.     }
  303.     secondD.exact = pSecondGrab->keybut;
  304.     secondM.exact = pSecondGrab->modifiers;
  305.     if (pSecondGrab->hasExt) {
  306.     secondD.pMask = GRABEXT(pSecondGrab)->pKeyButMask;
  307.     secondM.pMask = GRABEXT(pSecondGrab)->pModifiersMask;
  308.     } else {
  309.     secondD.pMask = NULL;
  310.     secondM.pMask = NULL;
  311.     }
  312.  
  313.     if (DetailSupersedesSecond(&secondD, &firstD, (unsigned short)AnyKey) &&
  314.     DetailSupersedesSecond(&firstM, &secondM, (unsigned short)AnyModifier))
  315.     return TRUE;
  316.     
  317.     if (DetailSupersedesSecond(&firstD, &secondD, (unsigned short)AnyKey) && 
  318.     DetailSupersedesSecond(&secondM, &firstM, (unsigned short)AnyModifier))
  319.     return TRUE;
  320.     
  321.     return FALSE;
  322. }
  323.  
  324.  
  325. /*
  326.  * Delete a grab combination from the passive grab list.  Each entry will
  327.  * be checked to see if it is affected by the grab being deleted.  This
  328.  * may result in multiple entries being modified/deleted.
  329.  */
  330.  
  331. static void DeleteServerGrabFromList(passiveListPtr, pMinuendGrab)
  332.     XtServerGrabPtr     *passiveListPtr;    
  333.     XtServerGrabPtr     pMinuendGrab;
  334. {
  335.     register XtServerGrabPtr *next;
  336.     register XtServerGrabPtr grab;
  337.     register XtServerGrabExtPtr ext;
  338.     
  339.     for (next = passiveListPtr; grab = *next; )
  340.     {
  341.     if (GrabMatchesSecond(grab, pMinuendGrab) && 
  342.         (pDisplay(grab) == pDisplay(pMinuendGrab)))
  343.     {
  344.         if (GrabSupersedesSecond(pMinuendGrab, grab))
  345.         {
  346.         /*
  347.          * The entry being deleted encompasses the list entry,
  348.          * so delete the list entry.
  349.          */
  350.         *next = grab->next;
  351.         FreeGrab(grab);
  352.         continue;
  353.         }
  354.  
  355.         if (!grab->hasExt) {
  356.         grab = (XtServerGrabPtr)
  357.             XtRealloc((char *)grab, (sizeof(XtServerGrabRec) +
  358.                          sizeof(XtServerGrabExtRec)));
  359.         *next = grab;
  360.         grab->hasExt = True;
  361.         ext = GRABEXT(grab);
  362.         ext->pKeyButMask = NULL;
  363.         ext->pModifiersMask = NULL;
  364.         ext->confineTo = None;
  365.         ext->cursor = None;
  366.         } else
  367.         ext = GRABEXT(grab);
  368.         if ((grab->keybut == AnyKey) && (grab->modifiers != AnyModifier))
  369.         {
  370.         /*
  371.          * If the list entry has the key detail of AnyKey, and
  372.          * a modifier detail not set to AnyModifier, then we
  373.          * simply need to turn off the key detail bit in the
  374.          * list entry's key detail mask.
  375.          */
  376.         DeleteDetailFromMask(&ext->pKeyButMask, pMinuendGrab->keybut);
  377.         } else if ((grab->modifiers == AnyModifier) &&
  378.                (grab->keybut != AnyKey)) {
  379.         /*
  380.          * The list entry has a specific key detail, but its
  381.          * modifier detail is set to AnyModifier; so, we only
  382.          * need to turn off the specified modifier combination
  383.          * in the list entry's modifier mask.
  384.          */
  385.         DeleteDetailFromMask(&ext->pModifiersMask,
  386.                      pMinuendGrab->modifiers);
  387.         } else if ((pMinuendGrab->keybut != AnyKey) &&
  388.                (pMinuendGrab->modifiers != AnyModifier)) {
  389.         /*
  390.          * The list entry has a key detail of AnyKey and a
  391.          * modifier detail of AnyModifier; the entry being
  392.          * deleted has a specific key and a specific modifier
  393.          * combination.  Therefore, we need to mask off the
  394.          * keycode from the list entry, and also create a
  395.          * new entry for this keycode, which has a modifier
  396.          * mask set to AnyModifier & ~(deleted modifiers).
  397.          */
  398.         XtServerGrabPtr pNewGrab;
  399.                   
  400.         DeleteDetailFromMask(&ext->pKeyButMask, pMinuendGrab->keybut);
  401.         pNewGrab = CreateGrab(grab->widget,
  402.                       (Boolean)grab->ownerEvents,
  403.                       (Modifiers)AnyModifier,
  404.                       pMinuendGrab->keybut,
  405.                       (int)grab->pointerMode,
  406.                       (int)grab->keyboardMode,
  407.                       (Mask)0, (Window)0, (Cursor)0, True);
  408.         GRABEXT(pNewGrab)->pModifiersMask =
  409.             CopyDetailMask(ext->pModifiersMask);
  410.                   
  411.         DeleteDetailFromMask(&GRABEXT(pNewGrab)->pModifiersMask,
  412.                      pMinuendGrab->modifiers);
  413.                   
  414.         pNewGrab->next = *passiveListPtr;
  415.         *passiveListPtr = pNewGrab;
  416.         } else if (pMinuendGrab->keybut == AnyKey) {
  417.         /*
  418.          * The list entry has keycode AnyKey and modifier
  419.          * AnyModifier; the entry being deleted has
  420.          * keycode AnyKey and specific modifiers.  So we
  421.          * simply need to mask off the specified modifier
  422.          * combination.
  423.          */
  424.         DeleteDetailFromMask(&ext->pModifiersMask,
  425.                      pMinuendGrab->modifiers);
  426.         } else {
  427.         /*
  428.          * The list entry has keycode AnyKey and modifier
  429.          * AnyModifier; the entry being deleted has a
  430.          * specific keycode and modifier AnyModifier.  So 
  431.          * we simply need to mask off the specified 
  432.          * keycode.
  433.          */
  434.         DeleteDetailFromMask(&ext->pKeyButMask, pMinuendGrab->keybut);
  435.         }
  436.     }
  437.     next = &(*next)->next;
  438.     }
  439. }
  440.  
  441. static void DestroyPassiveList(passiveListPtr)
  442.     XtServerGrabPtr    *passiveListPtr;
  443. {
  444.     XtServerGrabPtr    next, grab;
  445.  
  446.     for (next = *passiveListPtr; next; ) {
  447.     grab = next;
  448.     next = grab->next;
  449.       
  450.     /* not necessary to explicitly ungrab key or button;
  451.      * window is being destroyed so server will take care of it.
  452.      */ 
  453.  
  454.     FreeGrab(grab);
  455.     }
  456. }
  457.  
  458.  
  459. /*
  460.  * This function is called at widget destroy time to clean up
  461.  */
  462. /*ARGSUSED*/
  463. void _XtDestroyServerGrabs(w, closure, call_data)
  464.     Widget        w;
  465.     XtPointer        closure;
  466.     XtPointer        call_data; /* unused */
  467. {
  468.     XtPerWidgetInput    pwi = (XtPerWidgetInput)closure;
  469.     XtPerDisplayInput    pdi;
  470.     
  471.     pdi = _XtGetPerDisplayInput(XtDisplay(w));
  472.     
  473.     /* Remove the active grab, if necessary */
  474.     if ((pdi->keyboard.grabType != XtNoServerGrab) && 
  475.     (pdi->keyboard.grab.widget == w))
  476.     XtUngrabKeyboard(w, CurrentTime);
  477.     if ((pdi->pointer.grabType != XtNoServerGrab) && 
  478.     (pdi->pointer.grab.widget == w))
  479.     XtUngrabPointer(w, CurrentTime);
  480.     
  481.     DestroyPassiveList(&pwi->keyList);
  482.     DestroyPassiveList(&pwi->ptrList);
  483.  
  484.     _XtFreePerWidgetInput(w, pwi);
  485. }
  486.  
  487. /*
  488.  * If the incoming event is on the passive grab list, then activate
  489.  * the grab.  The grab will remain in effect until the key is released.
  490.  */
  491.  
  492. #if NeedFunctionPrototypes
  493. XtServerGrabPtr _XtCheckServerGrabsOnWidget (
  494.     XEvent         *event,
  495.     Widget        widget,
  496.     _XtBoolean        isKeyboard
  497.     )
  498. #else
  499. XtServerGrabPtr _XtCheckServerGrabsOnWidget (event, widget, isKeyboard)
  500.     XEvent         *event;
  501.     Widget        widget;
  502.     Boolean        isKeyboard;
  503. #endif
  504. {
  505.     register XtServerGrabPtr grab;
  506.     XtServerGrabRec     tempGrab;
  507.     XtServerGrabPtr    *passiveListPtr;
  508.     XtPerWidgetInput    pwi;
  509.  
  510.     if (!(pwi = _XtGetPerWidgetInput(widget, FALSE)))
  511.     return (XtServerGrabPtr)NULL;
  512.  
  513.     if (isKeyboard)
  514.     passiveListPtr = &pwi->keyList;
  515.     else
  516.     passiveListPtr = &pwi->ptrList;
  517.  
  518.     /*
  519.      * if either there is no entry in the context manager or the entry
  520.      * is empty, or the keyboard is grabed, then no work to be done
  521.      */
  522.     if (!*passiveListPtr)
  523.     return (XtServerGrabPtr)NULL;
  524.     
  525.     tempGrab.widget = widget;
  526.     tempGrab.keybut = event->xkey.keycode; /* also xbutton.button */
  527.     tempGrab.modifiers = event->xkey.state; /*also xbutton.state*/
  528.     tempGrab.hasExt = False;
  529.  
  530.     for (grab = *passiveListPtr; grab; grab = grab->next) {
  531.     if (GrabMatchesSecond(&tempGrab, grab))
  532.         return (grab);
  533.     }
  534.     return (XtServerGrabPtr)NULL;
  535. }
  536.  
  537. /*
  538.  * This handler is needed to guarantee that we see releases on passive
  539.  * button grabs for widgets that haven't selected for button release.
  540.  */
  541.  
  542. /*ARGSUSED*/
  543. static void  ActiveHandler (widget, pdi, event, cont)
  544.     Widget         widget;
  545.     XtPointer        pdi;
  546.     XEvent         *event;
  547.     Boolean        *cont;
  548. {
  549.     /* nothing */
  550. }
  551.  
  552.  
  553. /*
  554.  *    MakeGrab
  555.  */
  556. static void  MakeGrab(grab, passiveListPtr, isKeyboard, pdi, pwi)
  557.     XtServerGrabPtr    grab;
  558.     XtServerGrabPtr    *passiveListPtr;
  559.     Boolean        isKeyboard;
  560.     XtPerDisplayInput    pdi;
  561.     XtPerWidgetInput    pwi;
  562. {
  563.     if (!isKeyboard && !pwi->active_handler_added) {
  564.     XtAddEventHandler(grab->widget, ButtonReleaseMask, FALSE,
  565.               ActiveHandler, (XtPointer)pdi);
  566.     pwi->active_handler_added = TRUE;
  567.     }
  568.     
  569.     if (isKeyboard) {
  570.     XGrabKey(pDisplay(grab),
  571.          grab->keybut, grab->modifiers,
  572.          pWindow(grab), grab->ownerEvents,
  573.          grab->pointerMode, grab->keyboardMode);
  574.     } else {
  575.     Window confineTo = None;
  576.     Cursor cursor = None;
  577.  
  578.     if (grab->hasExt) {
  579.         confineTo = GRABEXT(grab)->confineTo;
  580.         cursor = GRABEXT(grab)->cursor;
  581.     }
  582.     XGrabButton(pDisplay(grab),
  583.             grab->keybut, grab->modifiers,
  584.             pWindow(grab), grab->ownerEvents, grab->eventMask,
  585.             grab->pointerMode, grab->keyboardMode,
  586.             confineTo, cursor);
  587.     }
  588.  
  589.     /* Add the new grab entry to the passive key grab list */
  590.     grab->next = *passiveListPtr;
  591.     *passiveListPtr = grab;
  592. }
  593.  
  594. static void MakeGrabs(passiveListPtr, isKeyboard, pdi)
  595.     XtServerGrabPtr    *passiveListPtr;
  596.     Boolean        isKeyboard;
  597.     XtPerDisplayInput    pdi;
  598. {
  599.     XtServerGrabPtr    next = *passiveListPtr;
  600.     XtServerGrabPtr    grab;
  601.     XtPerWidgetInput    pwi;
  602.     /*
  603.      * make MakeGrab build a new list that has had the merge
  604.      * processing done on it. Start with an empty list
  605.      * (passiveListPtr).
  606.      */
  607.     *passiveListPtr = NULL;
  608.     while (next)
  609.       {
  610.       grab = next;
  611.       next = grab->next;
  612.       pwi = _XtGetPerWidgetInput(grab->widget, FALSE);
  613.       MakeGrab(grab, passiveListPtr, isKeyboard, pdi, pwi);
  614.       }
  615.    
  616. /*
  617.  * This function is the event handler attached to the associated widget
  618.  * when grabs need to be added, but the widget is not yet realized.  When
  619.  * it is first mapped, this handler will be invoked, and it will add all
  620.  * needed grabs.
  621.  */
  622.  
  623. /*ARGSUSED*/
  624. static void  RealizeHandler (widget, closure, event, cont)
  625.     Widget         widget;
  626.     XtPointer        closure;
  627.     XEvent         *event;    /* unused */
  628.     Boolean        *cont;    /* unused */
  629. {
  630.     XtPerWidgetInput    pwi = (XtPerWidgetInput)closure;
  631.     XtPerDisplayInput    pdi = _XtGetPerDisplayInput(XtDisplay(widget));
  632.     
  633.     MakeGrabs(&pwi->keyList, KEYBOARD, pdi);
  634.     MakeGrabs(&pwi->ptrList, POINTER, pdi);
  635.  
  636.     XtRemoveEventHandler(widget, XtAllEvents, True,
  637.              RealizeHandler, (XtPointer)pwi);
  638.     pwi->realize_handler_added = FALSE;
  639. }
  640.  
  641. /***************************************************************************/
  642. /**************************** Global Routines ******************************/
  643. /***************************************************************************/
  644.  
  645.  
  646. /*
  647.  * Routine used by an application to set up a passive grab for a key/modifier
  648.  * combination.
  649.  */
  650.  
  651. static
  652. void GrabKeyOrButton (widget, keyOrButton, modifiers, owner_events,
  653.                pointer_mode, keyboard_mode, event_mask,
  654.                confine_to, cursor, isKeyboard)
  655.     Widget    widget;
  656.     KeyCode    keyOrButton;
  657.     Modifiers    modifiers;
  658.     Boolean    owner_events;
  659.     int     pointer_mode;
  660.     int     keyboard_mode;
  661.     Mask    event_mask;
  662.     Window     confine_to;
  663.     Cursor     cursor;
  664.     Boolean    isKeyboard;
  665. {
  666.     XtServerGrabPtr    *passiveListPtr;
  667.     XtServerGrabPtr     newGrab;
  668.     XtPerWidgetInput    pwi;
  669.     XtPerDisplayInput    pdi;
  670.     
  671.     
  672.     if (!XtIsWidget(widget)){
  673.     XtAppWarningMsg(XtWidgetToApplicationContext(widget),
  674.              XtNinvalidWidget, "grabKeyOrButton", XtCXtToolkitError,
  675.              "Widget specified in grab is not a widget",
  676.              (String *)NULL, (Cardinal *)NULL);
  677.     return;
  678.     }
  679.     
  680.     pwi = _XtGetPerWidgetInput(widget, TRUE);
  681.     if (isKeyboard)
  682.       passiveListPtr = &pwi->keyList;
  683.     else
  684.       passiveListPtr = &pwi->ptrList;
  685.     pdi = _XtGetPerDisplayInput(XtDisplay(widget));
  686.     
  687.     newGrab = CreateGrab(widget, owner_events, modifiers, 
  688.              keyOrButton, pointer_mode, keyboard_mode, 
  689.              event_mask, confine_to, cursor, False);
  690.     /*
  691.      *  if the widget is realized then process the entry into the grab
  692.      * list. else if the list is empty (i.e. first time) then add the
  693.      * event handler. then add the raw entry to the list for processing
  694.      * in the handler at realize time.
  695.      */
  696.     if (XtIsRealized(widget))
  697.       MakeGrab(newGrab, passiveListPtr, isKeyboard, pdi, pwi);
  698.     else {
  699.     if (!pwi->realize_handler_added)
  700.         {
  701.         XtAddEventHandler(widget, StructureNotifyMask, FALSE,
  702.                   RealizeHandler,
  703.                   (XtPointer)pwi);
  704.         pwi->realize_handler_added = TRUE;
  705.         }
  706.     
  707.     while (*passiveListPtr)
  708.         passiveListPtr = &(*passiveListPtr)->next;
  709.     *passiveListPtr = newGrab;
  710.     }
  711. }
  712.  
  713.  
  714. static
  715. void   UngrabKeyOrButton (widget, keyOrButton, modifiers, isKeyboard)
  716.     Widget    widget;
  717.     int        keyOrButton;
  718.     Modifiers    modifiers;
  719.     Boolean    isKeyboard;
  720. {
  721.     XtServerGrabRec     tempGrab;
  722.     XtPerWidgetInput    pwi;
  723.     
  724.     if (!XtIsWidget(widget)){
  725.     XtAppWarningMsg(XtWidgetToApplicationContext(widget),
  726.              XtNinvalidWidget, "ungrabKeyOrButton", XtCXtToolkitError,
  727.              "Widget specified in ungrab is not a widget",
  728.              (String *)NULL, (Cardinal *)NULL);
  729.     return;
  730.     }
  731.     
  732.     /* Build a temporary grab list entry */
  733.     tempGrab.widget = widget;
  734.     tempGrab.modifiers = modifiers;
  735.     tempGrab.keybut = keyOrButton;
  736.     tempGrab.hasExt = False;
  737.     
  738.     
  739.     pwi = _XtGetPerWidgetInput(widget, FALSE);
  740.     
  741.     /*
  742.      * if there is no entry in the context manager then somethings wrong
  743.      */
  744.     if (!pwi)
  745.       {
  746.       XtAppWarningMsg(XtWidgetToApplicationContext(widget),
  747.                "invalidGrab", "ungrabKeyOrButton", XtCXtToolkitError,
  748.                "Attempt to remove nonexistent passive grab",
  749.                (String *)NULL, (Cardinal *)NULL);
  750.       return;
  751.       }
  752.  
  753.     if (XtIsRealized(widget))
  754.       {
  755.       if (isKeyboard)
  756.         XUngrabKey(widget->core.screen->display,
  757.                keyOrButton, (unsigned int)modifiers,
  758.                widget->core.window);
  759.       else
  760.         XUngrabButton(widget->core.screen->display,
  761.               keyOrButton, (unsigned int)modifiers, 
  762.               widget->core.window);
  763.       }
  764.  
  765.    
  766.     /* Delete all entries which are encompassed by the specified grab. */
  767.     DeleteServerGrabFromList(isKeyboard ? &pwi->keyList : &pwi->ptrList,
  768.                  &tempGrab);
  769. }
  770.  
  771. #if NeedFunctionPrototypes
  772. void  XtGrabKey (
  773.     Widget    widget,
  774.     _XtKeyCode    keycode,
  775.     Modifiers    modifiers,
  776.     _XtBoolean    owner_events,
  777.     int     pointer_mode,
  778.     int     keyboard_mode
  779.     )
  780. #else
  781. void  XtGrabKey (widget, keycode, modifiers, owner_events,
  782.          pointer_mode, keyboard_mode)
  783.     Widget    widget;
  784.     KeyCode    keycode;
  785.     Modifiers    modifiers;
  786.     Boolean    owner_events;
  787.     int     pointer_mode;
  788.     int     keyboard_mode;
  789. #endif
  790. {
  791.     GrabKeyOrButton(widget, (KeyCode)keycode, modifiers, owner_events,
  792.             pointer_mode, keyboard_mode, 
  793.             (Mask)0, (Window)None, (Cursor)None, KEYBOARD);
  794. }
  795.  
  796. #if NeedFunctionPrototypes
  797. void  XtGrabButton(
  798.     Widget    widget,
  799.     int        button,
  800.     Modifiers    modifiers,
  801.     _XtBoolean    owner_events,
  802.     unsigned int event_mask,
  803.     int     pointer_mode,
  804.     int     keyboard_mode,
  805.     Window     confine_to,
  806.     Cursor     cursor
  807.     )
  808. #else
  809. void  XtGrabButton(widget, button, modifiers, owner_events,
  810.            event_mask, pointer_mode, keyboard_mode,
  811.            confine_to, cursor)
  812.     Widget    widget;
  813.     int        button;
  814.     Modifiers    modifiers;
  815.     Boolean    owner_events;
  816.     unsigned int event_mask;
  817.     int     pointer_mode;
  818.     int     keyboard_mode;
  819.     Window     confine_to;
  820.     Cursor     cursor;
  821. #endif
  822. {
  823.     GrabKeyOrButton(widget, (KeyCode)button, modifiers, owner_events,
  824.             pointer_mode, keyboard_mode, 
  825.             (Mask)event_mask, confine_to, cursor, POINTER);
  826. }
  827.  
  828.  
  829. /*
  830.  * Routine used by an application to clear a passive grab for a key/modifier
  831.  * combination.
  832.  */
  833.  
  834. #if NeedFunctionPrototypes
  835. void   XtUngrabKey (
  836.     Widget    widget,
  837.     _XtKeyCode    keycode,
  838.     Modifiers    modifiers
  839.     )
  840. #else
  841. void   XtUngrabKey (widget, keycode, modifiers)
  842.     Widget    widget;
  843.     KeyCode    keycode;
  844.     Modifiers    modifiers;
  845. #endif
  846. {
  847.  
  848.     UngrabKeyOrButton(widget, (int)keycode, modifiers, KEYBOARD);
  849. }
  850.  
  851. void   XtUngrabButton (widget, button, modifiers)
  852.     Widget    widget;
  853.     unsigned int button;
  854.     Modifiers    modifiers;
  855. {
  856.  
  857.     UngrabKeyOrButton(widget, (KeyCode)button, modifiers, POINTER);
  858. }
  859.  
  860. /*
  861.  * Active grab of Device. clear any client side grabs so we dont lock
  862.  */
  863. static int GrabDevice (widget, owner_events,
  864.                pointer_mode, keyboard_mode, 
  865.                event_mask, confine_to, cursor, time, isKeyboard)
  866.     Widget    widget;
  867.     Boolean    owner_events;
  868.     int     pointer_mode;
  869.     int     keyboard_mode;
  870.     Mask    event_mask;
  871.     Window     confine_to;
  872.     Cursor     cursor;
  873.     Time    time;
  874.     Boolean    isKeyboard;
  875. {
  876.     XtPerDisplayInput    pdi;
  877.     int            returnVal;
  878.     
  879.     if (!XtIsWidget(widget) || !XtIsRealized(widget))
  880.       XtAppErrorMsg(XtWidgetToApplicationContext(widget),
  881.             XtNinvalidWidget, "grabDevice", XtCXtToolkitError,
  882.             "Grab widget must be a realized widget",
  883.             (String*)NULL, (Cardinal*)NULL);
  884.     
  885.     pdi = _XtGetPerDisplayInput(XtDisplay(widget));
  886.     
  887.     if (!isKeyboard)
  888.       returnVal = XGrabPointer(XtDisplay(widget), XtWindow(widget), 
  889.                    owner_events, event_mask,
  890.                    pointer_mode, keyboard_mode,
  891.                    confine_to, cursor, time);
  892.     else
  893.       returnVal = XGrabKeyboard(XtDisplay(widget), XtWindow(widget), 
  894.                 owner_events, pointer_mode, 
  895.                 keyboard_mode, time);
  896.  
  897.     if (returnVal == GrabSuccess) {
  898.       XtDevice        device;
  899.       
  900.       device = isKeyboard ? &pdi->keyboard : &pdi->pointer;
  901.       /* fill in the server grab rec */
  902.       device->grab.widget = widget;
  903.       device->grab.modifiers = 0;
  904.       device->grab.keybut = 0;
  905.       device->grab.ownerEvents = owner_events;
  906.       device->grab.pointerMode = pointer_mode;
  907.       device->grab.keyboardMode = keyboard_mode;
  908.       device->grab.hasExt = False;
  909.       device->grabType = XtActiveServerGrab;
  910.       pdi->activatingKey = (KeyCode)0;
  911.       }
  912.     return returnVal;
  913. }
  914.  
  915. static void   UngrabDevice(widget, time, isKeyboard)
  916.     Widget    widget;
  917.     Time    time;
  918.     Boolean    isKeyboard;
  919. {
  920.     XtPerDisplayInput    pdi = _XtGetPerDisplayInput(XtDisplay(widget));
  921.     XtDevice        device = isKeyboard ? &pdi->keyboard : &pdi->pointer;
  922.  
  923.     if (!XtIsWidget(widget) || !XtIsRealized(widget))
  924.       XtAppErrorMsg(XtWidgetToApplicationContext(widget),
  925.             XtNinvalidWidget, "ungrabDevice", XtCXtToolkitError,
  926.             "Grab widget must be a realized widget",
  927.             (String*)NULL, (Cardinal*)NULL);
  928.      
  929.     if (device->grabType != XtNoServerGrab)
  930.       {
  931.       if (device->grabType != XtPseudoPassiveServerGrab)
  932.         {
  933.         if (isKeyboard)
  934.           XUngrabKeyboard(XtDisplay(widget), time);
  935.         else
  936.           XUngrabPointer(XtDisplay(widget), time);
  937.         }
  938.       device->grabType = XtNoServerGrab;
  939.       pdi->activatingKey = (KeyCode)0;
  940.       }
  941. }
  942.  
  943.  
  944. /*
  945.  * Active grab of keyboard. clear any client side grabs so we dont lock
  946.  */
  947. #if NeedFunctionPrototypes
  948. int XtGrabKeyboard (
  949.     Widget    widget,
  950.     _XtBoolean    owner_events,
  951.     int     pointer_mode,
  952.     int     keyboard_mode,
  953.     Time    time
  954.     )
  955. #else
  956. int XtGrabKeyboard (widget, owner_events,
  957.             pointer_mode, keyboard_mode, time)
  958.     Widget    widget;
  959.     Boolean    owner_events;
  960.     int     pointer_mode;
  961.     int     keyboard_mode;
  962.     Time    time;
  963. #endif
  964. {
  965.     return (GrabDevice (widget, owner_events,
  966.             pointer_mode, keyboard_mode, 
  967.             (Mask)0, (Window)None, (Cursor)None, time, KEYBOARD));
  968. }
  969.  
  970.  
  971. /*
  972.  * Ungrab the keyboard
  973.  */
  974.  
  975. void   XtUngrabKeyboard(widget, time)
  976.     Widget    widget;
  977.     Time    time;
  978. {
  979.     UngrabDevice(widget, time, KEYBOARD);
  980. }
  981.  
  982.  
  983.  
  984.  
  985. /*
  986.  * grab the pointer
  987.  */
  988. #if NeedFunctionPrototypes
  989. int XtGrabPointer (
  990.     Widget    widget,
  991.     _XtBoolean    owner_events,
  992.     unsigned int event_mask,
  993.     int     pointer_mode,
  994.     int     keyboard_mode,
  995.     Window     confine_to,
  996.     Cursor     cursor,
  997.     Time    time
  998.     )
  999. #else
  1000. int XtGrabPointer (widget, owner_events, event_mask,
  1001.            pointer_mode, keyboard_mode, 
  1002.            confine_to, cursor, time)
  1003.     Widget    widget;
  1004.     Boolean    owner_events;
  1005.     unsigned int event_mask;
  1006.     int     pointer_mode;
  1007.     int     keyboard_mode;
  1008.     Window     confine_to;
  1009.     Cursor     cursor;
  1010.     Time    time;
  1011. #endif
  1012. {
  1013.     return (GrabDevice (widget, owner_events,
  1014.             pointer_mode, keyboard_mode, 
  1015.             (Mask)event_mask, confine_to, 
  1016.             cursor, time, POINTER));
  1017. }
  1018.  
  1019.  
  1020. /*
  1021.  * Ungrab the pointer
  1022.  */
  1023.  
  1024. void   XtUngrabPointer(widget, time)
  1025.     Widget    widget;
  1026.     Time    time;
  1027. {
  1028.     UngrabDevice(widget, time, POINTER);
  1029. }
  1030.  
  1031.  
  1032.