summaryrefslogtreecommitdiffstats
path: root/unix/tkUnixWm.c
diff options
context:
space:
mode:
authorjenglish@flightlab.com <jenglish>2005-01-14 21:09:36 (GMT)
committerjenglish@flightlab.com <jenglish>2005-01-14 21:09:36 (GMT)
commita4d91efb43dc952e9aba5e6f40171de6b3dda678 (patch)
tree59591b101ee8718f9f9ae595c27261809be595ce /unix/tkUnixWm.c
parentf66f6f8bc16c7783eb0927829d57e2ab54c67e4c (diff)
downloadtk-a4d91efb43dc952e9aba5e6f40171de6b3dda678.zip
tk-a4d91efb43dc952e9aba5e6f40171de6b3dda678.tar.gz
tk-a4d91efb43dc952e9aba5e6f40171de6b3dda678.tar.bz2
unix/tkUnixWm.c: Sync with CVS HEAD (r1.47):
Fixes: #959973 "wm title bug" (support Unicode titles) Fixes: #742882 "Potential division by zero in gridded wm geometry" Use Tcl_GetTime instead of TclpGetTime [#874745] Use Tcl_Panic() instead of "panic" [#865264] Fixes: #632816 "cannot remove transient" Fixes: #568861 "Fix for wm minsize and maxsize commands" tests/unixWm.test, tests/wm.test: Updated test suite for #632816 (unixWm-37.3, unixWm-37.4, wm-grid-1.11, wm-grid-1.12) and #742882 (unixWm-20.9, unixWm-20.11).
Diffstat (limited to 'unix/tkUnixWm.c')
-rw-r--r--unix/tkUnixWm.c246
1 files changed, 165 insertions, 81 deletions
diff --git a/unix/tkUnixWm.c b/unix/tkUnixWm.c
index 6f89bc2..87c22b8 100644
--- a/unix/tkUnixWm.c
+++ b/unix/tkUnixWm.c
@@ -12,13 +12,12 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tkUnixWm.c,v 1.36.2.4 2004/10/27 17:34:36 dgp Exp $
+ * RCS: @(#) $Id: tkUnixWm.c,v 1.36.2.5 2005/01/14 21:09:46 jenglish Exp $
*/
#include "tkPort.h"
#include "tkInt.h"
#include "tkUnixInt.h"
-#include <errno.h>
/*
* A data structure of the following type holds information for
@@ -108,9 +107,9 @@ typedef struct TkWmInfo {
* window is gridded; otherwise it isn't
* gridded. */
int minWidth, minHeight; /* Minimum dimensions of window, in
- * grid units, not pixels. */
+ * pixels or grid units. */
int maxWidth, maxHeight; /* Maximum dimensions of window, in
- * grid units, not pixels. */
+ * pixels or grid units. 0 to default.*/
Tk_Window gridWin; /* Identifies the window that controls
* gridding for this top-level, or NULL if
* the top-level isn't currently gridded. */
@@ -131,7 +130,7 @@ typedef struct TkWmInfo {
*/
int width, height; /* Desired dimensions of window, specified
- * in grid units. These values are
+ * in pixels or grid units. These values are
* set by the "wm geometry" command and by
* ConfigureNotify events (for when wm
* resizes window). -1 means user hasn't
@@ -334,7 +333,9 @@ static void UpdateCommand _ANSI_ARGS_((TkWindow *winPtr));
static void UpdateGeometryInfo _ANSI_ARGS_((
ClientData clientData));
static void UpdateHints _ANSI_ARGS_((TkWindow *winPtr));
-static void UpdateSizeHints _ANSI_ARGS_((TkWindow *winPtr));
+static void UpdateSizeHints _ANSI_ARGS_((TkWindow *winPtr,
+ int newWidth, int newHeight));
+static void UpdateTitle _ANSI_ARGS_((TkWindow *winPtr));
static void UpdatePhotoIcon _ANSI_ARGS_((TkWindow *winPtr));
static void UpdateVRootGeometry _ANSI_ARGS_((WmInfo *wmPtr));
static void UpdateWmProtocols _ANSI_ARGS_((WmInfo *wmPtr));
@@ -550,13 +551,15 @@ TkWmNewWindow(winPtr)
wmPtr->hints.icon_x = wmPtr->hints.icon_y = 0;
wmPtr->hints.icon_mask = None;
wmPtr->hints.window_group = None;
- wmPtr->minWidth = wmPtr->minHeight = 1;
/*
* Default the maximum dimensions to the size of the display, minus
* a guess about how space is needed for window manager decorations.
*/
+ wmPtr->gridWin = NULL;
+ wmPtr->minWidth = wmPtr->minHeight = 1;
+ wmPtr->maxWidth = wmPtr->maxHeight = 0;
wmPtr->widthInc = wmPtr->heightInc = 1;
wmPtr->minAspect.x = wmPtr->minAspect.y = 1;
wmPtr->maxAspect.x = wmPtr->maxAspect.y = 1;
@@ -618,7 +621,6 @@ TkWmMapWindow(winPtr)
{
register WmInfo *wmPtr = winPtr->wmInfoPtr;
XTextProperty textProp;
- Tk_Uid string;
if (wmPtr->flags & WM_NEVER_MAPPED) {
Tcl_DString ds;
@@ -640,26 +642,10 @@ TkWmMapWindow(winPtr)
* window.
*/
- string = (wmPtr->title != NULL) ? wmPtr->title : winPtr->nameUid;
- 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);
+ UpdateTitle(winPtr);
UpdatePhotoIcon(winPtr);
- if (wmPtr->iconName != NULL) {
- Tcl_UtfToExternalDString(NULL, wmPtr->iconName, -1, &ds);
- XSetIconName(winPtr->display, wmPtr->wrapperPtr->window,
- Tcl_DStringValue(&ds));
- Tcl_DStringFree(&ds);
- }
-
if (wmPtr->masterPtr != NULL) {
/*
* Don't map a transient if the master is not mapped.
@@ -798,7 +784,7 @@ TkWmDeadWindow(winPtr)
for (prevPtr = (WmInfo *) winPtr->dispPtr->firstWmPtr; ;
prevPtr = prevPtr->nextPtr) {
if (prevPtr == NULL) {
- panic("couldn't unlink window in TkWmDeadWindow");
+ Tcl_Panic("couldn't unlink window in TkWmDeadWindow");
}
if (prevPtr->nextPtr == wmPtr) {
prevPtr->nextPtr = wmPtr->nextPtr;
@@ -880,8 +866,8 @@ TkWmDeadWindow(winPtr)
WmWaitMapProc, (ClientData) wmPtr2->winPtr);
wmPtr2->masterPtr = NULL;
if (!(wmPtr2->flags & WM_NEVER_MAPPED)) {
- XSetTransientForHint(wmPtr2->winPtr->display,
- wmPtr2->wrapperPtr->window, None);
+ XDeleteProperty(winPtr->display, wmPtr2->wrapperPtr->window,
+ Tk_InternAtom((Tk_Window) winPtr, "WM_TRANSIENT_FOR"));
/* FIXME: Need a call like Win32's UpdateWrapper() so
we can recreate the wrapper and get rid of the
transient window decorations. */
@@ -889,7 +875,7 @@ TkWmDeadWindow(winPtr)
}
}
if (wmPtr->numTransients != 0)
- panic("numTransients should be 0");
+ Tcl_Panic("numTransients should be 0");
if (wmPtr->masterPtr != NULL) {
wmPtr2 = wmPtr->masterPtr->wmInfoPtr;
@@ -1748,12 +1734,12 @@ WmGridCmd(tkwin, winPtr, interp, objc, objv)
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);
+ 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);
+ if (heightInc <= 0) {
+ Tcl_SetResult(interp, "heightInc can't be <= 0", TCL_STATIC);
return TCL_ERROR;
}
Tk_SetGrid((Tk_Window) winPtr, reqWidth, reqHeight, widthInc,
@@ -2065,12 +2051,7 @@ WmIconnameCmd(tkwin, winPtr, interp, objc, objv)
wmPtr->iconName = ckalloc((unsigned) (length + 1));
strcpy(wmPtr->iconName, argv3);
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);
+ UpdateTitle(winPtr);
}
}
return TCL_OK;
@@ -2882,7 +2863,7 @@ WmStackorderCmd(tkwin, winPtr, interp, objc, objv)
if (objc == 3) {
windows = TkWmStackorderToplevel(winPtr);
if (windows == NULL) {
- panic("TkWmStackorderToplevel failed");
+ Tcl_Panic("TkWmStackorderToplevel failed");
} else {
for (window_ptr = windows; *window_ptr ; window_ptr++) {
Tcl_AppendElement(interp, (*window_ptr)->pathName);
@@ -2937,9 +2918,9 @@ WmStackorderCmd(tkwin, winPtr, interp, objc, objv)
index2 = (window_ptr - windows);
}
if (index1 == -1)
- panic("winPtr window not found");
+ Tcl_Panic("winPtr window not found");
if (index2 == -1)
- panic("winPtr2 window not found");
+ Tcl_Panic("winPtr2 window not found");
ckfree((char *) windows);
}
@@ -3104,17 +3085,7 @@ WmTitleCmd(tkwin, winPtr, interp, objc, objv)
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);
- }
- Tcl_DStringFree(&ds);
+ UpdateTitle(winPtr);
}
}
return TCL_OK;
@@ -3250,10 +3221,13 @@ WmTransientCmd(tkwin, winPtr, interp, objc, objv)
return TCL_ERROR;
}
} else {
- Window xwin = (wmPtr->masterPtr == NULL) ? None :
- wmPtr->masterPtr->wmInfoPtr->wrapperPtr->window;
- XSetTransientForHint(winPtr->display, wmPtr->wrapperPtr->window,
- xwin);
+ if (wmPtr->masterPtr != NULL) {
+ XSetTransientForHint(winPtr->display, wmPtr->wrapperPtr->window,
+ wmPtr->masterPtr->wmInfoPtr->wrapperPtr->window);
+ } else {
+ XDeleteProperty(winPtr->display, wmPtr->wrapperPtr->window,
+ Tk_InternAtom((Tk_Window)winPtr, "WM_TRANSIENT_FOR"));
+ }
}
}
return TCL_OK;
@@ -3382,6 +3356,16 @@ Tk_SetGrid(tkwin, reqWidth, reqHeight, widthInc, heightInc)
register WmInfo *wmPtr;
/*
+ * Ensure widthInc and heightInc are greater than 0
+ */
+ if (widthInc <= 0) {
+ widthInc = 1;
+ }
+ if (heightInc <= 0) {
+ heightInc = 1;
+ }
+
+ /*
* Find the top-level window for tkwin, plus the window manager
* information.
*/
@@ -4124,7 +4108,7 @@ UpdateGeometryInfo(clientData)
{
register TkWindow *winPtr = (TkWindow *) clientData;
register WmInfo *wmPtr = winPtr->wmInfoPtr;
- int x, y, width, height;
+ int x, y, width, height, min, max;
unsigned long serial;
wmPtr->flags &= ~WM_UPDATE_PENDING;
@@ -4135,9 +4119,10 @@ UpdateGeometryInfo(clientData)
* requested depends on (a) the size requested internally
* by the window's widgets, (b) the size requested by the
* user in a "wm geometry" command or via wm-based interactive
- * resizing (if any), and (c) whether or not the window is
- * gridded. Don't permit sizes <= 0 because this upsets
- * the X server.
+ * resizing (if any), (c) whether or not the window is
+ * gridded, and (d) the current min or max size for
+ * the toplevel. Don't permit sizes <= 0 because this
+ * upsets the X server.
*/
if (wmPtr->width == -1) {
@@ -4151,6 +4136,28 @@ UpdateGeometryInfo(clientData)
if (width <= 0) {
width = 1;
}
+ /*
+ * Account for window max/min width
+ */
+ if (wmPtr->gridWin != NULL) {
+ min = winPtr->reqWidth
+ + (wmPtr->minWidth - wmPtr->reqGridWidth)*wmPtr->widthInc;
+ if (wmPtr->maxWidth > 0) {
+ max = winPtr->reqWidth
+ + (wmPtr->maxWidth - wmPtr->reqGridWidth)*wmPtr->widthInc;
+ } else {
+ max = 0;
+ }
+ } else {
+ min = wmPtr->minWidth;
+ max = wmPtr->maxWidth;
+ }
+ if (width < min) {
+ width = min;
+ } else if ((max > 0) && (width > max)) {
+ width = max;
+ }
+
if (wmPtr->height == -1) {
height = winPtr->reqHeight;
} else if (wmPtr->gridWin != NULL) {
@@ -4162,6 +4169,27 @@ UpdateGeometryInfo(clientData)
if (height <= 0) {
height = 1;
}
+ /*
+ * Account for window max/min height
+ */
+ if (wmPtr->gridWin != NULL) {
+ min = winPtr->reqHeight
+ + (wmPtr->minHeight - wmPtr->reqGridHeight)*wmPtr->heightInc;
+ if (wmPtr->maxHeight > 0) {
+ max = winPtr->reqHeight
+ + (wmPtr->maxHeight - wmPtr->reqGridHeight)*wmPtr->heightInc;
+ } else {
+ max = 0;
+ }
+ } else {
+ min = wmPtr->minHeight;
+ max = wmPtr->maxHeight;
+ }
+ if (height < min) {
+ height = min;
+ } else if ((max > 0) && (height > max)) {
+ height = max;
+ }
/*
* Compute the new position for the upper-left pixel of the window's
@@ -4198,7 +4226,7 @@ UpdateGeometryInfo(clientData)
wmPtr->flags |= WM_UPDATE_SIZE_HINTS;
}
if (wmPtr->flags & WM_UPDATE_SIZE_HINTS) {
- UpdateSizeHints(winPtr);
+ UpdateSizeHints(winPtr, width, height);
}
/*
@@ -4332,8 +4360,10 @@ UpdateGeometryInfo(clientData)
*/
static void
-UpdateSizeHints(winPtr)
+UpdateSizeHints(winPtr, newWidth, newHeight)
TkWindow *winPtr;
+ int newWidth;
+ int newHeight;
{
register WmInfo *wmPtr = winPtr->wmInfoPtr;
XSizeHints *hintsPtr;
@@ -4395,22 +4425,13 @@ UpdateSizeHints(winPtr)
*/
if (wmPtr->flags & WM_WIDTH_NOT_RESIZABLE) {
- if (wmPtr->width >= 0) {
- hintsPtr->min_width = wmPtr->width;
- } else {
- hintsPtr->min_width = winPtr->reqWidth;
- }
- hintsPtr->max_width = hintsPtr->min_width;
- hintsPtr->flags |= PMaxSize;
+ hintsPtr->max_width = hintsPtr->min_width = newWidth;
+ hintsPtr->flags |= PMaxSize;
}
if (wmPtr->flags & WM_HEIGHT_NOT_RESIZABLE) {
- if (wmPtr->height >= 0) {
- hintsPtr->min_height = wmPtr->height;
- } else {
- hintsPtr->min_height = winPtr->reqHeight + wmPtr->menuHeight;
- }
- hintsPtr->max_height = hintsPtr->min_height;
- hintsPtr->flags |= PMaxSize;
+ hintsPtr->max_height = hintsPtr->min_height =
+ newHeight + wmPtr->menuHeight;
+ hintsPtr->flags |= PMaxSize;
}
XSetWMNormalHints(winPtr->display, wmPtr->wrapperPtr->window, hintsPtr);
@@ -4421,6 +4442,69 @@ UpdateSizeHints(winPtr)
/*
*--------------------------------------------------------------
*
+ * UpdateTitle --
+ *
+ * This procedure is called to update the window title and
+ * icon name. It sets the ICCCM-defined properties WM_NAME
+ * and WM_ICON_NAME for older window managers, and the
+ * freedesktop.org-defined _NET_WM_NAME and _NET_WM_ICON_NAME
+ * properties for newer ones. The ICCCM properties are
+ * stored in the system encoding, the newer properties
+ * are stored in UTF-8.
+ *
+ * NOTE: the ICCCM specifies that WM_NAME and WM_ICON_NAME are
+ * stored in ISO-Latin-1. Tk has historically used the default
+ * system encoding (since 8.1). It's not clear whether this is
+ * correct or not.
+ *
+ * Side effects:
+ * Properties get changed for winPtr.
+ *
+ *--------------------------------------------------------------
+ */
+static void
+UpdateTitle(winPtr)
+ TkWindow *winPtr;
+{
+ WmInfo *wmPtr = winPtr->wmInfoPtr;
+ Atom XA_UTF8_STRING = Tk_InternAtom((Tk_Window) winPtr, "UTF8_STRING");
+ const char *string;
+ Tcl_DString ds;
+
+ /*
+ * Set window title:
+ */
+ string = (wmPtr->title != NULL) ? wmPtr->title : winPtr->nameUid;
+ Tcl_UtfToExternalDString(NULL, string, -1, &ds);
+ XStoreName(winPtr->display, wmPtr->wrapperPtr->window,
+ Tcl_DStringValue(&ds));
+ Tcl_DStringFree(&ds);
+
+ XChangeProperty(winPtr->display, wmPtr->wrapperPtr->window,
+ Tk_InternAtom((Tk_Window) winPtr, "_NET_WM_NAME"),
+ XA_UTF8_STRING, 8, PropModeReplace,
+ (const unsigned char*)string, (signed int)strlen(string));
+
+ /*
+ * Set icon name:
+ */
+ if (wmPtr->iconName != NULL) {
+ Tcl_UtfToExternalDString(NULL, wmPtr->iconName, -1, &ds);
+ XSetIconName(winPtr->display, wmPtr->wrapperPtr->window,
+ Tcl_DStringValue(&ds));
+ Tcl_DStringFree(&ds);
+
+ XChangeProperty(winPtr->display, wmPtr->wrapperPtr->window,
+ Tk_InternAtom((Tk_Window) winPtr, "_NET_WM_ICON_NAME"),
+ XA_UTF8_STRING, 8, PropModeReplace,
+ (const unsigned char*)wmPtr->iconName,
+ (signed int)strlen(wmPtr->iconName));
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ *
* UpdatePhotoIcon --
*
* This procedure is called to update the window ohoto icon.
@@ -4589,7 +4673,7 @@ WaitForEvent(display, wmInfoPtr, type, eventPtr)
oldRestrictProc = Tk_RestrictEvents(WaitRestrictProc, (ClientData) &info,
&oldRestrictData);
- TclpGetTime(&timeout);
+ Tcl_GetTime(&timeout);
timeout.sec += 2;
while (!info.foundEvent) {
@@ -5353,7 +5437,7 @@ Tk_MoveToplevelWindow(tkwin, x, y)
register WmInfo *wmPtr = winPtr->wmInfoPtr;
if (!(winPtr->flags & TK_TOP_LEVEL)) {
- panic("Tk_MoveToplevelWindow called with non-toplevel window");
+ Tcl_Panic("Tk_MoveToplevelWindow called with non-toplevel window");
}
wmPtr->x = x;
wmPtr->y = y;
@@ -5633,7 +5717,7 @@ TkWmStackorderToplevel(parentPtr)
}
}
if ((window_ptr - windows) != table.numEntries)
- panic("num matched toplevel windows does not equal num children");
+ Tcl_Panic("num matched toplevel windows does not equal num children");
*window_ptr = NULL;
if (numChildren) {
XFree((char *) children);
@@ -6278,7 +6362,7 @@ TkUnixSetMenubar(tkwin, menubar)
} else {
if ((menubarPtr->flags & TK_TOP_LEVEL)
|| (Tk_Screen(menubar) != Tk_Screen(tkwin))) {
- panic("TkUnixSetMenubar got bad menubar");
+ Tcl_Panic("TkUnixSetMenubar got bad menubar");
}
wmPtr->menuHeight = Tk_ReqHeight(menubar);
if (wmPtr->menuHeight == 0) {