summaryrefslogtreecommitdiffstats
path: root/macosx/tkMacOSXSubwindows.c
diff options
context:
space:
mode:
Diffstat (limited to 'macosx/tkMacOSXSubwindows.c')
-rw-r--r--macosx/tkMacOSXSubwindows.c1304
1 files changed, 1304 insertions, 0 deletions
diff --git a/macosx/tkMacOSXSubwindows.c b/macosx/tkMacOSXSubwindows.c
new file mode 100644
index 0000000..380725f
--- /dev/null
+++ b/macosx/tkMacOSXSubwindows.c
@@ -0,0 +1,1304 @@
+/*
+ * tkMacOSXSubwindows.c --
+ *
+ * Implements subwindows for the macintosh version of Tk.
+ *
+ * Copyright (c) 1995-1997 Sun Microsystems, Inc.
+ * Copyright 2001, Apple Computer, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * RCS: @(#) $Id: tkMacOSXSubwindows.c,v 1.2 2002/08/31 06:12:30 das Exp $
+ */
+
+#include "tkInt.h"
+#include "X11/X.h"
+#include "X11/Xlib.h"
+#include <stdio.h>
+
+#include <Carbon/Carbon.h>
+#include "tkMacOSXInt.h"
+#include "tkMacOSXDebug.h"
+
+/*
+ * Temporary region that can be reused.
+ */
+static RgnHandle tmpRgn = NULL;
+
+static void UpdateOffsets _ANSI_ARGS_((TkWindow *winPtr, int deltaX, int deltaY));
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * XDestroyWindow --
+ *
+ * Dealocates the given X Window.
+ *
+ * Results:
+ * The window id is returned.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+XDestroyWindow(
+ Display* display, /* Display. */
+ Window window) /* Window. */
+{
+ MacDrawable *macWin = (MacDrawable *) window;
+ CGrafPtr destPort;
+ /*
+ * Remove any dangling pointers that may exist if
+ * the window we are deleting is being tracked by
+ * the grab code.
+ */
+
+ TkPointerDeadWindow(macWin->winPtr);
+ macWin->toplevel->referenceCount--;
+
+
+ if (Tk_IsTopLevel(macWin->winPtr)) {
+ DisposeRgn(macWin->clipRgn);
+ DisposeRgn(macWin->aboveClipRgn);
+
+ /*
+ * Delete the Mac window and remove it from the windowTable.
+ * The window could be NULL if the window was never mapped.
+ * However, we don't do this for embedded windows, they don't
+ * go in the window list, and they do not own their portPtr's.
+ */
+
+ if (!(Tk_IsEmbedded(macWin->winPtr))) {
+ destPort = TkMacOSXGetDrawablePort(window);
+ if (destPort != NULL) {
+ TkMacOSXWindowList *listPtr, *prevPtr;
+ WindowRef winRef;
+ winRef = GetWindowFromPort(destPort);
+ TkMacOSXUnregisterMacWindow(winRef);
+ DisposeWindow(winRef);
+
+ for (listPtr = tkMacOSXWindowListPtr, prevPtr = NULL;
+ tkMacOSXWindowListPtr != NULL;
+ prevPtr = listPtr, listPtr = listPtr->nextPtr) {
+ if (listPtr->winPtr == macWin->winPtr) {
+ if (prevPtr == NULL) {
+ tkMacOSXWindowListPtr = listPtr->nextPtr;
+ } else {
+ prevPtr->nextPtr = listPtr->nextPtr;
+ }
+ ckfree((char *) listPtr);
+ break;
+ }
+ }
+ }
+ }
+
+ macWin->grafPtr = NULL;
+
+ /*
+ * Delay deletion of a toplevel data structure untill all
+ * children have been deleted.
+ */
+ if (macWin->toplevel->referenceCount == 0) {
+ ckfree((char *) macWin->toplevel);
+ }
+ } else {
+ CGrafPtr destPort;
+ destPort = TkMacOSXGetDrawablePort(window);
+ if (destPort != NULL) {
+ SetGWorld(destPort, NULL);
+ TkMacOSXInvalidateWindow(macWin, TK_PARENT_WINDOW);
+ }
+ if (macWin->winPtr->parentPtr != NULL) {
+ TkMacOSXInvalClipRgns(macWin->winPtr->parentPtr);
+ }
+ DisposeRgn(macWin->clipRgn);
+ DisposeRgn(macWin->aboveClipRgn);
+
+ if (macWin->toplevel->referenceCount == 0) {
+ ckfree((char *) macWin->toplevel);
+ }
+ ckfree((char *) macWin);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * XMapWindow --
+ *
+ * Map the given X Window to the screen. See X window documentation
+ * for more details.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The subwindow or toplevel may appear on the screen.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+XMapWindow(
+ Display* display, /* Display. */
+ Window window) /* Window. */
+{
+ MacDrawable *macWin = (MacDrawable *) window;
+ XEvent event;
+ CGrafPtr destPort;
+
+ /*
+ * Under certain situations it's possible for this function to be
+ * called before the toplevel window it's associated with has actually
+ * been mapped. In that case we need to create the real Macintosh
+ * window now as this function as well as other X functions assume that
+ * the portPtr is valid.
+ */
+ if (!TkMacOSXHostToplevelExists(macWin->toplevel->winPtr)) {
+ TkMacOSXMakeRealWindowExist(macWin->toplevel->winPtr);
+ }
+ destPort = TkMacOSXGetDrawablePort (window);
+
+ display->request++;
+ macWin->winPtr->flags |= TK_MAPPED;
+ if (Tk_IsTopLevel(macWin->winPtr)) {
+ if (!Tk_IsEmbedded(macWin->winPtr)) {
+ ShowWindow(GetWindowFromPort(destPort));
+ }
+
+ /*
+ * We only need to send the MapNotify event
+ * for toplevel windows.
+ */
+ event.xany.serial = display->request;
+ event.xany.send_event = False;
+ event.xany.display = display;
+
+ event.xmap.window = window;
+ event.xmap.type = MapNotify;
+ event.xmap.event = window;
+ event.xmap.override_redirect = macWin->winPtr->atts.override_redirect;
+ Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
+ } else {
+ TkMacOSXInvalClipRgns(macWin->winPtr->parentPtr);
+ }
+
+ /*
+ * Generate damage for that area of the window
+ */
+ SetGWorld (destPort, NULL);
+ TkMacOSXUpdateClipRgn(macWin->winPtr);
+ TkMacOSXInvalidateWindow(macWin, TK_PARENT_WINDOW);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * XUnmapWindow --
+ *
+ * Unmap the given X Window to the screen. See X window
+ * documentation for more details.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The subwindow or toplevel may be removed from the screen.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+XUnmapWindow(
+ Display* display, /* Display. */
+ Window window) /* Window. */
+{
+ MacDrawable *macWin = (MacDrawable *) window;
+ XEvent event;
+ CGrafPtr destPort;
+
+ destPort = TkMacOSXGetDrawablePort(window);
+
+ display->request++;
+ macWin->winPtr->flags &= ~TK_MAPPED;
+ if (Tk_IsTopLevel(macWin->winPtr)) {
+ if (!Tk_IsEmbedded(macWin->winPtr)) {
+ HideWindow(GetWindowFromPort(destPort));
+ }
+
+ /*
+ * We only need to send the UnmapNotify event
+ * for toplevel windows.
+ */
+ event.xany.serial = display->request;
+ event.xany.send_event = False;
+ event.xany.display = display;
+
+ event.xunmap.type = UnmapNotify;
+ event.xunmap.window = window;
+ event.xunmap.event = window;
+ event.xunmap.from_configure = false;
+ Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
+ } else {
+ /*
+ * Generate damage for that area of the window.
+ */
+ SetGWorld(destPort, NULL);
+ TkMacOSXInvalidateWindow(macWin, TK_PARENT_WINDOW); /* TODO: may not be valid */
+ TkMacOSXInvalClipRgns(macWin->winPtr->parentPtr);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * XResizeWindow --
+ *
+ * Resize a given X window. See X windows documentation for
+ * further details.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+XResizeWindow(
+ Display* display, /* Display. */
+ Window window, /* Window. */
+ unsigned int width,
+ unsigned int height)
+{
+ MacDrawable *macWin = (MacDrawable *) window;
+ CGrafPtr destPort;
+
+ destPort = TkMacOSXGetDrawablePort(window);
+ if (destPort == NULL) {
+ return;
+ }
+
+ display->request++;
+ SetPort( destPort);
+ if (Tk_IsTopLevel(macWin->winPtr)) {
+ if (!Tk_IsEmbedded(macWin->winPtr)) {
+ /*
+ * NOTE: we are not adding the new space to the update
+ * region. It is currently assumed that Tk will need
+ * to completely redraw anway.
+ */
+ SizeWindow(GetWindowFromPort(destPort),
+ (short) width, (short) height, false);
+ TkMacOSXInvalidateWindow(macWin, TK_WINDOW_ONLY);
+ TkMacOSXInvalClipRgns(macWin->winPtr);
+ } else {
+ int deltaX, deltaY;
+
+ /*
+ * Find the Parent window -
+ * For an embedded window this will be its container.
+ */
+ TkWindow *contWinPtr;
+
+ contWinPtr = TkpGetOtherWindow(macWin->winPtr);
+
+ if (contWinPtr != NULL) {
+ MacDrawable *macParent = contWinPtr->privatePtr;
+
+ TkMacOSXInvalClipRgns(macParent->winPtr);
+ TkMacOSXInvalidateWindow(macWin, TK_PARENT_WINDOW);
+
+ deltaX = macParent->xOff +
+ macWin->winPtr->changes.x - macWin->xOff;
+ deltaY = macParent->yOff +
+ macWin->winPtr->changes.y - macWin->yOff;
+
+ UpdateOffsets(macWin->winPtr, deltaX, deltaY);
+ } else {
+ /*
+ * This is the case where we are embedded in
+ * another app. At this point, we are assuming that
+ * the changes.x,y is not maintained, if you need
+ * the info get it from Tk_GetRootCoords,
+ * and that the toplevel sits at 0,0 when it is drawn.
+ */
+
+ TkMacOSXInvalidateWindow(macWin, TK_PARENT_WINDOW);
+ UpdateOffsets(macWin->winPtr, 0, 0);
+ }
+
+ }
+ } else {
+ /* TODO: update all xOff & yOffs */
+ int deltaX, deltaY, parentBorderwidth;
+ MacDrawable *macParent = macWin->winPtr->parentPtr->privatePtr;
+
+ if (macParent == NULL) {
+ return; /* TODO: Probably should be a panic */
+ }
+
+ TkMacOSXInvalClipRgns(macParent->winPtr);
+ TkMacOSXInvalidateWindow(macWin, TK_PARENT_WINDOW);
+
+ deltaX = - macWin->xOff;
+ deltaY = - macWin->yOff;
+
+ parentBorderwidth = macWin->winPtr->parentPtr->changes.border_width;
+
+ deltaX += macParent->xOff + parentBorderwidth +
+ macWin->winPtr->changes.x;
+ deltaY += macParent->yOff + parentBorderwidth +
+ macWin->winPtr->changes.y;
+
+ UpdateOffsets(macWin->winPtr, deltaX, deltaY);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * XMoveResizeWindow --
+ *
+ * Move or resize a given X window. See X windows documentation
+ * for further details.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+XMoveResizeWindow(
+ Display* display, /* Display. */
+ Window window, /* Window. */
+ int x, int y,
+ unsigned int width,
+ unsigned int height)
+{
+ MacDrawable * macWin = (MacDrawable *) window;
+ CGrafPtr destPort;
+
+ destPort = TkMacOSXGetDrawablePort(window);
+ if (destPort == NULL) {
+ return;
+ }
+
+ SetPort( destPort);
+ if (Tk_IsTopLevel(macWin->winPtr) && !Tk_IsEmbedded(macWin->winPtr)) {
+ /*
+ * NOTE: we are not adding the new space to the update
+ * region. It is currently assumed that Tk will need
+ * to completely redraw anway.
+ */
+
+ SizeWindow(GetWindowFromPort(destPort),
+ (short) width, (short) height, false);
+ MoveWindowStructure(GetWindowFromPort(destPort), x, y);
+
+ /* TODO: is the following right? */
+ TkMacOSXInvalidateWindow(macWin, TK_WINDOW_ONLY);
+ TkMacOSXInvalClipRgns(macWin->winPtr);
+ } else {
+ int deltaX, deltaY, parentBorderwidth;
+ Rect bounds;
+ MacDrawable *macParent;
+
+ /*
+ * Find the Parent window -
+ * For an embedded window this will be its container.
+ */
+
+ if (Tk_IsEmbedded(macWin->winPtr)) {
+ TkWindow *contWinPtr;
+
+ contWinPtr = TkpGetOtherWindow(macWin->winPtr);
+ if (contWinPtr == NULL) {
+ panic("XMoveResizeWindow could not find container");
+ }
+ macParent = contWinPtr->privatePtr;
+
+ /*
+ * NOTE: Here we should handle out of process embedding.
+ */
+
+
+ } else {
+ macParent = macWin->winPtr->parentPtr->privatePtr;
+ if (macParent == NULL) {
+ return; /* TODO: Probably should be a panic */
+ }
+ }
+
+ TkMacOSXInvalClipRgns(macParent->winPtr);
+ TkMacOSXInvalidateWindow(macWin, TK_PARENT_WINDOW);
+
+ deltaX = - macWin->xOff;
+ deltaY = - macWin->yOff;
+
+ /*
+ * If macWin->winPtr is an embedded window, don't offset by its
+ * parent's borderwidth...
+ */
+
+ if (!Tk_IsEmbedded(macWin->winPtr)) {
+ parentBorderwidth = macWin->winPtr->parentPtr->changes.border_width;
+ } else {
+ parentBorderwidth = 0;
+ }
+ deltaX += macParent->xOff + parentBorderwidth +
+ macWin->winPtr->changes.x;
+ deltaY += macParent->yOff + parentBorderwidth +
+ macWin->winPtr->changes.y;
+
+ UpdateOffsets(macWin->winPtr, deltaX, deltaY);
+ TkMacOSXWinBounds(macWin->winPtr, &bounds);
+ InvalWindowRect(GetWindowFromPort(destPort),&bounds);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * XMoveWindow --
+ *
+ * Move a given X window. See X windows documentation for further
+ * details.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+XMoveWindow(
+ Display* display, /* Display. */
+ Window window, /* Window. */
+ int x,
+ int y)
+{
+ MacDrawable *macWin = (MacDrawable *) window;
+ CGrafPtr destPort;
+
+ destPort = TkMacOSXGetDrawablePort(window);
+ if (destPort == NULL) {
+ return;
+ }
+
+ SetPort( destPort);
+ if (Tk_IsTopLevel(macWin->winPtr) && !Tk_IsEmbedded(macWin->winPtr)) {
+ /*
+ * NOTE: we are not adding the new space to the update
+ * region. It is currently assumed that Tk will need
+ * to completely redraw anway.
+ */
+ MoveWindowStructure( GetWindowFromPort(destPort), x, y);
+
+ /* TODO: is the following right? */
+ TkMacOSXInvalidateWindow(macWin, TK_WINDOW_ONLY);
+ TkMacOSXInvalClipRgns(macWin->winPtr);
+ } else {
+ int deltaX, deltaY, parentBorderwidth;
+ Rect bounds;
+ MacDrawable *macParent;
+
+ /*
+ * Find the Parent window -
+ * For an embedded window this will be its container.
+ */
+
+ if (Tk_IsEmbedded(macWin->winPtr)) {
+ TkWindow *contWinPtr;
+
+ contWinPtr = TkpGetOtherWindow(macWin->winPtr);
+ if (contWinPtr == NULL) {
+ panic("XMoveWindow could not find container");
+ }
+ macParent = contWinPtr->privatePtr;
+
+ /*
+ * NOTE: Here we should handle out of process embedding.
+ */
+
+ } else {
+ macParent = macWin->winPtr->parentPtr->privatePtr;
+ if (macParent == NULL) {
+ return; /* TODO: Probably should be a panic */
+ }
+ }
+
+ TkMacOSXInvalClipRgns(macParent->winPtr);
+ TkMacOSXInvalidateWindow(macWin, TK_PARENT_WINDOW);
+
+ deltaX = - macWin->xOff;
+ deltaY = - macWin->yOff;
+
+ /*
+ * If macWin->winPtr is an embedded window, don't offset by its
+ * parent's borderwidth...
+ */
+
+ if (!Tk_IsEmbedded(macWin->winPtr)) {
+ parentBorderwidth = macWin->winPtr->parentPtr->changes.border_width;
+ } else {
+ parentBorderwidth = 0;
+ }
+ deltaX += macParent->xOff + parentBorderwidth +
+ macWin->winPtr->changes.x;
+ deltaY += macParent->yOff + parentBorderwidth +
+ macWin->winPtr->changes.y;
+
+ UpdateOffsets(macWin->winPtr, deltaX, deltaY);
+ TkMacOSXWinBounds(macWin->winPtr, &bounds);
+ InvalWindowRect(GetWindowFromPort(destPort),&bounds);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * XRaiseWindow --
+ *
+ * Change the stacking order of a window.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Changes the stacking order of the specified window.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+XRaiseWindow(
+ Display* display, /* Display. */
+ Window window) /* Window. */
+{
+ MacDrawable *macWin = (MacDrawable *) window;
+
+ display->request++;
+ if (Tk_IsTopLevel(macWin->winPtr) && !Tk_IsEmbedded(macWin->winPtr)) {
+ TkWmRestackToplevel(macWin->winPtr, Above, NULL);
+ } else {
+ /* TODO: this should generate damage */
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * XLowerWindow --
+ *
+ * Change the stacking order of a window.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Changes the stacking order of the specified window.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+XLowerWindow(
+ Display* display, /* Display. */
+ Window window) /* Window. */
+{
+ MacDrawable *macWin = (MacDrawable *) window;
+
+ display->request++;
+ if (Tk_IsTopLevel(macWin->winPtr) && !Tk_IsEmbedded(macWin->winPtr)) {
+ TkWmRestackToplevel(macWin->winPtr, Below, NULL);
+ } else {
+ /* TODO: this should generate damage */
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * XConfigureWindow --
+ *
+ * Change the size, position, stacking, or border of the specified
+ * window.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Changes the attributes of the specified window. Note that we
+ * ignore the passed in values and use the values stored in the
+ * TkWindow data structure.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+XConfigureWindow(
+ Display* display, /* Display. */
+ Window w, /* Window. */
+ unsigned int value_mask,
+ XWindowChanges* values)
+{
+ MacDrawable *macWin = (MacDrawable *) w;
+ TkWindow *winPtr = macWin->winPtr;
+
+ display->request++;
+
+ /*
+ * Change the shape and/or position of the window.
+ */
+
+ if (value_mask & (CWX|CWY|CWWidth|CWHeight)) {
+ XMoveResizeWindow(display, w, winPtr->changes.x, winPtr->changes.y,
+ winPtr->changes.width, winPtr->changes.height);
+ }
+
+ /*
+ * Change the stacking order of the window. Tk actuall keeps all
+ * the information we need for stacking order. All we need to do
+ * is make sure the clipping regions get updated and generate damage
+ * that will ensure things get drawn correctly.
+ */
+
+ if (value_mask & CWStackMode) {
+ Rect bounds;
+ CGrafPtr destPort;
+
+ destPort = TkMacOSXGetDrawablePort(w);
+ if (destPort != NULL) {
+ SetPort( destPort);
+ TkMacOSXInvalClipRgns(winPtr->parentPtr);
+ TkMacOSXWinBounds(winPtr, &bounds);
+ InvalWindowRect(GetWindowFromPort(destPort),&bounds);
+ }
+ }
+
+ /* TkGenWMMoveRequestEvent(macWin->winPtr,
+ macWin->winPtr->changes.x, macWin->winPtr->changes.y); */
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacOSXUpdateClipRgn --
+ *
+ * This function updates the cliping regions for a given window
+ * and all of its children. Once updated the TK_CLIP_INVALID flag
+ * in the subwindow data structure is unset. The TK_CLIP_INVALID
+ * flag should always be unset before any drawing is attempted.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The clip regions for the window and its children are updated.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkMacOSXUpdateClipRgn(
+ TkWindow *winPtr)
+{
+ RgnHandle rgn;
+ int x, y;
+ TkWindow *win2Ptr;
+
+ if (winPtr == NULL) {
+ return;
+ }
+
+ if (winPtr->privatePtr->flags & TK_CLIP_INVALID) {
+ rgn = winPtr->privatePtr->aboveClipRgn;
+ if (tmpRgn == NULL) {
+ tmpRgn = NewRgn();
+ }
+
+ /*
+ * Start with a region defined by the window bounds.
+ */
+
+ x = winPtr->privatePtr->xOff;
+ y = winPtr->privatePtr->yOff;
+ SetRectRgn(rgn, (short) x, (short) y,
+ (short) (winPtr->changes.width + x),
+ (short) (winPtr->changes.height + y));
+
+ /*
+ * Clip away the area of any windows that may obscure this
+ * window.
+ * For a non-toplevel window, first, clip to the parents visable
+ * clip region.
+ * Second, clip away any siblings that are higher in the
+ * stacking order.
+ * For an embedded toplevel, just clip to the container's visible
+ * clip region. Remember, we only allow one contained window
+ * in a frame, and don't support any other widgets in the frame either.
+ * This is not currently enforced, however.
+ */
+
+ if (!Tk_IsTopLevel(winPtr)) {
+ TkMacOSXUpdateClipRgn(winPtr->parentPtr);
+ SectRgn(rgn,
+ winPtr->parentPtr->privatePtr->aboveClipRgn, rgn);
+
+ win2Ptr = winPtr->nextPtr;
+ while (win2Ptr != NULL) {
+ if (Tk_IsTopLevel(win2Ptr) || !Tk_IsMapped(win2Ptr)) {
+ win2Ptr = win2Ptr->nextPtr;
+ continue;
+ }
+ x = win2Ptr->privatePtr->xOff;
+ y = win2Ptr->privatePtr->yOff;
+ SetRectRgn(tmpRgn, (short) x, (short) y,
+ (short) (win2Ptr->changes.width + x),
+ (short) (win2Ptr->changes.height + y));
+ DiffRgn(rgn, tmpRgn, rgn);
+
+ win2Ptr = win2Ptr->nextPtr;
+ }
+ } else if (Tk_IsEmbedded(winPtr)) {
+ TkWindow *contWinPtr;
+
+ contWinPtr = TkpGetOtherWindow(winPtr);
+
+ if (contWinPtr != NULL) {
+ TkMacOSXUpdateClipRgn(contWinPtr);
+ SectRgn(rgn,
+ contWinPtr->privatePtr->aboveClipRgn, rgn);
+ } else if (gMacEmbedHandler != NULL) {
+ gMacEmbedHandler->getClipProc((Tk_Window) winPtr, tmpRgn);
+ SectRgn(rgn, tmpRgn, rgn);
+ }
+
+ /*
+ * NOTE: Here we should handle out of process embedding.
+ */
+
+ }
+
+ /*
+ * The final clip region is the aboveClip region (or visable
+ * region) minus all the children of this window.
+ * Alternatively, if the window is a container, we must also
+ * subtract the region of the embedded window.
+ */
+
+ rgn = winPtr->privatePtr->clipRgn;
+ CopyRgn(winPtr->privatePtr->aboveClipRgn, rgn);
+
+ win2Ptr = winPtr->childList;
+ while (win2Ptr != NULL) {
+ if (Tk_IsTopLevel(win2Ptr) || !Tk_IsMapped(win2Ptr)) {
+ win2Ptr = win2Ptr->nextPtr;
+ continue;
+ }
+ x = win2Ptr->privatePtr->xOff;
+ y = win2Ptr->privatePtr->yOff;
+ SetRectRgn(tmpRgn, (short) x, (short) y,
+ (short) (win2Ptr->changes.width + x),
+ (short) (win2Ptr->changes.height + y));
+ DiffRgn(rgn, tmpRgn, rgn);
+
+ win2Ptr = win2Ptr->nextPtr;
+ }
+
+ if (Tk_IsContainer(winPtr)) {
+ win2Ptr = TkpGetOtherWindow(winPtr);
+ if (win2Ptr != NULL) {
+ if (Tk_IsMapped(win2Ptr)) {
+ x = win2Ptr->privatePtr->xOff;
+ y = win2Ptr->privatePtr->yOff;
+ SetRectRgn(tmpRgn, (short) x, (short) y,
+ (short) (win2Ptr->changes.width + x),
+ (short) (win2Ptr->changes.height + y));
+ DiffRgn(rgn, tmpRgn, rgn);
+ }
+ }
+
+ /*
+ * NOTE: Here we should handle out of process embedding.
+ */
+
+ }
+
+ winPtr->privatePtr->flags &= ~TK_CLIP_INVALID;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacOSXVisableClipRgn --
+ *
+ * This function returnd the Macintosh cliping region for the
+ * given window. A NULL Rgn means the window is not visable.
+ *
+ * Results:
+ * The region.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+RgnHandle
+TkMacOSXVisableClipRgn(
+ TkWindow *winPtr)
+{
+ if (winPtr->privatePtr->flags & TK_CLIP_INVALID) {
+ TkMacOSXUpdateClipRgn(winPtr);
+ }
+
+ return winPtr->privatePtr->clipRgn;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacOSXInvalidateWindow --
+ *
+ * This function makes the window as invalid will generate damage
+ * for the window.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Damage is created.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkMacOSXInvalidateWindow(
+ MacDrawable *macWin, /* Make window that's causing damage. */
+ int flag) /* Should be TK_WINDOW_ONLY or
+ * TK_PARENT_WINDOW */
+{
+ WindowRef windowRef;
+ CGrafPtr grafPtr;
+
+ grafPtr=TkMacOSXGetDrawablePort((Drawable)macWin);
+ windowRef=GetWindowFromPort(grafPtr);
+
+ if (flag == TK_WINDOW_ONLY) {
+ InvalWindowRgn(windowRef,macWin->clipRgn);
+ } else {
+ if (!EmptyRgn(macWin->aboveClipRgn)) {
+ InvalWindowRgn(windowRef,macWin->aboveClipRgn);
+ }
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacOSXGetDrawablePort --
+ *
+ * This function returns the Graphics Port for a given X drawable.
+ *
+ * Results:
+ * A CGrafPort . Either an off screen pixmap or a Window.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+CGrafPtr
+TkMacOSXGetDrawablePort(
+ Drawable drawable)
+{
+ MacDrawable *macWin = (MacDrawable *) drawable;
+ GWorldPtr resultPort = NULL;
+
+ if (macWin == NULL) {
+ return NULL;
+ }
+
+ /*
+ * This is NULL for off-screen pixmaps. Then the portPtr
+ * always points to the off-screen port, and we don't
+ * have to worry about containment
+ */
+
+ if (macWin->clipRgn == NULL) {
+ return macWin->grafPtr;
+ }
+
+ /*
+ * If the Drawable is in an embedded window, use the Port of its container.
+ *
+ * TRICKY POINT: we can have cases when a toplevel is being destroyed
+ * where the winPtr for the toplevel has been freed, but the children
+ * are not all the way destroyed. The children will call this function
+ * as they are being destroyed, but Tk_IsEmbedded will return garbage.
+ * So we check the copy of the TK_EMBEDDED flag we put into the
+ * toplevel's macWin flags.
+ */
+
+
+
+
+ if (!(macWin->toplevel->flags & TK_EMBEDDED)) {
+ return macWin->toplevel->grafPtr;
+ } else {
+ TkWindow *contWinPtr;
+
+ contWinPtr = TkpGetOtherWindow(macWin->toplevel->winPtr);
+
+ if (contWinPtr != NULL) {
+ resultPort = TkMacOSXGetDrawablePort(
+ (Drawable) contWinPtr->privatePtr);
+ } else if (gMacEmbedHandler != NULL) {
+ resultPort = gMacEmbedHandler->getPortProc(
+ (Tk_Window) macWin->winPtr);
+ }
+
+ if (resultPort == NULL) {
+ /*
+ * FIXME:
+ *
+ * So far as I can tell, the only time that this happens is when
+ * we are tearing down an embedded child interpreter, and most
+ * of the time, this is harmless... However, we really need to
+ * find why the embedding loses.
+ */
+ DebugStr("\pTkMacOSXGetDrawablePort couldn't find container");
+ return NULL;
+ }
+
+ /*
+ * NOTE: Here we should handle out of process embedding.
+ */
+
+ }
+ return resultPort;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacOSXGetRootControl --
+ *
+ * This function returns the Root Control for a given X drawable.
+ *
+ * Results:
+ * A ControlRef .
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+ControlRef
+TkMacOSXGetRootControl(
+ Drawable drawable)
+{
+ /*
+ * will probably need to fix this up for embedding
+ */
+ MacDrawable *macWin = (MacDrawable *) drawable;
+ ControlRef result = NULL;
+
+ if (macWin == NULL) {
+ return NULL;
+ }
+ if (!(macWin->toplevel->flags & TK_EMBEDDED)) {
+ return macWin->toplevel->rootControl;
+ } else {
+ TkWindow *contWinPtr;
+
+ contWinPtr = TkpGetOtherWindow(macWin->toplevel->winPtr);
+
+ if (contWinPtr != NULL) {
+ result = TkMacOSXGetRootControl(
+ (Drawable) contWinPtr->privatePtr);
+ } else if (gMacEmbedHandler != NULL) {
+ result = NULL;
+ }
+ }
+ return result;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacOSXInvalClipRgns --
+ *
+ * This function invalidates the clipping regions for a given
+ * window and all of its children. This function should be
+ * called whenever changes are made to subwindows that would
+ * effect the size or position of windows.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The cliping regions for the window and its children are
+ * mark invalid. (Make sure they are valid before drawing.)
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkMacOSXInvalClipRgns(
+ TkWindow *winPtr)
+{
+ TkWindow *childPtr;
+
+ /*
+ * If already marked we can stop because all
+ * decendants will also already be marked.
+ */
+ if (winPtr->privatePtr->flags & TK_CLIP_INVALID) {
+ return;
+ }
+
+ winPtr->privatePtr->flags |= TK_CLIP_INVALID;
+
+ /*
+ * Invalidate clip regions for all children &
+ * their decendants - unless the child is a toplevel.
+ */
+ childPtr = winPtr->childList;
+ while (childPtr != NULL) {
+ if (!Tk_IsTopLevel(childPtr) && Tk_IsMapped(childPtr)) {
+ TkMacOSXInvalClipRgns(childPtr);
+ }
+ childPtr = childPtr->nextPtr;
+ }
+
+ /*
+ * Also, if the window is a container, mark its embedded window
+ */
+
+ if (Tk_IsContainer(winPtr)) {
+ childPtr = TkpGetOtherWindow(winPtr);
+
+ if (childPtr != NULL && Tk_IsMapped(childPtr)) {
+ TkMacOSXInvalClipRgns(childPtr);
+ }
+
+ /*
+ * NOTE: Here we should handle out of process embedding.
+ */
+
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacOSXWinBounds --
+ *
+ * Given a Tk window this function determines the windows
+ * bounds in relation to the Macintosh window's coordinate
+ * system. This is also the same coordinate system as the
+ * Tk toplevel window in which this window is contained.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkMacOSXWinBounds(
+ TkWindow *winPtr,
+ Rect *bounds)
+{
+ bounds->left = (short) winPtr->privatePtr->xOff;
+ bounds->top = (short) winPtr->privatePtr->yOff;
+ bounds->right = (short) (winPtr->privatePtr->xOff +
+ winPtr->changes.width);
+ bounds->bottom = (short) (winPtr->privatePtr->yOff +
+ winPtr->changes.height);
+}
+/*
+ *----------------------------------------------------------------------
+ *
+ * UpdateOffsets --
+ *
+ * Updates the X & Y offsets of the given TkWindow from the
+ * TopLevel it is a decendant of.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The xOff & yOff fields for the Mac window datastructure
+ * is updated to the proper offset.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+UpdateOffsets(
+ TkWindow *winPtr,
+ int deltaX,
+ int deltaY)
+{
+ TkWindow *childPtr;
+
+ if (winPtr->privatePtr == NULL) {
+ /*
+ * We havn't called Tk_MakeWindowExist for this window yet. The
+ * offset information will be postponed and calulated at that
+ * time. (This will usually only happen when a mapped parent is
+ * being moved but has child windows that have yet to be mapped.)
+ */
+ return;
+ }
+
+ winPtr->privatePtr->xOff += deltaX;
+ winPtr->privatePtr->yOff += deltaY;
+
+ childPtr = winPtr->childList;
+ while (childPtr != NULL) {
+ if (!Tk_IsTopLevel(childPtr)) {
+ UpdateOffsets(childPtr, deltaX, deltaY);
+ }
+ childPtr = childPtr->nextPtr;
+ }
+
+ if (Tk_IsContainer(winPtr)) {
+ childPtr = TkpGetOtherWindow(winPtr);
+ if (childPtr != NULL) {
+ UpdateOffsets(childPtr,deltaX,deltaY);
+ }
+
+ /*
+ * NOTE: Here we should handle out of process embedding.
+ */
+
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_GetPixmap --
+ *
+ * Creates an in memory drawing surface.
+ *
+ * Results:
+ * Returns a handle to a new pixmap.
+ *
+ * Side effects:
+ * Allocates a new Macintosh GWorld.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Pixmap
+Tk_GetPixmap(
+ Display *display, /* Display for new pixmap (can be null). */
+ Drawable d, /* Drawable where pixmap will be used (ignored). */
+ int width, /* Dimensions of pixmap. */
+ int height,
+ int depth) /* Bits per pixel for pixmap. */
+{
+ QDErr err;
+ GWorldPtr gWorld;
+ Rect bounds;
+ MacDrawable *macPix;
+ PixMapHandle pixels;
+
+ if (display != NULL) {
+ display->request++;
+ }
+ macPix = (MacDrawable *) ckalloc(sizeof(MacDrawable));
+ macPix->winPtr = NULL;
+ macPix->xOff = 0;
+ macPix->yOff = 0;
+ macPix->clipRgn = NULL;
+ macPix->aboveClipRgn = NULL;
+ macPix->referenceCount = 0;
+ macPix->toplevel = NULL;
+ macPix->flags = 0;
+
+ bounds.top = bounds.left = 0;
+ bounds.right = (short) width;
+ bounds.bottom = (short) height;
+ if (depth != 1) {
+ depth = 0;
+ }
+ /*
+ * Allocate memory for the off screen pixmap. If we fail
+ * try again from system memory. Eventually, we may have
+ * to panic.
+ */
+ err = NewGWorld(&gWorld, depth, &bounds, NULL, NULL, 0);
+ if (err != noErr) {
+ err = NewGWorld(&gWorld, depth, &bounds, NULL, NULL, useTempMem);
+ }
+ if (err != noErr) {
+ panic("Out of memory: NewGWorld failed in Tk_GetPixmap");
+ }
+
+ /*
+ * Lock down the pixels so they don't move out from under us.
+ */
+ pixels = GetGWorldPixMap(gWorld);
+ LockPixels(pixels);
+ macPix->grafPtr = gWorld;
+
+ return (Pixmap) macPix;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_FreePixmap --
+ *
+ * Release the resources associated with a pixmap.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Deletes the Macintosh GWorld created by Tk_GetPixmap.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tk_FreePixmap(
+ Display *display, /* Display. */
+ Pixmap pixmap) /* Pixmap to destroy */
+{
+ MacDrawable *macPix = (MacDrawable *) pixmap;
+ PixMapHandle pixels;
+
+ display->request++;
+ pixels = GetGWorldPixMap(macPix->grafPtr);
+ UnlockPixels(pixels);
+ DisposeGWorld(macPix->grafPtr);
+ ckfree((char *) macPix);
+}