summaryrefslogtreecommitdiffstats
path: root/win/tkWinEmbed.c
diff options
context:
space:
mode:
Diffstat (limited to 'win/tkWinEmbed.c')
-rw-r--r--win/tkWinEmbed.c1029
1 files changed, 733 insertions, 296 deletions
diff --git a/win/tkWinEmbed.c b/win/tkWinEmbed.c
index d0e0c05..bc86019 100644
--- a/win/tkWinEmbed.c
+++ b/win/tkWinEmbed.c
@@ -1,4 +1,4 @@
-/*
+/*
* tkWinEmbed.c --
*
* This file contains platform specific procedures for Windows platforms
@@ -8,54 +8,51 @@
*
* Copyright (c) 1996-1997 Sun Microsystems, Inc.
*
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
#include "tkWinInt.h"
-
/*
* One of the following structures exists for each container in this
- * application. It keeps track of the container window and its
- * associated embedded window.
+ * application. It keeps track of the container window and its associated
+ * embedded window.
*/
typedef struct Container {
- HWND parentHWnd; /* Windows HWND to the parent window */
- TkWindow *parentPtr; /* Tk's information about the container
- * or NULL if the container isn't
- * in this process. */
- HWND embeddedHWnd; /* Windows HWND to the embedded window
- */
- TkWindow *embeddedPtr; /* Tk's information about the embedded
- * window, or NULL if the
- * embedded application isn't in
- * this process. */
- struct Container *nextPtr; /* Next in list of all containers in
- * this process. */
+ HWND parentHWnd; /* Windows HWND to the parent window */
+ TkWindow *parentPtr; /* Tk's information about the container or
+ * NULL if the container isn't in this
+ * process. */
+ HWND embeddedHWnd; /* Windows HWND to the embedded window. */
+ TkWindow *embeddedPtr; /* Tk's information about the embedded window,
+ * or NULL if the embedded application isn't
+ * in this process. */
+ HWND embeddedMenuHWnd; /* Tk's embedded menu window handler. */
+ struct Container *nextPtr; /* Next in list of all containers in this
+ * process. */
} Container;
typedef struct ThreadSpecificData {
- Container *firstContainerPtr; /* First in list of all containers
- * managed by this process. */
+ Container *firstContainerPtr;
+ /* First in list of all containers managed by
+ * this process. */
} ThreadSpecificData;
static Tcl_ThreadDataKey dataKey;
-static void CleanupContainerList _ANSI_ARGS_((
- ClientData clientData));
-static void ContainerEventProc _ANSI_ARGS_((ClientData clientData,
- XEvent *eventPtr));
-static void EmbeddedEventProc _ANSI_ARGS_((
- ClientData clientData, XEvent *eventPtr));
-static void EmbedGeometryRequest _ANSI_ARGS_((
- Container*containerPtr, int width, int height));
-static void EmbedWindowDeleted _ANSI_ARGS_((TkWindow *winPtr));
+static void ContainerEventProc(ClientData clientData,
+ XEvent *eventPtr);
+static void EmbedGeometryRequest(Container *containerPtr,
+ int width, int height);
+static void EmbedWindowDeleted(TkWindow *winPtr);
+static void Tk_MapEmbeddedWindow(TkWindow* winPtr);
+HWND Tk_GetEmbeddedHWnd(TkWindow* winPtr);
/*
*----------------------------------------------------------------------
*
- * CleanupContainerList --
+ * TkWinCleanupContainerList --
*
* Finalizes the list of containers.
*
@@ -68,20 +65,17 @@ static void EmbedWindowDeleted _ANSI_ARGS_((TkWindow *winPtr));
*----------------------------------------------------------------------
*/
- /* ARGSUSED */
-static void
-CleanupContainerList(clientData)
- ClientData clientData;
+void
+TkWinCleanupContainerList(void)
{
Container *nextPtr;
- ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
- Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
-
- for (;
- tsdPtr->firstContainerPtr != (Container *) NULL;
- tsdPtr->firstContainerPtr = nextPtr) {
- nextPtr = tsdPtr->firstContainerPtr->nextPtr;
- ckfree((char *) tsdPtr->firstContainerPtr);
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+
+ for (; tsdPtr->firstContainerPtr != (Container *) NULL;
+ tsdPtr->firstContainerPtr = nextPtr) {
+ nextPtr = tsdPtr->firstContainerPtr->nextPtr;
+ ckfree((char *) tsdPtr->firstContainerPtr);
}
tsdPtr->firstContainerPtr = (Container *) NULL;
}
@@ -104,11 +98,11 @@ CleanupContainerList(clientData)
/* ARGSUSED */
int
-TkpTestembedCmd(clientData, interp, argc, argv)
- ClientData clientData;
- Tcl_Interp *interp;
- int argc;
- CONST char **argv;
+TkpTestembedCmd(
+ ClientData clientData,
+ Tcl_Interp *interp,
+ int argc,
+ CONST char **argv)
{
return TCL_OK;
}
@@ -116,19 +110,113 @@ TkpTestembedCmd(clientData, interp, argc, argv)
/*
*----------------------------------------------------------------------
*
+ * Tk_DetachEmbeddedWindow --
+ *
+ * This function detaches an embedded window
+ *
+ * Results:
+ * No return value. Detach the embedded window.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static
+void
+Tk_DetachEmbeddedWindow(
+ TkWindow *winPtr, /* an embedded window */
+ BOOL detachFlag) /* a flag of truely detaching */
+{
+ TkpWinToplevelDetachWindow(winPtr);
+ if(detachFlag) {
+ TkpWinToplevelOverrideRedirect(winPtr, 0);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_MapEmbeddedWindow --
+ *
+ * This function is required for mapping an embedded window during idle.
+ * The input winPtr must be preserved using Tcl_Preserve before call this
+ * function and will be released by this function.
+ *
+ * Results:
+ * No return value. Map the embedded window if it is not dead.
+ *
+ * Side effects:
+ * The embedded window may change its state as the container's.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static
+void Tk_MapEmbeddedWindow(
+ TkWindow *winPtr) /* Top-level window that's about to be
+ * mapped. */
+{
+ if(!(winPtr->flags & TK_ALREADY_DEAD)) {
+ HWND hwnd = (HWND)winPtr->privatePtr;
+ int state = SendMessage(hwnd, TK_STATE, -1, -1) - 1;
+
+ if (state < 0 || state > 3) {
+ state = NormalState;
+ }
+
+ while (Tcl_DoOneEvent(TCL_IDLE_EVENTS)) {
+ /* empty body */
+ }
+
+ TkpWmSetState(winPtr, state);
+ TkWmMapWindow(winPtr);
+ }
+ Tcl_Release((ClientData)winPtr);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
* TkpUseWindow --
*
- * This procedure causes a Tk window to use a given Windows handle
- * for a window as its underlying window, rather than a new Windows
- * window being created automatically. It is invoked by an embedded
- * application to specify the window in which the application is
- * embedded.
+ * This procedure causes a Tk window to use a given Windows handle for a
+ * window as its underlying window, rather than a new Windows window
+ * being created automatically. It is invoked by an embedded application
+ * to specify the window in which the application is embedded.
+ *
+ * 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
- * 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.
+ * The return value is normally TCL_OK. If an error occurred (such as 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.
@@ -136,31 +224,45 @@ TkpTestembedCmd(clientData, interp, argc, argv)
*----------------------------------------------------------------------
*/
-int
-TkpUseWindow(interp, tkwin, string)
- Tcl_Interp *interp; /* If not NULL, used for error reporting
- * if string is bogus. */
- Tk_Window tkwin; /* Tk window that does not yet have an
+int
+TkpUseWindow(
+ Tcl_Interp *interp, /* If not NULL, used for error reporting if
+ * string is bogus. */
+ Tk_Window tkwin, /* Tk window that does not yet have an
* associated X window. */
- CONST char *string; /* String identifying an X window to use
- * for tkwin; must be an integer value. */
+ CONST char *string) /* String identifying an X window to use for
+ * tkwin; must be an integer value. */
{
TkWindow *winPtr = (TkWindow *) tkwin;
- TkWindow *usePtr;
int id;
HWND hwnd;
- Container *containerPtr;
- ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
- Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+/*
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+*/
+/*
if (winPtr->window != None) {
- panic("TkpUseWindow: Already assigned a window");
+ Tcl_AppendResult(interp,
+ "can't modify container after widget is created", NULL);
+ return TCL_ERROR;
+ }
+*/
+
+ if (strcmp(string, "") == 0) {
+ if (winPtr->flags & TK_EMBEDDED) {
+ Tk_DetachEmbeddedWindow(winPtr, TRUE);
+ }
+ return TCL_OK;
}
if (Tcl_GetInt(interp, string, &id) != TCL_OK) {
- return TCL_ERROR;
+ return TCL_ERROR;
}
hwnd = (HWND) id;
+ if ((HWND)winPtr->privatePtr == hwnd) {
+ return TCL_OK;
+ }
/*
* Check if the window is a valid handle. If it is invalid, return
@@ -169,81 +271,58 @@ TkpUseWindow(interp, tkwin, string)
*/
if (!IsWindow(hwnd)) {
- if (interp != (Tcl_Interp *) NULL) {
- Tcl_AppendResult(interp, "window \"", string,
- "\" doesn't exist", (char *) NULL);
- }
- return TCL_ERROR;
+ if (interp != NULL) {
+ Tcl_AppendResult(interp, "window \"", string,
+ "\" doesn't exist", NULL);
+ }
+ 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;
+ }
+ } 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 \"%.80s\". 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;
}
}
+ Tk_DetachEmbeddedWindow(winPtr, FALSE);
+
/*
* Store the parent window in the platform private data slot so
* TkWmMapWindow can use it when creating the wrapper window.
*/
winPtr->privatePtr = (struct TkWindowPrivate*) hwnd;
+ winPtr->flags |= TK_EMBEDDED;
+ winPtr->flags &= ~(TK_MAPPED);
/*
- * Create an event handler to clean up the Container structure when
- * tkwin is eventually deleted.
- */
-
- Tk_CreateEventHandler(tkwin, StructureNotifyMask, EmbeddedEventProc,
- (ClientData) winPtr);
-
- /*
- * If this is the first container, register an exit handler so that
- * things will get cleaned up at finalization.
- */
-
- if (tsdPtr->firstContainerPtr == (Container *) NULL) {
- TkCreateExitHandler(CleanupContainerList, (ClientData) NULL);
- }
-
- /*
- * Save information about the container and the embedded window
- * in a Container structure. If there is already an existing
- * Container structure, it means that both container and embedded
- * app. are in the same process.
+ * Preserve the winPtr and create an idle handler to map the embedded
+ * window.
*/
- for (containerPtr = tsdPtr->firstContainerPtr;
- containerPtr != NULL; containerPtr = containerPtr->nextPtr) {
- if (containerPtr->parentHWnd == hwnd) {
- winPtr->flags |= TK_BOTH_HALVES;
- containerPtr->parentPtr->flags |= TK_BOTH_HALVES;
- break;
- }
- }
- if (containerPtr == NULL) {
- containerPtr = (Container *) ckalloc(sizeof(Container));
- containerPtr->parentPtr = NULL;
- containerPtr->parentHWnd = hwnd;
- containerPtr->nextPtr = tsdPtr->firstContainerPtr;
- tsdPtr->firstContainerPtr = containerPtr;
- }
-
- /*
- * embeddedHWnd is not created yet. It will be created by TkWmMapWindow(),
- * which will send a TK_ATTACHWINDOW to the container window.
- * TkWinEmbeddedEventProc will process this message and set the embeddedHWnd
- * variable
- */
-
- containerPtr->embeddedPtr = winPtr;
- containerPtr->embeddedHWnd = NULL;
-
- winPtr->flags |= TK_EMBEDDED;
- winPtr->flags &= (~(TK_MAPPED));
+ Tcl_Preserve((ClientData) winPtr);
+ Tcl_DoWhenIdle((Tcl_IdleProc*) Tk_MapEmbeddedWindow, (ClientData) winPtr);
return TCL_OK;
}
@@ -253,10 +332,10 @@ TkpUseWindow(interp, tkwin, string)
*
* TkpMakeContainer --
*
- * This procedure is called to indicate that a particular window will
- * be a container for an embedded application. This changes certain
- * aspects of the window's behavior, such as whether it will receive
- * events anymore.
+ * This procedure is called to indicate that a particular window will be
+ * a container for an embedded application. This changes certain aspects
+ * of the window's behavior, such as whether it will receive events
+ * anymore.
*
* Results:
* None.
@@ -268,26 +347,17 @@ TkpUseWindow(interp, tkwin, string)
*/
void
-TkpMakeContainer(tkwin)
- Tk_Window tkwin;
+TkpMakeContainer(
+ Tk_Window tkwin)
{
TkWindow *winPtr = (TkWindow *) tkwin;
Container *containerPtr;
- ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
- Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
/*
- * If this is the first container, register an exit handler so that
- * things will get cleaned up at finalization.
- */
-
- if (tsdPtr->firstContainerPtr == (Container *) NULL) {
- TkCreateExitHandler(CleanupContainerList, (ClientData) NULL);
- }
-
- /*
- * Register the window as a container so that, for example, we can
- * find out later if the embedded app. is in the same process.
+ * Register the window as a container so that, for example, we can find
+ * out later if the embedded app. is in the same process.
*/
Tk_MakeWindowExist(tkwin);
@@ -296,54 +366,23 @@ TkpMakeContainer(tkwin)
containerPtr->parentHWnd = Tk_GetHWND(Tk_WindowId(tkwin));
containerPtr->embeddedHWnd = NULL;
containerPtr->embeddedPtr = NULL;
+ containerPtr->embeddedMenuHWnd = NULL;
containerPtr->nextPtr = tsdPtr->firstContainerPtr;
tsdPtr->firstContainerPtr = containerPtr;
winPtr->flags |= TK_CONTAINER;
/*
- * Unlike in tkUnixEmbed.c, we don't make any requests for events
- * in the embedded window here. Now we just allow the embedding
- * of another TK application into TK windows. When the embedded
- * window makes a request, that will be done by sending to the
- * container window a WM_USER message, which will be intercepted
- * by TkWinContainerProc.
+ * Unlike in tkUnixEmbed.c, we don't make any requests for events in the
+ * embedded window here. Now we just allow the embedding of another TK
+ * application into TK windows. When the embedded window makes a request,
+ * that will be done by sending to the container window a WM_USER message,
+ * which will be intercepted by TkWinContainerProc.
*
* We need to get structure events of the container itself, though.
*/
Tk_CreateEventHandler(tkwin, StructureNotifyMask,
- ContainerEventProc, (ClientData) containerPtr);
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * EmbeddedEventProc --
- *
- * This procedure is invoked by the Tk event dispatcher when various
- * useful events are received for a window that is embedded in
- * another application.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Our internal state gets cleaned up when an embedded window is
- * destroyed.
- *
- *----------------------------------------------------------------------
- */
-
-static void
-EmbeddedEventProc(clientData, eventPtr)
- ClientData clientData; /* Token for container window. */
- XEvent *eventPtr; /* ResizeRequest event. */
-{
- TkWindow *winPtr = (TkWindow *) clientData;
-
- if (eventPtr->type == DestroyNotify) {
- EmbedWindowDeleted(winPtr);
- }
+ ContainerEventProc, (ClientData) containerPtr);
}
/*
@@ -351,32 +390,32 @@ EmbeddedEventProc(clientData, eventPtr)
*
* TkWinEmbeddedEventProc --
*
- * This procedure is invoked by the Tk event dispatcher when
- * various useful events are received for the *children* of a
- * container window. It forwards relevant information, such as
- * geometry requests, from the events into the container's
- * application.
+ * This procedure is invoked by the Tk event dispatcher when various
+ * useful events are received for the *children* of a container window.
+ * It forwards relevant information, such as geometry requests, from the
+ * events into the container's application.
*
* Results:
* None.
*
* Side effects:
- * Depends on the event. For example, when ConfigureRequest events
- * occur, geometry information gets set for the container window.
+ * Depends on the event. For example, when ConfigureRequest events occur,
+ * geometry information gets set for the container window.
*
*----------------------------------------------------------------------
*/
LRESULT
-TkWinEmbeddedEventProc(hwnd, message, wParam, lParam)
- HWND hwnd;
- UINT message;
- WPARAM wParam;
- LPARAM lParam;
+TkWinEmbeddedEventProc(
+ HWND hwnd,
+ UINT message,
+ WPARAM wParam,
+ LPARAM lParam)
{
+ int result = 1;
Container *containerPtr;
- ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
- Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
/*
* Find the Container structure associated with the parent window.
@@ -388,29 +427,345 @@ TkWinEmbeddedEventProc(hwnd, message, wParam, lParam)
/* empty loop body */
}
- if (containerPtr == NULL) {
- Tcl_Panic("TkWinContainerProc couldn't find Container record");
- }
+ if (containerPtr) {
+ TkWindow *topwinPtr = NULL;
+ if(Tk_IsTopLevel(containerPtr->parentPtr)) {
+ 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 (message) {
- case TK_ATTACHWINDOW:
- /* An embedded window (either from this application or from
- * another application) is trying to attach to this container.
- * We attach it only if this container is not yet containing any
- * window.
- */
- if (containerPtr->embeddedHWnd == NULL) {
- containerPtr->embeddedHWnd = (HWND)wParam;
- } else {
- return 0;
+ 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. We
+ * attach it only if this container is not yet containing any
+ * window.
+ *
+ * wParam - a handle of an embedded window
+ * lParam - N/A
+ *
+ * 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.
+ *
+ * Return value:
+ * 0 - the container is unable to be used.
+ * hwnd - the container is ready to be used.
+ */
+ if (containerPtr->embeddedHWnd == NULL) {
+ if (wParam) {
+ TkWindow *winPtr = (TkWindow *)
+ Tk_HWNDToWindow((HWND) wParam);
+ if (winPtr) {
+ winPtr->flags |= TK_BOTH_HALVES;
+ containerPtr->embeddedPtr = winPtr;
+ containerPtr->parentPtr->flags |= TK_BOTH_HALVES;
+ }
+ containerPtr->embeddedHWnd = (HWND)wParam;
+ }
+ result = (long)containerPtr->parentHWnd;
+ } else {
+ result = 0;
+ }
+ break;
+
+ case TK_DETACHWINDOW:
+ /*
+ * An embedded window notifies the container that it is detached.
+ * The container should clearn the related variables and redraw
+ * its window.
+ *
+ * wParam - N/A
+ * lParam - N/A
+ *
+ * Return value:
+ * 0 - the message is not processed.
+ * others - the message is processed.
+ */
+
+ containerPtr->embeddedMenuHWnd = NULL;
+ containerPtr->embeddedHWnd = NULL;
+ containerPtr->parentPtr->flags &= ~TK_BOTH_HALVES;
+ if (topwinPtr) {
+ TkWinSetMenu((Tk_Window) topwinPtr, 0);
+ }
+ InvalidateRect(hwnd, NULL, TRUE);
+ break;
+
+ case TK_GEOMETRYREQ:
+ /*
+ * An embedded window requests a window size change.
+ *
+ * wParam - window width
+ * lParam - window height
+ *
+ * Return value:
+ * 0 - the message is not processed.
+ * others - the message is processed.
+ */
+
+ EmbedGeometryRequest(containerPtr, (int)wParam, lParam);
+ break;
+
+ case TK_RAISEWINDOW:
+ /*
+ * An embedded window requests to change its Z-order.
+ *
+ * wParam - a window handle as a z-order stack reference
+ * lParam - a flag of above-below: 0 - above; 1 or others: - below
+ *
+ * Return value:
+ * 0 - the message is not processed.
+ * others - the message is processed.
+ */
+
+ TkWinSetWindowPos(GetParent(containerPtr->parentHWnd),
+ (HWND)wParam, (int)lParam);
+ break;
+
+ case TK_GETFRAMEWID:
+ /*
+ * An embedded window requests to get the frame window's id.
+ *
+ * wParam - N/A
+ * lParam - N/A
+ *
+ * Return vlaue:
+ *
+ * A handle of the frame window. If it is not availble, a zero is
+ * returned.
+ */
+ if (topwinPtr) {
+ result = (long)GetParent(containerPtr->parentHWnd);
+ } else {
+ topwinPtr = containerPtr->parentPtr;
+ while (!(topwinPtr->flags & TK_TOP_HIERARCHY)) {
+ topwinPtr = topwinPtr->parentPtr;
+ }
+ if (topwinPtr && topwinPtr->window) {
+ result = (long)GetParent(Tk_GetHWND(topwinPtr->window));
+ } else {
+ result = 0;
+ }
+ }
+ break;
+
+ case TK_CLAIMFOCUS:
+ /*
+ * An embedded window requests a focus.
+ *
+ * wParam - a flag of forcing focus
+ * lParam - N/A
+ *
+ * Return value:
+ * 0 - the message is not processed
+ * 1 - the message is processed
+ */
+
+ if (!SetFocus(containerPtr->embeddedHWnd) && wParam) {
+ /*
+ * forcing focus TBD
+ */
+ }
+ break;
+
+ case TK_WITHDRAW:
+ /*
+ * An embedded window requests withdraw.
+ *
+ * wParam - N/A
+ * lParam - N/A
+ *
+ * Return value
+ * 0 - the message is not processed
+ * 1 - the message is processed
+ */
+
+ if (topwinPtr) {
+ TkpWinToplevelWithDraw(topwinPtr);
+ } else {
+ result = 0;
+ }
+ break;
+
+ case TK_ICONIFY:
+ /*
+ * An embedded window requests iconification.
+ *
+ * wParam - N/A
+ * lParam - N/A
+ *
+ * Return value
+ * 0 - the message is not processed
+ * 1 - the message is processed
+ */
+
+ if (topwinPtr) {
+ TkpWinToplevelIconify(topwinPtr);
+ } else {
+ result = 0;
+ }
+ break;
+
+ case TK_DEICONIFY:
+ /*
+ * An embedded window requests deiconification.
+ *
+ * wParam - N/A
+ * lParam - N/A
+ *
+ * Return value
+ * 0 - the message is not processed
+ * 1 - the message is processed
+ */
+ if (topwinPtr) {
+ TkpWinToplevelDeiconify(topwinPtr);
+ } else {
+ result = 0;
+ }
+ break;
+
+ case TK_MOVEWINDOW:
+ /*
+ * An embedded window requests to move position if both wParam and
+ * lParam are greater or equal to 0.
+ * wParam - x value of the frame's upper left
+ * lParam - y value of the frame's upper left
+ *
+ * Otherwise an embedded window requests the current position
+ *
+ * Return value: an encoded window position in a 32bit long, i.e,
+ * ((x << 16) & 0xffff0000) | (y & 0xffff)
+ *
+ * Only a toplevel container may move the embedded.
+ */
+
+ result = TkpWinToplevelMove(containerPtr->parentPtr,
+ wParam, lParam);
+ break;
+
+ case TK_OVERRIDEREDIRECT:
+ /*
+ * An embedded window request overrideredirect.
+ *
+ * wParam
+ * 0 - add a frame if there is no one
+ * 1 - remove the frame if there is a one
+ * < 0 - query the current overrideredirect value
+ *
+ * lParam - N/A
+ *
+ * Return value:
+ * 1 + the current value of overrideredirect if the container is a
+ * toplevel. Otherwise 0.
+ */
+ if (topwinPtr) {
+ result = 1 + TkpWinToplevelOverrideRedirect(topwinPtr, wParam);
+ } else {
+ result = 0;
+ }
+ break;
+
+ case TK_SETMENU:
+ /*
+ * An embedded requests to set a menu.
+ *
+ * wParam - a menu handle
+ * lParam - a menu window handle
+ *
+ * Return value:
+ * 1 - the message is processed
+ * 0 - the message is not processed
+ */
+ if (topwinPtr) {
+ containerPtr->embeddedMenuHWnd = (HWND)lParam;
+ TkWinSetMenu((Tk_Window)topwinPtr, (HMENU)wParam);
+ } else {
+ result = 0;
+ }
+ break;
+
+ case TK_STATE:
+ /*
+ * An embedded window request set/get state services.
+ *
+ * wParam - service directive
+ * 0 - 3 for setting state
+ * 0 - withdrawn state
+ * 1 - normal state
+ * 2 - zoom state
+ * 3 - icon state
+ * others for gettting state
+ *
+ * lParam - N/A
+ *
+ * Return value
+ * 1 + the current state or 0 if the container is not a toplevel
+ */
+
+ if (topwinPtr) {
+ if (wParam <= 3) {
+ TkpWmSetState(topwinPtr, wParam);
+ }
+ result = 1+TkpWmGetState(topwinPtr);
+ } else {
+ result = 0;
+ }
+ break;
+
+ /*
+ * Return 0 since the current Tk container implementation is
+ * unable to provide following services.
+ */
+ default:
+ result = 0;
+ break;
}
+ } else {
+ if ((message == TK_INFO) && (wParam == TK_CONTAINER_VERIFY)) {
+ /*
+ * Reply the message sender: this is not a Tk container
+ */
- break;
- case TK_GEOMETRYREQ:
- EmbedGeometryRequest(containerPtr, (int) wParam, lParam);
- break;
+ return -(long)hwnd;
+ } else {
+ result = 0;
+ }
}
- return 1;
+
+ return result;
}
/*
@@ -418,39 +773,40 @@ TkWinEmbeddedEventProc(hwnd, message, wParam, lParam)
*
* EmbedGeometryRequest --
*
- * This procedure is invoked when an embedded application requests
- * a particular size. It processes the request (which may or may
- * not actually resize the window) and reflects the results back
- * to the embedded application.
+ * This procedure is invoked when an embedded application requests a
+ * particular size. It processes the request (which may or may not
+ * actually resize the window) and reflects the results back to the
+ * embedded application.
*
* Results:
* None.
*
* Side effects:
- * If we deny the child's size change request, a Configure event
- * is synthesized to let the child know that the size is the same
- * as it used to be. Events get processed while we're waiting for
- * the geometry managers to do their thing.
+ * If we deny the child's size change request, a Configure event is
+ * synthesized to let the child know that the size is the same as it used
+ * to be. Events get processed while we're waiting for the geometry
+ * managers to do their thing.
*
*----------------------------------------------------------------------
*/
void
-EmbedGeometryRequest(containerPtr, width, height)
- Container *containerPtr; /* Information about the container window. */
- int width, height; /* Size that the child has requested. */
+EmbedGeometryRequest(
+ Container *containerPtr, /* Information about the container window. */
+ int width, int height) /* Size that the child has requested. */
{
- TkWindow * winPtr = containerPtr->parentPtr;
-
+ TkWindow *winPtr = containerPtr->parentPtr;
+
/*
- * Forward the requested size into our geometry management hierarchy
- * via the container window. We need to send a Configure event back
- * to the embedded application even if we decide not to resize
- * the window; to make this happen, process all idle event handlers
- * synchronously here (so that the geometry managers have had a
- * chance to do whatever they want to do), and if the window's size
- * didn't change then generate a configure event.
+ * Forward the requested size into our geometry management hierarchy via
+ * the container window. We need to send a Configure event back to the
+ * embedded application even if we decide not to resize the window; to
+ * make this happen, process all idle event handlers synchronously here
+ * (so that the geometry managers have had a chance to do whatever they
+ * want to do), and if the window's size didn't change then generate a
+ * configure event.
*/
+
Tk_GeometryRequest((Tk_Window)winPtr, width, height);
if (containerPtr->embeddedHWnd != NULL) {
@@ -458,8 +814,8 @@ EmbedGeometryRequest(containerPtr, width, height)
/* Empty loop body. */
}
- SetWindowPos(containerPtr->embeddedHWnd, NULL,
- 0, 0, winPtr->changes.width, winPtr->changes.height, SWP_NOZORDER);
+ SetWindowPos(containerPtr->embeddedHWnd, NULL, 0, 0,
+ winPtr->changes.width, winPtr->changes.height, SWP_NOZORDER);
}
}
@@ -468,38 +824,41 @@ EmbedGeometryRequest(containerPtr, width, height)
*
* ContainerEventProc --
*
- * This procedure is invoked by the Tk event dispatcher when
- * various useful events are received for the container window.
+ * This procedure is invoked by the Tk event dispatcher when various
+ * useful events are received for the container window.
*
* Results:
* None.
*
* Side effects:
- * Depends on the event. For example, when ConfigureRequest events
- * occur, geometry information gets set for the container window.
+ * Depends on the event. For example, when ConfigureRequest events occur,
+ * geometry information gets set for the container window.
*
*----------------------------------------------------------------------
*/
static void
-ContainerEventProc(clientData, eventPtr)
- ClientData clientData; /* Token for container window. */
- XEvent *eventPtr; /* ResizeRequest event. */
+ContainerEventProc(
+ ClientData clientData, /* Token for container window. */
+ XEvent *eventPtr) /* ResizeRequest event. */
{
Container *containerPtr = (Container *)clientData;
Tk_Window tkwin = (Tk_Window)containerPtr->parentPtr;
if (eventPtr->type == ConfigureNotify) {
- if (containerPtr->embeddedPtr == NULL) {
- return;
- }
- /* Resize the embedded window, if there is any */
+ /*
+ * Resize the embedded window, if there is any.
+ */
+
if (containerPtr->embeddedHWnd) {
- SetWindowPos(containerPtr->embeddedHWnd, NULL,
- 0, 0, Tk_Width(tkwin), Tk_Height(tkwin), SWP_NOZORDER);
+ SetWindowPos(containerPtr->embeddedHWnd, NULL, 0, 0,
+ Tk_Width(tkwin), Tk_Height(tkwin), SWP_NOZORDER);
}
} else if (eventPtr->type == DestroyNotify) {
- /* The container is gone, remove it from the list */
+ /*
+ * The container is gone, remove it from the list.
+ */
+
EmbedWindowDeleted(containerPtr->parentPtr);
}
}
@@ -509,13 +868,13 @@ ContainerEventProc(clientData, eventPtr)
*
* TkpGetOtherWindow --
*
- * If both the container and embedded window are in the same
- * process, this procedure will return either one, given the other.
+ * If both the container and embedded window are in the same process,
+ * this procedure will return either one, given the other.
*
* Results:
* If winPtr is a container, the return value is the token for the
- * embedded window, and vice versa. If the "other" window isn't in
- * this process, NULL is returned.
+ * embedded window, and vice versa. If the "other" window isn't in this
+ * process, NULL is returned.
*
* Side effects:
* None.
@@ -524,13 +883,13 @@ ContainerEventProc(clientData, eventPtr)
*/
TkWindow *
-TkpGetOtherWindow(winPtr)
- TkWindow *winPtr; /* Tk's structure for a container or
- * embedded window. */
+TkpGetOtherWindow(
+ TkWindow *winPtr) /* Tk's structure for a container or embedded
+ * window. */
{
Container *containerPtr;
- ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
- Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
for (containerPtr = tsdPtr->firstContainerPtr; containerPtr != NULL;
containerPtr = containerPtr->nextPtr) {
@@ -546,12 +905,81 @@ TkpGetOtherWindow(winPtr)
/*
*----------------------------------------------------------------------
*
+ * Tk_GetEmbeddedHWnd --
+ *
+ * This function returns the embedded window id.
+ *
+ * Results:
+ * If winPtr is a container, the return value is the HWND for the
+ * embedded window. Otherwise it returns NULL.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+HWND
+Tk_GetEmbeddedHWnd(
+ TkWindow *winPtr)
+{
+ Container *containerPtr;
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+
+ for (containerPtr = tsdPtr->firstContainerPtr; containerPtr != NULL;
+ containerPtr = containerPtr->nextPtr) {
+ if (containerPtr->parentPtr == winPtr) {
+ return containerPtr->embeddedHWnd;
+ }
+ }
+ return NULL;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_GetEmbeddedMenuHWND --
+ *
+ * This function returns the embedded menu window id.
+ *
+ * Results:
+ * If winPtr is a container, the return value is the HWND for the
+ * embedded menu window. Otherwise it returns NULL.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+HWND
+Tk_GetEmbeddedMenuHWND(
+ Tk_Window tkwin)
+{
+ TkWindow *winPtr = (TkWindow*)tkwin;
+ Container *containerPtr;
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+
+ for (containerPtr = tsdPtr->firstContainerPtr; containerPtr != NULL;
+ containerPtr = containerPtr->nextPtr) {
+ if (containerPtr->parentPtr == winPtr) {
+ return containerPtr->embeddedMenuHWnd;
+ }
+ }
+ return NULL;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
* TkpClaimFocus --
*
- * This procedure is invoked when someone asks or the input focus
- * to be put on a window in an embedded application, but the
- * application doesn't currently have the focus. It requests the
- * input focus from the container application.
+ * This procedure is invoked when someone asks or the input focus to be
+ * put on a window in an embedded application, but the application
+ * doesn't currently have the focus. It requests the input focus from the
+ * container application.
*
* Results:
* None.
@@ -563,12 +991,12 @@ TkpGetOtherWindow(winPtr)
*/
void
-TkpClaimFocus(topLevelPtr, force)
- TkWindow *topLevelPtr; /* Top-level window containing desired
- * focus window; should be embedded. */
- int force; /* One means that the container should
- * claim the focus if it doesn't
- * currently have it. */
+TkpClaimFocus(
+ TkWindow *topLevelPtr, /* Top-level window containing desired focus
+ * window; should be embedded. */
+ int force) /* One means that the container should claim
+ * the focus if it doesn't currently have
+ * it. */
{
HWND hwnd = GetParent(Tk_GetHWND(topLevelPtr->window));
SendMessage(hwnd, TK_CLAIMFOCUS, (WPARAM) force, 0);
@@ -579,13 +1007,13 @@ TkpClaimFocus(topLevelPtr, force)
*
* TkpRedirectKeyEvent --
*
- * This procedure is invoked when a key press or release event
- * arrives for an application that does not believe it owns the
- * input focus. This can happen because of embedding; for example,
- * X can send an event to an embedded application when the real
- * focus window is in the container application and is an ancestor
- * of the container. This procedure's job is to forward the event
- * back to the application where it really belongs.
+ * This procedure is invoked when a key press or release event arrives
+ * for an application that does not believe it owns the input focus.
+ * This can happen because of embedding; for example, X can send an event
+ * to an embedded application when the real focus window is in the
+ * container application and is an ancestor of the container. This
+ * procedure's job is to forward the event back to the application where
+ * it really belongs.
*
* Results:
* None.
@@ -597,11 +1025,11 @@ TkpClaimFocus(topLevelPtr, force)
*/
void
-TkpRedirectKeyEvent(winPtr, eventPtr)
- TkWindow *winPtr; /* Window to which the event was originally
+TkpRedirectKeyEvent(
+ TkWindow *winPtr, /* Window to which the event was originally
* reported. */
- XEvent *eventPtr; /* X event to redirect (should be KeyPress
- * or KeyRelease). */
+ XEvent *eventPtr) /* X event to redirect (should be KeyPress or
+ * KeyRelease). */
{
/* not implemented */
}
@@ -611,9 +1039,9 @@ TkpRedirectKeyEvent(winPtr, eventPtr)
*
* EmbedWindowDeleted --
*
- * This procedure is invoked when a window involved in embedding
- * (as either the container or the embedded application) is
- * destroyed. It cleans up the Container structure for the window.
+ * This procedure is invoked when a window involved in embedding (as
+ * either the container or the embedded application) is destroyed. It
+ * cleans up the Container structure for the window.
*
* Results:
* None.
@@ -625,19 +1053,18 @@ TkpRedirectKeyEvent(winPtr, eventPtr)
*/
static void
-EmbedWindowDeleted(winPtr)
- TkWindow *winPtr; /* Tk's information about window that
- * was deleted. */
+EmbedWindowDeleted(
+ TkWindow *winPtr) /* Tk's information about window that was
+ * deleted. */
{
Container *containerPtr, *prevPtr;
- ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
- Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
/*
- * Find the Container structure for this window work. Delete the
+ * Find the Container structure for this window work. Delete the
* information about the embedded application and free the container's
- * record.
- * The main container may be null. [Bug #476176]
+ * record. The main container may be null. [Bug #476176]
*/
prevPtr = NULL;
@@ -650,13 +1077,15 @@ EmbedWindowDeleted(winPtr)
break;
}
if (containerPtr->parentPtr == winPtr) {
+ SendMessage(containerPtr->embeddedHWnd, WM_CLOSE, 0, 0);
containerPtr->parentPtr = NULL;
+ containerPtr->embeddedPtr = NULL;
break;
}
prevPtr = containerPtr;
containerPtr = containerPtr->nextPtr;
if (containerPtr == NULL) {
- panic("EmbedWindowDeleted couldn't find window");
+ return;
}
}
if ((containerPtr->embeddedPtr == NULL)
@@ -669,3 +1098,11 @@ EmbedWindowDeleted(winPtr)
ckfree((char *) containerPtr);
}
}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */