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. */ { TkWindow *winPtr = (TkWindow *) tkwin; TkWindow *usePtr; int id, anyError; Window parent; Tk_ErrorHandler handler; Container *containerPtr; XWindowAttributes parentAtts; ThreadSpecificData *tsdPtr = Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); if (winPtr->window != None) { 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) { return TCL_ERROR; } parent = (Window) id; usePtr = (TkWindow *) Tk_IdToWindow(winPtr->display, parent); 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; } /* * Tk sets the window colormap to the screen default colormap in * tkWindow.c:AllocWindow. This doesn't work well for embedded windows. So * we override the colormap and visual settings to be the same as the * parent window (which is in the container app). */ anyError = 0; handler = Tk_CreateErrorHandler(winPtr->display, -1, -1, -1, EmbedErrorProc, &anyError); if (!XGetWindowAttributes(winPtr->display, parent, &parentAtts)) { anyError = 1; } XSync(winPtr->display, False); Tk_DeleteErrorHandler(handler); if (anyError) { if (interp != 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; } Tk_SetWindowVisual(tkwin, parentAtts.visual, parentAtts.depth, parentAtts.colormap); /* * Create an event handler to clean up the Container structure when tkwin * is eventually deleted. */ Tk_CreateEventHandler(tkwin, StructureNotifyMask, EmbeddedEventProc, winPtr); /* * 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. */ for (containerPtr = tsdPtr->firstContainerPtr; containerPtr != NULL; containerPtr = containerPtr->nextPtr) { if (containerPtr->parent == parent) { winPtr->flags |= TK_BOTH_HALVES; containerPtr->parentPtr->flags |= TK_BOTH_HALVES; break; } } if (containerPtr == NULL) { containerPtr = ckalloc(sizeof(Container)); containerPtr->parent = parent; containerPtr->parentRoot = parentAtts.root; containerPtr->parentPtr = NULL; containerPtr->wrapper = None; containerPtr->nextPtr = tsdPtr->firstContainerPtr; tsdPtr->firstContainerPtr = containerPtr; } containerPtr->embeddedPtr = winPtr; winPtr->flags |= TK_EMBEDDED; return TCL_OK; }
SCISHARE int OpenGLCmd(ClientData clientData, Tcl_Interp *interp, int argc, CONST84 char **argv) { Tk_Window mainwin = (Tk_Window) clientData; OpenGLClientData *OpenGLPtr; Colormap cmap; Tk_Window tkwin; XVisualInfo temp_vi; int tempid; int n; #ifndef _WIN32 int attributes[50]; int idx = 0; #endif if (argc < 2) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " pathName ?options?\"", (char *) NULL); return TCL_ERROR; } tkwin = Tk_CreateWindowFromPath(interp, mainwin, argv[1], (char *) NULL); if (tkwin == NULL) { return TCL_ERROR; } Tk_SetClass(tkwin, "OpenGL"); /* Allocate and initialize the widget record. */ OpenGLPtr = (OpenGLClientData *) ckalloc(sizeof(OpenGLClientData)); OpenGLPtr->geometry = 0; OpenGLPtr->cursor = 0; OpenGLPtr->interp = interp; OpenGLPtr->tkwin = tkwin; OpenGLPtr->display = Tk_Display(tkwin); OpenGLPtr->x11_win=0; OpenGLPtr->screen_number = Tk_ScreenNumber(tkwin); #ifndef _WIN32 OpenGLPtr->glx_win=0; OpenGLPtr->fb_configs=glXGetFBConfigs(OpenGLPtr->display, OpenGLPtr->screen_number, &(OpenGLPtr->num_fb)); #else OpenGLPtr->hDC = 0; #endif OpenGLPtr->vi=0; OpenGLPtr->cx=0; Tk_CreateEventHandler(OpenGLPtr->tkwin, StructureNotifyMask, OpenGLEventProc, (ClientData) OpenGLPtr); Tcl_CreateCommand(interp, Tk_PathName(OpenGLPtr->tkwin), OpenGLWidgetCmd, (ClientData) OpenGLPtr, (Tcl_CmdDeleteProc *)0); if (OpenGLConfigure(interp, OpenGLPtr, argc-2, argv+2, 0) != TCL_OK) { return TCL_ERROR; } tempid = OpenGLPtr->visualid; if (OpenGLPtr->visualid) { temp_vi.visualid = OpenGLPtr->visualid; OpenGLPtr->vi = XGetVisualInfo(OpenGLPtr->display, VisualIDMask, &temp_vi, &n); if(!OpenGLPtr->vi || n!=1) { Tcl_AppendResult(interp, "Error finding visual", NULL); return TCL_ERROR; } } else { /* * Pick the right visual... */ #ifndef _WIN32 attributes[idx++]=GLX_BUFFER_SIZE; attributes[idx++]=OpenGLPtr->buffersize; attributes[idx++]=GLX_LEVEL; attributes[idx++]=OpenGLPtr->level; if(OpenGLPtr->rgba) attributes[idx++]=GLX_RGBA; if(OpenGLPtr->doublebuffer) attributes[idx++]=GLX_DOUBLEBUFFER; if(OpenGLPtr->stereo) attributes[idx++]=GLX_STEREO; attributes[idx++]=GLX_AUX_BUFFERS; attributes[idx++]=OpenGLPtr->auxbuffers; attributes[idx++]=GLX_RED_SIZE; attributes[idx++]=OpenGLPtr->redsize; attributes[idx++]=GLX_GREEN_SIZE; attributes[idx++]=OpenGLPtr->greensize; attributes[idx++]=GLX_BLUE_SIZE; attributes[idx++]=OpenGLPtr->bluesize; attributes[idx++]=GLX_ALPHA_SIZE; attributes[idx++]=OpenGLPtr->alphasize; attributes[idx++]=GLX_DEPTH_SIZE; attributes[idx++]=OpenGLPtr->depthsize; attributes[idx++]=GLX_STENCIL_SIZE; attributes[idx++]=OpenGLPtr->stencilsize; attributes[idx++]=GLX_ACCUM_RED_SIZE; attributes[idx++]=OpenGLPtr->accumredsize; attributes[idx++]=GLX_ACCUM_GREEN_SIZE; attributes[idx++]=OpenGLPtr->accumgreensize; attributes[idx++]=GLX_ACCUM_BLUE_SIZE; attributes[idx++]=OpenGLPtr->accumbluesize; attributes[idx++]=GLX_ACCUM_ALPHA_SIZE; attributes[idx++]=OpenGLPtr->accumalphasize; attributes[idx++]=None; OpenGLPtr->vi = glXChooseVisual(OpenGLPtr->display, OpenGLPtr->screen_number, attributes); OpenGLPtr->visualid=tempid; #else // WIN32 // I am using the *PixelFormat commands from win32 because according // to the Windows page, we should prefer this to wgl*PixelFormatARB. // Unfortunately, this means that the Windows code will differ // substantially from that of other platforms. However, it has the // advantage that we don't have to use the wglGetProc to get // the procedure address, or test to see if the applicable extension // is supported. WM:VI HWND hWnd = TkWinGetHWND(Tk_WindowId(OpenGLPtr->tkwin)); // a little ugly, but we need this to be defined before pfd, and // we need to follow C initialization rules DWORD dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | (OpenGLPtr->doublebuffer ? PFD_DOUBLEBUFFER : 0) | (OpenGLPtr->stereo ? PFD_STEREO : 0); int iPixelFormat; XVisualInfo xvi; int n_ret; PIXELFORMATDESCRIPTOR pfd = { sizeof(PIXELFORMATDESCRIPTOR), // size of this pfd 1, // version number dwFlags, PFD_TYPE_RGBA, // RGBA type OpenGLPtr->buffersize, // color depth OpenGLPtr->redsize, 0, OpenGLPtr->greensize, 0, OpenGLPtr->bluesize, 0, // color bits OpenGLPtr->alphasize,0, // alpha buffer OpenGLPtr->accumredsize+ OpenGLPtr->accumgreensize+ OpenGLPtr->accumbluesize,// accumulation buffer OpenGLPtr->accumredsize, OpenGLPtr->accumgreensize, OpenGLPtr->accumbluesize, OpenGLPtr->accumalphasize,// accum bits OpenGLPtr->depthsize, // 32-bit z-buffer OpenGLPtr->stencilsize,// no stencil buffer OpenGLPtr->auxbuffers, // no auxiliary buffer PFD_MAIN_PLANE, // main layer 0, // reserved 0, 0, 0 // layer masks ignored }; iPixelFormat = ChoosePixelFormat(OpenGLPtr->hDC, &pfd); SetPixelFormat(OpenGLPtr->hDC, iPixelFormat, &pfd); OpenGLPtr->visualid = iPixelFormat; OpenGLPtr->hDC = GetDC(hWnd); xvi.screen = OpenGLPtr->screen_number; n_ret=0; OpenGLPtr->vi = XGetVisualInfo(OpenGLPtr->display, VisualScreenMask, &xvi, &n_ret); #endif if (!OpenGLPtr->vi) { Tcl_AppendResult(interp, "Error selecting visual", (char*)NULL); return TCL_ERROR; } } cmap = XCreateColormap(OpenGLPtr->display, Tk_WindowId(Tk_MainWindow(OpenGLPtr->interp)), OpenGLPtr->vi->visual, AllocNone); if(Tk_SetWindowVisual(OpenGLPtr->tkwin, OpenGLPtr->vi->visual, OpenGLPtr->vi->depth, cmap) != 1) { Tcl_AppendResult(interp, "Error setting visual for window", (char*)NULL); return TCL_ERROR; } XSync(OpenGLPtr->display, False); Tcl_SetResult(interp,Tk_PathName(OpenGLPtr->tkwin),TCL_STATIC); return TCL_OK; }