📄 tkunixembed.c
字号:
XMoveResizeWindow(eventPtr->xconfigure.display, containerPtr->wrapper, 0, 0, (unsigned int) Tk_Width( (Tk_Window) containerPtr->parentPtr), (unsigned int) Tk_Height( (Tk_Window) containerPtr->parentPtr)); Tk_DeleteErrorHandler(errHandler); } } else if (eventPtr->type == DestroyNotify) { EmbedWindowDeleted(containerPtr->parentPtr); }}/* *---------------------------------------------------------------------- * * EmbedFocusProc -- * * This procedure is invoked by the Tk event dispatcher when * FocusIn and FocusOut events occur for a container window owned * by this application. It is responsible for moving the focus * back and forth between a container application and an embedded * application. * * Results: * None. * * Side effects: * The X focus may change. * *---------------------------------------------------------------------- */static voidEmbedFocusProc(clientData, eventPtr) ClientData clientData; /* Token for container window. */ XEvent *eventPtr; /* ResizeRequest event. */{ Container *containerPtr = (Container *) clientData; Tk_ErrorHandler errHandler; Display *display; display = Tk_Display(containerPtr->parentPtr); if (eventPtr->type == FocusIn) { /* * The focus just arrived at the container. Change the X focus * to move it to the embedded application, if there is one. * Ignore X errors that occur during this operation (it's * possible that the new focus window isn't mapped). */ if (containerPtr->wrapper != None) { errHandler = Tk_CreateErrorHandler(eventPtr->xfocus.display, -1, -1, -1, (Tk_ErrorProc *) NULL, (ClientData) NULL); XSetInputFocus(display, containerPtr->wrapper, RevertToParent, CurrentTime); Tk_DeleteErrorHandler(errHandler); } }}/* *---------------------------------------------------------------------- * * EmbedGeometryRequest -- * * This procedure is invoked when an embedded application requests * a particular size. It processes the request (which may or may * not actually honor the request) 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 how big it ought to be. * Events get processed while we're waiting for the geometry * managers to do their thing. * *---------------------------------------------------------------------- */static voidEmbedGeometryRequest(containerPtr, width, height) Container *containerPtr; /* Information about the embedding. */ int width, height; /* Size that the child has requested. */{ 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 if we decide not to honor its * request; 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); while (Tcl_DoOneEvent(TCL_IDLE_EVENTS)) { /* Empty loop body. */ } if ((winPtr->changes.width != width) || (winPtr->changes.height != height)) { EmbedSendConfigure(containerPtr); }}/* *---------------------------------------------------------------------- * * EmbedSendConfigure -- * * This procedure synthesizes a ConfigureNotify event to notify an * embedded application of its current size and location. This * procedure is called when the embedded application made a * geometry request that we did not grant, so that the embedded * application knows that its geometry didn't change after all. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */static voidEmbedSendConfigure(containerPtr) Container *containerPtr; /* Information about the embedding. */{ TkWindow *winPtr = containerPtr->parentPtr; XEvent event; event.xconfigure.type = ConfigureNotify; event.xconfigure.serial = LastKnownRequestProcessed(winPtr->display); event.xconfigure.send_event = True; event.xconfigure.display = winPtr->display; event.xconfigure.event = containerPtr->wrapper; event.xconfigure.window = containerPtr->wrapper; event.xconfigure.x = 0; event.xconfigure.y = 0; event.xconfigure.width = winPtr->changes.width; event.xconfigure.height = winPtr->changes.height; event.xconfigure.above = None; event.xconfigure.override_redirect = False; /* * Note: when sending the event below, the ButtonPressMask * causes the event to be sent only to applications that have * selected for ButtonPress events, which should be just the * embedded application. */ XSendEvent(winPtr->display, containerPtr->wrapper, False, 0, &event); /* * The following needs to be done if the embedded window is * not in the same application as the container window. */ if (containerPtr->embeddedPtr == NULL) { XMoveResizeWindow(winPtr->display, containerPtr->wrapper, 0, 0, (unsigned int) winPtr->changes.width, (unsigned int) winPtr->changes.height); }}/* *---------------------------------------------------------------------- * * TkpGetOtherWindow -- * * 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. * * Side effects: * None. * *---------------------------------------------------------------------- */TkWindow *TkpGetOtherWindow(winPtr) TkWindow *winPtr; /* Tk's structure for a container or * embedded window. */{ Container *containerPtr; for (containerPtr = firstContainerPtr; containerPtr != NULL; containerPtr = containerPtr->nextPtr) { if (containerPtr->embeddedPtr == winPtr) { return containerPtr->parentPtr; } else if (containerPtr->parentPtr == winPtr) { return containerPtr->embeddedPtr; } } panic("TkpGetOtherWindow couldn't find window"); return NULL;}/* *---------------------------------------------------------------------- * * 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. * * Results: * None. * * Side effects: * The event may get sent to a different application. * *---------------------------------------------------------------------- */voidTkpRedirectKeyEvent(winPtr, eventPtr) TkWindow *winPtr; /* Window to which the event was originally * reported. */ XEvent *eventPtr; /* X event to redirect (should be KeyPress * or KeyRelease). */{ Container *containerPtr; Window saved; /* * First, find the top-level window corresponding to winPtr. */ while (1) { if (winPtr == NULL) { /* * This window is being deleted. This is too confusing a * case to handle so discard the event. */ return; } if (winPtr->flags & TK_TOP_LEVEL) { break; } winPtr = winPtr->parentPtr; } if (winPtr->flags & TK_EMBEDDED) { /* * This application is embedded. If we got a key event without * officially having the focus, it means that the focus is * really in the container, but the mouse was over the embedded * application. Send the event back to the container. */ for (containerPtr = firstContainerPtr; containerPtr->embeddedPtr != winPtr; containerPtr = containerPtr->nextPtr) { /* Empty loop body. */ } saved = eventPtr->xkey.window; eventPtr->xkey.window = containerPtr->parent; XSendEvent(eventPtr->xkey.display, eventPtr->xkey.window, False, KeyPressMask|KeyReleaseMask, eventPtr); eventPtr->xkey.window = saved; }}/* *---------------------------------------------------------------------- * * 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. * * Results: * None. * * Side effects: * The input focus may change. * *---------------------------------------------------------------------- */voidTkpClaimFocus(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. */{ XEvent event; Container *containerPtr; if (!(topLevelPtr->flags & TK_EMBEDDED)) { return; } for (containerPtr = firstContainerPtr; containerPtr->embeddedPtr != topLevelPtr; containerPtr = containerPtr->nextPtr) { /* Empty loop body. */ } event.xfocus.type = FocusIn; event.xfocus.serial = LastKnownRequestProcessed(topLevelPtr->display); event.xfocus.send_event = 1; event.xfocus.display = topLevelPtr->display; event.xfocus.window = containerPtr->parent; event.xfocus.mode = EMBEDDED_APP_WANTS_FOCUS; event.xfocus.detail = force; XSendEvent(event.xfocus.display, event.xfocus.window, False, 0, &event);}/* *---------------------------------------------------------------------- * * TkpTestembedCmd -- * * This procedure implements the "testembed" command. It returns * some or all of the information in the list pointed to by * firstContainerPtr. * * Results: * A standard Tcl result. * * Side effects: * None. * *---------------------------------------------------------------------- */intTkpTestembedCmd(clientData, interp, argc, argv) ClientData clientData; /* Main window for application. */ Tcl_Interp *interp; /* Current interpreter. */ int argc; /* Number of arguments. */ char **argv; /* Argument strings. */{ int all; Container *containerPtr; Tcl_DString dString; char buffer[50]; if ((argc > 1) && (strcmp(argv[1], "all") == 0)) { all = 1; } else { all = 0; } Tcl_DStringInit(&dString); for (containerPtr = firstContainerPtr; containerPtr != NULL; containerPtr = containerPtr->nextPtr) { Tcl_DStringStartSublist(&dString); if (containerPtr->parent == None) { Tcl_DStringAppendElement(&dString, ""); } else { if (all) { sprintf(buffer, "0x%x", (int) containerPtr->parent); Tcl_DStringAppendElement(&dString, buffer); } else { Tcl_DStringAppendElement(&dString, "XXX"); } } if (containerPtr->parentPtr == NULL) { Tcl_DStringAppendElement(&dString, ""); } else { Tcl_DStringAppendElement(&dString, containerPtr->parentPtr->pathName); } if (containerPtr->wrapper == None) { Tcl_DStringAppendElement(&dString, ""); } else { if (all) { sprintf(buffer, "0x%x", (int) containerPtr->wrapper); Tcl_DStringAppendElement(&dString, buffer); } else { Tcl_DStringAppendElement(&dString, "XXX"); } } if (containerPtr->embeddedPtr == NULL) { Tcl_DStringAppendElement(&dString, ""); } else { Tcl_DStringAppendElement(&dString, containerPtr->embeddedPtr->pathName); } Tcl_DStringEndSublist(&dString); } Tcl_DStringResult(interp, &dString); return TCL_OK;}/* *---------------------------------------------------------------------- * * 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. * * Results: * None. * * Side effects: * A Container structure may be freed. * *---------------------------------------------------------------------- */static voidEmbedWindowDeleted(winPtr) TkWindow *winPtr; /* Tk's information about window that * was deleted. */{ Container *containerPtr, *prevPtr; /* * Find the Container structure for this window work. Delete the * information about the embedded application and free the container's * record. */ prevPtr = NULL; containerPtr = firstContainerPtr; while (1) { if (containerPtr->embeddedPtr == winPtr) { containerPtr->wrapper = None; containerPtr->embeddedPtr = NULL; break; } if (containerPtr->parentPtr == winPtr) { containerPtr->parentPtr = NULL; break; } prevPtr = containerPtr; containerPtr = containerPtr->nextPtr; } if ((containerPtr->embeddedPtr == NULL) && (containerPtr->parentPtr == NULL)) { if (prevPtr == NULL) { firstContainerPtr = containerPtr->nextPtr; } else { prevPtr->nextPtr = containerPtr->nextPtr; } ckfree((char *) containerPtr); }}/* *---------------------------------------------------------------------- * * TkUnixContainerId -- * * Given an embedded window, this procedure returns the X window * identifier for the associated container window. * * Results: * The return value is the X window identifier for winPtr's * container window. * * Side effects: * None. * *---------------------------------------------------------------------- */WindowTkUnixContainerId(winPtr) TkWindow *winPtr; /* Tk's structure for an embedded window. */{ Container *containerPtr; for (containerPtr = firstContainerPtr; containerPtr != NULL; containerPtr = containerPtr->nextPtr) { if (containerPtr->embeddedPtr == winPtr) { return containerPtr->parent; } } panic("TkUnixContainerId couldn't find window"); return None;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -