From 5a3617067387db921c9984395fbe013d68dc1d24 Mon Sep 17 00:00:00 2001 From: culler Date: Thu, 7 Nov 2019 23:22:34 +0000 Subject: Fix [c4abd2b0f3]: Tcl Panic in TkWmStackorderToplevel (for Aqua) --- macosx/tkMacOSXWm.c | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/macosx/tkMacOSXWm.c b/macosx/tkMacOSXWm.c index c2b67f6..dda6c19 100644 --- a/macosx/tkMacOSXWm.c +++ b/macosx/tkMacOSXWm.c @@ -3309,18 +3309,18 @@ WmStackorderCmd( if (objc == 3) { windows = TkWmStackorderToplevel(winPtr); - if (windows == NULL) { - Tcl_Panic("TkWmStackorderToplevel failed"); - } - - resultObj = Tcl_NewObj(); - for (windowPtr = windows; *windowPtr ; windowPtr++) { - Tcl_ListObjAppendElement(NULL, resultObj, + if (windows != NULL) { + resultObj = Tcl_NewObj(); + for (windowPtr = windows; *windowPtr ; windowPtr++) { + Tcl_ListObjAppendElement(NULL, resultObj, TkNewWindowObj((Tk_Window) *windowPtr)); + } + Tcl_SetObjResult(interp, resultObj); + ckfree(windows); + return TCL_OK; + } else { + return TCL_ERROR; } - Tcl_SetObjResult(interp, resultObj); - ckfree(windows); - return TCL_OK; } else { TkWindow *winPtr2; int index1 = -1, index2 = -1, result; @@ -6701,10 +6701,6 @@ TkWmStackorderToplevel( *windowPtr-- = childWinPtr; } } - if (windowPtr != windows-1) { - Tcl_Panic("num matched toplevel windows does not equal num " - "children"); - } } done: -- cgit v0.12 From 26733057747b9f7db38abe7f8c3a75132a8881f6 Mon Sep 17 00:00:00 2001 From: culler Date: Fri, 8 Nov 2019 06:51:55 +0000 Subject: Reimplement TkWmStackorderToplevel to make it straightforward and shorter and behave the same on macOS as on unix and Windows. --- macosx/tkMacOSXWm.c | 56 +++++++++++++---------------------------------------- tests/wm.test | 14 ++------------ 2 files changed, 15 insertions(+), 55 deletions(-) diff --git a/macosx/tkMacOSXWm.c b/macosx/tkMacOSXWm.c index dda6c19..dfe3a26 100644 --- a/macosx/tkMacOSXWm.c +++ b/macosx/tkMacOSXWm.c @@ -6621,7 +6621,7 @@ WmStackorderToplevelWrapperMap( Tcl_HashEntry *hPtr; int newEntry; - if (Tk_IsMapped(winPtr) && Tk_IsTopLevel(winPtr) + if (Tk_IsMapped(winPtr) && Tk_IsTopLevel(winPtr) && !Tk_IsEmbedded(winPtr) && (winPtr->display == display)) { hPtr = Tcl_CreateHashEntry(table, (char*) TkMacOSXDrawableWindow(winPtr->window), &newEntry); @@ -6642,8 +6642,8 @@ WmStackorderToplevelWrapperMap( * This procedure returns the stack order of toplevel windows. * * Results: - * An array of pointers to tk window objects in stacking order or else - * NULL if there was an error. + * A NULL terminated array of pointers to tk window objects in stacking + * order or else NULL if there was an error. * * Side effects: * None. @@ -6658,52 +6658,22 @@ TkWmStackorderToplevel( TkWindow *childWinPtr, **windows, **windowPtr; Tcl_HashTable table; Tcl_HashEntry *hPtr; - Tcl_HashSearch search; - - /* - * Map mac windows to a TkWindow of the wrapped toplevel. - */ + NSArray *macWindows = [NSApp orderedWindows]; + NSArray* backToFront = [[macWindows reverseObjectEnumerator] allObjects]; + NSInteger windowCount = [macWindows count]; + windows = windowPtr = ckalloc((windowCount + 1) * sizeof(TkWindow *)); Tcl_InitHashTable(&table, TCL_ONE_WORD_KEYS); WmStackorderToplevelWrapperMap(parentPtr, parentPtr->display, &table); - windows = ckalloc((table.numEntries+1) * sizeof(TkWindow *)); - - /* - * Special cases: If zero or one toplevels were mapped there is no need to - * enumerate Windows. - */ - - switch (table.numEntries) { - case 0: - windows[0] = NULL; - goto done; - case 1: - hPtr = Tcl_FirstHashEntry(&table, &search); - windows[0] = Tcl_GetHashValue(hPtr); - windows[1] = NULL; - goto done; - } - - NSArray *macWindows = [NSApp orderedWindows]; - NSInteger windowCount = [macWindows count]; - - if (!windowCount) { - ckfree(windows); - windows = NULL; - } else { - windowPtr = windows + table.numEntries; - *windowPtr-- = NULL; - for (NSWindow *w in macWindows) { - hPtr = Tcl_FindHashEntry(&table, (char*) w); - if (hPtr != NULL) { - childWinPtr = Tcl_GetHashValue(hPtr); - *windowPtr-- = childWinPtr; - } + for (NSWindow *w in backToFront) { + hPtr = Tcl_FindHashEntry(&table, (char*) w); + if (hPtr != NULL) { + childWinPtr = Tcl_GetHashValue(hPtr); + *windowPtr++ = childWinPtr; } } - - done: + *windowPtr = NULL; Tcl_DeleteHashTable(&table); return windows; } diff --git a/tests/wm.test b/tests/wm.test index c2bc385..1dbc372 100644 --- a/tests/wm.test +++ b/tests/wm.test @@ -1553,8 +1553,8 @@ test wm-stackorder-5.3 {An overrideredirect window\ destroy .t } -result 1 -test wm-stackorder-6.1 {An embedded toplevel does not\ - appear in the stacking order on unix or win} -constraints notAqua -body { +test wm-stackorder-6.1 {An embedded toplevel does not appear in the \ + stacking order} -body { toplevel .real -container 1 toplevel .embd -bg blue -use [winfo id .real] update @@ -1562,16 +1562,6 @@ test wm-stackorder-6.1 {An embedded toplevel does not\ } -cleanup { deleteWindows } -result {. .real} -test wm-stackorder-6.1.1 {An embedded toplevel does\ - appear in the stacking order on macOS} -constraints aqua -body { - toplevel .real -container 1 - toplevel .embd -bg blue -use [winfo id .real] - update - wm stackorder . -} -cleanup { - deleteWindows -} -result {. .embd} - stdWindow -- cgit v0.12 From bcb9c70e081e441f93428e84241226919588dc13 Mon Sep 17 00:00:00 2001 From: fvogel Date: Sat, 9 Nov 2019 10:18:10 +0000 Subject: Propagate previous Mac fix to the Windows platform --- win/tkWinWm.c | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/win/tkWinWm.c b/win/tkWinWm.c index 117b539..7df5dcf 100644 --- a/win/tkWinWm.c +++ b/win/tkWinWm.c @@ -5195,18 +5195,18 @@ WmStackorderCmd( if (objc == 3) { windows = TkWmStackorderToplevel(winPtr); - if (windows == NULL) { - Tcl_Panic("TkWmStackorderToplevel failed"); - } - - resultObj = Tcl_NewObj(); - for (windowPtr = windows; *windowPtr ; windowPtr++) { - Tcl_ListObjAppendElement(NULL, resultObj, - TkNewWindowObj((Tk_Window) *windowPtr)); + if (windows != NULL) { + resultObj = Tcl_NewObj(); + for (windowPtr = windows; *windowPtr ; windowPtr++) { + Tcl_ListObjAppendElement(NULL, resultObj, + TkNewWindowObj((Tk_Window) *windowPtr)); + } + Tcl_SetObjResult(interp, resultObj); + ckfree(windows); + return TCL_OK; + } else { + return TCL_ERROR; } - Tcl_SetObjResult(interp, resultObj); - ckfree(windows); - return TCL_OK; } else { TkWindow *winPtr2, **winPtr2Ptr = &winPtr2; int index1 = -1, index2 = -1, result; @@ -6812,8 +6812,6 @@ TkWmStackorderToplevel( (LPARAM) &pair) == 0) { ckfree(windows); windows = NULL; - } else if (pair.windowPtr != (windows-1)) { - Tcl_Panic("num matched toplevel windows does not equal num children"); } done: -- cgit v0.12 From 62caa9e27341a3355e8067480fd2a0fe5d942281 Mon Sep 17 00:00:00 2001 From: culler Date: Sat, 9 Nov 2019 13:12:24 +0000 Subject: make TkWmStackorderToplevel return NULL if ckalloc fails. --- macosx/tkMacOSXWm.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/macosx/tkMacOSXWm.c b/macosx/tkMacOSXWm.c index dfe3a26..53bb400 100644 --- a/macosx/tkMacOSXWm.c +++ b/macosx/tkMacOSXWm.c @@ -6663,18 +6663,19 @@ TkWmStackorderToplevel( NSInteger windowCount = [macWindows count]; windows = windowPtr = ckalloc((windowCount + 1) * sizeof(TkWindow *)); - Tcl_InitHashTable(&table, TCL_ONE_WORD_KEYS); - WmStackorderToplevelWrapperMap(parentPtr, parentPtr->display, &table); - - for (NSWindow *w in backToFront) { - hPtr = Tcl_FindHashEntry(&table, (char*) w); - if (hPtr != NULL) { - childWinPtr = Tcl_GetHashValue(hPtr); - *windowPtr++ = childWinPtr; + if (windows != NULL) { + Tcl_InitHashTable(&table, TCL_ONE_WORD_KEYS); + WmStackorderToplevelWrapperMap(parentPtr, parentPtr->display, &table); + for (NSWindow *w in backToFront) { + hPtr = Tcl_FindHashEntry(&table, (char*) w); + if (hPtr != NULL) { + childWinPtr = Tcl_GetHashValue(hPtr); + *windowPtr++ = childWinPtr; + } } + *windowPtr = NULL; + Tcl_DeleteHashTable(&table); } - *windowPtr = NULL; - Tcl_DeleteHashTable(&table); return windows; } -- cgit v0.12 From 7f952ce8386b3060408ee6f672760bc55606080d Mon Sep 17 00:00:00 2001 From: culler Date: Sun, 10 Nov 2019 18:35:46 +0000 Subject: On unix, make the wm stackorder command return an error if TkWmStackorderToplevel fails. --- unix/tkUnixWm.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/unix/tkUnixWm.c b/unix/tkUnixWm.c index bc7f1cb..0ebd4ac 100644 --- a/unix/tkUnixWm.c +++ b/unix/tkUnixWm.c @@ -3268,6 +3268,8 @@ WmStackorderCmd( ckfree(windows); Tcl_SetObjResult(interp, resultObj); return TCL_OK; + } else { + return TCL_ERROR; } } else { Tk_Window relWin; @@ -6432,6 +6434,9 @@ TkWmStackorderToplevel( TkWmStackorderToplevelWrapperMap(parentPtr, parentPtr->display, &table); window_ptr = windows = ckalloc((table.numEntries+1) * sizeof(TkWindow *)); + if (windows == NULL) { + return NULL; + } /* * Special cases: If zero or one toplevels were mapped there is no need to -- cgit v0.12