diff options
Diffstat (limited to 'unix/tkUnixEmbed.c')
-rw-r--r-- | unix/tkUnixEmbed.c | 247 |
1 files changed, 206 insertions, 41 deletions
diff --git a/unix/tkUnixEmbed.c b/unix/tkUnixEmbed.c index 5b5f486..7f3f94b 100644 --- a/unix/tkUnixEmbed.c +++ b/unix/tkUnixEmbed.c @@ -4,7 +4,7 @@ * This file contains platform-specific functions for UNIX to provide * basic operations needed for application embedding (where one * application can use as its main window an internal window from some - * other application). + * other application). Also includes code to support busy windows. * * Copyright (c) 1996-1997 Sun Microsystems, Inc. * @@ -13,6 +13,7 @@ */ #include "tkUnixInt.h" +#include "tkBusy.h" /* * One of the following structures exists for each container in this @@ -95,7 +96,7 @@ TkpUseWindow( * 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 + const char *string) /* String identifying an X window to use for * tkwin; must be an integer value. */ { TkWindow *winPtr = (TkWindow *) tkwin; @@ -105,12 +106,13 @@ TkpUseWindow( Tk_ErrorHandler handler; Container *containerPtr; XWindowAttributes parentAtts; - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + ThreadSpecificData *tsdPtr = Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); if (winPtr->window != None) { - Tcl_AppendResult(interp, - "can't modify container after widget is created", NULL); + Tcl_SetObjResult(interp, Tcl_NewStringObj( + "can't modify container after widget is created", -1)); + Tcl_SetErrorCode(interp, "TK", "EMBED", "POST_CREATE", NULL); return TCL_ERROR; } if (Tcl_GetInt(interp, string, &id) != TCL_OK) { @@ -119,12 +121,12 @@ TkpUseWindow( parent = (Window) id; usePtr = (TkWindow *) Tk_IdToWindow(winPtr->display, parent); - if (usePtr != NULL) { - if (!(usePtr->flags & TK_CONTAINER)) { - Tcl_AppendResult(interp, "window \"", usePtr->pathName, - "\" doesn't have -container option set", NULL); - return TCL_ERROR; - } + if (usePtr != NULL && !(usePtr->flags & TK_CONTAINER)) { + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "window \"%s\" doesn't have -container option set", + usePtr->pathName)); + Tcl_SetErrorCode(interp, "TK", "EMBED", "CONTAINER", NULL); + return TCL_ERROR; } /* @@ -136,7 +138,7 @@ TkpUseWindow( anyError = 0; handler = Tk_CreateErrorHandler(winPtr->display, -1, -1, -1, - EmbedErrorProc, (ClientData) &anyError); + EmbedErrorProc, &anyError); if (!XGetWindowAttributes(winPtr->display, parent, &parentAtts)) { anyError = 1; } @@ -144,8 +146,9 @@ TkpUseWindow( Tk_DeleteErrorHandler(handler); if (anyError) { if (interp != NULL) { - Tcl_AppendResult(interp, "couldn't create child of window \"", - string, "\"", NULL); + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "couldn't create child of window \"%s\"", string)); + Tcl_SetErrorCode(interp, "TK", "EMBED", "NO_TARGET", NULL); } return TCL_ERROR; } @@ -158,7 +161,7 @@ TkpUseWindow( */ Tk_CreateEventHandler(tkwin, StructureNotifyMask, EmbeddedEventProc, - (ClientData) winPtr); + winPtr); /* * Save information about the container and the embedded window in a @@ -176,7 +179,7 @@ TkpUseWindow( } } if (containerPtr == NULL) { - containerPtr = (Container *) ckalloc(sizeof(Container)); + containerPtr = ckalloc(sizeof(Container)); containerPtr->parent = parent; containerPtr->parentRoot = parentAtts.root; containerPtr->parentPtr = NULL; @@ -214,7 +217,7 @@ TkpMakeWindow( * the window is to be created. */ { Container *containerPtr; - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + ThreadSpecificData *tsdPtr = Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); if (winPtr->flags & TK_EMBEDDED) { @@ -270,7 +273,7 @@ TkpMakeContainer( { TkWindow *winPtr = (TkWindow *) tkwin; Container *containerPtr; - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + ThreadSpecificData *tsdPtr = Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); /* @@ -279,7 +282,7 @@ TkpMakeContainer( */ Tk_MakeWindowExist(tkwin); - containerPtr = (Container *) ckalloc(sizeof(Container)); + containerPtr = ckalloc(sizeof(Container)); containerPtr->parent = Tk_WindowId(tkwin); containerPtr->parentRoot = RootWindowOfScreen(Tk_Screen(tkwin)); containerPtr->parentPtr = winPtr; @@ -300,11 +303,11 @@ TkpMakeContainer( XSelectInput(winPtr->display, winPtr->window, winPtr->atts.event_mask); Tk_CreateEventHandler(tkwin, SubstructureNotifyMask|SubstructureRedirectMask, - ContainerEventProc, (ClientData) winPtr); + ContainerEventProc, winPtr); Tk_CreateEventHandler(tkwin, StructureNotifyMask, EmbedStructureProc, - (ClientData) containerPtr); + containerPtr); Tk_CreateEventHandler(tkwin, FocusChangeMask, EmbedFocusProc, - (ClientData) containerPtr); + containerPtr); } /* @@ -330,7 +333,7 @@ EmbedErrorProc( XErrorEvent *errEventPtr) /* Points to information about error (not * used). */ { - int *iPtr = (int *) clientData; + int *iPtr = clientData; *iPtr = 1; return 0; @@ -360,7 +363,7 @@ EmbeddedEventProc( ClientData clientData, /* Token for container window. */ XEvent *eventPtr) /* ResizeRequest event. */ { - TkWindow *winPtr = (TkWindow *) clientData; + TkWindow *winPtr = clientData; if (eventPtr->type == DestroyNotify) { EmbedWindowDeleted(winPtr); @@ -392,10 +395,10 @@ ContainerEventProc( ClientData clientData, /* Token for container window. */ XEvent *eventPtr) /* ResizeRequest event. */ { - TkWindow *winPtr = (TkWindow *) clientData; + TkWindow *winPtr = clientData; Container *containerPtr; Tk_ErrorHandler errHandler; - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + ThreadSpecificData *tsdPtr = Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); /* @@ -405,7 +408,7 @@ ContainerEventProc( */ errHandler = Tk_CreateErrorHandler(eventPtr->xfocus.display, -1, - -1, -1, NULL, (ClientData) NULL); + -1, -1, NULL, NULL); /* * Find the Container structure associated with the parent window. @@ -497,7 +500,7 @@ EmbedStructureProc( ClientData clientData, /* Token for container window. */ XEvent *eventPtr) /* ResizeRequest event. */ { - Container *containerPtr = (Container *) clientData; + Container *containerPtr = clientData; Tk_ErrorHandler errHandler; if (eventPtr->type == ConfigureNotify) { @@ -508,7 +511,7 @@ EmbedStructureProc( */ errHandler = Tk_CreateErrorHandler(eventPtr->xfocus.display, -1, - -1, -1, NULL, (ClientData) NULL); + -1, -1, NULL, NULL); XMoveResizeWindow(eventPtr->xconfigure.display, containerPtr->wrapper, 0, 0, (unsigned) Tk_Width((Tk_Window) containerPtr->parentPtr), @@ -544,7 +547,7 @@ EmbedFocusProc( ClientData clientData, /* Token for container window. */ XEvent *eventPtr) /* ResizeRequest event. */ { - Container *containerPtr = (Container *) clientData; + Container *containerPtr = clientData; Tk_ErrorHandler errHandler; Display *display; @@ -559,7 +562,7 @@ EmbedFocusProc( if (containerPtr->wrapper != None) { errHandler = Tk_CreateErrorHandler(eventPtr->xfocus.display, -1, - -1, -1, NULL, (ClientData) NULL); + -1, -1, NULL, NULL); XSetInputFocus(display, containerPtr->wrapper, RevertToParent, CurrentTime); Tk_DeleteErrorHandler(errHandler); @@ -702,7 +705,7 @@ TkpGetOtherWindow( * window. */ { Container *containerPtr; - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + ThreadSpecificData *tsdPtr = Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); for (containerPtr = tsdPtr->firstContainerPtr; @@ -748,7 +751,7 @@ TkpRedirectKeyEvent( { Container *containerPtr; Window saved; - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + ThreadSpecificData *tsdPtr = Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); /* @@ -820,7 +823,7 @@ TkpClaimFocus( { XEvent event; Container *containerPtr; - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + ThreadSpecificData *tsdPtr = Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); if (!(topLevelPtr->flags & TK_EMBEDDED)) { @@ -864,17 +867,17 @@ int TkpTestembedCmd( ClientData clientData, /* Main window for application. */ Tcl_Interp *interp, /* Current interpreter. */ - int argc, /* Number of arguments. */ - CONST char **argv) /* Argument strings. */ + int objc, /* Number of arguments. */ + Tcl_Obj *const objv[]) /* Argument strings. */ { int all; Container *containerPtr; Tcl_DString dString; char buffer[50]; - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + ThreadSpecificData *tsdPtr = Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); - if ((argc > 1) && (strcmp(argv[1], "all") == 0)) { + if ((objc > 1) && (strcmp(Tcl_GetString(objv[1]), "all") == 0)) { all = 1; } else { all = 0; @@ -941,7 +944,7 @@ EmbedWindowDeleted( * deleted. */ { Container *containerPtr, *prevPtr; - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + ThreadSpecificData *tsdPtr = Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); /* @@ -972,7 +975,7 @@ EmbedWindowDeleted( } else { prevPtr->nextPtr = containerPtr->nextPtr; } - ckfree((char *) containerPtr); + ckfree(containerPtr); } } @@ -999,7 +1002,7 @@ TkUnixContainerId( TkWindow *winPtr) /* Tk's structure for an embedded window. */ { Container *containerPtr; - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + ThreadSpecificData *tsdPtr = Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); for (containerPtr = tsdPtr->firstContainerPtr; @@ -1013,6 +1016,168 @@ TkUnixContainerId( } /* + *---------------------------------------------------------------------- + * + * TkpShowBusyWindow -- + * + * Makes a busy window "appear". + * + * Results: + * None. + * + * Side effects: + * Arranges for the busy window to start intercepting events and the + * cursor to change to the configured "hey, I'm busy!" setting. + * + *---------------------------------------------------------------------- + */ + +void +TkpShowBusyWindow( + TkBusy busy) +{ + Busy *busyPtr = (Busy *) busy; + + if (busyPtr->tkBusy != NULL) { + Tk_MapWindow(busyPtr->tkBusy); + + /* + * Always raise the busy window just in case new sibling windows have + * been created in the meantime. Can't use Tk_RestackWindow because it + * doesn't work under Win32. + */ + + XRaiseWindow(Tk_Display(busyPtr->tkBusy), + Tk_WindowId(busyPtr->tkBusy)); + } +} + +/* + *---------------------------------------------------------------------- + * + * TkpHideBusyWindow -- + * + * Makes a busy window "disappear". + * + * Results: + * None. + * + * Side effects: + * Arranges for the busy window to stop intercepting events, and the + * cursor to change back to its normal setting. + * + *---------------------------------------------------------------------- + */ + +void +TkpHideBusyWindow( + TkBusy busy) +{ + Busy *busyPtr = (Busy *) busy; + + if (busyPtr->tkBusy != NULL) { + Tk_UnmapWindow(busyPtr->tkBusy); + } +} + +/* + *---------------------------------------------------------------------- + * + * TkpMakeTransparentWindowExist -- + * + * Construct the platform-specific resources for a transparent window. + * + * Results: + * None. + * + * Side effects: + * Moves the specified window in the stacking order. + * + *---------------------------------------------------------------------- + */ + +void +TkpMakeTransparentWindowExist( + Tk_Window tkwin, /* Token for window. */ + Window parent) /* Parent window. */ +{ + TkWindow *winPtr = (TkWindow *) tkwin; + long int mask = CWDontPropagate | CWEventMask; + + /* + * Ignore the important events while the window is mapped. + */ + +#define USER_EVENTS \ + (EnterWindowMask | LeaveWindowMask | KeyPressMask | KeyReleaseMask | \ + ButtonPressMask | ButtonReleaseMask | PointerMotionMask) +#define PROP_EVENTS \ + (KeyPressMask | KeyReleaseMask | ButtonPressMask | \ + ButtonReleaseMask | PointerMotionMask) + + winPtr->atts.do_not_propagate_mask = PROP_EVENTS; + winPtr->atts.event_mask = USER_EVENTS; + winPtr->changes.border_width = 0; + winPtr->depth = 0; + + winPtr->window = XCreateWindow(winPtr->display, parent, + winPtr->changes.x, winPtr->changes.y, + (unsigned) winPtr->changes.width, /* width */ + (unsigned) winPtr->changes.height, /* height */ + (unsigned) winPtr->changes.border_width, /* border_width */ + winPtr->depth, InputOnly, winPtr->visual, mask, &winPtr->atts); +} + +/* + *---------------------------------------------------------------------- + * + * TkpCreateBusy -- + * + * Construct the platform-specific parts of a busy window. Note that this + * postpones the actual creation of the window resource until later. + * + * Results: + * None. + * + * Side effects: + * Sets up part of the busy window structure. + * + *---------------------------------------------------------------------- + */ + +void +TkpCreateBusy( + Tk_FakeWin *winPtr, + Tk_Window tkRef, + Window *parentPtr, + Tk_Window tkParent, + TkBusy busy) +{ + Window root, parent, *dummy; + unsigned int count; + + if (winPtr->flags & TK_REPARENTED) { + /* + * This works around a bug in the implementation of menubars for + * non-MacIntosh window systems (Win32 and X11). Tk doesn't reset the + * pointers to the parent window when the menu is reparented (since + * winPtr->parentPtr points to the wrong window). We get around this + * by determining the parent via the native API calls. + */ + + if (XQueryTree(Tk_Display(tkRef), Tk_WindowId(tkRef), &root, + &parent, &dummy, &count) > 0) { + XFree(dummy); + *parentPtr = parent; + } else { + *parentPtr = None; + } + } else { + *parentPtr = Tk_WindowId(tkParent); + } +} + +/* * Local Variables: * mode: c * c-basic-offset: 4 |