From adaeb1b2d2e9f439ab072349dedd7bd0f414394d Mon Sep 17 00:00:00 2001 From: hobbs Date: Mon, 15 Oct 2007 20:52:46 +0000 Subject: * generic/tkFocus.c, generic/tkFrame.c, generic/tkInt.h: * macosx/tkMacOSXButton.c, macosx/tkMacOSXMenubutton.c: * macosx/tkMacOSXWm.c, unix/tkUnixWm.c, win/tkWinWm.c: * doc/wm.n, tests/wm.test: TIP #125 implementation [Bug 998125] Adds [wm manage|forget] for dockable frames. Finished X11 and Windows code, needs OS X completion. --- ChangeLog | 9 ++ doc/wm.n | 29 ++++++- generic/tkFocus.c | 129 ++++++++++++++++++++++++++++- generic/tkFrame.c | 34 +++++++- generic/tkInt.h | 5 +- macosx/tkMacOSXButton.c | 14 +++- macosx/tkMacOSXMenubutton.c | 10 ++- macosx/tkMacOSXWm.c | 197 +++++++++++++++++++++++++++++++++++++++++--- tests/wm.test | 50 ++++++++++- unix/tkUnixWm.c | 161 ++++++++++++++++++++++++++++++++++-- win/tkWinWm.c | 159 +++++++++++++++++++++++++++++++++-- 11 files changed, 756 insertions(+), 41 deletions(-) diff --git a/ChangeLog b/ChangeLog index 3cdf169..e364260 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2007-10-15 Jeff Hobbs + + * generic/tkFocus.c, generic/tkFrame.c, generic/tkInt.h: + * macosx/tkMacOSXButton.c, macosx/tkMacOSXMenubutton.c: + * macosx/tkMacOSXWm.c, unix/tkUnixWm.c, win/tkWinWm.c: + * doc/wm.n, tests/wm.test: TIP #125 implementation [Bug 998125] + Adds [wm manage|forget] for dockable frames. + Finished X11 and Windows code, needs OS X completion. + 2007-10-15 Joe English * generic/ttk/ttkTreeview.c: Store pointer to column diff --git a/doc/wm.n b/doc/wm.n index b33bb4e..caaa66a 100644 --- a/doc/wm.n +++ b/doc/wm.n @@ -5,7 +5,7 @@ '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" -'\" RCS: @(#) $Id: wm.n,v 1.29 2007/04/23 21:19:52 das Exp $ +'\" RCS: @(#) $Id: wm.n,v 1.30 2007/10/15 20:52:47 hobbs Exp $ '\" .so man.macros .TH wm n 8.5 Tk "Tk Built-In Commands" @@ -219,6 +219,13 @@ the application may re-assign the focus among \fIwindow\fR's descendants. The focus model defaults to \fBpassive\fR, and Tk's \fBfocus\fR command assumes a passive model of focusing. .TP +\fBwm forget \fIwindow\fR +The \fIwindow\fR will be unmapped from the screen and will no longer +be managed by \fBwm\fR. Windows created with the \fBtoplevel\fR +command will be treated like \fBframe\fR windows once they are no +longer managed by \fBwm\fR, however, the -menu configuration will be +remembered and the menus will return once the widget is managed again. +.TP \fBwm frame \fIwindow\fR If \fIwindow\fR has been reparented by the window manager into a decorative frame, the command returns the platform specific window @@ -398,6 +405,11 @@ an icon window; this is needed in order to allow window managers to ``own'' those events. Note: not all window managers support the notion of an icon window. .TP +\fBwm manage \fIwidget\fR + +The \fIwidget\fR specified will become a stand alone top-level window. The window will be decorated with the window managers title bar, etc. + +.TP \fBwm maxsize \fIwindow\fR ?\fIwidth height\fR? If \fIwidth\fR and \fIheight\fR are specified, they give the maximum permissible dimensions for \fIwindow\fR. @@ -604,6 +616,21 @@ all forms of resizing, including the window's natural size as well as manual resizes and the \fBwm geometry\fR command. You can also use the command \fBwm resizable\fR to completely disable interactive resizing in one or both dimensions. +.PP +The \fBwm manage\fR and \fBwm forget\fR commands may be used to +perform undocking and docking of windows. After a widget is managed +by \fBwm manage\fR command, all other \fBwm\fR subcommands may be used +with the widget. Only widgets created using the toplevel command may +have an attached menu via the -menu configure option. A toplevel +widget may be used as a frame and managed with any of the other +geometry managers after using the \fBwm forget\fR command. Any menu +associated with a toplevel widget will be hidden when managed by +another geometry managers. The menus will reappear once the window is +managed by \fBwm\fR. All custom bindtags for widgets in a subtree +that have their top-level widget changed via a \fBwm manage\fR or +\fBwm forget\fR command, must be redone to adjust any top-level widget +path in the bindtags. Bindtags that have not been customized do not +have to be redone. .SH "GRIDDED GEOMETRY MANAGEMENT" .PP Gridded geometry management occurs when one of the widgets of an diff --git a/generic/tkFocus.c b/generic/tkFocus.c index 4b929c5..37d3795 100644 --- a/generic/tkFocus.c +++ b/generic/tkFocus.c @@ -9,7 +9,7 @@ * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkFocus.c,v 1.14 2007/09/07 00:34:52 dgp Exp $ + * RCS: @(#) $Id: tkFocus.c,v 1.15 2007/10/15 20:52:47 hobbs Exp $ */ #include "tkInt.h" @@ -1044,6 +1044,133 @@ TkFocusFree( } /* + *---------------------------------------------------------------------- + * + * TkFocusSplit -- + * + * Adjust focus window for a newly managed toplevel, thus splitting + * the toplevel into two toplevels. + * + * Results: + * None. + * + * Side effects: + * A new record is allocated for the new toplevel window. + * + *---------------------------------------------------------------------- + */ + +void +TkFocusSplit(winPtr) + TkWindow *winPtr; /* Window is the new toplevel + * Any focus point at or below window + * must be moved to this new toplevel */ +{ + ToplevelFocusInfo *tlFocusPtr; + DisplayFocusInfo *displayFocusPtr; + TkWindow *topLevelPtr; + TkWindow *subWinPtr; + + displayFocusPtr = FindDisplayFocusInfo(winPtr->mainPtr, winPtr->dispPtr); + + /* + * Find the top-level window for winPtr, then find (or create) + * a record for the top-level. Also see whether winPtr and all its + * ancestors are mapped. + */ + + for (topLevelPtr = winPtr; ; topLevelPtr = topLevelPtr->parentPtr) { + if (topLevelPtr == NULL) { + /* + * The window is being deleted. No point in worrying about + * giving it the focus. + */ + return; + } + if (topLevelPtr->flags & TK_TOP_HIERARCHY) { + break; + } + } + + /* Search all focus records to find child windows of winPtr */ + for (tlFocusPtr = winPtr->mainPtr->tlFocusPtr; tlFocusPtr != NULL; + tlFocusPtr = tlFocusPtr->nextPtr) { + if (tlFocusPtr->topLevelPtr == topLevelPtr) { + break; + } + } + + if (tlFocusPtr == NULL) { + /* No focus record for this toplevel, nothing to do. */ + return; + } + + /* See if current focusWin is child of the new toplevel */ + for (subWinPtr = tlFocusPtr->focusWinPtr; + subWinPtr && subWinPtr != winPtr && subWinPtr != topLevelPtr; + subWinPtr = subWinPtr->parentPtr) {} + + if (subWinPtr == winPtr) { + /* Move focus to new toplevel */ + ToplevelFocusInfo *newTlFocusPtr; + + newTlFocusPtr = (ToplevelFocusInfo *) ckalloc(sizeof(ToplevelFocusInfo)); + newTlFocusPtr->topLevelPtr = winPtr; + newTlFocusPtr->focusWinPtr = tlFocusPtr->focusWinPtr; + newTlFocusPtr->nextPtr = winPtr->mainPtr->tlFocusPtr; + winPtr->mainPtr->tlFocusPtr = newTlFocusPtr; + /* Move old toplevel's focus to the toplevel itself */ + tlFocusPtr->focusWinPtr = topLevelPtr; + } + /* If it's not, then let focus progress naturally */ +} + +/* + *---------------------------------------------------------------------- + * + * TkFocusJoin -- + * + * Remove the focus record for this window that is nolonger managed + * + * Results: + * None. + * + * Side effects: + * A tlFocusPtr record is removed + * + *---------------------------------------------------------------------- + */ + +void +TkFocusJoin(winPtr) + TkWindow *winPtr; /* Window is no longer a toplevel */ +{ + ToplevelFocusInfo *tlFocusPtr; + ToplevelFocusInfo *tmpPtr; + + /* + * Remove old toplevel record + */ + if (winPtr && winPtr->mainPtr && winPtr->mainPtr->tlFocusPtr + && winPtr->mainPtr->tlFocusPtr->topLevelPtr == winPtr) { + tmpPtr = winPtr->mainPtr->tlFocusPtr; + winPtr->mainPtr->tlFocusPtr = tmpPtr->nextPtr; + ckfree((char *)tmpPtr); + } else { + for (tlFocusPtr = winPtr->mainPtr->tlFocusPtr; tlFocusPtr != NULL; + tlFocusPtr = tlFocusPtr->nextPtr) { + if (tlFocusPtr->nextPtr && + tlFocusPtr->nextPtr->topLevelPtr == winPtr) { + tmpPtr = tlFocusPtr->nextPtr; + tlFocusPtr->nextPtr = tmpPtr->nextPtr; + ckfree((char *)tmpPtr); + break; + } + } + } +} + +/* * Local Variables: * mode: c * c-basic-offset: 4 diff --git a/generic/tkFrame.c b/generic/tkFrame.c index 0ea4111..7343b6a 100644 --- a/generic/tkFrame.c +++ b/generic/tkFrame.c @@ -11,7 +11,7 @@ * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkFrame.c,v 1.29 2007/09/07 00:34:52 dgp Exp $ + * RCS: @(#) $Id: tkFrame.c,v 1.30 2007/10/15 20:52:47 hobbs Exp $ */ #include "default.h" @@ -943,10 +943,11 @@ ConfigureFrame( * A few of the options require additional processing. */ - if (((oldMenuName == NULL) && (framePtr->menuName != NULL)) + if ((((oldMenuName == NULL) && (framePtr->menuName != NULL)) || ((oldMenuName != NULL) && (framePtr->menuName == NULL)) || ((oldMenuName != NULL) && (framePtr->menuName != NULL) - && strcmp(oldMenuName, framePtr->menuName) != 0)) { + && strcmp(oldMenuName, framePtr->menuName) != 0)) + && framePtr->type == TYPE_TOPLEVEL) { TkSetWindowMenuBar(interp, framePtr->tkwin, oldMenuName, framePtr->menuName); } @@ -1910,6 +1911,33 @@ FrameLostSlaveProc( FrameWorldChanged((ClientData) framePtr); } +void +TkMapTopFrame (tkwin) + Tk_Window tkwin; +{ + Frame *framePtr = ((TkWindow*)tkwin)->instanceData; + Tk_OptionTable optionTable; + if (Tk_IsTopLevel(tkwin) && framePtr->type == TYPE_FRAME) { + framePtr->type = TYPE_TOPLEVEL; + Tcl_DoWhenIdle(MapFrame, (ClientData)framePtr); + if (framePtr->menuName != NULL) { + TkSetWindowMenuBar(framePtr->interp, framePtr->tkwin, NULL, + framePtr->menuName); + } + } else if (!Tk_IsTopLevel(tkwin) && framePtr->type == TYPE_TOPLEVEL) { + framePtr->type = TYPE_FRAME; + } else { + /* Not a frame or toplevel, skip it */ + return; + } + /* + * The option table has already been created so + * the cached pointer will be returned. + */ + optionTable = Tk_CreateOptionTable(framePtr->interp, optionSpecs[framePtr->type]); + framePtr->optionTable = optionTable; +} + /* *-------------------------------------------------------------- * diff --git a/generic/tkInt.h b/generic/tkInt.h index da5b746..752c5eb 100644 --- a/generic/tkInt.h +++ b/generic/tkInt.h @@ -11,7 +11,7 @@ * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: $Id: tkInt.h,v 1.79 2007/10/15 07:24:48 das Exp $ + * RCS: $Id: tkInt.h,v 1.80 2007/10/15 20:52:47 hobbs Exp $ */ #ifndef _TKINT @@ -1180,6 +1180,7 @@ MODULE_SCOPE int TkTileParseProc(ClientData clientData, MODULE_SCOPE char * TkTilePrintProc(ClientData clientData, Tk_Window tkwin, char *widgRec, int offset, Tcl_FreeProc **freeProcPtr); +MODULE_SCOPE void TkMapTopFrame(Tk_Window tkwin); MODULE_SCOPE XEvent * TkpGetBindingXEvent(Tcl_Interp *interp); MODULE_SCOPE void TkCreateExitHandler(Tcl_ExitProc *proc, ClientData clientData); @@ -1196,6 +1197,8 @@ MODULE_SCOPE void TkPrintPadAmount(Tcl_Interp *interp, MODULE_SCOPE int TkParsePadAmount(Tcl_Interp *interp, Tk_Window tkwin, Tcl_Obj *objPtr, int *pad1Ptr, int *pad2Ptr); +MODULE_SCOPE void TkFocusSplit(TkWindow *winPtr); +MODULE_SCOPE void TkFocusJoin(TkWindow *winPtr); MODULE_SCOPE int TkpAlwaysShowSelection(Tk_Window tkwin); MODULE_SCOPE void TkpDrawCharsInContext(Display * display, Drawable drawable, GC gc, Tk_Font tkfont, diff --git a/macosx/tkMacOSXButton.c b/macosx/tkMacOSXButton.c index 8f05738..6d89667 100644 --- a/macosx/tkMacOSXButton.c +++ b/macosx/tkMacOSXButton.c @@ -11,7 +11,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkMacOSXButton.c,v 1.28 2007/10/12 03:06:37 das Exp $ + * RCS: @(#) $Id: tkMacOSXButton.c,v 1.29 2007/10/15 20:52:47 hobbs Exp $ */ #include "tkMacOSXPrivate.h" @@ -863,6 +863,7 @@ TkMacOSXDrawControl( TkButton *butPtr = (TkButton *) mbPtr; TkWindow *winPtr; Rect paneRect, cntrRect; + int rebuild; winPtr = (TkWindow *) butPtr->tkwin; @@ -888,12 +889,17 @@ TkMacOSXDrawControl( * The control has been previously initialised. * It may need to be re-initialised */ - +#ifdef TK_REBUILD_TOPLEVEL + rebuild = (winPtr->flags & TK_REBUILD_TOPLEVEL); + winPtr->flags &= ~TK_REBUILD_TOPLEVEL; +#else + rebuild = 0; +#endif if (mbPtr->flags) { MacControlParams params; TkMacOSXComputeControlParams(butPtr, ¶ms); - if (bcmp(¶ms, &mbPtr->params, sizeof(params))) { + if (rebuild || bcmp(¶ms, &mbPtr->params, sizeof(params))) { /* * The type of control has changed. * Clean it up and clear the flag. @@ -931,7 +937,7 @@ TkMacOSXDrawControl( len = 0; controlTitle[0] = 0; } - if (bcmp(mbPtr->controlTitle, controlTitle, len+1)) { + if (rebuild || bcmp(mbPtr->controlTitle, controlTitle, len+1)) { CFStringRef cf = CFStringCreateWithCString(NULL, (char*) controlTitle, kCFStringEncodingUTF8); diff --git a/macosx/tkMacOSXMenubutton.c b/macosx/tkMacOSXMenubutton.c index beb8e71..fb18b2e 100644 --- a/macosx/tkMacOSXMenubutton.c +++ b/macosx/tkMacOSXMenubutton.c @@ -11,7 +11,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkMacOSXMenubutton.c,v 1.15 2007/06/29 03:20:02 das Exp $ + * RCS: @(#) $Id: tkMacOSXMenubutton.c,v 1.16 2007/10/15 20:52:47 hobbs Exp $ */ #include "tkMacOSXPrivate.h" @@ -193,8 +193,12 @@ TkpDisplayMenuButton( if (mbPtr->userPane) { MenuButtonControlParams params; bzero(¶ms, sizeof(params)); - ComputeMenuButtonControlParams(butPtr, ¶ms ); - if (bcmp(¶ms,&mbPtr->params,sizeof(params))) { + ComputeMenuButtonControlParams(butPtr, ¶ms); + if ( +#ifdef TK_REBUILD_TOPLEVEL + (winPtr->flags & TK_REBUILD_TOPLEVEL) || +#endif + bcmp(¶ms,&mbPtr->params,sizeof(params))) { if (mbPtr->userPane) { DisposeControl(mbPtr->userPane); mbPtr->userPane = NULL; diff --git a/macosx/tkMacOSXWm.c b/macosx/tkMacOSXWm.c index c51509c..5166b17 100644 --- a/macosx/tkMacOSXWm.c +++ b/macosx/tkMacOSXWm.c @@ -13,7 +13,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkMacOSXWm.c,v 1.57 2007/10/12 03:14:48 das Exp $ + * RCS: @(#) $Id: tkMacOSXWm.c,v 1.58 2007/10/15 20:52:47 hobbs Exp $ */ #include "tkMacOSXPrivate.h" @@ -113,6 +113,8 @@ static int WmDeiconifyCmd(Tk_Window tkwin, TkWindow *winPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static int WmFocusmodelCmd(Tk_Window tkwin, TkWindow *winPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); +static int WmForgetCmd(Tk_Window tkwin, TkWindow *winPtr, + Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static int WmFrameCmd(Tk_Window tkwin, TkWindow *winPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static int WmGeometryCmd(Tk_Window tkwin, TkWindow *winPtr, Tcl_Interp *interp, @@ -135,6 +137,8 @@ static int WmIconpositionCmd(Tk_Window tkwin, TkWindow *winPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static int WmIconwindowCmd(Tk_Window tkwin, TkWindow *winPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); +static int WmManageCmd(Tk_Window tkwin, TkWindow *winPtr, Tcl_Interp *interp, + int objc, Tcl_Obj *const objv[]); static int WmMaxsizeCmd(Tk_Window tkwin, TkWindow *winPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static int WmMinsizeCmd(Tk_Window tkwin, TkWindow *winPtr, Tcl_Interp *interp, @@ -168,6 +172,7 @@ static void ApplyWindowClassAttributeChanges(TkWindow *winPtr, static void ApplyMasterOverrideChanges(TkWindow *winPtr, WindowRef macWindow); static void GetMinSize(TkWindow *winPtr, int *minWidthPtr, int *minHeightPtr); static void GetMaxSize(TkWindow *winPtr, int *maxWidthPtr, int *maxHeightPtr); +static void RemapWindows(TkWindow *winPtr, MacDrawable *parentWin); /* @@ -514,21 +519,21 @@ Tk_WmObjCmd( 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", - "iconphoto", "iconposition", - "iconwindow", "maxsize", "minsize", "overrideredirect", + "command", "deiconify", "focusmodel", "forget", + "frame", "geometry", "grid", "group", + "iconbitmap", "iconify", "iconmask", "iconname", + "iconphoto", "iconposition", "iconwindow", + "manage", "maxsize", "minsize", "overrideredirect", "positionfrom", "protocol", "resizable", "sizefrom", "stackorder", "state", "title", "transient", "withdraw", 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_ICONPHOTO, WMOPT_ICONPOSITION, - WMOPT_ICONWINDOW, WMOPT_MAXSIZE, WMOPT_MINSIZE, WMOPT_OVERRIDEREDIRECT, + WMOPT_COMMAND, WMOPT_DEICONIFY, WMOPT_FOCUSMODEL, WMOPT_FORGET, + WMOPT_FRAME, WMOPT_GEOMETRY, WMOPT_GRID, WMOPT_GROUP, + WMOPT_ICONBITMAP, WMOPT_ICONIFY, WMOPT_ICONMASK, WMOPT_ICONNAME, + WMOPT_ICONPHOTO, WMOPT_ICONPOSITION, WMOPT_ICONWINDOW, + WMOPT_MANAGE, WMOPT_MAXSIZE, WMOPT_MINSIZE, WMOPT_OVERRIDEREDIRECT, WMOPT_POSITIONFROM, WMOPT_PROTOCOL, WMOPT_RESIZABLE, WMOPT_SIZEFROM, WMOPT_STACKORDER, WMOPT_STATE, WMOPT_TITLE, WMOPT_TRANSIENT, WMOPT_WITHDRAW }; @@ -569,7 +574,8 @@ wrongNumArgs: != TCL_OK) { return TCL_ERROR; } - if (!Tk_IsTopLevel(winPtr)) { + if (!Tk_IsTopLevel(winPtr) && + (index != WMOPT_MANAGE) && (index != WMOPT_FORGET)) { Tcl_AppendResult(interp, "window \"", winPtr->pathName, "\" isn't a top-level window", NULL); return TCL_ERROR; @@ -590,6 +596,8 @@ wrongNumArgs: return WmDeiconifyCmd(tkwin, winPtr, interp, objc, objv); case WMOPT_FOCUSMODEL: return WmFocusmodelCmd(tkwin, winPtr, interp, objc, objv); + case WMOPT_FORGET: + return WmForgetCmd(tkwin, winPtr, interp, objc, objv); case WMOPT_FRAME: return WmFrameCmd(tkwin, winPtr, interp, objc, objv); case WMOPT_GEOMETRY: @@ -612,6 +620,8 @@ wrongNumArgs: return WmIconpositionCmd(tkwin, winPtr, interp, objc, objv); case WMOPT_ICONWINDOW: return WmIconwindowCmd(tkwin, winPtr, interp, objc, objv); + case WMOPT_MANAGE: + return WmManageCmd(tkwin, winPtr, interp, objc, objv); case WMOPT_MAXSIZE: return WmMaxsizeCmd(tkwin, winPtr, interp, objc, objv); case WMOPT_MINSIZE: @@ -1345,6 +1355,67 @@ WmFocusmodelCmd( /* *---------------------------------------------------------------------- * + * WmForgetCmd -- + * + * This procedure is invoked to process the "wm forget" 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 +WmForgetCmd(tkwin, winPtr, interp, objc, objv) + Tk_Window tkwin; /* Main window of the application. */ + TkWindow *winPtr; /* Toplevel or Frame to work with */ + Tcl_Interp *interp; /* Current interpreter. */ + int objc; /* Number of arguments. */ + Tcl_Obj *CONST objv[]; /* Argument objects. */ +{ + register Tk_Window frameWin = (Tk_Window)winPtr; + char *oldClass = (char*)Tk_Class(frameWin); + +#if 1 + Tcl_AppendResult(interp, "wm forget is not yet supported", (char*)NULL); + return TCL_ERROR; +#else + if (Tk_IsTopLevel(frameWin)) { + MacDrawable *macWin = (MacDrawable *) winPtr->window; + CGrafPtr destPort = TkMacOSXGetDrawablePort(winPtr->window); + + TkFocusJoin(winPtr); + Tk_UnmapWindow(frameWin); + + if (destPort != NULL) { + WindowRef winRef; + winRef = GetWindowFromPort(destPort); + TkMacOSXUnregisterMacWindow(winRef); + DisposeWindow(winRef); + } + macWin->grafPtr = NULL; + macWin->toplevel = winPtr->parentPtr->privatePtr->toplevel; + macWin->flags &= ~TK_HOST_EXISTS; + + RemapWindows(winPtr, macWin); + TkWmDeadWindow(winPtr); + winPtr->flags &= ~(TK_TOP_HIERARCHY|TK_TOP_LEVEL|TK_HAS_WRAPPER|TK_WIN_MANAGED); + + TkMapTopFrame(frameWin); + } else { + /* Already not managed by wm - ignore it */ + } + return TCL_OK; +#endif +} + +/* + *---------------------------------------------------------------------- + * * WmFrameCmd -- * * This procedure is invoked to process the "wm frame" Tcl command. @@ -2038,6 +2109,67 @@ WmIconwindowCmd( /* *---------------------------------------------------------------------- * + * WmManageCmd -- + * + * This procedure is invoked to process the "wm manage" 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 +WmManageCmd( + Tk_Window tkwin, /* Main window of the application. */ + TkWindow *winPtr, /* Toplevel or Frame to work with */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *CONST objv[]) /* Argument objects. */ +{ + register Tk_Window frameWin = (Tk_Window)winPtr; + register WmInfo *wmPtr = winPtr->wmInfoPtr; + char *oldClass = (char*)Tk_Class(frameWin); + +#if 1 + Tcl_AppendResult(interp, "wm manage is not yet supported", (char*)NULL); + return TCL_ERROR; +#else + if (!Tk_IsTopLevel(frameWin)) { + MacDrawable *macWin = (MacDrawable *) winPtr->window; + + TkFocusSplit(winPtr); + Tk_UnmapWindow(frameWin); + if (wmPtr == NULL) { + TkWmNewWindow(winPtr); + if (winPtr->window == None) { + Tk_MakeWindowExist((Tk_Window) winPtr); + macWin = (MacDrawable *) winPtr->window; + } + TkWmMapWindow(winPtr); + Tk_UnmapWindow(frameWin); + } + wmPtr = winPtr->wmInfoPtr; + winPtr->flags &= ~TK_MAPPED; + macWin->grafPtr = NULL; + macWin->toplevel = macWin; + RemapWindows(winPtr, macWin); + winPtr->flags |= (TK_TOP_HIERARCHY|TK_TOP_LEVEL|TK_HAS_WRAPPER|TK_WIN_MANAGED); + TkMapTopFrame (frameWin); + } else if (Tk_IsTopLevel(frameWin)) { + /* Already managed by wm - ignore it */ + } + return TCL_OK; +#endif +} + +/* + *---------------------------------------------------------------------- + * * WmMaxsizeCmd -- * * This procedure is invoked to process the "wm maxsize" Tcl command. @@ -6234,3 +6366,44 @@ GetMaxSize( *maxHeightPtr = maxHeight; } } + +/* + *---------------------------------------------------------------------- + * + * RemapWindows + * + * Adjust parent/child relation ships of + * the given window hierarchy. + * + * Results: + * none + * + * Side effects: + * keeps windowing system (X11) happy + * + *---------------------------------------------------------------------- + */ +static void +RemapWindows(TkWindow *winPtr, MacDrawable *parentWin) +{ + TkWindow *childPtr; + + /* Remove the OS specific window. + * It will get rebuilt when the window gets Mapped. + */ + if (winPtr->window != None) { + MacDrawable *macWin = (MacDrawable *) winPtr->window; + macWin->grafPtr = NULL; + macWin->toplevel = parentWin->toplevel; + winPtr->flags &= ~TK_MAPPED; +#ifdef TK_REBUILD_TOPLEVEL + winPtr->flags |= TK_REBUILD_TOPLEVEL; +#endif + } + + /* Repeat for all the children */ + for (childPtr = winPtr->childList; childPtr != NULL; + childPtr = childPtr->nextPtr) { + RemapWindows(childPtr, (MacDrawable *) winPtr->window); + } +} diff --git a/tests/wm.test b/tests/wm.test index 39e5596..e5c5aef 100644 --- a/tests/wm.test +++ b/tests/wm.test @@ -7,7 +7,7 @@ # Copyright (c) 1998-1999 by Scriptics Corporation. # All rights reserved. # -# RCS: @(#) $Id: wm.test,v 1.37 2006/12/28 21:15:14 mdejong Exp $ +# RCS: @(#) $Id: wm.test,v 1.38 2007/10/15 20:52:48 hobbs Exp $ # This file tests window manager interactions that work across # platforms. Window manager tests that only work on a specific @@ -47,7 +47,7 @@ test wm-1.1 {Tk_WmObjCmd procedure, miscellaneous errors} { } {1 {wrong # args: should be "wm option window ?arg ...?"}} test wm-1.2 {Tk_WmObjCmd procedure, miscellaneous errors} { list [catch {wm foo} msg] $msg -} {1 {bad option "foo": must be aspect, attributes, client, colormapwindows, command, deiconify, focusmodel, frame, geometry, grid, group, iconbitmap, iconify, iconmask, iconname, iconphoto, iconposition, iconwindow, maxsize, minsize, overrideredirect, positionfrom, protocol, resizable, sizefrom, stackorder, state, title, transient, or withdraw}} +} {1 {bad option "foo": must be aspect, attributes, client, colormapwindows, command, deiconify, focusmodel, forget, frame, geometry, grid, group, iconbitmap, iconify, iconmask, iconname, iconphoto, iconposition, iconwindow, manage, maxsize, minsize, overrideredirect, positionfrom, protocol, resizable, sizefrom, stackorder, state, title, transient, or withdraw}} test wm-1.3 {Tk_WmObjCmd procedure, miscellaneous errors} { list [catch {wm command} msg] $msg } {1 {wrong # args: should be "wm option window ?arg ...?"}} @@ -2033,6 +2033,52 @@ test wm-deletion-epoch-1.1 {Deletion epoch on multiple displays} -constraints al wm deiconify $w } -returnCodes error -result {bad window path name ".t"} +### Docking test (manage, forget) ### +test wm-manage-1.1 {} { + deleteWindows + set result [list] + toplevel .t + button .t.b -text "Manage This" + pack .t.b + update + lappend result [winfo manage .t.b] + lappend result [winfo toplevel .t.b] + wm manage .t.b + update + lappend result [winfo manage .t.b] + lappend result [winfo toplevel .t.b] + wm forget .t.b + pack .t.b + update + lappend result [winfo manage .t.b] + lappend result [winfo toplevel .t.b] + set result +} {pack .t wm .t.b pack .t} + +test wm-manage-1.2 {} { + deleteWindows + set result [list] + toplevel .t + toplevel .t.t + button .t.t.b -text "Manage This" + pack .t.t.b + update + lappend result [winfo manage .t.t] + lappend result [winfo toplevel .t.t.b] + wm forget .t.t + wm forget .t.t ; # second call should be a no-op + pack .t.t + update + lappend result [winfo manage .t.t] + lappend result [winfo toplevel .t.t.b] + wm manage .t.t + wm manage .t.t ; # second call should be a no-op + wm deiconify .t.t + update + lappend result [winfo manage .t.t] + lappend result [winfo toplevel .t.t.b] +} {wm .t.t pack .t wm .t.t} + # FIXME: # Test delivery of virtual events to the WM. We could check to see diff --git a/unix/tkUnixWm.c b/unix/tkUnixWm.c index efddad2..6a8eaf6 100644 --- a/unix/tkUnixWm.c +++ b/unix/tkUnixWm.c @@ -12,7 +12,7 @@ * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkUnixWm.c,v 1.56 2007/09/07 00:34:58 dgp Exp $ + * RCS: @(#) $Id: tkUnixWm.c,v 1.57 2007/10/15 20:52:48 hobbs Exp $ */ #include "tkUnixInt.h" @@ -290,6 +290,7 @@ typedef struct TkWmInfo { */ static void TopLevelReqProc(ClientData dummy, Tk_Window tkwin); +static void RemapWindows(TkWindow *winPtr, TkWindow *parentPtr); static void MenubarReqProc(ClientData clientData, Tk_Window tkwin); static const Tk_GeomMgr wmMgrType = { @@ -336,6 +337,7 @@ static void PropertyEvent(WmInfo *wmPtr, XPropertyEvent *eventPtr); static void TkWmStackorderToplevelWrapperMap(TkWindow *winPtr, Display *display, Tcl_HashTable *reparentTable); static void TopLevelReqProc(ClientData dummy, Tk_Window tkwin); +static void RemapWindows(TkWindow *winPtr, TkWindow *parentPtr); static void UpdateCommand(TkWindow *winPtr); static void UpdateGeometryInfo(ClientData clientData); static void UpdateHints(TkWindow *winPtr); @@ -380,6 +382,9 @@ static int WmDeiconifyCmd(Tk_Window tkwin, TkWindow *winPtr, static int WmFocusmodelCmd(Tk_Window tkwin, TkWindow *winPtr, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); +static int WmForgetCmd(Tk_Window tkwin, TkWindow *winPtr, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[]); static int WmFrameCmd(Tk_Window tkwin, TkWindow *winPtr, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); @@ -413,6 +418,9 @@ static int WmIconpositionCmd(Tk_Window tkwin, TkWindow *winPtr, static int WmIconwindowCmd(Tk_Window tkwin, TkWindow *winPtr, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); +static int WmManageCmd(Tk_Window tkwin, TkWindow *winPtr, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[]); static int WmMaxsizeCmd(Tk_Window tkwin, TkWindow *winPtr, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); @@ -996,21 +1004,21 @@ Tk_WmObjCmd( Tk_Window tkwin = (Tk_Window) clientData; static CONST char *optionStrings[] = { "aspect", "attributes", "client", "colormapwindows", - "command", "deiconify", "focusmodel", "frame", + "command", "deiconify", "focusmodel", "forget", "frame", "geometry", "grid", "group", "iconbitmap", "iconify", "iconmask", "iconname", "iconphoto", "iconposition", - "iconwindow", "maxsize", "minsize", "overrideredirect", + "iconwindow", "manage", "maxsize", "minsize", "overrideredirect", "positionfrom", "protocol", "resizable", "sizefrom", "stackorder", "state", "title", "transient", "withdraw", NULL }; enum options { WMOPT_ASPECT, WMOPT_ATTRIBUTES, WMOPT_CLIENT, WMOPT_COLORMAPWINDOWS, - WMOPT_COMMAND, WMOPT_DEICONIFY, WMOPT_FOCUSMODEL, WMOPT_FRAME, + WMOPT_COMMAND, WMOPT_DEICONIFY, WMOPT_FOCUSMODEL, WMOPT_FORGET, WMOPT_FRAME, WMOPT_GEOMETRY, WMOPT_GRID, WMOPT_GROUP, WMOPT_ICONBITMAP, WMOPT_ICONIFY, WMOPT_ICONMASK, WMOPT_ICONNAME, WMOPT_ICONPHOTO, WMOPT_ICONPOSITION, - WMOPT_ICONWINDOW, WMOPT_MAXSIZE, WMOPT_MINSIZE, WMOPT_OVERRIDEREDIRECT, + WMOPT_ICONWINDOW, WMOPT_MANAGE, WMOPT_MAXSIZE, WMOPT_MINSIZE, WMOPT_OVERRIDEREDIRECT, WMOPT_POSITIONFROM, WMOPT_PROTOCOL, WMOPT_RESIZABLE, WMOPT_SIZEFROM, WMOPT_STACKORDER, WMOPT_STATE, WMOPT_TITLE, WMOPT_TRANSIENT, WMOPT_WITHDRAW }; @@ -1065,7 +1073,8 @@ Tk_WmObjCmd( return TCL_ERROR; } winPtr = (TkWindow *) targetWin; - if (!Tk_IsTopLevel(winPtr)) { + if (!Tk_IsTopLevel(winPtr) && + (index != WMOPT_MANAGE) && (index != WMOPT_FORGET)) { Tcl_AppendResult(interp, "window \"", winPtr->pathName, "\" isn't a top-level window", NULL); return TCL_ERROR; @@ -1086,6 +1095,8 @@ Tk_WmObjCmd( return WmDeiconifyCmd(tkwin, winPtr, interp, objc, objv); case WMOPT_FOCUSMODEL: return WmFocusmodelCmd(tkwin, winPtr, interp, objc, objv); + case WMOPT_FORGET: + return WmForgetCmd(tkwin, winPtr, interp, objc, objv); case WMOPT_FRAME: return WmFrameCmd(tkwin, winPtr, interp, objc, objv); case WMOPT_GEOMETRY: @@ -1108,6 +1119,8 @@ Tk_WmObjCmd( return WmIconpositionCmd(tkwin, winPtr, interp, objc, objv); case WMOPT_ICONWINDOW: return WmIconwindowCmd(tkwin, winPtr, interp, objc, objv); + case WMOPT_MANAGE: + return WmManageCmd(tkwin, winPtr, interp, objc, objv); case WMOPT_MAXSIZE: return WmMaxsizeCmd(tkwin, winPtr, interp, objc, objv); case WMOPT_MINSIZE: @@ -1757,6 +1770,48 @@ WmFocusmodelCmd( /* *---------------------------------------------------------------------- * + * WmForgetCmd -- + * + * This procedure is invoked to process the "wm forget" 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 +WmForgetCmd(tkwin, winPtr, interp, objc, objv) + Tk_Window tkwin; /* Main window of the application. */ + TkWindow *winPtr; /* Toplevel or Frame to work with */ + Tcl_Interp *interp; /* Current interpreter. */ + int objc; /* Number of arguments. */ + Tcl_Obj *CONST objv[]; /* Argument objects. */ +{ + register Tk_Window frameWin = (Tk_Window)winPtr; + + if (Tk_IsTopLevel(frameWin)) { + TkFocusJoin(winPtr); + Tk_UnmapWindow(frameWin); + TkWmDeadWindow(winPtr); + winPtr->flags &= ~(TK_TOP_HIERARCHY|TK_TOP_LEVEL|TK_HAS_WRAPPER|TK_WIN_MANAGED); + RemapWindows(winPtr, winPtr->parentPtr); + /* flags (above) must be cleared before calling */ + /* TkMapTopFrame (below) */ + TkMapTopFrame(frameWin); + } else { + /* Already not managed by wm - ignore it */ + } + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * * WmFrameCmd -- * * This function is invoked to process the "wm frame" Tcl command. See @@ -2580,6 +2635,55 @@ WmIconwindowCmd( /* *---------------------------------------------------------------------- * + * WmManageCmd -- + * + * This procedure is invoked to process the "wm manage" 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 +WmManageCmd(tkwin, winPtr, interp, objc, objv) + Tk_Window tkwin; /* Main window of the application. */ + TkWindow *winPtr; /* Toplevel or Frame to work with */ + Tcl_Interp *interp; /* Current interpreter. */ + int objc; /* Number of arguments. */ + Tcl_Obj *CONST objv[]; /* Argument objects. */ +{ + register Tk_Window frameWin = (Tk_Window)winPtr; + register WmInfo *wmPtr = winPtr->wmInfoPtr; + + if (!Tk_IsTopLevel(frameWin)) { + TkFocusSplit(winPtr); + Tk_UnmapWindow(frameWin); + winPtr->flags |= TK_TOP_HIERARCHY|TK_TOP_LEVEL|TK_HAS_WRAPPER|TK_WIN_MANAGED; + if (wmPtr == NULL) { + TkWmNewWindow(winPtr); + TkWmMapWindow(winPtr); + Tk_UnmapWindow(frameWin); + } + wmPtr = winPtr->wmInfoPtr; + winPtr->flags &= ~TK_MAPPED; + RemapWindows(winPtr, wmPtr->wrapperPtr); + /* flags (above) must be set before calling */ + /* TkMapTopFrame (below) */ + TkMapTopFrame (frameWin); + } else if (Tk_IsTopLevel(frameWin)) { + /* Already managed by wm - ignore it */ + } + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * * WmMaxsizeCmd -- * * This function is invoked to process the "wm maxsize" Tcl command. See @@ -4298,7 +4402,8 @@ TopLevelReqProc( TkWindow *winPtr = (TkWindow *) tkwin; WmInfo *wmPtr; - wmPtr = winPtr->wmInfoPtr; + if ((wmPtr = winPtr->wmInfoPtr) == NULL) + return; if ((wmPtr->width >= 0) && (wmPtr->height >= 0)) { /* @@ -6728,6 +6833,10 @@ TkUnixSetMenubar( Tk_Window parent; TkWindow *menubarPtr = (TkWindow *) menubar; + /* Could be a Frame (i.e. not a toplevel) */ + if (wmPtr == NULL) + return; + if (wmPtr->menubar != NULL) { /* * There's already a menubar for this toplevel. If it isn't the same @@ -7018,6 +7127,44 @@ TkpWmSetState( } /* + *---------------------------------------------------------------------- + * + * RemapWindows + * + * Adjust parent/child relation ships of + * the given window hierarchy. + * + * Results: + * none + * + * Side effects: + * keeps windowing system (X11) happy + * + *---------------------------------------------------------------------- + */ + +static void +RemapWindows(winPtr, parentPtr) + TkWindow *winPtr; + TkWindow *parentPtr; +{ + XWindowAttributes win_attr; + + if (winPtr->window) { + XGetWindowAttributes(winPtr->display, winPtr->window, &win_attr); + if (parentPtr == NULL) { + XReparentWindow(winPtr->display, winPtr->window, + XRootWindow(winPtr->display, winPtr->screenNum), + win_attr.x, win_attr.y); + } else if (parentPtr->window) { + XReparentWindow(parentPtr->display, winPtr->window, + parentPtr->window, + win_attr.x, win_attr.y); + } + } +} + +/* * Local Variables: * mode: c * c-basic-offset: 4 diff --git a/win/tkWinWm.c b/win/tkWinWm.c index a26e0db..6844a49 100644 --- a/win/tkWinWm.c +++ b/win/tkWinWm.c @@ -12,7 +12,7 @@ * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkWinWm.c,v 1.118 2007/09/08 16:13:45 dkf Exp $ + * RCS: @(#) $Id: tkWinWm.c,v 1.119 2007/10/15 20:52:48 hobbs Exp $ */ #include "tkWinInt.h" @@ -356,6 +356,7 @@ typedef struct TkWmInfo { */ static void TopLevelReqProc(ClientData dummy, Tk_Window tkwin); +static void RemapWindows(TkWindow *winPtr, HWND parentHWND); static const Tk_GeomMgr wmMgrType = { "wm", /* name */ @@ -480,6 +481,9 @@ static int WmDeiconifyCmd(Tk_Window tkwin, static int WmFocusmodelCmd(Tk_Window tkwin, TkWindow *winPtr, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); +static int WmForgetCmd(Tk_Window tkwin, + TkWindow *winPtr, Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[]); static int WmFrameCmd(Tk_Window tkwin, TkWindow *winPtr, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); @@ -513,6 +517,9 @@ static int WmIconpositionCmd(Tk_Window tkwin, static int WmIconwindowCmd(Tk_Window tkwin, TkWindow *winPtr, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); +static int WmManageCmd(Tk_Window tkwin, + TkWindow *winPtr, Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[]); static int WmMaxsizeCmd(Tk_Window tkwin, TkWindow *winPtr, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); @@ -2838,7 +2845,7 @@ TkWmDeadWindow( if (!(winPtr->flags & TK_EMBEDDED)) { if (wmPtr->wrapper != NULL) { DestroyWindow(wmPtr->wrapper); - } else { + } else if (winPtr->window) { DestroyWindow(Tk_GetHWND(winPtr->window)); } } else { @@ -2915,22 +2922,22 @@ Tk_WmObjCmd( Tk_Window tkwin = (Tk_Window) clientData; static CONST char *optionStrings[] = { "aspect", "attributes", "client", "colormapwindows", - "command", "deiconify", "focusmodel", "frame", + "command", "deiconify", "focusmodel", "forget", "frame", "geometry", "grid", "group", "iconbitmap", "iconify", "iconmask", "iconname", "iconphoto", "iconposition", - "iconwindow", "maxsize", "minsize", "overrideredirect", + "iconwindow", "manage", "maxsize", "minsize", "overrideredirect", "positionfrom", "protocol", "resizable", "sizefrom", "stackorder", "state", "title", "transient", "withdraw", NULL }; enum options { WMOPT_ASPECT, WMOPT_ATTRIBUTES, WMOPT_CLIENT, WMOPT_COLORMAPWINDOWS, - WMOPT_COMMAND, WMOPT_DEICONIFY, WMOPT_FOCUSMODEL, WMOPT_FRAME, + WMOPT_COMMAND, WMOPT_DEICONIFY, WMOPT_FOCUSMODEL, WMOPT_FORGET, WMOPT_FRAME, WMOPT_GEOMETRY, WMOPT_GRID, WMOPT_GROUP, WMOPT_ICONBITMAP, WMOPT_ICONIFY, WMOPT_ICONMASK, WMOPT_ICONNAME, WMOPT_ICONPHOTO, WMOPT_ICONPOSITION, - WMOPT_ICONWINDOW, WMOPT_MAXSIZE, WMOPT_MINSIZE, WMOPT_OVERRIDEREDIRECT, + WMOPT_ICONWINDOW, WMOPT_MANAGE, WMOPT_MAXSIZE, WMOPT_MINSIZE, WMOPT_OVERRIDEREDIRECT, WMOPT_POSITIONFROM, WMOPT_PROTOCOL, WMOPT_RESIZABLE, WMOPT_SIZEFROM, WMOPT_STACKORDER, WMOPT_STATE, WMOPT_TITLE, WMOPT_TRANSIENT, WMOPT_WITHDRAW @@ -2985,7 +2992,8 @@ Tk_WmObjCmd( != TCL_OK) { return TCL_ERROR; } - if (!Tk_IsTopLevel(winPtr)) { + if (!Tk_IsTopLevel(winPtr) && + (index != WMOPT_MANAGE) && (index != WMOPT_FORGET)) { Tcl_AppendResult(interp, "window \"", winPtr->pathName, "\" isn't a top-level window", NULL); return TCL_ERROR; @@ -3006,6 +3014,8 @@ Tk_WmObjCmd( return WmDeiconifyCmd(tkwin, winPtr, interp, objc, objv); case WMOPT_FOCUSMODEL: return WmFocusmodelCmd(tkwin, winPtr, interp, objc, objv); + case WMOPT_FORGET: + return WmForgetCmd(tkwin, winPtr, interp, objc, objv); case WMOPT_FRAME: return WmFrameCmd(tkwin, winPtr, interp, objc, objv); case WMOPT_GEOMETRY: @@ -3028,6 +3038,8 @@ Tk_WmObjCmd( return WmIconpositionCmd(tkwin, winPtr, interp, objc, objv); case WMOPT_ICONWINDOW: return WmIconwindowCmd(tkwin, winPtr, interp, objc, objv); + case WMOPT_MANAGE: + return WmManageCmd(tkwin, winPtr, interp, objc, objv); case WMOPT_MAXSIZE: return WmMaxsizeCmd(tkwin, winPtr, interp, objc, objv); case WMOPT_MINSIZE: @@ -3737,6 +3749,47 @@ WmFocusmodelCmd( /* *---------------------------------------------------------------------- * + * WmForgetCmd -- + * + * This procedure is invoked to process the "wm forget" 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 +WmForgetCmd(tkwin, winPtr, interp, objc, objv) + Tk_Window tkwin; /* Main window of the application. */ + TkWindow *winPtr; /* Toplevel or Frame to work with */ + Tcl_Interp *interp; /* Current interpreter. */ + int objc; /* Number of arguments. */ + Tcl_Obj *CONST objv[]; /* Argument objects. */ +{ + register Tk_Window frameWin = (Tk_Window)winPtr; + char *oldClass = (char*)Tk_Class(frameWin); + + if (Tk_IsTopLevel(frameWin)) { + Tk_UnmapWindow(frameWin); + winPtr->flags &= ~(TK_TOP_HIERARCHY|TK_TOP_LEVEL|TK_HAS_WRAPPER|TK_WIN_MANAGED); + RemapWindows(winPtr, Tk_GetHWND(winPtr->parentPtr->window)); + TkWmDeadWindow(winPtr); + /* flags (above) must be cleared before calling */ + /* TkMapTopFrame (below) */ + TkMapTopFrame(frameWin); + } else { + /* Already not managed by wm - ignore it */ + } + return TCL_OK; +} +/* + *---------------------------------------------------------------------- + * * WmFrameCmd -- * * This function is invoked to process the "wm frame" Tcl command. See @@ -4592,6 +4645,54 @@ WmIconwindowCmd( /* *---------------------------------------------------------------------- * + * WmManageCmd -- + * + * This procedure is invoked to process the "wm manage" 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 +WmManageCmd(tkwin, winPtr, interp, objc, objv) + Tk_Window tkwin; /* Main window of the application. */ + TkWindow *winPtr; /* Toplevel or Frame to work with */ + Tcl_Interp *interp; /* Current interpreter. */ + int objc; /* Number of arguments. */ + Tcl_Obj *CONST objv[]; /* Argument objects. */ +{ + register Tk_Window frameWin = (Tk_Window)winPtr; + register WmInfo *wmPtr = winPtr->wmInfoPtr; + char *oldClass = (char*)Tk_Class(frameWin); + + if (!Tk_IsTopLevel(frameWin)) { + TkFocusSplit(winPtr); + Tk_UnmapWindow(frameWin); + winPtr->flags |= TK_TOP_HIERARCHY|TK_TOP_LEVEL|TK_HAS_WRAPPER|TK_WIN_MANAGED; + RemapWindows(winPtr, NULL); + if (wmPtr == NULL) { + TkWmNewWindow(winPtr); + } + wmPtr = winPtr->wmInfoPtr; + winPtr->flags &= ~TK_MAPPED; + /* flags (above) must be set before calling */ + /* TkMapTopFrame (below) */ + TkMapTopFrame (frameWin); + } else if (Tk_IsTopLevel(frameWin)) { + /* Already managed by wm - ignore it */ + } + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * * WmMaxsizeCmd -- * * This function is invoked to process the "wm maxsize" Tcl command. See @@ -6966,6 +7067,10 @@ TkWinSetMenu( TkWindow *winPtr = (TkWindow *) tkwin; WmInfo *wmPtr = winPtr->wmInfoPtr; + /* Could be a Frame (i.e. not a Toplevel) */ + if (wmPtr == NULL) + return; + wmPtr->hMenu = hMenu; if (!(wmPtr->flags & WM_NEVER_MAPPED)) { int syncPending = wmPtr->flags & WM_SYNC_PENDING; @@ -8431,6 +8536,46 @@ TkpWinToplevelDetachWindow( } /* + *---------------------------------------------------------------------- + * + * RemapWindows + * + * Adjust parent/child relation ships of + * the given window hierarchy. + * + * Results: + * none + * + * Side effects: + * keeps windowing system happy + * + *---------------------------------------------------------------------- + */ + +static void +RemapWindows(winPtr, parentHWND) + TkWindow *winPtr; + HWND parentHWND; +{ + TkWindow *childPtr; + + /* Skip Menus as they are handled differently */ + if (strcmp(Tk_Class(winPtr), "Menu") == 0) { + return; + } + if (winPtr->window) { + SetParent(Tk_GetHWND(winPtr->window), parentHWND); + } + + /* Repeat for all the children */ + for (childPtr = winPtr->childList; childPtr != NULL; + childPtr = childPtr->nextPtr) { + RemapWindows(childPtr, + winPtr->window ? Tk_GetHWND(winPtr->window) : NULL); + } +} + +/* * Local Variables: * mode: c * c-basic-offset: 4 -- cgit v0.12