00001
00002
00003
00004
00005
00006
00007
00008 #include <stdlib.h>
00009 #include <stdio.h>
00010 #include <errno.h>
00011 #include <assert.h>
00012 #include <string.h>
00013
00014
00015
00016
00017
00018
00019 #if !defined(_WIN32)
00020 # ifdef __sgi
00021 # include <bstring.h>
00022 # endif
00023 # if (defined(SVR4) || defined(CRAY) || defined(AIXV3)) && !defined(FD_SETSIZE)
00024 # include <sys/select.h>
00025 # ifdef luna
00026 # include <sysent.h>
00027 # endif
00028 # endif
00029
00030 # if defined(AIXV4) && !defined(NFDBITS)
00031 # include <sys/select.h>
00032 # endif
00033 #endif
00034
00035 #include <sys/types.h>
00036
00037 #if !defined(_WIN32)
00038 # if defined(__vms) && ( __VMS_VER < 70000000 )
00039 # include <sys/time.h>
00040 # else
00041 # ifndef __vms
00042 # include <sys/time.h>
00043 # endif
00044 # endif
00045 # include <unistd.h>
00046 # include <X11/Xlib.h>
00047 # include <X11/keysym.h>
00048 #else
00049 # ifdef __CYGWIN32__
00050 # include <sys/time.h>
00051 # else
00052 # include <sys/timeb.h>
00053 # endif
00054 # ifdef __hpux
00055
00056
00057
00058
00059 # include <X11/HPkeysym.h>
00060 # endif
00061 #endif
00062
00063 #if defined(__vms) && ( __VMS_VER < 70000000 )
00064 #include <ssdef.h>
00065 #include <psldef.h>
00066 extern int SYS$CLREF(int efn);
00067 extern int SYS$SETIMR(unsigned int efn, struct timeval *timeout, void *ast,
00068 unsigned int request_id, unsigned int flags);
00069 extern int SYS$WFLOR(unsigned int efn, unsigned int mask);
00070 extern int SYS$CANTIM(unsigned int request_id, unsigned int mode);
00071 #endif
00072
00073 #include "glutint.h"
00074
00075 static GLUTtimer *freeTimerList = NULL;
00076
00077 GLUTidleCB __glutIdleFunc = NULL;
00078 GLUTtimer *__glutTimerList = NULL;
00079 #ifdef SUPPORT_FORTRAN
00080 GLUTtimer *__glutNewTimer;
00081 #endif
00082 GLUTwindow *__glutWindowWorkList = NULL;
00083 GLUTmenu *__glutMappedMenu;
00084 GLUTmenu *__glutCurrentMenu = NULL;
00085
00086 void (*__glutUpdateInputDeviceMaskFunc) (GLUTwindow *);
00087 #if !defined(_WIN32)
00088 void (*__glutMenuItemEnterOrLeave)(GLUTmenuItem * item, int num, int type) = NULL;
00089 void (*__glutFinishMenu)(Window win, int x, int y);
00090 void (*__glutPaintMenu)(GLUTmenu * menu);
00091 void (*__glutStartMenu)(GLUTmenu * menu, GLUTwindow * window, int x, int y, int x_win, int y_win);
00092 GLUTmenu * (*__glutGetMenuByNum)(int menunum);
00093 GLUTmenuItem * (*__glutGetMenuItem)(GLUTmenu * menu, Window win, int *which);
00094 GLUTmenu * (*__glutGetMenu)(Window win);
00095 #endif
00096
00097 Atom __glutMotifHints = None;
00098
00099 unsigned int __glutModifierMask = (unsigned int) ~0;
00100 int __glutWindowDamaged = 0;
00101
00102 void APIENTRY
00103 glutIdleFunc(GLUTidleCB idleFunc)
00104 {
00105 __glutIdleFunc = idleFunc;
00106 }
00107
00108 void APIENTRY
00109 glutTimerFunc(unsigned int interval, GLUTtimerCB timerFunc, int value)
00110 {
00111 GLUTtimer *timer, *other;
00112 GLUTtimer **prevptr;
00113 struct timeval now;
00114
00115 if (!timerFunc)
00116 return;
00117
00118 if (freeTimerList) {
00119 timer = freeTimerList;
00120 freeTimerList = timer->next;
00121 } else {
00122 timer = (GLUTtimer *) malloc(sizeof(GLUTtimer));
00123 if (!timer)
00124 __glutFatalError("out of memory.");
00125 }
00126
00127 timer->func = timerFunc;
00128 #if defined(__vms) && ( __VMS_VER < 70000000 )
00129
00130 timer->timeout.val = interval * TICKS_PER_MILLISECOND;
00131 #else
00132 timer->timeout.tv_sec = (int) interval / 1000;
00133 timer->timeout.tv_usec = (int) (interval % 1000) * 1000;
00134 #endif
00135 timer->value = value;
00136 timer->next = NULL;
00137 GETTIMEOFDAY(&now);
00138 ADD_TIME(timer->timeout, timer->timeout, now);
00139 prevptr = &__glutTimerList;
00140 other = *prevptr;
00141 while (other && IS_AFTER(other->timeout, timer->timeout)) {
00142 prevptr = &other->next;
00143 other = *prevptr;
00144 }
00145 timer->next = other;
00146 #ifdef SUPPORT_FORTRAN
00147 __glutNewTimer = timer;
00148 #endif
00149 *prevptr = timer;
00150 }
00151
00152 void
00153 handleTimeouts(void)
00154 {
00155 struct timeval now;
00156 GLUTtimer *timer;
00157
00158
00159
00160 GETTIMEOFDAY(&now);
00161 while (IS_AT_OR_AFTER(__glutTimerList->timeout, now)) {
00162 timer = __glutTimerList;
00163 timer->func(timer->value);
00164 __glutTimerList = timer->next;
00165 timer->next = freeTimerList;
00166 freeTimerList = timer;
00167 if (!__glutTimerList)
00168 break;
00169 }
00170 }
00171
00172 void
00173 __glutPutOnWorkList(GLUTwindow * window, int workMask)
00174 {
00175 if (window->workMask) {
00176
00177 window->workMask |= workMask;
00178 } else {
00179
00180 window->workMask = workMask;
00181
00182
00183
00184 assert(window != __glutWindowWorkList);
00185 window->prevWorkWin = __glutWindowWorkList;
00186 __glutWindowWorkList = window;
00187 }
00188 }
00189
00190 void
00191 __glutPostRedisplay(GLUTwindow * window, int layerMask)
00192 {
00193 int shown = (layerMask & (GLUT_REDISPLAY_WORK | GLUT_REPAIR_WORK)) ?
00194 window->shownState : window->overlay->shownState;
00195
00196
00197
00198
00199 if (window->visState != GLUT_HIDDEN
00200 && window->visState != GLUT_FULLY_COVERED && shown) {
00201 __glutPutOnWorkList(window, layerMask);
00202 }
00203 }
00204
00205
00206 void APIENTRY
00207 glutPostRedisplay(void)
00208 {
00209 __glutPostRedisplay(__glutCurrentWindow, GLUT_REDISPLAY_WORK);
00210 }
00211
00212
00213
00214
00215
00216 void APIENTRY
00217 glutPostWindowRedisplay(int win)
00218 {
00219 __glutPostRedisplay(__glutWindowList[win - 1], GLUT_REDISPLAY_WORK);
00220 }
00221
00222
00223 static GLUTeventParser *eventParserList = NULL;
00224
00225
00226
00227
00228
00229
00230
00231 void
00232 __glutRegisterEventParser(GLUTeventParser * parser)
00233 {
00234 parser->next = eventParserList;
00235 eventParserList = parser;
00236 }
00237
00238 static void
00239 markWindowHidden(GLUTwindow * window)
00240 {
00241 if (GLUT_HIDDEN != window->visState) {
00242 GLUTwindow *child;
00243
00244 if (window->windowStatus) {
00245 window->visState = GLUT_HIDDEN;
00246 __glutSetWindow(window);
00247 window->windowStatus(GLUT_HIDDEN);
00248 }
00249
00250
00251 child = window->children;
00252 while (child) {
00253 markWindowHidden(child);
00254 child = child->siblings;
00255 }
00256 }
00257 }
00258
00259 #if !defined(_WIN32)
00260
00261 static void
00262 purgeStaleWindow(Window win)
00263 {
00264 GLUTstale **pEntry = &__glutStaleWindowList;
00265 GLUTstale *entry = __glutStaleWindowList;
00266
00267
00268
00269 while (entry) {
00270 if (entry->win == win) {
00271
00272 *pEntry = entry->next;
00273 free(entry);
00274 return;
00275 } else {
00276 pEntry = &entry->next;
00277 entry = *pEntry;
00278 }
00279 }
00280 }
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290 static int
00291 interruptibleXNextEvent(Display * dpy, XEvent * event)
00292 {
00293 fd_set fds;
00294 int rc;
00295
00296
00297
00298 XFlush(__glutDisplay);
00299 for (;;) {
00300 if (XPending(__glutDisplay)) {
00301 XNextEvent(dpy, event);
00302 return 1;
00303 }
00304 FD_ZERO(&fds);
00305 FD_SET(__glutConnectionFD, &fds);
00306 rc = select(__glutConnectionFD + 1, &fds,
00307 NULL, NULL, NULL);
00308 if (rc < 0) {
00309 if (errno == EINTR) {
00310 return 0;
00311 } else {
00312 __glutFatalError("select error.");
00313 }
00314 }
00315 }
00316 }
00317
00318 #endif
00319
00320 static void
00321 processEventsAndTimeouts(void)
00322 {
00323 do {
00324 #if defined(_WIN32)
00325 MSG event;
00326
00327 if(!GetMessage(&event, NULL, 0, 0))
00328 exit(0);
00329 TranslateMessage(&event);
00330 DispatchMessage(&event);
00331
00332 #else
00333 static int mappedMenuButton;
00334 GLUTeventParser *parser;
00335 XEvent event, ahead;
00336 GLUTwindow *window;
00337 GLUTkeyboardCB keyboard;
00338 GLUTspecialCB special;
00339 int gotEvent, x, y, width, height;
00340 static int is_first_configure_notify_event = 1;
00341 static int x_first = 0, y_first = 0;
00342
00343 gotEvent = interruptibleXNextEvent(__glutDisplay, &event);
00344 if (gotEvent) {
00345 switch (event.type) {
00346 case MappingNotify:
00347 XRefreshKeyboardMapping((XMappingEvent *) & event);
00348 break;
00349 case ConfigureNotify:
00350
00351
00352
00353
00354
00355
00356 window = __glutGetWindow(event.xconfigure.window);
00357 if (window) {
00358 if (window->win != event.xconfigure.window) {
00359
00360
00361
00362
00363 break;
00364 }
00365 x = event.xconfigure.x;
00366 y = event.xconfigure.y;
00367 if (is_first_configure_notify_event) {
00368 is_first_configure_notify_event = 0;
00369 x_first = x;
00370 y_first = y;
00371 x += window->x;
00372 y += window->y;
00373 } else if (x == x_first && y == y_first) {
00374 x = window->x;
00375 y = window->y;
00376 }
00377 if (x != window->x || y != window->y) {
00378 if (window->overlay) {
00379 XMoveWindow(__glutDisplay, window->overlay->win, x, y);
00380 }
00381 window->x = x;
00382 window->y = y;
00383 __glutSetWindow(window);
00384 glXWaitX();
00385 if (window->move) {
00386 window->move(x, y);
00387 }
00388 __glutWacomSetOffset(x, y);
00389 __glutPostRedisplay(window, GLUT_REPAIR_WORK);
00390 }
00391 width = event.xconfigure.width;
00392 height = event.xconfigure.height;
00393 if (width != window->width || height != window->height) {
00394 if (window->overlay) {
00395 XResizeWindow(__glutDisplay, window->overlay->win, width, height);
00396 }
00397 window->width = width;
00398 window->height = height;
00399 __glutSetWindow(window);
00400
00401
00402 glXWaitX();
00403 window->reshape(width, height);
00404 window->forceReshape = False;
00405
00406
00407
00408
00409
00410
00411 __glutPostRedisplay(window, GLUT_REPAIR_WORK);
00412 }
00413 }
00414 break;
00415 case Expose:
00416
00417 while (XEventsQueued(__glutDisplay, QueuedAfterReading)
00418 > 0) {
00419 XPeekEvent(__glutDisplay, &ahead);
00420 if (ahead.type != Expose ||
00421 ahead.xexpose.window != event.xexpose.window) {
00422 break;
00423 }
00424 XNextEvent(__glutDisplay, &event);
00425 }
00426 if (event.xexpose.count == 0) {
00427 GLUTmenu *menu;
00428
00429 if (__glutMappedMenu &&
00430 (menu = __glutGetMenu(event.xexpose.window))) {
00431 __glutPaintMenu(menu);
00432 } else {
00433 window = __glutGetWindow(event.xexpose.window);
00434 if (window) {
00435 if (window->win == event.xexpose.window) {
00436 __glutPostRedisplay(window, GLUT_REPAIR_WORK);
00437 } else if (window->overlay && window->overlay->win == event.xexpose.window) {
00438 __glutPostRedisplay(window, GLUT_OVERLAY_REPAIR_WORK);
00439 }
00440 }
00441 }
00442 } else {
00443
00444 }
00445 break;
00446 case ButtonPress:
00447 case ButtonRelease:
00448 if (__glutMappedMenu && event.type == ButtonRelease
00449 && mappedMenuButton == event.xbutton.button) {
00450
00451
00452 __glutFinishMenu(event.xbutton.window, event.xbutton.x, event.xbutton.y);
00453 } else {
00454 window = __glutGetWindow(event.xbutton.window);
00455 if (window) {
00456 GLUTmenu *menu;
00457 int menuNum;
00458
00459 menuNum = window->menu[event.xbutton.button - 1];
00460
00461
00462 if ((menuNum > 0) && (menu = __glutGetMenuByNum(menuNum))) {
00463 if (event.type == ButtonPress && !__glutMappedMenu) {
00464 __glutStartMenu(menu, window,
00465 event.xbutton.x_root, event.xbutton.y_root,
00466 event.xbutton.x, event.xbutton.y);
00467 mappedMenuButton = event.xbutton.button;
00468 } else {
00469
00470
00471
00472
00473 }
00474 } else if (window->mouse) {
00475 __glutSetWindow(window);
00476 __glutModifierMask = event.xbutton.state;
00477 window->mouse(event.xbutton.button - 1,
00478 event.type == ButtonRelease ?
00479 GLUT_UP : GLUT_DOWN,
00480 event.xbutton.x, event.xbutton.y);
00481 __glutModifierMask = ~0;
00482 } else {
00483
00484 }
00485 } else {
00486
00487
00488 }
00489 }
00490 break;
00491 case MotionNotify:
00492 if (!__glutMappedMenu) {
00493 window = __glutGetWindow(event.xmotion.window);
00494 if (window) {
00495
00496
00497 if (window->motion && event.xmotion.state &
00498 (Button1Mask | Button2Mask | Button3Mask)) {
00499 __glutSetWindow(window);
00500 window->motion(event.xmotion.x, event.xmotion.y);
00501 }
00502
00503
00504
00505 else if (window->passive &&
00506 ((event.xmotion.state &
00507 (Button1Mask | Button2Mask | Button3Mask)) ==
00508 0)) {
00509 __glutSetWindow(window);
00510 window->passive(event.xmotion.x,
00511 event.xmotion.y);
00512 }
00513 }
00514 } else {
00515
00516
00517 }
00518 break;
00519 case KeyPress:
00520 case KeyRelease:
00521 window = __glutGetWindow(event.xkey.window);
00522 if (!window) {
00523 break;
00524 }
00525 if (event.type == KeyPress) {
00526 keyboard = window->keyboard;
00527 } else {
00528
00529
00530
00531
00532
00533
00534
00535 if (window->ignoreKeyRepeat) {
00536 if (XEventsQueued(__glutDisplay, QueuedAfterReading)) {
00537 XPeekEvent(__glutDisplay, &ahead);
00538 if (ahead.type == KeyPress
00539 && ahead.xkey.window == event.xkey.window
00540 && ahead.xkey.keycode == event.xkey.keycode
00541 && ahead.xkey.time == event.xkey.time) {
00542
00543
00544 XNextEvent(__glutDisplay, &event);
00545 break;
00546 }
00547 }
00548 }
00549 keyboard = window->keyboardUp;
00550 }
00551 if (keyboard) {
00552 char tmp[1];
00553 int rc;
00554
00555 rc = XLookupString(&event.xkey, tmp, sizeof(tmp),
00556 NULL, NULL);
00557 if (rc) {
00558 __glutSetWindow(window);
00559 __glutModifierMask = event.xkey.state;
00560 keyboard(tmp[0],
00561 event.xkey.x, event.xkey.y);
00562 __glutModifierMask = ~0;
00563 break;
00564 }
00565 }
00566 if (event.type == KeyPress) {
00567 special = window->special;
00568 } else {
00569 special = window->specialUp;
00570 }
00571 if (special) {
00572 KeySym ks;
00573 int key;
00574
00575
00576
00577
00578 #ifndef XK_KP_Home
00579 #define XK_KP_Home 0xFF95
00580 #endif
00581 #ifndef XK_KP_Left
00582 #define XK_KP_Left 0xFF96
00583 #endif
00584 #ifndef XK_KP_Up
00585 #define XK_KP_Up 0xFF97
00586 #endif
00587 #ifndef XK_KP_Right
00588 #define XK_KP_Right 0xFF98
00589 #endif
00590 #ifndef XK_KP_Down
00591 #define XK_KP_Down 0xFF99
00592 #endif
00593 #ifndef XK_KP_Prior
00594 #define XK_KP_Prior 0xFF9A
00595 #endif
00596 #ifndef XK_KP_Next
00597 #define XK_KP_Next 0xFF9B
00598 #endif
00599 #ifndef XK_KP_End
00600 #define XK_KP_End 0xFF9C
00601 #endif
00602 #ifndef XK_KP_Insert
00603 #define XK_KP_Insert 0xFF9E
00604 #endif
00605 #ifndef XK_KP_Delete
00606 #define XK_KP_Delete 0xFF9F
00607 #endif
00608
00609 ks = XLookupKeysym((XKeyEvent *) & event, 0);
00610
00611
00612 switch (ks) {
00613
00614
00615 case XK_F1: key = GLUT_KEY_F1; break;
00616 case XK_F2: key = GLUT_KEY_F2; break;
00617 case XK_F3: key = GLUT_KEY_F3; break;
00618 case XK_F4: key = GLUT_KEY_F4; break;
00619 case XK_F5: key = GLUT_KEY_F5; break;
00620 case XK_F6: key = GLUT_KEY_F6; break;
00621 case XK_F7: key = GLUT_KEY_F7; break;
00622 case XK_F8: key = GLUT_KEY_F8; break;
00623 case XK_F9: key = GLUT_KEY_F9; break;
00624 case XK_F10: key = GLUT_KEY_F10; break;
00625 case XK_F11: key = GLUT_KEY_F11; break;
00626 case XK_F12: key = GLUT_KEY_F12; break;
00627
00628 case XK_KP_Left:
00629 case XK_Left: key = GLUT_KEY_LEFT; break;
00630 case XK_KP_Up:
00631 case XK_Up: key = GLUT_KEY_UP; break;
00632 case XK_KP_Right:
00633 case XK_Right: key = GLUT_KEY_RIGHT; break;
00634 case XK_KP_Down:
00635 case XK_Down: key = GLUT_KEY_DOWN; break;
00636
00637
00638 case XK_KP_Prior:
00639 case XK_Prior:
00640
00641 key = GLUT_KEY_PAGE_UP;
00642 break;
00643 case XK_KP_Next:
00644 case XK_Next:
00645
00646 key = GLUT_KEY_PAGE_DOWN;
00647 break;
00648 case XK_KP_Home:
00649 case XK_Home:
00650 key = GLUT_KEY_HOME;
00651 break;
00652 #ifdef __hpux
00653 case XK_Select:
00654 #endif
00655 case XK_KP_End:
00656 case XK_End:
00657 key = GLUT_KEY_END;
00658 break;
00659 #ifdef __hpux
00660 case XK_InsertChar:
00661 #endif
00662 case XK_KP_Insert:
00663 case XK_Insert:
00664 key = GLUT_KEY_INSERT;
00665 break;
00666 #ifdef __hpux
00667 case XK_DeleteChar:
00668 #endif
00669 case XK_KP_Delete:
00670
00671 __glutSetWindow(window);
00672 keyboard(127,
00673 event.xkey.x, event.xkey.y);
00674 goto skip;
00675 default:
00676 goto skip;
00677 }
00678 __glutSetWindow(window);
00679 __glutModifierMask = event.xkey.state;
00680 special(key, event.xkey.x, event.xkey.y);
00681 __glutModifierMask = ~0;
00682 skip:;
00683 }
00684 break;
00685 case EnterNotify:
00686 case LeaveNotify:
00687 if (event.xcrossing.mode != NotifyNormal ||
00688 event.xcrossing.detail == NotifyNonlinearVirtual ||
00689 event.xcrossing.detail == NotifyVirtual) {
00690
00691
00692
00693
00694
00695
00696
00697
00698 break;
00699 }
00700 if (__glutMappedMenu) {
00701 GLUTmenuItem *item;
00702 int num;
00703
00704 item = __glutGetMenuItem(__glutMappedMenu,
00705 event.xcrossing.window, &num);
00706 if (item) {
00707 __glutMenuItemEnterOrLeave(item, num, event.type);
00708 break;
00709 }
00710 }
00711 window = __glutGetWindow(event.xcrossing.window);
00712 if (window) {
00713 if (window->entry) {
00714 if (event.type == EnterNotify) {
00715
00716
00717
00718
00719
00720
00721
00722 if (window->entryState != EnterNotify) {
00723 int num = window->num;
00724 Window xid = window->win;
00725
00726 window->entryState = EnterNotify;
00727 __glutSetWindow(window);
00728 window->entry(GLUT_ENTERED);
00729
00730 if (__glutMappedMenu) {
00731
00732
00733
00734
00735 } else {
00736
00737
00738
00739
00740
00741
00742
00743
00744 window = __glutWindowList[num];
00745 if (window && window->passive && window->win == xid) {
00746 __glutSetWindow(window);
00747 window->passive(event.xcrossing.x, event.xcrossing.y);
00748 }
00749 }
00750 }
00751 } else {
00752 if (window->entryState != LeaveNotify) {
00753
00754
00755
00756
00757
00758
00759
00760
00761
00762
00763
00764
00765
00766 if (XEventsQueued(__glutDisplay, QueuedAfterReading)) {
00767 XPeekEvent(__glutDisplay, &ahead);
00768 if (ahead.type == EnterNotify &&
00769 __glutGetWindow(ahead.xcrossing.window) == window) {
00770 XNextEvent(__glutDisplay, &event);
00771 break;
00772 }
00773 }
00774 window->entryState = LeaveNotify;
00775 __glutSetWindow(window);
00776 window->entry(GLUT_LEFT);
00777 }
00778 }
00779 } else if (window->passive) {
00780 __glutSetWindow(window);
00781 window->passive(event.xcrossing.x, event.xcrossing.y);
00782 }
00783 }
00784 break;
00785 case UnmapNotify:
00786
00787
00788
00789
00790
00791
00792 window = __glutGetWindow(event.xunmap.window);
00793 if (window) {
00794 if (window->win != event.xconfigure.window) {
00795
00796
00797
00798
00799 break;
00800 }
00801 markWindowHidden(window);
00802 }
00803 break;
00804 case VisibilityNotify:
00805 window = __glutGetWindow(event.xvisibility.window);
00806 if (window) {
00807
00808
00809
00810
00811 int visState = event.xvisibility.state + 1;
00812
00813 if (visState != window->visState) {
00814 if (window->windowStatus) {
00815 window->visState = visState;
00816 __glutSetWindow(window);
00817 window->windowStatus(visState);
00818 }
00819 }
00820 }
00821 break;
00822 case ClientMessage:
00823 if (event.xclient.data.l[0] == __glutWMDeleteWindow)
00824 exit(0);
00825 break;
00826 case DestroyNotify:
00827 purgeStaleWindow(event.xdestroywindow.window);
00828 break;
00829 case CirculateNotify:
00830 case CreateNotify:
00831 case GravityNotify:
00832 case ReparentNotify:
00833
00834
00835 break;
00836 default:
00837
00838
00839
00840
00841
00842
00843 parser = eventParserList;
00844 while (parser) {
00845 if (parser->func(&event))
00846 break;
00847 parser = parser->next;
00848 }
00849 break;
00850 }
00851 }
00852 #endif
00853 if (__glutTimerList) {
00854 handleTimeouts();
00855 }
00856 }
00857 while (XPending(__glutDisplay));
00858 }
00859
00860 static void
00861 waitForSomething(void)
00862 {
00863 #if defined(__vms) && ( __VMS_VER < 70000000 )
00864 static struct timeval zerotime =
00865 {0};
00866 unsigned int timer_efn;
00867 #define timer_id 'glut'
00868 unsigned int wait_mask;
00869 #else
00870 static struct timeval zerotime =
00871 {0, 0};
00872 #if !defined(_WIN32)
00873 fd_set fds;
00874 #endif
00875 #endif
00876 struct timeval now, timeout, waittime;
00877 #if !defined(_WIN32)
00878 int rc;
00879 #endif
00880
00881
00882
00883 XFlush(__glutDisplay);
00884 if (XPending(__glutDisplay)) {
00885
00886
00887
00888
00889
00890
00891
00892
00893
00894 goto immediatelyHandleXinput;
00895 }
00896 #if defined(__vms) && ( __VMS_VER < 70000000 )
00897 timeout = __glutTimerList->timeout;
00898 GETTIMEOFDAY(&now);
00899 wait_mask = 1 << (__glutConnectionFD & 31);
00900 if (IS_AFTER(now, timeout)) {
00901
00902
00903
00904
00905 timer_efn = __glutConnectionFD - 1;
00906 if ((timer_efn / 32) != (__glutConnectionFD / 32)) {
00907 timer_efn = __glutConnectionFD + 1;
00908 }
00909 rc = SYS$CLREF(timer_efn);
00910 rc = SYS$SETIMR(timer_efn, &timeout, NULL, timer_id, 0);
00911 wait_mask |= 1 << (timer_efn & 31);
00912 } else {
00913 timer_efn = 0;
00914 }
00915 rc = SYS$WFLOR(__glutConnectionFD, wait_mask);
00916 if (timer_efn != 0 && SYS$CLREF(timer_efn) == SS$_WASCLR) {
00917 rc = SYS$CANTIM(timer_id, PSL$C_USER);
00918 }
00919
00920
00921 #else
00922 #if !defined(_WIN32)
00923 FD_ZERO(&fds);
00924 FD_SET(__glutConnectionFD, &fds);
00925 #endif
00926 timeout = __glutTimerList->timeout;
00927 GETTIMEOFDAY(&now);
00928 if (IS_AFTER(now, timeout)) {
00929 TIMEDELTA(waittime, timeout, now);
00930 } else {
00931 waittime = zerotime;
00932 }
00933 #if !defined(_WIN32)
00934 rc = select(__glutConnectionFD + 1, &fds,
00935 NULL, NULL, &waittime);
00936 if (rc < 0 && errno != EINTR)
00937 __glutFatalError("select error.");
00938 #else
00939 #if 0
00940
00941
00942 SetTimer(NULL, 2, waittime.tv_usec, NULL);
00943 WaitMessage();
00944 KillTimer(NULL, 2);
00945 #endif
00946
00947
00948 Sleep(0);
00949 #endif
00950 #endif
00951
00952
00953
00954
00955
00956
00957 if (XPending(__glutDisplay)) {
00958 immediatelyHandleXinput:
00959 processEventsAndTimeouts();
00960 } else {
00961 if (__glutTimerList)
00962 handleTimeouts();
00963 }
00964 }
00965
00966 static void
00967 idleWait(void)
00968 {
00969 if (XPending(__glutDisplay)) {
00970 processEventsAndTimeouts();
00971 } else {
00972 if (__glutTimerList) {
00973 handleTimeouts();
00974 }
00975 }
00976
00977 if (__glutIdleFunc) {
00978 __glutIdleFunc();
00979 }
00980 }
00981
00982 static GLUTwindow **beforeEnd;
00983
00984 static GLUTwindow *
00985 processWindowWorkList(GLUTwindow * window)
00986 {
00987 int workMask;
00988
00989 if (window->prevWorkWin) {
00990 window->prevWorkWin = processWindowWorkList(window->prevWorkWin);
00991 } else {
00992 beforeEnd = &window->prevWorkWin;
00993 }
00994
00995
00996
00997
00998
00999
01000
01001
01002 workMask = window->workMask;
01003 assert((workMask & GLUT_DUMMY_WORK) == 0);
01004
01005
01006
01007
01008
01009
01010 window->workMask = GLUT_DUMMY_WORK;
01011
01012
01013
01014
01015
01016
01017 if (workMask & (GLUT_EVENT_MASK_WORK | GLUT_DEVICE_MASK_WORK |
01018 GLUT_CONFIGURE_WORK | GLUT_COLORMAP_WORK | GLUT_MAP_WORK)) {
01019 #if !defined(_WIN32)
01020
01021 if (workMask & GLUT_EVENT_MASK_WORK) {
01022 long eventMask;
01023
01024
01025
01026
01027 if (window->children) {
01028 GLUTwindow *child = window->children;
01029 unsigned long attribMask = CWDontPropagate;
01030 XSetWindowAttributes wa;
01031
01032 wa.do_not_propagate_mask = window->eventMask & GLUT_DONT_PROPAGATE_FILTER_MASK;
01033 if (window->eventMask & GLUT_HACK_STOP_PROPAGATE_MASK) {
01034 wa.event_mask = child->eventMask | (window->eventMask & GLUT_HACK_STOP_PROPAGATE_MASK);
01035 attribMask |= CWEventMask;
01036 }
01037 do {
01038 XChangeWindowAttributes(__glutDisplay, child->win,
01039 attribMask, &wa);
01040 child = child->siblings;
01041 } while (child);
01042 }
01043 eventMask = window->eventMask;
01044 if (window->parent && window->parent->eventMask & GLUT_HACK_STOP_PROPAGATE_MASK)
01045 eventMask |= (window->parent->eventMask & GLUT_HACK_STOP_PROPAGATE_MASK);
01046 XSelectInput(__glutDisplay, window->win, eventMask);
01047 if (window->overlay)
01048 XSelectInput(__glutDisplay, window->overlay->win,
01049 window->eventMask & GLUT_OVERLAY_EVENT_FILTER_MASK);
01050 }
01051 #endif
01052
01053 if (workMask & GLUT_DEVICE_MASK_WORK) {
01054 __glutUpdateInputDeviceMaskFunc(window);
01055 }
01056
01057 if (workMask & GLUT_CONFIGURE_WORK) {
01058 #if defined(_WIN32)
01059 RECT changes;
01060 POINT point;
01061 UINT flags = SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOOWNERZORDER
01062 | SWP_NOSENDCHANGING | SWP_NOSIZE | SWP_NOZORDER;
01063
01064 GetClientRect(window->win, &changes);
01065
01066
01067
01068 if (!window->parent) {
01069 point.x = 0;
01070 point.y = 0;
01071 ClientToScreen(window->win, &point);
01072 changes.left = point.x;
01073 changes.top = point.y;
01074 }
01075 if (window->desiredConfMask & (CWX | CWY)) {
01076 changes.left = window->desiredX;
01077 changes.top = window->desiredY;
01078 flags &= ~SWP_NOMOVE;
01079 }
01080 if (window->desiredConfMask & (CWWidth | CWHeight)) {
01081 changes.right = changes.left + window->desiredWidth;
01082 changes.bottom = changes.top + window->desiredHeight;
01083 flags &= ~SWP_NOSIZE;
01084
01085
01086 }
01087 if (window->desiredConfMask & CWStackMode) {
01088 flags &= ~SWP_NOZORDER;
01089
01090 }
01091
01092
01093
01094
01095
01096
01097
01098 if (!window->parent && window != __glutGameModeWindow) {
01099 AdjustWindowRect(&changes,
01100 WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
01101 FALSE);
01102 }
01103
01104
01105 SetWindowPos(window->win,
01106 window->desiredStack == Above ? HWND_TOP : HWND_NOTOPMOST,
01107 changes.left, changes.top,
01108 changes.right - changes.left, changes.bottom - changes.top,
01109 flags);
01110
01111
01112 window->desiredConfMask = 0;
01113
01114
01115
01116 if (workMask & GLUT_FULL_SCREEN_WORK) {
01117 window->desiredConfMask |= CWX | CWY;
01118 window->desiredX = point.x;
01119 window->desiredY = point.y;
01120 }
01121 #else
01122 XWindowChanges changes;
01123
01124 changes.x = window->desiredX;
01125 changes.y = window->desiredY;
01126 if (window->desiredConfMask & (CWWidth | CWHeight)) {
01127 changes.width = window->desiredWidth;
01128 changes.height = window->desiredHeight;
01129 if (window->overlay)
01130 XResizeWindow(__glutDisplay, window->overlay->win,
01131 window->desiredWidth, window->desiredHeight);
01132 if (__glutMotifHints != None) {
01133 if (workMask & GLUT_FULL_SCREEN_WORK) {
01134 MotifWmHints hints;
01135
01136 hints.flags = MWM_HINTS_DECORATIONS;
01137 hints.decorations = 0;
01138
01139 XChangeProperty(__glutDisplay, window->win,
01140 __glutMotifHints, __glutMotifHints, 32,
01141 PropModeReplace, (unsigned char *) &hints, 4);
01142 if (workMask & GLUT_MAP_WORK) {
01143
01144
01145
01146
01147
01148
01149
01150
01151
01152
01153
01154
01155 XSizeHints hints;
01156
01157 hints.flags = USPosition | USSize;
01158 hints.x = 0;
01159 hints.y = 0;
01160 hints.width = window->desiredWidth;
01161 hints.height = window->desiredHeight;
01162 XSetWMNormalHints(__glutDisplay, window->win, &hints);
01163 }
01164 } else {
01165 XDeleteProperty(__glutDisplay, window->win, __glutMotifHints);
01166 }
01167 }
01168 }
01169 if (window->desiredConfMask & CWStackMode) {
01170 changes.stack_mode = window->desiredStack;
01171
01172
01173 if (window->parent && window->parent->overlay
01174 && window->desiredStack == Below) {
01175 changes.stack_mode = Above;
01176 changes.sibling = window->parent->overlay->win;
01177 window->desiredConfMask |= CWSibling;
01178 }
01179 }
01180 XConfigureWindow(__glutDisplay, window->win,
01181 window->desiredConfMask, &changes);
01182 window->desiredConfMask = 0;
01183 #endif
01184 }
01185 #if !defined(_WIN32)
01186
01187
01188 if (workMask & GLUT_COLORMAP_WORK) {
01189 __glutEstablishColormapsProperty(window);
01190 }
01191 #endif
01192 if (workMask & GLUT_MAP_WORK) {
01193 switch (window->desiredMapState) {
01194 case WithdrawnState:
01195 if (window->parent) {
01196 XUnmapWindow(__glutDisplay, window->win);
01197 } else {
01198 XWithdrawWindow(__glutDisplay, window->win,
01199 __glutScreen);
01200 }
01201 window->shownState = 0;
01202 break;
01203 case NormalState:
01204 XMapWindow(__glutDisplay, window->win);
01205 window->shownState = 1;
01206 break;
01207 #ifdef _WIN32
01208 case GameModeState:
01209 ShowWindow(window->win, SW_SHOW);
01210 window->shownState = 1;
01211 break;
01212 #endif
01213 case IconicState:
01214 XIconifyWindow(__glutDisplay, window->win, __glutScreen);
01215 window->shownState = 0;
01216 break;
01217 }
01218 }
01219 }
01220 if (workMask & (GLUT_REDISPLAY_WORK | GLUT_OVERLAY_REDISPLAY_WORK | GLUT_REPAIR_WORK | GLUT_OVERLAY_REPAIR_WORK)) {
01221 if (window->forceReshape) {
01222
01223
01224 __glutSetWindow(window);
01225 window->reshape(window->width, window->height);
01226 window->forceReshape = False;
01227
01228
01229
01230
01231
01232
01233
01234 workMask |= GLUT_REDISPLAY_WORK;
01235 }
01236
01237
01238
01239
01240
01241
01242
01243
01244
01245
01246 if (window->overlay && window->overlay->display) {
01247 int num = window->num;
01248 Window xid = window->overlay ? window->overlay->win : None;
01249
01250
01251
01252
01253
01254
01255
01256 if (workMask & (GLUT_REDISPLAY_WORK | GLUT_REPAIR_WORK)) {
01257 if (__glutMesaSwapHackSupport) {
01258 if (window->usedSwapBuffers) {
01259 if ((workMask & (GLUT_REPAIR_WORK | GLUT_REDISPLAY_WORK)) == GLUT_REPAIR_WORK) {
01260 SWAP_BUFFERS_WINDOW(window);
01261 goto skippedDisplayCallback1;
01262 }
01263 }
01264 }
01265
01266 #ifdef _WIN32
01267 window->renderDc = window->hdc;
01268 #endif
01269 window->renderWin = window->win;
01270 window->renderCtx = window->ctx;
01271 __glutWindowDamaged = (workMask & GLUT_REPAIR_WORK);
01272 __glutSetWindow(window);
01273 window->usedSwapBuffers = 0;
01274 window->display();
01275 __glutWindowDamaged = 0;
01276
01277 skippedDisplayCallback1:;
01278 }
01279 if (workMask & (GLUT_OVERLAY_REDISPLAY_WORK | GLUT_OVERLAY_REPAIR_WORK)) {
01280 window = __glutWindowList[num];
01281 if (window && window->overlay &&
01282 window->overlay->win == xid && window->overlay->display) {
01283
01284
01285 #ifdef _WIN32
01286 window->renderDc = window->overlay->hdc;
01287 #endif
01288 window->renderWin = window->overlay->win;
01289 window->renderCtx = window->overlay->ctx;
01290 __glutWindowDamaged = (workMask & GLUT_OVERLAY_REPAIR_WORK);
01291 __glutSetWindow(window);
01292 window->overlay->display();
01293 __glutWindowDamaged = 0;
01294 } else {
01295
01296
01297
01298 }
01299 }
01300 } else {
01301 if (__glutMesaSwapHackSupport) {
01302 if (!window->overlay && window->usedSwapBuffers) {
01303 if ((workMask & (GLUT_REPAIR_WORK | GLUT_REDISPLAY_WORK)) == GLUT_REPAIR_WORK) {
01304 SWAP_BUFFERS_WINDOW(window);
01305 goto skippedDisplayCallback2;
01306 }
01307 }
01308 }
01309
01310 __glutWindowDamaged = (workMask & (GLUT_OVERLAY_REPAIR_WORK | GLUT_REPAIR_WORK));
01311 __glutSetWindow(window);
01312 window->usedSwapBuffers = 0;
01313 window->display();
01314 __glutWindowDamaged = 0;
01315
01316 skippedDisplayCallback2:;
01317 }
01318 }
01319
01320
01321 workMask |= window->workMask;
01322
01323 if (workMask & GLUT_FINISH_WORK) {
01324
01325
01326
01327
01328
01329
01330 __glutSetWindow(window);
01331 glFinish();
01332 }
01333 if (workMask & GLUT_DEBUG_WORK) {
01334 __glutSetWindow(window);
01335 glutReportErrors();
01336 }
01337
01338 window->workMask &= ~(GLUT_DUMMY_WORK | GLUT_FINISH_WORK | GLUT_DEBUG_WORK);
01339 if (window->workMask) {
01340
01341 return window;
01342 } else {
01343
01344 return window->prevWorkWin;
01345 }
01346 }
01347
01348
01349 void APIENTRY
01350 glutMainLoop(void)
01351 {
01352 #if !defined(_WIN32)
01353 if (!__glutDisplay)
01354 __glutFatalUsage("main loop entered with out proper initialization.");
01355 #endif
01356 if (!__glutWindowListSize)
01357 __glutFatalUsage(
01358 "main loop entered with no windows created.");
01359 for (;;) {
01360 if (__glutWindowWorkList) {
01361 GLUTwindow *remainder, *work;
01362
01363 work = __glutWindowWorkList;
01364 __glutWindowWorkList = NULL;
01365 if (work) {
01366 remainder = processWindowWorkList(work);
01367 if (remainder) {
01368 *beforeEnd = __glutWindowWorkList;
01369 __glutWindowWorkList = remainder;
01370 }
01371 }
01372 }
01373 if (__glutIdleFunc || __glutWindowWorkList) {
01374 idleWait();
01375 } else {
01376 if (__glutTimerList) {
01377 waitForSomething();
01378 } else {
01379 processEventsAndTimeouts();
01380 }
01381 }
01382 }
01383 }
01384