tkMacWindowMgr.c
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:44k
源码类别:

通讯编程

开发平台:

Visual C++

  1. /* 
  2.  * tkMacWindowMgr.c --
  3.  *
  4.  * Implements common window manager functions for the Macintosh.
  5.  *
  6.  * Copyright (c) 1995-1998 Sun Microsystems, Inc.
  7.  *
  8.  * See the file "license.terms" for information on usage and redistribution
  9.  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
  10.  *
  11.  * RCS: @(#) $Id: tkMacWindowMgr.c,v 1.10 2002/06/14 22:25:12 jenglish Exp $
  12.  */
  13. #include <Events.h>
  14. #include <Dialogs.h>
  15. #include <EPPC.h>
  16. #include <Windows.h>
  17. #include <ToolUtils.h>
  18. #include <DiskInit.h>
  19. #include <LowMem.h>
  20. #include <Timer.h>
  21. #include <Sound.h>
  22. #include "tkInt.h"
  23. #include "tkPort.h"
  24. #include "tkMacInt.h"
  25. #define TK_DEFAULT_ABOUT 128
  26. /*
  27.  * Declarations of global variables defined in this file.
  28.  */
  29. int tkMacAppInFront = true;  /* Boolean variable for determining 
  30.   * if we are the frontmost app. */
  31. /*
  32.  *  Non-standard event types that can be passed to HandleEvent.
  33.  * These are defined and used by Netscape's plugin architecture.
  34.  */
  35. #define getFocusEvent       (osEvt + 16)
  36. #define loseFocusEvent      (osEvt + 17)
  37. #define adjustCursorEvent   (osEvt + 18)
  38. /*
  39.  * Declarations of static variables used in this file.
  40.  */
  41. static int  gEatButtonUp = 0;  /* 1 if we need to eat the next
  42.   * up event */
  43. static Tk_Window gGrabWinPtr = NULL;  /* Current grab window, NULL if no grab. */
  44. static Tk_Window gKeyboardWinPtr = NULL; /* Current keyboard grab window. */
  45. static RgnHandle gDamageRgn = NULL;  /* Damage region used for handling
  46.   * screen updates. */
  47. /*
  48.  * Forward declarations of procedures used in this file.
  49.  */
  50. static void BringWindowForward _ANSI_ARGS_((WindowRef wRef));
  51. static int  CheckEventsAvail _ANSI_ARGS_((void));
  52. static int  GenerateActivateEvents _ANSI_ARGS_((EventRecord *eventPtr,
  53. Window window));
  54. static int  GenerateFocusEvent _ANSI_ARGS_((EventRecord *eventPtr,
  55. Window window));
  56. static int GenerateKeyEvent _ANSI_ARGS_((EventRecord *eventPtr,
  57. Window window, UInt32 savedCode));
  58. static int GenerateUpdateEvent _ANSI_ARGS_((EventRecord *eventPtr,
  59. Window window));
  60. static void  GenerateUpdates _ANSI_ARGS_((RgnHandle updateRgn,
  61. TkWindow *winPtr));
  62. static int  GeneratePollingEvents _ANSI_ARGS_((void));
  63. static int  GeneratePollingEvents2 _ANSI_ARGS_((Window window,
  64.                 int adjustCursor));
  65. static OSErr TellWindowDefProcToCalcRegions _ANSI_ARGS_((WindowRef wRef));
  66. static int WindowManagerMouse _ANSI_ARGS_((EventRecord *theEvent,
  67.     Window window));
  68. /*
  69.  *----------------------------------------------------------------------
  70.  *
  71.  * WindowManagerMouse --
  72.  *
  73.  * This function determines if a button event is a "Window Manager"
  74.  * function or an event that should be passed to Tk's event
  75.  * queue.
  76.  *
  77.  * Results:
  78.  * Return true if event was placed on Tk's event queue.
  79.  *
  80.  * Side effects:
  81.  * Depends on where the button event occurs.
  82.  *
  83.  *----------------------------------------------------------------------
  84.  */
  85. static int
  86. WindowManagerMouse(
  87.     EventRecord *eventPtr, /* Macintosh event record. */
  88.     Window window) /* Window pointer. */
  89. {
  90.     WindowRef whichWindow, frontWindow, frontNonFloating;
  91.     Tk_Window tkwin;
  92.     Point where, where2;
  93.     int xOffset, yOffset;
  94.     short windowPart;
  95.     TkDisplay *dispPtr;
  96.     frontWindow = FrontWindow();
  97.     if (TkMacHaveAppearance() >= 0x110) {
  98.         frontNonFloating = FrontNonFloatingWindow();
  99.     } else {
  100.         frontNonFloating = frontWindow;
  101.     }
  102.     /* 
  103.      * The window manager only needs to know about mouse down events
  104.      * and sometimes we need to "eat" the mouse up.  Otherwise, we
  105.      * just pass the event to Tk.
  106.      */
  107.     if (eventPtr->what == mouseUp) {
  108. if (gEatButtonUp) {
  109.     gEatButtonUp = false;
  110.     return false;
  111. }
  112. return TkGenerateButtonEvent(eventPtr->where.h, eventPtr->where.v, 
  113. window, TkMacButtonKeyState());
  114.     }
  115.     windowPart = FindWindow(eventPtr->where, &whichWindow);
  116.     dispPtr = TkGetDisplayList();
  117.     tkwin = Tk_IdToWindow(dispPtr->display, window);
  118.     switch (windowPart) {
  119. case inSysWindow:
  120.     SystemClick(eventPtr, (GrafPort *) whichWindow);
  121.     return false;
  122. case inDrag:
  123.     if (!(TkpIsWindowFloating(whichWindow)) && (whichWindow != frontNonFloating)) {
  124. if (!(eventPtr->modifiers & cmdKey)) {
  125.     if ((gGrabWinPtr != NULL) && (gGrabWinPtr != tkwin)) {
  126. SysBeep(1);
  127. return false;
  128.     }
  129. }
  130.     }
  131.     /*
  132.      * Call DragWindow to move the window around.  It will
  133.      * also eat the mouse up event.
  134.      */
  135.     SetPort((GrafPort *) whichWindow);
  136.     where.h = where.v = 0;
  137.     LocalToGlobal(&where);
  138.     DragWindow(whichWindow, eventPtr->where,
  139.     &tcl_macQdPtr->screenBits.bounds);
  140.     gEatButtonUp = false;
  141.     where2.h = where2.v = 0;
  142.     LocalToGlobal(&where2);
  143.     if (EqualPt(where, where2)) {
  144. return false;
  145.     }
  146.     TkMacWindowOffset(whichWindow, &xOffset, &yOffset);
  147.     where2.h -= xOffset;
  148.     where2.v -= yOffset;
  149.     TkGenWMConfigureEvent(tkwin, where2.h, where2.v,
  150.     -1, -1, TK_LOCATION_CHANGED);
  151.     return true;
  152. case inGrow:
  153. case inContent:
  154.     if (!(TkpIsWindowFloating(whichWindow)) 
  155.             && (whichWindow != frontNonFloating)) {
  156. /*
  157.  * This click moves the window forward.  We don't want
  158.  * the corasponding mouse-up to be reported to the application
  159.  * or else it will mess up some Tk scripts.
  160.  */
  161. if ((gGrabWinPtr != NULL) && (gGrabWinPtr != tkwin)) {
  162.     SysBeep(1);
  163.     return false;
  164. }
  165. gEatButtonUp = true;
  166. SetPort((GrafPort *) whichWindow);
  167. BringWindowForward(whichWindow);
  168. return false;
  169.     } else {
  170. /*
  171.  * Generally the content region is the domain of Tk
  172.  * sub-windows.  However, one exception is the grow
  173.  * region.  A button down in this area will be handled
  174.  * by the window manager.  Note: this means that Tk 
  175.  * may not get button down events in this area!
  176.  */
  177. if (TkMacGrowToplevel(whichWindow, eventPtr->where) == true) {
  178.     return true;
  179. } else {
  180.     return TkGenerateButtonEvent(eventPtr->where.h,
  181.     eventPtr->where.v, window, TkMacButtonKeyState());
  182. }
  183.     }
  184. case inGoAway:
  185.     if (TrackGoAway( whichWindow, eventPtr->where)) {
  186. if (tkwin == NULL) {
  187.     return false;
  188. }
  189. TkGenWMDestroyEvent(tkwin);
  190. return true;
  191.     }
  192.     return false;
  193. case inMenuBar:
  194.     {
  195. int oldMode;
  196. KeyMap theKeys;
  197. GetKeys(theKeys);
  198. oldMode = Tcl_SetServiceMode(TCL_SERVICE_ALL);
  199. TkMacClearMenubarActive();
  200. /*
  201.  * Handle -postcommand
  202.  */
  203. TkMacPreprocessMenu();
  204. TkMacHandleMenuSelect(MenuSelect(eventPtr->where),
  205. theKeys[1] & 4);
  206. Tcl_SetServiceMode(oldMode);
  207. return true; /* TODO: may not be on event on queue. */
  208.     }
  209. case inZoomIn:
  210. case inZoomOut:
  211.     if (TkMacZoomToplevel(whichWindow, eventPtr->where, windowPart)
  212.     == true) {
  213. return true;
  214.     } else {
  215. return false;
  216.     }
  217. default:
  218.     return false;
  219.     }
  220. }
  221. /*
  222.  *----------------------------------------------------------------------
  223.  *
  224.  * TkAboutDlg --
  225.  *
  226.  * Displays the default Tk About box.  This code uses Macintosh
  227.  * resources to define the content of the About Box.
  228.  *
  229.  * Results:
  230.  * None.
  231.  *
  232.  * Side effects:
  233.  * None.
  234.  *
  235.  *----------------------------------------------------------------------
  236.  */
  237. void 
  238. TkAboutDlg()
  239. {
  240.     DialogPtr aboutDlog;
  241.     short itemHit = -9;
  242.     aboutDlog = GetNewDialog(128, NULL, (void*)(-1));
  243.     if (!aboutDlog) {
  244. return;
  245.     }
  246.     SelectWindow((WindowRef) aboutDlog);
  247.     while (itemHit != 1) {
  248. ModalDialog( NULL, &itemHit);
  249.     }
  250.     DisposeDialog(aboutDlog);
  251.     aboutDlog = NULL;
  252.     if (TkMacHaveAppearance() >= 0x110) {
  253.         SelectWindow(FrontNonFloatingWindow());
  254.     } else {
  255.     SelectWindow(FrontWindow());
  256.     }
  257.     return;
  258. }
  259. /*
  260.  *----------------------------------------------------------------------
  261.  *
  262.  * GenerateUpdateEvent --
  263.  *
  264.  * Given a Macintosh update event this function generates all the
  265.  * X update events needed by Tk.
  266.  *
  267.  * Results:
  268.  * True if event(s) are generated - false otherwise.  
  269.  *
  270.  * Side effects:
  271.  * Additional events may be place on the Tk event queue.
  272.  *
  273.  *----------------------------------------------------------------------
  274.  */
  275. static int
  276. GenerateUpdateEvent(
  277.     EventRecord *eventPtr, /* Incoming Mac event */
  278.     Window window) /* Root X window for event. */
  279. {
  280.     WindowRef macWindow;
  281.     register TkWindow *winPtr;
  282.     TkDisplay *dispPtr;
  283.     dispPtr = TkGetDisplayList();
  284.     winPtr = (TkWindow *) Tk_IdToWindow(dispPtr->display, window);
  285.     if (winPtr == NULL) {
  286.  return false;
  287.     }
  288.     
  289.     if (gDamageRgn == NULL) {
  290. gDamageRgn = NewRgn();
  291.     }
  292.     /*
  293.      * After the call to BeginUpdate the visable region (visRgn) of the 
  294.      * window is equal to the intersection of the real visable region and
  295.      * the update region for this event.  We use this region in all of our
  296.      * calculations.
  297.      */
  298.     if (eventPtr->message != NULL) {
  299. macWindow = (WindowRef) TkMacGetDrawablePort(window);
  300. BeginUpdate(macWindow);
  301. GenerateUpdates(macWindow->visRgn, winPtr);
  302. EndUpdate(macWindow);
  303. return true;
  304.     } else {
  305. /*
  306.  * This event didn't come from the system.  This might
  307.  * occur if we are running from inside of Netscape.
  308.  * In this we shouldn't call BeginUpdate as the vis region
  309.  * may be NULL.
  310.  */
  311. RgnHandle rgn;
  312. Rect bounds;
  313. rgn = NewRgn();
  314. TkMacWinBounds(winPtr, &bounds);
  315. RectRgn(rgn, &bounds);
  316. GenerateUpdates(rgn, winPtr);
  317. DisposeRgn(rgn);
  318. return true;
  319.     }
  320. }
  321. /*
  322.  *----------------------------------------------------------------------
  323.  *
  324.  * GenerateUpdates --
  325.  *
  326.  * Given a Macintosh update region and a Tk window this function
  327.  * geneates a X damage event for the window if it is within the
  328.  * update region.  The function will then recursivly have each
  329.  * damaged window generate damage events for its child windows.
  330.  *
  331.  * Results:
  332.  * None.
  333.  *
  334.  * Side effects:
  335.  * Additional events may be place on the Tk event queue.
  336.  *
  337.  *----------------------------------------------------------------------
  338.  */
  339. static void
  340. GenerateUpdates(
  341.     RgnHandle updateRgn,
  342.     TkWindow *winPtr)
  343. {
  344.     TkWindow *childPtr;
  345.     XEvent event;
  346.     Rect bounds;
  347.     TkMacWinBounds(winPtr, &bounds);
  348.     if (bounds.top > (*updateRgn)->rgnBBox.bottom ||
  349.     (*updateRgn)->rgnBBox.top > bounds.bottom ||
  350.     bounds.left > (*updateRgn)->rgnBBox.right ||
  351.     (*updateRgn)->rgnBBox.left > bounds.right ||
  352.     !RectInRgn(&bounds, updateRgn)) {
  353. return;
  354.     }
  355.     event.xany.serial = Tk_Display(winPtr)->request;
  356.     event.xany.send_event = false;
  357.     event.xany.window = Tk_WindowId(winPtr);
  358.     event.xany.display = Tk_Display(winPtr);
  359.     event.type = Expose;
  360.     /* 
  361.      * Compute the bounding box of the area that the damage occured in.
  362.      */
  363.     /*
  364.      * CopyRgn(TkMacVisableClipRgn(winPtr), rgn);
  365.      * TODO: this call doesn't work doing resizes!!!
  366.      */
  367.     RectRgn(gDamageRgn, &bounds);
  368.     SectRgn(gDamageRgn, updateRgn, gDamageRgn);
  369.     OffsetRgn(gDamageRgn, -bounds.left, -bounds.top);
  370.     event.xexpose.x = (**gDamageRgn).rgnBBox.left;
  371.     event.xexpose.y = (**gDamageRgn).rgnBBox.top;
  372.     event.xexpose.width = (**gDamageRgn).rgnBBox.right -
  373. (**gDamageRgn).rgnBBox.left;
  374.     event.xexpose.height = (**gDamageRgn).rgnBBox.bottom -
  375. (**gDamageRgn).rgnBBox.top;
  376.     event.xexpose.count = 0;
  377.     
  378.     Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
  379.     /*
  380.      * Generate updates for the children of this window
  381.      */
  382.      
  383.     for (childPtr = winPtr->childList; childPtr != NULL;
  384.        childPtr = childPtr->nextPtr) {
  385. if (!Tk_IsMapped(childPtr) || Tk_TopWinHierarchy(childPtr)) {
  386.     continue;
  387. }
  388. GenerateUpdates(updateRgn, childPtr);
  389.     }
  390.     
  391.     /*
  392.      * Generate updates for any contained windows
  393.      */
  394.     if (Tk_IsContainer(winPtr)) {
  395. childPtr = TkpGetOtherWindow(winPtr);
  396. if (childPtr != NULL && Tk_IsMapped(childPtr)) {
  397.     GenerateUpdates(updateRgn, childPtr);
  398. }
  399.     
  400. /*
  401.  * NOTE: Here we should handle out of process embedding.
  402.  */
  403.     
  404.     }
  405.     return;
  406. }
  407. /*
  408.  *----------------------------------------------------------------------
  409.  *
  410.  * TkGenerateButtonEvent --
  411.  *
  412.  * Given a global x & y position and the button key status this 
  413.  * procedure generates the appropiate X button event.  It also 
  414.  * handles the state changes needed to implement implicit grabs.
  415.  *
  416.  * Results:
  417.  * True if event(s) are generated - false otherwise.
  418.  *
  419.  * Side effects:
  420.  * Additional events may be place on the Tk event queue.
  421.  * Grab state may also change.
  422.  *
  423.  *----------------------------------------------------------------------
  424.  */
  425. int
  426. TkGenerateButtonEvent(
  427.     int x, /* X location of mouse */
  428.     int y, /* Y location of mouse */
  429.     Window window, /* X Window containing button event. */
  430.     unsigned int state) /* Button Key state suitable for X event */
  431. {
  432.     WindowRef whichWin, frontWin;
  433.     Point where;
  434.     Tk_Window tkwin;
  435.     int dummy;
  436.     TkDisplay *dispPtr;
  437.     /* 
  438.      * ButtonDown events will always occur in the front
  439.      * window.  ButtonUp events, however, may occur anywhere
  440.      * on the screen.  ButtonUp events should only be sent
  441.      * to Tk if in the front window or during an implicit grab.
  442.      */
  443.     where.h = x;
  444.     where.v = y;
  445.     FindWindow(where, &whichWin);
  446.     if (TkMacHaveAppearance() >= 0x110) {
  447.         frontWin = FrontNonFloatingWindow();
  448.     } else {
  449.         frontWin = FrontWindow();
  450.     }
  451.         
  452.     if ((frontWin == NULL) || ((!(TkpIsWindowFloating(whichWin)) && (frontWin != whichWin))
  453.             && gGrabWinPtr == NULL)) {
  454. return false;
  455.     }
  456.     dispPtr = TkGetDisplayList();
  457.     tkwin = Tk_IdToWindow(dispPtr->display, window);
  458.     
  459.     GlobalToLocal(&where);
  460.     if (tkwin != NULL) {
  461. tkwin = Tk_TopCoordsToWindow(tkwin, where.h, where.v, &dummy, &dummy);
  462.     }
  463.     Tk_UpdatePointer(tkwin, x,  y, state);
  464.     return true;
  465. }
  466. /*
  467.  *----------------------------------------------------------------------
  468.  *
  469.  * GenerateActivateEvents --
  470.  *
  471.  * Generate Activate/Deactivate events from a Macintosh Activate 
  472.  * event.  Note, the activate-on-foreground bit must be set in the 
  473.  * SIZE flags to ensure we get Activate/Deactivate in addition to 
  474.  * Susspend/Resume events.
  475.  *
  476.  * Results:
  477.  * Returns true if events were generate.
  478.  *
  479.  * Side effects:
  480.  * Queue events on Tk's event queue.
  481.  *
  482.  *----------------------------------------------------------------------
  483.  */
  484. static int
  485. GenerateActivateEvents(
  486.     EventRecord *eventPtr, /* Incoming Mac event */
  487.     Window window) /* Root X window for event. */
  488. {
  489.     TkWindow *winPtr;
  490.     TkDisplay *dispPtr;
  491.     
  492.     dispPtr = TkGetDisplayList();
  493.     winPtr = (TkWindow *) Tk_IdToWindow(dispPtr->display, window);
  494.     if (winPtr == NULL || winPtr->window == None) {
  495. return false;
  496.     }
  497.     TkGenerateActivateEvents(winPtr,
  498.     (eventPtr->modifiers & activeFlag) ? 1 : 0);
  499.     return true;
  500. }
  501. /*
  502.  *----------------------------------------------------------------------
  503.  *
  504.  * XSetInputFocus --
  505.  *
  506.  * Change the focus window for the application.
  507.  *
  508.  * Results:
  509.  * None.
  510.  *
  511.  * Side effects:
  512.  * None.
  513.  *
  514.  *----------------------------------------------------------------------
  515.  */
  516. void
  517. XSetInputFocus(
  518.     Display* display,
  519.     Window focus,
  520.     int revert_to,
  521.     Time time)
  522. {
  523.     /*
  524.      * Don't need to do a thing.  Tk manages the focus for us.
  525.      */
  526. }
  527. /*
  528.  *----------------------------------------------------------------------
  529.  *
  530.  * TkpChangeFocus --
  531.  *
  532.  * This procedure is a stub on the Mac because we always own the
  533.  * focus if we are a front most application.
  534.  *
  535.  * Results:
  536.  * The return value is the serial number of the command that
  537.  * changed the focus.  It may be needed by the caller to filter
  538.  * out focus change events that were queued before the command.
  539.  * If the procedure doesn't actually change the focus then
  540.  * it returns 0.
  541.  *
  542.  * Side effects:
  543.  * None.
  544.  *
  545.  *----------------------------------------------------------------------
  546.  */
  547. int
  548. TkpChangeFocus(winPtr, force)
  549.     TkWindow *winPtr; /* Window that is to receive the X focus. */
  550.     int force; /* Non-zero means claim the focus even
  551.  * if it didn't originally belong to
  552.  * topLevelPtr's application. */
  553. {
  554.     /*
  555.      * We don't really need to do anything on the Mac.  Tk will
  556.      * keep all this state for us.
  557.      */
  558.     if (winPtr->atts.override_redirect) {
  559. return 0;
  560.     }
  561.     /*
  562.      * Remember the current serial number for the X server and issue
  563.      * a dummy server request.  This marks the position at which we
  564.      * changed the focus, so we can distinguish FocusIn and FocusOut
  565.      * events on either side of the mark.
  566.      */
  567.     return NextRequest(winPtr->display);
  568. }
  569. /*
  570.  *----------------------------------------------------------------------
  571.  *
  572.  * GenerateFocusEvent --
  573.  *
  574.  * Generate FocusIn/FocusOut events from a Macintosh Activate 
  575.  * event.  Note, the activate-on-foreground bit must be set in 
  576.  * the SIZE flags to ensure we get Activate/Deactivate in addition 
  577.  * to Susspend/Resume events.
  578.  *
  579.  * Results:
  580.  * Returns true if events were generate.
  581.  *
  582.  * Side effects:
  583.  * Queue events on Tk's event queue.
  584.  *
  585.  *----------------------------------------------------------------------
  586.  */
  587. static int
  588. GenerateFocusEvent(
  589.     EventRecord *eventPtr, /* Incoming Mac event */
  590.     Window window) /* Root X window for event. */
  591. {
  592.     XEvent event;
  593.     Tk_Window tkwin;
  594.     TkDisplay *dispPtr;
  595.     
  596.     dispPtr = TkGetDisplayList();
  597.     tkwin = Tk_IdToWindow(dispPtr->display, window);
  598.     if (tkwin == NULL) {
  599. return false;
  600.     }
  601.     /* 
  602.      * Generate FocusIn and FocusOut events.  This event
  603.      * is only sent to the toplevel window.
  604.      */
  605.     if (eventPtr->modifiers & activeFlag) {
  606. event.xany.type = FocusIn;
  607.     } else {
  608. event.xany.type = FocusOut;
  609.     }
  610.     event.xany.serial = dispPtr->display->request;
  611.     event.xany.send_event = False;
  612.     event.xfocus.display = dispPtr->display;
  613.     event.xfocus.window = window;
  614.     event.xfocus.mode = NotifyNormal;
  615.     event.xfocus.detail = NotifyDetailNone;
  616.     Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
  617.     return true;
  618. }
  619. /*
  620.  *----------------------------------------------------------------------
  621.  *
  622.  * GenerateKeyEvent --
  623.  *
  624.  * Given Macintosh keyUp, keyDown & autoKey events this function
  625.  * generates the appropiate X key events.  The window that is passed
  626.  * should represent the frontmost window - which will recieve the
  627.  * event.
  628.  *
  629.  * Results:
  630.  * True if event(s) are generated - false otherwise.
  631.  *
  632.  * Side effects:
  633.  * Additional events may be place on the Tk event queue.
  634.  *
  635.  *----------------------------------------------------------------------
  636.  */
  637. static int
  638. GenerateKeyEvent(
  639.     EventRecord *eventPtr, /* Incoming Mac event */
  640.     Window window, /* Root X window for event. */
  641.     UInt32 savedKeyCode) /* If non-zero, this is a lead byte which
  642.       * should be combined with the character
  643.       * in this event to form one multi-byte 
  644.       * character. */
  645. {
  646.     Point where;
  647.     Tk_Window tkwin;
  648.     XEvent event;
  649.     unsigned char byte;
  650.     char buf[16];
  651.     TkDisplay *dispPtr;
  652.     
  653.     /*
  654.      * The focus must be in the FrontWindow on the Macintosh.
  655.      * We then query Tk to determine the exact Tk window
  656.      * that owns the focus.
  657.      */
  658.     dispPtr = TkGetDisplayList();
  659.     tkwin = Tk_IdToWindow(dispPtr->display, window);
  660.     
  661.     if (tkwin == NULL) {
  662.         return false;
  663.     }
  664.     tkwin = (Tk_Window) ((TkWindow *) tkwin)->dispPtr->focusPtr;
  665.     if (tkwin == NULL) {
  666. return false;
  667.     }
  668.     byte = (unsigned char) (eventPtr->message & charCodeMask);
  669.     if ((savedKeyCode == 0) && 
  670.             (Tcl_ExternalToUtf(NULL, NULL, (char *) &byte, 1, 0, NULL, 
  671.                  buf, sizeof(buf), NULL, NULL, NULL) != TCL_OK)) {
  672.         /*
  673.          * This event specifies a lead byte.  Wait for the second byte
  674.          * to come in before sending the XEvent.
  675.          */
  676.          
  677.         return false;
  678.     }   
  679.     where.v = eventPtr->where.v;
  680.     where.h = eventPtr->where.h;
  681.     event.xany.send_event = False;
  682.     event.xkey.same_screen = true;
  683.     event.xkey.subwindow = None;
  684.     event.xkey.time = TkpGetMS();
  685.     event.xkey.x_root = where.h;
  686.     event.xkey.y_root = where.v;
  687.     GlobalToLocal(&where);
  688.     Tk_TopCoordsToWindow(tkwin, where.h, where.v, 
  689.     &event.xkey.x, &event.xkey.y);
  690.     
  691.     event.xkey.keycode = byte |
  692.             ((savedKeyCode & charCodeMask) << 8) |
  693.             ((eventPtr->message & keyCodeMask) << 8);
  694.     event.xany.serial = Tk_Display(tkwin)->request;
  695.     event.xkey.window = Tk_WindowId(tkwin);
  696.     event.xkey.display = Tk_Display(tkwin);
  697.     event.xkey.root = XRootWindow(Tk_Display(tkwin), 0);
  698.     event.xkey.state = TkMacButtonKeyState();
  699.     if (eventPtr->what == keyDown) {
  700. event.xany.type = KeyPress;
  701. Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
  702.     } else if (eventPtr->what == keyUp) {
  703. event.xany.type = KeyRelease;
  704. Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
  705.     } else {
  706. /*
  707.  * Autokey events send multiple XKey events.
  708.  *
  709.  * Note: the last KeyRelease will always be missed with
  710.  * this scheme.  However, most Tk scripts don't look for
  711.  * KeyUp events so we should be OK.
  712.  */
  713. event.xany.type = KeyRelease;
  714. Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
  715. event.xany.type = KeyPress;
  716. Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
  717.     }
  718.     return true;
  719. }
  720. /*
  721.  *----------------------------------------------------------------------
  722.  *
  723.  * GeneratePollingEvents --
  724.  *
  725.  * This function polls the mouse position and generates X Motion,
  726.  * Enter & Leave events.  The cursor is also updated at this
  727.  * time.
  728.  *
  729.  * Results:
  730.  * True if event(s) are generated - false otherwise.  
  731.  *
  732.  * Side effects:
  733.  * Additional events may be place on the Tk event queue.
  734.  * The cursor may be changed.
  735.  *
  736.  *----------------------------------------------------------------------
  737.  */
  738. static int
  739. GeneratePollingEvents()
  740. {
  741.     Tk_Window tkwin, rootwin;
  742.     Window window;
  743.     WindowRef whichWindow, frontWin, frontNonFloating;
  744.     Point whereLocal, whereGlobal;
  745.     Boolean inContentRgn;
  746.     short part;
  747.     int local_x, local_y;
  748.     int generatedEvents = false;
  749.     TkDisplay *dispPtr;
  750.     /*
  751.      * First we get the current mouse position and determine
  752.      * what Tk window the mouse is over (if any).
  753.      */
  754.     frontWin = FrontWindow();
  755.     if (frontWin == NULL) {
  756. return false;
  757.     }
  758.     SetPort((GrafPort *) frontWin);
  759.    
  760.     GetMouse(&whereLocal);
  761.     whereGlobal = whereLocal;
  762.     LocalToGlobal(&whereGlobal);
  763.     part = FindWindow(whereGlobal, &whichWindow);
  764.     inContentRgn = (part == inContent || part == inGrow);
  765.     if (TkMacHaveAppearance() >= 0x110) {
  766.         /* 
  767.          * If the mouse is over the front non-floating window, then we
  768.          * need to set the local coordinates relative to that window
  769.          * rather than a possibly floating window above it.
  770.          */
  771.          
  772.         frontNonFloating = FrontNonFloatingWindow();
  773.         if (whichWindow == frontNonFloating 
  774.                 && (whichWindow != frontWin)) {
  775.             SetPort((GrafPort *) frontNonFloating);
  776.             whereLocal = whereGlobal;
  777.             GlobalToLocal(&whereLocal);
  778.         }
  779.     } else {
  780.         frontNonFloating = frontWin;
  781.     }
  782.     if ((!TkpIsWindowFloating(whichWindow) && (frontNonFloating != whichWindow)) || !inContentRgn) {
  783. tkwin = NULL;
  784.     } else {
  785. window = TkMacGetXWindow(whichWindow);
  786. dispPtr = TkGetDisplayList();
  787. rootwin = Tk_IdToWindow(dispPtr->display, window);
  788. if (rootwin == NULL) {
  789.     tkwin = NULL;
  790. } else {
  791.     tkwin = Tk_TopCoordsToWindow(rootwin, whereLocal.h, whereLocal.v, 
  792.     &local_x, &local_y);
  793. }
  794.     }
  795.     
  796.     /*
  797.      * The following call will generate the appropiate X events and
  798.      * adjust any state that Tk must remember.
  799.      */
  800.     if ((tkwin == NULL) && (gGrabWinPtr != NULL)) {
  801. tkwin = gGrabWinPtr;
  802.     }
  803.     Tk_UpdatePointer(tkwin, whereGlobal.h,  whereGlobal.v,
  804.     TkMacButtonKeyState());
  805.     
  806.     /*
  807.      * Finally, we make sure the proper cursor is installed.  The installation
  808.      * is polled to 1) make our resize hack work, and 2) make sure we have the 
  809.      * proper cursor even if someone else changed the cursor out from under
  810.      * us.
  811.      */
  812.     if ((gGrabWinPtr == NULL) && (part == inGrow) && 
  813.     TkMacResizable((TkWindow *) tkwin) && 
  814.     (TkMacGetScrollbarGrowWindow((TkWindow *) tkwin) == NULL)) {
  815. TkMacInstallCursor(1);
  816.     } else {
  817. TkMacInstallCursor(0);
  818.     }
  819.     return true;
  820. }
  821. /*
  822.  *----------------------------------------------------------------------
  823.  *
  824.  * GeneratePollingEvents2 --
  825.  *
  826.  * This function polls the mouse position and generates X Motion,
  827.  * Enter & Leave events.  The cursor is also updated at this
  828.  * time.  NOTE: this version is for Netscape!!!
  829.  *
  830.  * Results:
  831.  * True if event(s) are generated - false otherwise.  
  832.  *
  833.  * Side effects:
  834.  * Additional events may be place on the Tk event queue.
  835.  * The cursor may be changed.
  836.  *
  837.  *----------------------------------------------------------------------
  838.  */
  839. static int
  840. GeneratePollingEvents2(
  841.     Window window,
  842.     int adjustCursor)
  843. {
  844.     Tk_Window tkwin, rootwin;
  845.     WindowRef whichwindow, frontWin;
  846.     Point whereLocal, whereGlobal;
  847.     int local_x, local_y;
  848.     int generatedEvents = false;
  849.     Rect bounds;
  850.     TkDisplay *dispPtr;
  851.     
  852.     /*
  853.      * First we get the current mouse position and determine
  854.      * what Tk window the mouse is over (if any).
  855.      */
  856.     frontWin = FrontWindow();
  857.     if (frontWin == NULL) {
  858. return false;
  859.     }
  860.     SetPort((GrafPort *) frontWin);
  861.    
  862.     GetMouse(&whereLocal);
  863.     whereGlobal = whereLocal;
  864.     LocalToGlobal(&whereGlobal);
  865.     /*
  866.      * Determine if we are in a Tk window or not.
  867.      */
  868.     whichwindow = (WindowRef) TkMacGetDrawablePort(window);
  869.     if (whichwindow != frontWin) {
  870. tkwin = NULL;
  871.     } else {
  872.         dispPtr = TkGetDisplayList();
  873. rootwin = Tk_IdToWindow(dispPtr->display, window);
  874. TkMacWinBounds((TkWindow *) rootwin, &bounds);
  875. if (!PtInRect(whereLocal, &bounds)) {
  876.     tkwin = NULL;
  877. } else {
  878.     tkwin = Tk_TopCoordsToWindow(rootwin, whereLocal.h, whereLocal.v, 
  879.     &local_x, &local_y);
  880. }
  881.     }
  882.     
  883.     /*
  884.      * The following call will generate the appropiate X events and
  885.      * adjust any state that Tk must remember.
  886.      */
  887.     if ((tkwin == NULL) && (gGrabWinPtr != NULL)) {
  888. tkwin = gGrabWinPtr;
  889.     }
  890.     Tk_UpdatePointer(tkwin, whereGlobal.h,  whereGlobal.v,
  891.     TkMacButtonKeyState());
  892.     
  893.     /*
  894.      * Finally, we make sure the proper cursor is installed.  The installation
  895.      * is polled to 1) make our resize hack work, and 2) make sure we have the 
  896.      * proper cursor even if someone else changed the cursor out from under
  897.      * us.
  898.      */
  899.      
  900.     if (adjustCursor) {
  901.         TkMacInstallCursor(0);
  902.     }
  903.     return true;
  904. }
  905. /*
  906.  *----------------------------------------------------------------------
  907.  *
  908.  * TkMacButtonKeyState --
  909.  *
  910.  * Returns the current state of the button & modifier keys.
  911.  *
  912.  * Results:
  913.  * A bitwise inclusive OR of a subset of the following:
  914.  * Button1Mask, ShiftMask, LockMask, ControlMask, Mod?Mask,
  915.  * Mod?Mask.
  916.  *
  917.  * Side effects:
  918.  * None.
  919.  *
  920.  *----------------------------------------------------------------------
  921.  */
  922. unsigned int
  923. TkMacButtonKeyState()
  924. {
  925.     unsigned int state = 0;
  926.     KeyMap theKeys;
  927.     if (Button() & !gEatButtonUp) {
  928. state |= Button1Mask;
  929.     }
  930.     GetKeys(theKeys);
  931.     if (theKeys[1] & 2) {
  932. state |= LockMask;
  933.     }
  934.     if (theKeys[1] & 1) {
  935. state |= ShiftMask;
  936.     }
  937.     if (theKeys[1] & 8) {
  938. state |= ControlMask;
  939.     }
  940.     if (theKeys[1] & 32768) {
  941. state |= Mod1Mask; /* command key */
  942.     }
  943.     if (theKeys[1] & 4) {
  944. state |= Mod2Mask; /* option key */
  945.     }
  946.     return state;
  947. }
  948. /*
  949.  *----------------------------------------------------------------------
  950.  *
  951.  * XGrabKeyboard --
  952.  *
  953.  * Simulates a keyboard grab by setting the focus.
  954.  *
  955.  * Results:
  956.  * Always returns GrabSuccess.
  957.  *
  958.  * Side effects:
  959.  * Sets the keyboard focus to the specified window.
  960.  *
  961.  *----------------------------------------------------------------------
  962.  */
  963. int
  964. XGrabKeyboard(
  965.     Display* display,
  966.     Window grab_window,
  967.     Bool owner_events,
  968.     int pointer_mode,
  969.     int keyboard_mode,
  970.     Time time)
  971. {
  972.     gKeyboardWinPtr = Tk_IdToWindow(display, grab_window);
  973.     return GrabSuccess;
  974. }
  975. /*
  976.  *----------------------------------------------------------------------
  977.  *
  978.  * XUngrabKeyboard --
  979.  *
  980.  * Releases the simulated keyboard grab.
  981.  *
  982.  * Results:
  983.  * None.
  984.  *
  985.  * Side effects:
  986.  * Sets the keyboard focus back to the value before the grab.
  987.  *
  988.  *----------------------------------------------------------------------
  989.  */
  990. void
  991. XUngrabKeyboard(
  992.     Display* display,
  993.     Time time)
  994. {
  995.     gKeyboardWinPtr = NULL;
  996. }
  997. /*
  998.  *----------------------------------------------------------------------
  999.  *
  1000.  * XQueryPointer --
  1001.  *
  1002.  * Check the current state of the mouse.  This is not a complete
  1003.  * implementation of this function.  It only computes the root
  1004.  * coordinates and the current mask.
  1005.  *
  1006.  * Results:
  1007.  * Sets root_x_return, root_y_return, and mask_return.  Returns
  1008.  * true on success.
  1009.  *
  1010.  * Side effects:
  1011.  * None.
  1012.  *
  1013.  *----------------------------------------------------------------------
  1014.  */
  1015. Bool
  1016. XQueryPointer(
  1017.     Display* display,
  1018.     Window w,
  1019.     Window* root_return,
  1020.     Window* child_return,
  1021.     int* root_x_return,
  1022.     int* root_y_return,
  1023.     int* win_x_return,
  1024.     int* win_y_return,
  1025.     unsigned int* mask_return)
  1026. {
  1027.     Point where;
  1028.     GetMouse(&where);
  1029.     LocalToGlobal(&where);
  1030.     *root_x_return = where.h;
  1031.     *root_y_return = where.v;
  1032.     *mask_return = TkMacButtonKeyState();    
  1033.     return True;
  1034. }
  1035. /*
  1036.  *----------------------------------------------------------------------
  1037.  *
  1038.  * TkMacGenerateTime --
  1039.  *
  1040.  * Returns the total number of ticks from startup  This function
  1041.  * is used to generate the time of generated X events.
  1042.  *
  1043.  * Results:
  1044.  * Returns the current time (ticks from startup).
  1045.  *
  1046.  * Side effects:
  1047.  * None.
  1048.  *
  1049.  *----------------------------------------------------------------------
  1050.  */
  1051. Time
  1052. TkMacGenerateTime()
  1053. {
  1054.     return (Time) LMGetTicks();
  1055. }
  1056. /*
  1057.  *----------------------------------------------------------------------
  1058.  *
  1059.  * TkMacConvertEvent --
  1060.  *
  1061.  * This function converts a Macintosh event into zero or more
  1062.  * Tcl events.
  1063.  *
  1064.  * Results:
  1065.  * Returns 1 if event added to Tcl queue, 0 otherwse.
  1066.  *
  1067.  * Side effects:
  1068.  * May add events to Tcl's event queue.
  1069.  *
  1070.  *----------------------------------------------------------------------
  1071.  */
  1072. int
  1073. TkMacConvertEvent(
  1074.     EventRecord *eventPtr)
  1075. {
  1076.     WindowRef whichWindow;
  1077.     Window window;
  1078.     int eventFound = false;
  1079.     static UInt32 savedKeyCode;
  1080.     
  1081.     switch (eventPtr->what) {
  1082. case nullEvent:
  1083. case adjustCursorEvent:
  1084.     if (GeneratePollingEvents()) {
  1085. eventFound = true;
  1086.     }
  1087.     break;
  1088. case updateEvt:
  1089.     whichWindow = (WindowRef)eventPtr->message;
  1090.     window = TkMacGetXWindow(whichWindow);
  1091.     if (GenerateUpdateEvent(eventPtr, window)) {
  1092. eventFound = true;
  1093.     }
  1094.     break;
  1095. case mouseDown:
  1096. case mouseUp:
  1097.     FindWindow(eventPtr->where, &whichWindow);
  1098.     window = TkMacGetXWindow(whichWindow);
  1099.     if (WindowManagerMouse(eventPtr, window)) {
  1100. eventFound = true;
  1101.     }
  1102.     break;
  1103. case autoKey:
  1104. case keyDown:
  1105.     /*
  1106.      * Handle menu-key events here.  If it is *not*
  1107.      * a menu key - just fall through to handle as a
  1108.      * normal key event.
  1109.      */
  1110.     if ((eventPtr->modifiers & cmdKey) == cmdKey) {
  1111. long menuResult;
  1112. int oldMode;
  1113. oldMode = Tcl_SetServiceMode(TCL_SERVICE_ALL);
  1114. menuResult = MenuKey(eventPtr->message & charCodeMask);
  1115. Tcl_SetServiceMode(oldMode);
  1116. if (HiWord(menuResult) != 0) {
  1117.     TkMacHandleMenuSelect(menuResult, false);
  1118.     break;
  1119. }
  1120.     }
  1121.     /* fall through */
  1122.     
  1123. case keyUp:
  1124.     if (TkMacHaveAppearance() >= 0x110) {
  1125.     whichWindow = FrontNonFloatingWindow();
  1126.     } else {
  1127.         whichWindow = FrontWindow();
  1128.     }
  1129.     if (whichWindow == NULL) {
  1130.         /*
  1131.          * This happens if we get a key event before Tk has had a
  1132.          * chance to actually create and realize ".", if they type
  1133.          * when "." is withdrawn(!), or between the time "." is 
  1134.          * destroyed and the app exits.
  1135.          */
  1136.          
  1137.         return false;
  1138.     }
  1139.     window = TkMacGetXWindow(whichWindow);
  1140.     if (GenerateKeyEvent(eventPtr, window, savedKeyCode) == 0) {
  1141.         savedKeyCode = eventPtr->message;
  1142.         return false;
  1143.     }
  1144.     eventFound = true;
  1145.     break;
  1146.          
  1147. case activateEvt:
  1148.     window = TkMacGetXWindow((WindowRef) eventPtr->message);
  1149.     eventFound |= GenerateActivateEvents(eventPtr, window);
  1150.     eventFound |= GenerateFocusEvent(eventPtr, window);
  1151.     break;
  1152. case getFocusEvent:
  1153.     eventPtr->modifiers |= activeFlag;
  1154.     window = TkMacGetXWindow((WindowRef) eventPtr->message);
  1155.     eventFound |= GenerateFocusEvent(eventPtr, window);
  1156.     break;
  1157. case loseFocusEvent:
  1158.     eventPtr->modifiers &= ~activeFlag;
  1159.     window = TkMacGetXWindow((WindowRef) eventPtr->message);
  1160.     eventFound |= GenerateFocusEvent(eventPtr, window);
  1161.     break;
  1162. case kHighLevelEvent:
  1163.     TkMacDoHLEvent(eventPtr);
  1164.     /* TODO: should return true if events were placed on event queue. */
  1165.     break;
  1166. case osEvt:
  1167.     /*
  1168.      * Do clipboard conversion.
  1169.      */
  1170.     switch ((eventPtr->message & osEvtMessageMask) >> 24) {
  1171. case mouseMovedMessage:
  1172.     if (GeneratePollingEvents()) {
  1173. eventFound = true;
  1174.     }
  1175.     break;
  1176. case suspendResumeMessage:
  1177.     if (!(eventPtr->message & resumeFlag)) {
  1178. TkSuspendClipboard();
  1179.     }
  1180.     tkMacAppInFront = (eventPtr->message & resumeFlag);
  1181.     if (TkMacHaveAppearance() >= 0x110) {
  1182.         if (tkMacAppInFront) {
  1183.             ShowFloatingWindows();
  1184.         } else {
  1185.             HideFloatingWindows();
  1186.         }
  1187.     }
  1188.     break;
  1189.     }
  1190.     break;
  1191. case diskEvt:
  1192.     /* 
  1193.      * Disk insertion. 
  1194.      */
  1195.     if (HiWord(eventPtr->message) != noErr) {
  1196. Point pt;
  1197. DILoad();
  1198. pt.v = pt.h = 120;   /* parameter ignored in sys 7 */
  1199. DIBadMount(pt, eventPtr->message);
  1200. DIUnload();
  1201.     }
  1202.     break;
  1203.     }
  1204.     
  1205.     savedKeyCode = 0;
  1206.     return eventFound;
  1207. }
  1208. /*
  1209.  *----------------------------------------------------------------------
  1210.  *
  1211.  * TkMacConvertTkEvent --
  1212.  *
  1213.  * This function converts a Macintosh event into zero or more
  1214.  * Tcl events.  It is intended for use in Netscape-style embedding.
  1215.  *
  1216.  * Results:
  1217.  * Returns 1 if event added to Tcl queue, 0 otherwse.
  1218.  *
  1219.  * Side effects:
  1220.  * May add events to Tcl's event queue.
  1221.  *
  1222.  *----------------------------------------------------------------------
  1223.  */
  1224. int
  1225. TkMacConvertTkEvent(
  1226.     EventRecord *eventPtr,
  1227.     Window window)
  1228. {
  1229.     int eventFound = false;
  1230.     Point where;
  1231.     static UInt32 savedKeyCode;
  1232.     
  1233.     /*
  1234.      * By default, assume it is legal for us to set the cursor 
  1235.      */
  1236.      
  1237.     Tk_MacTkOwnsCursor(1);
  1238.     
  1239.     switch (eventPtr->what) {
  1240. case nullEvent:
  1241.         /*
  1242.          * We get NULL events only when the cursor is NOT over
  1243.  * the plugin.  Otherwise we get updateCursor events.
  1244.  * We will not generate polling events or move the cursor
  1245.  * in this case.
  1246.          */
  1247.             
  1248.     eventFound = false;
  1249.     break;
  1250. case adjustCursorEvent:
  1251.     if (GeneratePollingEvents2(window, 1)) {
  1252. eventFound = true;
  1253.     }
  1254.     break;
  1255. case updateEvt:
  1256.         /*
  1257.          * It is possibly not legal for us to set the cursor 
  1258.          */
  1259.      
  1260.             Tk_MacTkOwnsCursor(0);
  1261.     if (GenerateUpdateEvent(eventPtr, window)) {
  1262. eventFound = true;
  1263.     }
  1264.     break;
  1265. case mouseDown:
  1266. case mouseUp:
  1267.     GetMouse(&where);
  1268.     LocalToGlobal(&where);
  1269.     eventFound |= TkGenerateButtonEvent(where.h, where.v, 
  1270. window, TkMacButtonKeyState());
  1271.     break;
  1272. case autoKey:
  1273. case keyDown:
  1274.     /*
  1275.      * Handle menu-key events here.  If it is *not*
  1276.      * a menu key - just fall through to handle as a
  1277.      * normal key event.
  1278.      */
  1279.     if ((eventPtr->modifiers & cmdKey) == cmdKey) {
  1280. long menuResult = MenuKey(eventPtr->message & charCodeMask);
  1281. if (HiWord(menuResult) != 0) {
  1282.     TkMacHandleMenuSelect(menuResult, false);
  1283.     break;
  1284. }
  1285.     }
  1286.     /* fall through. */
  1287.     
  1288. case keyUp:
  1289.     if (GenerateKeyEvent(eventPtr, window, savedKeyCode) == 0) {
  1290.         savedKeyCode = eventPtr->message;
  1291.         return false;
  1292.     }         
  1293.     eventFound = true;
  1294.     break;
  1295.     
  1296. case activateEvt:
  1297.         /*
  1298.          * It is probably not legal for us to set the cursor
  1299.  * here, since we don't know where the mouse is in the
  1300.  * window that is being activated.
  1301.          */
  1302.      
  1303.             Tk_MacTkOwnsCursor(0);
  1304.     eventFound |= GenerateActivateEvents(eventPtr, window);
  1305.     eventFound |= GenerateFocusEvent(eventPtr, window);
  1306.     break;
  1307. case getFocusEvent:
  1308.     eventPtr->modifiers |= activeFlag;
  1309.     eventFound |= GenerateFocusEvent(eventPtr, window);
  1310.     break;
  1311. case loseFocusEvent:
  1312.     eventPtr->modifiers &= ~activeFlag;
  1313.     eventFound |= GenerateFocusEvent(eventPtr, window);
  1314.     break;
  1315. case kHighLevelEvent:
  1316.     TkMacDoHLEvent(eventPtr);
  1317.     /* TODO: should return true if events were placed on event queue. */
  1318.     break;
  1319. case osEvt:
  1320.     /*
  1321.      * Do clipboard conversion.
  1322.      */
  1323.     switch ((eventPtr->message & osEvtMessageMask) >> 24) {
  1324.         /*
  1325.          * It is possibly not legal for us to set the cursor.
  1326.          * Netscape sends us these events all the time... 
  1327.          */
  1328.      
  1329.                 Tk_MacTkOwnsCursor(0);
  1330.         
  1331. case mouseMovedMessage:
  1332.     /* if (GeneratePollingEvents2(window, 0)) {
  1333. eventFound = true;
  1334.     }  NEXT LINE IS TEMPORARY */
  1335.     eventFound = false;
  1336.     break;
  1337. case suspendResumeMessage:
  1338.     if (!(eventPtr->message & resumeFlag)) {
  1339. TkSuspendClipboard();
  1340.     }
  1341.     tkMacAppInFront = (eventPtr->message & resumeFlag);
  1342.     if (TkMacHaveAppearance() >= 0x110) {
  1343.         if (tkMacAppInFront) {
  1344.             ShowFloatingWindows();
  1345.         } else {
  1346.             HideFloatingWindows();
  1347.         }
  1348.     }
  1349.     break;
  1350.     }
  1351.     break;
  1352. case diskEvt:
  1353.     /* 
  1354.      * Disk insertion. 
  1355.      */
  1356.     if (HiWord(eventPtr->message) != noErr) {
  1357. Point pt;
  1358. DILoad();
  1359. pt.v = pt.h = 120;   /* parameter ignored in sys 7 */
  1360. DIBadMount(pt, eventPtr->message);
  1361. DIUnload();
  1362.     }
  1363.     break;
  1364.     }
  1365.     savedKeyCode = 0;    
  1366.     return eventFound;
  1367. }
  1368. /*
  1369.  *----------------------------------------------------------------------
  1370.  *
  1371.  * CheckEventsAvail --
  1372.  *
  1373.  * Checks to see if events are available on the Macintosh queue.
  1374.  * This function looks for both queued events (eg. key & button)
  1375.  * and generated events (update).
  1376.  *
  1377.  * Results:
  1378.  * True is events exist, false otherwise.
  1379.  *
  1380.  * Side effects:
  1381.  * None.
  1382.  *
  1383.  *----------------------------------------------------------------------
  1384.  */
  1385. static int
  1386. CheckEventsAvail()
  1387. {
  1388.     QHdrPtr evPtr;
  1389.     WindowPeek macWinPtr;
  1390.     
  1391.     evPtr = GetEvQHdr();
  1392.     if (evPtr->qHead != NULL) {
  1393. return true;
  1394.     }
  1395.     
  1396.     macWinPtr = (WindowPeek) FrontWindow();
  1397.     while (macWinPtr != NULL) {
  1398. if (!EmptyRgn(macWinPtr->updateRgn)) {
  1399.     return true;
  1400. }
  1401. macWinPtr = macWinPtr->nextWindow;
  1402.     }
  1403.     return false;
  1404. }
  1405. /*
  1406.  *----------------------------------------------------------------------
  1407.  *
  1408.  * TkpSetCapture --
  1409.  *
  1410.  * This function captures the mouse so that all future events
  1411.  * will be reported to this window, even if the mouse is outside
  1412.  * the window.  If the specified window is NULL, then the mouse
  1413.  * is released. 
  1414.  *
  1415.  * Results:
  1416.  * None.
  1417.  *
  1418.  * Side effects:
  1419.  * Sets the capture flag and captures the mouse.
  1420.  *
  1421.  *----------------------------------------------------------------------
  1422.  */
  1423. void
  1424. TkpSetCapture(
  1425.     TkWindow *winPtr) /* Capture window, or NULL. */
  1426. {
  1427.     while ((winPtr != NULL) && !Tk_TopWinHierarchy(winPtr)) {
  1428. winPtr = winPtr->parentPtr;
  1429.     }
  1430.     gGrabWinPtr = (Tk_Window) winPtr;
  1431. }
  1432. /*
  1433.  *----------------------------------------------------------------------
  1434.  *
  1435.  * TkMacWindowOffset --
  1436.  *
  1437.  * Determines the x and y offset from the orgin of the toplevel
  1438.  * window dressing (the structure region, ie. title bar) and the
  1439.  * orgin of the content area.
  1440.  *
  1441.  * Results:
  1442.  * The x & y offset in pixels.
  1443.  *
  1444.  * Side effects:
  1445.  * None.
  1446.  *
  1447.  *----------------------------------------------------------------------
  1448.  */
  1449. void
  1450. TkMacWindowOffset(
  1451.     WindowRef wRef,
  1452.     int *xOffset,
  1453.     int *yOffset)
  1454. {
  1455.     OSErr err = noErr;
  1456.     WindowPeek wPeek = (WindowPeek) wRef;
  1457.     RgnHandle strucRgn = wPeek->strucRgn;
  1458.     RgnHandle contRgn = wPeek->contRgn;
  1459.     Rect strucRect, contRect;
  1460.     if (!EmptyRgn(strucRgn) && !EmptyRgn(contRgn)) {
  1461. strucRect = (**strucRgn).rgnBBox;
  1462. contRect = (**contRgn).rgnBBox;
  1463.     } else {
  1464. /*
  1465.  * The current window's regions are not up to date.
  1466.  * Probably because the window isn't visable.  What we
  1467.  * will do is save the old regions, have the window calculate
  1468.  * what the regions should be, and then restore it self.
  1469.  */
  1470. strucRgn = NewRgn( );
  1471. contRgn = NewRgn( );
  1472. if (!strucRgn || !contRgn) {
  1473.     err = MemError( );
  1474.     
  1475. } else if (TkMacHaveAppearance()) {
  1476.     GetWindowRegion(wRef, kWindowStructureRgn, strucRgn);
  1477.     GetWindowRegion(wRef, kWindowContentRgn, contRgn);
  1478.     strucRect = (**strucRgn).rgnBBox;
  1479.     contRect = (**contRgn).rgnBBox;
  1480. } else {
  1481.     CopyRgn(wPeek->strucRgn, strucRgn);
  1482.     CopyRgn(wPeek->contRgn, contRgn);
  1483.     if (!(err = TellWindowDefProcToCalcRegions(wRef))) {
  1484. strucRect = (**(wPeek->strucRgn)).rgnBBox;
  1485. contRect = (**(wPeek->contRgn)).rgnBBox;
  1486.     }
  1487.     CopyRgn(strucRgn, wPeek->strucRgn);
  1488.     CopyRgn(contRgn, wPeek->contRgn);
  1489. }
  1490. if (contRgn) {
  1491.     DisposeRgn(contRgn);
  1492. }
  1493. if (strucRgn) {
  1494.     DisposeRgn(strucRgn);
  1495. }
  1496.     }
  1497.     if (!err) {
  1498. *xOffset = contRect.left - strucRect.left;
  1499. *yOffset = contRect.top - strucRect.top;
  1500.     } else {
  1501. *xOffset = 0;
  1502. *yOffset = 0;
  1503.     }
  1504.     return;
  1505. }
  1506. /*
  1507.  *----------------------------------------------------------------------
  1508.  *
  1509.  * TellWindowDefProcToCalcRegions --
  1510.  *
  1511.  * Force a Macintosh window to recalculate it's content and
  1512.  * structure regions.
  1513.  *
  1514.  * Results:
  1515.  * An OS error.
  1516.  *
  1517.  * Side effects:
  1518.  * The windows content and structure regions may be updated.
  1519.  *
  1520.  *----------------------------------------------------------------------
  1521.  */
  1522. static OSErr 
  1523. TellWindowDefProcToCalcRegions(
  1524.     WindowRef wRef)
  1525. {
  1526.     OSErr err = noErr;
  1527.     SInt8 hState;
  1528.     Handle wdef = ((WindowPeek) wRef)->windowDefProc;
  1529.     /*
  1530.      * Load and lock the window definition procedure for
  1531.      * the window.
  1532.      */
  1533.     hState = HGetState(wdef);
  1534.     if (!(err = MemError())) {
  1535. LoadResource(wdef);
  1536. if (!(err = ResError())) {
  1537.     MoveHHi(wdef);
  1538.     err = MemError();
  1539.     if (err == memLockedErr) {
  1540.         err = noErr;
  1541.     } else if (!err) {
  1542. HLock(wdef);
  1543. err = MemError();
  1544.     }
  1545. }
  1546.     }
  1547.     
  1548.     /*
  1549.      * Assuming there are no errors we now call the window definition 
  1550.      * procedure to tell it to calculate the regions for the window.
  1551.      */
  1552.     if (err == noErr) {
  1553.   (void) CallWindowDefProc((UniversalProcPtr) *wdef,
  1554. GetWVariant(wRef), wRef, wCalcRgns, 0);
  1555. HSetState(wdef, hState);
  1556. if (!err) {
  1557.      err = MemError();
  1558. }
  1559.     }
  1560.     return err;
  1561. }
  1562. /*
  1563.  *----------------------------------------------------------------------
  1564.  *
  1565.  * BringWindowForward --
  1566.  *
  1567.  * Bring this background window to the front.  We also set state
  1568.  * so Tk thinks the button is currently up.
  1569.  *
  1570.  * Results:
  1571.  * None.
  1572.  *
  1573.  * Side effects:
  1574.  * The window is brought forward.
  1575.  *
  1576.  *----------------------------------------------------------------------
  1577.  */
  1578. static void 
  1579. BringWindowForward(
  1580.     WindowRef wRef)
  1581. {
  1582.     if (!TkpIsWindowFloating(wRef)) {
  1583.         if ((TkMacHaveAppearance() < 0x110) || IsValidWindowPtr(wRef))
  1584.         SelectWindow(wRef);
  1585.     }
  1586. }
  1587. /*
  1588.  *----------------------------------------------------------------------
  1589.  *
  1590.  * TkpGetMS --
  1591.  *
  1592.  * Return a relative time in milliseconds.  It doesn't matter
  1593.  * when the epoch was.
  1594.  *
  1595.  * Results:
  1596.  * Number of milliseconds.
  1597.  *
  1598.  * Side effects:
  1599.  * None.
  1600.  *
  1601.  *----------------------------------------------------------------------
  1602.  */
  1603. unsigned long
  1604. TkpGetMS()
  1605. {
  1606.     long long * int64Ptr;
  1607.     UnsignedWide micros;
  1608.     
  1609.     Microseconds(&micros);
  1610.     int64Ptr = (long long *) &micros;
  1611.     /*
  1612.      * We need 64 bit math to do this.  This is available in CW 11
  1613.      * and on.  Other's will need to use a different scheme.
  1614.      */
  1615.     *int64Ptr /= 1000;
  1616.     return (long) *int64Ptr;
  1617. }
  1618. /*
  1619.  *----------------------------------------------------------------------
  1620.  *
  1621.  * TkpIsWindowFloating --
  1622.  *
  1623.  * Returns 1 if a window is floating, 0 otherwise.
  1624.  *
  1625.  * Results:
  1626.  * 1 or 0 depending on window's floating attribute.
  1627.  *
  1628.  * Side effects:
  1629.  * None.
  1630.  *
  1631.  *----------------------------------------------------------------------
  1632.  */
  1633. int
  1634. TkpIsWindowFloating(WindowRef wRef)
  1635. {
  1636.     WindowClass class;
  1637.     
  1638.     if (TkMacHaveAppearance() < 0x110) {
  1639.         return 0;
  1640.     }
  1641.     
  1642.     GetWindowClass(wRef, &class);
  1643.     
  1644.     return (class == kFloatingWindowClass);
  1645.         
  1646. }