home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / tk42r2s.zip / tk4.2 / os2 / tkOS2Pointer.c < prev    next >
C/C++ Source or Header  |  1999-07-27  |  22KB  |  858 lines

  1. /* 
  2.  * tkOS2Pointer.c --
  3.  *
  4.  *    OS/2 PM specific mouse tracking code.
  5.  *
  6.  * Copyright (c) 1996-1998 Illya Vaes
  7.  * Copyright (c) 1995 Sun Microsystems, Inc.
  8.  *
  9.  * See the file "license.terms" for information on usage and redistribution
  10.  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
  11.  */
  12.  
  13.  
  14. #include "tkOS2Int.h"
  15.  
  16. /*
  17.  * Check for enter/leave events every MOUSE_TIMER_INTERVAL milliseconds.
  18.  */
  19.  
  20. #define MOUSE_TIMER_INTERVAL 250
  21.  
  22. /*
  23.  * Mask that selects any of the state bits corresponding to buttons,
  24.  * plus masks that select individual buttons' bits:
  25.  */
  26.  
  27. #define ALL_BUTTONS \
  28.     (Button1Mask|Button2Mask|Button3Mask|Button4Mask|Button5Mask)
  29. static unsigned int buttonStates[] = {
  30.     Button1Mask, Button2Mask, Button3Mask, Button4Mask, Button5Mask
  31. };
  32.  
  33. /*
  34.  * Declarations of static variables used in the grab module.
  35.  */
  36.  
  37. static int captured;        /* 1 if mouse events outside of Tk windows
  38.                  * will be reported, else 0. */
  39. static TkWindow *grabWinPtr;    /* Window that defines the top of the grab
  40.                  * tree in a global grab. */
  41. static TkWindow *keyboardWinPtr;/* Current keyboard grab window. */
  42. static TkWindow *restrictWinPtr;
  43.                 /* Window to which all mouse
  44.                    events will be reported. */
  45.  
  46. /*
  47.  * Declarations of static variables used in mouse position tracking.
  48.  */
  49.  
  50. static POINTL lastMousePos;    /* Last known mouse position. */
  51. static HWND lastMouseWindow;    /* Last known mouse window. */
  52. static TkWindow *lastMouseWinPtr;
  53.                 /* Last window mouse was seen in.  Used to
  54.                  * detect Enter/Leave events. */
  55. static Tcl_TimerToken mouseTimer;
  56.                 /* Handle to the latest mouse timer. */
  57. static int mouseTimerSet;    /* Non-zero if the mouse timer is active. */
  58.  
  59. /*
  60.  * Forward declarations of procedures used in this file.
  61.  */
  62.  
  63. static void        InitializeCrossingEvent (
  64.                     XEvent *eventPtr, TkWindow *winPtr,
  65.                 long x, long y);
  66. static void        MouseTimerProc (ClientData clientData);
  67. static int        UpdateMousePosition (HWND hwnd,
  68.                 TkWindow *winPtr, long x, long y);
  69.  
  70. /*
  71.  *----------------------------------------------------------------------
  72.  *
  73.  * TkOS2PointerInit --
  74.  *
  75.  *    Initialize the mouse pointer module.
  76.  *
  77.  * Results:
  78.  *    None.
  79.  *
  80.  * Side effects:
  81.  *    Initializes various static variables.
  82.  *
  83.  *----------------------------------------------------------------------
  84.  */
  85.  
  86. void
  87. TkOS2PointerInit()
  88. {
  89.     captured = 0;
  90.     grabWinPtr = NULL;
  91.     keyboardWinPtr = NULL;
  92.     restrictWinPtr = NULL;
  93.  
  94.     mouseTimerSet = 0;
  95.     rc = WinQueryPointerPos(HWND_DESKTOP, &lastMousePos);
  96.     lastMouseWindow = WinWindowFromPoint(HWND_DESKTOP, &lastMousePos, TRUE);
  97.     lastMouseWinPtr = NULL;
  98. }
  99.  
  100. /*
  101.  *----------------------------------------------------------------------
  102.  *
  103.  * TkOS2PointerDeadWindow --
  104.  *
  105.  *    Clean up pointer module state when a window is destroyed.
  106.  *
  107.  * Results:
  108.  *    None.
  109.  *
  110.  * Side effects:
  111.  *    May change the grab module settings.
  112.  *
  113.  *----------------------------------------------------------------------
  114.  */
  115.  
  116. void
  117. TkOS2PointerDeadWindow(winPtr)
  118.     TkWindow *winPtr;
  119. {
  120.     if (winPtr == lastMouseWinPtr) {
  121.     lastMouseWinPtr = NULL;
  122.     }
  123.     if (winPtr == grabWinPtr) {
  124.     grabWinPtr = NULL;
  125.     }
  126.     if (winPtr == restrictWinPtr) {
  127.     restrictWinPtr = NULL;
  128.     }
  129.     if (!(restrictWinPtr || grabWinPtr)) {
  130.         BOOL rc;
  131.     captured = 0;
  132.     /* Release capture */
  133.     rc = WinSetCapture(HWND_DESKTOP, NULLHANDLE);
  134.     }
  135. }
  136.  
  137. /*
  138.  *----------------------------------------------------------------------
  139.  *
  140.  * TkOS2PointerEvent --
  141.  *
  142.  *    This procedure is called for each pointer-related event,
  143.  *    before the event is queued.  It simulates X style automatic
  144.  *    grabs so that button release events are not lost.  It also
  145.  *    updates the pointer position so enter/leave events will be
  146.  *    correctly generated.
  147.  *
  148.  * Results:
  149.  *    Returns 0 if the event should be discarded.
  150.  *
  151.  * Side effects:
  152.  *    Changes the current mouse capture window. 
  153.  *
  154.  *----------------------------------------------------------------------
  155.  */
  156.  
  157. void
  158. TkOS2PointerEvent(eventPtr, winPtr)
  159.     XEvent *eventPtr;        /* Event to process */
  160.     TkWindow *winPtr;        /* Window to which event was reported. */
  161. {
  162.     POINTL pos;
  163.     HWND hwnd;
  164.     TkOS2Drawable *todPtr;
  165.  
  166.     /*
  167.      * If the mouse is captured, OS/2 PM will report all pointer
  168.      * events to the capture window.  So, we need to determine which
  169.      * window the mouse is really over and change the event.  Note
  170.      * that the computed hwnd may point to a window not owned by Tk,
  171.      * or a toplevel decorative frame, so winPtr can be NULL.
  172.      */
  173.  
  174.     if (captured) {
  175.     pos.x = eventPtr->xmotion.x_root;
  176.         /* Translate Y coordinate to PM */
  177.     pos.y = yScreen - eventPtr->xmotion.y_root;
  178.         hwnd = WinWindowFromPoint(HWND_DESKTOP, &pos, TRUE);
  179.     todPtr = TkOS2GetDrawableFromHandle(hwnd);
  180.     if (todPtr && (todPtr->type == TOD_WINDOW)) {
  181.         winPtr = TkOS2GetWinPtr(todPtr);
  182.     } else {
  183.         winPtr = NULL;
  184.     }
  185.     } else {
  186.     hwnd = TkOS2GetHWND(Tk_WindowId(winPtr));
  187.     }
  188.  
  189.     switch (eventPtr->type) {
  190.     case MotionNotify: 
  191.  
  192.         /*
  193.          * If updating the mouse position caused an enter or leave
  194.          * event to be generated, we discard the motion event.
  195.          */
  196.  
  197.         if (UpdateMousePosition(hwnd, winPtr, eventPtr->xmotion.x_root,
  198.             eventPtr->xmotion.y_root)) {
  199.         return;
  200.         }
  201.         break;
  202.  
  203.     case ButtonPress:
  204.  
  205.         /*
  206.          * Set mouse capture and the restrict window if we are
  207.          * currently unrestricted.  However, If this is not the
  208.          * first button pressed and we are already grabbed, do not
  209.          * change anything.
  210.          */
  211.  
  212.         if (!restrictWinPtr) {
  213.         if (!grabWinPtr) {
  214.             /*
  215.              * Mouse was ungrabbed, so set a button grab.
  216.              */
  217.  
  218.             restrictWinPtr = winPtr;
  219.             captured = 1;
  220.             rc = WinSetCapture(HWND_DESKTOP, hwnd);
  221.         } else if ((eventPtr->xmotion.state & ALL_BUTTONS) == 0) {
  222.  
  223.             /*
  224.              * Mouse was grabbed, but not in a button grab.
  225.              * Make sure the new restrict window is inside the
  226.              * current grab tree.
  227.              */
  228.  
  229.             if (TkPositionInTree(winPtr, grabWinPtr)
  230.                 == TK_GRAB_IN_TREE) {
  231.             restrictWinPtr = winPtr;
  232.             } else {
  233.             restrictWinPtr = grabWinPtr;
  234.             }
  235.             captured = 1;
  236.             rc = WinSetCapture(HWND_DESKTOP,
  237.                           TkOS2GetHWND(Tk_WindowId(restrictWinPtr)));
  238.         }
  239.         }
  240.         break;
  241.  
  242.     case ButtonRelease:
  243.  
  244.         /*
  245.          * Release the mouse capture when the last button is
  246.          * released and we aren't in a global grab.
  247.          */
  248.             
  249.         if ((eventPtr->xbutton.state & ALL_BUTTONS)
  250.             == buttonStates[eventPtr->xbutton.button - Button1]) {
  251.         if (!grabWinPtr) {
  252.             captured = 0;
  253.                 rc = WinSetCapture(HWND_DESKTOP, NULLHANDLE);
  254.         }
  255.  
  256.         /*
  257.          * If we are releasing a restrict window, then we need
  258.          * to send the button event followed by mouse motion from
  259.          * the restrict window the the current mouse position.
  260.          */
  261.  
  262.         if (restrictWinPtr) {
  263.             if (Tk_WindowId(restrictWinPtr) != eventPtr->xany.window) {
  264.             TkChangeEventWindow(eventPtr, restrictWinPtr);
  265.             }
  266.             Tk_QueueWindowEvent(eventPtr, TCL_QUEUE_TAIL);
  267.             lastMouseWinPtr = restrictWinPtr;
  268.             restrictWinPtr = NULL;
  269.             UpdateMousePosition(hwnd, winPtr, eventPtr->xmotion.x_root,
  270.                 eventPtr->xmotion.y_root);
  271.             return;
  272.         }
  273.         }
  274.         break;
  275.     }
  276.  
  277.     /*
  278.      * If a restrict window is set, make sure the pointer event is reported
  279.      * relative to that window.  Otherwise, if a global grab is in effect
  280.      * then events outside of window managed by Tk should be reported to the
  281.      * grab window.
  282.      */
  283.  
  284.     if (restrictWinPtr) {
  285.     winPtr = restrictWinPtr;
  286.     } else if (grabWinPtr && !winPtr) {
  287.     winPtr = grabWinPtr;
  288.     }
  289.  
  290.     /*
  291.      * If the target window has changed, update the coordinates in the event.
  292.      */
  293.  
  294.     if (winPtr && Tk_WindowId(winPtr) != eventPtr->xany.window) {
  295.     TkChangeEventWindow(eventPtr, winPtr);
  296.     }
  297.     Tk_QueueWindowEvent(eventPtr, TCL_QUEUE_TAIL);
  298. }
  299.  
  300. /*
  301.  *----------------------------------------------------------------------
  302.  *
  303.  * XGrabPointer --
  304.  *
  305.  *    Capture the mouse so event are reported outside of toplevels.
  306.  *    Note that this is a very limited implementation that only
  307.  *    supports GrabModeAsync and owner_events True.
  308.  *
  309.  * Results:
  310.  *    NB! The following remark from the Sun team is not true, this
  311.  *    generates an errant program. Must always return GrabSuccess.
  312.  *    AlreadyGrabbed if we cannot grab, GrabSuccess otherwise.
  313.  *
  314.  * Side effects:
  315.  *    Turns on mouse capture, sets the global grab pointer, and
  316.  *    clears any window restrictions.
  317.  *
  318.  *----------------------------------------------------------------------
  319.  */
  320.  
  321. int
  322. XGrabPointer(display, grab_window, owner_events, event_mask, pointer_mode,
  323.     keyboard_mode, confine_to, cursor, time)
  324.     Display* display;
  325.     Window grab_window;
  326.     Bool owner_events;
  327.     unsigned int event_mask;
  328.     int pointer_mode;
  329.     int keyboard_mode;
  330.     Window confine_to;
  331.     Cursor cursor;
  332.     Time time;
  333. {
  334.     HWND hwnd = TkOS2GetHWND(grab_window);
  335.  
  336.     grabWinPtr = TkOS2GetWinPtr(grab_window);
  337.     captured = 1;
  338.     restrictWinPtr = NULL;
  339.     rc = WinSetCapture(HWND_DESKTOP, hwnd);
  340.     if (TkPositionInTree(lastMouseWinPtr, grabWinPtr) == TK_GRAB_IN_TREE) {
  341.         TkOS2UpdateCursor(lastMouseWinPtr);
  342.     } else {
  343.         TkOS2UpdateCursor(grabWinPtr);
  344.     }
  345.     return GrabSuccess;
  346. }
  347.  
  348. /*
  349.  *----------------------------------------------------------------------
  350.  *
  351.  * XUngrabPointer --
  352.  *
  353.  *    Release the current grab.
  354.  *
  355.  * Results:
  356.  *    None.
  357.  *
  358.  * Side effects:
  359.  *    Releases the mouse capture.
  360.  *
  361.  *----------------------------------------------------------------------
  362.  */
  363.  
  364. void
  365. XUngrabPointer(display, time)
  366.     Display* display;
  367.     Time time;
  368. {
  369.     captured = 0;
  370.     grabWinPtr = NULL;
  371.     restrictWinPtr = NULL;
  372.     rc = WinSetCapture(HWND_DESKTOP, NULLHANDLE);
  373.     TkOS2UpdateCursor(lastMouseWinPtr);
  374. }
  375.  
  376. /*
  377.  *----------------------------------------------------------------------
  378.  *
  379.  * XGrabKeyboard --
  380.  *
  381.  *    Simulates a keyboard grab by setting the focus.
  382.  *
  383.  * Results:
  384.  *    Always returns GrabSuccess.
  385.  *
  386.  * Side effects:
  387.  *    Sets the keyboard focus to the specified window.
  388.  *
  389.  *----------------------------------------------------------------------
  390.  */
  391.  
  392. int
  393. XGrabKeyboard(display, grab_window, owner_events, pointer_mode,
  394.     keyboard_mode, time)
  395.     Display* display;
  396.     Window grab_window;
  397.     Bool owner_events;
  398.     int pointer_mode;
  399.     int keyboard_mode;
  400.     Time time;
  401. {
  402.     keyboardWinPtr = TkOS2GetWinPtr(grab_window);
  403.     return GrabSuccess;
  404. }
  405.  
  406. /*
  407.  *----------------------------------------------------------------------
  408.  *
  409.  * XUngrabKeyboard --
  410.  *
  411.  *    Releases the simulated keyboard grab.
  412.  *
  413.  * Results:
  414.  *    None.
  415.  *
  416.  * Side effects:
  417.  *    Sets the keyboard focus back to the value before the grab.
  418.  *
  419.  *----------------------------------------------------------------------
  420.  */
  421.  
  422. void
  423. XUngrabKeyboard(display, time)
  424.     Display* display;
  425.     Time time;
  426. {
  427.     keyboardWinPtr = NULL;
  428. }
  429.  
  430. /*
  431.  *----------------------------------------------------------------------
  432.  *
  433.  * InitializeCrossingEvent --
  434.  *
  435.  *    Initializes the common fields for enter/leave events.
  436.  *
  437.  * Results:
  438.  *    None.
  439.  *
  440.  * Side effects:
  441.  *    Fills in the specified event structure.
  442.  *
  443.  *----------------------------------------------------------------------
  444.  */
  445.  
  446. static void
  447. InitializeCrossingEvent(eventPtr, winPtr, x, y)
  448.     XEvent *eventPtr;        /* Event structure to initialize. */
  449.     TkWindow *winPtr;        /* Window to make event relative to. */
  450.     long x, y;            /* Root coords of event. */
  451. {
  452.     eventPtr->xcrossing.serial = LastKnownRequestProcessed(winPtr->display);
  453.     eventPtr->xcrossing.serial = winPtr->display->request++;
  454.     eventPtr->xcrossing.send_event = 0;
  455.     eventPtr->xcrossing.display = winPtr->display;
  456.     eventPtr->xcrossing.root = RootWindow(winPtr->display, winPtr->screenNum);
  457.     eventPtr->xcrossing.time = TkCurrentTime(winPtr->dispPtr);
  458.     eventPtr->xcrossing.x_root = x;
  459.     /* This is an X Event, so we leave Y in X11 coordinates */
  460.     eventPtr->xcrossing.y_root = y;
  461.     eventPtr->xcrossing.state = TkOS2GetModifierState(WM_MOUSEMOVE, 0, 0, 0);
  462.     eventPtr->xcrossing.mode = NotifyNormal;
  463.     eventPtr->xcrossing.focus = False;
  464. }
  465.  
  466. /*
  467.  *----------------------------------------------------------------------
  468.  *
  469.  * UpdateMousePosition --
  470.  *
  471.  *    Update the current mouse window and position, and generate
  472.  *    any enter/leave events that are needed.  Will schedule a
  473.  *    timer to check the mouse position if the pointer is still
  474.  *    inside a Tk window.
  475.  *
  476.  * Results:
  477.  *    Returns 1 if enter/leave events were generated.
  478.  *
  479.  * Side effects:
  480.  *    May generate enter/leave events and schedule a timer.
  481.  *
  482.  *----------------------------------------------------------------------
  483.  */
  484.  
  485. int
  486. UpdateMousePosition(hwnd, winPtr, x, y)
  487.     HWND hwnd;            /* current mouse window */
  488.     TkWindow *winPtr;        /* current Tk window (or NULL)  */
  489.     long x;            /* current mouse position in */
  490.     long y;             /* root coordinates, X11 coordinates */
  491. {
  492.     int crossed = 0;        /* 1 if mouse crossed a window boundary */
  493.     TkWindow *cursorWinPtr;
  494.  
  495.     if (winPtr != lastMouseWinPtr) {
  496.     if (restrictWinPtr) {
  497.         int newPos, oldPos;
  498.  
  499.         newPos = TkPositionInTree(winPtr, restrictWinPtr);
  500.         oldPos = TkPositionInTree(lastMouseWinPtr, restrictWinPtr);
  501.  
  502.         /*
  503.          * Check if the mouse crossed into or out of the restrict
  504.          * window.  If so, we need to generate an Enter or Leave event.
  505.          */
  506.  
  507.         if ((newPos != oldPos) && ((newPos == TK_GRAB_IN_TREE)
  508.             || (oldPos == TK_GRAB_IN_TREE))) {
  509.         XEvent event;
  510.  
  511.         InitializeCrossingEvent(&event, restrictWinPtr, x, y);
  512.         if (newPos == TK_GRAB_IN_TREE) {
  513.             event.type = EnterNotify;
  514.         } else {
  515.             event.type = LeaveNotify;
  516.         }
  517.         if ((oldPos == TK_GRAB_ANCESTOR)
  518.             || (newPos == TK_GRAB_ANCESTOR)) {
  519.             event.xcrossing.detail = NotifyAncestor;
  520.         } else {
  521.             event.xcrossing.detail = NotifyVirtual;
  522.         }
  523.         TkChangeEventWindow(&event, restrictWinPtr);
  524.         Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
  525.         }
  526.  
  527.     } else {
  528.         TkWindow *targetPtr;
  529.  
  530.         if ((lastMouseWinPtr == NULL)
  531.         || (lastMouseWinPtr->window == None)) {
  532.         targetPtr = winPtr;
  533.         } else {
  534.         targetPtr = lastMouseWinPtr;
  535.         }
  536.  
  537.         if (targetPtr && (targetPtr->window != None)) {
  538.         XEvent event;
  539.  
  540.         /*
  541.          * Generate appropriate Enter/Leave events.
  542.          */
  543.  
  544.         InitializeCrossingEvent(&event, targetPtr, x, y);
  545.  
  546.         TkInOutEvents(&event, lastMouseWinPtr, winPtr, LeaveNotify,
  547.             EnterNotify, TCL_QUEUE_TAIL);
  548.  
  549.         if (TkPositionInTree(winPtr, grabWinPtr) == TK_GRAB_IN_TREE) {
  550.             TkOS2UpdateCursor(winPtr);
  551.         } else {
  552.             TkOS2UpdateCursor(grabWinPtr);
  553.         }
  554.         crossed = 1;
  555.         }
  556.     }
  557.     lastMouseWinPtr = winPtr;
  558.     }
  559.  
  560.     /*
  561.      * Make sure the cursor reflects the current mouse position.
  562.      */
  563.  
  564.     if (restrictWinPtr) {
  565.         cursorWinPtr = restrictWinPtr;
  566.     } else if (grabWinPtr) {
  567.         cursorWinPtr = (TkPositionInTree(winPtr, grabWinPtr)
  568.                 == TK_GRAB_IN_TREE) ? winPtr : grabWinPtr;
  569.     } else {
  570.         cursorWinPtr = winPtr;
  571.     }
  572.     TkOS2UpdateCursor(cursorWinPtr);
  573.  
  574.     lastMouseWindow = hwnd;
  575.     lastMousePos.x = x;
  576.     lastMousePos.y = yScreen - y;
  577.  
  578.     /*
  579.      * Ensure the mouse timer is set if we are still inside a Tk window.
  580.      */
  581.  
  582.     if (winPtr != NULL && !mouseTimerSet) {
  583.     mouseTimerSet = 1;
  584.     mouseTimer = Tcl_CreateTimerHandler(MOUSE_TIMER_INTERVAL,
  585.                                             MouseTimerProc, NULL);
  586.     }
  587.  
  588.     return crossed;
  589. }
  590.  
  591. /*
  592.  *----------------------------------------------------------------------
  593.  *
  594.  * MouseTimerProc --
  595.  *
  596.  *    Check the current mouse position and look for enter/leave 
  597.  *    events.
  598.  *
  599.  * Results:
  600.  *    None.
  601.  *
  602.  * Side effects:
  603.  *    May schedule a new timer and/or generate enter/leave events.
  604.  *
  605.  *----------------------------------------------------------------------
  606.  */
  607.  
  608. void
  609. MouseTimerProc(clientData)
  610.     ClientData clientData;
  611. {
  612.     POINTL pos;
  613.     HWND hwnd;
  614.     TkOS2Drawable *todPtr;
  615.     TkWindow *winPtr;
  616.  
  617.     mouseTimerSet = 0;
  618.  
  619.     /*
  620.      * Get the current mouse position and window.  Don't do anything
  621.      * if the mouse hasn't moved since the last time we looked.
  622.      */
  623.  
  624.     WinQueryPointerPos(HWND_DESKTOP, &pos);
  625.     if (pos.x == lastMousePos.x && pos.y == lastMousePos.y) {
  626.     /* Mouse hasn't moved */
  627.     hwnd = lastMouseWindow;
  628.     } else {
  629.         /* Mouse has moved, redetermine window */
  630.         hwnd = WinWindowFromPoint(HWND_DESKTOP, &pos, TRUE);
  631.     }
  632.  
  633.     /*
  634.      * Check to see if the current window is managed by Tk.
  635.      */
  636.  
  637.     if (hwnd == lastMouseWindow) {
  638.     winPtr = lastMouseWinPtr;
  639.     } else {
  640.     todPtr = TkOS2GetDrawableFromHandle(hwnd);
  641.     if (todPtr && (todPtr->type == TOD_WINDOW)) {
  642.         winPtr = TkOS2GetWinPtr(todPtr);
  643.     } else {
  644.         winPtr = NULL;
  645.     }
  646.     }
  647.  
  648.     /*
  649.      * Generate enter/leave events.
  650.      */
  651.  
  652.     UpdateMousePosition(hwnd, winPtr, pos.x, yScreen - pos.y);
  653. }
  654.  
  655. /*
  656.  *----------------------------------------------------------------------
  657.  *
  658.  * TkGetPointerCoords --
  659.  *
  660.  *    Fetch the position of the mouse pointer.
  661.  *
  662.  * Results:
  663.  *    *xPtr and *yPtr are filled in with the root coordinates
  664.  *    of the mouse pointer for the display.
  665.  *
  666.  * Side effects:
  667.  *    None.
  668.  *
  669.  *----------------------------------------------------------------------
  670.  */
  671.  
  672. void
  673. TkGetPointerCoords(tkwin, xPtr, yPtr)
  674.     Tk_Window tkwin;        /* Window that identifies screen on which
  675.                  * lookup is to be done. */
  676.     int *xPtr, *yPtr;        /* Store pointer coordinates here. */
  677. {
  678.     POINTL pos;
  679.  
  680.     WinQueryPointerPos(HWND_DESKTOP, &pos);
  681.     *xPtr = pos.x;
  682.     /* Translate from PM to X coordinates */
  683.     *yPtr = yScreen - pos.y;
  684. }
  685.  
  686. /*
  687.  *----------------------------------------------------------------------
  688.  *
  689.  * XQueryPointer --
  690.  *
  691.  *    Check the current state of the mouse.  This is not a complete
  692.  *    implementation of this function.  It only computes the root
  693.  *    coordinates and the current mask.
  694.  *
  695.  * Results:
  696.  *    Sets root_x_return, root_y_return, and mask_return.  Returns
  697.  *    true on success.
  698.  *
  699.  * Side effects:
  700.  *    None.
  701.  *
  702.  *----------------------------------------------------------------------
  703.  */
  704.  
  705. Bool
  706. XQueryPointer(display, w, root_return, child_return, root_x_return,
  707.     root_y_return, win_x_return, win_y_return, mask_return)
  708.     Display* display;
  709.     Window w;
  710.     Window* root_return;
  711.     Window* child_return;
  712.     int* root_x_return;
  713.     int* root_y_return;
  714.     int* win_x_return;
  715.     int* win_y_return;
  716.     unsigned int* mask_return;
  717. {
  718.     TkGetPointerCoords(NULL, root_x_return, root_y_return);
  719.     *mask_return = TkOS2GetModifierState(WM_MOUSEMOVE, 0, 0, 0);    
  720.     return True;
  721. }
  722.  
  723. /*
  724.  *----------------------------------------------------------------------
  725.  *
  726.  * XGetInputFocus --
  727.  *
  728.  *    Retrieves the current keyboard focus window.
  729.  *
  730.  * Results:
  731.  *    Returns the current focus window.
  732.  *
  733.  * Side effects:
  734.  *    None.
  735.  *
  736.  *----------------------------------------------------------------------
  737.  */
  738.  
  739. void
  740. XGetInputFocus(display, focus_return, revert_to_return)
  741.     Display *display;
  742.     Window *focus_return;
  743.     int *revert_to_return;
  744. {
  745.     HWND hwnd = WinQueryFocus(HWND_DESKTOP);
  746.     TkOS2Drawable *todPtr = TkOS2GetDrawableFromHandle(hwnd);
  747.  
  748.     /*
  749.      * The focus window may be a Tk window or a window manager decorative
  750.      * frame.
  751.      */
  752.  
  753.     if (todPtr) {
  754.     *focus_return = Tk_WindowId(TkOS2GetWinPtr(todPtr));
  755.     } else {
  756.     *focus_return = NULLHANDLE;
  757.     }
  758.     *revert_to_return = RevertToParent;
  759. }
  760.  
  761. /*
  762.  *----------------------------------------------------------------------
  763.  *
  764.  * XSetInputFocus --
  765.  *
  766.  *    Set the current focus window.
  767.  *
  768.  * Results:
  769.  *    None.
  770.  *
  771.  * Side effects:
  772.  *    Changes the keyboard focus and causes the selected window to
  773.  *    be activated.
  774.  *
  775.  *----------------------------------------------------------------------
  776.  */
  777.  
  778. void
  779. XSetInputFocus(display, focus, revert_to, time)
  780.     Display* display;
  781.     Window focus;
  782.     int revert_to;
  783.     Time time;
  784. {
  785.     HWND hwnd = TkOS2GetHWND(focus);
  786.     WinSetFocus(HWND_DESKTOP, hwnd);
  787. }
  788.  
  789. /*
  790.  *----------------------------------------------------------------------
  791.  *
  792.  * XDefineCursor --
  793.  *
  794.  *      This function is called to update the cursor on a window.
  795.  *      Since the mouse might be in the specified window, we need to
  796.  *      check the specified window against the current mouse position
  797.  *      and grab state.
  798.  *
  799.  * Results:
  800.  *      None.
  801.  *
  802.  * Side effects:
  803.  *      May update the cursor.
  804.  *
  805.  *----------------------------------------------------------------------
  806.  */
  807.  
  808. void
  809. XDefineCursor(display, w, cursor)
  810.     Display* display;
  811.     Window w;
  812.     Cursor cursor;
  813. {
  814.     TkWindow *winPtr = TkOS2GetWinPtr(w);
  815.  
  816.     if (restrictWinPtr) {
  817.  
  818.         /*
  819.          * If there is a restrict window, then we only update the cursor
  820.          * if the restrict window is the window being modified.
  821.          */
  822.  
  823.         if (winPtr == restrictWinPtr) {
  824.             goto update;
  825.         }
  826.     } else if (grabWinPtr) {
  827.  
  828.         /*
  829.          * If a grab is in effect, then we only update the cursor if the mouse
  830.          * pointer is outside the grab tree and the specified window is the
  831.          * grab window, or the pointer is inside the grab tree and the
  832.          * specified window is also the pointer window.
  833.          */
  834.  
  835.         if (TkPositionInTree(lastMouseWinPtr, grabWinPtr) == TK_GRAB_IN_TREE) {
  836.             if (winPtr == lastMouseWinPtr) {
  837.                 goto update;
  838.             }
  839.         } else if (winPtr == grabWinPtr) {
  840.             goto update;
  841.         }
  842.     } else {
  843.  
  844.         /*
  845.          * Otherwise, we only update the cursor if the specified window
  846.          * contains the mouse pointer.
  847.          */
  848.  
  849.         if (winPtr == lastMouseWinPtr) {
  850.             goto update;
  851.         }
  852.     }
  853.     return;
  854.  
  855. update:
  856.     TkOS2UpdateCursor(winPtr);
  857. }
  858.