/* grOGL1.c - * * This file contains primitive functions for OpenGL running under * an X window system (using GLUT). * Included here are initialization and closing * functions, and several utility routines used by the other X * modules. */ #include #include #include #include #ifdef SYSV #include #else #include #endif #include #include #include #include "misc/magic.h" #include "misc/magsgtty.h" #include "utils/geometry.h" #include "graphics/graphics.h" #include "windows/windows.h" #include "graphics/graphicsInt.h" #include "textio/textio.h" #include "textio/txcommands.h" #include "signals/signals.h" #include "utils/utils.h" #include "utils/hash.h" #include "grOGLInt.h" #include "misc/paths.h" GLubyte *grOGLStipples[GR_NUM_STIPPLES]; HashTable grOGLWindowTable; Display *grXdpy; GLXContext grXcontext; int grXscrn; int pipeRead, pipeWrite; int Xhelper; char grXdepth[8]; Visual *grVisual; OGL_CURRENT oglCurrent= {(XFontStruct *)NULL, 0,0,0,0, (Window)0, (MagWindow *)NULL}; /* This is kind of a long story, and very kludgy, but the following * things need to be defined as externals because of the way lint * libraries are made by taking this module and changing all procedures * names "Xxxx" to "Grxxx". The change is only done at the declaration * of the procedure, so we need these declarations to handle uses * of those names, which don't get modified. Check out the Makefile * for details on this. */ extern Void GrOGLClose(), GrOGLFlush(), GrOGLInit(), GrOGLCreate(); extern Void GrOGLDelete(),GrOGLConfigure(),GrOGLRaise(),GrOGLLower(); extern Void GrOGLLock(),GrOGLUnlock(),GrOGLIconUpdate(); extern Void grOGLWStdin(int , ClientData ); /*--------------------------------------------------------- * grxSetWMandC: * This is a local routine that resets the value of the current * write mask and color, if necessary. * * Results: None. * * Side Effects: None. * * Errors: None. *--------------------------------------------------------- */ Void groglSetWMandC (mask, c) int mask; /* New value for write mask */ int c; /* New value for current color */ { static int oldMask = -1; static int oldColor = -1; int lr, lb, lg; GLfloat fr, fb, fg; GLfloat aval = 0.75; /* Alpha value */ if (mask == oldMask && c == oldColor) return; /* ErrPrint2("Set mask (%d) and color (%d)\n", mask, c); */ GrGetColor(c, &lr, &lb, &lg); if (mask == -65) mask = 127; /* All planes */ GR_X_FLUSH_BATCH(); fr = ((GLfloat)lr / 255); fg = ((GLfloat)lg / 255); fb = ((GLfloat)lb / 255); if (mask == 127) glDisable(GL_BLEND); else { /* temporary: Calculate a "supercolor", out of normal color range, but */ /* which results in the desired color after a blend with the background. */ fr = fr * 2 - 0.8; fg = fg * 2 - 0.8; fb = fb * 2 - 0.8; glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } glColor4f(fr, fb, fg, aval); /* ErrPrint4("Mask is %d; Color is (%3.2f, %3.2f, %3.2f)\n", mask, */ /* fr, fb, fg); */ /* ErrPrint("Done with color and mask\n"); */ oldMask = mask; oldColor = c; } /*--------------------------------------------------------- * grxSetLineStyle: * This local routine sets the current line style. * * Results: None. * * Side Effects: * A new line style is output to the display. * *--------------------------------------------------------- */ Void groglSetLineStyle (style) int style; /* New stipple pattern for lines. */ { static int oldStyle = -1; GLushort glstyle; style &= 0xFF; if (style == oldStyle) return; oldStyle = style; GR_X_FLUSH_BATCH(); /* ErrPrint("Setting line style\n"); */ switch (style) { case 0xFF: case 0x00: glDisable(GL_LINE_STIPPLE); break; default: glstyle = style | (style << 8); glEnable(GL_LINE_STIPPLE); glLineStipple(1, glstyle); } /* ErrPrint("done Setting line style\n"); */ } /*--------------------------------------------------------- * grxSetSPattern: * xSetSPattern associates a stipple pattern with a given * stipple number. This is a local routine called from * grStyle.c . * * Results: None. * * Side Effects: None. *--------------------------------------------------------- */ Void groglSetSPattern (stipple, pattern) int stipple; /* The stipple number, 1-15. */ int pattern[8]; /* 32 x 32 bit pattern */ { int i, j, n = 0; GLubyte *pdata; pdata = (GLubyte *)mallocMagic(128 * sizeof(GLubyte)); /* expand magic's default 8x8 stipple to OpenGL's 32x32 */ for (i = 0; i < 32; i++) for (j = 0; j < 4; j++) { pdata[n++] = (GLubyte)pattern[i % 8]; } grOGLStipples[stipple] = pdata; } /*--------------------------------------------------------- * grxSetStipple: * This routine sets the Xs current stipple number. * * Results: None. * * Side Effects: * The current clipmask in the X is set to stipple, * if it wasn't that already. *--------------------------------------------------------- */ Void groglSetStipple (stipple) int stipple; /* The stipple number to be used. */ { static int oldStip = -1; if (stipple == oldStip) return; oldStip = stipple; /* ErrPrint("Setting polygon stipple\n"); */ if (stipple == 0 || stipple > GR_NUM_STIPPLES) { glDisable(GL_POLYGON_STIPPLE); } else { if (grOGLStipples[stipple] == (GLubyte *)NULL) MainExit(1); glEnable(GL_POLYGON_STIPPLE); glPolygonStipple(grOGLStipples[stipple]); } /* ErrPrint("done Setting polygon stipple\n"); */ } bool /*--------------------------------------------------------- * GrOGLInit: * GrOGLInit initializes the graphics display and clears its screen. * Files must have been previously opened with GrSetDisplay(); * * Results: TRUE if successful. *--------------------------------------------------------- */ GrOGLInit () { XVisualInfo *grVisualInfo; static int attributeList[] = { GLX_RGBA, None, None }; static char *OGLCMapType = "OpenGL"; /* ErrPrint("GrOGLInit:\n"); */ GrBoxWidenFactor = 2; grCMapType = OGLCMapType; grXdpy = XOpenDisplay(NULL); if (grXdpy == NULL) { TxError("Couldn't open display; check DISPLAY variable\n"); return false; } grXscrn = DefaultScreen(grXdpy); grVisualInfo = glXChooseVisual(grXdpy, grXscrn, attributeList); if (!grVisualInfo) { /* Try for a double-buffered configuration (added by Holger Vogt) */ attributeList[1] = GLX_DOUBLEBUFFER; grVisualInfo = glXChooseVisual(grXdpy, grXscrn, attributeList); if (!grVisualInfo) { TxError("No suitable visual!\n"); MainExit(1); } } grXscrn = grVisualInfo->screen; grVisual = grVisualInfo->visual; oglCurrent.depth = grVisualInfo->depth; sprintf(grXdepth, "%dbit", oglCurrent.depth); /* ErrPrint1("Visual depth is %d bits\n", oglCurrent.depth); */ grXcontext = glXCreateContext(grXdpy, grVisualInfo, NULL, GL_TRUE); HashInit(&grOGLWindowTable,8,HT_WORDKEYS); if (grVisualInfo != NULL) XFree(grVisualInfo); return groglPreLoadFont(); } /*--------------------------------------------------------- * GrOGLClose: * * Results: None. * * Side Effects: None. *--------------------------------------------------------- */ Void GrOGLClose () { if (grXdpy == NULL) return; TxDelete1InputDevice(pipeRead); close(pipeRead); kill(Xhelper, SIGKILL); do {} while (wait(0) != Xhelper); XCloseDisplay(grXdpy); } /*--------------------------------------------------------- * GrOGLFlush: * Flush output to display. * * Flushing is done automatically the next time input is read, * so this procedure should not be used very often. * * Results: None. * * Side Effects: None. *--------------------------------------------------------- */ Void GrOGLFlush () { /* ErrPrint("Flushing GL calls\n"); */ GR_X_FLUSH_BATCH(); glFlush(); glFinish(); /* ErrPrint("Done(GrOGLFlush)\n"); */ } /*------------------------------------------------------*/ /* Translate event coordinate to window coordinate */ /* (y is flipped relative to the window top) */ /*------------------------------------------------------*/ #define glTransYs(n) (DisplayHeight(grXdpy, grXscrn)-(n)) /* int glTransYs(int wy) { int my; GLint vparms[4]; glGetIntegerv(GL_VIEWPORT, vparms); my = vparms[3] - wy; return my; } */ /*----------------------------------------------------------------------*/ /* pipehandler() is the callback set up by TxAdd1Input. The purpose is */ /* to comply with magic's interrupt-driven protocol; magic blocks on */ /* select() until an input arrives at a registered file descriptor, */ /* then executes the callback associated with the fd, then checks to */ /* see if the Tx event queue size grew. X11Handler passes info along */ /* to X11Stdin() in the X11 version; that's because the X11 XtMainLoop */ /* is a macro and can be re-implemented using XNextEvent() calls. GL's */ /* glutMainLoop is not a macro, therefore we have to use its callback */ /* functions. But we can't make OpenGL calls from the callbacks with- */ /* out occasionally colliding with OpenGL calls made from the main */ /* process, so we get even more kludgy by doing the same thing as */ /* X11Handler but writing to the pipe from the callback function rather */ /* than from inside the main loop, which we can't touch. ---Tim */ /*----------------------------------------------------------------------*/ void pipehandler() { TxInputEvent *event; XEvent xevent; HashEntry *entry; read(pipeRead, &xevent, sizeof(XEvent)); /* ErrPrint("Pipehandler:\n"); */ switch(xevent.type) { case KeyPress: { /* Keyboard Callback Function */ int wx, wy, ky; int key; XKeyPressedEvent *KeyPressedEvent = (XKeyPressedEvent *) &xevent; /* ErrPrint3("KEY char=%d wx=%d wy=%d\n", key, wx, wy); */ oglCurrent.window = KeyPressedEvent->window; entry = HashLookOnly(&grOGLWindowTable,oglCurrent.window); oglCurrent.mw = (entry)?(MagWindow *)HashGetValue(entry):0; event = TxNewEvent(); read(pipeRead, &key, sizeof(int)); if (key == (int)'\015') key = (int)'\n'; /* Linefeed to Return */ event->txe_button = TX_CHARACTER; event->txe_ch = key; event->txe_buttonAction = TX_KEY_DOWN; event->txe_p.p_x = KeyPressedEvent->x; event->txe_p.p_y = glTransY(KeyPressedEvent->y); event->txe_wid = oglCurrent.mw ? oglCurrent.mw->w_wid : 0; TxAddEvent(event); } break; case ButtonPress: case ButtonRelease: { /* Mouse Callback Function */ XButtonEvent *ButtonEvent = (XButtonEvent *) &xevent; /* ErrPrint4("MOUSE button=%d state=%d wx=%d wy=%d\n", button, state, wx, wy); */ oglCurrent.window = ButtonEvent->window; entry = HashLookOnly(&grOGLWindowTable,oglCurrent.window); oglCurrent.mw = (entry)?(MagWindow *)HashGetValue(entry):0; event = TxNewEvent(); switch (ButtonEvent->button) { case Button1: event->txe_button = TX_LEFT_BUTTON; break; case Button2: event->txe_button = TX_MIDDLE_BUTTON; break; case Button3: event->txe_button = TX_RIGHT_BUTTON; break; } switch(ButtonEvent->type) { case ButtonRelease: event->txe_buttonAction = TX_BUTTON_UP; break; case ButtonPress: event->txe_buttonAction = TX_BUTTON_DOWN; break; } event->txe_p.p_x = ButtonEvent->x; event->txe_p.p_y = glTransY(ButtonEvent->y); event->txe_wid = oglCurrent.mw ? oglCurrent.mw->w_wid : 0; TxAddEvent(event); } break; case ConfigureNotify: { /* Reshape/Resize Callback Function */ XConfigureEvent *ConfigureEvent = (XConfigureEvent *) &xevent; Rect screenRect; int width, height; width = ConfigureEvent->width; height = ConfigureEvent->height; /* ErrPrint2("RESHAPE to width=%d height=%d\n", width, height); */ oglCurrent.window = ConfigureEvent->window; entry = HashLookOnly(&grOGLWindowTable,oglCurrent.window); oglCurrent.mw = (entry)?(MagWindow *)HashGetValue(entry):0; screenRect.r_xbot = ConfigureEvent->x; screenRect.r_xtop = ConfigureEvent->x + width; screenRect.r_ybot = ConfigureEvent->y; screenRect.r_ytop = ConfigureEvent->y + height; SigDisableInterrupts(); /* Basic GL parameters */ glLineWidth(1.0); glShadeModel (GL_FLAT); glPixelStorei(GL_PACK_LSB_FIRST, true); /* Force draw to front buffer (in case of double-buffered config) */ glDrawBuffer(GL_FRONT); /* added by Holger Vogt */ /* Open GL window reshape calls */ glMatrixMode(GL_PROJECTION); glLoadIdentity(); glViewport(0, 0, (GLsizei) width, (GLsizei) height); /* scale to fit window */ glScalef(1.0 / (float)(width >> 1), 1.0 / (float)(height >> 1), 1.0); /* magic origin maps to window center: move to window origin */ glTranslated(-(GLsizei)(width >> 1), -(GLsizei)(height >> 1), 0); gluOrtho2D(0, 0, (GLsizei) width, (GLsizei) height); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); /* Redraw the window */ WindReframe(oglCurrent.mw,&screenRect,FALSE,FALSE); WindRedisplay(oglCurrent.mw); SigEnableInterrupts(); } break; case Expose: { /* (Re)Display Callback Function */ Rect screenRect; XExposeEvent *ExposeEvent = (XExposeEvent*) &xevent; /* ErrPrint("REDISPLAY\n"); */ oglCurrent.window = ExposeEvent->window; entry = HashLookOnly(&grOGLWindowTable,oglCurrent.window); oglCurrent.mw = (entry)?(MagWindow *)HashGetValue(entry):0; screenRect.r_xbot = ExposeEvent->x; screenRect.r_xtop = ExposeEvent->x+ExposeEvent->width; screenRect.r_ytop = oglCurrent.mw->w_allArea.r_ytop-ExposeEvent->y; screenRect.r_ybot = oglCurrent.mw->w_allArea.r_ytop - (ExposeEvent->y + ExposeEvent->height); WindAreaChanged(oglCurrent.mw, &screenRect); WindUpdate(oglCurrent.mw); } break; case CreateNotify: { MagWindow *w; XAnyEvent *AnyEvent = (XAnyEvent *) &xevent; /* ErrPrint("CreateNotify Callback\n"); */ oglCurrent.window = AnyEvent->window; entry = HashLookOnly(&grOGLWindowTable,oglCurrent.window); w = (entry)?(MagWindow *)HashGetValue(entry):0; SigDisableInterrupts(); WindView(w); SigEnableInterrupts(); } break; } /* ErrPrint("Done (pipehandler)\n"); */ } /*--------------------------------------------------------- * oglSetDisplay: * This routine sets the appropriate parameters so that * Magic will work with glut. * * glut (OpenGL) calls for an interruptible event loop, * which avoids the necessity in Xlib to spawn a * separate process for handling X events. * * Results: success / fail * *--------------------------------------------------------- */ bool oglSetDisplay (dispType, outFileName, mouseFileName) char *dispType; /* arguments not used by X */ char *outFileName; char *mouseFileName; { int fildes[2], fildes2[2]; char *planecount; char *fullname; FILE* f; bool execFailed = false; WindPackageType = WIND_X_WINDOWS; /* This works okay. */ grCursorType = "bw"; WindScrollBarWidth = 14; pipe(fildes); pipe(fildes2); pipeRead = fildes[0]; pipeWrite = fildes2[1]; TxAdd1InputDevice(pipeRead, pipehandler, (ClientData) NULL); #ifdef CYGWIN f = PaOpen(X11HELP_PROG, "r", ".exe", HELPER_PATH, (char *) NULL, &fullname); #else f = PaOpen(X11HELP_PROG, "r", (char *) NULL, HELPER_PATH, (char *) NULL, &fullname); #endif if (f == NULL) { int error; TxError("Couldn't find helper process %s in search path \"%s\"\n", X11HELP_PROG, HELPER_PATH); error = 0; write(fildes[1], &error, 4); return false; } else { fclose(f); } FORK(Xhelper); if (Xhelper == 0) { /* Child process */ char argv[2][100]; sprintf(argv[0], "%s", fullname); sprintf(argv[1], "%d %d", fildes2[0],fildes[1]); if (execl(argv[0], argv[0], argv[1], 0) != 0) { execFailed = true; TxError("Couldn't execute helper process \"%s\".\n", fullname); TxFlush(); /* we're the child process -- don't muck things up by returning */ _exit(656); /* see vfork man page for reason for _exit() */ } }; sleep(1); /* Set up the procedure values in the indirection table. */ GrLockPtr = GrOGLLock; GrUnlockPtr = GrOGLUnlock; GrInitPtr = GrOGLInit; GrClosePtr = GrOGLClose; GrSetCMapPtr = GrOGLSetCMap; GrEnableTabletPtr = GrOGLEnableTablet; GrDisableTabletPtr = GrOGLDisableTablet; GrSetCursorPtr = GrOGLSetCursor; GrTextSizePtr = GrOGLTextSize; GrDrawGlyphPtr = GrOGLDrawGlyph; GrReadPixelPtr = GrOGLReadPixel; GrFlushPtr = GrOGLFlush; GrCreateWindowPtr = GrOGLCreate; GrDeleteWindowPtr = GrOGLDelete; GrConfigureWindowPtr = GrOGLConfigure; GrOverWindowPtr = GrOGLRaise; GrUnderWindowPtr = GrOGLLower; GrUpdateIconPtr = GrOGLIconUpdate; /* local indirections */ grSetSPatternPtr = groglSetSPattern; grPutTextPtr = groglPutText; grDefineCursorPtr = groglDefineCursor; GrBitBltPtr = GrOGLBitBlt; grDrawGridPtr = groglDrawGrid; grDrawLinePtr = groglDrawLine; grSetWMandCPtr = groglSetWMandC; grFillRectPtr = groglFillRect; grSetStipplePtr = groglSetStipple; grSetLineStylePtr = groglSetLineStyle; grSetCharSizePtr = groglSetCharSize; grMaxStipples = 32; #ifdef NONMANHATTAN grFillPolygonPtr = groglFillPolygon; #endif if (execFailed) { TxError("Execution failed!\n"); return false; } TxAdd1InputDevice(fileno(stdin), grOGLWStdin, (ClientData) NULL); if(!GrOGLInit()){ return false; } GrScreenRect.r_xbot = 0; GrScreenRect.r_ybot = 0; GrScreenRect.r_xtop = DisplayWidth(grXdpy,grXscrn); GrScreenRect.r_ytop = DisplayHeight(grXdpy,grXscrn); return true; } /* * ---------------------------------------------------------------------------- * * grOGLWStdin -- * Handle the stdin device for X window interface. * * Results: * None. * * Side Effects: * Adds events to the event queue. * * ---------------------------------------------------------------------------- */ /*ARGSUSED*/ Void grOGLWStdin(fd, cdata) int fd; ClientData cdata; { int ch; TxInputEvent *event; event = TxNewEvent(); ch = getc(stdin); if (ch == EOF) event->txe_button = TX_EOF; else event->txe_button = TX_CHARACTER; event->txe_ch = ch; event->txe_buttonAction = 0; event->txe_wid = WIND_NO_WINDOW; event->txe_p.p_x = GR_CURSOR_X; event->txe_p.p_y = GR_CURSOR_Y; TxAddEvent(event); } /* * ---------------------------------------------------------------------------- * * GrOGLCreate -- * Create a new window under OpenGL * Bind OpenGL window to Magic Window w. * * Results: * Window created, window ID send to OGLhelper. * * Side Effects: * None. * * ---------------------------------------------------------------------------- */ GrOGLCreate(w) MagWindow *w; { Window wind; HashEntry *entry; static int firstWindow = 1; XSizeHints *xsh; char *windowplace; char *option = (firstWindow)?"window":"newwindow"; int x = w->w_frameArea.r_xbot; int y = glTransYs(w->w_frameArea.r_ytop); int width = w->w_frameArea.r_xtop - w->w_frameArea.r_xbot; int height = w->w_frameArea.r_ytop - w->w_frameArea.r_ybot; unsigned long attribmask = CWBackPixel | CWBorderPixel | CWColormap; XSetWindowAttributes grAttributes; XConfigureEvent xevent; WindSeparateRedisplay(w); xsh = XAllocSizeHints(); if (windowplace=XGetDefault(grXdpy,"magic",option)) { XParseGeometry(windowplace,&x,&y,&width,&height); w->w_frameArea.r_xbot = x; w->w_frameArea.r_xtop = x+width; w->w_frameArea.r_ytop = glTransYs(y); w->w_frameArea.r_ybot = glTransYs(y+height); WindReframe(w,&(w->w_frameArea),FALSE,FALSE); xsh->flags = USPosition | USSize; } else { xsh->flags = PPosition|PSize; } /* ErrPrint("Creating OpenGL window.\n"); */ grAttributes.colormap = XCreateColormap(grXdpy, RootWindow(grXdpy, grXscrn), grVisual, AllocNone); grAttributes.background_pixel = WhitePixel(grXdpy, grXscrn); grAttributes.border_pixel = BlackPixel(grXdpy,grXscrn); if (wind = XCreateWindow(grXdpy, RootWindow(grXdpy, grXscrn), x, y, width, height, 0, oglCurrent.depth, InputOutput, grVisual, attribmask, &grAttributes)) { oglCurrent.window = wind; xsh->x = w->w_frameArea.r_xbot; xsh->y = glTransYs(w->w_frameArea.r_ytop); xsh->width = w->w_frameArea.r_xtop - w->w_frameArea.r_xbot; xsh->height= w->w_frameArea.r_ytop - w->w_frameArea.r_ybot; /* ErrPrint4(stderr, "x = %d, y = %d, width = %d, height = %d\n", */ /* xsh->x, xsh->y, xsh->width, xsh->height); */ XSetStandardProperties(grXdpy, wind, "magic", "magic", None, 0, 0, xsh); XMapWindow(grXdpy, wind); glXMakeCurrent(grXdpy, (GLXDrawable)wind, grXcontext); /* ErrPrint1("Window 0x%x is now mapped.\n", wind); */ oglCurrent.mw = w; w->w_grdata = (ClientData) wind; entry = HashFind(&grOGLWindowTable,oglCurrent.window); HashSetValue(entry,w); XDefineCursor(grXdpy, oglCurrent.window,oglCurrent.cursor); GrOGLIconUpdate(w,w->w_caption); XSync(grXdpy,0); if (firstWindow) firstWindow = 0; write(pipeWrite, (char *) &wind, sizeof(Window)); kill( Xhelper, SIGTERM); /* ErrPrint1("Done with window %d Creation.\n", wind); */ /* Force a StructureNotify event to get X11Helper to paint the window */ usleep(600); xevent.type = ConfigureNotify; xevent.width = width; xevent.height = height; xevent.x = xsh->x; xevent.y = xsh->y; xevent.window = wind; XSendEvent(grXdpy, wind, false, StructureNotifyMask, (XEvent *)&xevent); XFree(xsh); return groglLoadFont(); } else { TxError("Could not open new X window\n"); } return 0; } /* * ---------------------------------------------------------------------------- * * GrXDelete -- * Destroy an X window. * * Results: * Window destroyed. * * * ---------------------------------------------------------------------------- */ GrOGLDelete(w) MagWindow *w; { int xw; HashEntry *entry; xw = (Window) w->w_grdata; entry = HashLookOnly(&grOGLWindowTable,xw); HashSetValue(entry,NULL); XDestroyWindow(grXdpy, xw); } /* * ---------------------------------------------------------------------------- * * GrOGLConfigure -- * Full Screen function * * Results: * Window reconfigured to w->w_frameArea. * * Side Effects: * None. * * ---------------------------------------------------------------------------- */ /*ARGSUSED*/ GrOGLConfigure(w) MagWindow *w; { /* ErrPrint("GrOGLconfigure:\n"); */ XMoveResizeWindow(grXdpy,(Window) w->w_grdata, w->w_frameArea.r_xbot, glTransYs(w->w_frameArea.r_ytop), w->w_frameArea.r_xtop - w->w_frameArea.r_xbot, w->w_frameArea.r_ytop - w->w_frameArea.r_ybot); } /* * ---------------------------------------------------------------------------- * * GrXRaise -- * Raise a window to the top of the screen such that nothing * obscures it. * * Results: * Window raised. * * Side Effects: * None. * * ---------------------------------------------------------------------------- */ GrOGLRaise(w) MagWindow *w; { /* ErrPrint("Call to Raise\n"); */ XRaiseWindow(grXdpy, (Window) w->w_grdata ); } /* * ---------------------------------------------------------------------------- * * GrXLower -- * Lower a window below all other X windows. * obscures it. * * Results: * Window lowered. * * Side Effects: * None. * * ---------------------------------------------------------------------------- */ GrOGLLower(w) MagWindow *w; { /* ErrPrint("Call to Lower\n"); */ XLowerWindow(grXdpy, (Window) w->w_grdata ); } /* * ---------------------------------------------------------------------------- * * GrOGLLock -- * Lock a window and set global variables "oglCurrent.window" * and "oglCurrent.mw" to reference the locked window. * * Results: * Window locked. * * Side Effects: * None. * * ---------------------------------------------------------------------------- */ GrOGLLock(w, flag) MagWindow *w; bool flag; { grSimpleLock(w, flag); if ( w != (MagWindow *) GR_LOCK_SCREEN ) { oglCurrent.mw = w; oglCurrent.window = (Window) w->w_grdata; /* ErrPrint2("Setting window to 0x%x, Assoc. drawable 0x%x\n", */ /* w, w->w_grdata); */ glXMakeCurrent(grXdpy, (GLXDrawable)w->w_grdata, grXcontext); } } /* * ---------------------------------------------------------------------------- * * GrOGLUnlock -- * Unlock a window, flushing stuff out to the display. * * Results: * Window unlocked. * * Side Effects: * Display update. * * ---------------------------------------------------------------------------- */ GrOGLUnlock(w) MagWindow *w; { GR_X_FLUSH_BATCH(); grSimpleUnlock(w); } /* *------------------------------------------------------------------------- * * GrOGLIconUpdate -- updates the icon text with the window script * * Results: none * * Side Effects: changes the icon text * *------------------------------------------------------------------------- */ Void GrOGLIconUpdate(w,text) MagWindow *w; char *text; { Window wind = (Window) w->w_grdata; XClassHint class; char *brack; if (w->w_grdata == NULL) return; class.res_name = "magic"; class.res_class = "magic"; XSetClassHint( grXdpy, wind, &class); if (brack = index(text,'[')) { brack--; *brack = 0; XSetIconName(grXdpy,wind,text); XStoreName(grXdpy,wind,text); *brack = ' '; return; } if (brack = rindex(text,' ')) text = brack+1; XSetIconName(grXdpy,wind,text); XStoreName(grXdpy,wind,text); }