Index: generic/tkInt.h ================================================================== --- generic/tkInt.h +++ generic/tkInt.h @@ -1090,14 +1090,15 @@ #ifdef __cplusplus extern "C" { #endif /* - * Themed widget set init function: + * Themed widget set init function, and handler called when Tk is destroyed. */ MODULE_SCOPE int Ttk_Init(Tcl_Interp *interp); +MODULE_SCOPE void Ttk_TkDestroyedHandler(Tcl_Interp *interp); /* * Internal functions shared among Tk modules but not exported to the outside * world: */ Index: generic/tkWindow.c ================================================================== --- generic/tkWindow.c +++ generic/tkWindow.c @@ -1619,10 +1619,11 @@ TkBindFree(winPtr->mainPtr); TkDeleteAllImages(winPtr->mainPtr); TkFontPkgFree(winPtr->mainPtr); TkFocusFree(winPtr->mainPtr); TkStylePkgFree(winPtr->mainPtr); + Ttk_TkDestroyedHandler(winPtr->mainPtr->interp); /* * When embedding Tk into other applications, make sure that all * destroy events reach the server. Otherwise the embedding * application may also attempt to destroy the windows, resulting Index: generic/ttk/ttkTheme.c ================================================================== --- generic/ttk/ttkTheme.c +++ generic/ttk/ttkTheme.c @@ -401,12 +401,10 @@ Cleanup *cleanupList; /* Cleanup records */ Ttk_ResourceCache cache; /* Resource cache */ int themeChangePending; /* scheduled ThemeChangedProc call? */ } StylePackageData; -static void ThemeChangedProc(void *); /* Forward */ - /* Ttk_StylePkgFree -- * Cleanup procedure for StylePackageData. */ static void Ttk_StylePkgFree( ClientData clientData, @@ -415,17 +413,10 @@ StylePackageData *pkgPtr = (StylePackageData *)clientData; Tcl_HashSearch search; Tcl_HashEntry *entryPtr; Cleanup *cleanup; - /* - * Cancel any pending ThemeChanged calls: - */ - if (pkgPtr->themeChangePending) { - Tcl_CancelIdleCall(ThemeChangedProc, pkgPtr); - } - /* * Free themes. */ entryPtr = Tcl_FirstHashEntry(&pkgPtr->themeTable, &search); while (entryPtr != NULL) { @@ -484,11 +475,11 @@ * */ void Ttk_RegisterCleanup( Tcl_Interp *interp, ClientData clientData, Ttk_CleanupProc *cleanupProc) { - StylePackageData *pkgPtr = (StylePackageData *)GetStylePackageData(interp); + StylePackageData *pkgPtr = GetStylePackageData(interp); Cleanup *cleanup = (Cleanup *)ckalloc(sizeof(*cleanup)); cleanup->clientData = clientData; cleanup->cleanupProc = cleanupProc; cleanup->next = pkgPtr->cleanupList; @@ -528,10 +519,29 @@ if (!pkgPtr->themeChangePending) { Tcl_DoWhenIdle(ThemeChangedProc, pkgPtr); pkgPtr->themeChangePending = 1; } } + +/* Ttk_TkDestroyedHandler -- + * See bug [310c74ecf440]: idle calls to ThemeChangedProc() + * need to be canceled when Tk is destroyed, since the interp + * may still be active afterward; canceling them from + * Ttk_StylePkgFree() would be too late. + */ +void Ttk_TkDestroyedHandler( + Tcl_Interp* interp) +{ + StylePackageData* pkgPtr = GetStylePackageData(interp); + + /* + * Cancel any pending ThemeChanged calls: + */ + if (pkgPtr->themeChangePending) { + Tcl_CancelIdleCall(ThemeChangedProc, pkgPtr); + } +} /* * Ttk_CreateTheme -- * Create a new theme and register it in the global theme table. *