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 119bc67..b170ad0 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 (TkpScanWindowId(interp, string, &parent) != TCL_OK) { @@ -118,12 +120,12 @@ TkpUseWindow( } 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; } /* @@ -135,7 +137,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; } @@ -143,8 +145,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; } @@ -157,7 +160,7 @@ TkpUseWindow( */ Tk_CreateEventHandler(tkwin, StructureNotifyMask, EmbeddedEventProc, - (ClientData) winPtr); + winPtr); /* * Save information about the container and the embedded window in a @@ -175,7 +178,7 @@ TkpUseWindow( } } if (containerPtr == NULL) { - containerPtr = (Container *) ckalloc(sizeof(Container)); + containerPtr = ckalloc(sizeof(Container)); containerPtr->parent = parent; containerPtr->parentRoot = parentAtts.root; containerPtr->parentPtr = NULL; @@ -213,7 +216,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) { @@ -269,7 +272,7 @@ TkpMakeContainer( { TkWindow *winPtr = (TkWindow *) tkwin; Container *containerPtr; - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + ThreadSpecificData *tsdPtr = Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); /* @@ -278,7 +281,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; @@ -299,11 +302,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); } /* @@ -329,7 +332,7 @@ EmbedErrorProc( XErrorEvent *errEventPtr) /* Points to information about error (not * used). */ { - int *iPtr = (int *) clientData; + int *iPtr = clientData; *iPtr = 1; return 0; @@ -359,7 +362,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); @@ -391,10 +394,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)); /* @@ -404,7 +407,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. @@ -496,7 +499,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) { @@ -507,7 +510,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), @@ -543,7 +546,7 @@ EmbedFocusProc( ClientData clientData, /* Token for container window. */ XEvent *eventPtr) /* ResizeRequest event. */ { - Container *containerPtr = (Container *) clientData; + Container *containerPtr = clientData; Tk_ErrorHandler errHandler; Display *display; @@ -558,7 +561,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); @@ -701,7 +704,7 @@ TkpGetOtherWindow( * window. */ { Container *containerPtr; - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + ThreadSpecificData *tsdPtr = Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); for (containerPtr = tsdPtr->firstContainerPtr; @@ -747,7 +750,7 @@ TkpRedirectKeyEvent( { Container *containerPtr; Window saved; - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + ThreadSpecificData *tsdPtr = Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); /* @@ -819,7 +822,7 @@ TkpClaimFocus( { XEvent event; Container *containerPtr; - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + ThreadSpecificData *tsdPtr = Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); if (!(topLevelPtr->flags & TK_EMBEDDED)) { @@ -863,17 +866,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; @@ -940,7 +943,7 @@ EmbedWindowDeleted( * deleted. */ { Container *containerPtr, *prevPtr; - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + ThreadSpecificData *tsdPtr = Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); /* @@ -971,7 +974,7 @@ EmbedWindowDeleted( } else { prevPtr->nextPtr = containerPtr->nextPtr; } - ckfree((char *) containerPtr); + ckfree(containerPtr); } } @@ -998,7 +1001,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; @@ -1012,6 +1015,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 |