diff options
author | culler <culler> | 2019-11-17 16:53:11 (GMT) |
---|---|---|
committer | culler <culler> | 2019-11-17 16:53:11 (GMT) |
commit | 5fa1f5ca17abac3ec8d2d646fbf138502a0f4a59 (patch) | |
tree | 64e243c4c3c32c5add2d7c572c79957f1d63f6ad | |
parent | 321eba4fe5834e3df10efbbd71255704a011d2d8 (diff) | |
parent | 1dcfa065cbd9c94750fabda9313008e76e4d9c87 (diff) | |
download | tk-5fa1f5ca17abac3ec8d2d646fbf138502a0f4a59.zip tk-5fa1f5ca17abac3ec8d2d646fbf138502a0f4a59.tar.gz tk-5fa1f5ca17abac3ec8d2d646fbf138502a0f4a59.tar.bz2 |
Fix [c4abd2b0f3]: rework stackorder command on all platforms, and prevent panics on macOS.
-rw-r--r-- | macosx/tkMacOSXWm.c | 77 | ||||
-rw-r--r-- | tests/wm.test | 14 | ||||
-rw-r--r-- | unix/tkUnixWm.c | 5 | ||||
-rw-r--r-- | win/tkWinWm.c | 24 |
4 files changed, 40 insertions, 80 deletions
diff --git a/macosx/tkMacOSXWm.c b/macosx/tkMacOSXWm.c index 70e9cd9..6cf1b53 100644 --- a/macosx/tkMacOSXWm.c +++ b/macosx/tkMacOSXWm.c @@ -3311,18 +3311,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; @@ -6623,7 +6623,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); @@ -6644,8 +6644,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. @@ -6660,57 +6660,24 @@ TkWmStackorderToplevel( TkWindow *childWinPtr, **windows, **windowPtr; Tcl_HashTable table; Tcl_HashEntry *hPtr; - Tcl_HashSearch search; - - /* - * Map mac windows to a TkWindow of the wrapped toplevel. - */ - - 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]; + NSArray* backToFront = [[macWindows reverseObjectEnumerator] allObjects]; NSInteger windowCount = [macWindows count]; - if (!windowCount) { - ckfree(windows); - windows = NULL; - } else { - windowPtr = windows + table.numEntries; - *windowPtr-- = NULL; - for (NSWindow *w in macWindows) { + windows = windowPtr = ckalloc((windowCount + 1) * sizeof(TkWindow *)); + 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++ = childWinPtr; } } - if (windowPtr != windows-1) { - Tcl_Panic("num matched toplevel windows does not equal num " - "children"); - } + *windowPtr = NULL; + Tcl_DeleteHashTable(&table); } - - done: - Tcl_DeleteHashTable(&table); return windows; } diff --git a/tests/wm.test b/tests/wm.test index df8d325..7ba02e3 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 diff --git a/unix/tkUnixWm.c b/unix/tkUnixWm.c index f9cf4e7..893dfd7 100644 --- a/unix/tkUnixWm.c +++ b/unix/tkUnixWm.c @@ -3265,6 +3265,8 @@ WmStackorderCmd( ckfree(windows); Tcl_SetObjResult(interp, resultObj); return TCL_OK; + } else { + return TCL_ERROR; } } else { Tk_Window relWin; @@ -6428,6 +6430,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 diff --git a/win/tkWinWm.c b/win/tkWinWm.c index d273b4c..ba10c63 100644 --- a/win/tkWinWm.c +++ b/win/tkWinWm.c @@ -5189,18 +5189,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; @@ -6807,8 +6807,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: |