home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / tcltk805.zip / tcl805s.zip / tk8.0.5 / os2 / tkOS2Pointer.c < prev    next >
C/C++ Source or Header  |  2000-08-02  |  16KB  |  582 lines

  1. /* 
  2.  * tkOS2Pointer.c --
  3.  *
  4.  *    OS/2 PM specific mouse tracking code.
  5.  *
  6.  * Copyright (c) 1996-2000 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.  * Declarations of static variables used in this file.
  24.  */
  25.  
  26. static int captured = 0;        /* 1 if mouse is currently captured. */
  27. static TkWindow *keyboardWinPtr = NULL;    /* Current keyboard grab window. */
  28. static Tcl_TimerToken mouseTimer;       /* Handle to the latest mouse timer. */
  29. static int mouseTimerSet = 0;           /* 1 if the mouse timer is active. */
  30. static POINTL prevMousePos = {0,0};    /* previous position of the mouse. */
  31.  
  32. /*
  33.  * Forward declarations of procedures used in this file.
  34.  */
  35.  
  36. static void        MouseTimerProc (ClientData clientData);
  37.  
  38. /*
  39.  *----------------------------------------------------------------------
  40.  *
  41.  * TkOS2GetModifierState --
  42.  *
  43.  *      Return the modifier state as of the last message.
  44.  *
  45.  * Results:
  46.  *      Returns the X modifier mask.
  47.  *
  48.  * Side effects:
  49.  *      None.
  50.  *
  51.  *----------------------------------------------------------------------
  52.  */
  53.  
  54. int
  55. TkOS2GetModifierState()
  56. {
  57.     int state = 0;
  58.  
  59.     if (WinGetKeyState(HWND_DESKTOP, VK_SHIFT) & 0x8000) {
  60. #ifdef VERBOSE
  61.         printf("TkOS2GetModifierState ShiftMask\n");
  62. #endif
  63.         state |= ShiftMask;
  64.     }
  65.     if (WinGetKeyState(HWND_DESKTOP, VK_CTRL) & 0x8000) {
  66. #ifdef VERBOSE
  67.         printf("TkOS2GetModifierState ControlMask\n");
  68. #endif
  69.         state |= ControlMask;
  70.     }
  71.     if (WinGetKeyState(HWND_DESKTOP, VK_MENU) & 0x8000) {
  72. #ifdef VERBOSE
  73.         printf("TkOS2GetModifierState Mod2Mask\n");
  74. #endif
  75.         state |= Mod2Mask;
  76.     }
  77.     if (WinGetKeyState(HWND_DESKTOP, VK_CAPSLOCK) & 0x0001) {
  78. #ifdef VERBOSE
  79.         printf("TkOS2GetModifierState LockMask\n");
  80. #endif
  81.         state |= LockMask;
  82.     }
  83.     if (WinGetKeyState(HWND_DESKTOP, VK_NUMLOCK) & 0x0001) {
  84. #ifdef VERBOSE
  85.         printf("TkOS2GetModifierState Mod1Mask\n");
  86. #endif
  87.         state |= Mod1Mask;
  88.     }
  89.     if (WinGetKeyState(HWND_DESKTOP, VK_SCRLLOCK) & 0x0001) {
  90. #ifdef VERBOSE
  91.         printf("TkOS2GetModifierState Mod3Mask\n");
  92. #endif
  93.         state |= Mod3Mask;
  94.     }
  95.     if (WinGetKeyState(HWND_DESKTOP, VK_BUTTON1) & 0x8000) {
  96. #ifdef VERBOSE
  97.         printf("TkOS2GetModifierState Button1Mask\n");
  98. #endif
  99.         state |= Button1Mask;
  100.     }
  101.     /* OS/2 and X buttons 2 and 3 are reversed, 3 not necessarily available */
  102.     if (WinGetKeyState(HWND_DESKTOP, VK_BUTTON3) & 0x8000) {
  103. #ifdef VERBOSE
  104.         printf("TkOS2GetModifierState Button2Mask\n");
  105. #endif
  106.         state |= Button2Mask;
  107.     }
  108.     if (WinGetKeyState(HWND_DESKTOP, VK_BUTTON2) & 0x8000) {
  109. #ifdef VERBOSE
  110.         printf("TkOS2GetModifierState Button3Mask\n");
  111. #endif
  112.         state |= Button3Mask;
  113.     }
  114. #ifdef VERBOSE
  115.     printf("TkOS2GetModifierState: %x\n", state);
  116. #endif
  117.     return state;
  118. }
  119.  
  120. /*
  121.  *----------------------------------------------------------------------
  122.  *
  123.  * Tk_PointerEvent --
  124.  *
  125.  *      This procedure is called for each pointer-related event.
  126.  *      It converts the position to root coords and updates the
  127.  *      global pointer state machine.  It also ensures that the
  128.  *      mouse timer is scheduled.
  129.  *      NB: PM y coordinates!
  130.  *
  131.  * Results:
  132.  *      None.
  133.  *
  134.  * Side effects:
  135.  *      May queue events and change the grab state.
  136.  *
  137.  *----------------------------------------------------------------------
  138.  */
  139.  
  140. void
  141. Tk_PointerEvent(hwnd, x, y)
  142.     HWND hwnd;                          /* Window for coords, or NULLHANDLE for
  143.                                          * the root window. */
  144.     int x, y;                           /* Coords relative to hwnd, or screen
  145.                                          * if hwnd is NULLHANDLE. */
  146. {
  147.     POINTL pos;
  148.     int state;
  149.     Tk_Window tkwin;
  150.  
  151. #ifdef VERBOSE
  152.     printf("Tk_PointerEvent hwnd %x (%hd,%hd)\n", hwnd, x, y);
  153.     fflush(stdout);
  154. #endif
  155.     pos.x = (LONG) x;
  156.     pos.y = (LONG) y;
  157.  
  158.     /*
  159.      * Convert client coords to root coords if we were given a window.
  160.      */
  161.  
  162.     if (hwnd != NULLHANDLE) {
  163.         WinMapWindowPoints(hwnd, HWND_DESKTOP, &pos, 1);
  164. #ifdef VERBOSE
  165.         printf("mapped => (%hd,%hd)\n", pos.x, pos.y);
  166.         fflush(stdout);
  167. #endif
  168.     }
  169.  
  170.     /*
  171.      * If the mouse is captured, OS/2 will report all pointer
  172.      * events to the capture window.  So, we need to determine which
  173.      * window the mouse is really over and change the event.  Note
  174.      * that the computed hwnd may point to a window not owned by Tk,
  175.      * or a toplevel decorative frame, so tkwin can be NULL.
  176.      */
  177.  
  178.     if (captured || hwnd == NULLHANDLE) {
  179. #ifdef VERBOSE
  180.         printf("Tk_PointerEvent captured, hwnd %x => \n", hwnd);
  181.         fflush(stdout);
  182. #endif
  183.         hwnd = WinWindowFromPoint(HWND_DESKTOP, &pos, TRUE);
  184. #ifdef VERBOSE
  185.         printf("Tk_PointerEvent captured => %x\n", hwnd);
  186.         fflush(stdout);
  187. #endif
  188.     }
  189.     tkwin = Tk_HWNDToWindow(hwnd);
  190.  
  191.     state = TkOS2GetModifierState();
  192. #ifdef VERBOSE
  193.     printf("Tk_PointerEvent => tkwin %x (%hd,%hd) x11y %hd st %x hwnd %x\n",
  194.            tkwin, pos.x, pos.y, yScreen - pos.y, state, hwnd);
  195.     fflush(stdout);
  196. #endif
  197.  
  198.     /* Tk_UpdatePointer needs X Window System y coordinates */
  199. #ifdef VERBOSE
  200.     printf("calling Tk_UpdatePointer with %x, (%hd,%hd), %x\n", tkwin, pos.x,
  201.            yScreen - pos.y, state);
  202.     fflush(stdout);
  203.     printf("winPtr->display %x (screens %x), winPtr->screenNum %d, screen %x\n",
  204.            tkwin ? ((TkWindow *)tkwin)->display : 0,
  205.            tkwin ? (((TkWindow *)tkwin)->display)->screens : 0,
  206.            tkwin ? ((TkWindow *)tkwin)->screenNum : 0,
  207.            tkwin && (((TkWindow *)tkwin)->display)->screens != NULL ?
  208.         RootWindow(((TkWindow *)tkwin)->display, ((TkWindow *)tkwin)->screenNum)
  209.         : 0L);
  210.     fflush(stdout);
  211. #endif
  212.     Tk_UpdatePointer(tkwin, (int)pos.x, (int)(yScreen - pos.y), state);
  213. #ifdef VERBOSE
  214.     printf("After Tk_UpdatePointer\n");
  215. #endif
  216.  
  217.     if ((captured || tkwin) && !mouseTimerSet) {
  218.         mouseTimerSet = 1;
  219. #ifdef VERBOSE
  220.         printf("Creating mouseTimer %d\n", MOUSE_TIMER_INTERVAL);
  221. #endif
  222.         mouseTimer = Tcl_CreateTimerHandler(MOUSE_TIMER_INTERVAL,
  223.                 MouseTimerProc, NULL);
  224.     }
  225. }
  226.  
  227. /*
  228.  *----------------------------------------------------------------------
  229.  *
  230.  * XGrabKeyboard --
  231.  *
  232.  *    Simulates a keyboard grab by setting the focus.
  233.  *
  234.  * Results:
  235.  *    Always returns GrabSuccess.
  236.  *
  237.  * Side effects:
  238.  *    Sets the keyboard focus to the specified window.
  239.  *
  240.  *----------------------------------------------------------------------
  241.  */
  242.  
  243. int
  244. XGrabKeyboard(display, grab_window, owner_events, pointer_mode,
  245.     keyboard_mode, time)
  246.     Display* display;
  247.     Window grab_window;
  248.     Bool owner_events;
  249.     int pointer_mode;
  250.     int keyboard_mode;
  251.     Time time;
  252. {
  253. #ifdef VERBOSE
  254.     printf("XGrabKeyboard\n");
  255. #endif
  256.  
  257.     keyboardWinPtr = TkOS2GetWinPtr(grab_window);
  258.     return GrabSuccess;
  259. }
  260.  
  261. /*
  262.  *----------------------------------------------------------------------
  263.  *
  264.  * XUngrabKeyboard --
  265.  *
  266.  *    Releases the simulated keyboard grab.
  267.  *
  268.  * Results:
  269.  *    None.
  270.  *
  271.  * Side effects:
  272.  *    Sets the keyboard focus back to the value before the grab.
  273.  *
  274.  *----------------------------------------------------------------------
  275.  */
  276.  
  277. void
  278. XUngrabKeyboard(display, time)
  279.     Display* display;
  280.     Time time;
  281. {
  282. #ifdef VERBOSE
  283.     printf("XUngrabKeyboard\n");
  284. #endif
  285.  
  286.     keyboardWinPtr = NULL;
  287. }
  288.  
  289. /*
  290.  *----------------------------------------------------------------------
  291.  *
  292.  * MouseTimerProc --
  293.  *
  294.  *    Check the current mouse position and look for enter/leave 
  295.  *    events.
  296.  *
  297.  * Results:
  298.  *    None.
  299.  *
  300.  * Side effects:
  301.  *    May schedule a new timer and/or generate enter/leave events.
  302.  *
  303.  *----------------------------------------------------------------------
  304.  */
  305.  
  306. void
  307. MouseTimerProc(clientData)
  308.     ClientData clientData;
  309. {
  310.     POINTL pos;
  311.  
  312.     mouseTimerSet = 0;
  313.  
  314.     /*
  315.      * Get the current mouse position and window.  Don't do anything
  316.      * if the mouse hasn't moved since the last time we looked.
  317.      */
  318.  
  319.     rc = WinQueryPointerPos(HWND_DESKTOP, &pos);
  320.  
  321. #ifdef VERBOSE
  322.     printf("MouseTimerProc, WinQueryPointerPos returns %d (%d,%d)\n", rc,
  323.            pos.x, pos.y);
  324. #endif
  325.     if (pos.x != prevMousePos.x || pos.y != prevMousePos.y) {
  326.         /* Tk_PointerEvent handles PM Y coordinates */
  327.         Tk_PointerEvent(NULLHANDLE, pos.x, pos.y);
  328.     }
  329. }
  330.  
  331. /*
  332.  *----------------------------------------------------------------------
  333.  *
  334.  * TkGetPointerCoords --
  335.  *
  336.  *    Fetch the position of the mouse pointer.
  337.  *
  338.  * Results:
  339.  *    *xPtr and *yPtr are filled in with the root coordinates
  340.  *    of the mouse pointer for the display.
  341.  *
  342.  * Side effects:
  343.  *    None.
  344.  *
  345.  *----------------------------------------------------------------------
  346.  */
  347.  
  348. void
  349. TkGetPointerCoords(tkwin, xPtr, yPtr)
  350.     Tk_Window tkwin;        /* Window that identifies screen on which
  351.                  * lookup is to be done. */
  352.     int *xPtr, *yPtr;        /* Store pointer coordinates here. */
  353. {
  354.     POINTL pos;
  355.  
  356. #ifdef VERBOSE
  357.     printf("TkGetPointerCoords\n");
  358. #endif
  359.  
  360.     WinQueryPointerPos(HWND_DESKTOP, &pos);
  361.     *xPtr = pos.x;
  362.     /* Translate from PM to X coordinates */
  363.     *yPtr = yScreen - pos.y;
  364. }
  365.  
  366. /*
  367.  *----------------------------------------------------------------------
  368.  *
  369.  * XQueryPointer --
  370.  *
  371.  *    Check the current state of the mouse.  This is not a complete
  372.  *    implementation of this function.  It only computes the root
  373.  *    coordinates and the current mask.
  374.  *
  375.  * Results:
  376.  *    Sets root_x_return, root_y_return, and mask_return.  Returns
  377.  *    true on success.
  378.  *
  379.  * Side effects:
  380.  *    None.
  381.  *
  382.  *----------------------------------------------------------------------
  383.  */
  384.  
  385. Bool
  386. XQueryPointer(display, w, root_return, child_return, root_x_return,
  387.     root_y_return, win_x_return, win_y_return, mask_return)
  388.     Display* display;
  389.     Window w;
  390.     Window* root_return;
  391.     Window* child_return;
  392.     int* root_x_return;
  393.     int* root_y_return;
  394.     int* win_x_return;
  395.     int* win_y_return;
  396.     unsigned int* mask_return;
  397. {
  398. #ifdef VERBOSE
  399.     printf("XQueryPointer\n");
  400. #endif
  401.     TkGetPointerCoords(NULL, root_x_return, root_y_return);
  402.     *mask_return = TkOS2GetModifierState();    
  403.     return True;
  404. }
  405.  
  406. /*
  407.  *----------------------------------------------------------------------
  408.  *
  409.  * XGetInputFocus --
  410.  *
  411.  *    Retrieves the current keyboard focus window.
  412.  *
  413.  * Results:
  414.  *    Returns the current focus window.
  415.  *
  416.  * Side effects:
  417.  *    None.
  418.  *
  419.  *----------------------------------------------------------------------
  420.  */
  421.  
  422. void
  423. XGetInputFocus(display, focus_return, revert_to_return)
  424.     Display *display;
  425.     Window *focus_return;
  426.     int *revert_to_return;
  427. {
  428.     Tk_Window tkwin = Tk_HWNDToWindow(WinQueryFocus(HWND_DESKTOP));
  429.  
  430. #ifdef VERBOSE
  431.     printf("XGetInputFocus tkwin %x\n", tkwin);
  432. #endif
  433.  
  434.     *focus_return = tkwin ? Tk_WindowId(tkwin) : None;
  435.     *revert_to_return = RevertToParent;
  436.     display->request++;
  437. }
  438.  
  439. /*
  440.  *----------------------------------------------------------------------
  441.  *
  442.  * XSetInputFocus --
  443.  *
  444.  *    Set the current focus window.
  445.  *
  446.  * Results:
  447.  *    None.
  448.  *
  449.  * Side effects:
  450.  *    Changes the keyboard focus and causes the selected window to
  451.  *    be activated.
  452.  *
  453.  *----------------------------------------------------------------------
  454.  */
  455.  
  456. void
  457. XSetInputFocus(display, focus, revert_to, time)
  458.     Display* display;
  459.     Window focus;
  460.     int revert_to;
  461.     Time time;
  462. {
  463. #ifdef VERBOSE
  464.     printf("XSetInputFocus\n");
  465. #endif
  466.     display->request++;
  467.     if (focus != None) {
  468.         WinSetFocus(HWND_DESKTOP, Tk_GetHWND(focus));
  469.     }
  470. }
  471.  
  472. /*
  473.  *----------------------------------------------------------------------
  474.  *
  475.  * TkpChangeFocus --
  476.  *
  477.  *      This procedure is invoked to move the system focus from
  478.  *      one window to another.
  479.  *
  480.  * Results:
  481.  *      The return value is the serial number of the command that
  482.  *      changed the focus.  It may be needed by the caller to filter
  483.  *      out focus change events that were queued before the command.
  484.  *      If the procedure doesn't actually change the focus then
  485.  *      it returns 0.
  486.  *
  487.  * Side effects:
  488.  *      The official OS/2 focus window changes;  the application's focus
  489.  *      window isn't changed by this procedure.
  490.  *
  491.  *----------------------------------------------------------------------
  492.  */
  493.  
  494. int
  495. TkpChangeFocus(winPtr, force)
  496.     TkWindow *winPtr;           /* Window that is to receive the X focus. */
  497.     int force;                  /* Non-zero means claim the focus even
  498.                                  * if it didn't originally belong to
  499.                                  * topLevelPtr's application. */
  500. {
  501.     TkDisplay *dispPtr = winPtr->dispPtr;
  502.     Window focusWindow;
  503.     int dummy, serial;
  504.     TkWindow *winPtr2;
  505.  
  506.     if (!force) {
  507.         XGetInputFocus(dispPtr->display, &focusWindow, &dummy);
  508.         winPtr2 = (TkWindow *) Tk_IdToWindow(dispPtr->display, focusWindow);
  509.         if ((winPtr2 == NULL) || (winPtr2->mainPtr != winPtr->mainPtr)) {
  510.             return 0;
  511.         }
  512.     }
  513.  
  514.     if (winPtr->window == None) {
  515.         panic("ChangeXFocus got null X window");
  516.     }
  517.  
  518.     /*
  519.      * Change the foreground window so the focus window is raised to the top of
  520.      * the system stacking order and gets the keyboard focus.
  521.      */
  522.  
  523.     if (force) {
  524.         WinSetWindowPos(Tk_GetHWND(winPtr->window), HWND_TOP, 0L, 0L, 0L, 0L,
  525.                         SWP_ACTIVATE);
  526.     }
  527.     XSetInputFocus(dispPtr->display, winPtr->window, RevertToParent,
  528.             CurrentTime);
  529.  
  530.     /*
  531.      * Remember the current serial number for the X server and issue
  532.      * a dummy server request.  This marks the position at which we
  533.      * changed the focus, so we can distinguish FocusIn and FocusOut
  534.      * events on either side of the mark.
  535.      */
  536.  
  537.     serial = NextRequest(winPtr->display);
  538.     XNoOp(winPtr->display);
  539.     return serial;
  540. }
  541.  
  542. /*
  543.  *----------------------------------------------------------------------
  544.  *
  545.  * TkpSetCapture --
  546.  *
  547.  *      This function captures the mouse so that all future events
  548.  *      will be reported to this window, even if the mouse is outside
  549.  *      the window.  If the specified window is NULL, then the mouse
  550.  *      is released.
  551.  *
  552.  * Results:
  553.  *      None.
  554.  *
  555.  * Side effects:
  556.  *      Sets the capture flag and captures the mouse.
  557.  *
  558.  *----------------------------------------------------------------------
  559.  */
  560.  
  561. void
  562. TkpSetCapture(winPtr)
  563.     TkWindow *winPtr;                   /* Capture window, or NULL. */
  564. {
  565.     if (winPtr) {
  566. #ifdef VERBOSE
  567.         printf("TkpSetCapture winPtr %x hwnd %x\n", winPtr,
  568.                Tk_GetHWND(Tk_WindowId(winPtr)));
  569. #endif
  570.         WinSetCapture(HWND_DESKTOP, Tk_GetHWND(Tk_WindowId(winPtr)));
  571.         captured = 1;
  572.     } else {
  573.         if (captured) {
  574.             captured = 0;
  575. #ifdef VERBOSE
  576.             printf("TkpSetCapture winPtr %x NULLHANDLE\n", winPtr);
  577. #endif
  578.             WinSetCapture(HWND_DESKTOP, NULLHANDLE);
  579.         }
  580.     }
  581. }
  582.