summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorculler <culler>2019-11-17 16:53:11 (GMT)
committerculler <culler>2019-11-17 16:53:11 (GMT)
commit5fa1f5ca17abac3ec8d2d646fbf138502a0f4a59 (patch)
tree64e243c4c3c32c5add2d7c572c79957f1d63f6ad
parent321eba4fe5834e3df10efbbd71255704a011d2d8 (diff)
parent1dcfa065cbd9c94750fabda9313008e76e4d9c87 (diff)
downloadtk-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.c77
-rw-r--r--tests/wm.test14
-rw-r--r--unix/tkUnixWm.c5
-rw-r--r--win/tkWinWm.c24
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: