4 * This file contains code to implement a simple geometry manager
5 * for Tk based on absolute placement or "rubber-sheet" placement.
7 * Copyright 1992 Regents of the University of California
8 * Permission to use, copy, modify, and distribute this
9 * software and its documentation for any purpose and without
10 * fee is hereby granted, provided that this copyright
11 * notice appears in all copies. The University of California
12 * makes no representations about the suitability of this
13 * software for any purpose. It is provided "as is" without
14 * express or implied warranty.
18 static char rcsid
[] = "$Header: /user6/ouster/wish/RCS/tkPlace.c,v 1.6 92/06/10 08:59:28 ouster Exp $ SPRITE (Berkeley)";
25 * Border modes for relative placement:
27 * BM_INSIDE: relative distances computed using area inside
28 * all borders of master window.
29 * BM_OUTSIDE: relative distances computed using outside area
30 * that includes all borders of master.
31 * BM_IGNORE: border issues are ignored: place relative to
32 * master's actual window size.
35 typedef enum {BM_INSIDE
, BM_OUTSIDE
, BM_IGNORE
} BorderMode
;
38 * For each window whose geometry is managed by the placer there is
39 * a structure of the following type:
42 typedef struct Slave
{
43 Tk_Window tkwin
; /* Tk's token for window. */
44 struct Master
*masterPtr
; /* Pointer to information for window
45 * relative to which tkwin is placed.
46 * This isn't necessarily the logical
47 * parent of tkwin. NULL means the
48 * master was deleted or never assigned. */
49 struct Slave
*nextPtr
; /* Next in list of windows placed relative
50 * to same master (NULL for end of list). */
53 * Geometry information for window; where there are both relative
54 * and absolute values for the same attribute (e.g. x and relX) only
55 * one of them is actually used, depending on flags.
58 int x
, y
; /* X and Y pixel coordinates for tkwin. */
59 float relX
, relY
; /* X and Y coordinates relative to size of
61 int width
, height
; /* Absolute dimensions for tkwin. */
62 float relWidth
, relHeight
; /* Dimensions for tkwin relative to size of
64 Tk_Anchor anchor
; /* Which point on tkwin is placed at the
66 BorderMode borderMode
; /* How to treat borders of master window. */
67 int flags
; /* Various flags; see below for bit
72 * Flag definitions for Slave structures:
74 * CHILD_REL_X - 1 means use relX field; 0 means use x.
75 * CHILD_REL_Y - 1 means use relY field; 0 means use y;
76 * CHILD_WIDTH - 1 means use width field;
77 * CHILD_REL_WIDTH - 1 means use relWidth; if neither this nor
78 * CHILD_WIDTH is 1, use window's requested
80 * CHILD_HEIGHT - 1 means use height field;
81 * CHILD_REL_HEIGHT - 1 means use relHeight; if neither this nor
82 * CHILD_HEIGHT is 1, use window's requested
89 #define CHILD_REL_WIDTH 8
90 #define CHILD_HEIGHT 0x10
91 #define CHILD_REL_HEIGHT 0x20
94 * For each master window that has a slave managed by the placer there
95 * is a structure of the following form:
98 typedef struct Master
{
99 Tk_Window tkwin
; /* Tk's token for master window. */
100 struct Slave
*slavePtr
; /* First in linked list of slaves
101 * placed relative to this master. */
102 int flags
; /* See below for bit definitions. */
106 * Flag definitions for masters:
108 * PARENT_RECONFIG_PENDING - 1 means that a call to RecomputePlacement
109 * is already pending via a Do_When_Idle handler.
112 #define PARENT_RECONFIG_PENDING 1
115 * The hash tables below both use Tk_Window tokens as keys. They map
116 * from Tk_Windows to Slave and Master structures for windows, if they
120 static int initialized
= 0;
121 static Tcl_HashTable masterTable
;
122 static Tcl_HashTable slaveTable
;
125 * Forward declarations for procedures defined later in this file:
128 static void SlaveStructureProc
_ANSI_ARGS_((ClientData clientData
,
130 static int ConfigureSlave
_ANSI_ARGS_((Tcl_Interp
*interp
,
131 Slave
*slavePtr
, int argc
, char **argv
));
132 static Slave
* FindSlave
_ANSI_ARGS_((Tk_Window tkwin
));
133 static Master
* FindMaster
_ANSI_ARGS_((Tk_Window tkwin
));
134 static void MasterStructureProc
_ANSI_ARGS_((ClientData clientData
,
136 static void PlaceRequestProc
_ANSI_ARGS_((ClientData clientData
,
138 static void RecomputePlacement
_ANSI_ARGS_((ClientData clientData
));
139 static void UnlinkSlave
_ANSI_ARGS_((Slave
*slavePtr
));
142 *--------------------------------------------------------------
146 * This procedure is invoked to process the "place" Tcl
147 * commands. See the user documentation for details on
151 * A standard Tcl result.
154 * See the user documentation.
156 *--------------------------------------------------------------
160 Tk_PlaceCmd(clientData
, interp
, argc
, argv
)
161 ClientData clientData
; /* Main window associated with interpreter. */
162 Tcl_Interp
*interp
; /* Current interpreter. */
163 int argc
; /* Number of arguments. */
164 char **argv
; /* Argument strings. */
173 * Initialize, if that hasn't been done yet.
177 Tcl_InitHashTable(&masterTable
, TCL_ONE_WORD_KEYS
);
178 Tcl_InitHashTable(&slaveTable
, TCL_ONE_WORD_KEYS
);
183 Tcl_AppendResult(interp
, "wrong # args: should be \"",
184 argv
[0], " option|pathName args", (char *) NULL
);
188 length
= strlen(argv
[1]);
191 * Handle special shortcut where window name is first argument.
195 tkwin
= Tk_NameToWindow(interp
, argv
[1], (Tk_Window
) clientData
);
199 slavePtr
= FindSlave(tkwin
);
200 return ConfigureSlave(interp
, slavePtr
, argc
-2, argv
+2);
204 * Handle more general case of option followed by window name followed
205 * by possible additional arguments.
208 tkwin
= Tk_NameToWindow(interp
, argv
[2], (Tk_Window
) clientData
);
212 if ((c
== 'c') && (strncmp(argv
[1], "configure", length
) == 0)) {
214 Tcl_AppendResult(interp
, "wrong # args: should be \"",
216 " configure pathName option value ?option value ...?\"",
220 slavePtr
= FindSlave(tkwin
);
221 return ConfigureSlave(interp
, slavePtr
, argc
-3, argv
+3);
222 } else if ((c
== 'd') && (strncmp(argv
[1], "dependents", length
) == 0)) {
224 Tcl_AppendResult(interp
, "wrong # args: should be \"",
225 argv
[0], " dependents pathName\"", (char *) NULL
);
228 hPtr
= Tcl_FindHashEntry(&masterTable
, (char *) tkwin
);
231 masterPtr
= (Master
*) Tcl_GetHashValue(hPtr
);
232 for (slavePtr
= masterPtr
->slavePtr
; slavePtr
!= NULL
;
233 slavePtr
= slavePtr
->nextPtr
) {
234 Tcl_AppendElement(interp
, Tk_PathName(slavePtr
->tkwin
), 0);
237 } else if ((c
== 'f') && (strncmp(argv
[1], "forget", length
) == 0)) {
239 Tcl_AppendResult(interp
, "wrong # args: should be \"",
240 argv
[0], " forget pathName\"", (char *) NULL
);
243 hPtr
= Tcl_FindHashEntry(&slaveTable
, (char *) tkwin
);
247 slavePtr
= (Slave
*) Tcl_GetHashValue(hPtr
);
248 UnlinkSlave(slavePtr
);
249 Tcl_DeleteHashEntry(hPtr
);
250 Tk_DeleteEventHandler(tkwin
, StructureNotifyMask
, SlaveStructureProc
,
251 (ClientData
) slavePtr
);
252 Tk_ManageGeometry(tkwin
, (Tk_GeometryProc
*) NULL
, (ClientData
) NULL
);
253 Tk_UnmapWindow(tkwin
);
254 ckfree((char *) slavePtr
);
255 } else if ((c
== 'i') && (strncmp(argv
[1], "info", length
) == 0)) {
259 Tcl_AppendResult(interp
, "wrong # args: should be \"",
260 argv
[0], " info pathName\"", (char *) NULL
);
263 hPtr
= Tcl_FindHashEntry(&slaveTable
, (char *) tkwin
);
267 slavePtr
= (Slave
*) Tcl_GetHashValue(hPtr
);
268 if (slavePtr
->flags
& CHILD_REL_X
) {
269 sprintf(buffer
, "-relx %.4g", slavePtr
->relX
);
271 sprintf(buffer
, "-x %d", slavePtr
->x
);
273 Tcl_AppendResult(interp
, buffer
, (char *) NULL
);
274 if (slavePtr
->flags
& CHILD_REL_Y
) {
275 sprintf(buffer
, " -rely %.4g", slavePtr
->relY
);
277 sprintf(buffer
, " -y %d", slavePtr
->y
);
279 Tcl_AppendResult(interp
, buffer
, (char *) NULL
);
280 if (slavePtr
->flags
& CHILD_REL_WIDTH
) {
281 sprintf(buffer
, " -relwidth %.4g", slavePtr
->relWidth
);
282 Tcl_AppendResult(interp
, buffer
, (char *) NULL
);
283 } else if (slavePtr
->flags
& CHILD_WIDTH
) {
284 sprintf(buffer
, " -width %d", slavePtr
->width
);
285 Tcl_AppendResult(interp
, buffer
, (char *) NULL
);
287 if (slavePtr
->flags
& CHILD_REL_HEIGHT
) {
288 sprintf(buffer
, " -relheight %.4g", slavePtr
->relHeight
);
289 Tcl_AppendResult(interp
, buffer
, (char *) NULL
);
290 } else if (slavePtr
->flags
& CHILD_HEIGHT
) {
291 sprintf(buffer
, " -height %d", slavePtr
->height
);
292 Tcl_AppendResult(interp
, buffer
, (char *) NULL
);
294 Tcl_AppendResult(interp
, " -anchor ", Tk_NameOfAnchor(slavePtr
->anchor
),
296 if (slavePtr
->borderMode
== BM_OUTSIDE
) {
297 Tcl_AppendResult(interp
, " -bordermode outside", (char *) NULL
);
298 } else if (slavePtr
->borderMode
== BM_IGNORE
) {
299 Tcl_AppendResult(interp
, " -bordermode ignore", (char *) NULL
);
301 if ((slavePtr
->masterPtr
!= NULL
)
302 && (slavePtr
->masterPtr
->tkwin
!= Tk_Parent(slavePtr
->tkwin
))) {
303 Tcl_AppendResult(interp
, " -in ",
304 Tk_PathName(slavePtr
->masterPtr
->tkwin
), (char *) NULL
);
307 Tcl_AppendResult(interp
, "unknown or ambiguous option \"", argv
[1],
308 "\": must be configure, dependents, forget, or info",
316 *----------------------------------------------------------------------
320 * Given a Tk_Window token, find the Slave structure corresponding
321 * to that token (making a new one if necessary).
327 * A new Slave structure may be created.
329 *----------------------------------------------------------------------
334 Tk_Window tkwin
; /* Token for desired slave. */
337 register Slave
*slavePtr
;
340 hPtr
= Tcl_CreateHashEntry(&slaveTable
, (char *) tkwin
, &new);
342 slavePtr
= (Slave
*) ckalloc(sizeof(Slave
));
343 slavePtr
->tkwin
= tkwin
;
344 slavePtr
->masterPtr
= NULL
;
345 slavePtr
->nextPtr
= NULL
;
346 slavePtr
->x
= slavePtr
->y
= 0;
347 slavePtr
->relX
= slavePtr
->relY
= 0.0;
348 slavePtr
->width
= slavePtr
->height
= 0;
349 slavePtr
->relWidth
= slavePtr
->relHeight
= 0.0;
350 slavePtr
->anchor
= TK_ANCHOR_NW
;
351 slavePtr
->borderMode
= BM_INSIDE
;
353 Tcl_SetHashValue(hPtr
, slavePtr
);
354 Tk_CreateEventHandler(tkwin
, StructureNotifyMask
, SlaveStructureProc
,
355 (ClientData
) slavePtr
);
356 Tk_ManageGeometry(tkwin
, PlaceRequestProc
, (ClientData
) slavePtr
);
358 slavePtr
= (Slave
*) Tcl_GetHashValue(hPtr
);
364 *----------------------------------------------------------------------
368 * This procedure removes a slave window from the chain of slaves
375 * The slave list of slavePtr's master changes.
377 *----------------------------------------------------------------------
381 UnlinkSlave(slavePtr
)
382 Slave
*slavePtr
; /* Slave structure to be unlinked. */
384 register Master
*masterPtr
;
385 register Slave
*prevPtr
;
387 masterPtr
= slavePtr
->masterPtr
;
388 if (masterPtr
== NULL
) {
391 if (masterPtr
->slavePtr
== slavePtr
) {
392 masterPtr
->slavePtr
= slavePtr
->nextPtr
;
394 for (prevPtr
= masterPtr
->slavePtr
; ;
395 prevPtr
= prevPtr
->nextPtr
) {
396 if (prevPtr
== NULL
) {
397 panic("UnlinkSlave couldn't find slave to unlink");
399 if (prevPtr
->nextPtr
== slavePtr
) {
400 prevPtr
->nextPtr
= slavePtr
->nextPtr
;
405 slavePtr
->masterPtr
= NULL
;
409 *----------------------------------------------------------------------
413 * Given a Tk_Window token, find the Master structure corresponding
414 * to that token (making a new one if necessary).
420 * A new Master structure may be created.
422 *----------------------------------------------------------------------
427 Tk_Window tkwin
; /* Token for desired master. */
430 register Master
*masterPtr
;
433 hPtr
= Tcl_CreateHashEntry(&masterTable
, (char *) tkwin
, &new);
435 masterPtr
= (Master
*) ckalloc(sizeof(Master
));
436 masterPtr
->tkwin
= tkwin
;
437 masterPtr
->slavePtr
= NULL
;
438 masterPtr
->flags
= 0;
439 Tcl_SetHashValue(hPtr
, masterPtr
);
440 Tk_CreateEventHandler(masterPtr
->tkwin
, StructureNotifyMask
,
441 MasterStructureProc
, (ClientData
) masterPtr
);
443 masterPtr
= (Master
*) Tcl_GetHashValue(hPtr
);
449 *----------------------------------------------------------------------
453 * This procedure is called to process an argv/argc list to
454 * reconfigure the placement of a window.
457 * A standard Tcl result. If an error occurs then a message is
458 * left in interp->result.
461 * Information in slavePtr may change, and slavePtr's master is
462 * scheduled for reconfiguration.
464 *----------------------------------------------------------------------
468 ConfigureSlave(interp
, slavePtr
, argc
, argv
)
469 Tcl_Interp
*interp
; /* Used for error reporting. */
470 Slave
*slavePtr
; /* Pointer to current information
472 int argc
; /* Number of config arguments. */
473 char **argv
; /* String values for arguments. */
475 register Master
*masterPtr
;
476 int c
, length
, result
;
480 for ( ; argc
> 0; argc
-= 2, argv
+= 2) {
482 Tcl_AppendResult(interp
, "extra option \"", argv
[0],
483 "\" (option with no value?)", (char *) NULL
);
487 length
= strlen(argv
[0]);
489 if ((c
== 'a') && (strncmp(argv
[0], "-anchor", length
) == 0)) {
490 if (Tk_GetAnchor(interp
, argv
[1], &slavePtr
->anchor
) != TCL_OK
) {
494 } else if ((c
== 'b')
495 && (strncmp(argv
[0], "-bordermode", length
) == 0)) {
497 length
= strlen(argv
[1]);
498 if ((c
== 'i') && (strncmp(argv
[1], "ignore", length
) == 0)
500 slavePtr
->borderMode
= BM_IGNORE
;
501 } else if ((c
== 'i') && (strncmp(argv
[1], "inside", length
) == 0)
503 slavePtr
->borderMode
= BM_INSIDE
;
504 } else if ((c
== 'o')
505 && (strncmp(argv
[1], "outside", length
) == 0)) {
506 slavePtr
->borderMode
= BM_OUTSIDE
;
508 Tcl_AppendResult(interp
, "bad border mode \"", argv
[1],
509 "\": must be ignore, inside, or outside",
514 } else if ((c
== 'h') && (strncmp(argv
[0], "-height", length
) == 0)) {
515 if (argv
[1][0] == 0) {
516 slavePtr
->flags
&= ~(CHILD_REL_HEIGHT
|CHILD_HEIGHT
);
518 if (Tk_GetPixels(interp
, slavePtr
->tkwin
, argv
[1],
519 &slavePtr
->height
) != TCL_OK
) {
523 slavePtr
->flags
&= ~CHILD_REL_HEIGHT
;
524 slavePtr
->flags
|= CHILD_HEIGHT
;
526 } else if ((c
== 'i') && (strncmp(argv
[0], "-in", length
) == 0)) {
530 tkwin
= Tk_NameToWindow(interp
, argv
[1], slavePtr
->tkwin
);
537 * Make sure that the new master is either the logical parent
538 * of the slave or a descendant of that window.
541 for (ancestor
= tkwin
; ; ancestor
= Tk_Parent(ancestor
)) {
542 if (ancestor
== Tk_Parent(slavePtr
->tkwin
)) {
545 if (((Tk_FakeWin
*) (ancestor
))->flags
& TK_TOP_LEVEL
) {
546 Tcl_AppendResult(interp
, "can't place ",
547 Tk_PathName(slavePtr
->tkwin
), " relative to ",
548 Tk_PathName(tkwin
), (char *) NULL
);
553 UnlinkSlave(slavePtr
);
554 slavePtr
->masterPtr
= FindMaster(tkwin
);
555 slavePtr
->nextPtr
= slavePtr
->masterPtr
->slavePtr
;
556 slavePtr
->masterPtr
->slavePtr
= slavePtr
;
557 } else if ((c
== 'r') && (strncmp(argv
[0], "-relheight", length
) == 0)
559 if (Tcl_GetDouble(interp
, argv
[1], &d
) != TCL_OK
) {
563 slavePtr
->relHeight
= d
;
564 slavePtr
->flags
|= CHILD_REL_HEIGHT
;
565 slavePtr
->flags
&= ~CHILD_HEIGHT
;
566 } else if ((c
== 'r') && (strncmp(argv
[0], "-relwidth", length
) == 0)
568 if (Tcl_GetDouble(interp
, argv
[1], &d
) != TCL_OK
) {
572 slavePtr
->relWidth
= d
;
573 slavePtr
->flags
|= CHILD_REL_WIDTH
;
574 slavePtr
->flags
&= ~CHILD_WIDTH
;
575 } else if ((c
== 'r') && (strncmp(argv
[0], "-relx", length
) == 0)
577 if (Tcl_GetDouble(interp
, argv
[1], &d
) != TCL_OK
) {
582 slavePtr
->flags
|= CHILD_REL_X
;
583 } else if ((c
== 'r') && (strncmp(argv
[0], "-rely", length
) == 0)
585 if (Tcl_GetDouble(interp
, argv
[1], &d
) != TCL_OK
) {
590 slavePtr
->flags
|= CHILD_REL_Y
;
591 } else if ((c
== 'w') && (strncmp(argv
[0], "-width", length
) == 0)) {
592 if (argv
[1][0] == 0) {
593 slavePtr
->flags
&= ~(CHILD_REL_WIDTH
|CHILD_WIDTH
);
595 if (Tk_GetPixels(interp
, slavePtr
->tkwin
, argv
[1],
596 &slavePtr
->width
) != TCL_OK
) {
600 slavePtr
->flags
&= ~CHILD_REL_WIDTH
;
601 slavePtr
->flags
|= CHILD_WIDTH
;
603 } else if ((c
== 'x') && (strncmp(argv
[0], "-x", length
) == 0)) {
604 if (Tk_GetPixels(interp
, slavePtr
->tkwin
, argv
[1],
605 &slavePtr
->x
) != TCL_OK
) {
609 slavePtr
->flags
&= ~CHILD_REL_X
;
610 } else if ((c
== 'y') && (strncmp(argv
[0], "-y", length
) == 0)) {
611 if (Tk_GetPixels(interp
, slavePtr
->tkwin
, argv
[1],
612 &slavePtr
->y
) != TCL_OK
) {
616 slavePtr
->flags
&= ~CHILD_REL_Y
;
618 Tcl_AppendResult(interp
, "unknown or ambiguous option \"",
619 argv
[0], "\": must be -anchor, -bordermode, -height, ",
620 "-in, -relheight, -relwidth, -relx, -rely, -width, ",
621 "-x, or -y", (char *) NULL
);
628 * If there's no master specified for this slave, use its Tk_Parent.
629 * Then arrange for a placement recalculation in the master.
633 masterPtr
= slavePtr
->masterPtr
;
634 if (masterPtr
== NULL
) {
635 masterPtr
= FindMaster(Tk_Parent(slavePtr
->tkwin
));
636 slavePtr
->masterPtr
= masterPtr
;
637 slavePtr
->nextPtr
= masterPtr
->slavePtr
;
638 masterPtr
->slavePtr
= slavePtr
;
640 if (!(masterPtr
->flags
& PARENT_RECONFIG_PENDING
)) {
641 masterPtr
->flags
|= PARENT_RECONFIG_PENDING
;
642 Tk_DoWhenIdle(RecomputePlacement
, (ClientData
) masterPtr
);
648 *----------------------------------------------------------------------
650 * RecomputePlacement --
652 * This procedure is called as a when-idle handler. It recomputes
653 * the geometries of all the slaves of a given master.
659 * Windows may change size or shape.
661 *----------------------------------------------------------------------
665 RecomputePlacement(clientData
)
666 ClientData clientData
; /* Pointer to Master record. */
668 register Master
*masterPtr
= (Master
*) clientData
;
669 register Slave
*slavePtr
;
670 Tk_Window ancestor
, realMaster
;
671 int x
, y
, width
, height
;
672 int masterWidth
, masterHeight
, masterBW
;
674 masterPtr
->flags
&= ~PARENT_RECONFIG_PENDING
;
677 * Iterate over all the slaves for the master. Each slave's
678 * geometry can be computed independently of the other slaves.
681 for (slavePtr
= masterPtr
->slavePtr
; slavePtr
!= NULL
;
682 slavePtr
= slavePtr
->nextPtr
) {
684 * Step 1: compute size and borderwidth of master, taking into
685 * account desired border mode.
689 masterWidth
= Tk_Width(masterPtr
->tkwin
);
690 masterHeight
= Tk_Height(masterPtr
->tkwin
);
691 if (slavePtr
->borderMode
== BM_INSIDE
) {
692 masterBW
= Tk_InternalBorderWidth(masterPtr
->tkwin
);
693 } else if (slavePtr
->borderMode
== BM_OUTSIDE
) {
694 masterBW
= -Tk_Changes(masterPtr
->tkwin
)->border_width
;
696 masterWidth
-= 2*masterBW
;
697 masterHeight
-= 2*masterBW
;
700 * Step 2: compute size of slave (outside dimensions including
701 * border) and location of anchor point within master.
705 if (slavePtr
->flags
& CHILD_REL_X
) {
706 x
= (slavePtr
->relX
*masterWidth
) +
707 ((slavePtr
->relX
> 0) ? 0.5 : -0.5);
711 if (slavePtr
->flags
& CHILD_REL_Y
) {
712 y
= (slavePtr
->relY
*masterHeight
) +
713 ((slavePtr
->relY
> 0) ? 0.5 : -0.5);
716 if (slavePtr
->flags
& CHILD_REL_WIDTH
) {
717 width
= (slavePtr
->relWidth
*masterWidth
) + 0.5;
718 } else if (slavePtr
->flags
& CHILD_WIDTH
) {
719 width
= slavePtr
->width
;
721 width
= Tk_ReqWidth(slavePtr
->tkwin
)
722 + 2*Tk_Changes(slavePtr
->tkwin
)->border_width
;
724 if (slavePtr
->flags
& CHILD_REL_HEIGHT
) {
725 height
= (slavePtr
->relHeight
*masterHeight
) + 0.5;
726 } else if (slavePtr
->flags
& CHILD_HEIGHT
) {
727 height
= slavePtr
->height
;
729 height
= Tk_ReqHeight(slavePtr
->tkwin
)
730 + 2*Tk_Changes(slavePtr
->tkwin
)->border_width
;
734 * Step 3: adjust the x and y positions so that the desired
735 * anchor point on the slave appears at that position. Also
736 * adjust for the border mode and master's border.
739 switch (slavePtr
->anchor
) {
766 case TK_ANCHOR_CENTER
:
773 * Step 4: if masterPtr isn't actually the X master of slavePtr,
774 * then translate the x and y coordinates back into the coordinate
775 * system of masterPtr.
778 for (ancestor
= masterPtr
->tkwin
,
779 realMaster
= Tk_Parent(slavePtr
->tkwin
);
780 ancestor
!= realMaster
; ancestor
= Tk_Parent(ancestor
)) {
781 x
+= Tk_X(ancestor
) + Tk_Changes(ancestor
)->border_width
;
782 y
+= Tk_Y(ancestor
) + Tk_Changes(ancestor
)->border_width
;
786 * Step 5: adjust width and height again to reflect inside dimensions
787 * of window rather than outside. Also make sure that the width and
788 * height aren't zero.
791 width
-= 2*Tk_Changes(slavePtr
->tkwin
)->border_width
;
792 height
-= 2*Tk_Changes(slavePtr
->tkwin
)->border_width
;
801 * Step 6: see if the window's size or location has changed; if
802 * so then tell X to reconfigure it.
805 if ((x
!= Tk_X(slavePtr
->tkwin
))
806 || (y
!= Tk_Y(slavePtr
->tkwin
))
807 || (width
!= Tk_Width(slavePtr
->tkwin
))
808 || (height
!= Tk_Height(slavePtr
->tkwin
))) {
809 Tk_MoveResizeWindow(slavePtr
->tkwin
, x
, y
,
810 (unsigned int) width
, (unsigned int) height
);
812 Tk_MapWindow(slavePtr
->tkwin
);
817 *----------------------------------------------------------------------
819 * MasterStructureProc --
821 * This procedure is invoked by the Tk event handler when
822 * StructureNotify events occur for a master window.
828 * Structures get cleaned up if the window was deleted. If the
829 * window was resized then slave geometries get recomputed.
831 *----------------------------------------------------------------------
835 MasterStructureProc(clientData
, eventPtr
)
836 ClientData clientData
; /* Pointer to Master structure for window
837 * referred to by eventPtr. */
838 XEvent
*eventPtr
; /* Describes what just happened. */
840 register Master
*masterPtr
= (Master
*) clientData
;
841 register Slave
*slavePtr
, *nextPtr
;
843 if (eventPtr
->type
== ConfigureNotify
) {
844 if ((masterPtr
->slavePtr
!= NULL
)
845 && !(masterPtr
->flags
& PARENT_RECONFIG_PENDING
)) {
846 masterPtr
->flags
|= PARENT_RECONFIG_PENDING
;
847 Tk_DoWhenIdle(RecomputePlacement
, (ClientData
) masterPtr
);
849 } else if (eventPtr
->type
== DestroyNotify
) {
850 for (slavePtr
= masterPtr
->slavePtr
; slavePtr
!= NULL
;
851 slavePtr
= nextPtr
) {
852 slavePtr
->masterPtr
= NULL
;
853 nextPtr
= slavePtr
->nextPtr
;
854 slavePtr
->nextPtr
= NULL
;
856 Tcl_DeleteHashEntry(Tcl_FindHashEntry(&masterTable
,
857 (char *) masterPtr
->tkwin
));
858 if (masterPtr
->flags
& PARENT_RECONFIG_PENDING
) {
859 Tk_CancelIdleCall(RecomputePlacement
, (ClientData
) masterPtr
);
861 masterPtr
->tkwin
= NULL
;
862 ckfree((char *) masterPtr
);
867 *----------------------------------------------------------------------
869 * SlaveStructureProc --
871 * This procedure is invoked by the Tk event handler when
872 * StructureNotify events occur for a slave window.
878 * Structures get cleaned up if the window was deleted.
880 *----------------------------------------------------------------------
884 SlaveStructureProc(clientData
, eventPtr
)
885 ClientData clientData
; /* Pointer to Slave structure for window
886 * referred to by eventPtr. */
887 XEvent
*eventPtr
; /* Describes what just happened. */
889 register Slave
*slavePtr
= (Slave
*) clientData
;
891 if (eventPtr
->type
== DestroyNotify
) {
892 UnlinkSlave(slavePtr
);
893 Tcl_DeleteHashEntry(Tcl_FindHashEntry(&slaveTable
,
894 (char *) slavePtr
->tkwin
));
895 ckfree((char *) slavePtr
);
900 *----------------------------------------------------------------------
902 * PlaceRequestProc --
904 * This procedure is invoked by Tk whenever a slave managed by us
905 * changes its requested geometry.
911 * The window will get relayed out, if its requested size has
912 * anything to do with its actual size.
914 *----------------------------------------------------------------------
919 PlaceRequestProc(clientData
, tkwin
)
920 ClientData clientData
; /* Pointer to our record for slave. */
921 Tk_Window tkwin
; /* Window that changed its desired
924 Slave
*slavePtr
= (Slave
*) clientData
;
927 if (((slavePtr
->flags
& (CHILD_WIDTH
|CHILD_REL_WIDTH
)) != 0)
928 && ((slavePtr
->flags
& (CHILD_HEIGHT
|CHILD_REL_HEIGHT
)) != 0)) {
931 masterPtr
= slavePtr
->masterPtr
;
932 if (masterPtr
== NULL
) {
935 if (!(masterPtr
->flags
& PARENT_RECONFIG_PENDING
)) {
936 masterPtr
->flags
|= PARENT_RECONFIG_PENDING
;
937 Tk_DoWhenIdle(RecomputePlacement
, (ClientData
) masterPtr
);