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.c458
1 files changed, 339 insertions, 119 deletions
diff --git a/tk/unix/tkUnixWm.c b/tk/unix/tkUnixWm.c
index 4251c52ab23..98e4861f044 100644
--- a/tk/unix/tkUnixWm.c
+++ b/tk/unix/tkUnixWm.c
@@ -8,7 +8,6 @@
*
* Copyright (c) 1991-1994 The Regents of the University of California.
* Copyright (c) 1994-1997 Sun Microsystems, Inc.
- * Copyright (c) 1998 by Scriptics Corporation.
*
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
@@ -267,21 +266,10 @@ typedef struct TkWmInfo {
/*
* This module keeps a list of all top-level windows, primarily to
- * simplify the job of Tk_CoordsToWindow.
+ * simplify the job of Tk_CoordsToWindow. The list is called
+ * firstWmPtr and is stored in the TkDisplay structure.
*/
-static WmInfo *firstWmPtr = NULL; /* Points to first top-level window. */
-
-
-/*
- * The variable below is used to enable or disable tracing in this
- * module. If tracing is enabled, then information is printed on
- * standard output about interesting interactions with the window
- * manager.
- */
-
-static int wmTracing = 0;
-
/*
* The following structures are the official type records for geometry
* management of top-level and menubar windows.
@@ -337,6 +325,7 @@ static void ReparentEvent _ANSI_ARGS_((WmInfo *wmPtr,
XReparentEvent *eventPtr));
static void TopLevelReqProc _ANSI_ARGS_((ClientData dummy,
Tk_Window tkwin));
+static void UpdateCommand _ANSI_ARGS_((TkWindow *winPtr));
static void UpdateGeometryInfo _ANSI_ARGS_((
ClientData clientData));
static void UpdateHints _ANSI_ARGS_((TkWindow *winPtr));
@@ -378,6 +367,7 @@ TkWmNewWindow(winPtr)
TkWindow *winPtr; /* Newly-created top-level window. */
{
register WmInfo *wmPtr;
+ TkDisplay *dispPtr = winPtr->dispPtr;
wmPtr = (WmInfo *) ckalloc(sizeof(WmInfo));
wmPtr->winPtr = winPtr;
@@ -433,8 +423,8 @@ TkWmNewWindow(winPtr)
wmPtr->cmdArgv = NULL;
wmPtr->clientMachine = NULL;
wmPtr->flags = WM_NEVER_MAPPED;
- wmPtr->nextPtr = firstWmPtr;
- firstWmPtr = wmPtr;
+ wmPtr->nextPtr = (WmInfo *) dispPtr->firstWmPtr;
+ dispPtr->firstWmPtr = wmPtr;
winPtr->wmInfoPtr = wmPtr;
UpdateVRootGeometry(wmPtr);
@@ -480,6 +470,8 @@ TkWmMapWindow(winPtr)
char *string;
if (wmPtr->flags & WM_NEVER_MAPPED) {
+ Tcl_DString ds;
+
wmPtr->flags &= ~WM_NEVER_MAPPED;
/*
@@ -498,16 +490,22 @@ TkWmMapWindow(winPtr)
*/
string = (wmPtr->title != NULL) ? wmPtr->title : winPtr->nameUid;
- if (XStringListToTextProperty(&string, 1, &textProp) != 0) {
+ Tcl_UtfToExternalDString(NULL, string, -1, &ds);
+ string = Tcl_DStringValue(&ds);
+ if (XStringListToTextProperty(&(Tcl_DStringValue(&ds)), 1,
+ &textProp) != 0) {
XSetWMName(winPtr->display, wmPtr->wrapperPtr->window, &textProp);
XFree((char *) textProp.value);
}
-
+ Tcl_DStringFree(&ds);
+
TkWmSetClass(winPtr);
if (wmPtr->iconName != NULL) {
+ Tcl_UtfToExternalDString(NULL, wmPtr->iconName, -1, &ds);
XSetIconName(winPtr->display, wmPtr->wrapperPtr->window,
- wmPtr->iconName);
+ Tcl_DStringValue(&ds));
+ Tcl_DStringFree(&ds);
}
if (wmPtr->master != None) {
@@ -519,16 +517,17 @@ TkWmMapWindow(winPtr)
UpdateHints(winPtr);
UpdateWmProtocols(wmPtr);
if (wmPtr->cmdArgv != NULL) {
- XSetCommand(winPtr->display, wmPtr->wrapperPtr->window,
- wmPtr->cmdArgv, wmPtr->cmdArgc);
+ UpdateCommand(winPtr);
}
if (wmPtr->clientMachine != NULL) {
- if (XStringListToTextProperty(&wmPtr->clientMachine, 1, &textProp)
- != 0) {
+ 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);
}
+ Tcl_DStringFree(&ds);
}
}
if (wmPtr->hints.initial_state == WithdrawnState) {
@@ -630,12 +629,13 @@ TkWmDeadWindow(winPtr)
if (wmPtr == NULL) {
return;
}
- if (firstWmPtr == wmPtr) {
- firstWmPtr = wmPtr->nextPtr;
+ if ((WmInfo *) winPtr->dispPtr->firstWmPtr == wmPtr) {
+ winPtr->dispPtr->firstWmPtr = wmPtr->nextPtr;
} else {
register WmInfo *prevPtr;
- for (prevPtr = firstWmPtr; ; prevPtr = prevPtr->nextPtr) {
+ for (prevPtr = (WmInfo *) winPtr->dispPtr->firstWmPtr; ;
+ prevPtr = prevPtr->nextPtr) {
if (prevPtr == NULL) {
panic("couldn't unlink window in TkWmDeadWindow");
}
@@ -740,13 +740,18 @@ TkWmSetClass(winPtr)
if (winPtr->classUid != NULL) {
XClassHint *classPtr;
+ Tcl_DString name, class;
+ Tcl_UtfToExternalDString(NULL, winPtr->nameUid, -1, &name);
+ Tcl_UtfToExternalDString(NULL, winPtr->classUid, -1, &class);
classPtr = XAllocClassHint();
- classPtr->res_name = winPtr->nameUid;
- classPtr->res_class = winPtr->classUid;
+ classPtr->res_name = Tcl_DStringValue(&name);
+ classPtr->res_class = Tcl_DStringValue(&class);
XSetClassHint(winPtr->display, winPtr->wmInfoPtr->wrapperPtr->window,
classPtr);
XFree((char *) classPtr);
+ Tcl_DStringFree(&name);
+ Tcl_DStringFree(&class);
}
}
@@ -781,6 +786,7 @@ Tk_WmCmd(clientData, interp, argc, argv)
register WmInfo *wmPtr;
int c;
size_t length;
+ TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;
if (argc < 2) {
wrongNumArgs:
@@ -798,10 +804,11 @@ Tk_WmCmd(clientData, interp, argc, argv)
return TCL_ERROR;
}
if (argc == 2) {
- interp->result = (wmTracing) ? "on" : "off";
+ Tcl_SetResult(interp, ((dispPtr->wmTracing) ? "on" : "off"),
+ TCL_STATIC);
return TCL_OK;
}
- return Tcl_GetBoolean(interp, argv[2], &wmTracing);
+ return Tcl_GetBoolean(interp, argv[2], &dispPtr->wmTracing);
}
if (argc < 3) {
@@ -828,9 +835,12 @@ Tk_WmCmd(clientData, interp, argc, argv)
}
if (argc == 3) {
if (wmPtr->sizeHintsFlags & PAspect) {
- sprintf(interp->result, "%d %d %d %d", wmPtr->minAspect.x,
+ 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;
}
@@ -845,7 +855,8 @@ Tk_WmCmd(clientData, interp, argc, argv)
}
if ((numer1 <= 0) || (denom1 <= 0) || (numer2 <= 0) ||
(denom2 <= 0)) {
- interp->result = "aspect number can't be <= 0";
+ Tcl_SetResult(interp, "aspect number can't be <= 0",
+ TCL_STATIC);
return TCL_ERROR;
}
wmPtr->minAspect.x = numer1;
@@ -866,7 +877,7 @@ Tk_WmCmd(clientData, interp, argc, argv)
}
if (argc == 3) {
if (wmPtr->clientMachine != NULL) {
- interp->result = wmPtr->clientMachine;
+ Tcl_SetResult(interp, wmPtr->clientMachine, TCL_STATIC);
}
return TCL_OK;
}
@@ -890,12 +901,16 @@ Tk_WmCmd(clientData, interp, argc, argv)
strcpy(wmPtr->clientMachine, argv[3]);
if (!(wmPtr->flags & WM_NEVER_MAPPED)) {
XTextProperty textProp;
- if (XStringListToTextProperty(&wmPtr->clientMachine, 1, &textProp)
- != 0) {
+ 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);
}
+ Tcl_DStringFree(&ds);
}
} else if ((c == 'c') && (strncmp(argv[1], "colormapwindows", length) == 0)
&& (length >= 3)) {
@@ -985,8 +1000,9 @@ Tk_WmCmd(clientData, interp, argc, argv)
}
if (argc == 3) {
if (wmPtr->cmdArgv != NULL) {
- interp->result = Tcl_Merge(wmPtr->cmdArgc, wmPtr->cmdArgv);
- interp->freeProc = TCL_DYNAMIC;
+ Tcl_SetResult(interp,
+ Tcl_Merge(wmPtr->cmdArgc, wmPtr->cmdArgv),
+ TCL_DYNAMIC);
}
return TCL_OK;
}
@@ -1010,8 +1026,7 @@ Tk_WmCmd(clientData, interp, argc, argv)
wmPtr->cmdArgc = cmdArgc;
wmPtr->cmdArgv = cmdArgv;
if (!(wmPtr->flags & WM_NEVER_MAPPED)) {
- XSetCommand(winPtr->display, wmPtr->wrapperPtr->window,
- cmdArgv, cmdArgc);
+ UpdateCommand(winPtr);
}
} else if ((c == 'd') && (strncmp(argv[1], "deiconify", length) == 0)) {
if (argc != 3) {
@@ -1041,7 +1056,8 @@ Tk_WmCmd(clientData, interp, argc, argv)
return TCL_ERROR;
}
if (argc == 3) {
- interp->result = wmPtr->hints.input ? "passive" : "active";
+ Tcl_SetResult(interp, (wmPtr->hints.input ? "passive" : "active"),
+ TCL_STATIC);
return TCL_OK;
}
c = argv[3][0];
@@ -1059,6 +1075,7 @@ Tk_WmCmd(clientData, interp, argc, argv)
} 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 \"",
@@ -1069,7 +1086,8 @@ Tk_WmCmd(clientData, interp, argc, argv)
if (window == None) {
window = Tk_WindowId((Tk_Window) winPtr);
}
- sprintf(interp->result, "0x%x", (unsigned int) window);
+ 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;
@@ -1082,6 +1100,8 @@ Tk_WmCmd(clientData, interp, argc, argv)
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) {
@@ -1093,8 +1113,9 @@ Tk_WmCmd(clientData, interp, argc, argv)
width = winPtr->changes.width;
height = winPtr->changes.height;
}
- sprintf(interp->result, "%dx%d%c%d%c%d", width, height,
- xSign, wmPtr->x, ySign, wmPtr->y);
+ 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;
}
if (*argv[3] == '\0') {
@@ -1115,9 +1136,12 @@ Tk_WmCmd(clientData, interp, argc, argv)
}
if (argc == 3) {
if (wmPtr->sizeHintsFlags & PBaseSize) {
- sprintf(interp->result, "%d %d %d %d", wmPtr->reqGridWidth,
+ 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);
}
return TCL_OK;
}
@@ -1144,19 +1168,19 @@ Tk_WmCmd(clientData, interp, argc, argv)
return TCL_ERROR;
}
if (reqWidth < 0) {
- interp->result = "baseWidth can't be < 0";
+ Tcl_SetResult(interp, "baseWidth can't be < 0", TCL_STATIC);
return TCL_ERROR;
}
if (reqHeight < 0) {
- interp->result = "baseHeight can't be < 0";
+ Tcl_SetResult(interp, "baseHeight can't be < 0", TCL_STATIC);
return TCL_ERROR;
}
if (widthInc < 0) {
- interp->result = "widthInc can't be < 0";
+ Tcl_SetResult(interp, "widthInc can't be < 0", TCL_STATIC);
return TCL_ERROR;
}
if (heightInc < 0) {
- interp->result = "heightInc can't be < 0";
+ Tcl_SetResult(interp, "heightInc can't be < 0", TCL_STATIC);
return TCL_ERROR;
}
Tk_SetGrid((Tk_Window) winPtr, reqWidth, reqHeight, widthInc,
@@ -1177,7 +1201,7 @@ Tk_WmCmd(clientData, interp, argc, argv)
}
if (argc == 3) {
if (wmPtr->hints.flags & WindowGroupHint) {
- interp->result = wmPtr->leaderName;
+ Tcl_SetResult(interp, wmPtr->leaderName, TCL_STATIC);
}
return TCL_OK;
}
@@ -1204,6 +1228,9 @@ Tk_WmCmd(clientData, interp, argc, argv)
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));
@@ -1222,8 +1249,9 @@ Tk_WmCmd(clientData, interp, argc, argv)
}
if (argc == 3) {
if (wmPtr->hints.flags & IconPixmapHint) {
- interp->result = Tk_NameOfBitmap(winPtr->display,
- wmPtr->hints.icon_pixmap);
+ Tcl_SetResult(interp,
+ Tk_NameOfBitmap(winPtr->display, wmPtr->hints.icon_pixmap),
+ TCL_STATIC);
}
return TCL_OK;
}
@@ -1277,8 +1305,9 @@ Tk_WmCmd(clientData, interp, argc, argv)
} else {
if (XIconifyWindow(winPtr->display, wmPtr->wrapperPtr->window,
winPtr->screenNum) == 0) {
- interp->result =
- "couldn't send iconify message to window manager";
+ Tcl_SetResult(interp,
+ "couldn't send iconify message to window manager",
+ TCL_STATIC);
return TCL_ERROR;
}
WaitForMapNotify(winPtr, 0);
@@ -1295,8 +1324,9 @@ Tk_WmCmd(clientData, interp, argc, argv)
}
if (argc == 3) {
if (wmPtr->hints.flags & IconMaskHint) {
- interp->result = Tk_NameOfBitmap(winPtr->display,
- wmPtr->hints.icon_mask);
+ Tcl_SetResult(interp,
+ Tk_NameOfBitmap(winPtr->display, wmPtr->hints.icon_mask),
+ TCL_STATIC);
}
return TCL_OK;
}
@@ -1322,17 +1352,23 @@ Tk_WmCmd(clientData, interp, argc, argv)
return TCL_ERROR;
}
if (argc == 3) {
- interp->result = (wmPtr->iconName != NULL) ? wmPtr->iconName : "";
+ Tcl_SetResult(interp,
+ ((wmPtr->iconName != NULL) ? wmPtr->iconName : ""),
+ TCL_STATIC);
return TCL_OK;
} else {
if (wmPtr->iconName != NULL) {
- ckfree(wmPtr->iconName);
+ 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,
- wmPtr->iconName);
+ Tcl_DStringValue(&ds));
+ Tcl_DStringFree(&ds);
}
}
} else if ((c == 'i') && (strncmp(argv[1], "iconposition", length) == 0)
@@ -1347,8 +1383,11 @@ Tk_WmCmd(clientData, interp, argc, argv)
}
if (argc == 3) {
if (wmPtr->hints.flags & IconPositionHint) {
- sprintf(interp->result, "%d %d", wmPtr->hints.icon_x,
+ char buf[TCL_INTEGER_SPACE * 2];
+
+ sprintf(buf, "%d %d", wmPtr->hints.icon_x,
wmPtr->hints.icon_y);
+ Tcl_SetResult(interp, buf, TCL_VOLATILE);
}
return TCL_OK;
}
@@ -1378,7 +1417,7 @@ Tk_WmCmd(clientData, interp, argc, argv)
}
if (argc == 3) {
if (wmPtr->icon != NULL) {
- interp->result = Tk_PathName(wmPtr->icon);
+ Tcl_SetResult(interp, Tk_PathName(wmPtr->icon), TCL_STATIC);
}
return TCL_OK;
}
@@ -1447,8 +1486,9 @@ Tk_WmCmd(clientData, interp, argc, argv)
if (XWithdrawWindow(Tk_Display(tkwin2),
Tk_WindowId(wmPtr2->wrapperPtr),
Tk_ScreenNumber(tkwin2)) == 0) {
- interp->result =
- "couldn't send withdraw message to window manager";
+ Tcl_SetResult(interp,
+ "couldn't send withdraw message to window manager",
+ TCL_STATIC);
return TCL_ERROR;
}
WaitForMapNotify((TkWindow *) tkwin2, 0);
@@ -1464,8 +1504,11 @@ Tk_WmCmd(clientData, interp, argc, argv)
return TCL_ERROR;
}
if (argc == 3) {
+ char buf[TCL_INTEGER_SPACE * 2];
+
GetMaxSize(wmPtr, &width, &height);
- sprintf(interp->result, "%d %d", width, height);
+ sprintf(buf, "%d %d", width, height);
+ Tcl_SetResult(interp, buf, TCL_VOLATILE);
return TCL_OK;
}
if ((Tcl_GetInt(interp, argv[3], &width) != TCL_OK)
@@ -1485,8 +1528,10 @@ Tk_WmCmd(clientData, interp, argc, argv)
return TCL_ERROR;
}
if (argc == 3) {
- sprintf(interp->result, "%d %d", wmPtr->minWidth,
- wmPtr->minHeight);
+ 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_GetInt(interp, argv[3], &width) != TCL_OK)
@@ -1499,7 +1544,7 @@ Tk_WmCmd(clientData, interp, argc, argv)
goto updateGeom;
} else if ((c == 'o')
&& (strncmp(argv[1], "overrideredirect", length) == 0)) {
- int boolean;
+ int boolean, curValue;
XSetWindowAttributes atts;
if ((argc != 3) && (argc != 4)) {
@@ -1508,24 +1553,27 @@ Tk_WmCmd(clientData, interp, argc, argv)
(char *) NULL);
return TCL_ERROR;
}
+ curValue = Tk_Attributes((Tk_Window) winPtr)->override_redirect;
if (argc == 3) {
- if (Tk_Attributes((Tk_Window) winPtr)->override_redirect) {
- interp->result = "1";
- } else {
- interp->result = "0";
- }
+ Tcl_SetBooleanObj(Tcl_GetObjResult(interp), curValue);
return TCL_OK;
}
if (Tcl_GetBoolean(interp, argv[3], &boolean) != TCL_OK) {
return TCL_ERROR;
}
- atts.override_redirect = (boolean) ? True : False;
- Tk_ChangeWindowAttributes((Tk_Window) winPtr, CWOverrideRedirect,
- &atts);
- if (winPtr->wmInfoPtr->wrapperPtr != NULL) {
- Tk_ChangeWindowAttributes(
+ 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)) {
@@ -1537,9 +1585,9 @@ Tk_WmCmd(clientData, interp, argc, argv)
}
if (argc == 3) {
if (wmPtr->sizeHintsFlags & USPosition) {
- interp->result = "user";
+ Tcl_SetResult(interp, "user", TCL_STATIC);
} else if (wmPtr->sizeHintsFlags & PPosition) {
- interp->result = "program";
+ Tcl_SetResult(interp, "program", TCL_STATIC);
}
return TCL_OK;
}
@@ -1593,7 +1641,7 @@ Tk_WmCmd(clientData, interp, argc, argv)
for (protPtr = wmPtr->protPtr; protPtr != NULL;
protPtr = protPtr->nextPtr) {
if (protPtr->protocol == protocol) {
- interp->result = protPtr->command;
+ Tcl_SetResult(interp, protPtr->command, TCL_STATIC);
return TCL_OK;
}
}
@@ -1640,9 +1688,12 @@ Tk_WmCmd(clientData, interp, argc, argv)
return TCL_ERROR;
}
if (argc == 3) {
- sprintf(interp->result, "%d %d",
+ 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)
@@ -1671,9 +1722,9 @@ Tk_WmCmd(clientData, interp, argc, argv)
}
if (argc == 3) {
if (wmPtr->sizeHintsFlags & USSize) {
- interp->result = "user";
+ Tcl_SetResult(interp, "user", TCL_STATIC);
} else if (wmPtr->sizeHintsFlags & PSize) {
- interp->result = "program";
+ Tcl_SetResult(interp, "program", TCL_STATIC);
}
return TCL_OK;
}
@@ -1699,21 +1750,95 @@ Tk_WmCmd(clientData, interp, argc, argv)
goto updateGeom;
} else if ((c == 's') && (strncmp(argv[1], "state", length) == 0)
&& (length >= 2)) {
- if (argc != 3) {
+ if ((argc < 3) || (argc > 4)) {
Tcl_AppendResult(interp, "wrong # arguments: must be \"",
- argv[0], " state window\"", (char *) NULL);
+ argv[0], " state window ?state?\"", (char *) NULL);
return TCL_ERROR;
}
- if (wmPtr->iconFor != NULL) {
- interp->result = "icon";
- } else if (wmPtr->withdrawn) {
- interp->result = "withdrawn";
- } else if (Tk_IsMapped((Tk_Window) winPtr)
- || ((wmPtr->flags & WM_NEVER_MAPPED)
- && (wmPtr->hints.initial_state == NormalState))) {
- interp->result = "normal";
+ 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);
+ 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);
+ return TCL_ERROR;
+ }
} else {
- interp->result = "iconic";
+ 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 if ((c == 't') && (strncmp(argv[1], "title", length) == 0)
&& (length >= 2)) {
@@ -1723,24 +1848,28 @@ Tk_WmCmd(clientData, interp, argc, argv)
return TCL_ERROR;
}
if (argc == 3) {
- interp->result = (wmPtr->title != NULL) ? wmPtr->title
- : winPtr->nameUid;
+ Tcl_SetResult(interp,
+ ((wmPtr->title != NULL) ? wmPtr->title : winPtr->nameUid),
+ TCL_STATIC);
return TCL_OK;
} else {
if (wmPtr->title != NULL) {
- ckfree(wmPtr->title);
+ 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;
- if (XStringListToTextProperty(&wmPtr->title, 1,
+ 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);
}
}
} else if ((c == 't') && (strncmp(argv[1], "transient", length) == 0)
@@ -1755,7 +1884,7 @@ Tk_WmCmd(clientData, interp, argc, argv)
}
if (argc == 3) {
if (wmPtr->master != None) {
- interp->result = wmPtr->masterWindowName;
+ Tcl_SetResult(interp, wmPtr->masterWindowName, TCL_STATIC);
}
return TCL_OK;
}
@@ -1783,6 +1912,9 @@ Tk_WmCmd(clientData, interp, argc, argv)
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]);
}
@@ -1810,8 +1942,9 @@ Tk_WmCmd(clientData, interp, argc, argv)
}
if (XWithdrawWindow(winPtr->display, wmPtr->wrapperPtr->window,
winPtr->screenNum) == 0) {
- interp->result =
- "couldn't send withdraw message to window manager";
+ Tcl_SetResult(interp,
+ "couldn't send withdraw message to window manager",
+ TCL_STATIC);
return TCL_ERROR;
}
WaitForMapNotify(winPtr, 0);
@@ -2029,6 +2162,8 @@ ConfigureEvent(wmPtr, configEventPtr)
{
TkWindow *wrapperPtr = wmPtr->wrapperPtr;
TkWindow *winPtr = wmPtr->winPtr;
+ TkDisplay *dispPtr = wmPtr->winPtr->dispPtr;
+ Tk_ErrorHandler handler;
/*
* Update size information from the event. There are a couple of
@@ -2046,7 +2181,7 @@ ConfigureEvent(wmPtr, configEventPtr)
if (((wrapperPtr->changes.width != configEventPtr->width)
|| (wrapperPtr->changes.height != configEventPtr->height))
&& !(wmPtr->flags & WM_SYNC_PENDING)){
- if (wmTracing) {
+ if (dispPtr->wmTracing) {
printf("TopLevelEventProc: user changed %s size to %dx%d\n",
winPtr->pathName, configEventPtr->width,
configEventPtr->height);
@@ -2110,7 +2245,7 @@ ConfigureEvent(wmPtr, configEventPtr)
wmPtr->configHeight = configEventPtr->height;
}
- if (wmTracing) {
+ if (dispPtr->wmTracing) {
printf("ConfigureEvent: %s x = %d y = %d, width = %d, height = %d",
winPtr->pathName, configEventPtr->x, configEventPtr->y,
configEventPtr->width, configEventPtr->height);
@@ -2156,12 +2291,15 @@ ConfigureEvent(wmPtr, configEventPtr)
/*
* Make sure that the toplevel and menubar are properly positioned within
- * the wrapper.
+ * the wrapper. If the menuHeight happens to be zero, we'll get a
+ * BadValue X error that we want to ignore [Bug: 3377]
*/
-
+ handler = Tk_CreateErrorHandler(winPtr->display, -1, -1, -1,
+ (Tk_ErrorProc *) NULL, (ClientData) NULL);
XMoveResizeWindow(winPtr->display, winPtr->window, 0,
wmPtr->menuHeight, (unsigned) wrapperPtr->changes.width,
(unsigned) (wrapperPtr->changes.height - wmPtr->menuHeight));
+ Tk_DeleteErrorHandler(handler);
if ((wmPtr->menubar != NULL)
&& ((Tk_Width(wmPtr->menubar) != wrapperPtr->changes.width)
|| (Tk_Height(wmPtr->menubar) != wmPtr->menuHeight))) {
@@ -2213,6 +2351,7 @@ ReparentEvent(wmPtr, reparentEventPtr)
unsigned long numItems, bytesAfter;
unsigned int dummy;
Tk_ErrorHandler handler;
+ TkDisplay *dispPtr = wmPtr->winPtr->dispPtr;
/*
* Identify the root window for wrapperPtr. This is tricky because of
@@ -2238,7 +2377,7 @@ ReparentEvent(wmPtr, reparentEventPtr)
&& (actualType == XA_WINDOW))) {
if ((actualFormat == 32) && (numItems == 1)) {
vRoot = wmPtr->vRoot = *virtualRootPtr;
- } else if (wmTracing) {
+ } else if (dispPtr->wmTracing) {
printf("%s format %d numItems %ld\n",
"ReparentEvent got bogus VROOT property:", actualFormat,
numItems);
@@ -2247,7 +2386,7 @@ ReparentEvent(wmPtr, reparentEventPtr)
}
Tk_DeleteErrorHandler(handler);
- if (wmTracing) {
+ if (dispPtr->wmTracing) {
printf("ReparentEvent: %s reparented to 0x%x, vRoot = 0x%x\n",
wmPtr->winPtr->pathName,
(unsigned int) reparentEventPtr->parent, (unsigned int) vRoot);
@@ -2344,6 +2483,7 @@ ComputeReparentGeometry(wmPtr)
Window dummy2;
Status status;
Tk_ErrorHandler handler;
+ TkDisplay *dispPtr = wmPtr->winPtr->dispPtr;
handler = Tk_CreateErrorHandler(wrapperPtr->display, -1, -1, -1,
(Tk_ErrorProc *) NULL, (ClientData) NULL);
@@ -2410,7 +2550,7 @@ ComputeReparentGeometry(wmPtr)
wmPtr->wrapperPtr->changes.x = x + wmPtr->xInParent;
wmPtr->wrapperPtr->changes.y = y + wmPtr->yInParent;
- if (wmTracing) {
+ 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);
@@ -2443,6 +2583,7 @@ WrapperEventProc(clientData, eventPtr)
{
WmInfo *wmPtr = (WmInfo *) clientData;
XEvent mapEvent;
+ TkDisplay *dispPtr = wmPtr->winPtr->dispPtr;
wmPtr->flags |= WM_VROOT_OFFSET_STALE;
if (eventPtr->type == DestroyNotify) {
@@ -2462,7 +2603,7 @@ WrapperEventProc(clientData, eventPtr)
Tk_DestroyWindow((Tk_Window) wmPtr->winPtr);
Tk_DeleteErrorHandler(handler);
}
- if (wmTracing) {
+ if (dispPtr->wmTracing) {
printf("TopLevelEventProc: %s deleted\n", wmPtr->winPtr->pathName);
}
} else if (eventPtr->type == ConfigureNotify) {
@@ -2725,7 +2866,7 @@ UpdateGeometryInfo(clientData)
}
wmPtr->configWidth = width;
wmPtr->configHeight = height;
- if (wmTracing) {
+ if (winPtr->dispPtr->wmTracing) {
printf("UpdateGeometryInfo moving to %d %d, resizing to %d x %d,\n",
x, y, width, height);
}
@@ -2746,7 +2887,7 @@ UpdateGeometryInfo(clientData)
}
wmPtr->configWidth = width;
wmPtr->configHeight = height;
- if (wmTracing) {
+ if (winPtr->dispPtr->wmTracing) {
printf("UpdateGeometryInfo resizing to %d x %d\n", width, height);
}
XResizeWindow(winPtr->display, wmPtr->wrapperPtr->window,
@@ -2947,7 +3088,7 @@ WaitForConfigureNotify(winPtr, serial)
ConfigureNotify, &event);
wmPtr->flags &= ~WM_SYNC_PENDING;
if (code != TCL_OK) {
- if (wmTracing) {
+ if (winPtr->dispPtr->wmTracing) {
printf("WaitForConfigureNotify giving up on %s\n",
winPtr->pathName);
}
@@ -2959,7 +3100,7 @@ WaitForConfigureNotify(winPtr, serial)
}
}
wmPtr->flags &= ~WM_MOVE_PENDING;
- if (wmTracing) {
+ if (winPtr->dispPtr->wmTracing) {
printf("WaitForConfigureNotify finished with %s, serial %ld\n",
winPtr->pathName, serial);
}
@@ -3135,14 +3276,14 @@ WaitForMapNotify(winPtr, mapped)
* just quit.
*/
- if (wmTracing) {
+ if (winPtr->dispPtr->wmTracing) {
printf("WaitForMapNotify giving up on %s\n", winPtr->pathName);
}
break;
}
}
wmPtr->flags &= ~WM_MOVE_PENDING;
- if (wmTracing) {
+ if (winPtr->dispPtr->wmTracing) {
printf("WaitForMapNotify finished with %s\n", winPtr->pathName);
}
}
@@ -3188,7 +3329,7 @@ UpdateHints(winPtr)
*
* Results:
* A standard Tcl return value, plus an error message in
- * interp->result if an error occurs.
+ * the interp's result if an error occurs.
*
* Side effects:
* The size and/or location of winPtr may change.
@@ -3441,6 +3582,8 @@ Tk_CoordsToWindow(rootX, rootY, tkwin)
int x, y, childX, childY, tmpx, tmpy, bd;
WmInfo *wmPtr;
TkWindow *winPtr, *childPtr, *nextPtr;
+ TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;
+ Tk_ErrorHandler handler = NULL;
/*
* Step 1: scan the list of toplevel windows to see if there is a
@@ -3452,7 +3595,7 @@ Tk_CoordsToWindow(rootX, rootY, tkwin)
parent = window = RootWindowOfScreen(Tk_Screen(tkwin));
x = rootX;
y = rootY;
- for (wmPtr = firstWmPtr; wmPtr != NULL; wmPtr = wmPtr->nextPtr) {
+ for (wmPtr = (WmInfo *) dispPtr->firstWmPtr; wmPtr != NULL; wmPtr = wmPtr->nextPtr) {
if (Tk_Screen(wmPtr->winPtr) != Tk_Screen(tkwin)) {
continue;
}
@@ -3479,15 +3622,24 @@ Tk_CoordsToWindow(rootX, rootY, tkwin)
* the toplevel.
*/
+ handler = Tk_CreateErrorHandler(Tk_Display(tkwin), -1, -1, -1,
+ (Tk_ErrorProc *) NULL, (ClientData) NULL);
while (1) {
if (XTranslateCoordinates(Tk_Display(tkwin), parent, window,
x, y, &childX, &childY, &child) == False) {
- panic("Tk_CoordsToWindow got False return from XTranslateCoordinates");
+ /*
+ * We can end up here when the window is in the middle of
+ * being deleted
+ */
+ Tk_DeleteErrorHandler(handler);
+ return NULL;
}
if (child == None) {
+ Tk_DeleteErrorHandler(handler);
return NULL;
}
- for (wmPtr = firstWmPtr; wmPtr != NULL; wmPtr = wmPtr->nextPtr) {
+ for (wmPtr = (WmInfo *) dispPtr->firstWmPtr; wmPtr != NULL;
+ wmPtr = wmPtr->nextPtr) {
if (wmPtr->reparent == child) {
goto gotToplevel;
}
@@ -3506,6 +3658,14 @@ Tk_CoordsToWindow(rootX, rootY, tkwin)
}
gotToplevel:
+ if (handler) {
+ /*
+ * Check value of handler, because we can reach this label
+ * from above or below
+ */
+ Tk_DeleteErrorHandler(handler);
+ handler = NULL;
+ }
winPtr = wmPtr->winPtr;
if (winPtr->mainPtr != ((TkWindow *) tkwin)->mainPtr) {
return NULL;
@@ -3644,7 +3804,7 @@ UpdateVRootGeometry(wmPtr)
(unsigned int *) &wmPtr->vRootWidth,
(unsigned int *) &wmPtr->vRootHeight, (unsigned int *) &bd,
&dummy);
- if (wmTracing) {
+ if (winPtr->dispPtr->wmTracing) {
printf("UpdateVRootGeometry: x = %d, y = %d, width = %d, ",
wmPtr->vRootX, wmPtr->vRootY, wmPtr->vRootWidth);
printf("height = %d, status = %d\n", wmPtr->vRootHeight, status);
@@ -4818,3 +4978,63 @@ TkpGetWrapperWindow(winPtr)
return wmPtr->wrapperPtr;
}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * UpdateCommand --
+ *
+ * Update the WM_COMMAND property, taking care to translate
+ * the command strings into the external encoding.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+UpdateCommand(winPtr)
+ TkWindow *winPtr;
+{
+ register WmInfo *wmPtr = winPtr->wmInfoPtr;
+ Tcl_DString cmds, ds;
+ int i, *offsets;
+ char **cmdArgv;
+
+ /*
+ * Translate the argv strings into the external encoding. To avoid
+ * allocating lots of memory, the strings are appended to a buffer
+ * with nulls between each string.
+ *
+ * This code is tricky because we need to pass and array of pointers
+ * to XSetCommand. However, we can't compute the pointers as we go
+ * because the DString buffer space could get reallocated. So, store
+ * offsets for each element as we go, then compute pointers from the
+ * offsets once the entire DString is done.
+ */
+
+ cmdArgv = (char **) ckalloc(sizeof(char *) * wmPtr->cmdArgc);
+ offsets = (int *) ckalloc( sizeof(int) * wmPtr->cmdArgc);
+ Tcl_DStringInit(&cmds);
+ for (i = 0; i < wmPtr->cmdArgc; i++) {
+ Tcl_UtfToExternalDString(NULL, wmPtr->cmdArgv[i], -1, &ds);
+ offsets[i] = Tcl_DStringLength(&cmds);
+ Tcl_DStringAppend(&cmds, Tcl_DStringValue(&ds),
+ Tcl_DStringLength(&ds)+1);
+ Tcl_DStringFree(&ds);
+ }
+ cmdArgv[0] = Tcl_DStringValue(&cmds);
+ for (i = 1; i < wmPtr->cmdArgc; i++) {
+ cmdArgv[i] = cmdArgv[0] + offsets[i];
+ }
+
+ XSetCommand(winPtr->display, wmPtr->wrapperPtr->window,
+ cmdArgv, wmPtr->cmdArgc);
+ Tcl_DStringFree(&cmds);
+ ckfree((char *) cmdArgv);
+ ckfree((char *) offsets);
+}