00001
00002
00003
00004
00005
00006
00007
00008 #include <stdlib.h>
00009 #include <stdio.h>
00010 #include <errno.h>
00011 #include <unistd.h>
00012 #include <assert.h>
00013 #ifdef __sgi
00014 #include <bstring.h>
00015 #endif
00016 #ifdef AIXV3
00017 #include <sys/select.h>
00018 #endif
00019 #include <sys/types.h>
00020 #ifndef __vms
00021 #include <sys/time.h>
00022 #endif
00023 #include <X11/Xlib.h>
00024 #include <X11/keysym.h>
00025 #ifdef __hpux
00026
00027
00028
00029
00030 #include <X11/HPkeysym.h>
00031 #endif
00032 #ifdef __vms
00033 #include <ssdef.h>
00034 #include <psldef.h>
00035 extern int SYS$CLREF(int efn);
00036 extern int SYS$SETIMR(unsigned int efn, struct timeval *timeout, void *ast,
00037 unsigned int request_id, unsigned int flags);
00038 extern int SYS$WFLOR(unsigned int efn, unsigned int mask);
00039 extern int SYS$CANTIM(unsigned int request_id, unsigned int mode);
00040 #endif
00041 #include <GL/glut.h>
00042 #include "glutint.h"
00043
00044 static GLUTtimer *freeTimerList = NULL;
00045 static int mappedMenuButton;
00046
00047 GLUTidleCB __glutIdleFunc = NULL;
00048 GLUTtimer *__glutTimerList = NULL;
00049 #ifdef SUPPORT_FORTRAN
00050 GLUTtimer *__glutNewTimer;
00051 #endif
00052 GLUTwindow *__glutWindowWorkList = NULL;
00053 void (*__glutUpdateInputDeviceMaskFunc) (GLUTwindow *);
00054 Atom __glutMotifHints = None;
00055 unsigned int __glutModifierMask = ~0;
00056
00057 int __glutWindowDamaged = 0;
00058
00059 void
00060 glutIdleFunc(GLUTidleCB idleFunc)
00061 {
00062 __glutIdleFunc = idleFunc;
00063 }
00064
00065 void
00066 glutTimerFunc(unsigned int interval, GLUTtimerCB timerFunc, int value)
00067 {
00068 GLUTtimer *timer, *other;
00069 GLUTtimer **prevptr;
00070 struct timeval now;
00071
00072 if (!timerFunc)
00073 return;
00074
00075 if (freeTimerList) {
00076 timer = freeTimerList;
00077 freeTimerList = timer->next;
00078 } else {
00079 timer = (GLUTtimer *) malloc(sizeof(GLUTtimer));
00080 if (!timer)
00081 __glutFatalError("out of memory.");
00082 }
00083
00084 timer->func = timerFunc;
00085 #ifdef __vms
00086
00087 timer->timeout.val = interval * TICKS_PER_MILLISECOND;
00088 #else
00089 timer->timeout.tv_sec = (int) interval / 1000;
00090 timer->timeout.tv_usec = (int) (interval % 1000) * 1000;
00091 #endif
00092 timer->value = value;
00093 timer->next = NULL;
00094 GETTIMEOFDAY(&now);
00095 ADD_TIME(timer->timeout, timer->timeout, now);
00096 prevptr = &__glutTimerList;
00097 other = *prevptr;
00098 while (other && IS_AFTER(other->timeout, timer->timeout)) {
00099 prevptr = &other->next;
00100 other = *prevptr;
00101 }
00102 timer->next = other;
00103 #ifdef SUPPORT_FORTRAN
00104 __glutNewTimer = timer;
00105 #endif
00106 *prevptr = timer;
00107 }
00108
00109 static void
00110 handleTimeouts(void)
00111 {
00112 struct timeval now;
00113 GLUTtimer *timer;
00114
00115 if (__glutTimerList) {
00116 GETTIMEOFDAY(&now);
00117 while (IS_AT_OR_AFTER(__glutTimerList->timeout, now)) {
00118 timer = __glutTimerList;
00119 timer->func(timer->value);
00120 __glutTimerList = timer->next;
00121 timer->next = freeTimerList;
00122 freeTimerList = timer;
00123 if (!__glutTimerList)
00124 break;
00125 }
00126 }
00127 }
00128
00129 void
00130 __glutPutOnWorkList(GLUTwindow * window, int workMask)
00131 {
00132 if (window->workMask) {
00133
00134 window->workMask |= workMask;
00135 } else {
00136
00137 window->workMask = workMask;
00138 window->prevWorkWin = __glutWindowWorkList;
00139 __glutWindowWorkList = window;
00140 }
00141 }
00142
00143 void
00144 __glutPostRedisplay(GLUTwindow * window, int layerMask)
00145 {
00146 int shown = (layerMask == GLUT_REDISPLAY_WORK) ? window->shownState : window->overlay->shownState;
00147
00148
00149
00150
00151 if (window->visState != 0 && shown)
00152 __glutPutOnWorkList(window, layerMask);
00153 }
00154
00155 void
00156 glutPostRedisplay(void)
00157 {
00158 __glutPostRedisplay(__glutCurrentWindow, GLUT_REDISPLAY_WORK);
00159 }
00160
00161 static GLUTeventParser *eventParserList = NULL;
00162
00163
00164
00165
00166
00167
00168
00169 void
00170 __glutRegisterEventParser(GLUTeventParser * parser)
00171 {
00172 parser->next = eventParserList;
00173 eventParserList = parser;
00174 }
00175
00176 static void
00177 updateWindowVisibility(GLUTwindow * window, int visState)
00178 {
00179 if (window->shownState && visState != window->visState) {
00180 if (window->visibility) {
00181 window->visState = visState;
00182 __glutSetWindow(window);
00183 window->visibility(visState ?
00184 GLUT_VISIBLE : GLUT_NOT_VISIBLE);
00185 }
00186
00187
00188 if (!visState) {
00189 GLUTwindow *child = window->children;
00190
00191 while (child) {
00192 updateWindowVisibility(child, visState);
00193 child = child->siblings;
00194 }
00195 }
00196 }
00197 }
00198
00199 static void
00200 purgeStaleWindow(Window win)
00201 {
00202 GLUTstale **pEntry = &__glutStaleWindowList;
00203 GLUTstale *entry = __glutStaleWindowList;
00204
00205
00206
00207 while (entry) {
00208 if (entry->win == win) {
00209
00210 *pEntry = entry->next;
00211 free(entry);
00212 return;
00213 } else {
00214 pEntry = &entry->next;
00215 entry = *pEntry;
00216 }
00217 }
00218 }
00219
00220 static void
00221 processEvents(void)
00222 {
00223 XEvent event, ahead;
00224 GLUTwindow *window;
00225 int width, height;
00226 GLUTeventParser *parser;
00227
00228 do {
00229 XNextEvent(__glutDisplay, &event);
00230 switch (event.type) {
00231 case MappingNotify:
00232 XRefreshKeyboardMapping((XMappingEvent *) & event);
00233 break;
00234 case ConfigureNotify:
00235 window = __glutGetWindow(event.xconfigure.window);
00236 if (window) {
00237 if (window->win != event.xconfigure.window) {
00238
00239
00240
00241 break;
00242 }
00243 width = event.xconfigure.width;
00244 height = event.xconfigure.height;
00245 if (width != window->width || height != window->height) {
00246 if (window->overlay) {
00247 XResizeWindow(__glutDisplay, window->overlay->win, width, height);
00248 }
00249 window->width = width;
00250 window->height = height;
00251 __glutSetWindow(window);
00252
00253
00254 glXWaitX();
00255 window->reshape(width, height);
00256 window->forceReshape = False;
00257 }
00258 }
00259 break;
00260 case Expose:
00261
00262 while (XEventsQueued(__glutDisplay, QueuedAfterReading)
00263 > 0) {
00264 XPeekEvent(__glutDisplay, &ahead);
00265 if (ahead.type != Expose ||
00266 ahead.xexpose.window != event.xexpose.window)
00267 break;
00268 XNextEvent(__glutDisplay, &event);
00269 }
00270 if (event.xexpose.count == 0) {
00271 GLUTmenu *menu;
00272
00273 if (__glutMappedMenu &&
00274 (menu = __glutGetMenu(event.xexpose.window))) {
00275 __glutPaintMenu(menu);
00276 } else {
00277 window = __glutGetWindow(event.xexpose.window);
00278 if (window) {
00279 if (window->win == event.xexpose.window) {
00280 window->damaged = 1;
00281 __glutPostRedisplay(window, GLUT_REDISPLAY_WORK);
00282 } else if (window->overlay && window->overlay->win == event.xexpose.window) {
00283 __glutPostRedisplay(window, GLUT_OVERLAY_REDISPLAY_WORK);
00284 window->overlay->damaged = 1;
00285 }
00286 }
00287 }
00288 } else {
00289
00290 }
00291 break;
00292 case ButtonPress:
00293 case ButtonRelease:
00294 if (__glutMappedMenu && event.type == ButtonRelease
00295 && mappedMenuButton == event.xbutton.button) {
00296
00297
00298 __glutFinishMenu(event.xbutton.window, event.xbutton.x, event.xbutton.y);
00299 } else {
00300 window = __glutGetWindow(event.xbutton.window);
00301 if (window) {
00302 GLUTmenu *menu;
00303
00304 menu = __glutGetMenuByNum(
00305 window->menu[event.xbutton.button - 1]);
00306 if (menu) {
00307 if (event.type == ButtonPress && !__glutMappedMenu) {
00308 __glutStartMenu(menu, window,
00309 event.xbutton.x_root, event.xbutton.y_root,
00310 event.xbutton.x, event.xbutton.y);
00311 mappedMenuButton = event.xbutton.button;
00312 } else {
00313
00314
00315
00316
00317 }
00318 } else if (window->mouse) {
00319 __glutSetWindow(window);
00320 __glutModifierMask = event.xbutton.state;
00321 window->mouse(event.xbutton.button - 1,
00322 event.type == ButtonRelease ?
00323 GLUT_UP : GLUT_DOWN,
00324 event.xbutton.x, event.xbutton.y);
00325 __glutModifierMask = ~0;
00326 } else {
00327
00328 }
00329 } else {
00330
00331
00332 }
00333 }
00334 break;
00335 case MotionNotify:
00336 if (!__glutMappedMenu) {
00337 window = __glutGetWindow(event.xmotion.window);
00338 if (window) {
00339
00340
00341 if (window->motion && event.xmotion.state &
00342 (Button1Mask | Button2Mask | Button3Mask)) {
00343 __glutSetWindow(window);
00344 window->motion(event.xmotion.x, event.xmotion.y);
00345 }
00346
00347
00348
00349 else if (window->passive &&
00350 ((event.xmotion.state &
00351 (Button1Mask | Button2Mask | Button3Mask)) ==
00352 0)) {
00353 __glutSetWindow(window);
00354 window->passive(event.xmotion.x,
00355 event.xmotion.y);
00356 }
00357 }
00358 } else {
00359
00360
00361 }
00362 break;
00363 case KeyPress:
00364 window = __glutGetWindow(event.xkey.window);
00365 if (!window) {
00366 break;
00367 }
00368 if (window->keyboard) {
00369 char tmp[1];
00370 int rc;
00371
00372 rc = XLookupString(&event.xkey, tmp, sizeof(tmp),
00373 NULL, NULL);
00374 if (rc) {
00375 __glutSetWindow(window);
00376 __glutModifierMask = event.xkey.state;
00377 window->keyboard(tmp[0],
00378 event.xkey.x, event.xkey.y);
00379 __glutModifierMask = ~0;
00380 break;
00381 }
00382 }
00383 if (window->special) {
00384 KeySym ks;
00385 int key;
00386
00387 ks = XLookupKeysym((XKeyEvent *) & event, 0);
00388
00389
00390 switch (ks) {
00391
00392 case XK_F1: key = GLUT_KEY_F1; break;
00393 case XK_F2: key = GLUT_KEY_F2; break;
00394 case XK_F3: key = GLUT_KEY_F3; break;
00395 case XK_F4: key = GLUT_KEY_F4; break;
00396 case XK_F5: key = GLUT_KEY_F5; break;
00397 case XK_F6: key = GLUT_KEY_F6; break;
00398 case XK_F7: key = GLUT_KEY_F7; break;
00399 case XK_F8: key = GLUT_KEY_F8; break;
00400 case XK_F9: key = GLUT_KEY_F9; break;
00401 case XK_F10: key = GLUT_KEY_F10; break;
00402 case XK_F11: key = GLUT_KEY_F11; break;
00403 case XK_F12: key = GLUT_KEY_F12; break;
00404
00405 case XK_Left: key = GLUT_KEY_LEFT; break;
00406 case XK_Up: key = GLUT_KEY_UP; break;
00407 case XK_Right: key = GLUT_KEY_RIGHT; break;
00408 case XK_Down: key = GLUT_KEY_DOWN; break;
00409 case XK_Prior:
00410
00411 key = GLUT_KEY_PAGE_UP;
00412 break;
00413 case XK_Next:
00414
00415 key = GLUT_KEY_PAGE_DOWN;
00416 break;
00417 case XK_Home:
00418 key = GLUT_KEY_HOME;
00419 break;
00420 case XK_End:
00421 #ifdef __hpux
00422 case XK_Select:
00423 #endif
00424 key = GLUT_KEY_END;
00425 break;
00426 case XK_Insert:
00427 #ifdef __hpux
00428 case XK_InsertChar:
00429 #endif
00430 key = GLUT_KEY_INSERT;
00431 break;
00432 #ifdef __hpux
00433 case XK_DeleteChar:
00434
00435 __glutSetWindow(window);
00436 window->keyboard(127,
00437 event.xkey.x, event.xkey.y);
00438 goto skip;
00439 #endif
00440 default:
00441 goto skip;
00442 }
00443 __glutSetWindow(window);
00444 __glutModifierMask = event.xkey.state;
00445 window->special(key, event.xkey.x, event.xkey.y);
00446 __glutModifierMask = ~0;
00447 skip:;
00448 }
00449 break;
00450 case EnterNotify:
00451 case LeaveNotify:
00452 if (event.xcrossing.mode != NotifyNormal ||
00453 event.xcrossing.detail == NotifyNonlinearVirtual ||
00454 event.xcrossing.detail == NotifyVirtual) {
00455
00456
00457
00458
00459
00460
00461
00462
00463 break;
00464 }
00465 if (__glutMappedMenu) {
00466 GLUTmenuItem *item;
00467 int num;
00468
00469 item = __glutGetMenuItem(__glutMappedMenu,
00470 event.xcrossing.window, &num);
00471 if (item) {
00472 __glutMenuItemEnterOrLeave(item, num, event.type);
00473 break;
00474 }
00475 }
00476 window = __glutGetWindow(event.xcrossing.window);
00477 if (window) {
00478 if (window->entry) {
00479 if (event.type == EnterNotify) {
00480
00481
00482
00483
00484
00485
00486
00487 if (window->entryState != EnterNotify) {
00488 int num = window->num;
00489 Window xid = window->win;
00490
00491 window->entryState = EnterNotify;
00492 __glutSetWindow(window);
00493 window->entry(GLUT_ENTERED);
00494
00495 if (__glutMappedMenu) {
00496
00497
00498
00499
00500 } else {
00501
00502
00503
00504
00505
00506
00507
00508
00509 window = __glutWindowList[num];
00510 if (window && window->passive && window->win == xid) {
00511 __glutSetWindow(window);
00512 window->passive(event.xcrossing.x, event.xcrossing.y);
00513 }
00514 }
00515 }
00516 } else {
00517 if (window->entryState != LeaveNotify) {
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530 if (XEventsQueued(__glutDisplay, QueuedAfterReading)) {
00531 XPeekEvent(__glutDisplay, &ahead);
00532 if (ahead.type == EnterNotify &&
00533 __glutGetWindow(ahead.xcrossing.window) == window) {
00534 XNextEvent(__glutDisplay, &event);
00535 break;
00536 }
00537 }
00538 window->entryState = LeaveNotify;
00539 __glutSetWindow(window);
00540 window->entry(GLUT_LEFT);
00541 }
00542 }
00543 } else if (window->passive) {
00544 __glutSetWindow(window);
00545 window->passive(event.xcrossing.x, event.xcrossing.y);
00546 }
00547 }
00548 break;
00549 case UnmapNotify:
00550
00551
00552
00553
00554
00555 window = __glutGetWindow(event.xunmap.window);
00556 if (window) {
00557 if (window->win != event.xconfigure.window) {
00558
00559
00560
00561 break;
00562 }
00563 updateWindowVisibility(window, 0);
00564 }
00565 break;
00566 case VisibilityNotify:
00567 window = __glutGetWindow(event.xvisibility.window);
00568 if (window) {
00569 int visState = (event.xvisibility.state != VisibilityFullyObscured);
00570
00571 if (visState != window->visState) {
00572 if (window->visibility) {
00573 window->visState = visState;
00574 __glutSetWindow(window);
00575 window->visibility(visState ? GLUT_VISIBLE : GLUT_NOT_VISIBLE);
00576 }
00577 }
00578 }
00579 break;
00580 case ClientMessage:
00581 if (event.xclient.data.l[0] == __glutWMDeleteWindow)
00582 exit(0);
00583 break;
00584 case DestroyNotify:
00585 purgeStaleWindow(event.xdestroywindow.window);
00586 break;
00587 case CirculateNotify:
00588 case CreateNotify:
00589 case GravityNotify:
00590 case ReparentNotify:
00591
00592
00593 break;
00594 default:
00595
00596
00597
00598
00599
00600 parser = eventParserList;
00601 while (parser) {
00602 if (parser->func(&event))
00603 break;
00604 parser = parser->next;
00605 }
00606 break;
00607 }
00608 }
00609 while (XPending(__glutDisplay));
00610 }
00611
00612 static void
00613 waitForSomething(void)
00614 {
00615 #ifdef __vms
00616 static struct timeval zerotime = {0};
00617 unsigned int timer_efn;
00618 #define timer_id 'glut'
00619 unsigned int wait_mask;
00620 #else
00621 static struct timeval zerotime = {0, 0};
00622 fd_set fds;
00623 #endif
00624 struct timeval now, timeout, waittime;
00625 int rc;
00626
00627
00628
00629 XFlush(__glutDisplay);
00630 if (XPending(__glutDisplay)) {
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640 goto immediatelyHandleXinput;
00641 }
00642 #ifdef __vms
00643 timeout = __glutTimerList->timeout;
00644 GETTIMEOFDAY(&now);
00645 wait_mask = 1 << (__glutConnectionFD & 31);
00646 if (IS_AFTER(now, timeout)) {
00647
00648
00649
00650
00651 timer_efn = __glutConnectionFD - 1;
00652 if ((timer_efn / 32) != (__glutConnectionFD / 32) ) {
00653 timer_efn = __glutConnectionFD + 1;
00654 }
00655 rc = SYS$CLREF (timer_efn);
00656 rc = SYS$SETIMR (timer_efn, &timeout, NULL, timer_id, 0);
00657 wait_mask |= 1 << (timer_efn & 31);
00658 } else {
00659 timer_efn = 0;
00660 }
00661 rc = SYS$WFLOR (__glutConnectionFD, wait_mask);
00662 if (timer_efn != 0 && SYS$CLREF (timer_efn) == SS$_WASCLR) {
00663 rc = SYS$CANTIM (timer_id, PSL$C_USER);
00664 }
00665
00666
00667 #else
00668 FD_ZERO(&fds);
00669 FD_SET(__glutConnectionFD, &fds);
00670 timeout = __glutTimerList->timeout;
00671 GETTIMEOFDAY(&now);
00672 if (IS_AFTER(now, timeout)) {
00673 TIMEDELTA(waittime, timeout, now);
00674 } else {
00675 waittime = zerotime;
00676 }
00677 rc = select(__glutConnectionFD + 1, &fds,
00678 NULL, NULL, &waittime);
00679 if (rc < 0 && errno != EINTR)
00680 __glutFatalError("select error.");
00681 #endif
00682
00683
00684
00685
00686
00687 while (XPending(__glutDisplay)) {
00688 immediatelyHandleXinput:
00689 processEvents();
00690 }
00691 handleTimeouts();
00692 }
00693
00694 static void
00695 idleWait(void)
00696 {
00697 while (XPending(__glutDisplay)) {
00698 processEvents();
00699 }
00700 if (__glutTimerList)
00701 handleTimeouts();
00702
00703 if (__glutIdleFunc)
00704 __glutIdleFunc();
00705 }
00706
00707 static GLUTwindow **beforeEnd;
00708
00709 static GLUTwindow *
00710 processWindowWorkList(GLUTwindow * window)
00711 {
00712 int workMask;
00713
00714 if (window->prevWorkWin)
00715 window->prevWorkWin = processWindowWorkList(window->prevWorkWin);
00716 else
00717 beforeEnd = &window->prevWorkWin;
00718
00719
00720
00721
00722
00723
00724
00725
00726 workMask = window->workMask;
00727 assert((workMask & GLUT_DUMMY_WORK) == 0);
00728
00729
00730
00731
00732
00733
00734 window->workMask = GLUT_DUMMY_WORK;
00735
00736
00737
00738
00739
00740
00741 if (workMask & (GLUT_EVENT_MASK_WORK | GLUT_DEVICE_MASK_WORK |
00742 GLUT_CONFIGURE_WORK | GLUT_COLORMAP_WORK | GLUT_MAP_WORK)) {
00743
00744 if (workMask & GLUT_EVENT_MASK_WORK) {
00745 long eventMask;
00746
00747
00748
00749
00750 if (window->children) {
00751 GLUTwindow *child = window->children;
00752 unsigned long attribMask = CWDontPropagate;
00753 XSetWindowAttributes wa;
00754
00755 wa.do_not_propagate_mask = window->eventMask & GLUT_DONT_PROPAGATE_FILTER_MASK;
00756 if (window->eventMask & GLUT_HACK_STOP_PROPAGATE_MASK) {
00757 wa.event_mask = child->eventMask | (window->eventMask & GLUT_HACK_STOP_PROPAGATE_MASK);
00758 attribMask |= CWEventMask;
00759 }
00760 do {
00761 XChangeWindowAttributes(__glutDisplay, child->win,
00762 attribMask, &wa);
00763 child = child->siblings;
00764 } while (child);
00765 }
00766 eventMask = window->eventMask;
00767 if (window->parent && window->parent->eventMask & GLUT_HACK_STOP_PROPAGATE_MASK)
00768 eventMask |= (window->parent->eventMask & GLUT_HACK_STOP_PROPAGATE_MASK);
00769 XSelectInput(__glutDisplay, window->win, eventMask);
00770
00771 if (window->overlay)
00772 XSelectInput(__glutDisplay, window->overlay->win,
00773 window->eventMask & GLUT_OVERLAY_EVENT_FILTER_MASK);
00774 }
00775
00776 if (workMask & GLUT_DEVICE_MASK_WORK) {
00777 __glutUpdateInputDeviceMaskFunc(window);
00778 }
00779
00780
00781 if (workMask & GLUT_CONFIGURE_WORK) {
00782 XWindowChanges changes;
00783
00784 changes.x = window->desiredX;
00785 changes.y = window->desiredY;
00786 if (window->desiredConfMask & (CWWidth | CWHeight)) {
00787 changes.width = window->desiredWidth;
00788 changes.height = window->desiredHeight;
00789 if (window->overlay)
00790 XResizeWindow(__glutDisplay, window->overlay->win,
00791 window->desiredWidth, window->desiredHeight);
00792 if (__glutMotifHints != None) {
00793 if (workMask & GLUT_FULL_SCREEN_WORK) {
00794 MotifWmHints hints;
00795
00796 hints.flags = MWM_HINTS_DECORATIONS;
00797 hints.decorations = 0;
00798
00799 XChangeProperty(__glutDisplay, window->win,
00800 __glutMotifHints, __glutMotifHints, 32,
00801 PropModeReplace, (unsigned char *) &hints, 4);
00802 } else {
00803 XDeleteProperty(__glutDisplay, window->win, __glutMotifHints);
00804 }
00805 }
00806 }
00807 if (window->desiredConfMask & CWStackMode) {
00808 changes.stack_mode = window->desiredStack;
00809
00810
00811 if (window->parent && window->parent->overlay && window->desiredStack == Below) {
00812 changes.stack_mode = Above;
00813 changes.sibling = window->parent->overlay->win;
00814 window->desiredConfMask |= CWSibling;
00815 }
00816 }
00817 XConfigureWindow(__glutDisplay, window->win,
00818 window->desiredConfMask, &changes);
00819 window->desiredConfMask = 0;
00820 }
00821
00822
00823 if (workMask & GLUT_COLORMAP_WORK) {
00824 __glutEstablishColormapsProperty(window);
00825 }
00826 if (workMask & GLUT_MAP_WORK) {
00827 switch (window->desiredMapState) {
00828 case WithdrawnState:
00829 if (window->parent) {
00830 XUnmapWindow(__glutDisplay, window->win);
00831 } else {
00832 XWithdrawWindow(__glutDisplay, window->win,
00833 __glutScreen);
00834 }
00835 window->shownState = 0;
00836 break;
00837 case NormalState:
00838 XMapWindow(__glutDisplay, window->win);
00839 window->shownState = 1;
00840 break;
00841 case IconicState:
00842 XIconifyWindow(__glutDisplay, window->win, __glutScreen);
00843 window->shownState = 0;
00844 break;
00845 }
00846 }
00847 }
00848 if (workMask & (GLUT_REDISPLAY_WORK | GLUT_OVERLAY_REDISPLAY_WORK)) {
00849 if (window->forceReshape) {
00850
00851
00852 __glutSetWindow(window);
00853 window->reshape(window->width, window->height);
00854 window->forceReshape = False;
00855 }
00856
00857
00858
00859
00860
00861
00862
00863
00864
00865
00866 if (window->overlay && window->overlay->display) {
00867 int num = window->num;
00868 Window xid = window->overlay ? window->overlay->win : None;
00869
00870
00871
00872
00873
00874
00875
00876 if (workMask & GLUT_REDISPLAY_WORK) {
00877
00878
00879 window->renderWin = window->win;
00880 window->renderCtx = window->ctx;
00881 __glutWindowDamaged = window->damaged;
00882 window->damaged = 0;
00883 __glutSetWindow(window);
00884 window->display();
00885 __glutWindowDamaged = 0;
00886 }
00887 if (workMask & GLUT_OVERLAY_REDISPLAY_WORK) {
00888 window = __glutWindowList[num];
00889 if (window && window->overlay &&
00890 window->overlay->win == xid && window->overlay->display) {
00891
00892
00893 window->renderWin = window->overlay->win;
00894 window->renderCtx = window->overlay->ctx;
00895 __glutWindowDamaged = window->overlay->damaged;
00896 window->overlay->damaged = 0;
00897 __glutSetWindow(window);
00898 window->overlay->display();
00899 __glutWindowDamaged = 0;
00900 } else {
00901
00902
00903
00904 }
00905 }
00906 } else {
00907 __glutWindowDamaged = window->damaged;
00908 window->damaged = 0;
00909 if (window->overlay) {
00910 __glutWindowDamaged |= window->overlay->damaged;
00911 window->overlay->damaged = 0;
00912 }
00913 __glutSetWindow(window);
00914 window->display();
00915 __glutWindowDamaged = 0;
00916 }
00917 }
00918
00919
00920 workMask |= window->workMask;
00921
00922 if (workMask & GLUT_FINISH_WORK) {
00923 __glutSetWindow(window);
00924 glFinish();
00925 }
00926 if (workMask & GLUT_DEBUG_WORK) {
00927 GLenum error;
00928
00929 __glutSetWindow(window);
00930 while ((error = glGetError()) != GL_NO_ERROR)
00931 __glutWarning("GL error: %s", gluErrorString(error));
00932 }
00933
00934 window->workMask &= ~(GLUT_DUMMY_WORK | GLUT_FINISH_WORK | GLUT_DEBUG_WORK);
00935 if (window->workMask) {
00936
00937 return window;
00938 } else {
00939
00940 return window->prevWorkWin;
00941 }
00942 }
00943
00944 void
00945 glutMainLoop(void)
00946 {
00947 if (!__glutDisplay)
00948 __glutFatalUsage("main loop entered with out X connection.");
00949 if (!__glutWindowListSize)
00950 __glutFatalUsage(
00951 "main loop entered with no windows created.");
00952 for (;;) {
00953 if (__glutWindowWorkList) {
00954 GLUTwindow *remainder, *work;
00955
00956 work = __glutWindowWorkList;
00957 __glutWindowWorkList = NULL;
00958 if (work) {
00959 remainder = processWindowWorkList(work);
00960 if (remainder) {
00961 *beforeEnd = __glutWindowWorkList;
00962 __glutWindowWorkList = remainder;
00963 }
00964 }
00965 }
00966 if (__glutIdleFunc || __glutWindowWorkList) {
00967 idleWait();
00968 } else {
00969 if (__glutTimerList) {
00970 waitForSomething();
00971 } else {
00972 processEvents();
00973 }
00974 }
00975 }
00976 }