diff options
author | jan.nijtmans <nijtmans@users.sourceforge.net> | 2021-03-19 14:14:30 (GMT) |
---|---|---|
committer | jan.nijtmans <nijtmans@users.sourceforge.net> | 2021-03-19 14:14:30 (GMT) |
commit | 1a3588fddcd6bac239367f9c7dc73b642a2546a5 (patch) | |
tree | 2ca3dd23672c89bcd9be71aec17fdc6890b0c18b | |
parent | 395fb77029e7e4741eae88dd24edcc3cc3d2ab61 (diff) | |
parent | ebf11bca7e41dee3139cbb8c1c07113246920de4 (diff) | |
download | tk-1a3588fddcd6bac239367f9c7dc73b642a2546a5.zip tk-1a3588fddcd6bac239367f9c7dc73b642a2546a5.tar.gz tk-1a3588fddcd6bac239367f9c7dc73b642a2546a5.tar.bz2 |
Fix [9b6065d1fd]: Tk doesn't restore overwritten Tcl command "update"
-rw-r--r-- | generic/tkInt.h | 4 | ||||
-rw-r--r-- | generic/tkWindow.c | 27 | ||||
-rw-r--r-- | tests/window.test | 33 |
3 files changed, 60 insertions, 4 deletions
diff --git a/generic/tkInt.h b/generic/tkInt.h index fc4b0cd..c281821 100644 --- a/generic/tkInt.h +++ b/generic/tkInt.h @@ -679,6 +679,10 @@ typedef struct TkMainInfo { struct TkMainInfo *nextPtr; /* Next in list of all main windows managed by * this process. */ Tcl_HashTable busyTable; /* Information used by [tk busy] command. */ + Tcl_ObjCmdProc *tclUpdateObjProc; + /* Saved Tcl [update] command, used to restore + * Tcl's version of [update] after Tk is shut + * down */ } TkMainInfo; /* diff --git a/generic/tkWindow.c b/generic/tkWindow.c index 9750ed8..c2f6eaa 100644 --- a/generic/tkWindow.c +++ b/generic/tkWindow.c @@ -93,6 +93,7 @@ static const XSetWindowAttributes defAtts= { #define PASSMAINWINDOW 2 #define WINMACONLY 4 #define USEINITPROC 8 +#define SAVEUPDATECMD 16 /* better only be one of these! */ typedef int (TkInitProc)(Tcl_Interp *interp, ClientData clientData); typedef struct { @@ -126,7 +127,7 @@ static const TkCmd commands[] = { {"selection", Tk_SelectionObjCmd, PASSMAINWINDOW}, {"tk", (Tcl_ObjCmdProc *)(void *)TkInitTkCmd, USEINITPROC|PASSMAINWINDOW|ISSAFE}, {"tkwait", Tk_TkwaitObjCmd, PASSMAINWINDOW|ISSAFE}, - {"update", Tk_UpdateObjCmd, PASSMAINWINDOW|ISSAFE}, + {"update", Tk_UpdateObjCmd, PASSMAINWINDOW|ISSAFE|SAVEUPDATECMD}, {"winfo", Tk_WinfoObjCmd, PASSMAINWINDOW|ISSAFE}, {"wm", Tk_WmObjCmd, PASSMAINWINDOW}, @@ -880,6 +881,7 @@ TkCreateMainWindow( Tcl_InitHashTable(&mainPtr->imageTable, TCL_STRING_KEYS); mainPtr->strictMotif = 0; mainPtr->alwaysShowSelection = 0; + mainPtr->tclUpdateObjProc = NULL; if (Tcl_LinkVar(interp, "tk_strictMotif", (char *) &mainPtr->strictMotif, TCL_LINK_BOOLEAN) != TCL_OK) { Tcl_ResetResult(interp); @@ -919,6 +921,8 @@ TkCreateMainWindow( isSafe = Tcl_IsSafe(interp); for (cmdPtr = commands; cmdPtr->name != NULL; cmdPtr++) { + Tcl_CmdInfo cmdInfo; + if (cmdPtr->objProc == NULL) { Tcl_Panic("TkCreateMainWindow: builtin command with NULL string and object procs"); } @@ -938,6 +942,11 @@ TkCreateMainWindow( } else { clientData = NULL; } + if ((cmdPtr->flags & SAVEUPDATECMD) && + Tcl_GetCommandInfo(interp, cmdPtr->name, &cmdInfo) && + cmdInfo.isNativeObjectProc) { + mainPtr->tclUpdateObjProc = cmdInfo.objProc; + } if (cmdPtr->flags & USEINITPROC) { ((TkInitProc *)(void *)cmdPtr->objProc)(interp, clientData); } else { @@ -1502,10 +1511,20 @@ Tk_DestroyWindow( */ if ((winPtr->mainPtr->interp != NULL) && - !Tcl_InterpDeleted(winPtr->mainPtr->interp)) { + !Tcl_InterpDeleted(winPtr->mainPtr->interp)) { for (cmdPtr = commands; cmdPtr->name != NULL; cmdPtr++) { - Tcl_CreateObjCommand(winPtr->mainPtr->interp, cmdPtr->name, - TkDeadAppObjCmd, NULL, NULL); + if ((cmdPtr->flags & SAVEUPDATECMD) && + winPtr->mainPtr->tclUpdateObjProc != NULL) { + /* Restore Tcl's version of [update] */ + Tcl_CreateObjCommand(winPtr->mainPtr->interp, + cmdPtr->name, + winPtr->mainPtr->tclUpdateObjProc, + NULL, NULL); + } else { + Tcl_CreateObjCommand(winPtr->mainPtr->interp, + cmdPtr->name, TkDeadAppObjCmd, + NULL, NULL); + } } Tcl_CreateObjCommand(winPtr->mainPtr->interp, "send", TkDeadAppObjCmd, NULL, NULL); diff --git a/tests/window.test b/tests/window.test index fea695a..c3b507d 100644 --- a/tests/window.test +++ b/tests/window.test @@ -263,6 +263,38 @@ test window-2.11 {Tk_DestroyWindow, don't reanimate a half-dead window} -constra list $error $msg } -result {0 YES} +test window-2.12 {Test for ticket [9b6065d1fd] - restore Tcl [update] command} -constraints { + unixOrWin +} -body { + set code [loadTkCommand] + append code { + after 1000 {set forever 1} + after 100 {destroy .} + after 200 {catch bell msg; puts "ringing the bell -> $msg"} + after 250 {update idletasks} + after 300 {update} + puts "waiting" + vwait forever + puts "done waiting" + catch {bell} msg + puts "bell -> $msg" + catch update msg + puts "update -> $msg" + } + set script [makeFile $code script] + if {[catch {exec [interpreter] $script -geometry 10x10+0+0} msg]} { + set error 1 + } else { + set error 0 + } + removeFile script + list $error $msg +} -result {0 {waiting +ringing the bell -> can't invoke "bell" command: application has been destroyed +done waiting +bell -> can't invoke "bell" command: application has been destroyed +update -> }} + test window-3.1 {Tk_MakeWindowExist procedure, stacking order and menubars} -constraints { unix testmenubar @@ -342,6 +374,7 @@ test window-5.1 {Tk_MakeWindowExist procedure, stacking order and menubars} -con } -result {} + # cleanup cleanupTests return |