summaryrefslogtreecommitdiffstats
path: root/unix/tkUnixWm.c
diff options
context:
space:
mode:
authormdejong <mdejong>2001-12-04 03:07:43 (GMT)
committermdejong <mdejong>2001-12-04 03:07:43 (GMT)
commit89a2a69bd2e0485a1c668bce78c42f6ee838541a (patch)
treec10f74bc4d524b0bf65af204010f7cce724b7c23 /unix/tkUnixWm.c
parentd70e5cf9d2a8a440b0916ddb8170052056796356 (diff)
downloadtk-89a2a69bd2e0485a1c668bce78c42f6ee838541a.zip
tk-89a2a69bd2e0485a1c668bce78c42f6ee838541a.tar.gz
tk-89a2a69bd2e0485a1c668bce78c42f6ee838541a.tar.bz2
Add TK patch 481148 to implement TIP 74, the
wm stackorder command. * doc/winfo.n: Update documentation for the winfo children command to indicate that top-level windows are not returned in stacking order. * doc/wm.n: Add documentation for wm stackorder. * generic/tkInt.decls (TkWmStackorderToplevel): Add decl for new function. * generic/tkIntDecls.h: Regen. * generic/tkStubInit.c: Regen. * tests/unixWm.test: Add stackorder command to test for wm command usage message. * tests/wm.test: Add new set of tests for generic window manager methods. * unix/tkUnixWm.c (Tk_WmCmd, TkWmStackorderToplevelWrapperMap, TkWmStackorderToplevel): Add unix implementation of new wm stackorder command. * win/tkWinWm.c (Tk_WmCmd, TkWmStackorderToplevelEnumProc, TkWmStackorderToplevelWrapperMap, TkWmStackorderToplevel): Add windows implementation of new wm stackorder command.
Diffstat (limited to 'unix/tkUnixWm.c')
-rw-r--r--unix/tkUnixWm.c232
1 files changed, 228 insertions, 4 deletions
diff --git a/unix/tkUnixWm.c b/unix/tkUnixWm.c
index 9fff250..f0ee0b9 100644
--- a/unix/tkUnixWm.c
+++ b/unix/tkUnixWm.c
@@ -12,7 +12,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tkUnixWm.c,v 1.9 2001/08/28 19:41:55 hobbs Exp $
+ * RCS: @(#) $Id: tkUnixWm.c,v 1.10 2001/12/04 03:07:43 mdejong Exp $
*/
#include "tkPort.h"
@@ -323,6 +323,9 @@ static int ParseGeometry _ANSI_ARGS_((Tcl_Interp *interp,
char *string, TkWindow *winPtr));
static void ReparentEvent _ANSI_ARGS_((WmInfo *wmPtr,
XReparentEvent *eventPtr));
+static void TkWmStackorderToplevelWrapperMap _ANSI_ARGS_((
+ TkWindow *winPtr,
+ Tcl_HashTable *reparentTable));
static void TopLevelReqProc _ANSI_ARGS_((ClientData dummy,
Tk_Window tkwin));
static void UpdateCommand _ANSI_ARGS_((TkWindow *winPtr));
@@ -818,7 +821,7 @@ Tk_WmCmd(clientData, interp, argc, argv)
if (winPtr == NULL) {
return TCL_ERROR;
}
- if (!(winPtr->flags & TK_TOP_LEVEL)) {
+ if (!Tk_IsTopLevel(winPtr)) {
Tcl_AppendResult(interp, "window \"", winPtr->pathName,
"\" isn't a top-level window", (char *) NULL);
return TCL_ERROR;
@@ -1748,6 +1751,99 @@ Tk_WmCmd(clientData, interp, argc, argv)
}
wmPtr->flags |= WM_UPDATE_SIZE_HINTS;
goto updateGeom;
+ } else if ((c == 's') && (strncmp(argv[1], "stackorder", length) == 0)
+ && (length >= 2)) {
+ TkWindow **windows, **window_ptr;
+
+ if ((argc != 3) && (argc != 5)) {
+ Tcl_AppendResult(interp, "wrong # arguments: must be \"",
+ argv[0],
+ " stackorder window ?isabove|isbelow? ?window?\"",
+ (char *) NULL);
+ return TCL_ERROR;
+ }
+
+ if (argc == 3) {
+ windows = TkWmStackorderToplevel(winPtr);
+ if (windows == NULL) {
+ panic("TkWmStackorderToplevel failed");
+ } else {
+ for (window_ptr = windows; *window_ptr ; window_ptr++) {
+ Tcl_AppendElement(interp, (*window_ptr)->pathName);
+ }
+ ckfree((char *) windows);
+ return TCL_OK;
+ }
+ } else {
+ TkWindow *winPtr2;
+ int index1=-1, index2=-1, result;
+
+ winPtr2 = (TkWindow *) Tk_NameToWindow(interp, argv[4], tkwin);
+ if (winPtr2 == NULL) {
+ return TCL_ERROR;
+ }
+
+ if (!Tk_IsTopLevel(winPtr2)) {
+ Tcl_AppendResult(interp, "window \"", winPtr2->pathName,
+ "\" isn't a top-level window", (char *) NULL);
+ return TCL_ERROR;
+ }
+
+ if (!Tk_IsMapped(winPtr)) {
+ Tcl_AppendResult(interp, "window \"", winPtr->pathName,
+ "\" isn't mapped", (char *) NULL);
+ return TCL_ERROR;
+ }
+
+ if (!Tk_IsMapped(winPtr2)) {
+ Tcl_AppendResult(interp, "window \"", winPtr2->pathName,
+ "\" isn't mapped", (char *) NULL);
+ return TCL_ERROR;
+ }
+
+ /*
+ * Lookup stacking order of all toplevels that are children
+ * of "." and find the position of winPtr and winPtr2
+ * in the stacking order.
+ */
+
+ windows = TkWmStackorderToplevel(winPtr->mainPtr->winPtr);
+
+ if (windows == NULL) {
+ Tcl_AppendResult(interp, "TkWmStackorderToplevel failed",
+ (char *) NULL);
+ return TCL_ERROR;
+ } else {
+ for (window_ptr = windows; *window_ptr ; window_ptr++) {
+ if (*window_ptr == winPtr)
+ index1 = (window_ptr - windows);
+ if (*window_ptr == winPtr2)
+ index2 = (window_ptr - windows);
+ }
+ if (index1 == -1)
+ panic("winPtr window not found");
+ if (index2 == -1)
+ panic("winPtr2 window not found");
+
+ ckfree((char *) windows);
+ }
+
+ c = argv[3][0];
+ length = strlen(argv[3]);
+ if ((length > 2) && (c == 'i')
+ && (strncmp(argv[3], "isabove", length) == 0)) {
+ result = index1 > index2;
+ } else if ((length > 2) && (c == 'i')
+ && (strncmp(argv[3], "isbelow", length) == 0)) {
+ result = index1 < index2;
+ } else {
+ Tcl_AppendResult(interp, "bad argument \"", argv[3],
+ "\": must be isabove or isbelow", (char *) NULL);
+ return TCL_ERROR;
+ }
+ Tcl_SetIntObj(Tcl_GetObjResult(interp), result);
+ return TCL_OK;
+ }
} else if ((c == 's') && (strncmp(argv[1], "state", length) == 0)
&& (length >= 2)) {
if ((argc < 3) || (argc > 4)) {
@@ -1954,8 +2050,8 @@ Tk_WmCmd(clientData, interp, argc, argv)
"focusmodel, frame, geometry, grid, group, iconbitmap, ",
"iconify, iconmask, iconname, iconposition, ",
"iconwindow, maxsize, minsize, overrideredirect, ",
- "positionfrom, protocol, resizable, sizefrom, state, title, ",
- "transient, or withdraw",
+ "positionfrom, protocol, resizable, sizefrom, stackorder, ",
+ "state, title, transient, or withdraw",
(char *) NULL);
return TCL_ERROR;
}
@@ -4073,6 +4169,134 @@ TkWmProtocolEventProc(winPtr, eventPtr)
/*
*----------------------------------------------------------------------
*
+ * TkWmStackorderToplevelWrapperMap --
+ *
+ * This procedure will create a table that maps the reparent wrapper
+ * X id for a toplevel to the TkWindow structure that is wraps.
+ * Tk keeps track of a mapping from the window X id to the TkWindow
+ * structure but that does us no good here since we only get the X
+ * id of the wrapper window. Only those toplevel windows that are
+ * mapped have a position in the stacking order.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Adds entries to the passed hashtable.
+ *
+ *----------------------------------------------------------------------
+ */
+void
+TkWmStackorderToplevelWrapperMap(winPtr, table)
+ TkWindow *winPtr; /* TkWindow to recurse on */
+ Tcl_HashTable *table; /* Maps X id to TkWindow */
+{
+ TkWindow *childPtr;
+ Tcl_HashEntry *hPtr;
+ Window wrapper;
+ int newEntry;
+
+ if (Tk_IsMapped(winPtr) && Tk_IsTopLevel(winPtr)) {
+ wrapper = (winPtr->wmInfoPtr->reparent != None)
+ ? winPtr->wmInfoPtr->reparent
+ : winPtr->wmInfoPtr->wrapperPtr->window;
+
+ hPtr = Tcl_CreateHashEntry(table,
+ (char *) wrapper, &newEntry);
+ Tcl_SetHashValue(hPtr, winPtr);
+ }
+
+ for (childPtr = winPtr->childList; childPtr != NULL;
+ childPtr = childPtr->nextPtr) {
+ TkWmStackorderToplevelWrapperMap(childPtr, table);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkWmStackorderToplevel --
+ *
+ * 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.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+TkWindow **
+TkWmStackorderToplevel(parentPtr)
+ TkWindow *parentPtr; /* Parent toplevel window. */
+{
+ Window dummy1, dummy2, vRoot;
+ Window *children;
+ unsigned int numChildren, i;
+ TkWindow *childWinPtr, **windows, **window_ptr;
+ Tcl_HashTable table;
+ Tcl_HashEntry *hPtr;
+ Tcl_HashSearch search;
+
+ /*
+ * Map X Window ids to a TkWindow of the wrapped toplevel.
+ */
+
+ Tcl_InitHashTable(&table, TCL_ONE_WORD_KEYS);
+ TkWmStackorderToplevelWrapperMap(parentPtr, &table);
+
+ window_ptr = windows = (TkWindow **) ckalloc((table.numEntries+1)
+ * sizeof(TkWindow *));
+
+ /*
+ * Special cases: If zero or one toplevels were mapped
+ * there is no need to call XQueryTree.
+ */
+
+ switch (table.numEntries) {
+ case 0:
+ windows[0] = NULL;
+ goto done;
+ case 1:
+ hPtr = Tcl_FirstHashEntry(&table, &search);
+ windows[0] = (TkWindow *) Tcl_GetHashValue(hPtr);
+ windows[1] = NULL;
+ goto done;
+ }
+
+ vRoot = parentPtr->wmInfoPtr->vRoot;
+ if (vRoot == None) {
+ vRoot = RootWindowOfScreen(Tk_Screen((Tk_Window) parentPtr));
+ }
+
+ if (XQueryTree(parentPtr->display, vRoot, &dummy1, &dummy2,
+ &children, &numChildren) == 0) {
+ ckfree((char *) windows);
+ windows = NULL;
+ } else {
+ for (i = 0; i < numChildren; i++) {
+ hPtr = Tcl_FindHashEntry(&table, (char *) children[i]);
+ if (hPtr != NULL) {
+ childWinPtr = (TkWindow *) Tcl_GetHashValue(hPtr);
+ *window_ptr++ = childWinPtr;
+ }
+ }
+ if ((window_ptr - windows) != table.numEntries)
+ panic("num matched toplevel windows does not equal num children");
+ *window_ptr = NULL;
+ }
+
+ done:
+ Tcl_DeleteHashTable(&table);
+ return windows;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
* TkWmRestackToplevel --
*
* This procedure restacks a top-level window.