Logo Search packages:      
Sourcecode: magic version File versions  Download package

grOGL1.c

/* 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 <GL/gl.h>
#include <GL/glx.h>

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <signal.h>

#include "utils/magic.h"
#include "utils/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 "utils/signals.h"
#include "utils/utils.h"
#include "utils/hash.h"
#include "grOGLInt.h"
#include "utils/paths.h"

GLubyte     **grOGLStipples;
HashTable   grOGLWindowTable;
Display     *grXdpy;
GLXContext  grXcontext;
int         grXscrn;
int         pipeRead, pipeWrite;
int         Xhelper;
Visual            *grVisual;

#ifdef HAVE_PTHREADS
extern int writePipe;
extern int readPipe;        /* As seen from child */
#endif

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();
extern void GrOGLDelete(), GrOGLConfigure(), GrOGLRaise(), GrOGLLower();
extern void GrOGLLock(), GrOGLUnlock(), GrOGLIconUpdate();
extern bool GrOGLInit(), GrOGLCreate();
extern void grOGLWStdin();


/*---------------------------------------------------------
 * groglSetWMandC:
 *    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 == -65) mask = 127;          /* All planes */
    if (mask == oldMask && c == oldColor) return;

    GR_X_FLUSH_BATCH();

    GrGetColor(c, &lr, &lb, &lg);

    fr = ((GLfloat)lr / 255);
    fg = ((GLfloat)lg / 255);
    fb = ((GLfloat)lb / 255);

    if (mask == 127)
       glDisable(GL_BLEND);
    else {
       /* 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); 

    oldMask = mask;
    oldColor = c;
}


/*---------------------------------------------------------
 * groglSetLineStyle:
 *    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();

    switch (style) {
    case 0xFF:
    case 0x00:
      glDisable(GL_LINE_STIPPLE);
      break;
    default:
      glstyle = style | (style << 8);
      glEnable(GL_LINE_STIPPLE);
      glLineStipple(1, glstyle);
    }
}


/*---------------------------------------------------------
 * groglSetSPattern:
 *    xSetSPattern associates stipple patterns with
 *    OpenGL stipples.  This is a local routine
 *    called from grStyle.c.
 *
 * Results: None.
 *
 * Side Effects:    None.
 *---------------------------------------------------------
 */

void
groglSetSPattern (sttable, numstipples)
    int **sttable;                  /* The table of patterns */
    int numstipples;                /* Number of stipples */
{
    int i, j, k, n;
    GLubyte *pdata;

    grOGLStipples = (GLubyte **)mallocMagic(numstipples * sizeof(GLubyte *));
    for (k = 0; k < numstipples; k++)
    {
      pdata = (GLubyte *)mallocMagic(128 * sizeof(GLubyte));
      n = 0;

      /* 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)sttable[k][i % 8];

      grOGLStipples[k] = pdata;
    }
}


/*---------------------------------------------------------
 * groglSetStipple:
 *    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;
    GR_X_FLUSH_BATCH();
    if (stipple == 0 || stipple > grNumStipples) {
      glDisable(GL_POLYGON_STIPPLE);
    } else {
      if (grOGLStipples[stipple] == (GLubyte *)NULL) MainExit(1);
      glEnable(GL_POLYGON_STIPPLE);
      glPolygonStipple(grOGLStipples[stipple]);
    }
}


/*---------------------------------------------------------
 * GrOGLInit:
 *    GrOGLInit initializes the graphics display and clears its screen.
 *    Files must have been previously opened with GrSetDisplay();
 *
 * Results: TRUE if successful.
 *---------------------------------------------------------
 */

bool
GrOGLInit()
{
    XVisualInfo *grVisualInfo;
    static int    attributeList[] = { GLX_RGBA, None, None };
    static char *OGLCMapType = "OpenGL";

    grCMapType = OGLCMapType;
    grDStyleType = OGLCMapType;

#ifdef HAVE_PTHREADS
    XInitThreads();
#endif

    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;

    /* Note: The last parameter is GL_TRUE for direct rendering.  */
    /* Direct rendering has a speedup advantange for raw rendering, but */
    /* disallows X11 operations such as XCopyArea, which prevents the   */
    /* implementation of backing store and fast screen refreshes.  So   */
    /* we force an indirect rendering context through the X server.     */

    grXcontext = glXCreateContext(grXdpy, grVisualInfo, NULL, GL_FALSE);

    /* Basic GL parameters */

    glLineWidth(1.0);
    glShadeModel (GL_FLAT);
    glPixelStorei(GL_PACK_LSB_FIRST, TRUE);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    HashInit(&grOGLWindowTable,8,HT_WORDKEYS);

    /* Globally-accessed variables */
    grNumBitPlanes = oglCurrent.depth;
    grBitPlaneMask = (1 << oglCurrent.depth) - 1;

    if (grVisualInfo != NULL) XFree(grVisualInfo);
    return groglPreLoadFont();
}

/*---------------------------------------------------------
 * GrOGLClose:
 *
 * Results:
 *    None.
 *
 * Side Effects:
 *    Helper process/thread killed.
 *---------------------------------------------------------
 */

void
GrOGLClose()
{
    if (grXdpy == NULL) return;
    TxDelete1InputDevice(pipeRead);
    close(pipeRead);
#ifndef HAVE_PTHREADS
    kill(Xhelper, SIGKILL);
    do {} while (wait(0) != Xhelper);
#endif
    XCloseDisplay(grXdpy);
#ifdef HAVE_PTHREADS
    xloop_end();
#endif
}


/*---------------------------------------------------------
 * 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()
{
   GR_X_FLUSH_BATCH();
   glFlush();
   glFinish();
}

/*------------------------------------------------------*/
/* 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;
}
*/

/*
 *----------------------------------------------------------------------
 * Set the OpenGL viewport (projection matrix) for the current window
 *----------------------------------------------------------------------
 */
int
oglSetProjection(llx, lly, width, height)
    int llx, lly, width, height;
{
    glXMakeCurrent(grXdpy, (GLXDrawable)oglCurrent.window, grXcontext);

#ifndef OGL_SERVER_SIDE_ONLY
    /* For batch-processing lines and rectangles */
    glEnableClientState(GL_VERTEX_ARRAY);
#endif

    /* Force draw to front buffer (in case of double-buffered config) */
    glDrawBuffer(GL_FRONT);         /* added by Holger Vogt */

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();

    glViewport((GLsizei)llx, (GLsizei)lly, (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);
}

/*----------------------------------------------------------------------*/
/* 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. */
/*----------------------------------------------------------------------*/

void
pipehandler()
{
   TxInputEvent   *event;
   XEvent   xevent;
   HashEntry      *entry;
   MagWindow      *mw;

   read(pipeRead, &xevent, sizeof(XEvent));

   switch(xevent.type) {
      case KeyPress:    {     /* Keyboard Callback Function */

      int         wx, wy, ky;
      int         key;
      XKeyPressedEvent *KeyPressedEvent = (XKeyPressedEvent *) &xevent;

      entry = HashLookOnly(&grOGLWindowTable, KeyPressedEvent->window);
      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(mw, KeyPressedEvent->y);
      event->txe_wid = mw ? mw->w_wid : WIND_UNKNOWN_WINDOW;
      TxAddEvent(event);
      } break;

      case ButtonPress:
      case ButtonRelease: {   /* Mouse Callback Function */

      XButtonEvent *ButtonEvent = (XButtonEvent *) &xevent;

      entry = HashLookOnly(&grOGLWindowTable, ButtonEvent->window);
      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;
          case Button4:
            event->txe_button = TX_BUTTON_4;
            break;
          case Button5:
            event->txe_button = TX_BUTTON_5;
            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(mw, ButtonEvent->y);
      event->txe_wid = mw ? mw->w_wid : WIND_UNKNOWN_WINDOW;

      TxAddEvent(event);
      } break;

      case ConfigureNotify:   {     /* Reshape/Resize Callback Function */

      XConfigureEvent *ConfigureEvent = (XConfigureEvent *) &xevent;
      XEvent            discard;
      Rect        screenRect;
      int         width, height;

      width = ConfigureEvent->width;
      height = ConfigureEvent->height;

      entry = HashLookOnly(&grOGLWindowTable, ConfigureEvent->window);
      mw = (entry) ? (MagWindow *)HashGetValue(entry) : 0;

      screenRect.r_xbot = ConfigureEvent->x;
      screenRect.r_xtop = ConfigureEvent->x + width;
      screenRect.r_ybot = glTransYs(ConfigureEvent->y);
      screenRect.r_ytop = glTransYs(ConfigureEvent->y + height);
             
      SigDisableInterrupts();

      /* Redraw the window */

      WindReframe(mw, &screenRect, FALSE, FALSE);
      WindRedisplay(mw);
      SigEnableInterrupts();

      } break;

      case VisibilityNotify:        {
          XVisibilityEvent *VisEvent = (XVisibilityEvent*) &xevent;

          entry = HashLookOnly(&grOGLWindowTable, VisEvent->window);
          mw = (entry)?(MagWindow *)HashGetValue(entry):0;

          switch(VisEvent->state)
          {
            case VisibilityUnobscured:
                mw->w_flags &= ~WIND_OBSCURED;
                if (mw->w_backingStore == (ClientData)NULL)
                {
                  groglCreateBackingStore(mw);
                  if (mw->w_backingStore != (ClientData)NULL)
                  {
                      WindAreaChanged(mw, &mw->w_allArea);
                      WindUpdate();
                  }
                }
                break;
            case VisibilityPartiallyObscured:
            case VisibilityFullyObscured:
                mw->w_flags |= WIND_OBSCURED;
                break;
          }
      } break;

      case Expose:      {     /* (Re)Display Callback Function */

      Rect        screenRect;
      XEvent            discard;
      XExposeEvent      *ExposeEvent = (XExposeEvent*) &xevent;

      entry = HashLookOnly(&grOGLWindowTable, ExposeEvent->window);
      mw = (entry) ? (MagWindow *)HashGetValue(entry) : 0;

      screenRect.r_xbot = ExposeEvent->x;
      screenRect.r_xtop = ExposeEvent->x + ExposeEvent->width;
      screenRect.r_ytop = mw->w_allArea.r_ytop - ExposeEvent->y;
      screenRect.r_ybot = mw->w_allArea.r_ytop -
                  (ExposeEvent->y + ExposeEvent->height);

      if (mw->w_backingStore != (ClientData)NULL)
      {
          Rect surface;
          (*GrGetBackingStorePtr)(mw, &screenRect);
          WindScreenToSurface(mw, &screenRect, &surface);
          DBWHLRedrawPrepWindow(mw, &surface);
          WindDrawBorder(mw, &screenRect);
      }     
      else
          WindAreaChanged(mw, &screenRect);
      WindUpdate(mw);

      } break;

      case CreateNotify:      {
      
      XAnyEvent   *AnyEvent = (XAnyEvent *) &xevent;

      entry = HashLookOnly(&grOGLWindowTable, AnyEvent->window);
      mw = (entry)?(MagWindow *)HashGetValue(entry):0;

      SigDisableInterrupts();
      WindView(mw);
      SigEnableInterrupts();
      } break;
   }
}

/*---------------------------------------------------------
 * oglSetDisplay:
 *    This routine sets the appropriate parameters so that
 *    Magic will work with glX.
 *
 * 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 HAVE_PTHREADS
    writePipe = fildes[1];
    readPipe = fildes2[0];
#else
#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);
#endif

    /* Set up the procedure values in the indirection table. */

    GrPixelCorrect = 0;

    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; 
    GrBitBltPtr = GrOGLBitBlt;

    GrFreeBackingStorePtr = groglFreeBackingStore;
    GrCreateBackingStorePtr = groglCreateBackingStore;
    GrGetBackingStorePtr = groglGetBackingStore;
    GrPutBackingStorePtr = groglPutBackingStore;
    GrScrollBackingStorePtr = groglScrollBackingStore;

    /* local indirections */
    grSetSPatternPtr = groglSetSPattern;
    grPutTextPtr = groglPutText;
    grDefineCursorPtr = groglDefineCursor;
    grDrawGridPtr = groglDrawGrid;
    grDrawLinePtr = groglDrawLine;
    grSetWMandCPtr = groglSetWMandC;
    grFillRectPtr = groglFillRect;
    grSetStipplePtr = groglSetStipple;
    grSetLineStylePtr = groglSetLineStyle;
    grSetCharSizePtr = groglSetCharSize;
#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:
 *    Success/Fail
 *
 * Side Effects:
 *      Window created, window ID send to OGLhelper.
 *
 * ----------------------------------------------------------------------------
 */

bool
GrOGLCreate(w, name)
    MagWindow *w;
    char *name;
{
   Window   wind;
   HashEntry      *entry;
   static int     firstWindow = 1;
   XSizeHints     *xsh;
   char           *windowplace;
   char           *option = (firstWindow)?"window":"newwindow";
   bool           result = TRUE;
   int            x     = w->w_frameArea.r_xbot;
   int            y     = glTransYs(w->w_frameArea.r_ytop);
   unsigned int   width = w->w_frameArea.r_xtop - w->w_frameArea.r_xbot;
   unsigned 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;
   }

   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)) {
      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;
      XSetStandardProperties(grXdpy, wind, (name == NULL) ? "magic" : name,
                  "magic", None, 0, 0, xsh);

      XMapWindow(grXdpy, wind);

      oglCurrent.window = wind;
      oglCurrent.mw = w;
        glXMakeCurrent(grXdpy, (GLXDrawable)wind, grXcontext);

      w->w_grdata = (ClientData) wind;
      entry = HashFind(&grOGLWindowTable, wind);
      HashSetValue(entry,w);
      XDefineCursor(grXdpy, wind, oglCurrent.cursor);
      GrOGLIconUpdate(w, w->w_caption);

#ifdef HAVE_PTHREADS
        xloop_create(wind);
#else
      XSync(grXdpy,0);

      write(pipeWrite, (char *) &wind, sizeof(Window));
      kill( Xhelper, SIGTERM);
#endif

      if (firstWindow)
      {
          firstWindow = 0;
          result = groglLoadFont();
      }

      /* 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 result;
    }
    else {
      TxError("Could not open new X window\n");
      result = FALSE;
    }
    return result;
}

/*
 * ----------------------------------------------------------------------------
 *
 * GrOGLDelete --
 *      Destroy an X window.
 *
 * Results:
 *    None.
 *
 * Side effects:
 *      Window destroyed.
 *
 * ----------------------------------------------------------------------------
 */

void
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:
 *      None.
 *
 * Side Effects:
 *      Window reconfigured to w->w_frameArea.
 *
 * ----------------------------------------------------------------------------
 */

void
GrOGLConfigure(w)
    MagWindow *w;
{
    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);
}

/*
 * ----------------------------------------------------------------------------
 *
 * GrOGLRaise --
 *      Raise a window to the top of the screen such that nothing
 *    obscures it.
 *
 * Results:
 *      None.
 *
 * Side Effects:
 *      Window raised.
 *
 * ----------------------------------------------------------------------------
 */

void
GrOGLRaise(w)
    MagWindow *w;
{
    XRaiseWindow(grXdpy, (Window) w->w_grdata );
}

/*
 * ----------------------------------------------------------------------------
 *
 * GrOGLLower --
 *      Lower a window below all other X windows.
 *    obscures it.
 *
 * Results:
 *      None.
 *
 * Side Effects:
 *      Window lowered.
 *
 * ----------------------------------------------------------------------------
 */

void
GrOGLLower(w)
    MagWindow *w;
{
    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:
 *    None.
 *
 * Side Effects:
 *      Window locked.
 *
 * ----------------------------------------------------------------------------
 */

void
GrOGLLock(w, flag)
    MagWindow *w;
    bool flag;
{
    grSimpleLock(w, flag);
    if ( w != GR_LOCK_SCREEN )
    {
      oglCurrent.mw = w;
      oglCurrent.window = (Window) w->w_grdata;

      oglSetProjection(w->w_allArea.r_xbot, w->w_allArea.r_ybot,
                   w->w_allArea.r_xtop - w->w_allArea.r_xbot,
                   w->w_allArea.r_ytop - w->w_allArea.r_ybot);
    }
}

/*
 * ----------------------------------------------------------------------------
 *
 * GrOGLUnlock --
 *      Unlock a window, flushing stuff out to the display.
 *
 * Results:
 *    Display update.
 *
 * Side Effects:
 *      Window unlocked.
 *
 * ----------------------------------------------------------------------------
 */

void
GrOGLUnlock(w)
    MagWindow *w;
{
    GrOGLFlush();
    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 == (ClientData)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);
}

Generated by  Doxygen 1.6.0   Back to index