summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog13
-rw-r--r--generic/tk.h3
-rw-r--r--generic/tkGeometry.c81
-rw-r--r--generic/tkGrid.c49
-rw-r--r--generic/tkInt.h8
-rw-r--r--generic/tkPack.c49
-rw-r--r--generic/tkWindow.c7
-rw-r--r--tests/grid.test4
-rw-r--r--tests/packgrid.test223
-rw-r--r--tests/textIndex.test4
10 files changed, 431 insertions, 10 deletions
diff --git a/ChangeLog b/ChangeLog
index 5b08e80..a60818b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+2009-08-19 Peter Spjuth <peter.spjuth@gmail.com>
+
+ * generic/tk.h
+ * generic/tkGeometry.c
+ * generic/tkGrid.c
+ * generic/tkInt.h
+ * generic/tkPack.c
+ * generic/tkWindow.c
+ * tests/grid.test
+ * tests/packgrid.test
+ * tests/textIndex.test: Give an error if grid and pack are used in the
+ same master. [Patch 2475855]
+
2009-08-14 Daniel Steffen <das@users.sourceforge.net>
* macosx/tkMacOSXDraw.c: Avoid exception in XCopyArea() when copying
diff --git a/generic/tk.h b/generic/tk.h
index 0ebd36b..167da5a 100644
--- a/generic/tk.h
+++ b/generic/tk.h
@@ -12,7 +12,7 @@
* See the file "license.terms" for information on usage and redistribution of
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tk.h,v 1.130 2009/06/29 14:35:01 das Exp $
+ * RCS: @(#) $Id: tk.h,v 1.131 2009/08/19 23:02:00 pspjuth Exp $
*/
#ifndef _TK
@@ -791,6 +791,7 @@ typedef struct Tk_FakeWin {
int internalBorderBottom;
int minReqWidth;
int minReqHeight;
+ char *dummy20; /* geometryMaster */
} Tk_FakeWin;
/*
diff --git a/generic/tkGeometry.c b/generic/tkGeometry.c
index 53bd140..b5a1654 100644
--- a/generic/tkGeometry.c
+++ b/generic/tkGeometry.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: tkGeometry.c,v 1.14 2008/11/08 18:44:40 dkf Exp $
+ * RCS: @(#) $Id: tkGeometry.c,v 1.15 2009/08/19 23:02:00 pspjuth Exp $
*/
#include "tkInt.h"
@@ -306,6 +306,85 @@ Tk_SetMinimumRequestSize(
/*
*----------------------------------------------------------------------
*
+ * TkSetGeometryMaster --
+ *
+ * Set a geometry master for this window. Only one master may own
+ * a window at any time.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * The geometry master is recorded for the window.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TkSetGeometryMaster(
+ Tcl_Interp *interp, /* Current interpreter, for error. */
+ Tk_Window tkwin, /* Window that will have geometry master set. */
+ const char *master) /* The master identity. */
+{
+ register TkWindow *winPtr = (TkWindow *) tkwin;
+
+ if (winPtr->geometryMaster != NULL &&
+ strcmp(winPtr->geometryMaster, master) == 0) {
+ return TCL_OK;
+ }
+ if (winPtr->geometryMaster != NULL) {
+ if (interp != NULL) {
+ Tcl_AppendResult(interp, "cannot use geometry manager ", master,
+ " inside ", Tk_PathName(tkwin),
+ " which already has slaves managed by ",
+ winPtr->geometryMaster, NULL);
+ }
+ return TCL_ERROR;
+ }
+
+ winPtr->geometryMaster = ckalloc(strlen(master) + 1);
+ strcpy(winPtr->geometryMaster, master);
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkFreeGeometryMaster --
+ *
+ * Remove a geometry master for this window. Only one master may own
+ * a window at any time.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The geometry master is cleared for the window.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkFreeGeometryMaster(
+ Tk_Window tkwin, /* Window that will have geometry master cleared. */
+ const char *master) /* The master identity. */
+{
+ register TkWindow *winPtr = (TkWindow *) tkwin;
+
+ if (winPtr->geometryMaster != NULL &&
+ strcmp(winPtr->geometryMaster, master) != 0) {
+ Tcl_Panic("Trying to free %s from geometry manager %s.",
+ winPtr->geometryMaster, master);
+ }
+ if (winPtr->geometryMaster != NULL) {
+ ckfree(winPtr->geometryMaster);
+ winPtr->geometryMaster = NULL;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
* Tk_MaintainGeometry --
*
* This procedure is invoked by geometry managers to handle slaves whose
diff --git a/generic/tkGrid.c b/generic/tkGrid.c
index b4392f3..6dbe9a3 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.52 2009/02/03 23:55:47 nijtmans Exp $
+ * RCS: @(#) $Id: tkGrid.c,v 1.53 2009/08/19 23:02:00 pspjuth Exp $
*/
#include "tkInt.h"
@@ -242,10 +242,13 @@ typedef struct UniformGroup {
* size. 0 means if this window is a master then
* Tk will set its requested size to fit the
* needs of its slaves.
+ * ALLOCED_MASTER 1 means that Grid has allocated itself as
+ * geometry master for this window.
*/
#define REQUESTED_RELAYOUT 1
#define DONT_PROPAGATE 2
+#define ALLOCED_MASTER 4
/*
* Prototypes for procedures used only in this file:
@@ -875,8 +878,22 @@ GridPropagateCommand(
old = !(masterPtr->flags & DONT_PROPAGATE);
if (propagate != old) {
if (propagate) {
+ /*
+ * If we have slaves, we need to register as geometry master.
+ */
+
+ if (masterPtr->slavePtr != NULL) {
+ if (TkSetGeometryMaster(interp, master, "grid") != TCL_OK) {
+ return TCL_ERROR;
+ }
+ masterPtr->flags |= ALLOCED_MASTER;
+ }
masterPtr->flags &= ~DONT_PROPAGATE;
} else {
+ if (masterPtr->flags & ALLOCED_MASTER) {
+ TkFreeGeometryMaster(master, "grid");
+ masterPtr->flags &= ~ALLOCED_MASTER;
+ }
masterPtr->flags |= DONT_PROPAGATE;
}
@@ -2724,6 +2741,16 @@ Unlink(
SetGridSize(slavePtr->masterPtr);
slavePtr->masterPtr = NULL;
+
+ /*
+ * If we have emptied this master from slaves it means we are no longer
+ * handling it and should mark it as free.
+ */
+
+ if ((masterPtr->slavePtr == NULL) && (masterPtr->flags & ALLOCED_MASTER)) {
+ TkFreeGeometryMaster(masterPtr->tkwin, "grid");
+ masterPtr->flags &= ~ALLOCED_MASTER;
+ }
}
/*
@@ -3262,6 +3289,15 @@ ConfigureSlaves(
Tk_ManageGeometry(slave, &gridMgrType, slavePtr);
+ if (!(masterPtr->flags & DONT_PROPAGATE)) {
+ if (TkSetGeometryMaster(interp, masterPtr->tkwin, "grid")
+ != TCL_OK) {
+ Tk_ManageGeometry(slave, NULL, NULL);
+ return TCL_ERROR;
+ }
+ masterPtr->flags |= ALLOCED_MASTER;
+ }
+
/*
* Assign default position information.
*/
@@ -3386,6 +3422,17 @@ ConfigureSlaves(
return TCL_ERROR;
}
SetGridSize(masterPtr);
+
+ /*
+ * If we have emptied this master from slaves it means we are no longer
+ * handling it and should mark it as free.
+ */
+
+ if (masterPtr->slavePtr == NULL && masterPtr->flags & ALLOCED_MASTER) {
+ TkFreeGeometryMaster(masterPtr->tkwin, "grid");
+ masterPtr->flags &= ~ALLOCED_MASTER;
+ }
+
return TCL_OK;
}
diff --git a/generic/tkInt.h b/generic/tkInt.h
index 430d51e..958695e 100644
--- a/generic/tkInt.h
+++ b/generic/tkInt.h
@@ -11,7 +11,7 @@
* See the file "license.terms" for information on usage and redistribution of
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: $Id: tkInt.h,v 1.106 2009/07/02 10:34:32 patthoyts Exp $
+ * RCS: $Id: tkInt.h,v 1.107 2009/08/19 23:02:00 pspjuth Exp $
*/
#ifndef _TKINT
@@ -851,6 +851,7 @@ typedef struct TkWindow {
int minReqWidth; /* Minimum requested width. */
int minReqHeight; /* Minimum requested height. */
+ char *geometryMaster;
} TkWindow;
/*
@@ -1164,6 +1165,11 @@ MODULE_SCOPE int Tk_WmObjCmd(ClientData clientData, Tcl_Interp *interp,
MODULE_SCOPE int Tk_GetDoublePixelsFromObj(Tcl_Interp *interp,
Tk_Window tkwin, Tcl_Obj *objPtr,
double *doublePtr);
+MODULE_SCOPE int TkSetGeometryMaster(Tcl_Interp *interp,
+ Tk_Window tkwin, const char *master);
+MODULE_SCOPE void TkFreeGeometryMaster(Tk_Window tkwin,
+ const char *master);
+
MODULE_SCOPE void TkEventInit(void);
MODULE_SCOPE void TkRegisterObjTypes(void);
MODULE_SCOPE int TkCreateMenuCmd(Tcl_Interp *interp);
diff --git a/generic/tkPack.c b/generic/tkPack.c
index 334afdb..c113e6f 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.33 2009/02/03 23:55:47 nijtmans Exp $
+ * RCS: @(#) $Id: tkPack.c,v 1.34 2009/08/19 23:02:00 pspjuth Exp $
*/
#include "tkInt.h"
@@ -89,6 +89,8 @@ typedef struct Packer {
* size. 0 means if this window is a master then
* Tk will set its requested size to fit the
* needs of its slaves.
+ * ALLOCED_MASTER 1 means that Pack has allocated itself as
+ * geometry master for this window.
*/
#define REQUESTED_REPACK 1
@@ -97,6 +99,7 @@ typedef struct Packer {
#define EXPAND 8
#define OLD_STYLE 16
#define DONT_PROPAGATE 32
+#define ALLOCED_MASTER 64
/*
* The following structure is the official type record for the packer:
@@ -385,6 +388,16 @@ Tk_PackObjCmd(
return TCL_ERROR;
}
if (propagate) {
+ /*
+ * If we have slaves, we need to register as geometry master.
+ */
+
+ if (masterPtr->slavePtr != NULL) {
+ if (TkSetGeometryMaster(interp, master, "pack") != TCL_OK) {
+ return TCL_ERROR;
+ }
+ masterPtr->flags |= ALLOCED_MASTER;
+ }
masterPtr->flags &= ~DONT_PROPAGATE;
/*
@@ -400,6 +413,10 @@ Tk_PackObjCmd(
Tcl_DoWhenIdle(ArrangePacking, masterPtr);
}
} else {
+ if (masterPtr->flags & ALLOCED_MASTER) {
+ TkFreeGeometryMaster(master, "pack");
+ masterPtr->flags &= ~ALLOCED_MASTER;
+ }
masterPtr->flags |= DONT_PROPAGATE;
}
break;
@@ -1239,6 +1256,15 @@ PackAfter(
prevPtr->nextPtr = packPtr;
}
Tk_ManageGeometry(tkwin, &packerType, packPtr);
+
+ if (!(masterPtr->flags & DONT_PROPAGATE)) {
+ if (TkSetGeometryMaster(interp, masterPtr->tkwin, "pack")
+ != TCL_OK) {
+ Tk_ManageGeometry(tkwin, NULL, NULL);
+ return TCL_ERROR;
+ }
+ masterPtr->flags |= ALLOCED_MASTER;
+ }
}
}
@@ -1304,6 +1330,17 @@ Unlink(
}
packPtr->masterPtr = NULL;
+
+ /*
+ * If we have emptied this master from slaves it means we are no longer
+ * handling it and should mark it as free.
+ */
+
+ if (masterPtr->slavePtr == NULL && masterPtr->flags & ALLOCED_MASTER) {
+ TkFreeGeometryMaster(masterPtr->tkwin, "pack");
+ masterPtr->flags &= ~ALLOCED_MASTER;
+ }
+
}
/*
@@ -1740,6 +1777,7 @@ ConfigureSlaves(
}
Unlink(slavePtr);
}
+
slavePtr->masterPtr = masterPtr;
if (prevPtr == NULL) {
slavePtr->nextPtr = masterPtr->slavePtr;
@@ -1751,6 +1789,15 @@ ConfigureSlaves(
Tk_ManageGeometry(slave, &packerType, slavePtr);
prevPtr = slavePtr;
+ if (!(masterPtr->flags & DONT_PROPAGATE)) {
+ if (TkSetGeometryMaster(interp, masterPtr->tkwin, "pack")
+ != TCL_OK) {
+ Tk_ManageGeometry(slave, NULL, NULL);
+ return TCL_ERROR;
+ }
+ masterPtr->flags |= ALLOCED_MASTER;
+ }
+
/*
* Arrange for the master to be re-packed at the first idle moment.
*/
diff --git a/generic/tkWindow.c b/generic/tkWindow.c
index 8c2d435..70c8472 100644
--- a/generic/tkWindow.c
+++ b/generic/tkWindow.c
@@ -11,7 +11,7 @@
* See the file "license.terms" for information on usage and redistribution of
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tkWindow.c,v 1.103 2009/02/27 23:04:39 patthoyts Exp $
+ * RCS: @(#) $Id: tkWindow.c,v 1.104 2009/08/19 23:02:00 pspjuth Exp $
*/
#include "tkInt.h"
@@ -709,6 +709,7 @@ TkAllocWindow(
winPtr->internalBorderBottom = 0;
winPtr->minReqWidth = 0;
winPtr->minReqHeight = 0;
+ winPtr->geometryMaster = NULL;
return winPtr;
}
@@ -1485,6 +1486,10 @@ Tk_DestroyWindow(
TkOptionDeadWindow(winPtr);
TkSelDeadWindow(winPtr);
TkGrabDeadWindow(winPtr);
+ if (winPtr->geometryMaster != NULL) {
+ ckfree(winPtr->geometryMaster);
+ winPtr->geometryMaster = NULL;
+ }
if (winPtr->mainPtr != NULL) {
if (winPtr->pathName != NULL) {
Tk_DeleteAllBindings(winPtr->mainPtr->bindingTable,
diff --git a/tests/grid.test b/tests/grid.test
index bb89096..62e4eb3 100644
--- a/tests/grid.test
+++ b/tests/grid.test
@@ -5,7 +5,7 @@
# Copyright (c) 1998-1999 by Scriptics Corporation.
# All rights reserved.
#
-# RCS: @(#) $Id: grid.test,v 1.34 2008/08/27 18:08:02 pspjuth Exp $
+# RCS: @(#) $Id: grid.test,v 1.35 2009/08/19 23:02:00 pspjuth Exp $
package require tcltest 2.2
eval tcltest::configure $argv
@@ -1483,7 +1483,7 @@ test grid-15.2 {lost slave} -body {
button .b
grid .b -in .f
set a [grid slaves .f]
- pack .b
+ pack .b -in .f
lappend a [grid slaves .f]
grid .b -in .f
lappend a [grid slaves .f]
diff --git a/tests/packgrid.test b/tests/packgrid.test
new file mode 100644
index 0000000..cbbb6f0
--- /dev/null
+++ b/tests/packgrid.test
@@ -0,0 +1,223 @@
+# This file is a Tcl script to test out interaction between Tk's "pack" and
+# "grid" commands.
+# It is organized in the standard fashion for Tcl tests.
+#
+# Copyright (c) 2008 Peter Spjuth
+# All rights reserved.
+#
+# RCS: @(#) $Id: packgrid.test,v 1.1 2009/08/19 23:02:00 pspjuth Exp $
+#
+
+package require tcltest 2.2
+eval tcltest::configure $argv
+tcltest::loadTestedCommands
+namespace import -force tcltest::*
+
+test packgrid-1.1 {pack and grid in same master} -setup {
+ grid propagate . true
+ pack propagate . true
+ label .p -text PACK
+ label .g -text GRID
+} -body {
+ # Basic conflict
+ grid .g
+ pack .p
+} -returnCodes error -cleanup {
+ destroy .p
+ destroy .g
+} -result {cannot use geometry manager pack inside . which already has slaves managed by grid}
+
+test packgrid-1.2 {pack and grid in same master} -setup {
+ grid propagate . true
+ pack propagate . true
+ label .p -text PACK
+ label .g -text GRID
+} -body {
+ # Basic conflict
+ pack .p
+ grid .g
+} -returnCodes error -cleanup {
+ destroy .p
+ destroy .g
+} -result {cannot use geometry manager grid inside . which already has slaves managed by pack}
+
+test packgrid-1.3 {pack and grid in same master} -setup {
+ grid propagate . false
+ pack propagate . true
+ label .p -text PACK
+ label .g -text GRID
+} -body {
+ # Ok if one is non-propagating
+ grid .g
+ pack .p
+} -cleanup {
+ destroy .p
+ destroy .g
+} -result {}
+
+test packgrid-1.4 {pack and grid in same master} -setup {
+ grid propagate . false
+ pack propagate . true
+ label .p -text PACK
+ label .g -text GRID
+} -body {
+ # Ok if one is non-propagating
+ pack .p
+ grid .g
+} -cleanup {
+ destroy .p
+ destroy .g
+} -result {}
+
+test packgrid-1.5 {pack and grid in same master} -setup {
+ grid propagate . true
+ pack propagate . false
+ label .p -text PACK
+ label .g -text GRID
+} -body {
+ # Ok if one is non-propagating
+ grid .g
+ pack .p
+} -cleanup {
+ destroy .p
+ destroy .g
+} -result {}
+
+test packgrid-1.6 {pack and grid in same master} -setup {
+ grid propagate . true
+ pack propagate . false
+ label .p -text PACK
+ label .g -text GRID
+} -body {
+ # Ok if one is non-propagating
+ pack .p
+ grid .g
+} -cleanup {
+ destroy .p
+ destroy .g
+} -result {}
+
+test packgrid-2.1 {pack and grid in same master, change propagation} -setup {
+ grid propagate . false
+ pack propagate . true
+ label .p -text PACK
+ label .g -text GRID
+ pack .p
+ grid .g
+ update
+} -body {
+ grid propagate . true
+} -returnCodes error -cleanup {
+ destroy .p
+ destroy .g
+} -result {cannot use geometry manager grid inside . which already has slaves managed by pack}
+
+test packgrid-2.2 {pack and grid in same master, change propagation} -setup {
+ grid propagate . true
+ pack propagate . false
+ label .p -text PACK
+ label .g -text GRID
+ pack .p
+ grid .g
+ update
+} -body {
+ pack propagate . true
+} -returnCodes error -cleanup {
+ destroy .p
+ update
+ destroy .g
+} -result {cannot use geometry manager pack inside . which already has slaves managed by grid}
+
+test packgrid-2.3 {pack and grid in same master, change propagation} -setup {
+ grid propagate . false
+ pack propagate . false
+ label .p -text PACK
+ label .g -text GRID
+ pack .p
+ grid .g
+ update
+} -body {
+ grid propagate . true
+ update
+ pack propagate . true
+} -returnCodes error -cleanup {
+ destroy .p
+ destroy .g
+} -result {cannot use geometry manager pack inside . which already has slaves managed by grid}
+
+test packgrid-2.4 {pack and grid in same master, change propagation} -setup {
+ grid propagate . false
+ pack propagate . false
+ label .p -text PACK
+ label .g -text GRID
+ pack .p
+ grid .g
+ update
+} -body {
+ pack propagate . true
+ grid propagate . true
+} -returnCodes error -cleanup {
+ destroy .p
+ destroy .g
+} -result {cannot use geometry manager grid inside . which already has slaves managed by pack}
+
+test packgrid-3.1 {stealing slave} -setup {
+ grid propagate . true
+ pack propagate . true
+ label .p -text PACK
+ label .g -text GRID
+} -body {
+ # Ok to steal if the other one is emptied
+ grid .g
+ pack .g
+} -cleanup {
+ destroy .p
+ destroy .g
+} -result {}
+
+test packgrid-3.2 {stealing slave} -setup {
+ grid propagate . true
+ pack propagate . true
+ label .p -text PACK
+ label .g -text GRID
+} -body {
+ # Ok to steal if the other one is emptied
+ pack .g
+ grid .g
+} -cleanup {
+ destroy .p
+ destroy .g
+} -result {}
+
+test packgrid-3.3 {stealing slave} -setup {
+ grid propagate . true
+ pack propagate . true
+ label .p -text PACK
+ label .g -text GRID
+} -body {
+ # Not ok to steal if the other one is not emptied
+ grid .g
+ grid .p
+ pack .g
+} -returnCodes error -cleanup {
+ destroy .p
+ destroy .g
+} -result {cannot use geometry manager pack inside . which already has slaves managed by grid}
+
+test packgrid-3.4 {stealing slave} -setup {
+ grid propagate . true
+ pack propagate . true
+ label .p -text PACK
+ label .g -text GRID
+} -body {
+ # Not ok to steal if the other one is not emptied
+ pack .g
+ pack .p
+ grid .g
+} -returnCodes error -cleanup {
+ destroy .p
+ destroy .g
+} -result {cannot use geometry manager grid inside . which already has slaves managed by pack}
+
+cleanupTests
+return
diff --git a/tests/textIndex.test b/tests/textIndex.test
index 1546973..3b417d0 100644
--- a/tests/textIndex.test
+++ b/tests/textIndex.test
@@ -6,7 +6,7 @@
# Copyright (c) 1998-1999 by Scriptics Corporation.
# All rights reserved.
#
-# RCS: @(#) $Id: textIndex.test,v 1.18 2005/07/18 22:12:05 vincentdarley Exp $
+# RCS: @(#) $Id: textIndex.test,v 1.19 2009/08/19 23:02:00 pspjuth Exp $
package require tcltest 2.1
eval tcltest::configure $argv
@@ -784,7 +784,7 @@ test textIndex-19.12 {Display lines} {
} {2.20}
test textIndex-19.13 {Display lines} {
- destroy .t
+ destroy {*}[pack slaves .]
text .txt -height 1 -wrap word -yscroll ".sbar set" -width 400
scrollbar .sbar -command ".txt yview"
grid .txt .sbar -sticky news