OSDN Git Service

Initial revision
[pf3gnuchains/pf3gnuchains3x.git] / tk / mac / tkMacSubwindows.c
1 /* 
2  * tkMacSubwindows.c --
3  *
4  *      Implements subwindows for the macintosh version of Tk.
5  *
6  * Copyright (c) 1995-1997 Sun Microsystems, Inc.
7  *
8  * See the file "license.terms" for information on usage and redistribution
9  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
10  *
11  * RCS: @(#) $Id$
12  */
13
14 #include "tkInt.h"
15 #include "X.h"
16 #include "Xlib.h"
17 #include <stdio.h>
18
19 #include <Windows.h>
20 #include <QDOffscreen.h>
21 #include "tkMacInt.h"
22
23 /*
24  * Temporary region that can be reused.
25  */
26 static RgnHandle tmpRgn = NULL;
27
28 static void UpdateOffsets _ANSI_ARGS_((TkWindow *winPtr, int deltaX, int deltaY));
29
30 void tkMacMoveWindow _ANSI_ARGS_((WindowRef window, int x, int y));
31 \f
32 /*
33  *----------------------------------------------------------------------
34  *
35  * XDestroyWindow --
36  *
37  *      Dealocates the given X Window.
38  *
39  * Results:
40  *      The window id is returned.
41  *
42  * Side effects:
43  *      None.
44  *
45  *----------------------------------------------------------------------
46  */
47
48 void 
49 XDestroyWindow(
50     Display* display,           /* Display. */
51     Window window)              /* Window. */
52 {
53     MacDrawable *macWin = (MacDrawable *) window;
54     GWorldPtr destPort;
55
56     /*
57      * Remove any dangling pointers that may exist if
58      * the window we are deleting is being tracked by
59      * the grab code.
60      */
61
62     TkPointerDeadWindow(macWin->winPtr);
63     macWin->toplevel->referenceCount--;
64     
65     
66     if (Tk_IsTopLevel(macWin->winPtr)) {
67         DisposeRgn(macWin->clipRgn);
68         DisposeRgn(macWin->aboveClipRgn);
69         
70         /*
71          * Delete the Mac window and remove it from the windowTable.
72          * The window could be NULL if the window was never mapped.
73          * However, we don't do this for embedded windows, they don't
74          * go in the window list, and they do not own their portPtr's.
75          */
76          
77         if (!(Tk_IsEmbedded(macWin->winPtr))) {
78             destPort = TkMacGetDrawablePort(window);
79             if (destPort != NULL) {
80                 TkMacWindowList *listPtr, *prevPtr;
81             
82                 TkMacUnregisterMacWindow(destPort);
83                 DisposeWindow((WindowRef) destPort);
84             
85                 for (listPtr = tkMacWindowListPtr, prevPtr = NULL;
86                         tkMacWindowListPtr != NULL;
87                         prevPtr = listPtr, listPtr = listPtr->nextPtr) {
88                     if (listPtr->winPtr == macWin->winPtr) {
89                         if (prevPtr == NULL) {
90                             tkMacWindowListPtr = listPtr->nextPtr;
91                         } else {
92                             prevPtr->nextPtr = listPtr->nextPtr;
93                         }
94                         ckfree((char *) listPtr);
95                         break;
96                     }
97                 }
98             }
99         }
100         
101         macWin->portPtr = NULL;
102         
103         /*
104          * Delay deletion of a toplevel data structure untill all
105          * children have been deleted.
106          */
107         if (macWin->toplevel->referenceCount == 0) {
108             ckfree((char *) macWin->toplevel);
109         }
110     } else {
111         destPort = TkMacGetDrawablePort(window);
112         if (destPort != NULL) {
113             SetGWorld(destPort, NULL);
114             TkMacInvalidateWindow(macWin, TK_PARENT_WINDOW);
115         }
116         if (macWin->winPtr->parentPtr != NULL) {
117             TkMacInvalClipRgns(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     GWorldPtr 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 (!TkMacHostToplevelExists(macWin->toplevel->winPtr)) {
163         TkMacMakeRealWindowExist(macWin->toplevel->winPtr);
164     }
165     destPort = TkMacGetDrawablePort(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((WindowRef) 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         TkMacInvalClipRgns(macWin->winPtr->parentPtr);
189     }
190
191     /* 
192      * Generate damage for that area of the window 
193      */
194     SetGWorld(destPort, NULL);
195     TkMacUpdateClipRgn(macWin->winPtr);
196     TkMacInvalidateWindow(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     GWorldPtr destPort;
224
225     destPort = TkMacGetDrawablePort(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((WindowRef) 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         TkMacInvalidateWindow(macWin, TK_PARENT_WINDOW); /* TODO: may not be valid */
253         TkMacInvalClipRgns(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     GWorldPtr destPort;
283
284     destPort = TkMacGetDrawablePort(window);
285     if (destPort == NULL) {
286         return;
287     }
288
289     display->request++;
290     SetPort((GrafPtr) 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((WindowRef) destPort,
299                     (short) width, (short) height, false);
300             TkMacInvalidateWindow(macWin, TK_WINDOW_ONLY);
301             TkMacInvalClipRgns(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                 TkMacInvalClipRgns(macParent->winPtr);  
317                 TkMacInvalidateWindow(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                 TkMacInvalidateWindow(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         TkMacInvalClipRgns(macParent->winPtr);  
349         TkMacInvalidateWindow(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     GWorldPtr destPort;
392
393     destPort = TkMacGetDrawablePort(window);
394     if (destPort == NULL) {
395         return;
396     }
397
398     SetPort((GrafPtr) 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((WindowRef) destPort,
407                 (short) width, (short) height, false);
408         tkMacMoveWindow((WindowRef) destPort, x, y);
409         
410         /* TODO: is the following right? */
411         TkMacInvalidateWindow(macWin, TK_WINDOW_ONLY);
412         TkMacInvalClipRgns(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         TkMacInvalClipRgns(macParent->winPtr);
445         TkMacInvalidateWindow(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         TkMacWinBounds(macWin->winPtr, &bounds);
467         InvalRect(&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     GWorldPtr destPort;
497
498     destPort = TkMacGetDrawablePort(window);
499     if (destPort == NULL) {
500         return;
501     }
502
503     SetPort((GrafPtr) 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         tkMacMoveWindow((WindowRef) destPort, x, y);
511
512         /* TODO: is the following right? */
513         TkMacInvalidateWindow(macWin, TK_WINDOW_ONLY);
514         TkMacInvalClipRgns(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         TkMacInvalClipRgns(macParent->winPtr);
546         TkMacInvalidateWindow(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         TkMacWinBounds(macWin->winPtr, &bounds);
568         InvalRect(&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  * XConfigureWindow --
607  *
608  *      Change the size, position, stacking, or border of the specified
609  *      window.
610  *
611  * Results:
612  *      None.
613  *
614  * Side effects:
615  *      Changes the attributes of the specified window.  Note that we
616  *      ignore the passed in values and use the values stored in the
617  *      TkWindow data structure.
618  *
619  *----------------------------------------------------------------------
620  */
621
622 void
623 XConfigureWindow(
624     Display* display,           /* Display. */
625     Window w,                   /* Window. */
626     unsigned int value_mask,
627     XWindowChanges* values)
628 {
629     MacDrawable *macWin = (MacDrawable *) w;
630     TkWindow *winPtr = macWin->winPtr;
631
632     display->request++;
633
634     /*
635      * Change the shape and/or position of the window.
636      */
637
638     if (value_mask & (CWX|CWY|CWWidth|CWHeight)) {
639         XMoveResizeWindow(display, w, winPtr->changes.x, winPtr->changes.y,
640                 winPtr->changes.width, winPtr->changes.height);
641     }
642
643     /*
644      * Change the stacking order of the window.  Tk actuall keeps all
645      * the information we need for stacking order.  All we need to do
646      * is make sure the clipping regions get updated and generate damage
647      * that will ensure things get drawn correctly.
648      */
649
650     if (value_mask & CWStackMode) {
651         Rect bounds;
652         GWorldPtr destPort;
653         
654         destPort = TkMacGetDrawablePort(w);
655         if (destPort != NULL) {
656             SetPort((GrafPtr) destPort);
657             TkMacInvalClipRgns(winPtr->parentPtr);
658             TkMacWinBounds(winPtr, &bounds);
659             InvalRect(&bounds);
660         }
661     } 
662
663     /* TkGenWMMoveRequestEvent(macWin->winPtr, 
664             macWin->winPtr->changes.x, macWin->winPtr->changes.y); */
665 }
666 \f
667 /*
668  *----------------------------------------------------------------------
669  *
670  *  TkMacUpdateClipRgn --
671  *
672  *      This function updates the cliping regions for a given window
673  *      and all of its children.  Once updated the TK_CLIP_INVALID flag
674  *      in the subwindow data structure is unset.  The TK_CLIP_INVALID 
675  *      flag should always be unset before any drawing is attempted.
676  *
677  * Results:
678  *      None.
679  *
680  * Side effects:
681  *      The clip regions for the window and its children are updated.
682  *
683  *----------------------------------------------------------------------
684  */
685
686 void
687 TkMacUpdateClipRgn(
688     TkWindow *winPtr)
689 {
690     RgnHandle rgn;
691     int x, y;
692     TkWindow *win2Ptr;
693
694     if (winPtr == NULL) {
695         return;
696     }
697     
698     if (winPtr->privatePtr->flags & TK_CLIP_INVALID) {
699         rgn = winPtr->privatePtr->aboveClipRgn;
700         if (tmpRgn == NULL) {
701             tmpRgn = NewRgn();
702         }
703         
704         /* 
705          * Start with a region defined by the window bounds.  
706          */
707
708         x = winPtr->privatePtr->xOff;
709         y = winPtr->privatePtr->yOff;
710         SetRectRgn(rgn, (short) x, (short) y,
711             (short) (winPtr->changes.width  + x), 
712             (short) (winPtr->changes.height + y));
713             
714         /* 
715          * Clip away the area of any windows that may obscure this
716          * window.  
717          * For a non-toplevel window, first, clip to the parents visable
718          * clip region.
719          * Second, clip away any siblings that are higher in the
720          * stacking order.
721          * For an embedded toplevel, just clip to the container's visible
722          * clip region.  Remember, we only allow one contained window 
723          * in a frame, and don't support any other widgets in the frame either.
724          * This is not currently enforced, however.
725          */
726         
727         if (!Tk_IsTopLevel(winPtr)) { 
728             TkMacUpdateClipRgn(winPtr->parentPtr);
729             SectRgn(rgn, 
730                     winPtr->parentPtr->privatePtr->aboveClipRgn, rgn);
731                                 
732             win2Ptr = winPtr->nextPtr;
733             while (win2Ptr != NULL) {
734                 if (Tk_IsTopLevel(win2Ptr) || !Tk_IsMapped(win2Ptr)) {
735                     win2Ptr = win2Ptr->nextPtr;
736                     continue;
737                 }
738                 x = win2Ptr->privatePtr->xOff;
739                 y = win2Ptr->privatePtr->yOff;
740                 SetRectRgn(tmpRgn, (short) x, (short) y,
741                         (short) (win2Ptr->changes.width  + x), 
742                         (short) (win2Ptr->changes.height + y));
743                 DiffRgn(rgn, tmpRgn, rgn);
744                                                           
745                 win2Ptr = win2Ptr->nextPtr;
746             }
747         } else if (Tk_IsEmbedded(winPtr)) {
748             TkWindow *contWinPtr;
749         
750             contWinPtr = TkpGetOtherWindow(winPtr);
751              
752             if (contWinPtr != NULL) {
753                 TkMacUpdateClipRgn(contWinPtr);
754                 SectRgn(rgn, 
755                         contWinPtr->privatePtr->aboveClipRgn, rgn);
756             } else if (gMacEmbedHandler != NULL) {
757                 gMacEmbedHandler->getClipProc((Tk_Window) winPtr, tmpRgn);
758                 SectRgn(rgn, tmpRgn, rgn);
759             }
760             
761             /*
762              * NOTE: Here we should handle out of process embedding.
763              */
764                     
765         }
766         
767         /* 
768          * The final clip region is the aboveClip region (or visable
769          * region) minus all the children of this window.
770          * Alternatively, if the window is a container, we must also 
771          * subtract the region of the embedded window.
772          */
773          
774         rgn = winPtr->privatePtr->clipRgn;
775         CopyRgn(winPtr->privatePtr->aboveClipRgn, rgn);
776                 
777         win2Ptr = winPtr->childList;
778         while (win2Ptr != NULL) {
779             if (Tk_IsTopLevel(win2Ptr) || !Tk_IsMapped(win2Ptr)) {
780                 win2Ptr = win2Ptr->nextPtr;
781                 continue;
782             }
783             x = win2Ptr->privatePtr->xOff;
784             y = win2Ptr->privatePtr->yOff;
785             SetRectRgn(tmpRgn, (short) x, (short) y,
786                     (short) (win2Ptr->changes.width  + x), 
787                     (short) (win2Ptr->changes.height + y));
788             DiffRgn(rgn, tmpRgn, rgn);
789                                                           
790             win2Ptr = win2Ptr->nextPtr;
791         }
792         
793         if (Tk_IsContainer(winPtr)) {
794             win2Ptr = TkpGetOtherWindow(winPtr);
795             if (win2Ptr != NULL) {
796                 if (Tk_IsMapped(win2Ptr)) {
797                     x = win2Ptr->privatePtr->xOff;
798                     y = win2Ptr->privatePtr->yOff;
799                     SetRectRgn(tmpRgn, (short) x, (short) y,
800                             (short) (win2Ptr->changes.width  + x), 
801                             (short) (win2Ptr->changes.height + y));
802                     DiffRgn(rgn, tmpRgn, rgn);
803                 }
804             } 
805             
806             /*
807              * NOTE: Here we should handle out of process embedding.
808              */
809                     
810         }
811                 
812         winPtr->privatePtr->flags &= ~TK_CLIP_INVALID;
813     }
814 }
815 \f
816 /*
817  *----------------------------------------------------------------------
818  *
819  * TkMacVisableClipRgn --
820  *
821  *      This function returnd the Macintosh cliping region for the 
822  *      given window.  A NULL Rgn means the window is not visable.
823  *
824  * Results:
825  *      The region.
826  *
827  * Side effects:
828  *      None.
829  *
830  *----------------------------------------------------------------------
831  */
832
833 RgnHandle
834 TkMacVisableClipRgn(
835     TkWindow *winPtr)
836 {
837     if (winPtr->privatePtr->flags & TK_CLIP_INVALID) {
838         TkMacUpdateClipRgn(winPtr);
839     }
840
841     return winPtr->privatePtr->clipRgn;
842 }
843 \f
844 /*
845  *----------------------------------------------------------------------
846  *
847  * TkMacInvalidateWindow --
848  *
849  *      This function makes the window as invalid will generate damage
850  *      for the window.
851  *
852  * Results:
853  *      None.
854  *
855  * Side effects:
856  *      Damage is created.
857  *
858  *----------------------------------------------------------------------
859  */
860
861 void
862 TkMacInvalidateWindow(
863     MacDrawable *macWin,        /* Make window that's causing damage. */
864     int flag)                   /* Should be TK_WINDOW_ONLY or
865                                  * TK_PARENT_WINDOW */
866 {
867     
868     if (flag == TK_WINDOW_ONLY) {
869         InvalRgn(macWin->clipRgn);
870     } else {
871         if (!EmptyRgn(macWin->aboveClipRgn)) {
872             InvalRgn(macWin->aboveClipRgn);
873         }
874     }
875 }
876 \f
877 /*
878  *----------------------------------------------------------------------
879  *
880  * TkMacGetDrawablePort --
881  *
882  *      This function returns the Graphics Port for a given X drawable.
883  *
884  * Results:
885  *      A GWorld pointer.  Either an off screen pixmap or a Window.
886  *
887  * Side effects:
888  *      None.
889  *
890  *----------------------------------------------------------------------
891  */
892
893 GWorldPtr
894 TkMacGetDrawablePort(
895     Drawable drawable)
896 {
897     MacDrawable *macWin = (MacDrawable *) drawable;
898     GWorldPtr resultPort = NULL;
899     
900     if (macWin == NULL) {
901         return NULL;
902     }
903     
904     /*
905      * This is NULL for off-screen pixmaps.  Then the portPtr
906      * always points to the off-screen port, and we don't
907      * have to worry about containment
908      */
909      
910     if (macWin->clipRgn == NULL) {
911         return macWin->portPtr;
912     }
913     
914     /*
915      * If the Drawable is in an embedded window, use the Port of its container.
916      *  
917      * TRICKY POINT: we can have cases when a toplevel is being destroyed
918      * where the winPtr for the toplevel has been freed, but the children 
919      * are not all the way destroyed.  The children will call this function
920      * as they are being destroyed, but Tk_IsEmbedded will return garbage.
921      * So we check the copy of the TK_EMBEDDED flag we put into the 
922      * toplevel's macWin flags.
923      */
924     
925     if (!(macWin->toplevel->flags & TK_EMBEDDED)) {
926         return macWin->toplevel->portPtr;
927     } else {
928         TkWindow *contWinPtr;
929
930         contWinPtr = TkpGetOtherWindow(macWin->toplevel->winPtr);
931         
932         if (contWinPtr != NULL) {
933             resultPort = TkMacGetDrawablePort((Drawable) contWinPtr->privatePtr);
934         } else if (gMacEmbedHandler != NULL) {
935             resultPort = gMacEmbedHandler->getPortProc(
936                     (Tk_Window) macWin->winPtr);
937         } 
938         
939         if (resultPort == NULL) {
940             panic("TkMacGetDrawablePort couldn't find container");
941             return NULL;
942         }       
943             
944         /*
945          * NOTE: Here we should handle out of process embedding.
946          */
947                     
948     }
949     return resultPort;
950 }
951 \f
952 /*
953  *----------------------------------------------------------------------
954  *
955  * TkMacInvalClipRgns --
956  *
957  *      This function invalidates the clipping regions for a given
958  *      window and all of its children.  This function should be
959  *      called whenever changes are made to subwindows that would
960  *      effect the size or position of windows.
961  *
962  * Results:
963  *      None.
964  *
965  * Side effects:
966  *      The cliping regions for the window and its children are
967  *      mark invalid.  (Make sure they are valid before drawing.)
968  *
969  *----------------------------------------------------------------------
970  */
971
972 void
973 TkMacInvalClipRgns(
974     TkWindow *winPtr)
975 {
976     TkWindow *childPtr;
977         
978     /* 
979      * If already marked we can stop because all 
980      * decendants will also already be marked.
981      */
982     if (winPtr->privatePtr->flags & TK_CLIP_INVALID) {
983         return;
984     }
985         
986     winPtr->privatePtr->flags |= TK_CLIP_INVALID;
987         
988     /* 
989      * Invalidate clip regions for all children & 
990      * their decendants - unless the child is a toplevel.
991      */
992     childPtr = winPtr->childList;
993     while (childPtr != NULL) {
994         if (!Tk_IsTopLevel(childPtr) && Tk_IsMapped(childPtr)) {
995             TkMacInvalClipRgns(childPtr);
996         }
997         childPtr = childPtr->nextPtr;
998     }
999     
1000     /*
1001      * Also, if the window is a container, mark its embedded window
1002      */
1003      
1004     if (Tk_IsContainer(winPtr)) {
1005         childPtr = TkpGetOtherWindow(winPtr);
1006
1007         if (childPtr != NULL && Tk_IsMapped(childPtr)) {
1008             TkMacInvalClipRgns(childPtr);
1009         }
1010         
1011         /*
1012          * NOTE: Here we should handle out of process embedding.
1013          */
1014                         
1015     }               
1016 }
1017 \f
1018 /*
1019  *----------------------------------------------------------------------
1020  *
1021  * TkMacWinBounds --
1022  *
1023  *      Given a Tk window this function determines the windows
1024  *      bounds in relation to the Macintosh window's coordinate
1025  *      system.  This is also the same coordinate system as the
1026  *      Tk toplevel window in which this window is contained.
1027  *
1028  * Results:
1029  *      None.
1030  *
1031  * Side effects:
1032  *      None.
1033  *
1034  *----------------------------------------------------------------------
1035  */
1036
1037 void
1038 TkMacWinBounds(
1039     TkWindow *winPtr,
1040     Rect *bounds)
1041 {
1042     bounds->left = (short) winPtr->privatePtr->xOff;
1043     bounds->top = (short) winPtr->privatePtr->yOff;
1044     bounds->right = (short) (winPtr->privatePtr->xOff +
1045             winPtr->changes.width);
1046     bounds->bottom = (short) (winPtr->privatePtr->yOff +
1047             winPtr->changes.height);
1048 }
1049 \f
1050 /*
1051  *----------------------------------------------------------------------
1052  *
1053  * tkMacMoveWindow --
1054  *
1055  *      A replacement for the Macintosh MoveWindow function.  This
1056  *      function adjusts the inputs to MoveWindow to offset the root of 
1057  *      the window system.  This has the effect of making the coords 
1058  *      refer to the window dressing rather than the top of the content.
1059  *
1060  * Results:
1061  *      None.
1062  *
1063  * Side effects:
1064  *      Moves the Macintosh window.
1065  *
1066  *----------------------------------------------------------------------
1067  */
1068
1069 void 
1070 tkMacMoveWindow(
1071     WindowRef window,
1072     int x,
1073     int y)
1074 {
1075     int xOffset, yOffset;
1076
1077     TkMacWindowOffset(window, &xOffset, &yOffset);
1078     MoveWindow((WindowRef) window, 
1079         (short) (x + xOffset), (short) (y + yOffset), false);
1080 }
1081 \f
1082 /*
1083  *----------------------------------------------------------------------
1084  *
1085  * UpdateOffsets --
1086  *
1087  *      Updates the X & Y offsets of the given TkWindow from the
1088  *      TopLevel it is a decendant of.
1089  *
1090  * Results:
1091  *      None.
1092  *
1093  * Side effects:
1094  *      The xOff & yOff fields for the Mac window datastructure
1095  *      is updated to the proper offset.
1096  *
1097  *----------------------------------------------------------------------
1098  */
1099
1100 static void
1101 UpdateOffsets(
1102     TkWindow *winPtr,
1103     int deltaX,
1104     int deltaY)
1105 {
1106     TkWindow *childPtr;
1107
1108     if (winPtr->privatePtr == NULL) {
1109         /*
1110          * We havn't called Tk_MakeWindowExist for this window yet.  The
1111          * offset information will be postponed and calulated at that 
1112          * time.  (This will usually only happen when a mapped parent is
1113          * being moved but has child windows that have yet to be mapped.)
1114          */
1115         return;
1116     }
1117     
1118     winPtr->privatePtr->xOff += deltaX;
1119     winPtr->privatePtr->yOff += deltaY;
1120
1121     childPtr = winPtr->childList;
1122     while (childPtr != NULL) {
1123         if (!Tk_IsTopLevel(childPtr)) {
1124             UpdateOffsets(childPtr, deltaX, deltaY);
1125         }
1126         childPtr = childPtr->nextPtr;
1127     }
1128     
1129     if (Tk_IsContainer(winPtr)) {
1130         childPtr = TkpGetOtherWindow(winPtr);
1131         if (childPtr != NULL) {
1132             UpdateOffsets(childPtr,deltaX,deltaY);
1133         }
1134             
1135         /*
1136          * NOTE: Here we should handle out of process embedding.
1137          */
1138                     
1139     }
1140 }
1141 \f
1142 /*
1143  *----------------------------------------------------------------------
1144  *
1145  * Tk_GetPixmap --
1146  *
1147  *      Creates an in memory drawing surface.
1148  *
1149  * Results:
1150  *      Returns a handle to a new pixmap.
1151  *
1152  * Side effects:
1153  *      Allocates a new Macintosh GWorld.
1154  *
1155  *----------------------------------------------------------------------
1156  */
1157
1158 Pixmap
1159 Tk_GetPixmap(
1160     Display *display,   /* Display for new pixmap (can be null). */
1161     Drawable d,         /* Drawable where pixmap will be used (ignored). */
1162     int width,          /* Dimensions of pixmap. */
1163     int height,
1164     int depth)          /* Bits per pixel for pixmap. */
1165 {
1166     QDErr err;
1167     GWorldPtr gWorld;
1168     Rect bounds;
1169     MacDrawable *macPix;
1170     PixMapHandle pixels;
1171     
1172     if (display != NULL) {
1173         display->request++;
1174     }
1175     macPix = (MacDrawable *) ckalloc(sizeof(MacDrawable));
1176     macPix->winPtr = NULL;
1177     macPix->xOff = 0;
1178     macPix->yOff = 0;
1179     macPix->clipRgn = NULL;
1180     macPix->aboveClipRgn = NULL;
1181     macPix->referenceCount = 0;
1182     macPix->toplevel = NULL;
1183     macPix->flags = 0;
1184
1185     bounds.top = bounds.left = 0;
1186     bounds.right = (short) width;
1187     bounds.bottom = (short) height;
1188     if (depth != 1) {
1189         depth = 0;
1190     }
1191
1192     /*
1193      * Allocate memory for the off screen pixmap.  If we fail
1194      * try again from system memory.  Eventually, we may have
1195      * to panic.
1196      */
1197     err = NewGWorld(&gWorld, depth, &bounds, NULL, NULL, 0);
1198     if (err != noErr) {
1199         err = NewGWorld(&gWorld, depth, &bounds, NULL, NULL, useTempMem);
1200     }
1201     if (err != noErr) {
1202         panic("Out of memory: NewGWorld failed in Tk_GetPixmap");
1203     }
1204
1205     /*
1206      * Lock down the pixels so they don't move out from under us.
1207      */
1208     pixels = GetGWorldPixMap(gWorld);
1209     LockPixels(pixels);
1210     macPix->portPtr = gWorld;
1211
1212     return (Pixmap) macPix;
1213 }
1214 \f
1215 /*
1216  *----------------------------------------------------------------------
1217  *
1218  * Tk_FreePixmap --
1219  *
1220  *      Release the resources associated with a pixmap.
1221  *
1222  * Results:
1223  *      None.
1224  *
1225  * Side effects:
1226  *      Deletes the Macintosh GWorld created by Tk_GetPixmap.
1227  *
1228  *----------------------------------------------------------------------
1229  */
1230
1231 void 
1232 Tk_FreePixmap(
1233     Display *display,           /* Display. */
1234     Pixmap pixmap)              /* Pixmap to destroy */
1235 {
1236     MacDrawable *macPix = (MacDrawable *) pixmap;
1237     PixMapHandle pixels;
1238
1239     display->request++;
1240     pixels = GetGWorldPixMap(macPix->portPtr);
1241     UnlockPixels(pixels);
1242     DisposeGWorld(macPix->portPtr);
1243     ckfree((char *) macPix);
1244 }
1245 \f