home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / X / mit / lib / Xt / PassivGrab.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-07-21  |  26.8 KB  |  1,018 lines

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