summaryrefslogtreecommitdiff
path: root/tk/unix/tkUnixWm.c
diff options
context:
space:
mode:
Diffstat (limited to 'tk/unix/tkUnixWm.c')
-rw-r--r--tk/unix/tkUnixWm.c3856
1 files changed, 2576 insertions, 1280 deletions
diff --git a/tk/unix/tkUnixWm.c b/tk/unix/tkUnixWm.c
index 98e4861f044..0d21b1d44a0 100644
--- a/tk/unix/tkUnixWm.c
+++ b/tk/unix/tkUnixWm.c
@@ -1,4 +1,4 @@
-/*
+/*
* tkUnixWm.c --
*
* This module takes care of the interactions between a Tk-based
@@ -35,7 +35,7 @@ typedef struct ProtocolHandler {
* end of list. */
Tcl_Interp *interp; /* Interpreter in which to invoke command. */
char command[4]; /* Tcl command to invoke when a client
- * message for this protocol arrives.
+ * message for this protocol arrives.
* The actual size of the structure varies
* to accommodate the needs of the actual
* command. THIS MUST BE THE LAST FIELD OF
@@ -62,19 +62,14 @@ typedef struct TkWmInfo {
char *title; /* Title to display in window caption. If
* NULL, use name of widget. Malloced. */
char *iconName; /* Name to display in icon. Malloced. */
- Window master; /* Master window for TRANSIENT_FOR property,
- * or None. */
XWMHints hints; /* Various pieces of information for
* window manager. */
char *leaderName; /* Path name of leader of window group
* (corresponds to hints.window_group).
* Malloc-ed. Note: this field doesn't
* get updated if leader is destroyed. */
- char *masterWindowName; /* Path name of window specified as master
- * in "wm transient" command, or NULL.
- * Malloc-ed. Note: this field doesn't
- * get updated if masterWindowName is
- * destroyed. */
+ TkWindow *masterPtr; /* Master window for TRANSIENT_FOR property,
+ * or NULL. */
Tk_Window icon; /* Window to use as icon for this window,
* or NULL. */
Tk_Window iconFor; /* Window for which this window is icon, or
@@ -196,12 +191,13 @@ typedef struct TkWmInfo {
ProtocolHandler *protPtr; /* First in list of protocol handlers for
* this window (NULL means none). */
int cmdArgc; /* Number of elements in cmdArgv below. */
- char **cmdArgv; /* Array of strings to store in the
+ CONST char **cmdArgv; /* Array of strings to store in the
* WM_COMMAND property. NULL means nothing
* available. */
char *clientMachine; /* String to store in WM_CLIENT_MACHINE
* property, or NULL. */
int flags; /* Miscellaneous flags, defined below. */
+ int numTransients; /* number of transients on this window */
struct TkWmInfo *nextPtr; /* Next in list of all top-level windows. */
} WmInfo;
@@ -248,6 +244,9 @@ typedef struct TkWmInfo {
* allow the user to change the height of the
* window (controlled by "wm resizable"
* command).
+ * WM_TRANSIENT_WITHDRAWN - non-zero means that this is a transient window
+ * that has explicitly been withdrawn. It should
+ * not mirror state changes in the master.
*/
#define WM_NEVER_MAPPED 1
@@ -263,10 +262,11 @@ typedef struct TkWmInfo {
#define WM_ADDED_TOPLEVEL_COLORMAP 0x800
#define WM_WIDTH_NOT_RESIZABLE 0x1000
#define WM_HEIGHT_NOT_RESIZABLE 0x2000
+#define WM_TRANSIENT_WITHDRAWN 0x4000
/*
* This module keeps a list of all top-level windows, primarily to
- * simplify the job of Tk_CoordsToWindow. The list is called
+ * simplify the job of Tk_CoordsToWindow. The list is called
* firstWmPtr and is stored in the TkDisplay structure.
*/
@@ -300,7 +300,7 @@ static Tk_GeomMgr menubarMgrType = {
typedef struct WaitRestrictInfo {
Display *display; /* Window belongs to this display. */
- Window window; /* We're waiting for events on this window. */
+ WmInfo *wmInfoPtr;
int type; /* We only care about this type of event. */
XEvent *eventPtr; /* Where to store the event when it's found. */
int foundEvent; /* Non-zero means that an event of the
@@ -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));
@@ -335,7 +338,7 @@ static void UpdateWmProtocols _ANSI_ARGS_((WmInfo *wmPtr));
static void WaitForConfigureNotify _ANSI_ARGS_((TkWindow *winPtr,
unsigned long serial));
static int WaitForEvent _ANSI_ARGS_((Display *display,
- Window window, int type, XEvent *eventPtr));
+ WmInfo *wmInfoPtr, int type, XEvent *eventPtr));
static void WaitForMapNotify _ANSI_ARGS_((TkWindow *winPtr,
int mapped));
static Tk_RestrictAction
@@ -343,6 +346,157 @@ static Tk_RestrictAction
XEvent *eventPtr));
static void WrapperEventProc _ANSI_ARGS_((ClientData clientData,
XEvent *eventPtr));
+static void WmWaitMapProc _ANSI_ARGS_((
+ ClientData clientData, XEvent *eventPtr));
+
+static int WmAspectCmd _ANSI_ARGS_((Tk_Window tkwin,
+ TkWindow *winPtr, Tcl_Interp *interp, int objc,
+ Tcl_Obj *CONST objv[]));
+static int WmAttributesCmd _ANSI_ARGS_((Tk_Window tkwin,
+ TkWindow *winPtr, Tcl_Interp *interp, int objc,
+ Tcl_Obj *CONST objv[]));
+static int WmClientCmd _ANSI_ARGS_((Tk_Window tkwin,
+ TkWindow *winPtr, Tcl_Interp *interp, int objc,
+ Tcl_Obj *CONST objv[]));
+static int WmColormapwindowsCmd _ANSI_ARGS_((Tk_Window tkwin,
+ TkWindow *winPtr, Tcl_Interp *interp, int objc,
+ Tcl_Obj *CONST objv[]));
+static int WmCommandCmd _ANSI_ARGS_((Tk_Window tkwin,
+ TkWindow *winPtr, Tcl_Interp *interp, int objc,
+ Tcl_Obj *CONST objv[]));
+static int WmDeiconifyCmd _ANSI_ARGS_((Tk_Window tkwin,
+ TkWindow *winPtr, Tcl_Interp *interp, int objc,
+ Tcl_Obj *CONST objv[]));
+static int WmFocusmodelCmd _ANSI_ARGS_((Tk_Window tkwin,
+ TkWindow *winPtr, Tcl_Interp *interp, int objc,
+ Tcl_Obj *CONST objv[]));
+static int WmFrameCmd _ANSI_ARGS_((Tk_Window tkwin,
+ TkWindow *winPtr, Tcl_Interp *interp, int objc,
+ Tcl_Obj *CONST objv[]));
+static int WmGeometryCmd _ANSI_ARGS_((Tk_Window tkwin,
+ TkWindow *winPtr, Tcl_Interp *interp, int objc,
+ Tcl_Obj *CONST objv[]));
+static int WmGridCmd _ANSI_ARGS_((Tk_Window tkwin,
+ TkWindow *winPtr, Tcl_Interp *interp, int objc,
+ Tcl_Obj *CONST objv[]));
+static int WmGroupCmd _ANSI_ARGS_((Tk_Window tkwin,
+ TkWindow *winPtr, Tcl_Interp *interp, int objc,
+ Tcl_Obj *CONST objv[]));
+static int WmIconbitmapCmd _ANSI_ARGS_((Tk_Window tkwin,
+ TkWindow *winPtr, Tcl_Interp *interp, int objc,
+ Tcl_Obj *CONST objv[]));
+static int WmIconifyCmd _ANSI_ARGS_((Tk_Window tkwin,
+ TkWindow *winPtr, Tcl_Interp *interp, int objc,
+ Tcl_Obj *CONST objv[]));
+static int WmIconmaskCmd _ANSI_ARGS_((Tk_Window tkwin,
+ TkWindow *winPtr, Tcl_Interp *interp, int objc,
+ Tcl_Obj *CONST objv[]));
+static int WmIconnameCmd _ANSI_ARGS_((Tk_Window tkwin,
+ TkWindow *winPtr, Tcl_Interp *interp, int objc,
+ Tcl_Obj *CONST objv[]));
+static int WmIconpositionCmd _ANSI_ARGS_((Tk_Window tkwin,
+ TkWindow *winPtr, Tcl_Interp *interp, int objc,
+ Tcl_Obj *CONST objv[]));
+static int WmIconwindowCmd _ANSI_ARGS_((Tk_Window tkwin,
+ TkWindow *winPtr, Tcl_Interp *interp, int objc,
+ Tcl_Obj *CONST objv[]));
+static int WmMaxsizeCmd _ANSI_ARGS_((Tk_Window tkwin,
+ TkWindow *winPtr, Tcl_Interp *interp, int objc,
+ Tcl_Obj *CONST objv[]));
+static int WmMinsizeCmd _ANSI_ARGS_((Tk_Window tkwin,
+ TkWindow *winPtr, Tcl_Interp *interp, int objc,
+ Tcl_Obj *CONST objv[]));
+static int WmOverrideredirectCmd _ANSI_ARGS_((Tk_Window tkwin,
+ TkWindow *winPtr, Tcl_Interp *interp, int objc,
+ Tcl_Obj *CONST objv[]));
+static int WmPositionfromCmd _ANSI_ARGS_((Tk_Window tkwin,
+ TkWindow *winPtr, Tcl_Interp *interp, int objc,
+ Tcl_Obj *CONST objv[]));
+static int WmProtocolCmd _ANSI_ARGS_((Tk_Window tkwin,
+ TkWindow *winPtr, Tcl_Interp *interp, int objc,
+ Tcl_Obj *CONST objv[]));
+static int WmResizableCmd _ANSI_ARGS_((Tk_Window tkwin,
+ TkWindow *winPtr, Tcl_Interp *interp, int objc,
+ Tcl_Obj *CONST objv[]));
+static int WmSizefromCmd _ANSI_ARGS_((Tk_Window tkwin,
+ TkWindow *winPtr, Tcl_Interp *interp, int objc,
+ Tcl_Obj *CONST objv[]));
+static int WmStackorderCmd _ANSI_ARGS_((Tk_Window tkwin,
+ TkWindow *winPtr, Tcl_Interp *interp, int objc,
+ Tcl_Obj *CONST objv[]));
+static int WmStateCmd _ANSI_ARGS_((Tk_Window tkwin,
+ TkWindow *winPtr, Tcl_Interp *interp, int objc,
+ Tcl_Obj *CONST objv[]));
+static int WmTitleCmd _ANSI_ARGS_((Tk_Window tkwin,
+ TkWindow *winPtr, Tcl_Interp *interp, int objc,
+ Tcl_Obj *CONST objv[]));
+static int WmTransientCmd _ANSI_ARGS_((Tk_Window tkwin,
+ TkWindow *winPtr, Tcl_Interp *interp, int objc,
+ Tcl_Obj *CONST objv[]));
+static int WmWithdrawCmd _ANSI_ARGS_((Tk_Window tkwin,
+ TkWindow *winPtr, Tcl_Interp *interp, int objc,
+ Tcl_Obj *CONST objv[]));
+static void WmUpdateGeom _ANSI_ARGS_((WmInfo *wmPtr,
+ TkWindow *winPtr));
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TkWmCleanup --
+ *
+ * This procedure is invoked to cleanup remaining wm resources
+ * associated with a display.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * All WmInfo structure resources are freed and invalidated.
+ *
+ *--------------------------------------------------------------
+ */
+
+void TkWmCleanup(dispPtr)
+ TkDisplay *dispPtr;
+{
+ WmInfo *wmPtr, *nextPtr;
+ for (wmPtr = dispPtr->firstWmPtr; wmPtr != NULL; wmPtr = nextPtr) {
+ /*
+ * We can't assume we have access to winPtr's anymore, so some
+ * cleanup requiring winPtr data is avoided.
+ */
+ nextPtr = wmPtr->nextPtr;
+ if (wmPtr->title != NULL) {
+ ckfree(wmPtr->title);
+ }
+ if (wmPtr->iconName != NULL) {
+ ckfree(wmPtr->iconName);
+ }
+ if (wmPtr->leaderName != NULL) {
+ ckfree(wmPtr->leaderName);
+ }
+ if (wmPtr->menubar != NULL) {
+ Tk_DestroyWindow(wmPtr->menubar);
+ }
+ if (wmPtr->wrapperPtr != NULL) {
+ Tk_DestroyWindow((Tk_Window) wmPtr->wrapperPtr);
+ }
+ while (wmPtr->protPtr != NULL) {
+ ProtocolHandler *protPtr;
+
+ protPtr = wmPtr->protPtr;
+ wmPtr->protPtr = protPtr->nextPtr;
+ Tcl_EventuallyFree((ClientData) protPtr, TCL_DYNAMIC);
+ }
+ if (wmPtr->cmdArgv != NULL) {
+ ckfree((char *) wmPtr->cmdArgv);
+ }
+ if (wmPtr->clientMachine != NULL) {
+ ckfree((char *) wmPtr->clientMachine);
+ }
+ ckfree((char *) wmPtr);
+ }
+}
/*
*--------------------------------------------------------------
@@ -370,11 +524,11 @@ TkWmNewWindow(winPtr)
TkDisplay *dispPtr = winPtr->dispPtr;
wmPtr = (WmInfo *) ckalloc(sizeof(WmInfo));
+ memset(wmPtr, 0, sizeof(WmInfo));
wmPtr->winPtr = winPtr;
wmPtr->reparent = None;
- wmPtr->title = NULL;
- wmPtr->iconName = NULL;
- wmPtr->master = None;
+ wmPtr->masterPtr = NULL;
+ wmPtr->numTransients = 0;
wmPtr->hints.flags = InputHint | StateHint;
wmPtr->hints.input = True;
wmPtr->hints.initial_state = NormalState;
@@ -383,15 +537,6 @@ TkWmNewWindow(winPtr)
wmPtr->hints.icon_x = wmPtr->hints.icon_y = 0;
wmPtr->hints.icon_mask = None;
wmPtr->hints.window_group = None;
- wmPtr->leaderName = NULL;
- wmPtr->masterWindowName = NULL;
- wmPtr->icon = NULL;
- wmPtr->iconFor = NULL;
- wmPtr->withdrawn = 0;
- wmPtr->wrapperPtr = NULL;
- wmPtr->menubar = NULL;
- wmPtr->menuHeight = 0;
- wmPtr->sizeHintsFlags = 0;
wmPtr->minWidth = wmPtr->minHeight = 1;
/*
@@ -399,9 +544,6 @@ TkWmNewWindow(winPtr)
* a guess about how space is needed for window manager decorations.
*/
- wmPtr->maxWidth = 0;
- wmPtr->maxHeight = 0;
- wmPtr->gridWin = NULL;
wmPtr->widthInc = wmPtr->heightInc = 1;
wmPtr->minAspect.x = wmPtr->minAspect.y = 1;
wmPtr->maxAspect.x = wmPtr->maxAspect.y = 1;
@@ -415,13 +557,9 @@ TkWmNewWindow(winPtr)
+ 2*winPtr->changes.border_width;
wmPtr->parentHeight = winPtr->changes.height
+ 2*winPtr->changes.border_width;
- wmPtr->xInParent = wmPtr->yInParent = 0;
wmPtr->configWidth = -1;
wmPtr->configHeight = -1;
wmPtr->vRoot = None;
- wmPtr->protPtr = NULL;
- wmPtr->cmdArgv = NULL;
- wmPtr->clientMachine = NULL;
wmPtr->flags = WM_NEVER_MAPPED;
wmPtr->nextPtr = (WmInfo *) dispPtr->firstWmPtr;
dispPtr->firstWmPtr = wmPtr;
@@ -467,7 +605,7 @@ TkWmMapWindow(winPtr)
{
register WmInfo *wmPtr = winPtr->wmInfoPtr;
XTextProperty textProp;
- char *string;
+ Tk_Uid string;
if (wmPtr->flags & WM_NEVER_MAPPED) {
Tcl_DString ds;
@@ -507,12 +645,21 @@ TkWmMapWindow(winPtr)
Tcl_DStringValue(&ds));
Tcl_DStringFree(&ds);
}
-
- if (wmPtr->master != None) {
- XSetTransientForHint(winPtr->display, wmPtr->wrapperPtr->window,
- wmPtr->master);
+
+ if (wmPtr->masterPtr != NULL) {
+ /*
+ * Don't map a transient if the master is not mapped.
+ */
+
+ if (!Tk_IsMapped(wmPtr->masterPtr)) {
+ wmPtr->withdrawn = 1;
+ wmPtr->hints.initial_state = WithdrawnState;
+ } else {
+ XSetTransientForHint(winPtr->display, wmPtr->wrapperPtr->window,
+ wmPtr->masterPtr->wmInfoPtr->wrapperPtr->window);
+ }
}
-
+
wmPtr->flags |= WM_UPDATE_SIZE_HINTS;
UpdateHints(winPtr);
UpdateWmProtocols(wmPtr);
@@ -596,7 +743,7 @@ TkWmUnmapWindow(winPtr)
* mapped when in fact it is mapped. I suspect that this has something
* to do with the window manager filtering Map events (and possily not
* filtering Unmap events?).
- */
+ */
XUnmapWindow(winPtr->display, winPtr->wmInfoPtr->wrapperPtr->window);
WaitForMapNotify(winPtr, 0);
}
@@ -634,7 +781,7 @@ TkWmDeadWindow(winPtr)
} else {
register WmInfo *prevPtr;
- for (prevPtr = (WmInfo *) winPtr->dispPtr->firstWmPtr; ;
+ for (prevPtr = (WmInfo *) winPtr->dispPtr->firstWmPtr; ;
prevPtr = prevPtr->nextPtr) {
if (prevPtr == NULL) {
panic("couldn't unlink window in TkWmDeadWindow");
@@ -660,9 +807,6 @@ TkWmDeadWindow(winPtr)
if (wmPtr->leaderName != NULL) {
ckfree(wmPtr->leaderName);
}
- if (wmPtr->masterWindowName != NULL) {
- ckfree(wmPtr->masterWindowName);
- }
if (wmPtr->icon != NULL) {
wmPtr2 = ((TkWindow *) wmPtr->icon)->wmInfoPtr;
wmPtr2->iconFor = NULL;
@@ -706,6 +850,44 @@ TkWmDeadWindow(winPtr)
if (wmPtr->flags & WM_UPDATE_PENDING) {
Tcl_CancelIdleCall(UpdateGeometryInfo, (ClientData) winPtr);
}
+ /*
+ * Reset all transient windows whose master is the dead window.
+ */
+
+ for (wmPtr2 = winPtr->dispPtr->firstWmPtr; wmPtr2 != NULL;
+ wmPtr2 = wmPtr2->nextPtr) {
+ if (wmPtr2->masterPtr == winPtr) {
+ wmPtr->numTransients--;
+ Tk_DeleteEventHandler((Tk_Window) wmPtr2->masterPtr,
+ StructureNotifyMask,
+ WmWaitMapProc, (ClientData) wmPtr2->winPtr);
+ wmPtr2->masterPtr = NULL;
+ if (!(wmPtr2->flags & WM_NEVER_MAPPED)) {
+ XSetTransientForHint(wmPtr2->winPtr->display,
+ wmPtr2->wrapperPtr->window, None);
+ /* FIXME: Need a call like Win32's UpdateWrapper() so
+ we can recreate the wrapper and get rid of the
+ transient window decorations. */
+ }
+ }
+ }
+ if (wmPtr->numTransients != 0)
+ panic("numTransients should be 0");
+
+ if (wmPtr->masterPtr != NULL) {
+ wmPtr2 = wmPtr->masterPtr->wmInfoPtr;
+ /*
+ * If we had a master, tell them that we aren't tied
+ * to them anymore
+ */
+ if (wmPtr2 != NULL) {
+ wmPtr2->numTransients--;
+ }
+ Tk_DeleteEventHandler((Tk_Window) wmPtr->masterPtr,
+ StructureNotifyMask,
+ WmWaitMapProc, (ClientData) winPtr);
+ wmPtr->masterPtr = NULL;
+ }
ckfree((char *) wmPtr);
winPtr->wmInfoPtr = NULL;
}
@@ -758,7 +940,7 @@ TkWmSetClass(winPtr)
/*
*----------------------------------------------------------------------
*
- * Tk_WmCmd --
+ * Tk_WmObjCmd --
*
* This procedure is invoked to process the "wm" Tcl command.
* See the user documentation for details on what it does.
@@ -774,1199 +956,2231 @@ TkWmSetClass(winPtr)
/* ARGSUSED */
int
-Tk_WmCmd(clientData, interp, argc, argv)
+Tk_WmObjCmd(clientData, interp, objc, objv)
ClientData clientData; /* Main window associated with
* interpreter. */
Tcl_Interp *interp; /* Current interpreter. */
- int argc; /* Number of arguments. */
- char **argv; /* Argument strings. */
+ int objc; /* Number of arguments. */
+ Tcl_Obj *CONST objv[]; /* Argument objects. */
{
Tk_Window tkwin = (Tk_Window) clientData;
+ static CONST char *optionStrings[] = {
+ "aspect", "attributes", "client", "colormapwindows",
+ "command", "deiconify", "focusmodel", "frame",
+ "geometry", "grid", "group", "iconbitmap",
+ "iconify", "iconmask", "iconname", "iconposition",
+ "iconwindow", "maxsize", "minsize", "overrideredirect",
+ "positionfrom", "protocol", "resizable", "sizefrom",
+ "stackorder", "state", "title", "transient",
+ "withdraw", (char *) NULL };
+ enum options {
+ WMOPT_ASPECT, WMOPT_ATTRIBUTES, WMOPT_CLIENT, WMOPT_COLORMAPWINDOWS,
+ WMOPT_COMMAND, WMOPT_DEICONIFY, WMOPT_FOCUSMODEL, WMOPT_FRAME,
+ WMOPT_GEOMETRY, WMOPT_GRID, WMOPT_GROUP, WMOPT_ICONBITMAP,
+ WMOPT_ICONIFY, WMOPT_ICONMASK, WMOPT_ICONNAME, WMOPT_ICONPOSITION,
+ WMOPT_ICONWINDOW, WMOPT_MAXSIZE, WMOPT_MINSIZE, WMOPT_OVERRIDEREDIRECT,
+ WMOPT_POSITIONFROM, WMOPT_PROTOCOL, WMOPT_RESIZABLE, WMOPT_SIZEFROM,
+ WMOPT_STACKORDER, WMOPT_STATE, WMOPT_TITLE, WMOPT_TRANSIENT,
+ WMOPT_WITHDRAW };
+ int index;
+ int length;
+ char *argv1;
TkWindow *winPtr;
- register WmInfo *wmPtr;
- int c;
- size_t length;
TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;
- if (argc < 2) {
+ if (objc < 2) {
wrongNumArgs:
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- argv[0], " option window ?arg ...?\"", (char *) NULL);
+ Tcl_WrongNumArgs(interp, 1, objv, "option window ?arg ...?");
return TCL_ERROR;
}
- c = argv[1][0];
- length = strlen(argv[1]);
- if ((c == 't') && (strncmp(argv[1], "tracing", length) == 0)
+
+ argv1 = Tcl_GetStringFromObj(objv[1], &length);
+ if ((argv1[0] == 't') && (strncmp(argv1, "tracing", (size_t) length) == 0)
&& (length >= 3)) {
- if ((argc != 2) && (argc != 3)) {
- Tcl_AppendResult(interp, "wrong # arguments: must be \"",
- argv[0], " tracing ?boolean?\"", (char *) NULL);
+ int wmTracing;
+ if ((objc != 2) && (objc != 3)) {
+ Tcl_WrongNumArgs(interp, 2, objv, "?boolean?");
return TCL_ERROR;
}
- if (argc == 2) {
- Tcl_SetResult(interp, ((dispPtr->wmTracing) ? "on" : "off"),
- TCL_STATIC);
+ if (objc == 2) {
+ Tcl_SetResult(interp,
+ ((dispPtr->flags & TK_DISPLAY_WM_TRACING) ? "on" : "off"),
+ TCL_STATIC);
return TCL_OK;
}
- return Tcl_GetBoolean(interp, argv[2], &dispPtr->wmTracing);
+ if (Tcl_GetBooleanFromObj(interp, objv[2], &wmTracing) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (wmTracing) {
+ dispPtr->flags |= TK_DISPLAY_WM_TRACING;
+ } else {
+ dispPtr->flags &= ~TK_DISPLAY_WM_TRACING;
+ }
+ return TCL_OK;
+ }
+
+ if (Tcl_GetIndexFromObj(interp, objv[1], optionStrings, "option", 0,
+ &index) != TCL_OK) {
+ return TCL_ERROR;
}
- if (argc < 3) {
+ if (objc < 3) {
goto wrongNumArgs;
}
- winPtr = (TkWindow *) Tk_NameToWindow(interp, argv[2], tkwin);
- if (winPtr == NULL) {
+
+ if (TkGetWindowFromObj(interp, tkwin, objv[2], (Tk_Window *) &winPtr)
+ != TCL_OK) {
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;
}
- wmPtr = winPtr->wmInfoPtr;
- if ((c == 'a') && (strncmp(argv[1], "aspect", length) == 0)) {
- int numer1, denom1, numer2, denom2;
- if ((argc != 3) && (argc != 7)) {
- Tcl_AppendResult(interp, "wrong # arguments: must be \"",
- argv[0], " aspect window ?minNumer minDenom ",
- "maxNumer maxDenom?\"", (char *) NULL);
- return TCL_ERROR;
- }
- if (argc == 3) {
- if (wmPtr->sizeHintsFlags & PAspect) {
- char buf[TCL_INTEGER_SPACE * 4];
-
- sprintf(buf, "%d %d %d %d", wmPtr->minAspect.x,
- wmPtr->minAspect.y, wmPtr->maxAspect.x,
- wmPtr->maxAspect.y);
- Tcl_SetResult(interp, buf, TCL_VOLATILE);
- }
- return TCL_OK;
- }
- if (*argv[3] == '\0') {
- wmPtr->sizeHintsFlags &= ~PAspect;
- } else {
- if ((Tcl_GetInt(interp, argv[3], &numer1) != TCL_OK)
- || (Tcl_GetInt(interp, argv[4], &denom1) != TCL_OK)
- || (Tcl_GetInt(interp, argv[5], &numer2) != TCL_OK)
- || (Tcl_GetInt(interp, argv[6], &denom2) != TCL_OK)) {
- return TCL_ERROR;
- }
- if ((numer1 <= 0) || (denom1 <= 0) || (numer2 <= 0) ||
- (denom2 <= 0)) {
- Tcl_SetResult(interp, "aspect number can't be <= 0",
- TCL_STATIC);
- return TCL_ERROR;
- }
- wmPtr->minAspect.x = numer1;
- wmPtr->minAspect.y = denom1;
- wmPtr->maxAspect.x = numer2;
- wmPtr->maxAspect.y = denom2;
- wmPtr->sizeHintsFlags |= PAspect;
+ switch ((enum options) index) {
+ case WMOPT_ASPECT:
+ return WmAspectCmd(tkwin, winPtr, interp, objc, objv);
+ case WMOPT_ATTRIBUTES:
+ return WmAttributesCmd(tkwin, winPtr, interp, objc, objv);
+ case WMOPT_CLIENT:
+ return WmClientCmd(tkwin, winPtr, interp, objc, objv);
+ case WMOPT_COLORMAPWINDOWS:
+ return WmColormapwindowsCmd(tkwin, winPtr, interp, objc, objv);
+ case WMOPT_COMMAND:
+ return WmCommandCmd(tkwin, winPtr, interp, objc, objv);
+ case WMOPT_DEICONIFY:
+ return WmDeiconifyCmd(tkwin, winPtr, interp, objc, objv);
+ case WMOPT_FOCUSMODEL:
+ return WmFocusmodelCmd(tkwin, winPtr, interp, objc, objv);
+ case WMOPT_FRAME:
+ return WmFrameCmd(tkwin, winPtr, interp, objc, objv);
+ case WMOPT_GEOMETRY:
+ return WmGeometryCmd(tkwin, winPtr, interp, objc, objv);
+ case WMOPT_GRID:
+ return WmGridCmd(tkwin, winPtr, interp, objc, objv);
+ case WMOPT_GROUP:
+ return WmGroupCmd(tkwin, winPtr, interp, objc, objv);
+ case WMOPT_ICONBITMAP:
+ return WmIconbitmapCmd(tkwin, winPtr, interp, objc, objv);
+ case WMOPT_ICONIFY:
+ return WmIconifyCmd(tkwin, winPtr, interp, objc, objv);
+ case WMOPT_ICONMASK:
+ return WmIconmaskCmd(tkwin, winPtr, interp, objc, objv);
+ case WMOPT_ICONNAME:
+ return WmIconnameCmd(tkwin, winPtr, interp, objc, objv);
+ case WMOPT_ICONPOSITION:
+ return WmIconpositionCmd(tkwin, winPtr, interp, objc, objv);
+ case WMOPT_ICONWINDOW:
+ return WmIconwindowCmd(tkwin, winPtr, interp, objc, objv);
+ case WMOPT_MAXSIZE:
+ return WmMaxsizeCmd(tkwin, winPtr, interp, objc, objv);
+ case WMOPT_MINSIZE:
+ return WmMinsizeCmd(tkwin, winPtr, interp, objc, objv);
+ case WMOPT_OVERRIDEREDIRECT:
+ return WmOverrideredirectCmd(tkwin, winPtr, interp, objc, objv);
+ case WMOPT_POSITIONFROM:
+ return WmPositionfromCmd(tkwin, winPtr, interp, objc, objv);
+ case WMOPT_PROTOCOL:
+ return WmProtocolCmd(tkwin, winPtr, interp, objc, objv);
+ case WMOPT_RESIZABLE:
+ return WmResizableCmd(tkwin, winPtr, interp, objc, objv);
+ case WMOPT_SIZEFROM:
+ return WmSizefromCmd(tkwin, winPtr, interp, objc, objv);
+ case WMOPT_STACKORDER:
+ return WmStackorderCmd(tkwin, winPtr, interp, objc, objv);
+ case WMOPT_STATE:
+ return WmStateCmd(tkwin, winPtr, interp, objc, objv);
+ case WMOPT_TITLE:
+ return WmTitleCmd(tkwin, winPtr, interp, objc, objv);
+ case WMOPT_TRANSIENT:
+ return WmTransientCmd(tkwin, winPtr, interp, objc, objv);
+ case WMOPT_WITHDRAW:
+ return WmWithdrawCmd(tkwin, winPtr, interp, objc, objv);
+ }
+
+ /* This should not happen */
+ return TCL_ERROR;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * WmAspectCmd --
+ *
+ * This procedure is invoked to process the "wm aspect" Tcl command.
+ * See the user documentation for details on what it does.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+WmAspectCmd(tkwin, winPtr, interp, objc, objv)
+ Tk_Window tkwin; /* Main window of the application. */
+ TkWindow *winPtr; /* Toplevel to work with */
+ Tcl_Interp *interp; /* Current interpreter. */
+ int objc; /* Number of arguments. */
+ Tcl_Obj *CONST objv[]; /* Argument objects. */
+{
+ register WmInfo *wmPtr = winPtr->wmInfoPtr;
+ int numer1, denom1, numer2, denom2;
+
+ if ((objc != 3) && (objc != 7)) {
+ Tcl_WrongNumArgs(interp, 2, objv,
+ "window ?minNumer minDenom maxNumer maxDenom?");
+ return TCL_ERROR;
+ }
+ if (objc == 3) {
+ if (wmPtr->sizeHintsFlags & PAspect) {
+ char buf[TCL_INTEGER_SPACE * 4];
+
+ sprintf(buf, "%d %d %d %d", wmPtr->minAspect.x,
+ wmPtr->minAspect.y, wmPtr->maxAspect.x,
+ wmPtr->maxAspect.y);
+ Tcl_SetResult(interp, buf, TCL_VOLATILE);
}
- wmPtr->flags |= WM_UPDATE_SIZE_HINTS;
- goto updateGeom;
- } else if ((c == 'c') && (strncmp(argv[1], "client", length) == 0)
- && (length >= 2)) {
- if ((argc != 3) && (argc != 4)) {
- Tcl_AppendResult(interp, "wrong # arguments: must be \"",
- argv[0], " client window ?name?\"",
- (char *) NULL);
+ return TCL_OK;
+ }
+ if (*Tcl_GetString(objv[3]) == '\0') {
+ wmPtr->sizeHintsFlags &= ~PAspect;
+ } else {
+ if ((Tcl_GetIntFromObj(interp, objv[3], &numer1) != TCL_OK)
+ || (Tcl_GetIntFromObj(interp, objv[4], &denom1) != TCL_OK)
+ || (Tcl_GetIntFromObj(interp, objv[5], &numer2) != TCL_OK)
+ || (Tcl_GetIntFromObj(interp, objv[6], &denom2) != TCL_OK)) {
return TCL_ERROR;
}
- if (argc == 3) {
- if (wmPtr->clientMachine != NULL) {
- Tcl_SetResult(interp, wmPtr->clientMachine, TCL_STATIC);
- }
- return TCL_OK;
+ if ((numer1 <= 0) || (denom1 <= 0) || (numer2 <= 0) ||
+ (denom2 <= 0)) {
+ Tcl_SetResult(interp, "aspect number can't be <= 0",
+ TCL_STATIC);
+ return TCL_ERROR;
}
- if (argv[3][0] == 0) {
- if (wmPtr->clientMachine != NULL) {
- ckfree((char *) wmPtr->clientMachine);
- wmPtr->clientMachine = NULL;
- if (!(wmPtr->flags & WM_NEVER_MAPPED)) {
- XDeleteProperty(winPtr->display, wmPtr->wrapperPtr->window,
- Tk_InternAtom((Tk_Window) winPtr,
- "WM_CLIENT_MACHINE"));
- }
- }
- return TCL_OK;
+ wmPtr->minAspect.x = numer1;
+ wmPtr->minAspect.y = denom1;
+ wmPtr->maxAspect.x = numer2;
+ wmPtr->maxAspect.y = denom2;
+ wmPtr->sizeHintsFlags |= PAspect;
+ }
+ wmPtr->flags |= WM_UPDATE_SIZE_HINTS;
+ WmUpdateGeom(wmPtr, winPtr);
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * WmAttributesCmd --
+ *
+ * This procedure is invoked to process the "wm attributes" Tcl command.
+ * See the user documentation for details on what it does.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+WmAttributesCmd(tkwin, winPtr, interp, objc, objv)
+ Tk_Window tkwin; /* Main window of the application. */
+ TkWindow *winPtr; /* Toplevel to work with */
+ Tcl_Interp *interp; /* Current interpreter. */
+ int objc; /* Number of arguments. */
+ Tcl_Obj *CONST objv[]; /* Argument objects. */
+{
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "window");
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * WmClientCmd --
+ *
+ * This procedure is invoked to process the "wm client" Tcl command.
+ * See the user documentation for details on what it does.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+WmClientCmd(tkwin, winPtr, interp, objc, objv)
+ Tk_Window tkwin; /* Main window of the application. */
+ TkWindow *winPtr; /* Toplevel to work with */
+ Tcl_Interp *interp; /* Current interpreter. */
+ int objc; /* Number of arguments. */
+ Tcl_Obj *CONST objv[]; /* Argument objects. */
+{
+ register WmInfo *wmPtr = winPtr->wmInfoPtr;
+ char *argv3;
+ int length;
+
+ if ((objc != 3) && (objc != 4)) {
+ Tcl_WrongNumArgs(interp, 2, objv, "window ?name?");
+ return TCL_ERROR;
+ }
+ if (objc == 3) {
+ if (wmPtr->clientMachine != NULL) {
+ Tcl_SetResult(interp, wmPtr->clientMachine, TCL_STATIC);
}
+ return TCL_OK;
+ }
+ argv3 = Tcl_GetStringFromObj(objv[3], &length);
+ if (argv3[0] == 0) {
if (wmPtr->clientMachine != NULL) {
ckfree((char *) wmPtr->clientMachine);
- }
- wmPtr->clientMachine = (char *)
- ckalloc((unsigned) (strlen(argv[3]) + 1));
- strcpy(wmPtr->clientMachine, argv[3]);
- if (!(wmPtr->flags & WM_NEVER_MAPPED)) {
- XTextProperty textProp;
- Tcl_DString ds;
-
- Tcl_UtfToExternalDString(NULL, wmPtr->clientMachine, -1, &ds);
- if (XStringListToTextProperty(&(Tcl_DStringValue(&ds)), 1,
- &textProp) != 0) {
- XSetWMClientMachine(winPtr->display, wmPtr->wrapperPtr->window,
- &textProp);
- XFree((char *) textProp.value);
+ wmPtr->clientMachine = NULL;
+ if (!(wmPtr->flags & WM_NEVER_MAPPED)) {
+ XDeleteProperty(winPtr->display, wmPtr->wrapperPtr->window,
+ Tk_InternAtom((Tk_Window) winPtr,
+ "WM_CLIENT_MACHINE"));
}
- Tcl_DStringFree(&ds);
}
- } else if ((c == 'c') && (strncmp(argv[1], "colormapwindows", length) == 0)
- && (length >= 3)) {
- Window *cmapList;
- TkWindow *winPtr2;
- int count, i, windowArgc, gotToplevel;
- char buffer[20], **windowArgv;
+ return TCL_OK;
+ }
+ if (wmPtr->clientMachine != NULL) {
+ ckfree((char *) wmPtr->clientMachine);
+ }
+ wmPtr->clientMachine = (char *)
+ ckalloc((unsigned) (length + 1));
+ strcpy(wmPtr->clientMachine, argv3);
+ if (!(wmPtr->flags & WM_NEVER_MAPPED)) {
+ XTextProperty textProp;
+ Tcl_DString ds;
- if ((argc != 3) && (argc != 4)) {
- Tcl_AppendResult(interp, "wrong # arguments: must be \"",
- argv[0], " colormapwindows window ?windowList?\"",
- (char *) NULL);
- return TCL_ERROR;
- }
- Tk_MakeWindowExist((Tk_Window) winPtr);
- if (wmPtr->wrapperPtr == NULL) {
- CreateWrapper(wmPtr);
+ Tcl_UtfToExternalDString(NULL, wmPtr->clientMachine, -1, &ds);
+ if (XStringListToTextProperty(&(Tcl_DStringValue(&ds)), 1,
+ &textProp) != 0) {
+ XSetWMClientMachine(winPtr->display, wmPtr->wrapperPtr->window,
+ &textProp);
+ XFree((char *) textProp.value);
}
- if (argc == 3) {
- if (XGetWMColormapWindows(winPtr->display,
- wmPtr->wrapperPtr->window, &cmapList, &count) == 0) {
- return TCL_OK;
- }
- for (i = 0; i < count; i++) {
- if ((i == (count-1))
- && (wmPtr->flags & WM_ADDED_TOPLEVEL_COLORMAP)) {
- break;
- }
- winPtr2 = (TkWindow *) Tk_IdToWindow(winPtr->display,
- cmapList[i]);
- if (winPtr2 == NULL) {
- sprintf(buffer, "0x%lx", cmapList[i]);
- Tcl_AppendElement(interp, buffer);
- } else {
- Tcl_AppendElement(interp, winPtr2->pathName);
- }
- }
- XFree((char *) cmapList);
+ Tcl_DStringFree(&ds);
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * WmColormapwindowsCmd --
+ *
+ * This procedure is invoked to process the "wm colormapwindows"
+ * Tcl command.
+ * See the user documentation for details on what it does.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+WmColormapwindowsCmd(tkwin, winPtr, interp, objc, objv)
+ Tk_Window tkwin; /* Main window of the application. */
+ TkWindow *winPtr; /* Toplevel to work with */
+ Tcl_Interp *interp; /* Current interpreter. */
+ int objc; /* Number of arguments. */
+ Tcl_Obj *CONST objv[]; /* Argument objects. */
+{
+ register WmInfo *wmPtr = winPtr->wmInfoPtr;
+ Window *cmapList;
+ TkWindow *winPtr2;
+ int count, i, windowObjc, gotToplevel;
+ Tcl_Obj **windowObjv;
+ char buffer[20];
+
+ if ((objc != 3) && (objc != 4)) {
+ Tcl_WrongNumArgs(interp, 2, objv, "window ?windowList?");
+ return TCL_ERROR;
+ }
+ Tk_MakeWindowExist((Tk_Window) winPtr);
+ if (wmPtr->wrapperPtr == NULL) {
+ CreateWrapper(wmPtr);
+ }
+ if (objc == 3) {
+ if (XGetWMColormapWindows(winPtr->display,
+ wmPtr->wrapperPtr->window, &cmapList, &count) == 0) {
return TCL_OK;
}
- if (Tcl_SplitList(interp, argv[3], &windowArgc, &windowArgv)
- != TCL_OK) {
- return TCL_ERROR;
- }
- cmapList = (Window *) ckalloc((unsigned)
- ((windowArgc+1)*sizeof(Window)));
- gotToplevel = 0;
- for (i = 0; i < windowArgc; i++) {
- winPtr2 = (TkWindow *) Tk_NameToWindow(interp, windowArgv[i],
- tkwin);
- if (winPtr2 == NULL) {
- ckfree((char *) cmapList);
- ckfree((char *) windowArgv);
- return TCL_ERROR;
- }
- if (winPtr2 == winPtr) {
- gotToplevel = 1;
+ for (i = 0; i < count; i++) {
+ if ((i == (count-1))
+ && (wmPtr->flags & WM_ADDED_TOPLEVEL_COLORMAP)) {
+ break;
}
- if (winPtr2->window == None) {
- Tk_MakeWindowExist((Tk_Window) winPtr2);
+ winPtr2 = (TkWindow *) Tk_IdToWindow(winPtr->display,
+ cmapList[i]);
+ if (winPtr2 == NULL) {
+ sprintf(buffer, "0x%lx", cmapList[i]);
+ Tcl_AppendElement(interp, buffer);
+ } else {
+ Tcl_AppendElement(interp, winPtr2->pathName);
}
- cmapList[i] = winPtr2->window;
}
- if (!gotToplevel) {
- wmPtr->flags |= WM_ADDED_TOPLEVEL_COLORMAP;
- cmapList[windowArgc] = wmPtr->wrapperPtr->window;
- windowArgc++;
- } else {
- wmPtr->flags &= ~WM_ADDED_TOPLEVEL_COLORMAP;
- }
- wmPtr->flags |= WM_COLORMAPS_EXPLICIT;
- XSetWMColormapWindows(winPtr->display, wmPtr->wrapperPtr->window,
- cmapList, windowArgc);
- ckfree((char *) cmapList);
- ckfree((char *) windowArgv);
+ XFree((char *) cmapList);
return TCL_OK;
- } else if ((c == 'c') && (strncmp(argv[1], "command", length) == 0)
- && (length >= 3)) {
- int cmdArgc;
- char **cmdArgv;
-
- if ((argc != 3) && (argc != 4)) {
- Tcl_AppendResult(interp, "wrong # arguments: must be \"",
- argv[0], " command window ?value?\"",
- (char *) NULL);
+ }
+ if (Tcl_ListObjGetElements(interp, objv[3], &windowObjc, &windowObjv)
+ != TCL_OK) {
+ return TCL_ERROR;
+ }
+ cmapList = (Window *) ckalloc((unsigned)
+ ((windowObjc+1)*sizeof(Window)));
+ gotToplevel = 0;
+ for (i = 0; i < windowObjc; i++) {
+ if (TkGetWindowFromObj(interp, tkwin, windowObjv[i],
+ (Tk_Window *) &winPtr2) != TCL_OK)
+ {
+ ckfree((char *) cmapList);
return TCL_ERROR;
}
- if (argc == 3) {
- if (wmPtr->cmdArgv != NULL) {
- Tcl_SetResult(interp,
- Tcl_Merge(wmPtr->cmdArgc, wmPtr->cmdArgv),
- TCL_DYNAMIC);
- }
- return TCL_OK;
+ if (winPtr2 == winPtr) {
+ gotToplevel = 1;
}
- if (argv[3][0] == 0) {
- if (wmPtr->cmdArgv != NULL) {
- ckfree((char *) wmPtr->cmdArgv);
- wmPtr->cmdArgv = NULL;
- if (!(wmPtr->flags & WM_NEVER_MAPPED)) {
- XDeleteProperty(winPtr->display, wmPtr->wrapperPtr->window,
- Tk_InternAtom((Tk_Window) winPtr, "WM_COMMAND"));
- }
- }
- return TCL_OK;
+ if (winPtr2->window == None) {
+ Tk_MakeWindowExist((Tk_Window) winPtr2);
}
- if (Tcl_SplitList(interp, argv[3], &cmdArgc, &cmdArgv) != TCL_OK) {
- return TCL_ERROR;
+ cmapList[i] = winPtr2->window;
+ }
+ if (!gotToplevel) {
+ wmPtr->flags |= WM_ADDED_TOPLEVEL_COLORMAP;
+ cmapList[windowObjc] = wmPtr->wrapperPtr->window;
+ windowObjc++;
+ } else {
+ wmPtr->flags &= ~WM_ADDED_TOPLEVEL_COLORMAP;
+ }
+ wmPtr->flags |= WM_COLORMAPS_EXPLICIT;
+ XSetWMColormapWindows(winPtr->display, wmPtr->wrapperPtr->window,
+ cmapList, windowObjc);
+ ckfree((char *) cmapList);
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * WmCommandCmd --
+ *
+ * This procedure is invoked to process the "wm command" Tcl command.
+ * See the user documentation for details on what it does.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+WmCommandCmd(tkwin, winPtr, interp, objc, objv)
+ Tk_Window tkwin; /* Main window of the application. */
+ TkWindow *winPtr; /* Toplevel to work with */
+ Tcl_Interp *interp; /* Current interpreter. */
+ int objc; /* Number of arguments. */
+ Tcl_Obj *CONST objv[]; /* Argument objects. */
+{
+ register WmInfo *wmPtr = winPtr->wmInfoPtr;
+ char *argv3;
+ int cmdArgc;
+ CONST char **cmdArgv;
+
+ if ((objc != 3) && (objc != 4)) {
+ Tcl_WrongNumArgs(interp, 2, objv, "window ?value?");
+ return TCL_ERROR;
+ }
+ if (objc == 3) {
+ if (wmPtr->cmdArgv != NULL) {
+ Tcl_SetResult(interp,
+ Tcl_Merge(wmPtr->cmdArgc, wmPtr->cmdArgv),
+ TCL_DYNAMIC);
}
+ return TCL_OK;
+ }
+ argv3 = Tcl_GetString(objv[3]);
+ if (argv3[0] == 0) {
if (wmPtr->cmdArgv != NULL) {
ckfree((char *) wmPtr->cmdArgv);
+ wmPtr->cmdArgv = NULL;
+ if (!(wmPtr->flags & WM_NEVER_MAPPED)) {
+ XDeleteProperty(winPtr->display, wmPtr->wrapperPtr->window,
+ Tk_InternAtom((Tk_Window) winPtr, "WM_COMMAND"));
+ }
}
- wmPtr->cmdArgc = cmdArgc;
- wmPtr->cmdArgv = cmdArgv;
- if (!(wmPtr->flags & WM_NEVER_MAPPED)) {
- UpdateCommand(winPtr);
+ return TCL_OK;
+ }
+ if (Tcl_SplitList(interp, argv3, &cmdArgc, &cmdArgv) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (wmPtr->cmdArgv != NULL) {
+ ckfree((char *) wmPtr->cmdArgv);
+ }
+ wmPtr->cmdArgc = cmdArgc;
+ wmPtr->cmdArgv = cmdArgv;
+ if (!(wmPtr->flags & WM_NEVER_MAPPED)) {
+ UpdateCommand(winPtr);
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * WmDeiconifyCmd --
+ *
+ * This procedure is invoked to process the "wm deiconify" Tcl command.
+ * See the user documentation for details on what it does.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+WmDeiconifyCmd(tkwin, winPtr, interp, objc, objv)
+ Tk_Window tkwin; /* Main window of the application. */
+ TkWindow *winPtr; /* Toplevel to work with */
+ Tcl_Interp *interp; /* Current interpreter. */
+ int objc; /* Number of arguments. */
+ Tcl_Obj *CONST objv[]; /* Argument objects. */
+{
+ register WmInfo *wmPtr = winPtr->wmInfoPtr;
+
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "window");
+ return TCL_ERROR;
+ }
+ if (wmPtr->iconFor != NULL) {
+ Tcl_AppendResult(interp, "can't deiconify ", Tcl_GetString(objv[2]),
+ ": it is an icon for ", Tk_PathName(wmPtr->iconFor),
+ (char *) NULL);
+ return TCL_ERROR;
+ }
+ if (winPtr->flags & TK_EMBEDDED) {
+ Tcl_AppendResult(interp, "can't deiconify ", winPtr->pathName,
+ ": it is an embedded window", (char *) NULL);
+ return TCL_ERROR;
+ }
+ if (wmPtr->flags & WM_TRANSIENT_WITHDRAWN) {
+ wmPtr->flags &= ~WM_TRANSIENT_WITHDRAWN;
+ }
+ TkpWmSetState(winPtr, NormalState);
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * WmFocusmodelCmd --
+ *
+ * This procedure is invoked to process the "wm focusmodel" Tcl command.
+ * See the user documentation for details on what it does.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+WmFocusmodelCmd(tkwin, winPtr, interp, objc, objv)
+ Tk_Window tkwin; /* Main window of the application. */
+ TkWindow *winPtr; /* Toplevel to work with */
+ Tcl_Interp *interp; /* Current interpreter. */
+ int objc; /* Number of arguments. */
+ Tcl_Obj *CONST objv[]; /* Argument objects. */
+{
+ register WmInfo *wmPtr = winPtr->wmInfoPtr;
+ static CONST char *optionStrings[] = {
+ "active", "passive", (char *) NULL };
+ enum options {
+ OPT_ACTIVE, OPT_PASSIVE };
+ int index;
+
+ if ((objc != 3) && (objc != 4)) {
+ Tcl_WrongNumArgs(interp, 2, objv, "window ?active|passive?");
+ return TCL_ERROR;
+ }
+ if (objc == 3) {
+ Tcl_SetResult(interp, (wmPtr->hints.input ? "passive" : "active"),
+ TCL_STATIC);
+ return TCL_OK;
+ }
+
+ if (Tcl_GetIndexFromObj(interp, objv[3], optionStrings, "argument", 0,
+ &index) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (index == OPT_ACTIVE) {
+ wmPtr->hints.input = False;
+ } else { /* OPT_PASSIVE */
+ wmPtr->hints.input = True;
+ }
+ UpdateHints(winPtr);
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * WmFrameCmd --
+ *
+ * This procedure is invoked to process the "wm frame" Tcl command.
+ * See the user documentation for details on what it does.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+WmFrameCmd(tkwin, winPtr, interp, objc, objv)
+ Tk_Window tkwin; /* Main window of the application. */
+ TkWindow *winPtr; /* Toplevel to work with */
+ Tcl_Interp *interp; /* Current interpreter. */
+ int objc; /* Number of arguments. */
+ Tcl_Obj *CONST objv[]; /* Argument objects. */
+{
+ register WmInfo *wmPtr = winPtr->wmInfoPtr;
+ Window window;
+ char buf[TCL_INTEGER_SPACE];
+
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "window");
+ return TCL_ERROR;
+ }
+ window = wmPtr->reparent;
+ if (window == None) {
+ window = Tk_WindowId((Tk_Window) winPtr);
+ }
+ sprintf(buf, "0x%x", (unsigned int) window);
+ Tcl_SetResult(interp, buf, TCL_VOLATILE);
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * WmGeometryCmd --
+ *
+ * This procedure is invoked to process the "wm geometry" Tcl command.
+ * See the user documentation for details on what it does.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+WmGeometryCmd(tkwin, winPtr, interp, objc, objv)
+ Tk_Window tkwin; /* Main window of the application. */
+ TkWindow *winPtr; /* Toplevel to work with */
+ Tcl_Interp *interp; /* Current interpreter. */
+ int objc; /* Number of arguments. */
+ Tcl_Obj *CONST objv[]; /* Argument objects. */
+{
+ register WmInfo *wmPtr = winPtr->wmInfoPtr;
+ char xSign, ySign;
+ int width, height;
+ char *argv3;
+
+ if ((objc != 3) && (objc != 4)) {
+ Tcl_WrongNumArgs(interp, 2, objv, "window ?newGeometry?");
+ return TCL_ERROR;
+ }
+ if (objc == 3) {
+ char buf[16 + TCL_INTEGER_SPACE * 4];
+
+ xSign = (wmPtr->flags & WM_NEGATIVE_X) ? '-' : '+';
+ ySign = (wmPtr->flags & WM_NEGATIVE_Y) ? '-' : '+';
+ if (wmPtr->gridWin != NULL) {
+ width = wmPtr->reqGridWidth + (winPtr->changes.width
+ - winPtr->reqWidth)/wmPtr->widthInc;
+ height = wmPtr->reqGridHeight + (winPtr->changes.height
+ - winPtr->reqHeight)/wmPtr->heightInc;
+ } else {
+ width = winPtr->changes.width;
+ height = winPtr->changes.height;
}
- } else if ((c == 'd') && (strncmp(argv[1], "deiconify", length) == 0)) {
- if (argc != 3) {
- Tcl_AppendResult(interp, "wrong # arguments: must be \"",
- argv[0], " deiconify window\"", (char *) NULL);
- return TCL_ERROR;
+ sprintf(buf, "%dx%d%c%d%c%d", width, height, xSign, wmPtr->x,
+ ySign, wmPtr->y);
+ Tcl_SetResult(interp, buf, TCL_VOLATILE);
+ return TCL_OK;
+ }
+ argv3 = Tcl_GetString(objv[3]);
+ if (*argv3 == '\0') {
+ wmPtr->width = -1;
+ wmPtr->height = -1;
+ WmUpdateGeom(wmPtr, winPtr);
+ return TCL_OK;
+ }
+ return ParseGeometry(interp, argv3, winPtr);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * WmGridCmd --
+ *
+ * This procedure is invoked to process the "wm grid" Tcl command.
+ * See the user documentation for details on what it does.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+WmGridCmd(tkwin, winPtr, interp, objc, objv)
+ Tk_Window tkwin; /* Main window of the application. */
+ TkWindow *winPtr; /* Toplevel to work with */
+ Tcl_Interp *interp; /* Current interpreter. */
+ int objc; /* Number of arguments. */
+ Tcl_Obj *CONST objv[]; /* Argument objects. */
+{
+ register WmInfo *wmPtr = winPtr->wmInfoPtr;
+ int reqWidth, reqHeight, widthInc, heightInc;
+
+ if ((objc != 3) && (objc != 7)) {
+ Tcl_WrongNumArgs(interp, 2, objv,
+ "window ?baseWidth baseHeight widthInc heightInc?");
+ return TCL_ERROR;
+ }
+ if (objc == 3) {
+ if (wmPtr->sizeHintsFlags & PBaseSize) {
+ char buf[TCL_INTEGER_SPACE * 4];
+
+ sprintf(buf, "%d %d %d %d", wmPtr->reqGridWidth,
+ wmPtr->reqGridHeight, wmPtr->widthInc,
+ wmPtr->heightInc);
+ Tcl_SetResult(interp, buf, TCL_VOLATILE);
}
- if (wmPtr->iconFor != NULL) {
- Tcl_AppendResult(interp, "can't deiconify ", argv[2],
- ": it is an icon for ", Tk_PathName(wmPtr->iconFor),
- (char *) NULL);
- return TCL_ERROR;
+ return TCL_OK;
+ }
+ if (*Tcl_GetString(objv[3]) == '\0') {
+ /*
+ * Turn off gridding and reset the width and height
+ * to make sense as ungridded numbers.
+ */
+
+ wmPtr->sizeHintsFlags &= ~(PBaseSize|PResizeInc);
+ if (wmPtr->width != -1) {
+ wmPtr->width = winPtr->reqWidth + (wmPtr->width
+ - wmPtr->reqGridWidth)*wmPtr->widthInc;
+ wmPtr->height = winPtr->reqHeight + (wmPtr->height
+ - wmPtr->reqGridHeight)*wmPtr->heightInc;
}
- wmPtr->hints.initial_state = NormalState;
- wmPtr->withdrawn = 0;
- if (wmPtr->flags & WM_NEVER_MAPPED) {
- return TCL_OK;
+ wmPtr->widthInc = 1;
+ wmPtr->heightInc = 1;
+ } else {
+ if ((Tcl_GetIntFromObj(interp, objv[3], &reqWidth) != TCL_OK)
+ || (Tcl_GetIntFromObj(interp, objv[4], &reqHeight) != TCL_OK)
+ || (Tcl_GetIntFromObj(interp, objv[5], &widthInc) != TCL_OK)
+ || (Tcl_GetIntFromObj(interp, objv[6], &heightInc) != TCL_OK)) {
+ return TCL_ERROR;
}
- UpdateHints(winPtr);
- Tk_MapWindow((Tk_Window) winPtr);
- } else if ((c == 'f') && (strncmp(argv[1], "focusmodel", length) == 0)
- && (length >= 2)) {
- if ((argc != 3) && (argc != 4)) {
- Tcl_AppendResult(interp, "wrong # arguments: must be \"",
- argv[0], " focusmodel window ?active|passive?\"",
- (char *) NULL);
+ if (reqWidth < 0) {
+ Tcl_SetResult(interp, "baseWidth can't be < 0", TCL_STATIC);
return TCL_ERROR;
}
- if (argc == 3) {
- Tcl_SetResult(interp, (wmPtr->hints.input ? "passive" : "active"),
- TCL_STATIC);
- return TCL_OK;
+ if (reqHeight < 0) {
+ Tcl_SetResult(interp, "baseHeight can't be < 0", TCL_STATIC);
+ return TCL_ERROR;
}
- c = argv[3][0];
- length = strlen(argv[3]);
- if ((c == 'a') && (strncmp(argv[3], "active", length) == 0)) {
- wmPtr->hints.input = False;
- } else if ((c == 'p') && (strncmp(argv[3], "passive", length) == 0)) {
- wmPtr->hints.input = True;
- } else {
- Tcl_AppendResult(interp, "bad argument \"", argv[3],
- "\": must be active or passive", (char *) NULL);
+ if (widthInc < 0) {
+ Tcl_SetResult(interp, "widthInc can't be < 0", TCL_STATIC);
return TCL_ERROR;
}
- UpdateHints(winPtr);
- } else if ((c == 'f') && (strncmp(argv[1], "frame", length) == 0)
- && (length >= 2)) {
- Window window;
- char buf[TCL_INTEGER_SPACE];
-
- if (argc != 3) {
- Tcl_AppendResult(interp, "wrong # arguments: must be \"",
- argv[0], " frame window\"", (char *) NULL);
+ if (heightInc < 0) {
+ Tcl_SetResult(interp, "heightInc can't be < 0", TCL_STATIC);
return TCL_ERROR;
}
- window = wmPtr->reparent;
- if (window == None) {
- window = Tk_WindowId((Tk_Window) winPtr);
+ Tk_SetGrid((Tk_Window) winPtr, reqWidth, reqHeight, widthInc,
+ heightInc);
+ }
+ wmPtr->flags |= WM_UPDATE_SIZE_HINTS;
+ WmUpdateGeom(wmPtr, winPtr);
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * WmGroupCmd --
+ *
+ * This procedure is invoked to process the "wm group" Tcl command.
+ * See the user documentation for details on what it does.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+WmGroupCmd(tkwin, winPtr, interp, objc, objv)
+ Tk_Window tkwin; /* Main window of the application. */
+ TkWindow *winPtr; /* Toplevel to work with */
+ Tcl_Interp *interp; /* Current interpreter. */
+ int objc; /* Number of arguments. */
+ Tcl_Obj *CONST objv[]; /* Argument objects. */
+{
+ register WmInfo *wmPtr = winPtr->wmInfoPtr;
+ Tk_Window tkwin2;
+ WmInfo *wmPtr2;
+ char *argv3;
+ int length;
+
+ if ((objc != 3) && (objc != 4)) {
+ Tcl_WrongNumArgs(interp, 2, objv, "window ?pathName?");
+ return TCL_ERROR;
+ }
+ if (objc == 3) {
+ if (wmPtr->hints.flags & WindowGroupHint) {
+ Tcl_SetResult(interp, wmPtr->leaderName, TCL_STATIC);
}
- sprintf(buf, "0x%x", (unsigned int) window);
- Tcl_SetResult(interp, buf, TCL_VOLATILE);
- } else if ((c == 'g') && (strncmp(argv[1], "geometry", length) == 0)
- && (length >= 2)) {
- char xSign, ySign;
- int width, height;
-
- if ((argc != 3) && (argc != 4)) {
- Tcl_AppendResult(interp, "wrong # arguments: must be \"",
- argv[0], " geometry window ?newGeometry?\"",
- (char *) NULL);
+ return TCL_OK;
+ }
+ argv3 = Tcl_GetStringFromObj(objv[3], &length);
+ if (*argv3 == '\0') {
+ wmPtr->hints.flags &= ~WindowGroupHint;
+ if (wmPtr->leaderName != NULL) {
+ ckfree(wmPtr->leaderName);
+ }
+ wmPtr->leaderName = NULL;
+ } else {
+ if (TkGetWindowFromObj(interp, tkwin, objv[3], &tkwin2) != TCL_OK) {
return TCL_ERROR;
}
- if (argc == 3) {
- char buf[16 + TCL_INTEGER_SPACE * 4];
-
- xSign = (wmPtr->flags & WM_NEGATIVE_X) ? '-' : '+';
- ySign = (wmPtr->flags & WM_NEGATIVE_Y) ? '-' : '+';
- if (wmPtr->gridWin != NULL) {
- width = wmPtr->reqGridWidth + (winPtr->changes.width
- - winPtr->reqWidth)/wmPtr->widthInc;
- height = wmPtr->reqGridHeight + (winPtr->changes.height
- - winPtr->reqHeight)/wmPtr->heightInc;
- } else {
- width = winPtr->changes.width;
- height = winPtr->changes.height;
- }
- sprintf(buf, "%dx%d%c%d%c%d", width, height, xSign, wmPtr->x,
- ySign, wmPtr->y);
- Tcl_SetResult(interp, buf, TCL_VOLATILE);
- return TCL_OK;
+ while (!Tk_TopWinHierarchy(tkwin2)) {
+ /*
+ * Ensure that the group leader is actually a Tk toplevel.
+ */
+
+ tkwin2 = Tk_Parent(tkwin2);
}
- if (*argv[3] == '\0') {
- wmPtr->width = -1;
- wmPtr->height = -1;
- goto updateGeom;
+ Tk_MakeWindowExist(tkwin2);
+ wmPtr2 = ((TkWindow *) tkwin2)->wmInfoPtr;
+ if (wmPtr2->wrapperPtr == NULL) {
+ CreateWrapper(wmPtr2);
}
- return ParseGeometry(interp, argv[3], winPtr);
- } else if ((c == 'g') && (strncmp(argv[1], "grid", length) == 0)
- && (length >= 3)) {
- int reqWidth, reqHeight, widthInc, heightInc;
+ if (wmPtr->leaderName != NULL) {
+ ckfree(wmPtr->leaderName);
+ }
+ wmPtr->hints.window_group = Tk_WindowId(wmPtr2->wrapperPtr);
+ wmPtr->hints.flags |= WindowGroupHint;
+ wmPtr->leaderName = ckalloc((unsigned) (length + 1));
+ strcpy(wmPtr->leaderName, argv3);
+ }
+ UpdateHints(winPtr);
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * WmIconbitmapCmd --
+ *
+ * This procedure is invoked to process the "wm iconbitmap" Tcl command.
+ * See the user documentation for details on what it does.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
- if ((argc != 3) && (argc != 7)) {
- Tcl_AppendResult(interp, "wrong # arguments: must be \"",
- argv[0], " grid window ?baseWidth baseHeight ",
- "widthInc heightInc?\"", (char *) NULL);
+static int
+WmIconbitmapCmd(tkwin, winPtr, interp, objc, objv)
+ Tk_Window tkwin; /* Main window of the application. */
+ TkWindow *winPtr; /* Toplevel to work with */
+ Tcl_Interp *interp; /* Current interpreter. */
+ int objc; /* Number of arguments. */
+ Tcl_Obj *CONST objv[]; /* Argument objects. */
+{
+ register WmInfo *wmPtr = winPtr->wmInfoPtr;
+ Pixmap pixmap;
+ char *argv3;
+
+ if ((objc < 3) || (objc > 4)) {
+ Tcl_WrongNumArgs(interp, 2, objv, "window ?bitmap?");
+ return TCL_ERROR;
+ }
+ if (objc == 3) {
+ if (wmPtr->hints.flags & IconPixmapHint) {
+ Tcl_SetResult(interp, (char *)
+ Tk_NameOfBitmap(winPtr->display, wmPtr->hints.icon_pixmap),
+ TCL_STATIC);
+ }
+ return TCL_OK;
+ }
+ argv3 = Tcl_GetString(objv[3]);
+ if (*argv3 == '\0') {
+ if (wmPtr->hints.icon_pixmap != None) {
+ Tk_FreeBitmap(winPtr->display, wmPtr->hints.icon_pixmap);
+ wmPtr->hints.icon_pixmap = None;
+ }
+ wmPtr->hints.flags &= ~IconPixmapHint;
+ } else {
+ pixmap = Tk_GetBitmap(interp, (Tk_Window) winPtr, argv3);
+ if (pixmap == None) {
return TCL_ERROR;
}
- if (argc == 3) {
- if (wmPtr->sizeHintsFlags & PBaseSize) {
- char buf[TCL_INTEGER_SPACE * 4];
+ wmPtr->hints.icon_pixmap = pixmap;
+ wmPtr->hints.flags |= IconPixmapHint;
+ }
+ UpdateHints(winPtr);
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * WmIconifyCmd --
+ *
+ * This procedure is invoked to process the "wm iconify" Tcl command.
+ * See the user documentation for details on what it does.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
- sprintf(buf, "%d %d %d %d", wmPtr->reqGridWidth,
- wmPtr->reqGridHeight, wmPtr->widthInc,
- wmPtr->heightInc);
- Tcl_SetResult(interp, buf, TCL_VOLATILE);
- }
- return TCL_OK;
- }
- if (*argv[3] == '\0') {
- /*
- * Turn off gridding and reset the width and height
- * to make sense as ungridded numbers.
- */
+static int
+WmIconifyCmd(tkwin, winPtr, interp, objc, objv)
+ Tk_Window tkwin; /* Main window of the application. */
+ TkWindow *winPtr; /* Toplevel to work with */
+ Tcl_Interp *interp; /* Current interpreter. */
+ int objc; /* Number of arguments. */
+ Tcl_Obj *CONST objv[]; /* Argument objects. */
+{
+ register WmInfo *wmPtr = winPtr->wmInfoPtr;
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "window");
+ return TCL_ERROR;
+ }
+ if (Tk_Attributes((Tk_Window) winPtr)->override_redirect) {
+ Tcl_AppendResult(interp, "can't iconify \"", winPtr->pathName,
+ "\": override-redirect flag is set", (char *) NULL);
+ return TCL_ERROR;
+ }
+ if (wmPtr->masterPtr != NULL) {
+ Tcl_AppendResult(interp, "can't iconify \"", winPtr->pathName,
+ "\": it is a transient", (char *) NULL);
+ return TCL_ERROR;
+ }
+ if (wmPtr->iconFor != NULL) {
+ Tcl_AppendResult(interp, "can't iconify ", winPtr->pathName,
+ ": it is an icon for ", Tk_PathName(wmPtr->iconFor),
+ (char *) NULL);
+ return TCL_ERROR;
+ }
+ if (winPtr->flags & TK_EMBEDDED) {
+ Tcl_AppendResult(interp, "can't iconify ", winPtr->pathName,
+ ": it is an embedded window", (char *) NULL);
+ return TCL_ERROR;
+ }
+ if (TkpWmSetState(winPtr, IconicState) == 0) {
+ Tcl_SetResult(interp,
+ "couldn't send iconify message to window manager",
+ TCL_STATIC);
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * WmIconmaskCmd --
+ *
+ * This procedure is invoked to process the "wm iconmask" Tcl command.
+ * See the user documentation for details on what it does.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
- wmPtr->sizeHintsFlags &= ~(PBaseSize|PResizeInc);
- if (wmPtr->width != -1) {
- wmPtr->width = winPtr->reqWidth + (wmPtr->width
- - wmPtr->reqGridWidth)*wmPtr->widthInc;
- wmPtr->height = winPtr->reqHeight + (wmPtr->height
- - wmPtr->reqGridHeight)*wmPtr->heightInc;
- }
- wmPtr->widthInc = 1;
- wmPtr->heightInc = 1;
- } else {
- if ((Tcl_GetInt(interp, argv[3], &reqWidth) != TCL_OK)
- || (Tcl_GetInt(interp, argv[4], &reqHeight) != TCL_OK)
- || (Tcl_GetInt(interp, argv[5], &widthInc) != TCL_OK)
- || (Tcl_GetInt(interp, argv[6], &heightInc) != TCL_OK)) {
- return TCL_ERROR;
- }
- if (reqWidth < 0) {
- Tcl_SetResult(interp, "baseWidth can't be < 0", TCL_STATIC);
- return TCL_ERROR;
- }
- if (reqHeight < 0) {
- Tcl_SetResult(interp, "baseHeight can't be < 0", TCL_STATIC);
- return TCL_ERROR;
- }
- if (widthInc < 0) {
- Tcl_SetResult(interp, "widthInc can't be < 0", TCL_STATIC);
- return TCL_ERROR;
- }
- if (heightInc < 0) {
- Tcl_SetResult(interp, "heightInc can't be < 0", TCL_STATIC);
- return TCL_ERROR;
- }
- Tk_SetGrid((Tk_Window) winPtr, reqWidth, reqHeight, widthInc,
- heightInc);
- }
- wmPtr->flags |= WM_UPDATE_SIZE_HINTS;
- goto updateGeom;
- } else if ((c == 'g') && (strncmp(argv[1], "group", length) == 0)
- && (length >= 3)) {
- Tk_Window tkwin2;
- WmInfo *wmPtr2;
+static int
+WmIconmaskCmd(tkwin, winPtr, interp, objc, objv)
+ Tk_Window tkwin; /* Main window of the application. */
+ TkWindow *winPtr; /* Toplevel to work with */
+ Tcl_Interp *interp; /* Current interpreter. */
+ int objc; /* Number of arguments. */
+ Tcl_Obj *CONST objv[]; /* Argument objects. */
+{
+ register WmInfo *wmPtr = winPtr->wmInfoPtr;
+ Pixmap pixmap;
+ char *argv3;
- if ((argc != 3) && (argc != 4)) {
- Tcl_AppendResult(interp, "wrong # arguments: must be \"",
- argv[0], " group window ?pathName?\"",
- (char *) NULL);
+ if ((objc != 3) && (objc != 4)) {
+ Tcl_WrongNumArgs(interp, 2, objv, "window ?bitmap?");
+ return TCL_ERROR;
+ }
+ if (objc == 3) {
+ if (wmPtr->hints.flags & IconMaskHint) {
+ Tcl_SetResult(interp, (char *)
+ Tk_NameOfBitmap(winPtr->display, wmPtr->hints.icon_mask),
+ TCL_STATIC);
+ }
+ return TCL_OK;
+ }
+ argv3 = Tcl_GetString(objv[3]);
+ if (*argv3 == '\0') {
+ if (wmPtr->hints.icon_mask != None) {
+ Tk_FreeBitmap(winPtr->display, wmPtr->hints.icon_mask);
+ }
+ wmPtr->hints.flags &= ~IconMaskHint;
+ } else {
+ pixmap = Tk_GetBitmap(interp, tkwin, argv3);
+ if (pixmap == None) {
return TCL_ERROR;
}
- if (argc == 3) {
- if (wmPtr->hints.flags & WindowGroupHint) {
- Tcl_SetResult(interp, wmPtr->leaderName, TCL_STATIC);
- }
- return TCL_OK;
+ wmPtr->hints.icon_mask = pixmap;
+ wmPtr->hints.flags |= IconMaskHint;
+ }
+ UpdateHints(winPtr);
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * WmIconnameCmd --
+ *
+ * This procedure is invoked to process the "wm iconname" Tcl command.
+ * See the user documentation for details on what it does.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+WmIconnameCmd(tkwin, winPtr, interp, objc, objv)
+ Tk_Window tkwin; /* Main window of the application. */
+ TkWindow *winPtr; /* Toplevel to work with */
+ Tcl_Interp *interp; /* Current interpreter. */
+ int objc; /* Number of arguments. */
+ Tcl_Obj *CONST objv[]; /* Argument objects. */
+{
+ register WmInfo *wmPtr = winPtr->wmInfoPtr;
+ char *argv3;
+ int length;
+
+ if (objc > 4) {
+ Tcl_WrongNumArgs(interp, 2, objv, "window ?newName?");
+ return TCL_ERROR;
+ }
+ if (objc == 3) {
+ Tcl_SetResult(interp,
+ ((wmPtr->iconName != NULL) ? wmPtr->iconName : ""),
+ TCL_STATIC);
+ return TCL_OK;
+ } else {
+ if (wmPtr->iconName != NULL) {
+ ckfree((char *) wmPtr->iconName);
}
- if (*argv[3] == '\0') {
- wmPtr->hints.flags &= ~WindowGroupHint;
- if (wmPtr->leaderName != NULL) {
- ckfree(wmPtr->leaderName);
- }
- wmPtr->leaderName = NULL;
- } else {
- tkwin2 = Tk_NameToWindow(interp, argv[3], tkwin);
- if (tkwin2 == NULL) {
- return TCL_ERROR;
- }
- while (!Tk_IsTopLevel(tkwin2)) {
- /*
- * Ensure that the group leader is actually a Tk toplevel.
- */
+ argv3 = Tcl_GetStringFromObj(objv[3], &length);
+ wmPtr->iconName = ckalloc((unsigned) (length + 1));
+ strcpy(wmPtr->iconName, argv3);
+ if (!(wmPtr->flags & WM_NEVER_MAPPED)) {
+ Tcl_DString ds;
- tkwin2 = Tk_Parent(tkwin2);
- }
- Tk_MakeWindowExist(tkwin2);
- wmPtr2 = ((TkWindow *) tkwin2)->wmInfoPtr;
- if (wmPtr2->wrapperPtr == NULL) {
- CreateWrapper(wmPtr2);
- }
- if (wmPtr->leaderName != NULL) {
- ckfree(wmPtr->leaderName);
- }
- wmPtr->hints.window_group = Tk_WindowId(wmPtr2->wrapperPtr);
- wmPtr->hints.flags |= WindowGroupHint;
- wmPtr->leaderName = ckalloc((unsigned) (strlen(argv[3])+1));
- strcpy(wmPtr->leaderName, argv[3]);
+ Tcl_UtfToExternalDString(NULL, wmPtr->iconName, -1, &ds);
+ XSetIconName(winPtr->display, wmPtr->wrapperPtr->window,
+ Tcl_DStringValue(&ds));
+ Tcl_DStringFree(&ds);
}
- UpdateHints(winPtr);
- } else if ((c == 'i') && (strncmp(argv[1], "iconbitmap", length) == 0)
- && (length >= 5)) {
- Pixmap pixmap;
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * WmIconpositionCmd --
+ *
+ * This procedure is invoked to process the "wm iconposition"
+ * Tcl command.
+ * See the user documentation for details on what it does.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
- if ((argc != 3) && (argc != 4)) {
- Tcl_AppendResult(interp, "wrong # arguments: must be \"",
- argv[0], " iconbitmap window ?bitmap?\"",
- (char *) NULL);
- return TCL_ERROR;
+static int
+WmIconpositionCmd(tkwin, winPtr, interp, objc, objv)
+ Tk_Window tkwin; /* Main window of the application. */
+ TkWindow *winPtr; /* Toplevel to work with */
+ Tcl_Interp *interp; /* Current interpreter. */
+ int objc; /* Number of arguments. */
+ Tcl_Obj *CONST objv[]; /* Argument objects. */
+{
+ register WmInfo *wmPtr = winPtr->wmInfoPtr;
+ int x, y;
+
+ if ((objc != 3) && (objc != 5)) {
+ Tcl_WrongNumArgs(interp, 2, objv, "window ?x y?");
+ return TCL_ERROR;
+ }
+ if (objc == 3) {
+ if (wmPtr->hints.flags & IconPositionHint) {
+ char buf[TCL_INTEGER_SPACE * 2];
+
+ sprintf(buf, "%d %d", wmPtr->hints.icon_x,
+ wmPtr->hints.icon_y);
+ Tcl_SetResult(interp, buf, TCL_VOLATILE);
}
- if (argc == 3) {
- if (wmPtr->hints.flags & IconPixmapHint) {
- Tcl_SetResult(interp,
- Tk_NameOfBitmap(winPtr->display, wmPtr->hints.icon_pixmap),
- TCL_STATIC);
- }
- return TCL_OK;
+ return TCL_OK;
+ }
+ if (*Tcl_GetString(objv[3]) == '\0') {
+ wmPtr->hints.flags &= ~IconPositionHint;
+ } else {
+ if ((Tcl_GetIntFromObj(interp, objv[3], &x) != TCL_OK)
+ || (Tcl_GetIntFromObj(interp, objv[4], &y) != TCL_OK)){
+ return TCL_ERROR;
}
- if (*argv[3] == '\0') {
- if (wmPtr->hints.icon_pixmap != None) {
- Tk_FreeBitmap(winPtr->display, wmPtr->hints.icon_pixmap);
- wmPtr->hints.icon_pixmap = None;
- }
- wmPtr->hints.flags &= ~IconPixmapHint;
- } else {
- pixmap = Tk_GetBitmap(interp, (Tk_Window) winPtr,
- Tk_GetUid(argv[3]));
- if (pixmap == None) {
- return TCL_ERROR;
- }
- wmPtr->hints.icon_pixmap = pixmap;
- wmPtr->hints.flags |= IconPixmapHint;
+ wmPtr->hints.icon_x = x;
+ wmPtr->hints.icon_y = y;
+ wmPtr->hints.flags |= IconPositionHint;
+ }
+ UpdateHints(winPtr);
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * WmIconwindowCmd --
+ *
+ * This procedure is invoked to process the "wm iconwindow" Tcl command.
+ * See the user documentation for details on what it does.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+WmIconwindowCmd(tkwin, winPtr, interp, objc, objv)
+ Tk_Window tkwin; /* Main window of the application. */
+ TkWindow *winPtr; /* Toplevel to work with */
+ Tcl_Interp *interp; /* Current interpreter. */
+ int objc; /* Number of arguments. */
+ Tcl_Obj *CONST objv[]; /* Argument objects. */
+{
+ register WmInfo *wmPtr = winPtr->wmInfoPtr;
+ Tk_Window tkwin2;
+ WmInfo *wmPtr2;
+ XSetWindowAttributes atts;
+
+ if ((objc != 3) && (objc != 4)) {
+ Tcl_WrongNumArgs(interp, 2, objv, "window ?pathName?");
+ return TCL_ERROR;
+ }
+ if (objc == 3) {
+ if (wmPtr->icon != NULL) {
+ Tcl_SetResult(interp, Tk_PathName(wmPtr->icon), TCL_STATIC);
}
- UpdateHints(winPtr);
- } else if ((c == 'i') && (strncmp(argv[1], "iconify", length) == 0)
- && (length >= 5)) {
- if (argc != 3) {
- Tcl_AppendResult(interp, "wrong # arguments: must be \"",
- argv[0], " iconify window\"", (char *) NULL);
- return TCL_ERROR;
+ return TCL_OK;
+ }
+ if (*Tcl_GetString(objv[3]) == '\0') {
+ wmPtr->hints.flags &= ~IconWindowHint;
+ if (wmPtr->icon != NULL) {
+ /*
+ * Remove the icon window relationship. In principle we
+ * should also re-enable button events for the window, but
+ * this doesn't work in general because the window manager
+ * is probably selecting on them (we'll get an error if
+ * we try to re-enable the events). So, just leave the
+ * icon window event-challenged; the user will have to
+ * recreate it if they want button events.
+ */
+
+ wmPtr2 = ((TkWindow *) wmPtr->icon)->wmInfoPtr;
+ wmPtr2->iconFor = NULL;
+ wmPtr2->withdrawn = 1;
+ wmPtr2->hints.initial_state = WithdrawnState;
}
- if (Tk_Attributes((Tk_Window) winPtr)->override_redirect) {
- Tcl_AppendResult(interp, "can't iconify \"", winPtr->pathName,
- "\": override-redirect flag is set", (char *) NULL);
+ wmPtr->icon = NULL;
+ } else {
+ if (TkGetWindowFromObj(interp, tkwin, objv[3], &tkwin2) != TCL_OK) {
return TCL_ERROR;
}
- if (wmPtr->master != None) {
- Tcl_AppendResult(interp, "can't iconify \"", winPtr->pathName,
- "\": it is a transient", (char *) NULL);
+ if (!Tk_IsTopLevel(tkwin2)) {
+ Tcl_AppendResult(interp, "can't use ", Tcl_GetString(objv[3]),
+ " as icon window: not at top level", (char *) NULL);
return TCL_ERROR;
}
- if (wmPtr->iconFor != NULL) {
- Tcl_AppendResult(interp, "can't iconify ", argv[2],
- ": it is an icon for ", Tk_PathName(wmPtr->iconFor),
- (char *) NULL);
+ wmPtr2 = ((TkWindow *) tkwin2)->wmInfoPtr;
+ if (wmPtr2->iconFor != NULL) {
+ Tcl_AppendResult(interp, Tcl_GetString(objv[3]),
+ " is already an icon for ",
+ Tk_PathName(wmPtr2->iconFor), (char *) NULL);
return TCL_ERROR;
}
- wmPtr->hints.initial_state = IconicState;
- if (wmPtr->flags & WM_NEVER_MAPPED) {
- return TCL_OK;
+ if (wmPtr->icon != NULL) {
+ WmInfo *wmPtr3 = ((TkWindow *) wmPtr->icon)->wmInfoPtr;
+ wmPtr3->iconFor = NULL;
+ wmPtr3->withdrawn = 1;
+ wmPtr3->hints.initial_state = WithdrawnState;
}
- if (wmPtr->withdrawn) {
- UpdateHints(winPtr);
- Tk_MapWindow((Tk_Window) winPtr);
- wmPtr->withdrawn = 0;
- } else {
- if (XIconifyWindow(winPtr->display, wmPtr->wrapperPtr->window,
- winPtr->screenNum) == 0) {
+
+ /*
+ * Disable button events in the icon window: some window
+ * managers (like olvwm) want to get the events themselves,
+ * but X only allows one application at a time to receive
+ * button events for a window.
+ */
+
+ atts.event_mask = Tk_Attributes(tkwin2)->event_mask
+ & ~ButtonPressMask;
+ Tk_ChangeWindowAttributes(tkwin2, CWEventMask, &atts);
+ Tk_MakeWindowExist(tkwin2);
+ if (wmPtr2->wrapperPtr == NULL) {
+ CreateWrapper(wmPtr2);
+ }
+ wmPtr->hints.icon_window = Tk_WindowId(wmPtr2->wrapperPtr);
+ wmPtr->hints.flags |= IconWindowHint;
+ wmPtr->icon = tkwin2;
+ wmPtr2->iconFor = (Tk_Window) winPtr;
+ if (!wmPtr2->withdrawn && !(wmPtr2->flags & WM_NEVER_MAPPED)) {
+ wmPtr2->withdrawn = 0;
+ if (XWithdrawWindow(Tk_Display(tkwin2),
+ Tk_WindowId(wmPtr2->wrapperPtr),
+ Tk_ScreenNumber(tkwin2)) == 0) {
Tcl_SetResult(interp,
- "couldn't send iconify message to window manager",
+ "couldn't send withdraw message to window manager",
TCL_STATIC);
return TCL_ERROR;
}
- WaitForMapNotify(winPtr, 0);
+ WaitForMapNotify((TkWindow *) tkwin2, 0);
}
- } else if ((c == 'i') && (strncmp(argv[1], "iconmask", length) == 0)
- && (length >= 5)) {
- Pixmap pixmap;
+ }
+ UpdateHints(winPtr);
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * WmMaxsizeCmd --
+ *
+ * This procedure is invoked to process the "wm maxsize" Tcl command.
+ * See the user documentation for details on what it does.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
- if ((argc != 3) && (argc != 4)) {
- Tcl_AppendResult(interp, "wrong # arguments: must be \"",
- argv[0], " iconmask window ?bitmap?\"",
- (char *) NULL);
- return TCL_ERROR;
- }
- if (argc == 3) {
- if (wmPtr->hints.flags & IconMaskHint) {
- Tcl_SetResult(interp,
- Tk_NameOfBitmap(winPtr->display, wmPtr->hints.icon_mask),
- TCL_STATIC);
- }
- return TCL_OK;
+static int
+WmMaxsizeCmd(tkwin, winPtr, interp, objc, objv)
+ Tk_Window tkwin; /* Main window of the application. */
+ TkWindow *winPtr; /* Toplevel to work with */
+ Tcl_Interp *interp; /* Current interpreter. */
+ int objc; /* Number of arguments. */
+ Tcl_Obj *CONST objv[]; /* Argument objects. */
+{
+ register WmInfo *wmPtr = winPtr->wmInfoPtr;
+ int width, height;
+
+ if ((objc != 3) && (objc != 5)) {
+ Tcl_WrongNumArgs(interp, 2, objv, "window ?width height?");
+ return TCL_ERROR;
+ }
+ if (objc == 3) {
+ char buf[TCL_INTEGER_SPACE * 2];
+
+ GetMaxSize(wmPtr, &width, &height);
+ sprintf(buf, "%d %d", width, height);
+ Tcl_SetResult(interp, buf, TCL_VOLATILE);
+ return TCL_OK;
+ }
+ if ((Tcl_GetIntFromObj(interp, objv[3], &width) != TCL_OK)
+ || (Tcl_GetIntFromObj(interp, objv[4], &height) != TCL_OK)) {
+ return TCL_ERROR;
+ }
+ wmPtr->maxWidth = width;
+ wmPtr->maxHeight = height;
+ wmPtr->flags |= WM_UPDATE_SIZE_HINTS;
+ WmUpdateGeom(wmPtr, winPtr);
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * WmMinsizeCmd --
+ *
+ * This procedure is invoked to process the "wm minsize" Tcl command.
+ * See the user documentation for details on what it does.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+WmMinsizeCmd(tkwin, winPtr, interp, objc, objv)
+ Tk_Window tkwin; /* Main window of the application. */
+ TkWindow *winPtr; /* Toplevel to work with */
+ Tcl_Interp *interp; /* Current interpreter. */
+ int objc; /* Number of arguments. */
+ Tcl_Obj *CONST objv[]; /* Argument objects. */
+{
+ register WmInfo *wmPtr = winPtr->wmInfoPtr;
+ int width, height;
+
+ if ((objc != 3) && (objc != 5)) {
+ Tcl_WrongNumArgs(interp, 2, objv, "window ?width height?");
+ return TCL_ERROR;
+ }
+ if (objc == 3) {
+ char buf[TCL_INTEGER_SPACE * 2];
+
+ sprintf(buf, "%d %d", wmPtr->minWidth, wmPtr->minHeight);
+ Tcl_SetResult(interp, buf, TCL_VOLATILE);
+ return TCL_OK;
+ }
+ if ((Tcl_GetIntFromObj(interp, objv[3], &width) != TCL_OK)
+ || (Tcl_GetIntFromObj(interp, objv[4], &height) != TCL_OK)) {
+ return TCL_ERROR;
+ }
+ wmPtr->minWidth = width;
+ wmPtr->minHeight = height;
+ wmPtr->flags |= WM_UPDATE_SIZE_HINTS;
+ WmUpdateGeom(wmPtr, winPtr);
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * WmOverrideredirectCmd --
+ *
+ * This procedure is invoked to process the "wm overrideredirect"
+ * Tcl command.
+ * See the user documentation for details on what it does.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+WmOverrideredirectCmd(tkwin, winPtr, interp, objc, objv)
+ Tk_Window tkwin; /* Main window of the application. */
+ TkWindow *winPtr; /* Toplevel to work with */
+ Tcl_Interp *interp; /* Current interpreter. */
+ int objc; /* Number of arguments. */
+ Tcl_Obj *CONST objv[]; /* Argument objects. */
+{
+ int boolean, curValue;
+ XSetWindowAttributes atts;
+
+ if ((objc != 3) && (objc != 4)) {
+ Tcl_WrongNumArgs(interp, 2, objv, "window ?boolean?");
+ return TCL_ERROR;
+ }
+ curValue = Tk_Attributes((Tk_Window) winPtr)->override_redirect;
+ if (objc == 3) {
+ Tcl_SetBooleanObj(Tcl_GetObjResult(interp), curValue);
+ return TCL_OK;
+ }
+ if (Tcl_GetBooleanFromObj(interp, objv[3], &boolean) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (curValue != boolean) {
+ /*
+ * Only do this if we are really changing value, because it
+ * causes some funky stuff to occur
+ */
+ atts.override_redirect = (boolean) ? True : False;
+ Tk_ChangeWindowAttributes((Tk_Window) winPtr, CWOverrideRedirect,
+ &atts);
+ if (winPtr->wmInfoPtr->wrapperPtr != NULL) {
+ Tk_ChangeWindowAttributes(
+ (Tk_Window) winPtr->wmInfoPtr->wrapperPtr,
+ CWOverrideRedirect, &atts);
}
- if (*argv[3] == '\0') {
- if (wmPtr->hints.icon_mask != None) {
- Tk_FreeBitmap(winPtr->display, wmPtr->hints.icon_mask);
- }
- wmPtr->hints.flags &= ~IconMaskHint;
- } else {
- pixmap = Tk_GetBitmap(interp, tkwin, Tk_GetUid(argv[3]));
- if (pixmap == None) {
- return TCL_ERROR;
- }
- wmPtr->hints.icon_mask = pixmap;
- wmPtr->hints.flags |= IconMaskHint;
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * WmPositionfromCmd --
+ *
+ * This procedure is invoked to process the "wm positionfrom"
+ * Tcl command.
+ * See the user documentation for details on what it does.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+WmPositionfromCmd(tkwin, winPtr, interp, objc, objv)
+ Tk_Window tkwin; /* Main window of the application. */
+ TkWindow *winPtr; /* Toplevel to work with */
+ Tcl_Interp *interp; /* Current interpreter. */
+ int objc; /* Number of arguments. */
+ Tcl_Obj *CONST objv[]; /* Argument objects. */
+{
+ register WmInfo *wmPtr = winPtr->wmInfoPtr;
+ static CONST char *optionStrings[] = {
+ "program", "user", (char *) NULL };
+ enum options {
+ OPT_PROGRAM, OPT_USER };
+ int index;
+
+ if ((objc != 3) && (objc != 4)) {
+ Tcl_WrongNumArgs(interp, 2, objv, "window ?user/program?");
+ return TCL_ERROR;
+ }
+ if (objc == 3) {
+ if (wmPtr->sizeHintsFlags & USPosition) {
+ Tcl_SetResult(interp, "user", TCL_STATIC);
+ } else if (wmPtr->sizeHintsFlags & PPosition) {
+ Tcl_SetResult(interp, "program", TCL_STATIC);
}
- UpdateHints(winPtr);
- } else if ((c == 'i') && (strncmp(argv[1], "iconname", length) == 0)
- && (length >= 5)) {
- if (argc > 4) {
- Tcl_AppendResult(interp, "wrong # arguments: must be \"",
- argv[0], " iconname window ?newName?\"", (char *) NULL);
+ return TCL_OK;
+ }
+ if (*Tcl_GetString(objv[3]) == '\0') {
+ wmPtr->sizeHintsFlags &= ~(USPosition|PPosition);
+ } else {
+ if (Tcl_GetIndexFromObj(interp, objv[3], optionStrings, "argument", 0,
+ &index) != TCL_OK) {
return TCL_ERROR;
}
- if (argc == 3) {
- Tcl_SetResult(interp,
- ((wmPtr->iconName != NULL) ? wmPtr->iconName : ""),
- TCL_STATIC);
- return TCL_OK;
+ if (index == OPT_USER) {
+ wmPtr->sizeHintsFlags &= ~PPosition;
+ wmPtr->sizeHintsFlags |= USPosition;
} else {
- if (wmPtr->iconName != NULL) {
- ckfree((char *) wmPtr->iconName);
- }
- wmPtr->iconName = ckalloc((unsigned) (strlen(argv[3]) + 1));
- strcpy(wmPtr->iconName, argv[3]);
- if (!(wmPtr->flags & WM_NEVER_MAPPED)) {
- Tcl_DString ds;
-
- Tcl_UtfToExternalDString(NULL, wmPtr->iconName, -1, &ds);
- XSetIconName(winPtr->display, wmPtr->wrapperPtr->window,
- Tcl_DStringValue(&ds));
- Tcl_DStringFree(&ds);
- }
+ wmPtr->sizeHintsFlags &= ~USPosition;
+ wmPtr->sizeHintsFlags |= PPosition;
}
- } else if ((c == 'i') && (strncmp(argv[1], "iconposition", length) == 0)
- && (length >= 5)) {
- int x, y;
+ }
+ wmPtr->flags |= WM_UPDATE_SIZE_HINTS;
+ WmUpdateGeom(wmPtr, winPtr);
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * WmProtocolCmd --
+ *
+ * This procedure is invoked to process the "wm protocol" Tcl command.
+ * See the user documentation for details on what it does.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
- if ((argc != 3) && (argc != 5)) {
- Tcl_AppendResult(interp, "wrong # arguments: must be \"",
- argv[0], " iconposition window ?x y?\"",
- (char *) NULL);
- return TCL_ERROR;
- }
- if (argc == 3) {
- if (wmPtr->hints.flags & IconPositionHint) {
- char buf[TCL_INTEGER_SPACE * 2];
+static int
+WmProtocolCmd(tkwin, winPtr, interp, objc, objv)
+ Tk_Window tkwin; /* Main window of the application. */
+ TkWindow *winPtr; /* Toplevel to work with */
+ Tcl_Interp *interp; /* Current interpreter. */
+ int objc; /* Number of arguments. */
+ Tcl_Obj *CONST objv[]; /* Argument objects. */
+{
+ register WmInfo *wmPtr = winPtr->wmInfoPtr;
+ register ProtocolHandler *protPtr, *prevPtr;
+ Atom protocol;
+ char *cmd;
+ int cmdLength;
- sprintf(buf, "%d %d", wmPtr->hints.icon_x,
- wmPtr->hints.icon_y);
- Tcl_SetResult(interp, buf, TCL_VOLATILE);
- }
- return TCL_OK;
+ if ((objc < 3) || (objc > 5)) {
+ Tcl_WrongNumArgs(interp, 2, objv, "window ?name? ?command?");
+ return TCL_ERROR;
+ }
+ if (objc == 3) {
+ /*
+ * Return a list of all defined protocols for the window.
+ */
+ for (protPtr = wmPtr->protPtr; protPtr != NULL;
+ protPtr = protPtr->nextPtr) {
+ Tcl_AppendElement(interp,
+ Tk_GetAtomName((Tk_Window) winPtr, protPtr->protocol));
}
- if (*argv[3] == '\0') {
- wmPtr->hints.flags &= ~IconPositionHint;
- } else {
- if ((Tcl_GetInt(interp, argv[3], &x) != TCL_OK)
- || (Tcl_GetInt(interp, argv[4], &y) != TCL_OK)){
- return TCL_ERROR;
+ return TCL_OK;
+ }
+ protocol = Tk_InternAtom((Tk_Window) winPtr, Tcl_GetString(objv[3]));
+ if (objc == 4) {
+ /*
+ * Return the command to handle a given protocol.
+ */
+ for (protPtr = wmPtr->protPtr; protPtr != NULL;
+ protPtr = protPtr->nextPtr) {
+ if (protPtr->protocol == protocol) {
+ Tcl_SetResult(interp, protPtr->command, TCL_STATIC);
+ return TCL_OK;
}
- wmPtr->hints.icon_x = x;
- wmPtr->hints.icon_y = y;
- wmPtr->hints.flags |= IconPositionHint;
- }
- UpdateHints(winPtr);
- } else if ((c == 'i') && (strncmp(argv[1], "iconwindow", length) == 0)
- && (length >= 5)) {
- Tk_Window tkwin2;
- WmInfo *wmPtr2;
- XSetWindowAttributes atts;
-
- if ((argc != 3) && (argc != 4)) {
- Tcl_AppendResult(interp, "wrong # arguments: must be \"",
- argv[0], " iconwindow window ?pathName?\"",
- (char *) NULL);
- return TCL_ERROR;
}
- if (argc == 3) {
- if (wmPtr->icon != NULL) {
- Tcl_SetResult(interp, Tk_PathName(wmPtr->icon), TCL_STATIC);
+ return TCL_OK;
+ }
+
+ /*
+ * Delete any current protocol handler, then create a new
+ * one with the specified command, unless the command is
+ * empty.
+ */
+
+ for (protPtr = wmPtr->protPtr, prevPtr = NULL; protPtr != NULL;
+ prevPtr = protPtr, protPtr = protPtr->nextPtr) {
+ if (protPtr->protocol == protocol) {
+ if (prevPtr == NULL) {
+ wmPtr->protPtr = protPtr->nextPtr;
+ } else {
+ prevPtr->nextPtr = protPtr->nextPtr;
}
- return TCL_OK;
+ Tcl_EventuallyFree((ClientData) protPtr, TCL_DYNAMIC);
+ break;
}
- if (*argv[3] == '\0') {
- wmPtr->hints.flags &= ~IconWindowHint;
- if (wmPtr->icon != NULL) {
- /*
- * Remove the icon window relationship. In principle we
- * should also re-enable button events for the window, but
- * this doesn't work in general because the window manager
- * is probably selecting on them (we'll get an error if
- * we try to re-enable the events). So, just leave the
- * icon window event-challenged; the user will have to
- * recreate it if they want button events.
- */
+ }
+ cmd = Tcl_GetStringFromObj(objv[4], &cmdLength);
+ if (cmdLength > 0) {
+ protPtr = (ProtocolHandler *) ckalloc(HANDLER_SIZE(cmdLength));
+ protPtr->protocol = protocol;
+ protPtr->nextPtr = wmPtr->protPtr;
+ wmPtr->protPtr = protPtr;
+ protPtr->interp = interp;
+ strcpy(protPtr->command, cmd);
+ }
+ if (!(wmPtr->flags & WM_NEVER_MAPPED)) {
+ UpdateWmProtocols(wmPtr);
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * WmResizableCmd --
+ *
+ * This procedure is invoked to process the "wm resizable" Tcl command.
+ * See the user documentation for details on what it does.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
- wmPtr2 = ((TkWindow *) wmPtr->icon)->wmInfoPtr;
- wmPtr2->iconFor = NULL;
- wmPtr2->withdrawn = 1;
- wmPtr2->hints.initial_state = WithdrawnState;
- }
- wmPtr->icon = NULL;
- } else {
- tkwin2 = Tk_NameToWindow(interp, argv[3], tkwin);
- if (tkwin2 == NULL) {
- return TCL_ERROR;
- }
- if (!Tk_IsTopLevel(tkwin2)) {
- Tcl_AppendResult(interp, "can't use ", argv[3],
- " as icon window: not at top level", (char *) NULL);
- return TCL_ERROR;
- }
- wmPtr2 = ((TkWindow *) tkwin2)->wmInfoPtr;
- if (wmPtr2->iconFor != NULL) {
- Tcl_AppendResult(interp, argv[3], " is already an icon for ",
- Tk_PathName(wmPtr2->iconFor), (char *) NULL);
- return TCL_ERROR;
- }
- if (wmPtr->icon != NULL) {
- WmInfo *wmPtr3 = ((TkWindow *) wmPtr->icon)->wmInfoPtr;
- wmPtr3->iconFor = NULL;
- wmPtr3->withdrawn = 1;
- wmPtr3->hints.initial_state = WithdrawnState;
- }
+static int
+WmResizableCmd(tkwin, winPtr, interp, objc, objv)
+ Tk_Window tkwin; /* Main window of the application. */
+ TkWindow *winPtr; /* Toplevel to work with */
+ Tcl_Interp *interp; /* Current interpreter. */
+ int objc; /* Number of arguments. */
+ Tcl_Obj *CONST objv[]; /* Argument objects. */
+{
+ register WmInfo *wmPtr = winPtr->wmInfoPtr;
+ int width, height;
- /*
- * Disable button events in the icon window: some window
- * managers (like olvwm) want to get the events themselves,
- * but X only allows one application at a time to receive
- * button events for a window.
- */
+ if ((objc != 3) && (objc != 5)) {
+ Tcl_WrongNumArgs(interp, 2, objv, "window ?width height?");
+ return TCL_ERROR;
+ }
+ if (objc == 3) {
+ char buf[TCL_INTEGER_SPACE * 2];
- atts.event_mask = Tk_Attributes(tkwin2)->event_mask
- & ~ButtonPressMask;
- Tk_ChangeWindowAttributes(tkwin2, CWEventMask, &atts);
- Tk_MakeWindowExist(tkwin2);
- if (wmPtr2->wrapperPtr == NULL) {
- CreateWrapper(wmPtr2);
- }
- wmPtr->hints.icon_window = Tk_WindowId(wmPtr2->wrapperPtr);
- wmPtr->hints.flags |= IconWindowHint;
- wmPtr->icon = tkwin2;
- wmPtr2->iconFor = (Tk_Window) winPtr;
- if (!wmPtr2->withdrawn && !(wmPtr2->flags & WM_NEVER_MAPPED)) {
- wmPtr2->withdrawn = 0;
- if (XWithdrawWindow(Tk_Display(tkwin2),
- Tk_WindowId(wmPtr2->wrapperPtr),
- Tk_ScreenNumber(tkwin2)) == 0) {
- Tcl_SetResult(interp,
- "couldn't send withdraw message to window manager",
- TCL_STATIC);
- return TCL_ERROR;
- }
- WaitForMapNotify((TkWindow *) tkwin2, 0);
- }
- }
- UpdateHints(winPtr);
- } else if ((c == 'm') && (strncmp(argv[1], "maxsize", length) == 0)
- && (length >= 2)) {
- int width, height;
- if ((argc != 3) && (argc != 5)) {
- Tcl_AppendResult(interp, "wrong # arguments: must be \"",
- argv[0], " maxsize window ?width height?\"", (char *) NULL);
- return TCL_ERROR;
- }
- if (argc == 3) {
- char buf[TCL_INTEGER_SPACE * 2];
-
- GetMaxSize(wmPtr, &width, &height);
- sprintf(buf, "%d %d", width, height);
- Tcl_SetResult(interp, buf, TCL_VOLATILE);
- return TCL_OK;
+ sprintf(buf, "%d %d",
+ (wmPtr->flags & WM_WIDTH_NOT_RESIZABLE) ? 0 : 1,
+ (wmPtr->flags & WM_HEIGHT_NOT_RESIZABLE) ? 0 : 1);
+ Tcl_SetResult(interp, buf, TCL_VOLATILE);
+ return TCL_OK;
+ }
+ if ((Tcl_GetBooleanFromObj(interp, objv[3], &width) != TCL_OK)
+ || (Tcl_GetBooleanFromObj(interp, objv[4], &height) != TCL_OK)) {
+ return TCL_ERROR;
+ }
+ if (width) {
+ wmPtr->flags &= ~WM_WIDTH_NOT_RESIZABLE;
+ } else {
+ wmPtr->flags |= WM_WIDTH_NOT_RESIZABLE;
+ }
+ if (height) {
+ wmPtr->flags &= ~WM_HEIGHT_NOT_RESIZABLE;
+ } else {
+ wmPtr->flags |= WM_HEIGHT_NOT_RESIZABLE;
+ }
+ wmPtr->flags |= WM_UPDATE_SIZE_HINTS;
+ WmUpdateGeom(wmPtr, winPtr);
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * WmSizefromCmd --
+ *
+ * This procedure is invoked to process the "wm sizefrom" Tcl command.
+ * See the user documentation for details on what it does.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+WmSizefromCmd(tkwin, winPtr, interp, objc, objv)
+ Tk_Window tkwin; /* Main window of the application. */
+ TkWindow *winPtr; /* Toplevel to work with */
+ Tcl_Interp *interp; /* Current interpreter. */
+ int objc; /* Number of arguments. */
+ Tcl_Obj *CONST objv[]; /* Argument objects. */
+{
+ register WmInfo *wmPtr = winPtr->wmInfoPtr;
+ static CONST char *optionStrings[] = {
+ "program", "user", (char *) NULL };
+ enum options {
+ OPT_PROGRAM, OPT_USER };
+ int index;
+
+ if ((objc != 3) && (objc != 4)) {
+ Tcl_WrongNumArgs(interp, 2, objv, "window ?user|program?");
+ return TCL_ERROR;
+ }
+ if (objc == 3) {
+ if (wmPtr->sizeHintsFlags & USSize) {
+ Tcl_SetResult(interp, "user", TCL_STATIC);
+ } else if (wmPtr->sizeHintsFlags & PSize) {
+ Tcl_SetResult(interp, "program", TCL_STATIC);
}
- if ((Tcl_GetInt(interp, argv[3], &width) != TCL_OK)
- || (Tcl_GetInt(interp, argv[4], &height) != TCL_OK)) {
+ return TCL_OK;
+ }
+
+ if (*Tcl_GetString(objv[3]) == '\0') {
+ wmPtr->sizeHintsFlags &= ~(USSize|PSize);
+ } else {
+ if (Tcl_GetIndexFromObj(interp, objv[3], optionStrings, "argument", 0,
+ &index) != TCL_OK) {
return TCL_ERROR;
}
- wmPtr->maxWidth = width;
- wmPtr->maxHeight = height;
- wmPtr->flags |= WM_UPDATE_SIZE_HINTS;
- goto updateGeom;
- } else if ((c == 'm') && (strncmp(argv[1], "minsize", length) == 0)
- && (length >= 2)) {
- int width, height;
- if ((argc != 3) && (argc != 5)) {
- Tcl_AppendResult(interp, "wrong # arguments: must be \"",
- argv[0], " minsize window ?width height?\"", (char *) NULL);
- return TCL_ERROR;
+ if (index == OPT_USER) {
+ wmPtr->sizeHintsFlags &= ~PSize;
+ wmPtr->sizeHintsFlags |= USSize;
+ } else { /* OPT_PROGRAM */
+ wmPtr->sizeHintsFlags &= ~USSize;
+ wmPtr->sizeHintsFlags |= PSize;
}
- if (argc == 3) {
- char buf[TCL_INTEGER_SPACE * 2];
+ }
+ wmPtr->flags |= WM_UPDATE_SIZE_HINTS;
+ WmUpdateGeom(wmPtr, winPtr);
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * WmStackorderCmd --
+ *
+ * This procedure is invoked to process the "wm stackorder" Tcl command.
+ * See the user documentation for details on what it does.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
- sprintf(buf, "%d %d", wmPtr->minWidth, wmPtr->minHeight);
- Tcl_SetResult(interp, buf, TCL_VOLATILE);
+static int
+WmStackorderCmd(tkwin, winPtr, interp, objc, objv)
+ Tk_Window tkwin; /* Main window of the application. */
+ TkWindow *winPtr; /* Toplevel to work with */
+ Tcl_Interp *interp; /* Current interpreter. */
+ int objc; /* Number of arguments. */
+ Tcl_Obj *CONST objv[]; /* Argument objects. */
+{
+ TkWindow **windows, **window_ptr;
+ static CONST char *optionStrings[] = {
+ "isabove", "isbelow", (char *) NULL };
+ enum options {
+ OPT_ISABOVE, OPT_ISBELOW };
+ int index;
+
+ if ((objc != 3) && (objc != 5)) {
+ Tcl_WrongNumArgs(interp, 2, objv, "window ?isabove|isbelow window?");
+ return TCL_ERROR;
+ }
+
+ if (objc == 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;
}
- if ((Tcl_GetInt(interp, argv[3], &width) != TCL_OK)
- || (Tcl_GetInt(interp, argv[4], &height) != TCL_OK)) {
- return TCL_ERROR;
- }
- wmPtr->minWidth = width;
- wmPtr->minHeight = height;
- wmPtr->flags |= WM_UPDATE_SIZE_HINTS;
- goto updateGeom;
- } else if ((c == 'o')
- && (strncmp(argv[1], "overrideredirect", length) == 0)) {
- int boolean, curValue;
- XSetWindowAttributes atts;
-
- if ((argc != 3) && (argc != 4)) {
- Tcl_AppendResult(interp, "wrong # arguments: must be \"",
- argv[0], " overrideredirect window ?boolean?\"",
- (char *) NULL);
+ } else {
+ TkWindow *winPtr2;
+ int index1=-1, index2=-1, result;
+
+ if (TkGetWindowFromObj(interp, tkwin, objv[4], (Tk_Window *) &winPtr2)
+ != TCL_OK) {
return TCL_ERROR;
}
- curValue = Tk_Attributes((Tk_Window) winPtr)->override_redirect;
- if (argc == 3) {
- Tcl_SetBooleanObj(Tcl_GetObjResult(interp), curValue);
- return TCL_OK;
- }
- if (Tcl_GetBoolean(interp, argv[3], &boolean) != TCL_OK) {
+
+ if (!Tk_IsTopLevel(winPtr2)) {
+ Tcl_AppendResult(interp, "window \"", winPtr2->pathName,
+ "\" isn't a top-level window", (char *) NULL);
return TCL_ERROR;
}
- if (curValue != boolean) {
- /*
- * Only do this if we are really changing value, because it
- * causes some funky stuff to occur
- */
- atts.override_redirect = (boolean) ? True : False;
- Tk_ChangeWindowAttributes((Tk_Window) winPtr, CWOverrideRedirect,
- &atts);
- if (winPtr->wmInfoPtr->wrapperPtr != NULL) {
- Tk_ChangeWindowAttributes(
- (Tk_Window) winPtr->wmInfoPtr->wrapperPtr,
- CWOverrideRedirect, &atts);
- }
- }
- } else if ((c == 'p') && (strncmp(argv[1], "positionfrom", length) == 0)
- && (length >= 2)) {
- if ((argc != 3) && (argc != 4)) {
- Tcl_AppendResult(interp, "wrong # arguments: must be \"",
- argv[0], " positionfrom window ?user/program?\"",
- (char *) NULL);
+
+ if (!Tk_IsMapped(winPtr)) {
+ Tcl_AppendResult(interp, "window \"", winPtr->pathName,
+ "\" isn't mapped", (char *) NULL);
return TCL_ERROR;
}
- if (argc == 3) {
- if (wmPtr->sizeHintsFlags & USPosition) {
- Tcl_SetResult(interp, "user", TCL_STATIC);
- } else if (wmPtr->sizeHintsFlags & PPosition) {
- Tcl_SetResult(interp, "program", TCL_STATIC);
- }
- return TCL_OK;
- }
- if (*argv[3] == '\0') {
- wmPtr->sizeHintsFlags &= ~(USPosition|PPosition);
- } else {
- c = argv[3][0];
- length = strlen(argv[3]);
- if ((c == 'u') && (strncmp(argv[3], "user", length) == 0)) {
- wmPtr->sizeHintsFlags &= ~PPosition;
- wmPtr->sizeHintsFlags |= USPosition;
- } else if ((c == 'p') && (strncmp(argv[3], "program", length) == 0)) {
- wmPtr->sizeHintsFlags &= ~USPosition;
- wmPtr->sizeHintsFlags |= PPosition;
- } else {
- Tcl_AppendResult(interp, "bad argument \"", argv[3],
- "\": must be program or user", (char *) NULL);
- return TCL_ERROR;
- }
- }
- wmPtr->flags |= WM_UPDATE_SIZE_HINTS;
- goto updateGeom;
- } else if ((c == 'p') && (strncmp(argv[1], "protocol", length) == 0)
- && (length >= 2)) {
- register ProtocolHandler *protPtr, *prevPtr;
- Atom protocol;
- int cmdLength;
-
- if ((argc < 3) || (argc > 5)) {
- Tcl_AppendResult(interp, "wrong # arguments: must be \"",
- argv[0], " protocol window ?name? ?command?\"",
- (char *) NULL);
+
+ if (!Tk_IsMapped(winPtr2)) {
+ Tcl_AppendResult(interp, "window \"", winPtr2->pathName,
+ "\" isn't mapped", (char *) NULL);
return TCL_ERROR;
}
- if (argc == 3) {
- /*
- * Return a list of all defined protocols for the window.
- */
- for (protPtr = wmPtr->protPtr; protPtr != NULL;
- protPtr = protPtr->nextPtr) {
- Tcl_AppendElement(interp,
- Tk_GetAtomName((Tk_Window) winPtr, protPtr->protocol));
- }
- return TCL_OK;
- }
- protocol = Tk_InternAtom((Tk_Window) winPtr, argv[3]);
- if (argc == 4) {
- /*
- * Return the command to handle a given protocol.
- */
- for (protPtr = wmPtr->protPtr; protPtr != NULL;
- protPtr = protPtr->nextPtr) {
- if (protPtr->protocol == protocol) {
- Tcl_SetResult(interp, protPtr->command, TCL_STATIC);
- return TCL_OK;
- }
- }
- return TCL_OK;
- }
/*
- * Delete any current protocol handler, then create a new
- * one with the specified command, unless the command is
- * empty.
+ * Lookup stacking order of all toplevels that are children
+ * of "." and find the position of winPtr and winPtr2
+ * in the stacking order.
*/
- for (protPtr = wmPtr->protPtr, prevPtr = NULL; protPtr != NULL;
- prevPtr = protPtr, protPtr = protPtr->nextPtr) {
- if (protPtr->protocol == protocol) {
- if (prevPtr == NULL) {
- wmPtr->protPtr = protPtr->nextPtr;
- } else {
- prevPtr->nextPtr = protPtr->nextPtr;
- }
- Tcl_EventuallyFree((ClientData) protPtr, TCL_DYNAMIC);
- break;
+ 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);
}
- cmdLength = strlen(argv[4]);
- if (cmdLength > 0) {
- protPtr = (ProtocolHandler *) ckalloc(HANDLER_SIZE(cmdLength));
- protPtr->protocol = protocol;
- protPtr->nextPtr = wmPtr->protPtr;
- wmPtr->protPtr = protPtr;
- protPtr->interp = interp;
- strcpy(protPtr->command, argv[4]);
+
+ if (Tcl_GetIndexFromObj(interp, objv[3], optionStrings, "argument", 0,
+ &index) != TCL_OK) {
+ return TCL_ERROR;
}
- if (!(wmPtr->flags & WM_NEVER_MAPPED)) {
- UpdateWmProtocols(wmPtr);
+ if (index == OPT_ISABOVE) {
+ result = index1 > index2;
+ } else { /* OPT_ISBELOW */
+ result = index1 < index2;
}
- } else if ((c == 'r') && (strncmp(argv[1], "resizable", length) == 0)) {
- int width, height;
+ Tcl_SetIntObj(Tcl_GetObjResult(interp), result);
+ return TCL_OK;
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * WmStateCmd --
+ *
+ * This procedure is invoked to process the "wm state" Tcl command.
+ * See the user documentation for details on what it does.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
- if ((argc != 3) && (argc != 5)) {
- Tcl_AppendResult(interp, "wrong # arguments: must be \"",
- argv[0], " resizable window ?width height?\"",
+static int
+WmStateCmd(tkwin, winPtr, interp, objc, objv)
+ Tk_Window tkwin; /* Main window of the application. */
+ TkWindow *winPtr; /* Toplevel to work with */
+ Tcl_Interp *interp; /* Current interpreter. */
+ int objc; /* Number of arguments. */
+ Tcl_Obj *CONST objv[]; /* Argument objects. */
+{
+ register WmInfo *wmPtr = winPtr->wmInfoPtr;
+ static CONST char *optionStrings[] = {
+ "normal", "iconic", "withdrawn", (char *) NULL };
+ enum options {
+ OPT_NORMAL, OPT_ICONIC, OPT_WITHDRAWN };
+ int index;
+
+ if ((objc < 3) || (objc > 4)) {
+ Tcl_WrongNumArgs(interp, 2, objv, "window ?state?");
+ return TCL_ERROR;
+ }
+ if (objc == 4) {
+ if (wmPtr->iconFor != NULL) {
+ Tcl_AppendResult(interp, "can't change state of ",
+ Tcl_GetString(objv[2]),
+ ": it is an icon for ", Tk_PathName(wmPtr->iconFor),
(char *) NULL);
return TCL_ERROR;
}
- if (argc == 3) {
- char buf[TCL_INTEGER_SPACE * 2];
- sprintf(buf, "%d %d",
- (wmPtr->flags & WM_WIDTH_NOT_RESIZABLE) ? 0 : 1,
- (wmPtr->flags & WM_HEIGHT_NOT_RESIZABLE) ? 0 : 1);
- Tcl_SetResult(interp, buf, TCL_VOLATILE);
- return TCL_OK;
- }
- if ((Tcl_GetBoolean(interp, argv[3], &width) != TCL_OK)
- || (Tcl_GetBoolean(interp, argv[4], &height) != TCL_OK)) {
+ if (Tcl_GetIndexFromObj(interp, objv[3], optionStrings, "argument", 0,
+ &index) != TCL_OK) {
return TCL_ERROR;
}
- if (width) {
- wmPtr->flags &= ~WM_WIDTH_NOT_RESIZABLE;
- } else {
- wmPtr->flags |= WM_WIDTH_NOT_RESIZABLE;
- }
- if (height) {
- wmPtr->flags &= ~WM_HEIGHT_NOT_RESIZABLE;
- } else {
- wmPtr->flags |= WM_HEIGHT_NOT_RESIZABLE;
- }
- wmPtr->flags |= WM_UPDATE_SIZE_HINTS;
- goto updateGeom;
- } else if ((c == 's') && (strncmp(argv[1], "sizefrom", length) == 0)
- && (length >= 2)) {
- if ((argc != 3) && (argc != 4)) {
- Tcl_AppendResult(interp, "wrong # arguments: must be \"",
- argv[0], " sizefrom window ?user|program?\"",
- (char *) NULL);
- return TCL_ERROR;
- }
- if (argc == 3) {
- if (wmPtr->sizeHintsFlags & USSize) {
- Tcl_SetResult(interp, "user", TCL_STATIC);
- } else if (wmPtr->sizeHintsFlags & PSize) {
- Tcl_SetResult(interp, "program", TCL_STATIC);
+
+ if (index == OPT_NORMAL) {
+ if (wmPtr->flags & WM_TRANSIENT_WITHDRAWN) {
+ wmPtr->flags &= ~WM_TRANSIENT_WITHDRAWN;
}
- return TCL_OK;
- }
- if (*argv[3] == '\0') {
- wmPtr->sizeHintsFlags &= ~(USSize|PSize);
- } else {
- c = argv[3][0];
- length = strlen(argv[3]);
- if ((c == 'u') && (strncmp(argv[3], "user", length) == 0)) {
- wmPtr->sizeHintsFlags &= ~PSize;
- wmPtr->sizeHintsFlags |= USSize;
- } else if ((c == 'p')
- && (strncmp(argv[3], "program", length) == 0)) {
- wmPtr->sizeHintsFlags &= ~USSize;
- wmPtr->sizeHintsFlags |= PSize;
- } else {
- Tcl_AppendResult(interp, "bad argument \"", argv[3],
- "\": must be program or user", (char *) NULL);
+ (void) TkpWmSetState(winPtr, NormalState);
+ } else if (index == OPT_ICONIC) {
+ if (Tk_Attributes((Tk_Window) winPtr)->override_redirect) {
+ Tcl_AppendResult(interp, "can't iconify \"",
+ winPtr->pathName,
+ "\": override-redirect flag is set",
+ (char *) NULL);
return TCL_ERROR;
}
- }
- wmPtr->flags |= WM_UPDATE_SIZE_HINTS;
- goto updateGeom;
- } else if ((c == 's') && (strncmp(argv[1], "state", length) == 0)
- && (length >= 2)) {
- if ((argc < 3) || (argc > 4)) {
- Tcl_AppendResult(interp, "wrong # arguments: must be \"",
- argv[0], " state window ?state?\"", (char *) NULL);
- return TCL_ERROR;
- }
- if (argc == 4) {
- if (wmPtr->iconFor != NULL) {
- Tcl_AppendResult(interp, "can't change state of ", argv[2],
- ": it is an icon for ", Tk_PathName(wmPtr->iconFor),
- (char *) NULL);
+ if (wmPtr->masterPtr != NULL) {
+ Tcl_AppendResult(interp, "can't iconify \"",
+ winPtr->pathName,
+ "\": it is a transient", (char *) NULL);
return TCL_ERROR;
}
-
- c = argv[3][0];
- length = strlen(argv[3]);
-
- if ((c == 'n') && (strncmp(argv[3], "normal", length) == 0)) {
- wmPtr->hints.initial_state = NormalState;
- wmPtr->withdrawn = 0;
- if (wmPtr->flags & WM_NEVER_MAPPED) {
- return TCL_OK;
- }
- UpdateHints(winPtr);
- Tk_MapWindow((Tk_Window) winPtr);
- } else if ((c == 'i')
- && (strncmp(argv[3], "iconic", length) == 0)) {
- if (Tk_Attributes((Tk_Window) winPtr)->override_redirect) {
- Tcl_AppendResult(interp, "can't iconify \"",
- winPtr->pathName,
- "\": override-redirect flag is set",
- (char *) NULL);
- return TCL_ERROR;
- }
- if (wmPtr->master != None) {
- Tcl_AppendResult(interp, "can't iconify \"",
- winPtr->pathName,
- "\": it is a transient", (char *) NULL);
- return TCL_ERROR;
- }
- wmPtr->hints.initial_state = IconicState;
- if (wmPtr->flags & WM_NEVER_MAPPED) {
- return TCL_OK;
- }
- if (wmPtr->withdrawn) {
- UpdateHints(winPtr);
- Tk_MapWindow((Tk_Window) winPtr);
- wmPtr->withdrawn = 0;
- } else {
- if (XIconifyWindow(winPtr->display,
- wmPtr->wrapperPtr->window,
- winPtr->screenNum) == 0) {
- Tcl_SetResult(interp, "couldn't send iconify message to window manager", TCL_STATIC);
- return TCL_ERROR;
- }
- WaitForMapNotify(winPtr, 0);
- }
- } else if ((c == 'w')
- && (strncmp(argv[3], "withdrawn", length) == 0)) {
- wmPtr->hints.initial_state = WithdrawnState;
- wmPtr->withdrawn = 1;
- if (wmPtr->flags & WM_NEVER_MAPPED) {
- return TCL_OK;
- }
- if (XWithdrawWindow(winPtr->display, wmPtr->wrapperPtr->window,
- winPtr->screenNum) == 0) {
- Tcl_SetResult(interp,
- "couldn't send withdraw message to window manager",
- TCL_STATIC);
- return TCL_ERROR;
- }
- WaitForMapNotify(winPtr, 0);
- } else {
- Tcl_AppendResult(interp, "bad argument \"", argv[3],
- "\": must be normal, iconic or withdrawn",
- (char *) NULL);
+ if (TkpWmSetState(winPtr, IconicState) == 0) {
+ Tcl_SetResult(interp,
+ "couldn't send iconify message to window manager",
+ TCL_STATIC);
return TCL_ERROR;
}
- } else {
- if (wmPtr->iconFor != NULL) {
- Tcl_SetResult(interp, "icon", TCL_STATIC);
- } else if (wmPtr->withdrawn) {
- Tcl_SetResult(interp, "withdrawn", TCL_STATIC);
- } else if (Tk_IsMapped((Tk_Window) winPtr)
- || ((wmPtr->flags & WM_NEVER_MAPPED)
- && (wmPtr->hints.initial_state == NormalState))) {
- Tcl_SetResult(interp, "normal", TCL_STATIC);
- } else {
- Tcl_SetResult(interp, "iconic", TCL_STATIC);
+ } else { /* OPT_WITHDRAWN */
+ if (wmPtr->masterPtr != NULL) {
+ wmPtr->flags |= WM_TRANSIENT_WITHDRAWN;
+ }
+ if (TkpWmSetState(winPtr, WithdrawnState) == 0) {
+ Tcl_SetResult(interp,
+ "couldn't send withdraw message to window manager",
+ TCL_STATIC);
+ return TCL_ERROR;
}
}
- } else if ((c == 't') && (strncmp(argv[1], "title", length) == 0)
- && (length >= 2)) {
- if (argc > 4) {
- Tcl_AppendResult(interp, "wrong # arguments: must be \"",
- argv[0], " title window ?newTitle?\"", (char *) NULL);
- return TCL_ERROR;
- }
- if (argc == 3) {
- Tcl_SetResult(interp,
- ((wmPtr->title != NULL) ? wmPtr->title : winPtr->nameUid),
- TCL_STATIC);
- return TCL_OK;
+ } else {
+ if (wmPtr->iconFor != NULL) {
+ Tcl_SetResult(interp, "icon", TCL_STATIC);
+ } else if (wmPtr->withdrawn) {
+ Tcl_SetResult(interp, "withdrawn", TCL_STATIC);
+ } else if (Tk_IsMapped((Tk_Window) winPtr)
+ || ((wmPtr->flags & WM_NEVER_MAPPED)
+ && (wmPtr->hints.initial_state == NormalState))) {
+ Tcl_SetResult(interp, "normal", TCL_STATIC);
} else {
- if (wmPtr->title != NULL) {
- ckfree((char *) wmPtr->title);
- }
- wmPtr->title = ckalloc((unsigned) (strlen(argv[3]) + 1));
- strcpy(wmPtr->title, argv[3]);
- if (!(wmPtr->flags & WM_NEVER_MAPPED)) {
- XTextProperty textProp;
- Tcl_DString ds;
-
- Tcl_UtfToExternalDString(NULL, wmPtr->title, -1, &ds);
- if (XStringListToTextProperty(&(Tcl_DStringValue(&ds)), 1,
- &textProp) != 0) {
- XSetWMName(winPtr->display, wmPtr->wrapperPtr->window,
- &textProp);
- XFree((char *) textProp.value);
- }
- Tcl_DStringFree(&ds);
- }
+ Tcl_SetResult(interp, "iconic", TCL_STATIC);
}
- } else if ((c == 't') && (strncmp(argv[1], "transient", length) == 0)
- && (length >= 3)) {
- Tk_Window master;
- WmInfo *wmPtr2;
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * WmTitleCmd --
+ *
+ * This procedure is invoked to process the "wm title" Tcl command.
+ * See the user documentation for details on what it does.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
- if ((argc != 3) && (argc != 4)) {
- Tcl_AppendResult(interp, "wrong # arguments: must be \"",
- argv[0], " transient window ?master?\"", (char *) NULL);
- return TCL_ERROR;
+static int
+WmTitleCmd(tkwin, winPtr, interp, objc, objv)
+ Tk_Window tkwin; /* Main window of the application. */
+ TkWindow *winPtr; /* Toplevel to work with */
+ Tcl_Interp *interp; /* Current interpreter. */
+ int objc; /* Number of arguments. */
+ Tcl_Obj *CONST objv[]; /* Argument objects. */
+{
+ register WmInfo *wmPtr = winPtr->wmInfoPtr;
+ char *argv3;
+ int length;
+
+ if (objc > 4) {
+ Tcl_WrongNumArgs(interp, 2, objv, "window ?newTitle?");
+ return TCL_ERROR;
+ }
+ if (objc == 3) {
+ Tcl_SetResult(interp, (char *)
+ ((wmPtr->title != NULL) ? wmPtr->title : winPtr->nameUid),
+ TCL_STATIC);
+ return TCL_OK;
+ } else {
+ if (wmPtr->title != NULL) {
+ ckfree((char *) wmPtr->title);
}
- if (argc == 3) {
- if (wmPtr->master != None) {
- Tcl_SetResult(interp, wmPtr->masterWindowName, TCL_STATIC);
+ argv3 = Tcl_GetStringFromObj(objv[3], &length);
+ wmPtr->title = ckalloc((unsigned) (length + 1));
+ strcpy(wmPtr->title, argv3);
+
+ if (!(wmPtr->flags & WM_NEVER_MAPPED)) {
+ XTextProperty textProp;
+ Tcl_DString ds;
+
+ Tcl_UtfToExternalDString(NULL, wmPtr->title, -1, &ds);
+ if (XStringListToTextProperty(&(Tcl_DStringValue(&ds)), 1,
+ &textProp) != 0) {
+ XSetWMName(winPtr->display, wmPtr->wrapperPtr->window,
+ &textProp);
+ XFree((char *) textProp.value);
}
- return TCL_OK;
+ Tcl_DStringFree(&ds);
}
- if (argv[3][0] == '\0') {
- wmPtr->master = None;
- if (wmPtr->masterWindowName != NULL) {
- ckfree(wmPtr->masterWindowName);
- }
- wmPtr->masterWindowName = NULL;
- } else {
- master = Tk_NameToWindow(interp, argv[3], tkwin);
- if (master == NULL) {
- return TCL_ERROR;
- }
- while (!Tk_IsTopLevel(master)) {
- /*
- * Ensure that the master window is actually a Tk toplevel.
- */
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * WmTransientCmd --
+ *
+ * This procedure is invoked to process the "wm transient" Tcl command.
+ * See the user documentation for details on what it does.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
- master = Tk_Parent(master);
- }
- Tk_MakeWindowExist(master);
- wmPtr2 = ((TkWindow *) master)->wmInfoPtr;
- if (wmPtr2->wrapperPtr == NULL) {
- CreateWrapper(wmPtr2);
- }
- wmPtr->master = Tk_WindowId(wmPtr2->wrapperPtr);
- if (wmPtr->masterWindowName != NULL) {
- ckfree((char *) wmPtr->masterWindowName);
- }
- wmPtr->masterWindowName = ckalloc((unsigned) (strlen(argv[3])+1));
- strcpy(wmPtr->masterWindowName, argv[3]);
+static int
+WmTransientCmd(tkwin, winPtr, interp, objc, objv)
+ Tk_Window tkwin; /* Main window of the application. */
+ TkWindow *winPtr; /* Toplevel to work with */
+ Tcl_Interp *interp; /* Current interpreter. */
+ int objc; /* Number of arguments. */
+ Tcl_Obj *CONST objv[]; /* Argument objects. */
+{
+ register WmInfo *wmPtr = winPtr->wmInfoPtr;
+ TkWindow *masterPtr = wmPtr->masterPtr;
+ WmInfo *wmPtr2;
+
+ if ((objc != 3) && (objc != 4)) {
+ Tcl_WrongNumArgs(interp, 2, objv, "window ?master?");
+ return TCL_ERROR;
+ }
+ if (objc == 3) {
+ if (masterPtr != NULL) {
+ Tcl_SetResult(interp, Tk_PathName(masterPtr), TCL_STATIC);
}
- if (!(wmPtr->flags & WM_NEVER_MAPPED)) {
- XSetTransientForHint(winPtr->display, wmPtr->wrapperPtr->window,
- wmPtr->master);
+ return TCL_OK;
+ }
+ if (Tcl_GetString(objv[3])[0] == '\0') {
+ if (masterPtr != NULL) {
+ /*
+ * If we had a master, tell them that we aren't tied
+ * to them anymore
+ */
+
+ masterPtr->wmInfoPtr->numTransients--;
+ Tk_DeleteEventHandler((Tk_Window) masterPtr,
+ StructureNotifyMask,
+ WmWaitMapProc, (ClientData) winPtr);
+
+ /* FIXME: Need a call like Win32's UpdateWrapper() so
+ we can recreate the wrapper and get rid of the
+ transient window decorations. */
}
- } else if ((c == 'w') && (strncmp(argv[1], "withdraw", length) == 0)
- && (length >= 2)) {
- if (argc != 3) {
- Tcl_AppendResult(interp, "wrong # arguments: must be \"",
- argv[0], " withdraw window\"", (char *) NULL);
+
+ wmPtr->masterPtr = NULL;
+ } else {
+ if (TkGetWindowFromObj(interp, tkwin, objv[3],
+ (Tk_Window *) &masterPtr) != TCL_OK) {
return TCL_ERROR;
}
+ while (!Tk_TopWinHierarchy(masterPtr)) {
+ /*
+ * Ensure that the master window is actually a Tk toplevel.
+ */
+
+ masterPtr = masterPtr->parentPtr;
+ }
+ Tk_MakeWindowExist((Tk_Window) masterPtr);
+
if (wmPtr->iconFor != NULL) {
- Tcl_AppendResult(interp, "can't withdraw ", argv[2],
- ": it is an icon for ", Tk_PathName(wmPtr->iconFor),
+ Tcl_AppendResult(interp, "can't make \"",
+ Tcl_GetString(objv[2]),
+ "\" a transient: it is an icon for ",
+ Tk_PathName(wmPtr->iconFor),
(char *) NULL);
return TCL_ERROR;
}
- wmPtr->hints.initial_state = WithdrawnState;
- wmPtr->withdrawn = 1;
- if (wmPtr->flags & WM_NEVER_MAPPED) {
- return TCL_OK;
+
+ wmPtr2 = masterPtr->wmInfoPtr;
+ if (wmPtr2->wrapperPtr == NULL) {
+ CreateWrapper(wmPtr2);
}
- if (XWithdrawWindow(winPtr->display, wmPtr->wrapperPtr->window,
- winPtr->screenNum) == 0) {
- Tcl_SetResult(interp,
- "couldn't send withdraw message to window manager",
- TCL_STATIC);
+
+ if (wmPtr2->iconFor != NULL) {
+ Tcl_AppendResult(interp, "can't make \"",
+ Tcl_GetString(objv[3]),
+ "\" a master: it is an icon for ",
+ Tk_PathName(wmPtr2->iconFor),
+ (char *) NULL);
return TCL_ERROR;
}
- WaitForMapNotify(winPtr, 0);
- } else {
- Tcl_AppendResult(interp, "unknown or ambiguous option \"", argv[1],
- "\": must be aspect, client, command, deiconify, ",
- "focusmodel, frame, geometry, grid, group, iconbitmap, ",
- "iconify, iconmask, iconname, iconposition, ",
- "iconwindow, maxsize, minsize, overrideredirect, ",
- "positionfrom, protocol, resizable, sizefrom, state, title, ",
- "transient, or withdraw",
+
+ if (masterPtr == winPtr) {
+ Tcl_AppendResult(interp, "can't make \"", Tk_PathName(winPtr),
+ "\" its own master",
+ (char *) NULL);
+ return TCL_ERROR;
+ } else if (masterPtr != wmPtr->masterPtr) {
+ /*
+ * Remove old master map/unmap binding before setting
+ * the new master. The event handler will ensure that
+ * transient states reflect the state of the master.
+ */
+
+ if (wmPtr->masterPtr != NULL) {
+ wmPtr->masterPtr->wmInfoPtr->numTransients--;
+ Tk_DeleteEventHandler((Tk_Window) wmPtr->masterPtr,
+ StructureNotifyMask,
+ WmWaitMapProc, (ClientData) winPtr);
+ }
+
+ masterPtr->wmInfoPtr->numTransients++;
+ Tk_CreateEventHandler((Tk_Window) masterPtr,
+ StructureNotifyMask,
+ WmWaitMapProc, (ClientData) winPtr);
+
+ wmPtr->masterPtr = masterPtr;
+ }
+ }
+ if (!(wmPtr->flags & WM_NEVER_MAPPED)) {
+ if (wmPtr->masterPtr != NULL && !Tk_IsMapped(wmPtr->masterPtr)) {
+ if (TkpWmSetState(winPtr, WithdrawnState) == 0) {
+ Tcl_SetResult(interp,
+ "couldn't send withdraw message to window manager",
+ TCL_STATIC);
+ return TCL_ERROR;
+ }
+ } else {
+ Window xwin = (wmPtr->masterPtr == NULL) ? None :
+ wmPtr->masterPtr->wmInfoPtr->wrapperPtr->window;
+ XSetTransientForHint(winPtr->display, wmPtr->wrapperPtr->window,
+ xwin);
+ }
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * WmWithdrawCmd --
+ *
+ * This procedure is invoked to process the "wm withdraw" Tcl command.
+ * See the user documentation for details on what it does.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+WmWithdrawCmd(tkwin, winPtr, interp, objc, objv)
+ Tk_Window tkwin; /* Main window of the application. */
+ TkWindow *winPtr; /* Toplevel to work with */
+ Tcl_Interp *interp; /* Current interpreter. */
+ int objc; /* Number of arguments. */
+ Tcl_Obj *CONST objv[]; /* Argument objects. */
+{
+ register WmInfo *wmPtr = winPtr->wmInfoPtr;
+
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "window");
+ return TCL_ERROR;
+ }
+ if (wmPtr->iconFor != NULL) {
+ Tcl_AppendResult(interp, "can't withdraw ", Tcl_GetString(objv[2]),
+ ": it is an icon for ", Tk_PathName(wmPtr->iconFor),
(char *) NULL);
return TCL_ERROR;
}
+ if (wmPtr->masterPtr != NULL) {
+ wmPtr->flags |= WM_TRANSIENT_WITHDRAWN;
+ }
+ if (TkpWmSetState(winPtr, WithdrawnState) == 0) {
+ Tcl_SetResult(interp,
+ "couldn't send withdraw message to window manager",
+ TCL_STATIC);
+ return TCL_ERROR;
+ }
return TCL_OK;
+}
- updateGeom:
+/*
+ * Invoked by those wm subcommands that affect geometry.
+ * Schedules a geometry update.
+ */
+static void
+WmUpdateGeom(wmPtr, winPtr)
+ WmInfo *wmPtr;
+ TkWindow *winPtr;
+{
if (!(wmPtr->flags & (WM_UPDATE_PENDING|WM_NEVER_MAPPED))) {
Tcl_DoWhenIdle(UpdateGeometryInfo, (ClientData) winPtr);
wmPtr->flags |= WM_UPDATE_PENDING;
}
- return TCL_OK;
+}
+
+/*
+ * Invoked when a MapNotify or UnmapNotify event is delivered for a
+ * toplevel that is the master of a transient toplevel.
+ */
+static void
+WmWaitMapProc(clientData, eventPtr)
+ ClientData clientData; /* Pointer to window. */
+ XEvent *eventPtr; /* Information about event. */
+{
+ TkWindow *winPtr = (TkWindow *) clientData;
+ TkWindow *masterPtr = winPtr->wmInfoPtr->masterPtr;
+
+ if (masterPtr == NULL)
+ return;
+
+ if (eventPtr->type == MapNotify) {
+ if (!(winPtr->wmInfoPtr->flags & WM_TRANSIENT_WITHDRAWN))
+ (void) TkpWmSetState(winPtr, NormalState);
+ } else if (eventPtr->type == UnmapNotify) {
+ (void) TkpWmSetState(winPtr, WithdrawnState);
+ }
}
/*
@@ -2011,7 +3225,7 @@ Tk_SetGrid(tkwin, reqWidth, reqHeight, widthInc, heightInc)
* information.
*/
- while (!(winPtr->flags & TK_TOP_LEVEL)) {
+ while (!(winPtr->flags & TK_TOP_HIERARCHY)) {
winPtr = winPtr->parentPtr;
if (winPtr == NULL) {
/*
@@ -2022,6 +3236,9 @@ Tk_SetGrid(tkwin, reqWidth, reqHeight, widthInc, heightInc)
}
}
wmPtr = winPtr->wmInfoPtr;
+ if (wmPtr == NULL) {
+ return;
+ }
if ((wmPtr->gridWin != NULL) && (wmPtr->gridWin != tkwin)) {
return;
@@ -2032,7 +3249,7 @@ Tk_SetGrid(tkwin, reqWidth, reqHeight, widthInc, heightInc)
&& (wmPtr->widthInc == widthInc)
&& (wmPtr->heightInc == heightInc)
&& ((wmPtr->sizeHintsFlags & (PBaseSize|PResizeInc))
- == (PBaseSize|PResizeInc) )) {
+ == (PBaseSize|PResizeInc))) {
return;
}
@@ -2053,7 +3270,7 @@ Tk_SetGrid(tkwin, reqWidth, reqHeight, widthInc, heightInc)
wmPtr->height = -1;
}
- /*
+ /*
* Set the new gridding information, and start the process of passing
* all of this information to the window manager.
*/
@@ -2103,7 +3320,7 @@ Tk_UnsetGrid(tkwin)
* information.
*/
- while (!(winPtr->flags & TK_TOP_LEVEL)) {
+ while (!(winPtr->flags & TK_TOP_HIERARCHY)) {
winPtr = winPtr->parentPtr;
if (winPtr == NULL) {
/*
@@ -2114,6 +3331,10 @@ Tk_UnsetGrid(tkwin)
}
}
wmPtr = winPtr->wmInfoPtr;
+ if (wmPtr == NULL) {
+ return;
+ }
+
if (tkwin != wmPtr->gridWin) {
return;
}
@@ -2165,7 +3386,7 @@ ConfigureEvent(wmPtr, configEventPtr)
TkDisplay *dispPtr = wmPtr->winPtr->dispPtr;
Tk_ErrorHandler handler;
- /*
+ /*
* Update size information from the event. There are a couple of
* tricky points here:
*
@@ -2181,7 +3402,7 @@ ConfigureEvent(wmPtr, configEventPtr)
if (((wrapperPtr->changes.width != configEventPtr->width)
|| (wrapperPtr->changes.height != configEventPtr->height))
&& !(wmPtr->flags & WM_SYNC_PENDING)){
- if (dispPtr->wmTracing) {
+ if (dispPtr->flags & TK_DISPLAY_WM_TRACING) {
printf("TopLevelEventProc: user changed %s size to %dx%d\n",
winPtr->pathName, configEventPtr->width,
configEventPtr->height);
@@ -2245,12 +3466,13 @@ ConfigureEvent(wmPtr, configEventPtr)
wmPtr->configHeight = configEventPtr->height;
}
- if (dispPtr->wmTracing) {
- printf("ConfigureEvent: %s x = %d y = %d, width = %d, height = %d",
+ if (dispPtr->flags & TK_DISPLAY_WM_TRACING) {
+ printf("ConfigureEvent: %s x = %d y = %d, width = %d, height = %d\n",
winPtr->pathName, configEventPtr->x, configEventPtr->y,
configEventPtr->width, configEventPtr->height);
- printf(" send_event = %d, serial = %ld\n", configEventPtr->send_event,
- configEventPtr->serial);
+ printf(" send_event = %d, serial = %ld (win %p, wrapper %p)\n",
+ configEventPtr->send_event, configEventPtr->serial,
+ winPtr, wrapperPtr);
}
wrapperPtr->changes.width = configEventPtr->width;
wrapperPtr->changes.height = configEventPtr->height;
@@ -2274,6 +3496,12 @@ ConfigureEvent(wmPtr, configEventPtr)
* there is a parent shrink-wrapped around the window.
*/
+ if (dispPtr->flags & TK_DISPLAY_WM_TRACING) {
+ printf(" %s parent == %p, above %p\n",
+ winPtr->pathName, (void *) wmPtr->reparent,
+ (void *) configEventPtr->above);
+ }
+
if ((wmPtr->reparent == None) || !ComputeReparentGeometry(wmPtr)) {
wmPtr->parentWidth = configEventPtr->width
+ 2*configEventPtr->border_width;
@@ -2377,7 +3605,7 @@ ReparentEvent(wmPtr, reparentEventPtr)
&& (actualType == XA_WINDOW))) {
if ((actualFormat == 32) && (numItems == 1)) {
vRoot = wmPtr->vRoot = *virtualRootPtr;
- } else if (dispPtr->wmTracing) {
+ } else if (dispPtr->flags & TK_DISPLAY_WM_TRACING) {
printf("%s format %d numItems %ld\n",
"ReparentEvent got bogus VROOT property:", actualFormat,
numItems);
@@ -2386,9 +3614,9 @@ ReparentEvent(wmPtr, reparentEventPtr)
}
Tk_DeleteErrorHandler(handler);
- if (dispPtr->wmTracing) {
- printf("ReparentEvent: %s reparented to 0x%x, vRoot = 0x%x\n",
- wmPtr->winPtr->pathName,
+ if (dispPtr->flags & TK_DISPLAY_WM_TRACING) {
+ printf("ReparentEvent: %s (%p) reparented to 0x%x, vRoot = 0x%x\n",
+ wmPtr->winPtr->pathName, wmPtr->winPtr,
(unsigned int) reparentEventPtr->parent, (unsigned int) vRoot);
}
@@ -2411,6 +3639,8 @@ ReparentEvent(wmPtr, reparentEventPtr)
wmPtr->xInParent = wmPtr->yInParent = 0;
wrapperPtr->changes.x = reparentEventPtr->x;
wrapperPtr->changes.y = reparentEventPtr->y;
+ wmPtr->winPtr->changes.x = reparentEventPtr->x;
+ wmPtr->winPtr->changes.y = reparentEventPtr->y + wmPtr->menuHeight;
return;
}
@@ -2428,8 +3658,8 @@ ReparentEvent(wmPtr, reparentEventPtr)
(Tk_ErrorProc *) NULL, (ClientData) NULL);
wmPtr->reparent = reparentEventPtr->parent;
while (1) {
- if (XQueryTree(wrapperPtr->display, wmPtr->reparent, &dummy2, &ancestor,
- &children, &dummy) == 0) {
+ if (XQueryTree(wrapperPtr->display, wmPtr->reparent, &dummy2,
+ &ancestor, &children, &dummy) == 0) {
Tk_DeleteErrorHandler(handler);
goto noReparent;
}
@@ -2536,8 +3766,8 @@ ComputeReparentGeometry(wmPtr)
*/
if (!(wmPtr->flags & WM_MOVE_PENDING)
- && ((wmPtr->wrapperPtr->changes.x != (x + wmPtr->xInParent))
- || (wmPtr->wrapperPtr->changes.y != (y + wmPtr->yInParent)))) {
+ && ((wrapperPtr->changes.x != (x + wmPtr->xInParent))
+ || (wrapperPtr->changes.y != (y + wmPtr->yInParent)))) {
wmPtr->x = x;
if (wmPtr->flags & WM_NEGATIVE_X) {
wmPtr->x = wmPtr->vRootWidth - (wmPtr->x + wmPtr->parentWidth);
@@ -2548,12 +3778,13 @@ ComputeReparentGeometry(wmPtr)
}
}
- wmPtr->wrapperPtr->changes.x = x + wmPtr->xInParent;
- wmPtr->wrapperPtr->changes.y = y + wmPtr->yInParent;
- if (dispPtr->wmTracing) {
- printf("wrapperPtr coords %d,%d, wmPtr coords %d,%d, offsets %d %d\n",
- wrapperPtr->changes.x, wrapperPtr->changes.y,
- wmPtr->x, wmPtr->y, wmPtr->xInParent, wmPtr->yInParent);
+ wrapperPtr->changes.x = x + wmPtr->xInParent;
+ wrapperPtr->changes.y = y + wmPtr->yInParent;
+ if (dispPtr->flags & TK_DISPLAY_WM_TRACING) {
+ printf("wrapperPtr %p coords %d,%d\n",
+ wrapperPtr, wrapperPtr->changes.x, wrapperPtr->changes.y);
+ printf(" wmPtr %p coords %d,%d, offsets %d %d\n",
+ wmPtr, wmPtr->x, wmPtr->y, wmPtr->xInParent, wmPtr->yInParent);
}
return 1;
}
@@ -2597,13 +3828,13 @@ WrapperEventProc(clientData, eventPtr)
* Tk_DestroyWindow will try to destroy the window, but of course
* it's already gone.
*/
-
+
handler = Tk_CreateErrorHandler(wmPtr->winPtr->display, -1, -1, -1,
(Tk_ErrorProc *) NULL, (ClientData) NULL);
Tk_DestroyWindow((Tk_Window) wmPtr->winPtr);
Tk_DeleteErrorHandler(handler);
}
- if (dispPtr->wmTracing) {
+ if (dispPtr->flags & TK_DISPLAY_WM_TRACING) {
printf("TopLevelEventProc: %s deleted\n", wmPtr->winPtr->pathName);
}
} else if (eventPtr->type == ConfigureNotify) {
@@ -2851,7 +4082,8 @@ UpdateGeometryInfo(clientData)
serial = NextRequest(winPtr->display);
height += wmPtr->menuHeight;
if (wmPtr->flags & WM_MOVE_PENDING) {
- if ((x == winPtr->changes.x) && (y == winPtr->changes.y)
+ if ((x + wmPtr->xInParent == winPtr->changes.x) &&
+ (y + wmPtr->yInParent + wmPtr->menuHeight == winPtr->changes.y)
&& (width == wmPtr->wrapperPtr->changes.width)
&& (height == wmPtr->wrapperPtr->changes.height)) {
/*
@@ -2866,7 +4098,7 @@ UpdateGeometryInfo(clientData)
}
wmPtr->configWidth = width;
wmPtr->configHeight = height;
- if (winPtr->dispPtr->wmTracing) {
+ if (winPtr->dispPtr->flags & TK_DISPLAY_WM_TRACING) {
printf("UpdateGeometryInfo moving to %d %d, resizing to %d x %d,\n",
x, y, width, height);
}
@@ -2887,8 +4119,9 @@ UpdateGeometryInfo(clientData)
}
wmPtr->configWidth = width;
wmPtr->configHeight = height;
- if (winPtr->dispPtr->wmTracing) {
- printf("UpdateGeometryInfo resizing to %d x %d\n", width, height);
+ if (winPtr->dispPtr->flags & TK_DISPLAY_WM_TRACING) {
+ printf("UpdateGeometryInfo resizing %p to %d x %d\n",
+ (void *)wmPtr->wrapperPtr->window, width, height);
}
XResizeWindow(winPtr->display, wmPtr->wrapperPtr->window,
(unsigned) width, (unsigned) height);
@@ -2899,7 +4132,7 @@ UpdateGeometryInfo(clientData)
* It is possible that the window's overall size has not changed
* but the menu size has.
*/
-
+
Tk_MoveResizeWindow(wmPtr->menubar, 0, 0,
wmPtr->wrapperPtr->changes.width, wmPtr->menuHeight);
XResizeWindow(winPtr->display, wmPtr->wrapperPtr->window,
@@ -3084,11 +4317,10 @@ WaitForConfigureNotify(winPtr, serial)
while (!gotConfig) {
wmPtr->flags |= WM_SYNC_PENDING;
- code = WaitForEvent(winPtr->display, wmPtr->wrapperPtr->window,
- ConfigureNotify, &event);
+ code = WaitForEvent(winPtr->display, wmPtr, ConfigureNotify, &event);
wmPtr->flags &= ~WM_SYNC_PENDING;
if (code != TCL_OK) {
- if (winPtr->dispPtr->wmTracing) {
+ if (winPtr->dispPtr->flags & TK_DISPLAY_WM_TRACING) {
printf("WaitForConfigureNotify giving up on %s\n",
winPtr->pathName);
}
@@ -3100,7 +4332,7 @@ WaitForConfigureNotify(winPtr, serial)
}
}
wmPtr->flags &= ~WM_MOVE_PENDING;
- if (winPtr->dispPtr->wmTracing) {
+ if (winPtr->dispPtr->flags & TK_DISPLAY_WM_TRACING) {
printf("WaitForConfigureNotify finished with %s, serial %ld\n",
winPtr->pathName, serial);
}
@@ -3131,9 +4363,9 @@ WaitForConfigureNotify(winPtr, serial)
*/
static int
-WaitForEvent(display, window, type, eventPtr)
+WaitForEvent(display, wmInfoPtr, type, eventPtr)
Display *display; /* Display event is coming from. */
- Window window; /* Window for which event is desired. */
+ WmInfo *wmInfoPtr; /* Window for which event is desired. */
int type; /* Type of event that is wanted. */
XEvent *eventPtr; /* Place to store event. */
{
@@ -3149,7 +4381,7 @@ WaitForEvent(display, window, type, eventPtr)
*/
info.display = display;
- info.window = window;
+ info.wmInfoPtr = wmInfoPtr;
info.type = type;
info.eventPtr = eventPtr;
info.foundEvent = 0;
@@ -3203,7 +4435,8 @@ WaitRestrictProc(clientData, eventPtr)
if (eventPtr->type == ReparentNotify) {
return TK_PROCESS_EVENT;
}
- if ((eventPtr->xany.window != infoPtr->window)
+ if (((eventPtr->xany.window != infoPtr->wmInfoPtr->wrapperPtr->window)
+ && (eventPtr->xany.window != infoPtr->wmInfoPtr->reparent))
|| (eventPtr->xany.display != infoPtr->display)) {
return TK_DEFER_EVENT;
}
@@ -3265,7 +4498,7 @@ WaitForMapNotify(winPtr, mapped)
break;
}
wmPtr->flags |= WM_SYNC_PENDING;
- code = WaitForEvent(winPtr->display, wmPtr->wrapperPtr->window,
+ code = WaitForEvent(winPtr->display, wmPtr,
mapped ? MapNotify : UnmapNotify, &event);
wmPtr->flags &= ~WM_SYNC_PENDING;
if (code != TCL_OK) {
@@ -3276,15 +4509,16 @@ WaitForMapNotify(winPtr, mapped)
* just quit.
*/
- if (winPtr->dispPtr->wmTracing) {
+ if (winPtr->dispPtr->flags & TK_DISPLAY_WM_TRACING) {
printf("WaitForMapNotify giving up on %s\n", winPtr->pathName);
}
break;
}
}
wmPtr->flags &= ~WM_MOVE_PENDING;
- if (winPtr->dispPtr->wmTracing) {
- printf("WaitForMapNotify finished with %s\n", winPtr->pathName);
+ if (winPtr->dispPtr->flags & TK_DISPLAY_WM_TRACING) {
+ printf("WaitForMapNotify finished with %s (winPtr %p, wmPtr %p)\n",
+ winPtr->pathName, winPtr, wmPtr);
}
}
@@ -3525,7 +4759,7 @@ Tk_GetRootCoords(tkwin, xPtr, yPtr)
if (root == None) {
root = RootWindowOfScreen(Tk_Screen((Tk_Window)winPtr));
}
- XTranslateCoordinates(winPtr->display, winPtr->window,
+ XTranslateCoordinates(winPtr->display, winPtr->window,
root, 0, 0, &rootX, &rootY, &dummyChild);
x += rootX;
y += rootY;
@@ -3638,7 +4872,7 @@ Tk_CoordsToWindow(rootX, rootY, tkwin)
Tk_DeleteErrorHandler(handler);
return NULL;
}
- for (wmPtr = (WmInfo *) dispPtr->firstWmPtr; wmPtr != NULL;
+ for (wmPtr = (WmInfo *) dispPtr->firstWmPtr; wmPtr != NULL;
wmPtr = wmPtr->nextPtr) {
if (wmPtr->reparent == child) {
goto gotToplevel;
@@ -3708,7 +4942,7 @@ Tk_CoordsToWindow(rootX, rootY, tkwin)
nextPtr = NULL;
for (childPtr = winPtr->childList; childPtr != NULL;
childPtr = childPtr->nextPtr) {
- if (!Tk_IsMapped(childPtr) || (childPtr->flags & TK_TOP_LEVEL)) {
+ if (!Tk_IsMapped(childPtr) || (childPtr->flags & TK_TOP_HIERARCHY)) {
continue;
}
if (childPtr->flags & TK_REPARENTED) {
@@ -3804,7 +5038,7 @@ UpdateVRootGeometry(wmPtr)
(unsigned int *) &wmPtr->vRootWidth,
(unsigned int *) &wmPtr->vRootHeight, (unsigned int *) &bd,
&dummy);
- if (winPtr->dispPtr->wmTracing) {
+ if (winPtr->dispPtr->flags & TK_DISPLAY_WM_TRACING) {
printf("UpdateVRootGeometry: x = %d, y = %d, width = %d, ",
wmPtr->vRootX, wmPtr->vRootY, wmPtr->vRootWidth);
printf("height = %d, status = %d\n", wmPtr->vRootHeight, status);
@@ -3858,10 +5092,18 @@ Tk_GetVRootGeometry(tkwin, xPtr, yPtr, widthPtr, heightPtr)
* information for that window.
*/
- while (!(winPtr->flags & TK_TOP_LEVEL) && (winPtr->parentPtr != NULL)) {
+ while (!(winPtr->flags & TK_TOP_HIERARCHY) && (winPtr->parentPtr != NULL)) {
winPtr = winPtr->parentPtr;
}
wmPtr = winPtr->wmInfoPtr;
+ if (wmPtr == NULL) {
+ /* Punt. */
+ *xPtr = 0;
+ *yPtr = 0;
+ *widthPtr = 0;
+ *heightPtr = 0;
+ }
+
/*
* Make sure that the geometry information is up-to-date, then copy
@@ -4019,7 +5261,7 @@ TkWmProtocolEventProc(winPtr, eventPtr)
register ProtocolHandler *protPtr;
Atom protocol;
int result;
- char *protocolName;
+ CONST char *protocolName;
Tcl_Interp *interp;
wmPtr = winPtr->wmInfoPtr;
@@ -4070,6 +5312,139 @@ 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.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static 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) &&
+ !Tk_IsEmbedded(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;
+ if (numChildren) {
+ XFree((char *) children);
+ }
+ }
+
+ done:
+ Tcl_DeleteHashTable(&table);
+ return windows;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
* TkWmRestackToplevel --
*
* This procedure restacks a top-level window.
@@ -4079,8 +5454,6 @@ TkWmProtocolEventProc(winPtr, eventPtr)
*
* Side effects:
* WinPtr gets restacked as specified by aboveBelow and otherPtr.
- * This procedure doesn't return until the restack has taken
- * effect and the ConfigureNotify event for it has been received.
*
*----------------------------------------------------------------------
*/
@@ -4095,192 +5468,45 @@ TkWmRestackToplevel(winPtr, aboveBelow, otherPtr)
* above or below *all* siblings. */
{
XWindowChanges changes;
- XWindowAttributes atts;
unsigned int mask;
- Window window, dummy1, dummy2, vRoot;
- Window *children;
- unsigned int numChildren;
- int i;
- int desiredIndex = 0; /* Initialized to stop gcc warnings. */
- int ourIndex = 0; /* Initialized to stop gcc warnings. */
- unsigned long serial;
- XEvent event;
- int diff;
- Tk_ErrorHandler handler;
TkWindow *wrapperPtr;
+ memset(&changes, 0, sizeof(XWindowChanges));
changes.stack_mode = aboveBelow;
- changes.sibling = None;
mask = CWStackMode;
- if (winPtr->window == None) {
- Tk_MakeWindowExist((Tk_Window) winPtr);
- }
- if (winPtr->wmInfoPtr->flags & WM_NEVER_MAPPED) {
- /*
- * Can't set stacking order properly until the window is on the
- * screen (mapping it may give it a reparent window), so make sure
- * it's on the screen.
- */
-
- TkWmMapWindow(winPtr);
- }
- wrapperPtr = winPtr->wmInfoPtr->wrapperPtr;
- window = (winPtr->wmInfoPtr->reparent != None)
- ? winPtr->wmInfoPtr->reparent : wrapperPtr->window;
- if (otherPtr != NULL) {
- if (otherPtr->window == None) {
- Tk_MakeWindowExist((Tk_Window) otherPtr);
- }
- if (otherPtr->wmInfoPtr->flags & WM_NEVER_MAPPED) {
- TkWmMapWindow(otherPtr);
- }
- changes.sibling = (otherPtr->wmInfoPtr->reparent != None)
- ? otherPtr->wmInfoPtr->reparent
- : otherPtr->wmInfoPtr->wrapperPtr->window;
- mask = CWStackMode|CWSibling;
- }
/*
- * Before actually reconfiguring the window, see if it's already
- * in the right place. If so then don't reconfigure it. The
- * reason for this extra work is that some window managers will
- * ignore the reconfigure request if the window is already in
- * the right place, causing a long delay in WaitForConfigureNotify
- * while it times out. Special note: if the window is almost in
- * the right place, and the only windows between it and the right
- * place aren't mapped, then we don't reconfigure it either, for
- * the same reason.
+ * Make sure that winPtr and its wrapper window have been created.
*/
-
- vRoot = winPtr->wmInfoPtr->vRoot;
- if (vRoot == None) {
- vRoot = RootWindowOfScreen(Tk_Screen((Tk_Window) winPtr));
+ if (winPtr->wmInfoPtr->flags & WM_NEVER_MAPPED) {
+ TkWmMapWindow(winPtr);
}
- if (XQueryTree(winPtr->display, vRoot, &dummy1, &dummy2,
- &children, &numChildren) != 0) {
- /*
- * Find where our window is in the stacking order, and
- * compute the desired location in the stacking order.
- */
-
- for (i = 0; i < numChildren; i++) {
- if (children[i] == window) {
- ourIndex = i;
- }
- if (children[i] == changes.sibling) {
- desiredIndex = i;
- }
- }
- if (mask & CWSibling) {
- if (aboveBelow == Above) {
- if (desiredIndex < ourIndex) {
- desiredIndex += 1;
- }
- } else {
- if (desiredIndex > ourIndex) {
- desiredIndex -= 1;
- }
- }
- } else {
- if (aboveBelow == Above) {
- desiredIndex = numChildren-1;
- } else {
- desiredIndex = 0;
- }
- }
+ wrapperPtr = winPtr->wmInfoPtr->wrapperPtr;
+ if (otherPtr != NULL) {
/*
- * See if there are any mapped windows between where we are
- * and where we want to be.
+ * The window is to be restacked with respect to another toplevel.
+ * Make sure it has been created as well.
*/
-
- handler = Tk_CreateErrorHandler(winPtr->display, -1, -1, -1,
- (Tk_ErrorProc *) NULL, (ClientData) NULL);
- while (desiredIndex != ourIndex) {
- if ((XGetWindowAttributes(winPtr->display, children[desiredIndex],
- &atts) != 0) && (atts.map_state != IsUnmapped)) {
- break;
- }
- if (desiredIndex < ourIndex) {
- desiredIndex++;
- } else {
- desiredIndex--;
- }
- }
- Tk_DeleteErrorHandler(handler);
- XFree((char *) children);
- if (ourIndex == desiredIndex) {
- return;
+ if (otherPtr->wmInfoPtr->flags & WM_NEVER_MAPPED) {
+ TkWmMapWindow(otherPtr);
}
+ changes.sibling = otherPtr->wmInfoPtr->wrapperPtr->window;
+ mask |= CWSibling;
}
/*
- * Reconfigure the window. This tricky because of two things:
- * (a) Some window managers, like olvwm, insist that we raise
- * or lower the toplevel window itself, as opposed to its
- * decorative frame. Attempts to raise or lower the frame
- * are ignored.
- * (b) If the raise or lower is relative to a sibling, X will
- * generate an error unless we work with the frames (the
- * toplevels themselves aren't siblings).
- * Fortunately, the procedure XReconfigureWMWindow is supposed
- * to handle all of this stuff, so be careful to use it instead
- * of XConfigureWindow.
+ * Reconfigure the window. Note that we use XReconfigureWMWindow
+ * instead of XConfigureWindow, in order to handle the case
+ * where the window is to be restacked with respect to another toplevel.
+ * See [ICCCM] 4.1.5 "Configuring the Window" and XReconfigureWMWindow(3)
+ * for details.
*/
- serial = NextRequest(winPtr->display);
- if (window != wrapperPtr->window) {
- /*
- * We're going to have to wait for events on a window that
- * Tk doesn't own, so we have to tell X specially that we
- * want to get events on that window. To make matters worse,
- * it's possible that the window doesn't exist anymore (e.g.
- * the toplevel could have been withdrawn) so ignore events
- * occurring during the request.
- */
-
- handler = Tk_CreateErrorHandler(winPtr->display, -1, -1, -1,
- (Tk_ErrorProc *) NULL, (ClientData) NULL);
- XSelectInput(winPtr->display, window, StructureNotifyMask);
- Tk_DeleteErrorHandler(handler);
- }
XReconfigureWMWindow(winPtr->display, wrapperPtr->window,
Tk_ScreenNumber((Tk_Window) winPtr), mask, &changes);
-
- /*
- * Wait for the reconfiguration to complete. If we don't wait, then
- * the window may not restack for a while and the application might
- * observe it before it has restacked. Waiting for the reconfiguration
- * is tricky if winPtr has been reparented, since the window getting
- * the event isn't one that Tk owns.
- */
-
- if (window == wrapperPtr->window) {
- WaitForConfigureNotify(winPtr, serial);
- } else {
- while (1) {
- if (WaitForEvent(winPtr->display, window, ConfigureNotify,
- &event) != TCL_OK) {
- break;
- }
- diff = event.xconfigure.serial - serial;
- if (diff >= 0) {
- break;
- }
- }
-
- /*
- * Ignore errors that occur when we are de-selecting events on
- * window, since it's possible that the window doesn't exist
- * anymore (see comment above previous call to XSelectInput).
- */
-
- handler = Tk_CreateErrorHandler(winPtr->display, -1, -1, -1,
- (Tk_ErrorProc *) NULL, (ClientData) NULL);
- XSelectInput(winPtr->display, window, (long) 0);
- Tk_DeleteErrorHandler(handler);
- }
}
+
/*
*----------------------------------------------------------------------
@@ -4327,10 +5553,14 @@ TkWmAddToColormapWindows(winPtr)
return;
}
- if (topPtr->flags & TK_TOP_LEVEL) {
+ if (topPtr->flags & TK_TOP_HIERARCHY) {
break;
}
}
+ if (topPtr->wmInfoPtr == NULL) {
+ return;
+ }
+
if (topPtr->wmInfoPtr->flags & WM_COLORMAPS_EXPLICIT) {
return;
}
@@ -4427,7 +5657,7 @@ TkWmRemoveFromColormapWindows(winPtr)
return;
}
- if (topPtr->flags & TK_TOP_LEVEL) {
+ if (topPtr->flags & TK_TOP_HIERARCHY) {
break;
}
}
@@ -4439,6 +5669,10 @@ TkWmRemoveFromColormapWindows(winPtr)
return;
}
+ if (topPtr->wmInfoPtr == NULL) {
+ return;
+ }
+
if (topPtr->wmInfoPtr->wrapperPtr == NULL) {
CreateWrapper(topPtr->wmInfoPtr);
}
@@ -4614,7 +5848,7 @@ TkpMakeMenuWindow(tkwin, transient)
XSetWindowAttributes atts;
TkWindow *wrapperPtr;
- if (!Tk_IsTopLevel(tkwin)) {
+ if (!Tk_HasWrapper(tkwin)) {
return;
}
wmPtr = ((TkWindow *) tkwin)->wmInfoPtr;
@@ -4724,9 +5958,6 @@ CreateWrapper(wmPtr)
wrapperPtr->mainPtr->refCount++;
wrapperPtr->dirtyAtts = 0;
wrapperPtr->dirtyChanges = 0;
-#ifdef TK_USE_INPUT_METHODS
- wrapperPtr->inputContext = NULL;
-#endif /* TK_USE_INPUT_METHODS */
wrapperPtr->wmInfoPtr = wmPtr;
/*
@@ -5038,3 +6269,68 @@ UpdateCommand(winPtr)
ckfree((char *) cmdArgv);
ckfree((char *) offsets);
}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkpWmSetState --
+ *
+ * Sets the window manager state for the wrapper window of a
+ * given toplevel window.
+ *
+ * Results:
+ * 0 on error, 1 otherwise
+ *
+ * Side effects:
+ * May minimize, restore, or withdraw a window.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TkpWmSetState(winPtr, state)
+ TkWindow *winPtr; /* Toplevel window to operate on. */
+ int state; /* One of IconicState, NormalState,
+ * or WithdrawnState. */
+{
+ WmInfo *wmPtr = winPtr->wmInfoPtr;
+
+ if (state == WithdrawnState) {
+ wmPtr->hints.initial_state = WithdrawnState;
+ wmPtr->withdrawn = 1;
+ if (wmPtr->flags & WM_NEVER_MAPPED) {
+ return 1;
+ }
+ if (XWithdrawWindow(winPtr->display, wmPtr->wrapperPtr->window,
+ winPtr->screenNum) == 0) {
+ return 0;
+ }
+ WaitForMapNotify(winPtr, 0);
+ } else if (state == NormalState) {
+ wmPtr->hints.initial_state = NormalState;
+ wmPtr->withdrawn = 0;
+ if (wmPtr->flags & WM_NEVER_MAPPED) {
+ return 1;
+ }
+ UpdateHints(winPtr);
+ Tk_MapWindow((Tk_Window) winPtr);
+ } else if (state == IconicState) {
+ wmPtr->hints.initial_state = IconicState;
+ if (wmPtr->flags & WM_NEVER_MAPPED) {
+ return 1;
+ }
+ if (wmPtr->withdrawn) {
+ UpdateHints(winPtr);
+ Tk_MapWindow((Tk_Window) winPtr);
+ wmPtr->withdrawn = 0;
+ } else {
+ if (XIconifyWindow(winPtr->display, wmPtr->wrapperPtr->window,
+ winPtr->screenNum) == 0) {
+ return 0;
+ }
+ WaitForMapNotify(winPtr, 0);
+ }
+ }
+
+ return 1;
+}