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 *--------------------------------------------------------------
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. */
174 * Initialize, if that hasn't been done yet.
178 Tcl_InitHashTable(&masterTable
, TCL_ONE_WORD_KEYS
);
179 Tcl_InitHashTable(&slaveTable
, TCL_ONE_WORD_KEYS
);
184 Tcl_AppendResult(interp
, "wrong # args: should be \"",
185 argv
[0], " option|pathName args", (char *) NULL
);
189 length
= strlen(argv
[1]);
192 * Handle special shortcut where window name is first argument.
196 tkwin
= Tk_NameToWindow(interp
, argv
[1], (Tk_Window
) clientData
);
200 slavePtr
= FindSlave(tkwin
);
201 return ConfigureSlave(interp
, slavePtr
, argc
-2, argv
+2);
205 * Handle more general case of option followed by window name followed
206 * by possible additional arguments.
209 tkwin
= Tk_NameToWindow(interp
, argv
[2], (Tk_Window
) clientData
);
213 if ((c
== 'c') && (strncmp(argv
[1], "configure", length
) == 0)) {
215 Tcl_AppendResult(interp
, "wrong # args: should be \"",
217 " configure pathName option value ?option value ...?\"",
221 slavePtr
= FindSlave(tkwin
);
222 return ConfigureSlave(interp
, slavePtr
, argc
-3, argv
+3);
223 } else if ((c
== 'd') && (strncmp(argv
[1], "dependents", length
) == 0)) {
225 Tcl_AppendResult(interp
, "wrong # args: should be \"",
226 argv
[0], " dependents pathName\"", (char *) NULL
);
229 hPtr
= Tcl_FindHashEntry(&masterTable
, (char *) tkwin
);
232 masterPtr
= (Master
*) Tcl_GetHashValue(hPtr
);
233 for (slavePtr
= masterPtr
->slavePtr
; slavePtr
!= NULL
;
234 slavePtr
= slavePtr
->nextPtr
) {
235 Tcl_AppendElement(interp
, Tk_PathName(slavePtr
->tkwin
), 0);
238 } else if ((c
== 'f') && (strncmp(argv
[1], "forget", length
) == 0)) {
240 Tcl_AppendResult(interp
, "wrong # args: should be \"",
241 argv
[0], " forget pathName\"", (char *) NULL
);
244 hPtr
= Tcl_FindHashEntry(&slaveTable
, (char *) tkwin
);
248 slavePtr
= (Slave
*) Tcl_GetHashValue(hPtr
);
249 UnlinkSlave(slavePtr
);
250 Tcl_DeleteHashEntry(hPtr
);
251 Tk_DeleteEventHandler(tkwin
, StructureNotifyMask
, SlaveStructureProc
,
252 (ClientData
) slavePtr
);
253 Tk_ManageGeometry(tkwin
, (Tk_GeometryProc
*) NULL
, (ClientData
) NULL
);
254 Tk_UnmapWindow(tkwin
);
255 ckfree((char *) slavePtr
);
256 } else if ((c
== 'i') && (strncmp(argv
[1], "info", length
) == 0)) {
260 Tcl_AppendResult(interp
, "wrong # args: should be \"",
261 argv
[0], " info pathName\"", (char *) NULL
);
264 hPtr
= Tcl_FindHashEntry(&slaveTable
, (char *) tkwin
);
268 slavePtr
= (Slave
*) Tcl_GetHashValue(hPtr
);
269 if (slavePtr
->flags
& CHILD_REL_X
) {
270 sprintf(buffer
, "-relx %.4g", slavePtr
->relX
);
272 sprintf(buffer
, "-x %d", slavePtr
->x
);
274 Tcl_AppendResult(interp
, buffer
, (char *) NULL
);
275 if (slavePtr
->flags
& CHILD_REL_Y
) {
276 sprintf(buffer
, " -rely %.4g", slavePtr
->relY
);
278 sprintf(buffer
, " -y %d", slavePtr
->y
);
280 Tcl_AppendResult(interp
, buffer
, (char *) NULL
);
281 if (slavePtr
->flags
& CHILD_REL_WIDTH
) {
282 sprintf(buffer
, " -relwidth %.4g", slavePtr
->relWidth
);
283 Tcl_AppendResult(interp
, buffer
, (char *) NULL
);
284 } else if (slavePtr
->flags
& CHILD_WIDTH
) {
285 sprintf(buffer
, " -width %d", slavePtr
->width
);
286 Tcl_AppendResult(interp
, buffer
, (char *) NULL
);
288 if (slavePtr
->flags
& CHILD_REL_HEIGHT
) {
289 sprintf(buffer
, " -relheight %.4g", slavePtr
->relHeight
);
290 Tcl_AppendResult(interp
, buffer
, (char *) NULL
);
291 } else if (slavePtr
->flags
& CHILD_HEIGHT
) {
292 sprintf(buffer
, " -height %d", slavePtr
->height
);
293 Tcl_AppendResult(interp
, buffer
, (char *) NULL
);
295 Tcl_AppendResult(interp
, " -anchor ", Tk_NameOfAnchor(slavePtr
->anchor
),
297 if (slavePtr
->borderMode
== BM_OUTSIDE
) {
298 Tcl_AppendResult(interp
, " -bordermode outside", (char *) NULL
);
299 } else if (slavePtr
->borderMode
== BM_IGNORE
) {
300 Tcl_AppendResult(interp
, " -bordermode ignore", (char *) NULL
);
302 if ((slavePtr
->masterPtr
!= NULL
)
303 && (slavePtr
->masterPtr
->tkwin
!= Tk_Parent(slavePtr
->tkwin
))) {
304 Tcl_AppendResult(interp
, " -in ",
305 Tk_PathName(slavePtr
->masterPtr
->tkwin
), (char *) NULL
);
308 Tcl_AppendResult(interp
, "unknown or ambiguous option \"", argv
[1],
309 "\": must be configure, dependents, forget, or info",
317 *----------------------------------------------------------------------
321 * Given a Tk_Window token, find the Slave structure corresponding
322 * to that token (making a new one if necessary).
328 * A new Slave structure may be created.
330 *----------------------------------------------------------------------
335 Tk_Window tkwin
/* Token for desired slave. */
339 register Slave
*slavePtr
;
342 hPtr
= Tcl_CreateHashEntry(&slaveTable
, (char *) tkwin
, &new);
344 slavePtr
= (Slave
*) ckalloc(sizeof(Slave
));
345 slavePtr
->tkwin
= tkwin
;
346 slavePtr
->masterPtr
= NULL
;
347 slavePtr
->nextPtr
= NULL
;
348 slavePtr
->x
= slavePtr
->y
= 0;
349 slavePtr
->relX
= slavePtr
->relY
= 0.0;
350 slavePtr
->width
= slavePtr
->height
= 0;
351 slavePtr
->relWidth
= slavePtr
->relHeight
= 0.0;
352 slavePtr
->anchor
= TK_ANCHOR_NW
;
353 slavePtr
->borderMode
= BM_INSIDE
;
355 Tcl_SetHashValue(hPtr
, slavePtr
);
356 Tk_CreateEventHandler(tkwin
, StructureNotifyMask
, SlaveStructureProc
,
357 (ClientData
) slavePtr
);
358 Tk_ManageGeometry(tkwin
, PlaceRequestProc
, (ClientData
) slavePtr
);
360 slavePtr
= (Slave
*) Tcl_GetHashValue(hPtr
);
366 *----------------------------------------------------------------------
370 * This procedure removes a slave window from the chain of slaves
377 * The slave list of slavePtr's master changes.
379 *----------------------------------------------------------------------
384 Slave
*slavePtr
/* Slave structure to be unlinked. */
387 register Master
*masterPtr
;
388 register Slave
*prevPtr
;
390 masterPtr
= slavePtr
->masterPtr
;
391 if (masterPtr
== NULL
) {
394 if (masterPtr
->slavePtr
== slavePtr
) {
395 masterPtr
->slavePtr
= slavePtr
->nextPtr
;
397 for (prevPtr
= masterPtr
->slavePtr
; ;
398 prevPtr
= prevPtr
->nextPtr
) {
399 if (prevPtr
== NULL
) {
400 panic("UnlinkSlave couldn't find slave to unlink");
402 if (prevPtr
->nextPtr
== slavePtr
) {
403 prevPtr
->nextPtr
= slavePtr
->nextPtr
;
408 slavePtr
->masterPtr
= NULL
;
412 *----------------------------------------------------------------------
416 * Given a Tk_Window token, find the Master structure corresponding
417 * to that token (making a new one if necessary).
423 * A new Master structure may be created.
425 *----------------------------------------------------------------------
430 Tk_Window tkwin
/* Token for desired master. */
434 register Master
*masterPtr
;
437 hPtr
= Tcl_CreateHashEntry(&masterTable
, (char *) tkwin
, &new);
439 masterPtr
= (Master
*) ckalloc(sizeof(Master
));
440 masterPtr
->tkwin
= tkwin
;
441 masterPtr
->slavePtr
= NULL
;
442 masterPtr
->flags
= 0;
443 Tcl_SetHashValue(hPtr
, masterPtr
);
444 Tk_CreateEventHandler(masterPtr
->tkwin
, StructureNotifyMask
,
445 MasterStructureProc
, (ClientData
) masterPtr
);
447 masterPtr
= (Master
*) Tcl_GetHashValue(hPtr
);
453 *----------------------------------------------------------------------
457 * This procedure is called to process an argv/argc list to
458 * reconfigure the placement of a window.
461 * A standard Tcl result. If an error occurs then a message is
462 * left in interp->result.
465 * Information in slavePtr may change, and slavePtr's master is
466 * scheduled for reconfiguration.
468 *----------------------------------------------------------------------
473 Tcl_Interp
*interp
, /* Used for error reporting. */
474 Slave
*slavePtr
, /* Pointer to current information
476 int argc
, /* Number of config arguments. */
477 char **argv
/* String values for arguments. */
480 register Master
*masterPtr
;
481 int c
, length
, result
;
485 for ( ; argc
> 0; argc
-= 2, argv
+= 2) {
487 Tcl_AppendResult(interp
, "extra option \"", argv
[0],
488 "\" (option with no value?)", (char *) NULL
);
492 length
= strlen(argv
[0]);
494 if ((c
== 'a') && (strncmp(argv
[0], "-anchor", length
) == 0)) {
495 if (Tk_GetAnchor(interp
, argv
[1], &slavePtr
->anchor
) != TCL_OK
) {
499 } else if ((c
== 'b')
500 && (strncmp(argv
[0], "-bordermode", length
) == 0)) {
502 length
= strlen(argv
[1]);
503 if ((c
== 'i') && (strncmp(argv
[1], "ignore", length
) == 0)
505 slavePtr
->borderMode
= BM_IGNORE
;
506 } else if ((c
== 'i') && (strncmp(argv
[1], "inside", length
) == 0)
508 slavePtr
->borderMode
= BM_INSIDE
;
509 } else if ((c
== 'o')
510 && (strncmp(argv
[1], "outside", length
) == 0)) {
511 slavePtr
->borderMode
= BM_OUTSIDE
;
513 Tcl_AppendResult(interp
, "bad border mode \"", argv
[1],
514 "\": must be ignore, inside, or outside",
519 } else if ((c
== 'h') && (strncmp(argv
[0], "-height", length
) == 0)) {
520 if (argv
[1][0] == 0) {
521 slavePtr
->flags
&= ~(CHILD_REL_HEIGHT
|CHILD_HEIGHT
);
523 if (Tk_GetPixels(interp
, slavePtr
->tkwin
, argv
[1],
524 &slavePtr
->height
) != TCL_OK
) {
528 slavePtr
->flags
&= ~CHILD_REL_HEIGHT
;
529 slavePtr
->flags
|= CHILD_HEIGHT
;
531 } else if ((c
== 'i') && (strncmp(argv
[0], "-in", length
) == 0)) {
535 tkwin
= Tk_NameToWindow(interp
, argv
[1], slavePtr
->tkwin
);
542 * Make sure that the new master is either the logical parent
543 * of the slave or a descendant of that window.
546 for (ancestor
= tkwin
; ; ancestor
= Tk_Parent(ancestor
)) {
547 if (ancestor
== Tk_Parent(slavePtr
->tkwin
)) {
550 if (((Tk_FakeWin
*) (ancestor
))->flags
& TK_TOP_LEVEL
) {
551 Tcl_AppendResult(interp
, "can't place ",
552 Tk_PathName(slavePtr
->tkwin
), " relative to ",
553 Tk_PathName(tkwin
), (char *) NULL
);
558 UnlinkSlave(slavePtr
);
559 slavePtr
->masterPtr
= FindMaster(tkwin
);
560 slavePtr
->nextPtr
= slavePtr
->masterPtr
->slavePtr
;
561 slavePtr
->masterPtr
->slavePtr
= slavePtr
;
562 } else if ((c
== 'r') && (strncmp(argv
[0], "-relheight", length
) == 0)
564 if (Tcl_GetDouble(interp
, argv
[1], &d
) != TCL_OK
) {
568 slavePtr
->relHeight
= d
;
569 slavePtr
->flags
|= CHILD_REL_HEIGHT
;
570 slavePtr
->flags
&= ~CHILD_HEIGHT
;
571 } else if ((c
== 'r') && (strncmp(argv
[0], "-relwidth", length
) == 0)
573 if (Tcl_GetDouble(interp
, argv
[1], &d
) != TCL_OK
) {
577 slavePtr
->relWidth
= d
;
578 slavePtr
->flags
|= CHILD_REL_WIDTH
;
579 slavePtr
->flags
&= ~CHILD_WIDTH
;
580 } else if ((c
== 'r') && (strncmp(argv
[0], "-relx", length
) == 0)
582 if (Tcl_GetDouble(interp
, argv
[1], &d
) != TCL_OK
) {
587 slavePtr
->flags
|= CHILD_REL_X
;
588 } else if ((c
== 'r') && (strncmp(argv
[0], "-rely", length
) == 0)
590 if (Tcl_GetDouble(interp
, argv
[1], &d
) != TCL_OK
) {
595 slavePtr
->flags
|= CHILD_REL_Y
;
596 } else if ((c
== 'w') && (strncmp(argv
[0], "-width", length
) == 0)) {
597 if (argv
[1][0] == 0) {
598 slavePtr
->flags
&= ~(CHILD_REL_WIDTH
|CHILD_WIDTH
);
600 if (Tk_GetPixels(interp
, slavePtr
->tkwin
, argv
[1],
601 &slavePtr
->width
) != TCL_OK
) {
605 slavePtr
->flags
&= ~CHILD_REL_WIDTH
;
606 slavePtr
->flags
|= CHILD_WIDTH
;
608 } else if ((c
== 'x') && (strncmp(argv
[0], "-x", length
) == 0)) {
609 if (Tk_GetPixels(interp
, slavePtr
->tkwin
, argv
[1],
610 &slavePtr
->x
) != TCL_OK
) {
614 slavePtr
->flags
&= ~CHILD_REL_X
;
615 } else if ((c
== 'y') && (strncmp(argv
[0], "-y", length
) == 0)) {
616 if (Tk_GetPixels(interp
, slavePtr
->tkwin
, argv
[1],
617 &slavePtr
->y
) != TCL_OK
) {
621 slavePtr
->flags
&= ~CHILD_REL_Y
;
623 Tcl_AppendResult(interp
, "unknown or ambiguous option \"",
624 argv
[0], "\": must be -anchor, -bordermode, -height, ",
625 "-in, -relheight, -relwidth, -relx, -rely, -width, ",
626 "-x, or -y", (char *) NULL
);
633 * If there's no master specified for this slave, use its Tk_Parent.
634 * Then arrange for a placement recalculation in the master.
638 masterPtr
= slavePtr
->masterPtr
;
639 if (masterPtr
== NULL
) {
640 masterPtr
= FindMaster(Tk_Parent(slavePtr
->tkwin
));
641 slavePtr
->masterPtr
= masterPtr
;
642 slavePtr
->nextPtr
= masterPtr
->slavePtr
;
643 masterPtr
->slavePtr
= slavePtr
;
645 if (!(masterPtr
->flags
& PARENT_RECONFIG_PENDING
)) {
646 masterPtr
->flags
|= PARENT_RECONFIG_PENDING
;
647 Tk_DoWhenIdle(RecomputePlacement
, (ClientData
) masterPtr
);
653 *----------------------------------------------------------------------
655 * RecomputePlacement --
657 * This procedure is called as a when-idle handler. It recomputes
658 * the geometries of all the slaves of a given master.
664 * Windows may change size or shape.
666 *----------------------------------------------------------------------
671 ClientData clientData
/* Pointer to Master record. */
674 register Master
*masterPtr
= (Master
*) clientData
;
675 register Slave
*slavePtr
;
676 Tk_Window ancestor
, realMaster
;
677 int x
, y
, width
, height
;
678 int masterWidth
, masterHeight
, masterBW
;
680 masterPtr
->flags
&= ~PARENT_RECONFIG_PENDING
;
683 * Iterate over all the slaves for the master. Each slave's
684 * geometry can be computed independently of the other slaves.
687 for (slavePtr
= masterPtr
->slavePtr
; slavePtr
!= NULL
;
688 slavePtr
= slavePtr
->nextPtr
) {
690 * Step 1: compute size and borderwidth of master, taking into
691 * account desired border mode.
695 masterWidth
= Tk_Width(masterPtr
->tkwin
);
696 masterHeight
= Tk_Height(masterPtr
->tkwin
);
697 if (slavePtr
->borderMode
== BM_INSIDE
) {
698 masterBW
= Tk_InternalBorderWidth(masterPtr
->tkwin
);
699 } else if (slavePtr
->borderMode
== BM_OUTSIDE
) {
700 masterBW
= -Tk_Changes(masterPtr
->tkwin
)->border_width
;
702 masterWidth
-= 2*masterBW
;
703 masterHeight
-= 2*masterBW
;
706 * Step 2: compute size of slave (outside dimensions including
707 * border) and location of anchor point within master.
711 if (slavePtr
->flags
& CHILD_REL_X
) {
712 x
= (slavePtr
->relX
*masterWidth
) +
713 ((slavePtr
->relX
> 0) ? 0.5 : -0.5);
717 if (slavePtr
->flags
& CHILD_REL_Y
) {
718 y
= (slavePtr
->relY
*masterHeight
) +
719 ((slavePtr
->relY
> 0) ? 0.5 : -0.5);
722 if (slavePtr
->flags
& CHILD_REL_WIDTH
) {
723 width
= (slavePtr
->relWidth
*masterWidth
) + 0.5;
724 } else if (slavePtr
->flags
& CHILD_WIDTH
) {
725 width
= slavePtr
->width
;
727 width
= Tk_ReqWidth(slavePtr
->tkwin
)
728 + 2*Tk_Changes(slavePtr
->tkwin
)->border_width
;
730 if (slavePtr
->flags
& CHILD_REL_HEIGHT
) {
731 height
= (slavePtr
->relHeight
*masterHeight
) + 0.5;
732 } else if (slavePtr
->flags
& CHILD_HEIGHT
) {
733 height
= slavePtr
->height
;
735 height
= Tk_ReqHeight(slavePtr
->tkwin
)
736 + 2*Tk_Changes(slavePtr
->tkwin
)->border_width
;
740 * Step 3: adjust the x and y positions so that the desired
741 * anchor point on the slave appears at that position. Also
742 * adjust for the border mode and master's border.
745 switch (slavePtr
->anchor
) {
772 case TK_ANCHOR_CENTER
:
779 * Step 4: if masterPtr isn't actually the X master of slavePtr,
780 * then translate the x and y coordinates back into the coordinate
781 * system of masterPtr.
784 for (ancestor
= masterPtr
->tkwin
,
785 realMaster
= Tk_Parent(slavePtr
->tkwin
);
786 ancestor
!= realMaster
; ancestor
= Tk_Parent(ancestor
)) {
787 x
+= Tk_X(ancestor
) + Tk_Changes(ancestor
)->border_width
;
788 y
+= Tk_Y(ancestor
) + Tk_Changes(ancestor
)->border_width
;
792 * Step 5: adjust width and height again to reflect inside dimensions
793 * of window rather than outside. Also make sure that the width and
794 * height aren't zero.
797 width
-= 2*Tk_Changes(slavePtr
->tkwin
)->border_width
;
798 height
-= 2*Tk_Changes(slavePtr
->tkwin
)->border_width
;
807 * Step 6: see if the window's size or location has changed; if
808 * so then tell X to reconfigure it.
811 if ((x
!= Tk_X(slavePtr
->tkwin
))
812 || (y
!= Tk_Y(slavePtr
->tkwin
))
813 || (width
!= Tk_Width(slavePtr
->tkwin
))
814 || (height
!= Tk_Height(slavePtr
->tkwin
))) {
815 Tk_MoveResizeWindow(slavePtr
->tkwin
, x
, y
,
816 (unsigned int) width
, (unsigned int) height
);
818 Tk_MapWindow(slavePtr
->tkwin
);
823 *----------------------------------------------------------------------
825 * MasterStructureProc --
827 * This procedure is invoked by the Tk event handler when
828 * StructureNotify events occur for a master window.
834 * Structures get cleaned up if the window was deleted. If the
835 * window was resized then slave geometries get recomputed.
837 *----------------------------------------------------------------------
841 MasterStructureProc (
842 ClientData clientData
, /* Pointer to Master structure for window
843 * referred to by eventPtr. */
844 XEvent
*eventPtr
/* Describes what just happened. */
847 register Master
*masterPtr
= (Master
*) clientData
;
848 register Slave
*slavePtr
, *nextPtr
;
850 if (eventPtr
->type
== ConfigureNotify
) {
851 if ((masterPtr
->slavePtr
!= NULL
)
852 && !(masterPtr
->flags
& PARENT_RECONFIG_PENDING
)) {
853 masterPtr
->flags
|= PARENT_RECONFIG_PENDING
;
854 Tk_DoWhenIdle(RecomputePlacement
, (ClientData
) masterPtr
);
856 } else if (eventPtr
->type
== DestroyNotify
) {
857 for (slavePtr
= masterPtr
->slavePtr
; slavePtr
!= NULL
;
858 slavePtr
= nextPtr
) {
859 slavePtr
->masterPtr
= NULL
;
860 nextPtr
= slavePtr
->nextPtr
;
861 slavePtr
->nextPtr
= NULL
;
863 Tcl_DeleteHashEntry(Tcl_FindHashEntry(&masterTable
,
864 (char *) masterPtr
->tkwin
));
865 if (masterPtr
->flags
& PARENT_RECONFIG_PENDING
) {
866 Tk_CancelIdleCall(RecomputePlacement
, (ClientData
) masterPtr
);
868 masterPtr
->tkwin
= NULL
;
869 ckfree((char *) masterPtr
);
874 *----------------------------------------------------------------------
876 * SlaveStructureProc --
878 * This procedure is invoked by the Tk event handler when
879 * StructureNotify events occur for a slave window.
885 * Structures get cleaned up if the window was deleted.
887 *----------------------------------------------------------------------
892 ClientData clientData
, /* Pointer to Slave structure for window
893 * referred to by eventPtr. */
894 XEvent
*eventPtr
/* Describes what just happened. */
897 register Slave
*slavePtr
= (Slave
*) clientData
;
899 if (eventPtr
->type
== DestroyNotify
) {
900 UnlinkSlave(slavePtr
);
901 Tcl_DeleteHashEntry(Tcl_FindHashEntry(&slaveTable
,
902 (char *) slavePtr
->tkwin
));
903 ckfree((char *) slavePtr
);
908 *----------------------------------------------------------------------
910 * PlaceRequestProc --
912 * This procedure is invoked by Tk whenever a slave managed by us
913 * changes its requested geometry.
919 * The window will get relayed out, if its requested size has
920 * anything to do with its actual size.
922 *----------------------------------------------------------------------
928 ClientData clientData
, /* Pointer to our record for slave. */
929 Tk_Window tkwin
/* Window that changed its desired
933 Slave
*slavePtr
= (Slave
*) clientData
;
936 if (((slavePtr
->flags
& (CHILD_WIDTH
|CHILD_REL_WIDTH
)) != 0)
937 && ((slavePtr
->flags
& (CHILD_HEIGHT
|CHILD_REL_HEIGHT
)) != 0)) {
940 masterPtr
= slavePtr
->masterPtr
;
941 if (masterPtr
== NULL
) {
944 if (!(masterPtr
->flags
& PARENT_RECONFIG_PENDING
)) {
945 masterPtr
->flags
|= PARENT_RECONFIG_PENDING
;
946 Tk_DoWhenIdle(RecomputePlacement
, (ClientData
) masterPtr
);