#ifdef __VMS
#include <GL/vms_x_fix.h>
#endif
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <assert.h>
#include <string.h>
#if !defined(_WIN32)
# ifdef __sgi
# include <bstring.h>
# endif
# if (defined(__FreeBSD__) || defined(SVR4) || defined(CRAY) || defined(AIXV3)) && !defined(FD_SETSIZE)
# include <sys/select.h>
# ifdef luna
# include <sysent.h>
# endif
# endif
# if defined(AIXV4) && !defined(NFDBITS)
# include <sys/select.h>
# endif
#endif
#include <sys/types.h>
#if !defined(_WIN32)
# if defined(__vms) && ( __VMS_VER < 70000000 )
# include <sys/time.h>
# else
# ifndef __vms
# include <sys/time.h>
# endif
# endif
# include <unistd.h>
# include <X11/Xlib.h>
# include <X11/keysym.h>
#else
# ifdef __CYGWIN32__
# include <sys/time.h>
# else
# include <sys/timeb.h>
# endif
# ifdef __hpux
# include <X11/HPkeysym.h>
# endif
#endif
#include "glutint.h"
#if defined(__vms) && ( __VMS_VER < 70000000 )
#include <ssdef.h>
#include <psldef.h>
extern int SYS$CLREF(int efn);
extern int SYS$SETIMR(unsigned int efn, struct timeval6 *timeout, void *ast,
unsigned int request_id, unsigned int flags);
extern int SYS$WFLOR(unsigned int efn, unsigned int mask);
extern int SYS$CANTIM(unsigned int request_id, unsigned int mode);
#endif
static GLUTtimer *freeTimerList = NULL;
GLUTidleCB __glutIdleFunc = NULL;
GLUTtimer *__glutTimerList = NULL;
#ifdef SUPPORT_FORTRAN
GLUTtimer *__glutNewTimer;
#endif
GLUTwindow *__glutWindowWorkList = NULL;
GLUTmenu *__glutMappedMenu;
GLUTmenu *__glutCurrentMenu = NULL;
void (*__glutUpdateInputDeviceMaskFunc) (GLUTwindow *);
#if !defined(_WIN32)
void (*__glutMenuItemEnterOrLeave)(GLUTmenuItem * item, int num, int type) = NULL;
void (*__glutFinishMenu)(Window win, int x, int y);
void (*__glutPaintMenu)(GLUTmenu * menu);
void (*__glutStartMenu)(GLUTmenu * menu, GLUTwindow * window, int x, int y, int x_win, int y_win);
GLUTmenu * (*__glutGetMenuByNum)(int menunum);
GLUTmenuItem * (*__glutGetMenuItem)(GLUTmenu * menu, Window win, int *which);
GLUTmenu * (*__glutGetMenu)(Window win);
#endif
Atom __glutMotifHints = None;
unsigned int __glutModifierMask = (unsigned int) ~0;
int __glutWindowDamaged = 0;
void GLUTAPIENTRY
glutIdleFunc(GLUTidleCB idleFunc)
{
__glutIdleFunc = idleFunc;
}
void GLUTAPIENTRY
glutTimerFunc(unsigned int interval, GLUTtimerCB timerFunc, int value)
{
GLUTtimer *timer, *other;
GLUTtimer **prevptr;
#ifdef OLD_VMS
struct timeval6 now;
#else
struct timeval now;
#endif
if (!timerFunc)
return;
if (freeTimerList) {
timer = freeTimerList;
freeTimerList = timer->next;
} else {
timer = (GLUTtimer *) malloc(sizeof(GLUTtimer));
if (!timer)
__glutFatalError("out of memory.");
}
timer->func = timerFunc;
#if defined(__vms) && ( __VMS_VER < 70000000 )
timer->timeout.val = interval * TICKS_PER_MILLISECOND;
#else
timer->timeout.tv_sec = (int) interval / 1000;
timer->timeout.tv_usec = (int) (interval % 1000) * 1000;
#endif
timer->value = value;
timer->next = NULL;
GETTIMEOFDAY(&now);
ADD_TIME(timer->timeout, timer->timeout, now);
prevptr = &__glutTimerList;
other = *prevptr;
while (other && IS_AFTER(other->timeout, timer->timeout)) {
prevptr = &other->next;
other = *prevptr;
}
timer->next = other;
#ifdef SUPPORT_FORTRAN
__glutNewTimer = timer;
#endif
*prevptr = timer;
}
void
handleTimeouts(void)
{
#ifdef OLD_VMS
struct timeval6 now;
#else
struct timeval now;
#endif
GLUTtimer *timer;
GETTIMEOFDAY(&now);
while (IS_AT_OR_AFTER(__glutTimerList->timeout, now)) {
timer = __glutTimerList;
timer->func(timer->value);
__glutTimerList = timer->next;
timer->next = freeTimerList;
freeTimerList = timer;
if (!__glutTimerList)
break;
}
}
void
__glutPutOnWorkList(GLUTwindow * window, int workMask)
{
if (window->workMask) {
window->workMask |= workMask;
} else {
window->workMask = workMask;
assert(window != __glutWindowWorkList);
window->prevWorkWin = __glutWindowWorkList;
__glutWindowWorkList = window;
}
}
void
__glutPostRedisplay(GLUTwindow * window, int layerMask)
{
int shown = (layerMask & (GLUT_REDISPLAY_WORK | GLUT_REPAIR_WORK)) ?
window->shownState : window->overlay->shownState;
if (window->visState != GLUT_HIDDEN
&& window->visState != GLUT_FULLY_COVERED && shown) {
__glutPutOnWorkList(window, layerMask);
}
}
void GLUTAPIENTRY
glutPostRedisplay(void)
{
__glutPostRedisplay(__glutCurrentWindow, GLUT_REDISPLAY_WORK);
}
void GLUTAPIENTRY
glutPostWindowRedisplay(int win)
{
__glutPostRedisplay(__glutWindowList[win - 1], GLUT_REDISPLAY_WORK);
}
static GLUTeventParser *eventParserList = NULL;
void
__glutRegisterEventParser(GLUTeventParser * parser)
{
parser->next = eventParserList;
eventParserList = parser;
}
static void
markWindowHidden(GLUTwindow * window)
{
if (GLUT_HIDDEN != window->visState) {
GLUTwindow *child;
if (window->windowStatus) {
window->visState = GLUT_HIDDEN;
__glutSetWindow(window);
window->windowStatus(GLUT_HIDDEN);
}
child = window->children;
while (child) {
markWindowHidden(child);
child = child->siblings;
}
}
}
#if !defined(_WIN32)
static void
purgeStaleWindow(Window win)
{
GLUTstale **pEntry = &__glutStaleWindowList;
GLUTstale *entry = __glutStaleWindowList;
while (entry) {
if (entry->win == win) {
*pEntry = entry->next;
free(entry);
return;
} else {
pEntry = &entry->next;
entry = *pEntry;
}
}
}
static int
interruptibleXNextEvent(Display * dpy, XEvent * event)
{
fd_set fds;
int rc;
XFlush(__glutDisplay);
for (;;) {
if (XPending(__glutDisplay)) {
XNextEvent(dpy, event);
return 1;
}
#ifndef VMS
FD_ZERO(&fds);
FD_SET(__glutConnectionFD, &fds);
rc = select(__glutConnectionFD + 1, &fds, NULL, NULL, NULL);
if (rc < 0) {
if (errno == EINTR) {
return 0;
} else {
__glutFatalError("select error.");
}
}
#endif
}
}
#endif
static void
processEventsAndTimeouts(void)
{
do {
#if defined(_WIN32)
MSG event;
if(!GetMessage(&event, NULL, 0, 0))
exit(0);
TranslateMessage(&event);
DispatchMessage(&event);
#else
static int mappedMenuButton;
GLUTeventParser *parser;
XEvent event, ahead;
GLUTwindow *window;
GLUTkeyboardCB keyboard;
GLUTspecialCB special;
int gotEvent, width, height;
gotEvent = interruptibleXNextEvent(__glutDisplay, &event);
if (gotEvent) {
switch (event.type) {
case MappingNotify:
XRefreshKeyboardMapping((XMappingEvent *) & event);
break;
case ConfigureNotify:
window = __glutGetWindow(event.xconfigure.window);
if (window) {
if (window->win != event.xconfigure.window) {
break;
}
width = event.xconfigure.width;
height = event.xconfigure.height;
if (width != window->width || height != window->height) {
if (window->overlay) {
XResizeWindow(__glutDisplay, window->overlay->win, width, height);
}
window->width = width;
window->height = height;
__glutSetWindow(window);
glXWaitX();
window->reshape(width, height);
window->forceReshape = False;
__glutPostRedisplay(window, GLUT_REPAIR_WORK);
}
}
break;
case Expose:
while (XEventsQueued(__glutDisplay, QueuedAfterReading)
> 0) {
XPeekEvent(__glutDisplay, &ahead);
if (ahead.type != Expose ||
ahead.xexpose.window != event.xexpose.window) {
break;
}
XNextEvent(__glutDisplay, &event);
}
if (event.xexpose.count == 0) {
GLUTmenu *menu;
if (__glutMappedMenu &&
(menu = __glutGetMenu(event.xexpose.window))) {
__glutPaintMenu(menu);
} else {
window = __glutGetWindow(event.xexpose.window);
if (window) {
if (window->win == event.xexpose.window) {
__glutPostRedisplay(window, GLUT_REPAIR_WORK);
} else if (window->overlay && window->overlay->win == event.xexpose.window) {
__glutPostRedisplay(window, GLUT_OVERLAY_REPAIR_WORK);
}
}
}
} else {
}
break;
case ButtonPress:
case ButtonRelease:
if (__glutMappedMenu && event.type == ButtonRelease
&& mappedMenuButton == event.xbutton.button) {
__glutFinishMenu(event.xbutton.window, event.xbutton.x, event.xbutton.y);
} else {
window = __glutGetWindow(event.xbutton.window);
if (window) {
GLUTmenu *menu;
int menuNum;
if (event.xbutton.button <= GLUT_MAX_MENUS)
menuNum = window->menu[event.xbutton.button - 1];
else
menuNum = 0;
if ((menuNum > 0) && (menu = __glutGetMenuByNum(menuNum))) {
if (event.type == ButtonPress && !__glutMappedMenu) {
__glutStartMenu(menu, window,
event.xbutton.x_root, event.xbutton.y_root,
event.xbutton.x, event.xbutton.y);
mappedMenuButton = event.xbutton.button;
} else {
}
} else if (window->mouse) {
__glutSetWindow(window);
__glutModifierMask = event.xbutton.state;
window->mouse(event.xbutton.button - 1,
event.type == ButtonRelease ?
GLUT_UP : GLUT_DOWN,
event.xbutton.x, event.xbutton.y);
__glutModifierMask = ~0;
} else {
}
} else {
}
}
break;
case MotionNotify:
if (!__glutMappedMenu) {
window = __glutGetWindow(event.xmotion.window);
if (window) {
if (window->motion && event.xmotion.state &
(Button1Mask | Button2Mask | Button3Mask)) {
__glutSetWindow(window);
window->motion(event.xmotion.x, event.xmotion.y);
}
else if (window->passive &&
((event.xmotion.state &
(Button1Mask | Button2Mask | Button3Mask)) ==
0)) {
__glutSetWindow(window);
window->passive(event.xmotion.x,
event.xmotion.y);
}
}
} else {
}
break;
case KeyPress:
case KeyRelease:
window = __glutGetWindow(event.xkey.window);
if (!window) {
break;
}
if (event.type == KeyPress) {
keyboard = window->keyboard;
} else {
if (window->ignoreKeyRepeat) {
if (XEventsQueued(__glutDisplay, QueuedAfterReading)) {
XPeekEvent(__glutDisplay, &ahead);
if (ahead.type == KeyPress
&& ahead.xkey.window == event.xkey.window
&& ahead.xkey.keycode == event.xkey.keycode
&& ahead.xkey.time == event.xkey.time) {
XNextEvent(__glutDisplay, &event);
break;
}
}
}
keyboard = window->keyboardUp;
}
if (keyboard) {
char tmp[1];
int rc;
rc = XLookupString(&event.xkey, tmp, sizeof(tmp),
NULL, NULL);
if (rc) {
__glutSetWindow(window);
__glutModifierMask = event.xkey.state;
keyboard(tmp[0],
event.xkey.x, event.xkey.y);
__glutModifierMask = ~0;
break;
}
}
if (event.type == KeyPress) {
special = window->special;
} else {
special = window->specialUp;
}
if (special) {
KeySym ks;
int key;
#ifndef XK_KP_Home
#define XK_KP_Home 0xFF95
#endif
#ifndef XK_KP_Left
#define XK_KP_Left 0xFF96
#endif
#ifndef XK_KP_Up
#define XK_KP_Up 0xFF97
#endif
#ifndef XK_KP_Right
#define XK_KP_Right 0xFF98
#endif
#ifndef XK_KP_Down
#define XK_KP_Down 0xFF99
#endif
#ifndef XK_KP_Prior
#define XK_KP_Prior 0xFF9A
#endif
#ifndef XK_KP_Next
#define XK_KP_Next 0xFF9B
#endif
#ifndef XK_KP_End
#define XK_KP_End 0xFF9C
#endif
#ifndef XK_KP_Insert
#define XK_KP_Insert 0xFF9E
#endif
#ifndef XK_KP_Delete
#define XK_KP_Delete 0xFF9F
#endif
ks = XLookupKeysym((XKeyEvent *) & event, 0);
switch (ks) {
case XK_F1: key = GLUT_KEY_F1; break;
case XK_F2: key = GLUT_KEY_F2; break;
case XK_F3: key = GLUT_KEY_F3; break;
case XK_F4: key = GLUT_KEY_F4; break;
case XK_F5: key = GLUT_KEY_F5; break;
case XK_F6: key = GLUT_KEY_F6; break;
case XK_F7: key = GLUT_KEY_F7; break;
case XK_F8: key = GLUT_KEY_F8; break;
case XK_F9: key = GLUT_KEY_F9; break;
case XK_F10: key = GLUT_KEY_F10; break;
case XK_F11: key = GLUT_KEY_F11; break;
case XK_F12: key = GLUT_KEY_F12; break;
case XK_KP_Left:
case XK_Left: key = GLUT_KEY_LEFT; break;
case XK_KP_Up:
case XK_Up: key = GLUT_KEY_UP; break;
case XK_KP_Right:
case XK_Right: key = GLUT_KEY_RIGHT; break;
case XK_KP_Down:
case XK_Down: key = GLUT_KEY_DOWN; break;
case XK_KP_Prior:
case XK_Prior:
key = GLUT_KEY_PAGE_UP;
break;
case XK_KP_Next:
case XK_Next:
key = GLUT_KEY_PAGE_DOWN;
break;
case XK_KP_Home:
case XK_Home:
key = GLUT_KEY_HOME;
break;
#ifdef __hpux
case XK_Select:
#endif
case XK_KP_End:
case XK_End:
key = GLUT_KEY_END;
break;
#ifdef __hpux
case XK_InsertChar:
#endif
case XK_KP_Insert:
case XK_Insert:
key = GLUT_KEY_INSERT;
break;
#ifdef __hpux
case XK_DeleteChar:
#endif
case XK_KP_Delete:
__glutSetWindow(window);
keyboard(127,
event.xkey.x, event.xkey.y);
goto skip;
default:
goto skip;
}
__glutSetWindow(window);
__glutModifierMask = event.xkey.state;
special(key, event.xkey.x, event.xkey.y);
__glutModifierMask = ~0;
skip:;
}
break;
case EnterNotify:
case LeaveNotify:
if (event.xcrossing.mode != NotifyNormal ||
event.xcrossing.detail == NotifyNonlinearVirtual ||
event.xcrossing.detail == NotifyVirtual) {
break;
}
if (__glutMappedMenu) {
GLUTmenuItem *item;
int num;
item = __glutGetMenuItem(__glutMappedMenu,
event.xcrossing.window, &num);
if (item) {
__glutMenuItemEnterOrLeave(item, num, event.type);
break;
}
}
window = __glutGetWindow(event.xcrossing.window);
if (window) {
if (window->entry) {
if (event.type == EnterNotify) {
if (window->entryState != EnterNotify) {
int num = window->num;
Window xid = window->win;
window->entryState = EnterNotify;
__glutSetWindow(window);
window->entry(GLUT_ENTERED);
if (__glutMappedMenu) {
} else {
window = __glutWindowList[num];
if (window && window->passive && window->win == xid) {
__glutSetWindow(window);
window->passive(event.xcrossing.x, event.xcrossing.y);
}
}
}
} else {
if (window->entryState != LeaveNotify) {
if (XEventsQueued(__glutDisplay, QueuedAfterReading)) {
XPeekEvent(__glutDisplay, &ahead);
if (ahead.type == EnterNotify &&
__glutGetWindow(ahead.xcrossing.window) == window) {
XNextEvent(__glutDisplay, &event);
break;
}
}
window->entryState = LeaveNotify;
__glutSetWindow(window);
window->entry(GLUT_LEFT);
}
}
} else if (window->passive) {
__glutSetWindow(window);
window->passive(event.xcrossing.x, event.xcrossing.y);
}
}
break;
case UnmapNotify:
window = __glutGetWindow(event.xunmap.window);
if (window) {
if (window->win != event.xconfigure.window) {
break;
}
markWindowHidden(window);
}
break;
case VisibilityNotify:
window = __glutGetWindow(event.xvisibility.window);
if (window) {
int visState = event.xvisibility.state + 1;
if (visState != window->visState) {
if (window->windowStatus) {
window->visState = visState;
__glutSetWindow(window);
window->windowStatus(visState);
}
}
}
break;
case ClientMessage:
if (event.xclient.data.l[0] == __glutWMDeleteWindow)
exit(0);
break;
case DestroyNotify:
purgeStaleWindow(event.xdestroywindow.window);
break;
case CirculateNotify:
case CreateNotify:
case GravityNotify:
case ReparentNotify:
break;
default:
parser = eventParserList;
while (parser) {
if (parser->func(&event))
break;
parser = parser->next;
}
break;
}
}
#endif
if (__glutTimerList) {
handleTimeouts();
}
}
while (XPending(__glutDisplay));
}
static void
waitForSomething(void)
{
#if defined(__vms) && ( __VMS_VER < 70000000 )
static struct timeval6 zerotime =
{0};
unsigned int timer_efn;
#define timer_id 'glut'
unsigned int wait_mask;
#else
static struct timeval zerotime =
{0, 0};
#if !defined(_WIN32)
fd_set fds;
#endif
#endif
#ifdef OLD_VMS
struct timeval6 now, timeout, waittime;
#else
struct timeval now, timeout, waittime;
#endif
#if !defined(_WIN32)
int rc;
#endif
XFlush(__glutDisplay);
if (XPending(__glutDisplay)) {
goto immediatelyHandleXinput;
}
#if defined(__vms) && ( __VMS_VER < 70000000 )
timeout = __glutTimerList->timeout;
GETTIMEOFDAY(&now);
wait_mask = 1 << (__glutConnectionFD & 31);
if (IS_AFTER(now, timeout)) {
timer_efn = __glutConnectionFD - 1;
if ((timer_efn / 32) != (__glutConnectionFD / 32)) {
timer_efn = __glutConnectionFD + 1;
}
rc = SYS$CLREF(timer_efn);
rc = SYS$SETIMR(timer_efn, &timeout, NULL, timer_id, 0);
wait_mask |= 1 << (timer_efn & 31);
} else {
timer_efn = 0;
}
rc = SYS$WFLOR(__glutConnectionFD, wait_mask);
if (timer_efn != 0 && SYS$CLREF(timer_efn) == SS$_WASCLR) {
rc = SYS$CANTIM(timer_id, PSL$C_USER);
}
#else
#if !defined(_WIN32)
FD_ZERO(&fds);
FD_SET(__glutConnectionFD, &fds);
#endif
timeout = __glutTimerList->timeout;
GETTIMEOFDAY(&now);
if (IS_AFTER(now, timeout)) {
TIMEDELTA(waittime, timeout, now);
} else {
waittime = zerotime;
}
#if !defined(_WIN32)
rc = select(__glutConnectionFD + 1, &fds,
NULL, NULL, &waittime);
if (rc < 0 && errno != EINTR)
__glutFatalError("select error.");
#else
MsgWaitForMultipleObjects(0, NULL, FALSE,
waittime.tv_sec*1000 + waittime.tv_usec/1000, QS_ALLINPUT);
#endif
#endif
if (XPending(__glutDisplay)) {
immediatelyHandleXinput:
processEventsAndTimeouts();
} else {
if (__glutTimerList)
handleTimeouts();
}
}
static void
idleWait(void)
{
if (XPending(__glutDisplay)) {
processEventsAndTimeouts();
} else {
if (__glutTimerList) {
handleTimeouts();
}
}
if (__glutIdleFunc) {
__glutIdleFunc();
}
}
static GLUTwindow **beforeEnd;
static GLUTwindow *
processWindowWorkList(GLUTwindow * window)
{
int workMask;
if (window->prevWorkWin) {
window->prevWorkWin = processWindowWorkList(window->prevWorkWin);
} else {
beforeEnd = &window->prevWorkWin;
}
workMask = window->workMask;
assert((workMask & GLUT_DUMMY_WORK) == 0);
window->workMask = GLUT_DUMMY_WORK;
if (workMask & (GLUT_EVENT_MASK_WORK | GLUT_DEVICE_MASK_WORK |
GLUT_CONFIGURE_WORK | GLUT_COLORMAP_WORK | GLUT_MAP_WORK)) {
#if !defined(_WIN32)
if (workMask & GLUT_EVENT_MASK_WORK) {
long eventMask;
if (window->children) {
GLUTwindow *child = window->children;
unsigned long attribMask = CWDontPropagate;
XSetWindowAttributes wa;
wa.do_not_propagate_mask = window->eventMask & GLUT_DONT_PROPAGATE_FILTER_MASK;
if (window->eventMask & GLUT_HACK_STOP_PROPAGATE_MASK) {
wa.event_mask = child->eventMask | (window->eventMask & GLUT_HACK_STOP_PROPAGATE_MASK);
attribMask |= CWEventMask;
}
do {
XChangeWindowAttributes(__glutDisplay, child->win,
attribMask, &wa);
child = child->siblings;
} while (child);
}
eventMask = window->eventMask;
if (window->parent && window->parent->eventMask & GLUT_HACK_STOP_PROPAGATE_MASK)
eventMask |= (window->parent->eventMask & GLUT_HACK_STOP_PROPAGATE_MASK);
XSelectInput(__glutDisplay, window->win, eventMask);
if (window->overlay)
XSelectInput(__glutDisplay, window->overlay->win,
window->eventMask & GLUT_OVERLAY_EVENT_FILTER_MASK);
}
#endif
if (workMask & GLUT_DEVICE_MASK_WORK) {
__glutUpdateInputDeviceMaskFunc(window);
}
if (workMask & GLUT_CONFIGURE_WORK) {
#if defined(_WIN32)
RECT changes;
POINT point;
UINT flags = SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOOWNERZORDER
| SWP_NOSENDCHANGING | SWP_NOSIZE | SWP_NOZORDER;
GetClientRect(window->win, &changes);
if (!window->parent) {
point.x = 0;
point.y = 0;
ClientToScreen(window->win, &point);
changes.left = point.x;
changes.top = point.y;
}
if (window->desiredConfMask & (CWX | CWY)) {
changes.left = window->desiredX;
changes.top = window->desiredY;
flags &= ~SWP_NOMOVE;
}
if (window->desiredConfMask & (CWWidth | CWHeight)) {
changes.right = changes.left + window->desiredWidth;
changes.bottom = changes.top + window->desiredHeight;
flags &= ~SWP_NOSIZE;
}
if (window->desiredConfMask & CWStackMode) {
flags &= ~SWP_NOZORDER;
}
if (!window->parent && window != __glutGameModeWindow) {
AdjustWindowRect(&changes,
WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
FALSE);
}
SetWindowPos(window->win,
window->desiredStack == Above ? HWND_TOP : HWND_NOTOPMOST,
changes.left, changes.top,
changes.right - changes.left, changes.bottom - changes.top,
flags);
window->desiredConfMask = 0;
if (workMask & GLUT_FULL_SCREEN_WORK) {
window->desiredConfMask |= CWX | CWY;
window->desiredX = point.x;
window->desiredY = point.y;
}
#else
XWindowChanges changes;
changes.x = window->desiredX;
changes.y = window->desiredY;
if (window->desiredConfMask & (CWWidth | CWHeight)) {
changes.width = window->desiredWidth;
changes.height = window->desiredHeight;
if (window->overlay)
XResizeWindow(__glutDisplay, window->overlay->win,
window->desiredWidth, window->desiredHeight);
if (__glutMotifHints != None) {
if (workMask & GLUT_FULL_SCREEN_WORK) {
MotifWmHints hints;
hints.flags = MWM_HINTS_DECORATIONS;
hints.decorations = 0;
XChangeProperty(__glutDisplay, window->win,
__glutMotifHints, __glutMotifHints, 32,
PropModeReplace, (unsigned char *) &hints, 4);
if (workMask & GLUT_MAP_WORK) {
XSizeHints hints;
hints.flags = USPosition | USSize;
hints.x = 0;
hints.y = 0;
hints.width = window->desiredWidth;
hints.height = window->desiredHeight;
XSetWMNormalHints(__glutDisplay, window->win, &hints);
}
} else {
XDeleteProperty(__glutDisplay, window->win, __glutMotifHints);
}
}
}
if (window->desiredConfMask & CWStackMode) {
changes.stack_mode = window->desiredStack;
if (window->parent && window->parent->overlay
&& window->desiredStack == Below) {
changes.stack_mode = Above;
changes.sibling = window->parent->overlay->win;
window->desiredConfMask |= CWSibling;
}
}
XConfigureWindow(__glutDisplay, window->win,
window->desiredConfMask, &changes);
window->desiredConfMask = 0;
#endif
}
#if !defined(_WIN32)
if (workMask & GLUT_COLORMAP_WORK) {
__glutEstablishColormapsProperty(window);
}
#endif
if (workMask & GLUT_MAP_WORK) {
switch (window->desiredMapState) {
case WithdrawnState:
if (window->parent) {
XUnmapWindow(__glutDisplay, window->win);
} else {
XWithdrawWindow(__glutDisplay, window->win,
__glutScreen);
}
window->shownState = 0;
break;
case NormalState:
XMapWindow(__glutDisplay, window->win);
window->shownState = 1;
break;
#ifdef _WIN32
case GameModeState:
ShowWindow(window->win, SW_SHOW);
window->shownState = 1;
break;
#endif
case IconicState:
XIconifyWindow(__glutDisplay, window->win, __glutScreen);
window->shownState = 0;
break;
}
}
}
if (workMask & (GLUT_REDISPLAY_WORK | GLUT_OVERLAY_REDISPLAY_WORK | GLUT_REPAIR_WORK | GLUT_OVERLAY_REPAIR_WORK)) {
if (window->forceReshape) {
__glutSetWindow(window);
window->reshape(window->width, window->height);
window->forceReshape = False;
workMask |= GLUT_REDISPLAY_WORK;
}
if (window->overlay && window->overlay->display) {
int num = window->num;
Window xid = window->overlay ? window->overlay->win : None;
if (workMask & (GLUT_REDISPLAY_WORK | GLUT_REPAIR_WORK)) {
if (__glutMesaSwapHackSupport) {
if (window->usedSwapBuffers) {
if ((workMask & (GLUT_REPAIR_WORK | GLUT_REDISPLAY_WORK)) == GLUT_REPAIR_WORK) {
SWAP_BUFFERS_WINDOW(window);
goto skippedDisplayCallback1;
}
}
}
#ifdef _WIN32
window->renderDc = window->hdc;
#endif
window->renderWin = window->win;
window->renderCtx = window->ctx;
__glutWindowDamaged = (workMask & GLUT_REPAIR_WORK);
__glutSetWindow(window);
window->usedSwapBuffers = 0;
window->display();
__glutWindowDamaged = 0;
skippedDisplayCallback1:;
}
if (workMask & (GLUT_OVERLAY_REDISPLAY_WORK | GLUT_OVERLAY_REPAIR_WORK)) {
window = __glutWindowList[num];
if (window && window->overlay &&
window->overlay->win == xid && window->overlay->display) {
#ifdef _WIN32
window->renderDc = window->overlay->hdc;
#endif
window->renderWin = window->overlay->win;
window->renderCtx = window->overlay->ctx;
__glutWindowDamaged = (workMask & GLUT_OVERLAY_REPAIR_WORK);
__glutSetWindow(window);
window->overlay->display();
__glutWindowDamaged = 0;
} else {
}
}
} else {
if (__glutMesaSwapHackSupport) {
if (!window->overlay && window->usedSwapBuffers) {
if ((workMask & (GLUT_REPAIR_WORK | GLUT_REDISPLAY_WORK)) == GLUT_REPAIR_WORK) {
SWAP_BUFFERS_WINDOW(window);
goto skippedDisplayCallback2;
}
}
}
__glutWindowDamaged = (workMask & (GLUT_OVERLAY_REPAIR_WORK | GLUT_REPAIR_WORK));
__glutSetWindow(window);
window->usedSwapBuffers = 0;
window->display();
__glutWindowDamaged = 0;
skippedDisplayCallback2:;
}
}
workMask |= window->workMask;
if (workMask & GLUT_FINISH_WORK) {
__glutSetWindow(window);
glFinish();
}
if (workMask & GLUT_DEBUG_WORK) {
__glutSetWindow(window);
glutReportErrors();
}
window->workMask &= ~(GLUT_DUMMY_WORK | GLUT_FINISH_WORK | GLUT_DEBUG_WORK);
if (window->workMask) {
return window;
} else {
return window->prevWorkWin;
}
}
#ifndef _WIN32
static
#endif
void
__glutProcessWindowWorkLists(void)
{
if (__glutWindowWorkList) {
GLUTwindow *remainder, *work;
work = __glutWindowWorkList;
__glutWindowWorkList = NULL;
if (work) {
remainder = processWindowWorkList(work);
if (remainder) {
*beforeEnd = __glutWindowWorkList;
__glutWindowWorkList = remainder;
}
}
}
}
void GLUTAPIENTRY
glutMainLoop(void)
{
#if !defined(_WIN32)
if (!__glutDisplay)
__glutFatalUsage("main loop entered with out proper initialization.");
#endif
if (!__glutWindowListSize)
__glutFatalUsage(
"main loop entered with no windows created.");
for (;;) {
__glutProcessWindowWorkLists();
if (__glutIdleFunc || __glutWindowWorkList) {
idleWait();
} else {
if (__glutTimerList) {
waitForSomething();
} else {
processEventsAndTimeouts();
}
}
}
}