From 88b0719da010bfb547b954ddb13d9ae51ae2fe30 Mon Sep 17 00:00:00 2001 From: chengyemao Date: Sun, 19 Dec 2004 18:14:26 +0000 Subject: Bug fix and feature implementation of embedded/embedding Tk --- win/tkWin.h | 14 ++++++-- win/tkWinEmbed.c | 99 ++++++++++++++++++++++++++++++++++++++++++++++++++++---- win/tkWinWm.c | 30 ++++++++++++----- win/tkWinX.c | 8 ++++- 4 files changed, 133 insertions(+), 18 deletions(-) diff --git a/win/tkWin.h b/win/tkWin.h index 6cad91c..ca7fdc8 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.7 2004/12/18 20:21:09 chengyemao Exp $ + * RCS: @(#) $Id: tkWin.h,v 1.8 2004/12/19 18:14:26 chengyemao Exp $ */ #ifndef _TKWIN @@ -30,13 +30,23 @@ /* * The following messages are used to communicate between a Tk toplevel - * and its container window. + * 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. */ #define TK_CLAIMFOCUS (WM_USER) /* an embedded window requests to focus */ #define TK_GEOMETRYREQ (WM_USER+1) /* an embedded window requests to change size */ #define TK_ATTACHWINDOW (WM_USER+2) /* an embedded window requests to attach */ #define TK_DETACHWINDOW (WM_USER+3) /* an embedded window requests to detach */ +#define TK_MOVEWINDOW (WM_USER+4) /* an embedded window requests to move */ +#define TK_RAISEWINDOW (WM_USER+5) /* an embedded window requests to raise */ +#define TK_ICONIFY (WM_USER+6) /* an embedded window requests to iconify */ +#define TK_DEICONIFY (WM_USER+7) /* an embedded window requests to deiconify */ +#define TK_WITHDRAW (WM_USER+8) /* an embedded window requests to withdraw */ +#define TK_TITLE (WM_USER+9) /* an embedded window requests to set title */ /* diff --git a/win/tkWinEmbed.c b/win/tkWinEmbed.c index 0ee1f2f..d43f3b5 100644 --- a/win/tkWinEmbed.c +++ b/win/tkWinEmbed.c @@ -11,11 +11,11 @@ * 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.12 2004/12/18 20:35:16 chengyemao Exp $ + * RCS: @(#) $Id: tkWinEmbed.c,v 1.13 2004/12/19 18:14:26 chengyemao Exp $ */ #include "tkWinInt.h" - +extern TkWinProcs *tkWinProcs; /* * One of the following structures exists for each container in this @@ -121,11 +121,19 @@ TkpTestembedCmd(clientData, interp, argc, argv) * 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 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). + * * Results: * The return value is normally TCL_OK. If an error occurred (such as - * if the argument does not identify a legal Windows window handle), - * the return value is TCL_ERROR and an error message is left in the - * the interp's result if interp is not NULL. + * if the argument does not identify a legal Windows window handle or + * it is already in use or a cancel button is pressed by a user in + * confirming the use window as a Tk container) the return value is + * TCL_ERROR and an error message is left in the the interp's result + * if interp is not NULL. * * Side effects: * None. @@ -180,6 +188,22 @@ TkpUseWindow(interp, tkwin, string) "\" doesn't have -container option set", (char *) 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 already in use", string); + Tcl_SetResult(interp, msg, TCL_VOLATILE); + 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; + } + } } /* @@ -353,6 +377,7 @@ TkWinEmbeddedEventProc(hwnd, message, wParam, lParam) WPARAM wParam; LPARAM lParam; { + int result = 1; Container *containerPtr; ThreadSpecificData *tsdPtr = (ThreadSpecificData *) Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); @@ -374,11 +399,19 @@ TkWinEmbeddedEventProc(hwnd, message, wParam, lParam) * another application) is trying to attach to this container. * We attach it only if this container is not yet containing any * window. + * + * wParam - a handle of an embedded window + * + * An embedded window may send this message with a wParam of NULL + * to test if a window is able to provide embedding service. The + * container returns its window handle for accepting the attachment + * and identifying itself or a zero for being already in use. */ if (containerPtr->embeddedHWnd == NULL) { containerPtr->embeddedHWnd = (HWND)wParam; + result = (long)containerPtr->parentHWnd; } else { - return 0; + result = 0; } break; @@ -388,11 +421,63 @@ TkWinEmbeddedEventProc(hwnd, message, wParam, lParam) break; case TK_GEOMETRYREQ: + /* + * wParam - window width + * lParam - window height + */ EmbedGeometryRequest(containerPtr, (int) wParam, lParam); break; + + case TK_RAISEWINDOW: + /* + * wParam - a window handle as a z-order stack reference + * lParam - a flag of above-below: 0 - above; 1 or others: - below + */ + TkWinSetWindowPos(GetParent(containerPtr->parentHWnd), (HWND)wParam, (int)lParam); + break; + + case TK_TITLE: + /* + * lParam - a pointer to a unicode string + */ + (*tkWinProcs->setWindowText)(GetParent(containerPtr->parentHWnd), (LPCTSTR)lParam); + break; + + case TK_CLAIMFOCUS: + /* + * wParam - a flag of forcing focus + */ + if(!SetFocus(containerPtr->embeddedHWnd) && wParam) { + /* + * forcing focus TBD + */ + } + break; + + /* + * Return 0 since the current Tk container implementation + * is unable to provide these services. + * + */ + case TK_ICONIFY: + case TK_DEICONIFY: + case TK_WITHDRAW: + result = 0; + break; + + case TK_MOVEWINDOW: + /* + * wParam - x value of the frame's upper left; + * lParam - y value of the frame's upper left; + */ + result = 0; + break; } + } else { + result = 0; } - return 1; + + return result; } /* diff --git a/win/tkWinWm.c b/win/tkWinWm.c index 603f1df..4328663 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.80 2004/12/17 14:17:54 chengyemao Exp $ + * RCS: @(#) $Id: tkWinWm.c,v 1.81 2004/12/19 18:14:26 chengyemao Exp $ */ #include "tkWinInt.h" @@ -3279,9 +3279,12 @@ WmDeiconifyCmd(tkwin, winPtr, interp, objc, objv) return TCL_ERROR; } if (winPtr->flags & TK_EMBEDDED) { - Tcl_AppendResult(interp, "can't deiconify ", winPtr->pathName, + if(!SendMessage(wmPtr->wrapper, TK_DEICONIFY, 0, 0)) { + Tcl_AppendResult(interp, "can't deiconify ", winPtr->pathName, ": it is an embedded window", (char *) NULL); - return TCL_ERROR; + return TCL_ERROR; + } + return TCL_OK; } wmPtr->flags &= ~WM_WITHDRAWN; @@ -3811,9 +3814,11 @@ WmIconifyCmd(tkwin, winPtr, interp, objc, objv) return TCL_ERROR; } if (winPtr->flags & TK_EMBEDDED) { - Tcl_AppendResult(interp, "can't iconify ", winPtr->pathName, + if(!SendMessage(wmPtr->wrapper, TK_ICONIFY, 0, 0)) { + Tcl_AppendResult(interp, "can't iconify ", winPtr->pathName, ": it is an embedded window", (char *) NULL); - return TCL_ERROR; + return TCL_ERROR; + } } TkpWmSetState(winPtr, IconicState); return TCL_OK; @@ -4913,8 +4918,13 @@ WmTitleCmd(tkwin, winPtr, interp, objc, objv) if (!(wmPtr->flags & WM_NEVER_MAPPED) && wmPtr->wrapper != NULL) { Tcl_DString titleString; Tcl_WinUtfToTChar(wmPtr->title, -1, &titleString); - (*tkWinProcs->setWindowText)(wmPtr->wrapper, + if(winPtr->flags & TK_EMBEDDED) { + SendMessage(wmPtr->wrapper, TK_TITLE, 0, + (long)(LPCTSTR)Tcl_DStringValue(&titleString)); + } else { + (*tkWinProcs->setWindowText)(wmPtr->wrapper, (LPCTSTR) Tcl_DStringValue(&titleString)); + } Tcl_DStringFree(&titleString); } } @@ -5604,7 +5614,7 @@ UpdateGeometryInfo(clientData) * the other process understands this Tk message, otherwise * our requested geometry will be ignored. */ - + SendMessage(wmPtr->wrapper, TK_MOVEWINDOW, x, y); SendMessage(wmPtr->wrapper, TK_GEOMETRYREQ, width, height); } else { int reqHeight, reqWidth; @@ -6307,7 +6317,11 @@ TkWmRestackToplevel(winPtr, aboveBelow, otherPtr) insertAfter = NULL; } - TkWinSetWindowPos(hwnd, insertAfter, aboveBelow); + if(winPtr->flags & TK_EMBEDDED) { + SendMessage(winPtr->wmInfoPtr->wrapper, TK_RAISEWINDOW, (WPARAM)insertAfter, aboveBelow); + } else { + TkWinSetWindowPos(hwnd, insertAfter, aboveBelow); + } } /* diff --git a/win/tkWinX.c b/win/tkWinX.c index 784ff18..40abdf9 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.36 2004/12/17 14:17:56 chengyemao Exp $ + * RCS: @(#) $Id: tkWinX.c,v 1.37 2004/12/19 18:14:27 chengyemao Exp $ */ #include "tkWinInt.h" @@ -814,6 +814,12 @@ TkWinChildProc(hwnd, message, wParam, lParam) case TK_GEOMETRYREQ: case TK_ATTACHWINDOW: case TK_DETACHWINDOW: + case TK_ICONIFY: + case TK_DEICONIFY: + case TK_MOVEWINDOW: + case TK_WITHDRAW: + case TK_RAISEWINDOW: + case TK_TITLE: result = TkWinEmbeddedEventProc(hwnd, message, wParam, lParam); break; -- cgit v0.12