summaryrefslogtreecommitdiffstats
path: root/generic
diff options
context:
space:
mode:
authormdejong <mdejong>2003-03-12 00:09:32 (GMT)
committermdejong <mdejong>2003-03-12 00:09:32 (GMT)
commit6be1cd95fff709a3869038db3e989865154259fb (patch)
treeecef370c50b2d02b66d81ba8deaa5e9601199442 /generic
parent7be603f3c85d34e87e54b45c813ecbe337c89854 (diff)
downloadtk-6be1cd95fff709a3869038db3e989865154259fb.zip
tk-6be1cd95fff709a3869038db3e989865154259fb.tar.gz
tk-6be1cd95fff709a3869038db3e989865154259fb.tar.bz2
* generic/tkGrid.c (GridStructureProc, ConfigureSlaves):
Check for a NULL masterPtr and slavePtr in the GridStructureProc code to ensure that a Gridder created before some error condition is ignored when it comes to geometry calculations. This approach closely matches the pack implementation. Keep track of a -in argument to a grid command in order to detect the case of an already gridded widget that wants to change some options. The previous implementation could make repeated and unnecessary calls to Tk_ManageGeometry. Replace use of "parent" with "master" in comments throughout the file. * generic/tkPack.c (PackStructureProc): Check for a NULL masterPtr before other checks so that a slave created under certain error conditions is cleaned up properly. Replace use of "parent" with "master" in comments throughout the file. * generic/tkPlace.c (CreateSlave, ConfigureSlave, SlaveStructureProc): Don't call Tk_ManageGeometry in CreateSlave since this was causing incorrect results in some error cases. Rework the ConfigureSlave method so that slave setup is done in one place. The call to Tk_ManageGeometry was added to the one place where a slave is setup. When a slave is configured but the master is not changed, simply goto the scheduleLayout label. Check for a NULL master in SlaveStructureProc for the sake of readability. * tests/grid.test: * tests/pack.test: * tests/place.test: Add test to check that a winfo manager call does not return incorrect results after an error condition is hit. [Patch 693063]
Diffstat (limited to 'generic')
-rw-r--r--generic/tkGrid.c75
-rw-r--r--generic/tkPack.c43
-rw-r--r--generic/tkPlace.c119
3 files changed, 141 insertions, 96 deletions
diff --git a/generic/tkGrid.c b/generic/tkGrid.c
index f5c3503..78fe219 100644
--- a/generic/tkGrid.c
+++ b/generic/tkGrid.c
@@ -8,7 +8,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tkGrid.c,v 1.25 2002/10/10 21:07:51 pspjuth Exp $
+ * RCS: @(#) $Id: tkGrid.c,v 1.26 2003/03/12 00:09:36 mdejong Exp $
*/
#include "tkInt.h"
@@ -141,9 +141,9 @@ typedef struct {
int rowSpace; /* The number of slots currently allocated
* for row constraints. */
int startX; /* Pixel offset of this layout within its
- * parent. */
+ * master. */
int startY; /* Pixel offset of this layout within its
- * parent. */
+ * master. */
} GridMaster;
/*
@@ -163,7 +163,7 @@ typedef struct Gridder {
* is managed (NULL means this window
* isn't managed by the gridder). */
struct Gridder *nextPtr; /* Next window managed within same
- * parent. List order doesn't matter. */
+ * master. List order doesn't matter. */
struct Gridder *slavePtr; /* First in list of slaves managed
* inside this window (NULL means
* no grid slaves). */
@@ -187,7 +187,7 @@ typedef struct Gridder {
* sticks to. See below for definitions */
int doubleBw; /* Twice the window's last known border
* width. If this changes, the window
- * must be re-arranged within its parent. */
+ * must be re-arranged within its master. */
int *abortPtr; /* If non-NULL, it means that there is a nested
* call to ArrangeGrid already working on
* this window. *abortPtr may be set to 1 to
@@ -676,7 +676,7 @@ GridLocationCommand(tkwin, interp, objc, objv)
Gridder *masterPtr; /* master grid record */
GridMaster *gridPtr; /* pointer to grid data */
register SlotInfo *slotPtr;
- int x, y; /* Offset in pixels, from edge of parent. */
+ int x, y; /* Offset in pixels, from edge of master. */
int i, j; /* Corresponding column and row indeces. */
int endX, endY; /* end of grid */
@@ -1286,7 +1286,7 @@ AdjustOffsets(size, slots, slotPtr)
}
/*
- * If all the weights are zero, center the layout in its parent if
+ * If all the weights are zero, center the layout in its master if
* there is extra space, else clip on the bottom/right.
*/
@@ -1487,7 +1487,7 @@ AdjustForSticky(slavePtr, xPtr, yPtr, widthPtr, heightPtr)
static void
ArrangeGrid(clientData)
- ClientData clientData; /* Structure describing parent whose slaves
+ ClientData clientData; /* Structure describing master whose slaves
* are to be re-layed out. */
{
register Gridder *masterPtr = (Gridder *) clientData;
@@ -1500,9 +1500,9 @@ ArrangeGrid(clientData)
masterPtr->flags &= ~REQUESTED_RELAYOUT;
/*
- * If the parent has no slaves anymore, then don't do anything
- * at all: just leave the parent's size as-is. Otherwise there is
- * no way to "relinquish" control over the parent so another geometry
+ * If the master has no slaves anymore, then don't do anything
+ * at all: just leave the master's size as-is. Otherwise there is
+ * no way to "relinquish" control over the master so another geometry
* manager can take over.
*/
@@ -1560,10 +1560,10 @@ ArrangeGrid(clientData)
}
/*
- * If the currently requested layout size doesn't match the parent's
+ * If the currently requested layout size doesn't match the master's
* window size, then adjust the slot offsets according to the
* weights. If all of the weights are zero, center the layout in
- * its parent. I haven't decided what to do if the parent is smaller
+ * its master. I haven't decided what to do if the master is smaller
* than the requested size.
*/
@@ -2325,13 +2325,13 @@ InitMasterData(masterPtr)
*
* Unlink --
*
- * Remove a grid from its parent's list of slaves.
+ * Remove a grid from its master's list of slaves.
*
* Results:
* None.
*
* Side effects:
- * The parent will be scheduled for re-arranging, and the size of the
+ * The master will be scheduled for re-arranging, and the size of the
* grid will be adjusted accordingly
*
*----------------------------------------------------------------------
@@ -2440,13 +2440,14 @@ GridStructureProc(clientData, eventPtr)
TkDisplay *dispPtr = ((TkWindow *) gridPtr->tkwin)->dispPtr;
if (eventPtr->type == ConfigureNotify) {
- if (!(gridPtr->flags & REQUESTED_RELAYOUT)) {
+ if ((gridPtr->slavePtr != NULL)
+ && !(gridPtr->flags & REQUESTED_RELAYOUT)) {
gridPtr->flags |= REQUESTED_RELAYOUT;
Tcl_DoWhenIdle(ArrangeGrid, (ClientData) gridPtr);
}
- if (gridPtr->doubleBw != 2*Tk_Changes(gridPtr->tkwin)->border_width) {
- if ((gridPtr->masterPtr != NULL) &&
- !(gridPtr->masterPtr->flags & REQUESTED_RELAYOUT)) {
+ if ((gridPtr->masterPtr != NULL)
+ && (gridPtr->doubleBw != 2*Tk_Changes(gridPtr->tkwin)->border_width)) {
+ if (!(gridPtr->masterPtr->flags & REQUESTED_RELAYOUT)) {
gridPtr->doubleBw = 2*Tk_Changes(gridPtr->tkwin)->border_width;
gridPtr->masterPtr->flags |= REQUESTED_RELAYOUT;
Tcl_DoWhenIdle(ArrangeGrid, (ClientData) gridPtr->masterPtr);
@@ -2473,7 +2474,8 @@ GridStructureProc(clientData, eventPtr)
gridPtr->tkwin = NULL;
Tcl_EventuallyFree((ClientData) gridPtr, DestroyGrid);
} else if (eventPtr->type == MapNotify) {
- if (!(gridPtr->flags & REQUESTED_RELAYOUT)) {
+ if ((gridPtr->slavePtr != NULL)
+ && !(gridPtr->flags & REQUESTED_RELAYOUT)) {
gridPtr->flags |= REQUESTED_RELAYOUT;
Tcl_DoWhenIdle(ArrangeGrid, (ClientData) gridPtr);
}
@@ -2542,6 +2544,7 @@ ConfigureSlaves(interp, tkwin, objc, objv)
int index;
char *string;
char firstChar, prevChar;
+ int positionGiven;
/*
* Count the number of windows, or window short-cuts.
@@ -2609,6 +2612,7 @@ ConfigureSlaves(interp, tkwin, objc, objv)
*/
masterPtr = NULL;
+ positionGiven = 0;
for (j = 0; j < numWindows; j++) {
string = Tcl_GetString(objv[j]);
firstChar = string[0];
@@ -2695,6 +2699,7 @@ ConfigureSlaves(interp, tkwin, objc, objv)
TCL_STATIC);
return TCL_ERROR;
}
+ positionGiven = 1;
masterPtr = GetGrid(other);
InitMasterData(masterPtr);
} else if (index == CONF_IPADX) {
@@ -2765,15 +2770,30 @@ ConfigureSlaves(interp, tkwin, objc, objv)
}
/*
- * Make sure we have a geometry master. We look at:
- * 1) the -in flag
- * 2) the geometry master of the first slave (if specified)
- * 3) the parent of the first slave.
+ * If no position was specified via -in and the slave is
+ * already packed, then leave it in its current location.
*/
-
- if (masterPtr == NULL) {
+
+ if (!positionGiven && (slavePtr->masterPtr != NULL)) {
masterPtr = slavePtr->masterPtr;
+ goto scheduleLayout;
}
+
+ /*
+ * If the same -in window is passed in again, then just
+ * leave it in its current location.
+ */
+
+ if (positionGiven && (masterPtr == slavePtr->masterPtr)) {
+ goto scheduleLayout;
+ }
+
+ /*
+ * Make sure we have a geometry master. We look at:
+ * 1) the -in flag
+ * 2) the parent of the first slave.
+ */
+
parent = Tk_Parent(slave);
if (masterPtr == NULL) {
masterPtr = GetGrid(parent);
@@ -2845,10 +2865,11 @@ ConfigureSlaves(interp, tkwin, objc, objv)
defaultColumnSpan = 1;
/*
- * Arrange for the parent to be re-arranged at the first
+ * Arrange for the master to be re-arranged at the first
* idle moment.
*/
+ scheduleLayout:
if (masterPtr->abortPtr != NULL) {
*masterPtr->abortPtr = 1;
}
diff --git a/generic/tkPack.c b/generic/tkPack.c
index 607af25..cdb52be 100644
--- a/generic/tkPack.c
+++ b/generic/tkPack.c
@@ -10,7 +10,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tkPack.c,v 1.16 2002/06/14 22:25:12 jenglish Exp $
+ * RCS: @(#) $Id: tkPack.c,v 1.17 2003/03/12 00:09:36 mdejong Exp $
*/
#include "tkPort.h"
@@ -37,12 +37,12 @@ typedef struct Packer {
* is packed (NULL means this window
* isn't managed by the packer). */
struct Packer *nextPtr; /* Next window packed within same
- * parent. List is priority-ordered:
+ * master. List is priority-ordered:
* first on list gets packed first. */
struct Packer *slavePtr; /* First in list of slaves packed
* inside this window (NULL means
* no packed slaves). */
- Side side; /* Side of parent against which
+ Side side; /* Side of master against which
* this window is packed. */
Tk_Anchor anchor; /* If frame allocated for window is larger
* than window needs, this indicates how
@@ -60,7 +60,7 @@ typedef struct Packer {
* each side). */
int doubleBw; /* Twice the window's last known border
* width. If this changes, the window
- * must be repacked within its parent. */
+ * must be repacked within its master. */
int *abortPtr; /* If non-NULL, it means that there is a nested
* call to ArrangePacking already working on
* this window. *abortPtr may be set to 1 to
@@ -83,7 +83,7 @@ typedef struct Packer {
* any larger than needed.
* FILLY: Same as FILLX, except for height.
* EXPAND: 1 means this window's frame will absorb any
- * extra space in the parent window.
+ * extra space in the master window.
* OLD_STYLE: 1 means this window is being managed with
* the old-style packer algorithms (before
* Tk version 3.3). The main difference is
@@ -544,7 +544,7 @@ PackLostSlaveProc(clientData, tkwin)
static void
ArrangePacking(clientData)
- ClientData clientData; /* Structure describing parent whose slaves
+ ClientData clientData; /* Structure describing master whose slaves
* are to be re-layed out. */
{
register Packer *masterPtr = (Packer *) clientData;
@@ -552,7 +552,7 @@ ArrangePacking(clientData)
int cavityX, cavityY, cavityWidth, cavityHeight;
/* These variables keep track of the
* as-yet-unallocated space remaining in
- * the middle of the parent window. */
+ * the middle of the master window. */
int frameX, frameY, frameWidth, frameHeight;
/* These variables keep track of the frame
* allocated to the current window. */
@@ -568,8 +568,8 @@ ArrangePacking(clientData)
masterPtr->flags &= ~REQUESTED_REPACK;
/*
- * If the parent has no slaves anymore, then don't do anything
- * at all: just leave the parent's size as-is.
+ * If the master has no slaves anymore, then don't do anything
+ * at all: just leave the master's size as-is.
*/
if (masterPtr->slavePtr == NULL) {
@@ -648,10 +648,10 @@ ArrangePacking(clientData)
}
/*
- * If the total amount of space needed in the parent window has
+ * If the total amount of space needed in the master window has
* changed, and if we're propagating geometry information, then
* notify the next geometry manager up and requeue ourselves to
- * start again after the parent has had a chance to
+ * start again after the master has had a chance to
* resize us.
*/
@@ -1129,7 +1129,7 @@ TkParsePadAmount(interp, tkwin, specObj, halfPtr, allPtr)
* PackAfter --
*
* This procedure does most of the real work of adding
- * one or more windows into the packing order for its parent.
+ * one or more windows into the packing order for its master.
*
* Results:
* A standard Tcl return value.
@@ -1316,7 +1316,7 @@ PackAfter(interp, prevPtr, masterPtr, objc, objv)
}
/*
- * Add the window in the correct place in its parent's
+ * Add the window in the correct place in its master's
* packing order, then make sure that the window is
* managed by us.
*/
@@ -1334,7 +1334,7 @@ PackAfter(interp, prevPtr, masterPtr, objc, objv)
}
/*
- * Arrange for the parent to be re-packed at the first
+ * Arrange for the master to be re-packed at the first
* idle moment.
*/
@@ -1353,13 +1353,13 @@ PackAfter(interp, prevPtr, masterPtr, objc, objv)
*
* Unlink --
*
- * Remove a packer from its parent's list of slaves.
+ * Remove a packer from its master's list of slaves.
*
* Results:
* None.
*
* Side effects:
- * The parent will be scheduled for repacking.
+ * The master will be scheduled for repacking.
*
*----------------------------------------------------------------------
*/
@@ -1458,9 +1458,9 @@ PackStructureProc(clientData, eventPtr)
packPtr->flags |= REQUESTED_REPACK;
Tcl_DoWhenIdle(ArrangePacking, (ClientData) packPtr);
}
- if (packPtr->doubleBw != 2*Tk_Changes(packPtr->tkwin)->border_width) {
- if ((packPtr->masterPtr != NULL)
- && !(packPtr->masterPtr->flags & REQUESTED_REPACK)) {
+ if ((packPtr->masterPtr != NULL)
+ && (packPtr->doubleBw != 2*Tk_Changes(packPtr->tkwin)->border_width)) {
+ if (!(packPtr->masterPtr->flags & REQUESTED_REPACK)) {
packPtr->doubleBw = 2*Tk_Changes(packPtr->tkwin)->border_width;
packPtr->masterPtr->flags |= REQUESTED_REPACK;
Tcl_DoWhenIdle(ArrangePacking, (ClientData) packPtr->masterPtr);
@@ -1759,7 +1759,8 @@ ConfigureSlaves(interp, tkwin, objc, objv)
}
/*
- * If the slave is going to be put back after itself then
+ * If the slave is going to be put back after itself or
+ * the same -in window is passed in again, then just
* skip the whole operation, since it won't work anyway.
*/
@@ -1834,7 +1835,7 @@ ConfigureSlaves(interp, tkwin, objc, objv)
prevPtr = slavePtr;
/*
- * Arrange for the parent to be re-packed at the first
+ * Arrange for the master to be re-packed at the first
* idle moment.
*/
diff --git a/generic/tkPlace.c b/generic/tkPlace.c
index 05a75fb..09452b3 100644
--- a/generic/tkPlace.c
+++ b/generic/tkPlace.c
@@ -10,7 +10,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tkPlace.c,v 1.13 2002/11/07 19:10:30 pspjuth Exp $
+ * RCS: @(#) $Id: tkPlace.c,v 1.14 2003/03/12 00:09:37 mdejong Exp $
*/
#include "tkPort.h"
@@ -398,7 +398,6 @@ CreateSlave(tkwin)
Tcl_SetHashValue(hPtr, slavePtr);
Tk_CreateEventHandler(tkwin, StructureNotifyMask, SlaveStructureProc,
(ClientData) slavePtr);
- Tk_ManageGeometry(tkwin, &placerType, (ClientData) slavePtr);
} else {
slavePtr = (Slave *) Tcl_GetHashValue(hPtr);
}
@@ -590,9 +589,9 @@ ConfigureSlave(interp, tkwin, table, objc, objv)
register Master *masterPtr;
Tk_SavedOptions savedOptions;
int mask;
- int result = TCL_OK;
Slave *slavePtr;
-
+ Tk_Window masterWin = (Tk_Window) NULL;
+
if (Tk_TopWinHierarchy(tkwin)) {
Tcl_AppendResult(interp, "can't use placer on top-level window \"",
Tk_PathName(tkwin), "\"; use wm command instead",
@@ -601,27 +600,54 @@ ConfigureSlave(interp, tkwin, table, objc, objv)
}
slavePtr = CreateSlave(tkwin);
-
+
if (Tk_SetOptions(interp, (char *)slavePtr, table, objc, objv,
slavePtr->tkwin, &savedOptions, &mask) != TCL_OK) {
- Tk_RestoreSavedOptions(&savedOptions);
- result = TCL_ERROR;
- goto done;
+ goto error;
+ }
+
+ /*
+ * Set slave flags. First clear the field, then add bits as needed.
+ */
+
+ slavePtr->flags = 0;
+ if (slavePtr->heightPtr) {
+ slavePtr->flags |= CHILD_HEIGHT;
+ }
+
+ if (slavePtr->relHeightPtr) {
+ slavePtr->flags |= CHILD_REL_HEIGHT;
+ }
+
+ if (slavePtr->relWidthPtr) {
+ slavePtr->flags |= CHILD_REL_WIDTH;
+ }
+
+ if (slavePtr->widthPtr) {
+ slavePtr->flags |= CHILD_WIDTH;
}
- if (mask & IN_MASK) {
+ if (((mask & IN_MASK) == 0) && (slavePtr->masterPtr != NULL)) {
+ /*
+ * If no -in option was passed and the slave is already placed
+ * then just recompute the placement.
+ */
+
+ masterPtr = slavePtr->masterPtr;
+ goto scheduleLayout;
+ } else if (mask & IN_MASK) {
/* -in changed */
Tk_Window tkwin;
Tk_Window ancestor;
-
+
tkwin = slavePtr->inTkwin;
-
+
/*
* Make sure that the new master is either the logical parent
* of the slave or a descendant of that window, and that the
* master and slave aren't the same.
*/
-
+
for (ancestor = tkwin; ; ancestor = Tk_Parent(ancestor)) {
if (ancestor == Tk_Parent(slavePtr->tkwin)) {
break;
@@ -630,24 +656,22 @@ ConfigureSlave(interp, tkwin, table, objc, objv)
Tcl_AppendResult(interp, "can't place ",
Tk_PathName(slavePtr->tkwin), " relative to ",
Tk_PathName(tkwin), (char *) NULL);
- result = TCL_ERROR;
- Tk_RestoreSavedOptions(&savedOptions);
- goto done;
+ goto error;
}
}
if (slavePtr->tkwin == tkwin) {
Tcl_AppendResult(interp, "can't place ",
Tk_PathName(slavePtr->tkwin), " relative to itself",
(char *) NULL);
- result = TCL_ERROR;
- Tk_RestoreSavedOptions(&savedOptions);
- goto done;
+ goto error;
}
if ((slavePtr->masterPtr != NULL)
&& (slavePtr->masterPtr->tkwin == tkwin)) {
/*
* Re-using same old master. Nothing to do.
*/
+ masterPtr = slavePtr->masterPtr;
+ goto scheduleLayout;
} else {
if ((slavePtr->masterPtr != NULL)
&& (slavePtr->masterPtr->tkwin
@@ -656,53 +680,50 @@ ConfigureSlave(interp, tkwin, table, objc, objv)
slavePtr->masterPtr->tkwin);
}
UnlinkSlave(slavePtr);
- slavePtr->masterPtr = CreateMaster(tkwin);
- slavePtr->nextPtr = slavePtr->masterPtr->slavePtr;
- slavePtr->masterPtr->slavePtr = slavePtr;
+ masterWin = tkwin;
}
}
/*
- * Set slave flags. First clear the field, then add bits as needed.
+ * If there's no master specified for this slave, use its Tk_Parent.
*/
- slavePtr->flags = 0;
- if (slavePtr->heightPtr) {
- slavePtr->flags |= CHILD_HEIGHT;
+ if (masterWin == NULL) {
+ masterWin = Tk_Parent(slavePtr->tkwin);
+ slavePtr->inTkwin = masterWin;
}
- if (slavePtr->relHeightPtr) {
- slavePtr->flags |= CHILD_REL_HEIGHT;
- }
+ /*
+ * Manage the slave window in this master.
+ */
- if (slavePtr->relWidthPtr) {
- slavePtr->flags |= CHILD_REL_WIDTH;
- }
-
- if (slavePtr->widthPtr) {
- slavePtr->flags |= CHILD_WIDTH;
- }
+ masterPtr = CreateMaster(masterWin);
+ slavePtr->masterPtr = masterPtr;
+ slavePtr->nextPtr = masterPtr->slavePtr;
+ masterPtr->slavePtr = slavePtr;
+ Tk_ManageGeometry(slavePtr->tkwin, &placerType, (ClientData) slavePtr);
/*
- * If there's no master specified for this slave, use its Tk_Parent.
- * Then arrange for a placement recalculation in the master.
+ * Arrange for the master to be re-arranged at the first
+ * idle moment.
*/
+ scheduleLayout:
Tk_FreeSavedOptions(&savedOptions);
- done:
- masterPtr = slavePtr->masterPtr;
- if (masterPtr == NULL) {
- masterPtr = CreateMaster(Tk_Parent(slavePtr->tkwin));
- slavePtr->masterPtr = masterPtr;
- slavePtr->nextPtr = masterPtr->slavePtr;
- masterPtr->slavePtr = slavePtr;
- }
- slavePtr->inTkwin = masterPtr->tkwin;
+
if (!(masterPtr->flags & PARENT_RECONFIG_PENDING)) {
masterPtr->flags |= PARENT_RECONFIG_PENDING;
Tcl_DoWhenIdle(RecomputePlacement, (ClientData) masterPtr);
}
- return result;
+ return TCL_OK;
+
+ /*
+ * Error while processing some option, cleanup and return.
+ */
+
+ error:
+ Tk_RestoreSavedOptions(&savedOptions);
+ return TCL_ERROR;
}
/*
@@ -1074,7 +1095,9 @@ SlaveStructureProc(clientData, eventPtr)
TkDisplay * dispPtr = ((TkWindow *) slavePtr->tkwin)->dispPtr;
if (eventPtr->type == DestroyNotify) {
- UnlinkSlave(slavePtr);
+ if (slavePtr->masterPtr != NULL) {
+ UnlinkSlave(slavePtr);
+ }
Tcl_DeleteHashEntry(Tcl_FindHashEntry(&dispPtr->slaveTable,
(char *) slavePtr->tkwin));
ckfree((char *) slavePtr);