summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--win/tkWin.h21
-rw-r--r--win/tkWinEmbed.c130
-rw-r--r--win/tkWinWm.c12
-rw-r--r--win/tkWinX.c3
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;