From 755a33fa24ee2e9c505c528c743441fb070e6259 Mon Sep 17 00:00:00 2001 From: chengyemao Date: Sun, 16 Jan 2005 00:23:11 +0000 Subject: Added TK_INFO message for use in an embedded window attachment protocol; modified TkpUseWindow to allow to attach to a legacy container with a warning; modified some return values of messages from an embedded window to differentiate a case of unprocessed --- win/tkWin.h | 21 ++++++--- win/tkWinEmbed.c | 130 +++++++++++++++++++++++++++++++++++++------------------ win/tkWinWm.c | 12 ++--- win/tkWinX.c | 3 +- 4 files changed, 112 insertions(+), 54 deletions(-) diff --git a/win/tkWin.h b/win/tkWin.h index 6df0144..08d6d64 100644 --- a/win/tkWin.h +++ b/win/tkWin.h @@ -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: tkWin.h,v 1.12 2005/01/07 15:18:03 chengyemao Exp $ + * RCS: @(#) $Id: tkWin.h,v 1.13 2005/01/16 00:23:11 chengyemao Exp $ */ #ifndef _TKWIN @@ -30,11 +30,10 @@ /* * The following messages are used to communicate between a Tk toplevel - * and its container window. A zero should be returned if a Tk container - * is not able to provide a requested service. A Tk container may not be - * able to provide service to all of the following requests at the moment. - * But an embedded Tk window will send out these requests to support - * external Tk container application. + * and its container window. A Tk container may not be able to provide + * service to all of the following requests at the moment. But an embedded + * Tk window will send out these requests to support external Tk container + * application. */ #define TK_CLAIMFOCUS (WM_USER) /* an embedded window requests to focus */ @@ -50,6 +49,16 @@ #define TK_OVERRIDEREDIRECT (WM_USER+10) /* an embedded window requests to overrideredirect */ #define TK_SETMENU (WM_USER+11) /* an embedded window requests to setup menu */ #define TK_STATE (WM_USER+12) /* an embedded window sets/gets state */ +#define TK_INFO (WM_USER+13) /* an embedded window requests a container's info */ + +/* + * The following are sub-messages (wParam) for TK_INFO. An embedded window may + * send a TK_INFO message with one of the sub-messages to query a container + * for verification and availability + */ +#define TK_CONTAINER_VERIFY 0x01 +#define TK_CONTAINER_ISAVAILABLE 0x02 + /* *-------------------------------------------------------------- diff --git a/win/tkWinEmbed.c b/win/tkWinEmbed.c index dd001ea..6cfc8b4 100644 --- a/win/tkWinEmbed.c +++ b/win/tkWinEmbed.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: tkWinEmbed.c,v 1.24 2005/01/12 04:30:19 chengyemao Exp $ + * RCS: @(#) $Id: tkWinEmbed.c,v 1.25 2005/01/16 00:23:12 chengyemao Exp $ */ #include "tkWinInt.h" @@ -52,6 +52,7 @@ static void EmbedGeometryRequest _ANSI_ARGS_(( Container*containerPtr, int width, int height)); static void EmbedWindowDeleted _ANSI_ARGS_((TkWindow *winPtr)); static void Tk_MapEmbeddedWindow _ANSI_ARGS_((TkWindow* winPtr)); +HWND Tk_GetEmbeddedHWnd _ANSI_ARGS_((TkWindow* winPtr)); /* @@ -150,15 +151,29 @@ static void Tk_MapEmbeddedWindow(winPtr) * application to specify the window in which the application is * embedded. * - * This procesure sends a TK_ATTACHWINDOW message to the window to - * use. The returned value is either 0 (the window to use is already - * in use or unable to be used as a container) or the hwnd of the - * window to use (the window to use is ready to serve as a container) - * or other values (the window to use needs to be confirmed since - * this protocol was not used before Tk85). This protocol is required - * in order to verify if the window to use is a valid container. - * Without an id verification, an invalid window attachment may cause - * unexpected crashes/panics (see bug # 1096074). + * This procedure uses a simple attachment protocol by sending + * TK_INFO messages to the window to use with two sub messages: + * + * TK_CONTAINER_VERIFY - if a window handles this message, + * it should return either a (long)hwnd for a container or + * a -(long)hwnd for a non-container. + * + * TK_CONTAINER_ISAVAILABLE - a container window should return + * either a TRUE (non-zero) if it is available for use or + * a FALSE (zero) othersize. + * + * The TK_INFO messages are required in order to verify if the window + * to use is a valid container. Without an id verification, an invalid + * window attachment may cause unexpected crashes/panics (bug 1096074). + * Additional sub messages may be definded/used in future for other + * needs. + * + * We do not enforce the above protocol for the reason of backward + * compatibility. If the window to use is unable to handle TK_INFO + * messages (e.g., legacy Tk container applications before 8.5), + * a dialog box with a warning message pops up and the user is asked + * to confirm if the attachment should proceed. However, we may have + * to enforce it in future. * * Results: * The return value is normally TCL_OK. If an error occurred (such as @@ -225,28 +240,26 @@ TkpUseWindow(interp, tkwin, string) return TCL_ERROR; } - usePtr = (TkWindow *) Tk_HWNDToWindow(hwnd); - if (usePtr != NULL) { - if (!(usePtr->flags & TK_CONTAINER)) { - Tcl_AppendResult(interp, "window \"", usePtr->pathName, - "\" doesn't have -container option set", (char *) NULL); + id = SendMessage(hwnd, TK_INFO, TK_CONTAINER_VERIFY, 0); + if(id == (long)hwnd) { + if(!SendMessage(hwnd, TK_INFO, TK_CONTAINER_ISAVAILABLE, 0)) { + Tcl_AppendResult(interp, "The container is already in use", NULL); return TCL_ERROR; } - } - - id = SendMessage(hwnd, TK_ATTACHWINDOW, 0, 0); - if(id == 0 || id != (long)hwnd) { - char msg[256]; - if(id == 0) { - sprintf(msg, "The window \"%s\" is unable to be or has already been used as a container.", string); - Tcl_SetResult(interp, msg, TCL_VOLATILE); + } else if(id == -(long)hwnd) { + Tcl_AppendResult(interp, "the window to use is not a Tk container", NULL); + return TCL_ERROR; + } else { + /* + * Proceed if the user decide to do so because it can be a legacy + * container application. However we may have to return a TCL_ERROR + * in order to avoid bug 1096074 in future. + */ + char msg[256]; + sprintf(msg, "Unable to get information of window \"%s\". Attach to this\nwindow may have unpredictable results if it is not a valid container.\n\nPress Ok to proceed or Cancel to abort attaching.", string); + if(IDCANCEL == MessageBox(hwnd, msg, "Tk Warning", MB_OKCANCEL | MB_ICONWARNING)) { + Tcl_SetResult(interp, "Operation has been canceled", TCL_STATIC); return TCL_ERROR; - } else { - sprintf(msg, "The window \"%s\" failed to identify itself as a Tk container.\nPress Ok to proceed or Cancel to abort attaching.", string); - if(IDCANCEL == MessageBox(hwnd, msg, "Tk Warning", MB_OKCANCEL | MB_ICONWARNING)) { - Tcl_SetResult(interp, "Operation has been canceled", TCL_STATIC); - return TCL_ERROR; - } } } @@ -278,10 +291,7 @@ TkpUseWindow(interp, tkwin, string) containerPtr != NULL; containerPtr = containerPtr->nextPtr) { if (containerPtr->parentHWnd == hwnd) { winPtr->flags |= TK_BOTH_HALVES; - containerPtr->parentPtr = usePtr; - if(usePtr) { - containerPtr->parentPtr->flags |= TK_BOTH_HALVES; - } + containerPtr->parentPtr->flags |= TK_BOTH_HALVES; break; } } @@ -454,6 +464,37 @@ TkWinEmbeddedEventProc(hwnd, message, wParam, lParam) topwinPtr = containerPtr->parentPtr; } switch (message) { + case TK_INFO: + /* An embedded window may send this message for container + * verification and availability before attach. + * + * wParam - a sub message + * + * TK_CONTAINER_ISAVAILABLE - if the container is + * available for use? + * result = 1 for yes and 0 for no; + * + * TK_CONTAINER_VERIFY - request the container to + * verify its identification + * result = (long)hwnd if this window is a container + * -(long)hwnd otherwise + * + * lParam - N/A + */ + switch(wParam) { + case TK_CONTAINER_ISAVAILABLE: + result = containerPtr->embeddedHWnd == NULL? 1:0; + break; + + case TK_CONTAINER_VERIFY: + result = (long)containerPtr->parentHWnd; + break; + + default: + result = 0; + } + break; + case TK_ATTACHWINDOW: /* An embedded window (either from this application or from * another application) is trying to attach to this container. @@ -644,13 +685,13 @@ TkWinEmbeddedEventProc(hwnd, message, wParam, lParam) * lParam - N/A * * Return value: - * the current value of overrideredirect if the container is - * a toplevel. Otherwise -1. + * 1 + the current value of overrideredirect if the container is + * a toplevel. Otherwise 0. */ if(topwinPtr) { - result = TkpWinToplevelOverrideRedirect(topwinPtr, wParam); + result = 1+TkpWinToplevelOverrideRedirect(topwinPtr, wParam); } else { - result = -1; + result = 0; } break; @@ -686,15 +727,15 @@ TkWinEmbeddedEventProc(hwnd, message, wParam, lParam) * lParam - N/A * * Return value - * the current state or -1 if the container is not a toplevel + * 1 + the current state or 0 if the container is not a toplevel */ if(topwinPtr) { if(wParam >= 0 && wParam <= 3) { TkpWmSetState(topwinPtr, wParam); } - result = TkpWmGetState(topwinPtr); + result = 1+TkpWmGetState(topwinPtr); } else { - result = -1; + result = 0; } break; @@ -708,7 +749,14 @@ TkWinEmbeddedEventProc(hwnd, message, wParam, lParam) break; } } else { - result = 0; + if(message == TK_INFO && wParam == TK_CONTAINER_VERIFY) { + /* + * Reply the message sender: this is not a Tk container + */ + return -(long)hwnd; + } else { + result = 0; + } } return result; diff --git a/win/tkWinWm.c b/win/tkWinWm.c index 77a521b..e680145 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.93 2005/01/13 01:48:03 chengyemao Exp $ + * RCS: @(#) $Id: tkWinWm.c,v 1.94 2005/01/16 00:23:13 chengyemao Exp $ */ #include "tkWinInt.h" @@ -2241,7 +2241,7 @@ UpdateWrapper(winPtr) */ if (winPtr->flags & TK_EMBEDDED) { - if(state != SendMessage(wmPtr->wrapper, TK_STATE, state, 0)) { + if(state+1 != SendMessage(wmPtr->wrapper, TK_STATE, state, 0)) { TkpWmSetState(winPtr, NormalState); wmPtr->hints.initial_state = NormalState; } @@ -4341,7 +4341,7 @@ WmOverrideredirectCmd(tkwin, winPtr, interp, objc, objv) return TCL_ERROR; } if(winPtr->flags & TK_EMBEDDED) { - curValue = SendMessage(wmPtr->wrapper, TK_OVERRIDEREDIRECT, -1, -1); + curValue = SendMessage(wmPtr->wrapper, TK_OVERRIDEREDIRECT, -1, -1)-1; if(curValue < 0) { Tcl_AppendResult(interp, "Container does not support overrideredirect", NULL); return TCL_ERROR; @@ -4849,7 +4849,7 @@ WmStateCmd(tkwin, winPtr, interp, objc, objv) break; } - if(state != SendMessage(wmPtr->wrapper, TK_STATE, state, 0)) { + if(state+1 != SendMessage(wmPtr->wrapper, TK_STATE, state, 0)) { Tcl_AppendResult(interp, "can't change state of ", winPtr->pathName, ": the container does not support the request", (char *) NULL); @@ -4894,7 +4894,7 @@ WmStateCmd(tkwin, winPtr, interp, objc, objv) } else { int state; if(winPtr->flags & TK_EMBEDDED) - state = SendMessage(wmPtr->wrapper, TK_STATE, -1, -1); + state = SendMessage(wmPtr->wrapper, TK_STATE, -1, -1)-1; else state = wmPtr->hints.initial_state; switch (state) { @@ -7976,7 +7976,7 @@ void TkpWinToplevelDetachWindow(winPtr) { register WmInfo *wmPtr = winPtr->wmInfoPtr; if(winPtr->flags & TK_EMBEDDED) { - int state = SendMessage(wmPtr->wrapper, TK_STATE, -1, -1); + int state = SendMessage(wmPtr->wrapper, TK_STATE, -1, -1)-1; SendMessage(wmPtr->wrapper, TK_SETMENU, 0, 0); SendMessage(wmPtr->wrapper, TK_DETACHWINDOW, 0, 0); winPtr->flags &= ~TK_EMBEDDED; diff --git a/win/tkWinX.c b/win/tkWinX.c index 41cfc04..0b15aab 100644 --- a/win/tkWinX.c +++ b/win/tkWinX.c @@ -10,7 +10,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkWinX.c,v 1.41 2005/01/07 15:18:04 chengyemao Exp $ + * RCS: @(#) $Id: tkWinX.c,v 1.42 2005/01/16 00:23:15 chengyemao Exp $ */ #include "tkWinInt.h" @@ -823,6 +823,7 @@ TkWinChildProc(hwnd, message, wParam, lParam) case TK_OVERRIDEREDIRECT: case TK_SETMENU: case TK_STATE: + case TK_INFO: result = TkWinEmbeddedEventProc(hwnd, message, wParam, lParam); break; -- cgit v0.12