Exemplo n.º 1
0
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;
}
Exemplo n.º 2
0
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;
}