magic/graphics/grOGL1.c

1098 lines
27 KiB
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"
/* C99 compat */
#include "dbwind/dbwind.h"
#include "utils/main.h"
#include "utils/malloc.h"
GLubyte **grOGLStipples;
HashTable grOGLWindowTable;
extern Display *grXdpy; /* grX11thread.c */
GLXContext grXcontext;
extern int grXscrn; /* grX11su1.c */
extern int pipeRead, pipeWrite; /* grX11su1.c */
extern int Xhelper; /* grX11su1.c */
extern Visual *grVisual; /* grX11su1.c */
#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(int fd, ClientData cdata); /* cb_textio_input_t (unused) */
/*---------------------------------------------------------
* 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);
ATTR_UNREACHABLE;
}
}
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
*----------------------------------------------------------------------
*/
void
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 */
#ifdef OGL_INVERT_Y
glScalef(1.0 / (float)(width >> 1), -1.0 / (float)(height >> 1), 1.0);
#else
glScalef(1.0 / (float)(width >> 1), 1.0 / (float)(height >> 1), 1.0);
#endif
/* 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. */
/*----------------------------------------------------------------------*/
/** @typedef cb_textio_input_t */
void
pipehandler(
int fd,
ClientData cdata) /* notused */
{
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, (char *)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, (char *)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, (char *)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, (char *)VisEvent->window);
mw = (entry)?(MagWindow *)HashGetValue(entry):0;
if (!mw)
break;
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, (char *)ExposeEvent->window);
mw = (entry) ? (MagWindow *)HashGetValue(entry) : 0;
if (!mw)
break;
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;
(*GrLockPtr)(mw, FALSE);
(*GrGetBackingStorePtr)(mw, &screenRect);
(*GrUnlockPtr)(mw);
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, (char *)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;
#ifdef VECTOR_FONTS
grFontTextPtr = groglFontText;
#endif
grDefineCursorPtr = groglDefineCursor;
grDrawGridPtr = groglDrawGrid;
grDrawLinePtr = groglDrawLine;
grSetWMandCPtr = groglSetWMandC;
grFillRectPtr = groglFillRect;
grSetStipplePtr = groglSetStipple;
grSetLineStylePtr = groglSetLineStyle;
grSetCharSizePtr = groglSetCharSize;
grFillPolygonPtr = groglFillPolygon;
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*/
/** @typedef cb_textio_input_t */
void
grOGLWStdin(
int fd,
ClientData cdata) /* notused */
{
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, (char *)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, (const char *)(intptr_t)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 == PTR2CD(NULL)) return;
class.res_name = "magic";
class.res_class = "magic";
XSetClassHint( grXdpy, wind, &class);
if (text == NULL)
return;
if ((brack = strchr(text,'[')) && brack != text)
{
brack--;
*brack = 0;
XSetIconName(grXdpy,wind,text);
XStoreName(grXdpy,wind,text);
*brack = ' ';
return;
}
if ((brack = strrchr(text,' '))) text = brack+1;
XSetIconName(grXdpy,wind,text);
XStoreName(grXdpy,wind,text);
}