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

通讯编程

开发平台:

Visual C++

  1. /*
  2.  * tkMacOSXSubwindows.c --
  3.  *
  4.  * Implements subwindows for the macintosh version of Tk.
  5.  *
  6.  * Copyright (c) 1995-1997 Sun Microsystems, Inc.
  7.  * Copyright 2001, Apple Computer, Inc.
  8.  * Copyright (c) 2006-2007 Daniel A. Steffen <das@users.sourceforge.net>
  9.  *
  10.  * See the file "license.terms" for information on usage and redistribution
  11.  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
  12.  *
  13.  * RCS: @(#) $Id: tkMacOSXSubwindows.c,v 1.2.2.22 2007/12/18 18:21:31 das Exp $
  14.  */
  15. #include "tkMacOSXPrivate.h"
  16. #include "tkMacOSXDebug.h"
  17. #include "tkMacOSXWm.h"
  18. /*
  19. #ifdef TK_MAC_DEBUG
  20. #define TK_MAC_DEBUG_CLIP_REGIONS
  21. #endif
  22. */
  23. /*
  24.  * Prototypes for functions used only in this file.
  25.  */
  26. static void MoveResizeWindow(MacDrawable *macWin);
  27. static void GenerateConfigureNotify(TkWindow *winPtr, int includeWin);
  28. static void UpdateOffsets(TkWindow *winPtr, int deltaX, int deltaY);
  29. /*
  30.  *----------------------------------------------------------------------
  31.  *
  32.  * XDestroyWindow --
  33.  *
  34.  * Dealocates the given X Window.
  35.  *
  36.  * Results:
  37.  * The window id is returned.
  38.  *
  39.  * Side effects:
  40.  * None.
  41.  *
  42.  *----------------------------------------------------------------------
  43.  */
  44. void
  45. XDestroyWindow(
  46.     Display* display, /* Display. */
  47.     Window window) /* Window. */
  48. {
  49.     MacDrawable *macWin = (MacDrawable *) window;
  50.     /*
  51.      * Remove any dangling pointers that may exist if
  52.      * the window we are deleting is being tracked by
  53.      * the grab code.
  54.      */
  55.     TkPointerDeadWindow(macWin->winPtr);
  56.     macWin->toplevel->referenceCount--;
  57.     if (Tk_IsTopLevel(macWin->winPtr)) {
  58. WindowRef winRef;
  59. /*
  60.  * We are relying on the Activate Mac OS event to pass the
  61.  * focus away from a window that is getting Destroyed to the
  62.  * Front non-floating window. BUT we don't get activate events
  63.  * when a floating window is destroyed - since the front non-floating
  64.  * window doesn't in fact get activated... So maybe we can check here
  65.  * and if we are destroying a floating window, we can pass the focus
  66.  * back to the front non-floating window...
  67.  */
  68. if (macWin->grafPtr != NULL) {
  69.     TkWindow *focusPtr = TkGetFocusWin(macWin->winPtr);
  70.     if (focusPtr == NULL || (focusPtr->mainPtr->winPtr == macWin->winPtr)) {
  71. winRef = TkMacOSXDrawableWindow(window);
  72. if (TkpIsWindowFloating (winRef)) {
  73.     Window window;
  74.     window = TkMacOSXGetXWindow(ActiveNonFloatingWindow());
  75.     if (window != None) {
  76. TkMacOSXGenerateFocusEvent(window, 1);
  77.     }
  78. }
  79.     }
  80. }
  81. if (macWin->visRgn) {
  82.     CFRelease(macWin->visRgn);
  83. }
  84. if (macWin->aboveVisRgn) {
  85.     CFRelease(macWin->aboveVisRgn);
  86. }
  87. /*
  88.  * Delete the Mac window and remove it from the windowTable.
  89.  * The window could be NULL if the window was never mapped.
  90.  * However, we don't do this for embedded windows, they don't
  91.  * go in the window list, and they do not own their portPtr's.
  92.  */
  93. if (!(Tk_IsEmbedded(macWin->winPtr))) {
  94.     WindowRef winRef = TkMacOSXDrawableWindow(window);
  95.     if (winRef) {
  96. TkMacOSXWindowList *listPtr, *prevPtr;
  97. WindowGroupRef group;
  98. if (GetWindowProperty(winRef, 'Tk  ', 'TsGp', sizeof(group),
  99. NULL, &group) == noErr) {
  100.     TkDisplay *dispPtr = TkGetDisplayList();
  101.     ItemCount i = CountWindowGroupContents(group,
  102.     kWindowGroupContentsReturnWindows);
  103.     while (i > 0) {
  104. WindowRef macWin;
  105. ChkErr(GetIndexedWindow, group, i--, 0, &macWin);
  106. if (macWin) {
  107.     WindowGroupRef newGroup = NULL;
  108.     Window window = TkMacOSXGetXWindow(macWin);
  109.     if (window != None) {
  110. TkWindow * winPtr = (TkWindow *)Tk_IdToWindow(
  111. dispPtr->display, window);
  112. if (winPtr && winPtr->wmInfoPtr) {
  113.     newGroup = GetWindowGroupOfClass(
  114.     winPtr->wmInfoPtr->macClass);
  115. }
  116.     }
  117.     if (!newGroup) {
  118. newGroup = GetWindowGroupOfClass(
  119. kDocumentWindowClass);
  120.     }
  121.     ChkErr(SetWindowGroup, macWin, newGroup);
  122. }
  123.     }
  124.     ChkErr(SetWindowGroupOwner, group, NULL);
  125.     ChkErr(ReleaseWindowGroup, group);
  126. }
  127. TkMacOSXUnregisterMacWindow(winRef);
  128. DisposeWindow(winRef);
  129. for (listPtr = tkMacOSXWindowListPtr, prevPtr = NULL;
  130. tkMacOSXWindowListPtr != NULL;
  131. prevPtr = listPtr, listPtr = listPtr->nextPtr) {
  132.     if (listPtr->winPtr == macWin->winPtr) {
  133. if (prevPtr == NULL) {
  134.     tkMacOSXWindowListPtr = listPtr->nextPtr;
  135. } else {
  136.     prevPtr->nextPtr = listPtr->nextPtr;
  137. }
  138. ckfree((char *) listPtr);
  139. break;
  140.     }
  141. }
  142.     }
  143. }
  144. macWin->grafPtr = NULL;
  145. /*
  146.  * Delay deletion of a toplevel data structure untill all
  147.  * children have been deleted.
  148.  */
  149. if (macWin->toplevel->referenceCount == 0) {
  150.     ckfree((char *) macWin->toplevel);
  151. }
  152.     } else {
  153. TkMacOSXInvalidateWindow(macWin, TK_PARENT_WINDOW);
  154. if (macWin->winPtr->parentPtr != NULL) {
  155.     TkMacOSXInvalClipRgns((Tk_Window) macWin->winPtr->parentPtr);
  156. }
  157. if (macWin->visRgn) {
  158.     CFRelease(macWin->visRgn);
  159. }
  160. if (macWin->aboveVisRgn) {
  161.     CFRelease(macWin->aboveVisRgn);
  162. }
  163. if (macWin->toplevel->referenceCount == 0) {
  164.     ckfree((char *) macWin->toplevel);
  165. }
  166. ckfree((char *) macWin);
  167.     }
  168. }
  169. /*
  170.  *----------------------------------------------------------------------
  171.  *
  172.  * XMapWindow --
  173.  *
  174.  * Map the given X Window to the screen. See X window documentation
  175.  *  for more details.
  176.  *
  177.  * Results:
  178.  * None.
  179.  *
  180.  * Side effects:
  181.  * The subwindow or toplevel may appear on the screen.
  182.  *
  183.  *----------------------------------------------------------------------
  184.  */
  185. void
  186. XMapWindow(
  187.     Display* display, /* Display. */
  188.     Window window) /* Window. */
  189. {
  190.     MacDrawable *macWin = (MacDrawable *) window;
  191.     XEvent event;
  192.     /*
  193.      * Under certain situations it's possible for this function to be
  194.      * called before the toplevel window it's associated with has actually
  195.      * been mapped. In that case we need to create the real Macintosh
  196.      * window now as this function as well as other X functions assume that
  197.      * the portPtr is valid.
  198.      */
  199.     if (!TkMacOSXHostToplevelExists(macWin->toplevel->winPtr)) {
  200. TkMacOSXMakeRealWindowExist(macWin->toplevel->winPtr);
  201.     }
  202.     display->request++;
  203.     macWin->winPtr->flags |= TK_MAPPED;
  204.     if (Tk_IsTopLevel(macWin->winPtr)) {
  205. if (!Tk_IsEmbedded(macWin->winPtr)) {
  206.     /*
  207.      * XXX This should be ShowSheetWindow for kSheetWindowClass
  208.      * XXX windows that have a wmPtr->master parent set.
  209.      */
  210.     WindowRef wRef = TkMacOSXDrawableWindow(window);
  211.     if ((macWin->winPtr->wmInfoPtr->macClass == kSheetWindowClass)
  212.     && (macWin->winPtr->wmInfoPtr->master != None)) {
  213. ShowSheetWindow(wRef, TkMacOSXDrawableWindow(
  214. macWin->winPtr->wmInfoPtr->master));
  215.     } else {
  216. ShowWindow(wRef);
  217.     }
  218. }
  219. TkMacOSXInvalClipRgns((Tk_Window) macWin->winPtr);
  220. /*
  221.  * We only need to send the MapNotify event
  222.  * for toplevel windows.
  223.  */
  224. event.xany.serial = display->request;
  225. event.xany.send_event = False;
  226. event.xany.display = display;
  227. event.xmap.window = window;
  228. event.xmap.type = MapNotify;
  229. event.xmap.event = window;
  230. event.xmap.override_redirect = macWin->winPtr->atts.override_redirect;
  231. Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
  232.     } else {
  233. /*
  234.  * Generate damage for that area of the window
  235.  */
  236. TkMacOSXInvalClipRgns((Tk_Window) macWin->winPtr->parentPtr);
  237. TkMacOSXInvalidateWindow(macWin, TK_PARENT_WINDOW);
  238.     }
  239. }
  240. /*
  241.  *----------------------------------------------------------------------
  242.  *
  243.  * XUnmapWindow --
  244.  *
  245.  * Unmap the given X Window to the screen. See X window
  246.  * documentation for more details.
  247.  *
  248.  * Results:
  249.  * None.
  250.  *
  251.  * Side effects:
  252.  * The subwindow or toplevel may be removed from the screen.
  253.  *
  254.  *----------------------------------------------------------------------
  255.  */
  256. void
  257. XUnmapWindow(
  258.     Display* display, /* Display. */
  259.     Window window) /* Window. */
  260. {
  261.     MacDrawable *macWin = (MacDrawable *) window;
  262.     XEvent event;
  263.     display->request++;
  264.     macWin->winPtr->flags &= ~TK_MAPPED;
  265.     if (Tk_IsTopLevel(macWin->winPtr)) {
  266. if (!Tk_IsEmbedded(macWin->winPtr)
  267. && macWin->winPtr->wmInfoPtr->hints.initial_state != IconicState) {
  268.     /*
  269.      * XXX This should be HideSheetWindow for kSheetWindowClass
  270.      * XXX windows that have a wmPtr->master parent set.
  271.      */
  272.     WindowRef wref = TkMacOSXDrawableWindow(window);
  273.     if ((macWin->winPtr->wmInfoPtr->macClass == kSheetWindowClass)
  274.     && (macWin->winPtr->wmInfoPtr->master != None)) {
  275. HideSheetWindow(wref);
  276.     } else {
  277. HideWindow(wref);
  278.     }
  279. }
  280. TkMacOSXInvalClipRgns((Tk_Window) macWin->winPtr);
  281. /*
  282.  * We only need to send the UnmapNotify event
  283.  * for toplevel windows.
  284.  */
  285. event.xany.serial = display->request;
  286. event.xany.send_event = False;
  287. event.xany.display = display;
  288. event.xunmap.type = UnmapNotify;
  289. event.xunmap.window = window;
  290. event.xunmap.event = window;
  291. event.xunmap.from_configure = false;
  292. Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
  293.     } else {
  294. /*
  295.  * Generate damage for that area of the window.
  296.  */
  297. TkMacOSXInvalidateWindow(macWin, TK_PARENT_WINDOW);
  298. TkMacOSXInvalClipRgns((Tk_Window) macWin->winPtr->parentPtr);
  299.     }
  300. }
  301. /*
  302.  *----------------------------------------------------------------------
  303.  *
  304.  * XResizeWindow --
  305.  *
  306.  * Resize a given X window. See X windows documentation for
  307.  * further details.
  308.  *
  309.  * Results:
  310.  * None.
  311.  *
  312.  * Side effects:
  313.  * None.
  314.  *
  315.  *----------------------------------------------------------------------
  316.  */
  317. void
  318. XResizeWindow(
  319.     Display* display, /* Display. */
  320.     Window window, /* Window. */
  321.     unsigned int width,
  322.     unsigned int height)
  323. {
  324.     MacDrawable *macWin = (MacDrawable *) window;
  325.     display->request++;
  326.     if (Tk_IsTopLevel(macWin->winPtr) && !Tk_IsEmbedded(macWin->winPtr)) {
  327. WindowRef w = TkMacOSXDrawableWindow(window);
  328. if (w) {
  329.     Rect bounds;
  330.     ChkErr(GetWindowBounds, w, kWindowContentRgn, &bounds);
  331.     bounds.right = bounds.left + width;
  332.     bounds.bottom = bounds.top + height;
  333.     ChkErr(SetWindowBounds, w, kWindowContentRgn, &bounds);
  334. }
  335.     } else {
  336. MoveResizeWindow(macWin);
  337.     }
  338. }
  339. /*
  340.  *----------------------------------------------------------------------
  341.  *
  342.  * XMoveResizeWindow --
  343.  *
  344.  * Move or resize a given X window. See X windows documentation
  345.  * for further details.
  346.  *
  347.  * Results:
  348.  * None.
  349.  *
  350.  * Side effects:
  351.  * None.
  352.  *
  353.  *----------------------------------------------------------------------
  354.  */
  355. void
  356. XMoveResizeWindow(
  357.     Display* display, /* Display. */
  358.     Window window, /* Window. */
  359.     int x, int y,
  360.     unsigned int width,
  361.     unsigned int height)
  362. {
  363.     MacDrawable * macWin = (MacDrawable *) window;
  364.     display->request++;
  365.     if (Tk_IsTopLevel(macWin->winPtr) && !Tk_IsEmbedded(macWin->winPtr)) {
  366. WindowRef w = TkMacOSXDrawableWindow(window);
  367. if (w) {
  368.     Rect bounds;
  369.     bounds.left = x + macWin->winPtr->wmInfoPtr->xInParent;
  370.     bounds.right = bounds.left + width;
  371.     bounds.top = y + macWin->winPtr->wmInfoPtr->yInParent;
  372.     bounds.bottom = bounds.top + height;
  373.     ChkErr(SetWindowBounds, w, kWindowContentRgn, &bounds);
  374. }
  375.     } else {
  376. MoveResizeWindow(macWin);
  377.     }
  378. }
  379. /*
  380.  *----------------------------------------------------------------------
  381.  *
  382.  * XMoveWindow --
  383.  *
  384.  * Move a given X window. See X windows documentation for further
  385.  * details.
  386.  *
  387.  * Results:
  388.  * None.
  389.  *
  390.  * Side effects:
  391.  * None.
  392.  *
  393.  *----------------------------------------------------------------------
  394.  */
  395. void
  396. XMoveWindow(
  397.     Display* display, /* Display. */
  398.     Window window, /* Window. */
  399.     int x,
  400.     int y)
  401. {
  402.     MacDrawable *macWin = (MacDrawable *) window;
  403.     display->request++;
  404.     if (Tk_IsTopLevel(macWin->winPtr) && !Tk_IsEmbedded(macWin->winPtr)) {
  405. WindowRef w = TkMacOSXDrawableWindow(window);
  406. if (w) {
  407.     ChkErr(MoveWindowStructure, w, x, y);
  408. }
  409.     } else {
  410. MoveResizeWindow(macWin);
  411.     }
  412. }
  413. /*
  414.  *----------------------------------------------------------------------
  415.  *
  416.  * MoveResizeWindow --
  417.  *
  418.  * Helper proc for XResizeWindow, XMoveResizeWindow and XMoveWindow.
  419.  *
  420.  * Results:
  421.  * None.
  422.  *
  423.  * Side effects:
  424.  * None.
  425.  *
  426.  *----------------------------------------------------------------------
  427.  */
  428. static void
  429. MoveResizeWindow(
  430.     MacDrawable *macWin)
  431. {
  432.     int deltaX = 0, deltaY = 0, parentBorderwidth = 0;
  433.     MacDrawable *macParent = NULL;
  434.     CGrafPtr destPort = TkMacOSXGetDrawablePort((Drawable) macWin);
  435.     /*
  436.      * Find the Parent window, for an embedded window it will be its container.
  437.      */
  438.     if (Tk_IsEmbedded(macWin->winPtr)) {
  439. TkWindow *contWinPtr = TkpGetOtherWindow(macWin->winPtr);
  440. if (contWinPtr) {
  441.     macParent = contWinPtr->privatePtr;
  442. } else {
  443.     /*
  444.      * Here we should handle out of process embedding.
  445.      * At this point, we are assuming that the changes.x,y is not
  446.      * maintained, if you need the info get it from Tk_GetRootCoords,
  447.      * and that the toplevel sits at 0,0 when it is drawn.
  448.      */
  449. }
  450.     } else {
  451. /*
  452.  * TODO: update all xOff & yOffs
  453.  */
  454. macParent = macWin->winPtr->parentPtr->privatePtr;
  455. parentBorderwidth = macWin->winPtr->parentPtr->changes.border_width;
  456.     }
  457.     if (macParent) {
  458. deltaX = macParent->xOff + parentBorderwidth +
  459. macWin->winPtr->changes.x - macWin->xOff;
  460. deltaY = macParent->yOff + parentBorderwidth +
  461. macWin->winPtr->changes.y - macWin->yOff;
  462.     }
  463.     if (destPort) {
  464. TkMacOSXInvalidateWindow(macWin, TK_PARENT_WINDOW);
  465. if (macParent) {
  466.     TkMacOSXInvalClipRgns((Tk_Window) macParent->winPtr);
  467. }
  468.     }
  469.     UpdateOffsets(macWin->winPtr, deltaX, deltaY);
  470.     if (destPort) {
  471. TkMacOSXInvalidateWindow(macWin, TK_PARENT_WINDOW);
  472.     }
  473.     GenerateConfigureNotify(macWin->winPtr, 0);
  474. }
  475. /*
  476.  *----------------------------------------------------------------------
  477.  *
  478.  * GenerateConfigureNotify --
  479.  *
  480.  * Generates ConfigureNotify events for all the child widgets
  481.  * of the widget passed in the winPtr parameter. If includeWin
  482.  * is true, also generates ConfigureNotify event for the
  483.  * widget itself.
  484.  *
  485.  * Results:
  486.  * None.
  487.  *
  488.  * Side effects:
  489.  * ConfigureNotify events will be posted.
  490.  *
  491.  *----------------------------------------------------------------------
  492.  */
  493. static void
  494. GenerateConfigureNotify (TkWindow *winPtr, int includeWin)
  495. {
  496.     TkWindow *childPtr;
  497.     for (childPtr = winPtr->childList; childPtr != NULL;
  498.        childPtr = childPtr->nextPtr) {
  499. if (!Tk_IsMapped(childPtr) || Tk_IsTopLevel(childPtr)) {
  500.     continue;
  501. }
  502. GenerateConfigureNotify(childPtr, 1);
  503.     }
  504.     if (includeWin) {
  505. TkDoConfigureNotify(winPtr);
  506.     }
  507. }
  508. /*
  509.  *----------------------------------------------------------------------
  510.  *
  511.  * XRaiseWindow --
  512.  *
  513.  * Change the stacking order of a window.
  514.  *
  515.  * Results:
  516.  * None.
  517.  *
  518.  * Side effects:
  519.  * Changes the stacking order of the specified window.
  520.  *
  521.  *----------------------------------------------------------------------
  522.  */
  523. void
  524. XRaiseWindow(
  525.     Display* display, /* Display. */
  526.     Window window) /* Window. */
  527. {
  528.     MacDrawable *macWin = (MacDrawable *) window;
  529.     display->request++;
  530.     if (Tk_IsTopLevel(macWin->winPtr) && !Tk_IsEmbedded(macWin->winPtr)) {
  531. TkWmRestackToplevel(macWin->winPtr, Above, NULL);
  532.     } else {
  533. /*
  534.  * TODO: this should generate damage
  535.  */
  536.     }
  537. }
  538. #if 0
  539. /*
  540.  *----------------------------------------------------------------------
  541.  *
  542.  * XLowerWindow --
  543.  *
  544.  * Change the stacking order of a window.
  545.  *
  546.  * Results:
  547.  * None.
  548.  *
  549.  * Side effects:
  550.  * Changes the stacking order of the specified window.
  551.  *
  552.  *----------------------------------------------------------------------
  553.  */
  554. void
  555. XLowerWindow(
  556.     Display* display, /* Display. */
  557.     Window window) /* Window. */
  558. {
  559.     MacDrawable *macWin = (MacDrawable *) window;
  560.     display->request++;
  561.     if (Tk_IsTopLevel(macWin->winPtr) && !Tk_IsEmbedded(macWin->winPtr)) {
  562. TkWmRestackToplevel(macWin->winPtr, Below, NULL);
  563.     } else {
  564. /*
  565.  * TODO: this should generate damage
  566.  */
  567.     }
  568. }
  569. #endif
  570. /*
  571.  *----------------------------------------------------------------------
  572.  *
  573.  * XConfigureWindow --
  574.  *
  575.  * Change the size, position, stacking, or border of the specified
  576.  * window.
  577.  *
  578.  * Results:
  579.  * None.
  580.  *
  581.  * Side effects:
  582.  * Changes the attributes of the specified window. Note that we
  583.  * ignore the passed in values and use the values stored in the
  584.  * TkWindow data structure.
  585.  *
  586.  *----------------------------------------------------------------------
  587.  */
  588. void
  589. XConfigureWindow(
  590.     Display* display, /* Display. */
  591.     Window w, /* Window. */
  592.     unsigned int value_mask,
  593.     XWindowChanges* values)
  594. {
  595.     MacDrawable *macWin = (MacDrawable *) w;
  596.     TkWindow *winPtr = macWin->winPtr;
  597.     display->request++;
  598.     /*
  599.      * Change the shape and/or position of the window.
  600.      */
  601.     if (value_mask & (CWX|CWY|CWWidth|CWHeight)) {
  602. XMoveResizeWindow(display, w, winPtr->changes.x, winPtr->changes.y,
  603. winPtr->changes.width, winPtr->changes.height);
  604.     }
  605.     /*
  606.      * Change the stacking order of the window. Tk actuall keeps all
  607.      * the information we need for stacking order. All we need to do
  608.      * is make sure the clipping regions get updated and generate damage
  609.      * that will ensure things get drawn correctly.
  610.      */
  611.     if (value_mask & CWStackMode) {
  612. Rect bounds;
  613. WindowRef wRef = TkMacOSXDrawableWindow(w);
  614. if (wRef) {
  615.     TkMacOSXInvalClipRgns((Tk_Window) winPtr->parentPtr);
  616.     TkMacOSXWinBounds(winPtr, &bounds);
  617.     InvalWindowRect(wRef, &bounds);
  618. }
  619.     }
  620.     /* TkGenWMMoveRequestEvent(macWin->winPtr,
  621.     macWin->winPtr->changes.x, macWin->winPtr->changes.y); */
  622. }
  623. /*
  624.  *----------------------------------------------------------------------
  625.  *
  626.  * TkMacOSXUpdateClipRgn --
  627.  *
  628.  * This function updates the cliping regions for a given window
  629.  * and all of its children. Once updated the TK_CLIP_INVALID flag
  630.  * in the subwindow data structure is unset. The TK_CLIP_INVALID
  631.  * flag should always be unset before any drawing is attempted.
  632.  *
  633.  * Results:
  634.  * None.
  635.  *
  636.  * Side effects:
  637.  * The clip regions for the window and its children are updated.
  638.  *
  639.  *----------------------------------------------------------------------
  640.  */
  641. void
  642. TkMacOSXUpdateClipRgn(
  643.     TkWindow *winPtr)
  644. {
  645.     MacDrawable *macWin;
  646.     if (winPtr == NULL) {
  647. return;
  648.     }
  649.     macWin = winPtr->privatePtr;
  650.     if (macWin && macWin->flags & TK_CLIP_INVALID) {
  651. TkWindow *win2Ptr;
  652. if (Tk_IsMapped(winPtr)) {
  653.     int rgnChanged = 0;
  654.     CGRect bounds;
  655.     HIMutableShapeRef rgn;
  656.     /*
  657.      * Start with a region defined by the window bounds.
  658.      */
  659.     TkMacOSXWinCGBounds(winPtr, &bounds);
  660.     rgn = TkMacOSXHIShapeCreateMutableWithRect(&bounds);
  661.     /*
  662.      * Clip away the area of any windows that may obscure this
  663.      * window.
  664.      * For a non-toplevel window, first, clip to the parents visible
  665.      * clip region.
  666.      * Second, clip away any siblings that are higher in the
  667.      * stacking order.
  668.      * For an embedded toplevel, just clip to the container's visible
  669.      * clip region. Remember, we only allow one contained window
  670.      * in a frame, and don't support any other widgets in the frame
  671.      * either. This is not currently enforced, however.
  672.      */
  673.     if (!Tk_IsTopLevel(winPtr)) {
  674. TkMacOSXUpdateClipRgn(winPtr->parentPtr);
  675. if (winPtr->parentPtr) {
  676.     ChkErr(HIShapeIntersect,
  677.     winPtr->parentPtr->privatePtr->aboveVisRgn, rgn,
  678.     rgn);
  679. }
  680. win2Ptr = winPtr;
  681. while ((win2Ptr = win2Ptr->nextPtr)) {
  682.     if (Tk_IsTopLevel(win2Ptr) || !Tk_IsMapped(win2Ptr)) {
  683. continue;
  684.     }
  685.     TkMacOSXWinCGBounds(win2Ptr, &bounds);
  686.     ChkErr(TkMacOSHIShapeDifferenceWithRect, rgn, &bounds);
  687. }
  688.     } else if (Tk_IsEmbedded(winPtr)) {
  689. win2Ptr = TkpGetOtherWindow(winPtr);
  690. if (win2Ptr) {
  691.     TkMacOSXUpdateClipRgn(win2Ptr);
  692.     ChkErr(HIShapeIntersect,
  693.     win2Ptr->privatePtr->aboveVisRgn, rgn, rgn);
  694. } else if (tkMacOSXEmbedHandler != NULL) {
  695.     HIShapeRef visRgn;
  696.     TkMacOSXCheckTmpQdRgnEmpty();
  697.     tkMacOSXEmbedHandler->getClipProc((Tk_Window) winPtr,
  698.     tkMacOSXtmpQdRgn);
  699.     visRgn = HIShapeCreateWithQDRgn(tkMacOSXtmpQdRgn);
  700.     SetEmptyRgn(tkMacOSXtmpQdRgn);
  701.     ChkErr(HIShapeIntersect, visRgn, rgn, rgn);
  702. }
  703. /*
  704.  * TODO: Here we should handle out of process embedding.
  705.  */
  706.     } else if (winPtr->wmInfoPtr->attributes &
  707.     kWindowResizableAttribute) {
  708. HIViewRef growBoxView;
  709. OSErr err = HIViewFindByID(HIViewGetRoot(
  710. TkMacOSXDrawableWindow(winPtr->window)),
  711. kHIViewWindowGrowBoxID, &growBoxView);
  712. if (err == noErr) {
  713.     ChkErr(HIViewGetFrame, growBoxView, &bounds);
  714.     bounds = CGRectOffset(bounds,
  715.     -winPtr->wmInfoPtr->xInParent,
  716.     -winPtr->wmInfoPtr->yInParent);
  717.     ChkErr(TkMacOSHIShapeDifferenceWithRect, rgn, &bounds);
  718. }
  719.     }
  720.     macWin->aboveVisRgn = HIShapeCreateCopy(rgn);
  721.     /*
  722.      * The final clip region is the aboveVis region (or visible
  723.      * region) minus all the children of this window.
  724.      * If the window is a container, we must also subtract the region
  725.      * of the embedded window.
  726.      */
  727.     win2Ptr = winPtr->childList;
  728.     while (win2Ptr) {
  729. if (Tk_IsTopLevel(win2Ptr) || !Tk_IsMapped(win2Ptr)) {
  730.     win2Ptr = win2Ptr->nextPtr;
  731.     continue;
  732. }
  733. TkMacOSXWinCGBounds(win2Ptr, &bounds);
  734. ChkErr(TkMacOSHIShapeDifferenceWithRect, rgn, &bounds);
  735. rgnChanged = 1;
  736. win2Ptr = win2Ptr->nextPtr;
  737.     }
  738.     if (Tk_IsContainer(winPtr)) {
  739. win2Ptr = TkpGetOtherWindow(winPtr);
  740. if (win2Ptr) {
  741.     if (Tk_IsMapped(win2Ptr)) {
  742. TkMacOSXWinCGBounds(win2Ptr, &bounds);
  743. ChkErr(TkMacOSHIShapeDifferenceWithRect, rgn, &bounds);
  744. rgnChanged = 1;
  745.     }
  746. }
  747. /*
  748.  * TODO: Here we should handle out of process embedding.
  749.  */
  750.     }
  751.     if (rgnChanged) {
  752. HIShapeRef diffRgn = HIShapeCreateDifference(
  753. macWin->aboveVisRgn, rgn);
  754. if (!HIShapeIsEmpty(diffRgn)) {
  755.     macWin->visRgn = HIShapeCreateCopy(rgn);
  756. }
  757. CFRelease(diffRgn);
  758.     }
  759.     CFRelease(rgn);
  760. } else {
  761.     /*
  762.      * An unmapped window has empty clip regions to prevent any
  763.      * (erroneous) drawing into it or its children from becoming
  764.      * visible. [Bug 940117]
  765.      */
  766.     if (!Tk_IsTopLevel(winPtr)) {
  767. TkMacOSXUpdateClipRgn(winPtr->parentPtr);
  768.     } else if (Tk_IsEmbedded(winPtr)) {
  769. win2Ptr = TkpGetOtherWindow(winPtr);
  770. if (win2Ptr) {
  771.     TkMacOSXUpdateClipRgn(win2Ptr);
  772. }
  773.     }
  774.     macWin->aboveVisRgn = TkMacOSXHIShapeCreateEmpty();
  775. }
  776. if (!macWin->visRgn) {
  777.     macWin->visRgn = HIShapeCreateCopy(macWin->aboveVisRgn);
  778. }
  779. macWin->flags &= ~TK_CLIP_INVALID;
  780. #ifdef TK_MAC_DEBUG_CLIP_REGIONS
  781. TkMacOSXDebugFlashRegion((Drawable) macWin, macWin->visRgn);
  782. #endif /* TK_MAC_DEBUG_CLIP_REGIONS */
  783.     }
  784. }
  785. /*
  786.  *----------------------------------------------------------------------
  787.  *
  788.  * TkMacOSXVisableClipRgn --
  789.  *
  790.  * This function returnd the Macintosh cliping region for the
  791.  * given window. A NULL Rgn means the window is not visible.
  792.  *
  793.  * Results:
  794.  * The region.
  795.  *
  796.  * Side effects:
  797.  * None.
  798.  *
  799.  *----------------------------------------------------------------------
  800.  */
  801. RgnHandle
  802. TkMacOSXVisableClipRgn(
  803.     TkWindow *winPtr)
  804. {
  805.     static RgnHandle visQdRgn = NULL;
  806.     if (visQdRgn == NULL) {
  807. visQdRgn = NewRgn();
  808.     }
  809.     if (winPtr->privatePtr->flags & TK_CLIP_INVALID) {
  810. TkMacOSXUpdateClipRgn(winPtr);
  811.     }
  812.     ChkErr(HIShapeGetAsQDRgn, winPtr->privatePtr->visRgn, visQdRgn);
  813.     return visQdRgn;
  814. }
  815. /*
  816.  *----------------------------------------------------------------------
  817.  *
  818.  * TkMacOSXInvalidateWindow --
  819.  *
  820.  * This function makes the window as invalid will generate damage
  821.  * for the window.
  822.  *
  823.  * Results:
  824.  * None.
  825.  *
  826.  * Side effects:
  827.  * Damage is created.
  828.  *
  829.  *----------------------------------------------------------------------
  830.  */
  831. void
  832. TkMacOSXInvalidateWindow(
  833.     MacDrawable *macWin, /* Make window that's causing damage. */
  834.     int flag) /* Should be TK_WINDOW_ONLY or
  835.  * TK_PARENT_WINDOW */
  836. {
  837.     WindowRef windowRef;
  838.     HIShapeRef rgn;
  839.     windowRef = TkMacOSXDrawableWindow((Drawable)macWin);
  840.     if (macWin->flags & TK_CLIP_INVALID) {
  841. TkMacOSXUpdateClipRgn(macWin->winPtr);
  842.     }
  843.     rgn = (flag == TK_WINDOW_ONLY) ? macWin->visRgn : macWin->aboveVisRgn;
  844.     if (!HIShapeIsEmpty(rgn)) {
  845. TkMacOSXCheckTmpQdRgnEmpty();
  846. ChkErr(HIShapeGetAsQDRgn, rgn, tkMacOSXtmpQdRgn);
  847. InvalWindowRgn(windowRef, tkMacOSXtmpQdRgn);
  848. SetEmptyRgn(tkMacOSXtmpQdRgn);
  849.     }
  850. #ifdef TK_MAC_DEBUG_CLIP_REGIONS
  851.     TkMacOSXDebugFlashRegion((Drawable) macWin, rgn);
  852. #endif /* TK_MAC_DEBUG_CLIP_REGIONS */
  853. }
  854. /*
  855.  *----------------------------------------------------------------------
  856.  *
  857.  * TkMacOSXGetDrawableWindow --
  858.  *
  859.  * This function returns the WindowRef for a given X drawable.
  860.  *
  861.  * Results:
  862.  * A WindowRef, or NULL for off screen pixmaps.
  863.  *
  864.  * Side effects:
  865.  * None.
  866.  *
  867.  *----------------------------------------------------------------------
  868.  */
  869. WindowRef
  870. TkMacOSXDrawableWindow(
  871.     Drawable drawable)
  872. {
  873.     MacDrawable *macWin = (MacDrawable *) drawable;
  874.     WindowRef result = NULL;
  875.     if (!macWin || macWin->flags & TK_IS_PIXMAP) {
  876. result = NULL;
  877.     } else {
  878. result = GetWindowFromPort(TkMacOSXGetDrawablePort(drawable));
  879.     }
  880.     return result;
  881. }
  882. /*
  883.  *----------------------------------------------------------------------
  884.  *
  885.  * TkMacOSXGetDrawablePort --
  886.  *
  887.  * This function returns the Graphics Port for a given X drawable.
  888.  *
  889.  * Results:
  890.  * A CGrafPort . Either an off screen pixmap or a Window.
  891.  *
  892.  * Side effects:
  893.  * None.
  894.  *
  895.  *----------------------------------------------------------------------
  896.  */
  897. CGrafPtr
  898. TkMacOSXGetDrawablePort(
  899.     Drawable drawable)
  900. {
  901.     MacDrawable *macWin = (MacDrawable *) drawable;
  902.     CGrafPtr resultPort = NULL;
  903.     if (macWin) {
  904. if (macWin->toplevel) {
  905.     /*
  906.      * If the Drawable is in an embedded window, use the Port of its
  907.      * container.
  908.      *
  909.      * TRICKY POINT: we can have cases when a toplevel is being
  910.      * destroyed where the winPtr for the toplevel has been freed, but
  911.      * the children are not all the way destroyed. The children will
  912.      * call this function as they are being destroyed, but
  913.      * Tk_IsEmbedded will return garbage. So we check the copy of the
  914.      * TK_EMBEDDED flag we put into the toplevel's macWin flags.
  915.      */
  916.     if (macWin->toplevel->flags & TK_EMBEDDED) {
  917. TkWindow *contWinPtr;
  918. contWinPtr = TkpGetOtherWindow(macWin->toplevel->winPtr);
  919. if (contWinPtr != NULL) {
  920.     resultPort = TkMacOSXGetDrawablePort(
  921. (Drawable) contWinPtr->privatePtr);
  922. } else if (tkMacOSXEmbedHandler != NULL) {
  923.     resultPort = tkMacOSXEmbedHandler->getPortProc(
  924.     (Tk_Window) macWin->winPtr);
  925. }
  926. if (!resultPort) {
  927.     /*
  928.      * FIXME: So far as I can tell, the only time that this
  929.      * happens is when we are tearing down an embedded child
  930.      * interpreter, and most of the time, this is harmless...
  931.      * However, we really need to find why the embedding loses.
  932.      */
  933.     TkMacOSXDbgMsg("Couldn't find container");
  934. }
  935. /*
  936.  * TODO: Here we should handle out of process embedding.
  937.  */
  938.     } else {
  939. resultPort = macWin->toplevel->grafPtr;
  940.     }
  941. } else {
  942.     if ((macWin->flags & TK_IS_PIXMAP) && !macWin->grafPtr) {
  943. Rect bounds = {0, 0, macWin->size.height, macWin->size.width};
  944. ChkErr(NewGWorld, &macWin->grafPtr,
  945. (macWin->flags & TK_IS_BW_PIXMAP) ? 1 : 0,
  946. &bounds, NULL, NULL, 0
  947. #ifdef __LITTLE_ENDIAN__
  948. | kNativeEndianPixMap
  949. #endif
  950. );
  951.     }
  952.     resultPort = macWin->grafPtr;
  953. }
  954.     }
  955.     return resultPort;
  956. }
  957. /*
  958.  *----------------------------------------------------------------------
  959.  *
  960.  * TkMacOSXGetRootControl --
  961.  *
  962.  * This function returns the Root Control for a given X drawable.
  963.  *
  964.  * Results:
  965.  * A ControlRef .
  966.  *
  967.  * Side effects:
  968.  * None.
  969.  *
  970.  *----------------------------------------------------------------------
  971.  */
  972. ControlRef
  973. TkMacOSXGetRootControl(
  974.     Drawable drawable)
  975. {
  976.     /*
  977.      * will probably need to fix this up for embedding
  978.      */
  979.     MacDrawable *macWin = (MacDrawable *) drawable;
  980.     ControlRef result = NULL;
  981.     if (macWin == NULL) {
  982. return NULL;
  983.     }
  984.     if (!(macWin->toplevel->flags & TK_EMBEDDED)) {
  985. return macWin->toplevel->rootControl;
  986.     } else {
  987. TkWindow *contWinPtr;
  988. contWinPtr = TkpGetOtherWindow(macWin->toplevel->winPtr);
  989. if (contWinPtr != NULL) {
  990.     result = TkMacOSXGetRootControl(
  991. (Drawable) contWinPtr->privatePtr);
  992. } else if (tkMacOSXEmbedHandler != NULL) {
  993.     result = NULL;
  994. }
  995.    }
  996.     return result;
  997. }
  998. /*
  999.  *----------------------------------------------------------------------
  1000.  *
  1001.  * TkMacOSXInvalClipRgns --
  1002.  *
  1003.  * This function invalidates the clipping regions for a given
  1004.  * window and all of its children. This function should be
  1005.  * called whenever changes are made to subwindows that would
  1006.  * affect the size or position of windows.
  1007.  *
  1008.  * Results:
  1009.  * None.
  1010.  *
  1011.  * Side effects:
  1012.  * The cliping regions for the window and its children are
  1013.  * mark invalid. (Make sure they are valid before drawing.)
  1014.  *
  1015.  *----------------------------------------------------------------------
  1016.  */
  1017. void
  1018. TkMacOSXInvalClipRgns(
  1019.     Tk_Window tkwin)
  1020. {
  1021.     TkWindow *winPtr = (TkWindow *) tkwin;
  1022.     TkWindow *childPtr;
  1023.     MacDrawable *macWin = winPtr->privatePtr;
  1024.     /*
  1025.      * If already marked we can stop because all
  1026.      * decendants will also already be marked.
  1027.      */
  1028.     if (!macWin || macWin->flags & TK_CLIP_INVALID) {
  1029. return;
  1030.     }
  1031.     macWin->flags |= TK_CLIP_INVALID;
  1032.     if (macWin->visRgn) {
  1033. CFRelease(macWin->visRgn);
  1034. macWin->visRgn = NULL;
  1035.     }
  1036.     if (macWin->aboveVisRgn) {
  1037. CFRelease(macWin->aboveVisRgn);
  1038. macWin->aboveVisRgn = NULL;
  1039.     }
  1040.     /*
  1041.      * Invalidate clip regions for all children &
  1042.      * their decendants - unless the child is a toplevel.
  1043.      */
  1044.     childPtr = winPtr->childList;
  1045.     while (childPtr) {
  1046. if (!Tk_IsTopLevel(childPtr)) {
  1047.     TkMacOSXInvalClipRgns((Tk_Window) childPtr);
  1048. }
  1049. childPtr = childPtr->nextPtr;
  1050.     }
  1051.     /*
  1052.      * Also, if the window is a container, mark its embedded window
  1053.      */
  1054.     if (Tk_IsContainer(winPtr)) {
  1055. childPtr = TkpGetOtherWindow(winPtr);
  1056. if (childPtr) {
  1057.     TkMacOSXInvalClipRgns((Tk_Window) childPtr);
  1058. }
  1059. /*
  1060.  * TODO: Here we should handle out of process embedding.
  1061.  */
  1062.     }
  1063. }
  1064. /*
  1065.  *----------------------------------------------------------------------
  1066.  *
  1067.  * TkMacOSXWinBounds --
  1068.  *
  1069.  * Given a Tk window this function determines the windows
  1070.  * bounds in relation to the Macintosh window's coordinate
  1071.  * system. This is also the same coordinate system as the
  1072.  * Tk toplevel window in which this window is contained.
  1073.  *
  1074.  * Results:
  1075.  * None.
  1076.  *
  1077.  * Side effects:
  1078.  * None.
  1079.  *
  1080.  *----------------------------------------------------------------------
  1081.  */
  1082. void
  1083. TkMacOSXWinBounds(
  1084.     TkWindow *winPtr,
  1085.     Rect *bounds)
  1086. {
  1087.     bounds->left = winPtr->privatePtr->xOff;
  1088.     bounds->top = winPtr->privatePtr->yOff;
  1089.     bounds->right = bounds->left + winPtr->changes.width;
  1090.     bounds->bottom = bounds->top + winPtr->changes.height;
  1091. }
  1092. /*
  1093.  *----------------------------------------------------------------------
  1094.  *
  1095.  * TkMacOSXWinCGBounds --
  1096.  *
  1097.  * Given a Tk window this function determines the windows
  1098.  * bounds in relation to the Macintosh window's coordinate
  1099.  * system. This is also the same coordinate system as the
  1100.  * Tk toplevel window in which this window is contained.
  1101.  *
  1102.  * Results:
  1103.  * None.
  1104.  *
  1105.  * Side effects:
  1106.  * None.
  1107.  *
  1108.  *----------------------------------------------------------------------
  1109.  */
  1110. void
  1111. TkMacOSXWinCGBounds(
  1112.     TkWindow *winPtr,
  1113.     CGRect *bounds)
  1114. {
  1115.     bounds->origin.x = winPtr->privatePtr->xOff;
  1116.     bounds->origin.y = winPtr->privatePtr->yOff;
  1117.     bounds->size.width = winPtr->changes.width;
  1118.     bounds->size.height = winPtr->changes.height;
  1119. }
  1120. /*
  1121.  *----------------------------------------------------------------------
  1122.  *
  1123.  * UpdateOffsets --
  1124.  *
  1125.  * Updates the X & Y offsets of the given TkWindow from the
  1126.  * TopLevel it is a decendant of.
  1127.  *
  1128.  * Results:
  1129.  * None.
  1130.  *
  1131.  * Side effects:
  1132.  * The xOff & yOff fields for the Mac window datastructure
  1133.  * is updated to the proper offset.
  1134.  *
  1135.  *----------------------------------------------------------------------
  1136.  */
  1137. static void
  1138. UpdateOffsets(
  1139.     TkWindow *winPtr,
  1140.     int deltaX,
  1141.     int deltaY)
  1142. {
  1143.     TkWindow *childPtr;
  1144.     if (winPtr->privatePtr == NULL) {
  1145. /*
  1146.  * We haven't called Tk_MakeWindowExist for this window yet. The
  1147.  * offset information will be postponed and calulated at that
  1148.  * time. (This will usually only happen when a mapped parent is
  1149.  * being moved but has child windows that have yet to be mapped.)
  1150.  */
  1151. return;
  1152.     }
  1153.     winPtr->privatePtr->xOff += deltaX;
  1154.     winPtr->privatePtr->yOff += deltaY;
  1155.     childPtr = winPtr->childList;
  1156.     while (childPtr != NULL) {
  1157. if (!Tk_IsTopLevel(childPtr)) {
  1158.     UpdateOffsets(childPtr, deltaX, deltaY);
  1159. }
  1160. childPtr = childPtr->nextPtr;
  1161.     }
  1162.     if (Tk_IsContainer(winPtr)) {
  1163. childPtr = TkpGetOtherWindow(winPtr);
  1164. if (childPtr != NULL) {
  1165.     UpdateOffsets(childPtr,deltaX,deltaY);
  1166. }
  1167. /*
  1168.  * TODO: Here we should handle out of process embedding.
  1169.  */
  1170.     }
  1171. }
  1172. /*
  1173.  *----------------------------------------------------------------------
  1174.  *
  1175.  * Tk_GetPixmap --
  1176.  *
  1177.  * Creates an in memory drawing surface.
  1178.  *
  1179.  * Results:
  1180.  * Returns a handle to a new pixmap.
  1181.  *
  1182.  * Side effects:
  1183.  * Allocates a new Macintosh GWorld.
  1184.  *
  1185.  *----------------------------------------------------------------------
  1186.  */
  1187. Pixmap
  1188. Tk_GetPixmap(
  1189.     Display *display, /* Display for new pixmap (can be null). */
  1190.     Drawable d, /* Drawable where pixmap will be used (ignored). */
  1191.     int width, /* Dimensions of pixmap. */
  1192.     int height,
  1193.     int depth) /* Bits per pixel for pixmap. */
  1194. {
  1195.     MacDrawable *macPix;
  1196.     if (display != NULL) {
  1197. display->request++;
  1198.     }
  1199.     macPix = (MacDrawable *) ckalloc(sizeof(MacDrawable));
  1200.     macPix->winPtr = NULL;
  1201.     macPix->xOff = 0;
  1202.     macPix->yOff = 0;
  1203.     macPix->visRgn = NULL;
  1204.     macPix->aboveVisRgn = NULL;
  1205.     macPix->drawRect = CGRectNull;
  1206.     macPix->referenceCount = 0;
  1207.     macPix->toplevel = NULL;
  1208.     macPix->flags = TK_IS_PIXMAP | (depth == 1 ? TK_IS_BW_PIXMAP : 0);
  1209.     macPix->grafPtr = NULL;
  1210.     macPix->context = NULL;
  1211.     macPix->size = CGSizeMake(width, height);
  1212.     {
  1213. Rect bounds = {0, 0, height, width};
  1214. ChkErr(NewGWorld, &macPix->grafPtr, depth == 1 ? 1 : 0, &bounds, NULL,
  1215. NULL, 0
  1216. #ifdef __LITTLE_ENDIAN__
  1217. | kNativeEndianPixMap
  1218. #endif
  1219. );
  1220.     }
  1221.     return (Pixmap) macPix;
  1222. }
  1223. /*
  1224.  *----------------------------------------------------------------------
  1225.  *
  1226.  * Tk_FreePixmap --
  1227.  *
  1228.  * Release the resources associated with a pixmap.
  1229.  *
  1230.  * Results:
  1231.  * None.
  1232.  *
  1233.  * Side effects:
  1234.  * Deletes the Macintosh GWorld created by Tk_GetPixmap.
  1235.  *
  1236.  *----------------------------------------------------------------------
  1237.  */
  1238. void
  1239. Tk_FreePixmap(
  1240.     Display *display, /* Display. */
  1241.     Pixmap pixmap) /* Pixmap to destroy */
  1242. {
  1243.     MacDrawable *macPix = (MacDrawable *) pixmap;
  1244.     display->request++;
  1245.     if (macPix->grafPtr) {
  1246. DisposeGWorld(macPix->grafPtr);
  1247.     }
  1248.     if (macPix->context) {
  1249. TkMacOSXDbgMsg("Cannot free CG backed Pixmap");
  1250.     }
  1251.     ckfree((char *) macPix);
  1252. }