OSDN Git Service

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