/* * $Id$ * * $Date$ * $Revision$ * * (C) 1999 by Hyperion * All rights reserved * * This file is part of the MiniGL library project * See the file Licence.txt for more details * */ #include "mgl/gl.h" #include "GL/glut.h" #include #include "requesters.h" #include #include #include #include "sysinc.h" #include #include #include #include #include #include #include #include "util.h" static int __glutWindow = 1; extern struct MiniGLIFace *IMiniGL; extern struct IntuitionIFace *IIntuition; extern struct TimerIFace *__ITimer; extern struct KeymapIFace *__IKeymap; /* From glut_gamemode.c */ void glut_GLUTLeaveGameMode(struct GlutIFace *Self); TimerHook* timerhook_new(struct MsgPort *timerPort); void timerhook_delete(TimerHook *timerHook); char *mystrdup(char *other) { char *c = other; int len = 0; char *copy; if (!other) { return 0; } while (other && *c) { len++; c++; } copy = AllocVecInternal(len+1, MEMF_ANY); while (!copy) { return 0; } c = copy; while (*other) { *c++ = *other++; } *c++ = 0; return copy; } void glut_GLUTExit(struct GlutIFace *Self) { GLUTcontext ctx = (GLUTcontext)GET_INSTANCE(Self); if (ctx->gameModeData.gameModeActive) { glut_GLUTLeaveGameMode(Self); } if (ctx->__glutContext) { ctx->__glutContext->DeleteContext(); ctx->__glutContext = 0; } FreeVecInternalCheckAndClear((void**)&ctx->warpPointerEvent); if (ctx->warpPointerIOReq) { IExec->CloseDevice((struct IORequest *)ctx->warpPointerIOReq); DeleteIORequestInternal((struct IORequest *)ctx->warpPointerIOReq); ctx->warpPointerIOReq = NULL; } if (ctx->warpPointerMP) { DeleteMsgPortInternal(ctx->warpPointerMP); ctx->warpPointerMP = NULL; } TimerHook *timerHook = (TimerHook*)IExec->RemTail((struct List*) &(ctx->freeTimerHookList)); while (timerHook) { timerhook_delete(timerHook); timerHook = (TimerHook*)IExec->RemTail((struct List*) &(ctx->freeTimerHookList)); } timerHook = (TimerHook*)IExec->RemTail((struct List*) &(ctx->activeTimerHookList)); while (timerHook) { timerhook_delete(timerHook); timerHook = (TimerHook*)IExec->RemTail((struct List*) &(ctx->activeTimerHookList)); } } void glut_GLUTInit(struct GlutIFace *Self, int *argc, char **argv) { GLUTcontext ctx = (GLUTcontext)GET_INSTANCE(Self); __ITimer->GetSysTime(&ctx->__glutStartTime); ctx->__glutWindowWidth = 300; ctx->__glutWindowHeight = 300; ctx->__glutWindowX = 10; ctx->__glutWindowY = 10; ctx->__glutDisplayMode = GLUT_RGBA|GLUT_SINGLE; ctx->__glutContext = 0; ctx->ignoreKeyRepeat = GL_FALSE; ctx->keyRepeatMode = GLUT_KEY_REPEAT_ON; ctx->gameModeData.gameModeActive = GL_FALSE; ctx->gameModeSize.X = 640; ctx->gameModeSize.Y = 480; ctx->gameModeDepth = 16; ctx->gameModeRefresh = 72; ctx->modifiers = MODIFIERS_INVALID; ctx->actionOnWindowClose = GLUT_ACTION_GLUTMAINLOOP_RETURNS; ctx->warpPointerMP = NULL; ctx->warpPointerIOReq = NULL; ctx->warpPointerEvent = NULL; struct EClockVal eClkVal; ULONG eFreq = __ITimer->ReadEClock(&eClkVal); // 49995000 ctx->ticksPerMSec = eFreq / 1000.0; // 49995 } void glut_GLUTInitWindowSize(struct GlutIFace *Self, int width, int height) { GLUTcontext ctx = (GLUTcontext)GET_INSTANCE(Self); ctx->__glutWindowWidth = width; ctx->__glutWindowHeight = height; } void glut_GLUTInitWindowPosition(struct GlutIFace *Self, int x, int y) { GLUTcontext ctx = (GLUTcontext)GET_INSTANCE(Self); ctx->__glutWindowX = x; ctx->__glutWindowY = y; } void glut_GLUTInitDisplayMode(struct GlutIFace *Self, unsigned int mode) { GLUTcontext ctx = (GLUTcontext)GET_INSTANCE(Self); ctx->__glutDisplayMode = mode; } int glut_GLUTCreateWindow(struct GlutIFace *Self, const char *name) { GLUTcontext ctx = (GLUTcontext)GET_INSTANCE(Self); struct Window *window; GLcontext context; ctx->__glutContext = IMiniGL->CreateContextTags( MGLCC_Width, ctx->__glutWindowWidth, MGLCC_Height, ctx->__glutWindowHeight, MGLCC_WindowLeft, ctx->__glutWindowX, MGLCC_WindowTop, ctx->__glutWindowY, MGLCC_Windowed, TRUE, MGLCC_Buffers, ctx->__glutDisplayMode & GLUT_DOUBLE ? 2 : 1, MGLCC_PixelDepth, 16, MGLCC_CloseGadget, TRUE, MGLCC_SizeGadget, TRUE, MGLCC_StencilBuffer, ctx->__glutDisplayMode & GLUT_STENCIL ? TRUE : FALSE, TAG_DONE ); if (!ctx->__glutContext) { Self->GLUTExit(); return -1; } dprintf("Window created\n"); context = (GLcontext)GET_INSTANCE(ctx->__glutContext); ctx->glctx = context; dprintf("Context = %p, if = %p\n", context, ctx->__glutContext); window = (struct Window *)ctx->__glutContext->GetWindowHandle(); dprintf("Window handle = %p\n", window); dprintf("Setting smart lock mode\n"); ctx->__glutContext->LockMode(MGL_LOCK_SMART); IIntuition->SetWindowTitles(window, name, name); dprintf("Setting up a redisplay event\n"); ctx->GlutEvent = GLUTEVENT_REDISPLAY; ctx->IconName = 0; ctx->GlutSingle = ctx->__glutDisplayMode & GLUT_DOUBLE ? GL_FALSE : GL_TRUE; ctx->GlutW = ctx->__glutWindowWidth; ctx->GlutH = ctx->__glutWindowHeight; dprintf("Done\n"); return __glutWindow++; } /* FIXME: Implement * glutCreateSubWindow * glutSetWindow * glutGetWindow */ void glut_GLUTDestroyWindow(struct GlutIFace *Self, int window) { GLUTcontext ctx = (GLUTcontext)GET_INSTANCE(Self); /* FIXME: window id is ignored */ if (window == 1) { ctx->__glutContext->DeleteContext(); ctx->__glutContext = NULL; } } void glut_GLUTPostRedisplay(struct GlutIFace *Self) { GLUTcontext ctx = (GLUTcontext)GET_INSTANCE(Self); ctx->GlutEvent |= GLUTEVENT_REDISPLAY; } void glut_GLUTSwapBuffers(struct GlutIFace *Self) { GLUTcontext ctx = (GLUTcontext)GET_INSTANCE(Self); ctx->__glutContext->SwitchDisplay(); } void glut_GLUTPositionWindow(struct GlutIFace *Self, int x, int y) { GLUTcontext ctx = (GLUTcontext)GET_INSTANCE(Self); ctx->newX = x; ctx->newY = y; ctx->GlutEvent |= GLUTEVENT_REPOSITION; } void glut_GLUTReshapeWindow(struct GlutIFace *Self, int width, int height) { GLUTcontext ctx = (GLUTcontext)GET_INSTANCE(Self); ctx->newW = width; ctx->newH = height; ctx->GlutEvent |= GLUTEVENT_RESHAPE; } void glut_GLUTFullScreen(struct GlutIFace *Self) { GLUTcontext ctx = (GLUTcontext)GET_INSTANCE(Self); ctx->GlutEvent |= GLUTEVENT_FULLSCREEN; } void glut_GLUTPushWindow(struct GlutIFace *Self) { GLUTcontext ctx = (GLUTcontext)GET_INSTANCE(Self); ctx->GlutEvent |= GLUTEVENT_PUSHWINDOW; ctx->GlutEvent &= ~GLUTEVENT_POPWINDOW; } void glut_GLUTPopWindow(struct GlutIFace *Self) { GLUTcontext ctx = (GLUTcontext)GET_INSTANCE(Self); ctx->GlutEvent |= GLUTEVENT_POPWINDOW; ctx->GlutEvent &= ~GLUTEVENT_PUSHWINDOW; } void glut_GLUTShowWindow(struct GlutIFace *Self) { GLUTcontext ctx = (GLUTcontext)GET_INSTANCE(Self); ctx->GlutEvent |= GLUTEVENT_SHOWWINDOW; ctx->GlutEvent &= ~GLUTEVENT_HIDEWINDOW; } void glut_GLUTHideWindow(struct GlutIFace *Self) { GLUTcontext ctx = (GLUTcontext)GET_INSTANCE(Self); ctx->GlutEvent |= GLUTEVENT_HIDEWINDOW; ctx->GlutEvent &= ~GLUTEVENT_SHOWWINDOW; } void glut_GLUTIconifyWindow(struct GlutIFace *Self) { GLUTcontext ctx = (GLUTcontext)GET_INSTANCE(Self); ctx->GlutEvent |= GLUTEVENT_ICONIFY; } void glut_GLUTSetWindowTitle(struct GlutIFace *Self, char *name) { GLUTcontext ctx = (GLUTcontext)GET_INSTANCE(Self); struct Window *window = (struct Window *)ctx->__glutContext->GetWindowHandle(); IIntuition->SetWindowTitles(window, name, name); } void glut_GLUTSetIconTitle(struct GlutIFace *Self, char *name) { GLUTcontext ctx = (GLUTcontext)GET_INSTANCE(Self); if (ctx->IconName) FreeVecInternal(ctx->IconName); ctx->IconName = mystrdup(name); } /* FIXME: Implement glutSetCursor */ /* FIXME: Implement Menus */ void glut_GLUTWarpPointer(struct GlutIFace *Self, int x, int y ) { GLUTcontext ctx = (GLUTcontext)GET_INSTANCE(Self); // Initialize fields if necessary if (!ctx->warpPointerMP) { ctx->warpPointerMP = CreateMsgPortInternal(); if (!ctx->warpPointerMP) { dprintf("Error: Could not create a message port\n"); return; } } if (!ctx->warpPointerEvent) { // We're using a single memory allocation for both the event and the pixel-pointer ctx->warpPointerEvent = AllocVecInternal(sizeof(struct InputEvent) + sizeof(struct IEPointerPixel),MEMF_PUBLIC); if (!ctx->warpPointerEvent) { dprintf("Error: Could not allocate memory for this operation\n"); return; } ctx->warpPointerEvent->ie_EventAddress = (APTR)ctx->warpPointerEvent + sizeof(struct InputEvent); ctx->warpPointerEvent->ie_NextEvent = NULL; ctx->warpPointerEvent->ie_Class = IECLASS_NEWPOINTERPOS; ctx->warpPointerEvent->ie_SubClass = IESUBCLASS_PIXEL; ctx->warpPointerEvent->ie_Code = IECODE_NOBUTTON; ctx->warpPointerEvent->ie_Qualifier = 0; } if (!ctx->warpPointerIOReq) { // Open the input device and initialize the I/O request ctx->warpPointerIOReq = (struct IOStdReq*)CreateIORequestInternal(ctx->warpPointerMP,sizeof(struct IOStdReq)); if (!ctx->warpPointerIOReq) { dprintf("Error: Could not create IORequest.\n"); return; } if (IExec->OpenDevice("input.device",0, (struct IORequest *)ctx->warpPointerIOReq, 0) != 0) { DeleteIORequestInternal((struct IORequest*)ctx->warpPointerIOReq); ctx->warpPointerIOReq = NULL; dprintf("Error: Could not open input device.\n"); return; } ctx->warpPointerIOReq->io_Data = (APTR)ctx->warpPointerEvent; ctx->warpPointerIOReq->io_Length = sizeof(struct InputEvent); ctx->warpPointerIOReq->io_Command = IND_WRITEEVENT; } // Get the necessary information struct IEPointerPixel *pixel = ctx->warpPointerEvent->ie_EventAddress; struct Window *window = (struct Window *)ctx->__glutContext->GetWindowHandle(); LONG left, top; IIntuition->GetWindowAttrs(window, WA_Left, &left, WA_Top, &top, TAG_END); pixel->iepp_Screen=(struct Screen *)window->WScreen; pixel->iepp_Position.X = left + window->BorderLeft + x; pixel->iepp_Position.Y = top + window->BorderTop + y; // Execute! IExec->DoIO((struct IORequest *)ctx->warpPointerIOReq); } void glut_GLUTSpaceballMotionFunc(struct GlutIFace *Self, void (* callback)( int, int, int ) ) { // FIXME: this is not supported yet dprintf("unsupported callback\n"); } void glut_GLUTSpaceballRotateFunc(struct GlutIFace *Self, void (* callback)( int, int, int ) ) { // FIXME: this is not supported yet dprintf("unsupported callback\n"); } void glut_GLUTSpaceballButtonFunc(struct GlutIFace *Self, void (* callback)( int, int ) ) { // FIXME: this is not supported yet dprintf("unsupported callback\n"); } void glut_GLUTButtonBoxFunc(struct GlutIFace *Self, void (* callback)( int, int ) ) { // FIXME: this is not supported yet dprintf("unsupported callback\n"); } void glut_GLUTDialsFunc(struct GlutIFace *Self, void (* callback)( int, int ) ) { // FIXME: this is not supported yet dprintf("unsupported callback\n"); } void glut_GLUTTabletMotionFunc(struct GlutIFace *Self, void (* callback)( int, int ) ) { // FIXME: this is not supported yet dprintf("unsupported callback\n"); } void glut_GLUTTabletButtonFunc(struct GlutIFace *Self, void (* callback)( int, int, int, int ) ) { // FIXME: this is not supported yet dprintf("unsupported callback\n"); } void glut_GLUTOverlayDisplayFunc(struct GlutIFace *Self, void (* callback)( void ) ) { // Overlay is not actually supported dprintf("Overlay is not supported\n"); } void glut_GLUTJoystickFunc(struct GlutIFace *Self, void (* callback)( unsigned int, int, int, int ), int pollInterval ) { // FIXME: this is not supported yet dprintf("unsupported callback\n"); } void glut_GLUTDisplayFunc(struct GlutIFace *Self, void (*func)()) { GLUTcontext ctx = (GLUTcontext)GET_INSTANCE(Self); ctx->glutDisplayFunc = func; } void glut_GLUTReshapeFunc(struct GlutIFace *Self, void (*func)(int width, int height)) { GLUTcontext ctx = (GLUTcontext)GET_INSTANCE(Self); ctx->glutReshapeFunc = func; } void glut_GLUTKeyboardFunc(struct GlutIFace *Self, void (*func)(unsigned char key, int x, int y)) { GLUTcontext ctx = (GLUTcontext)GET_INSTANCE(Self); ctx->glutKeyboardFunc = func; } void glut_GLUTKeyboardUpFunc(struct GlutIFace *Self, void (*func)(unsigned char key, int x, int y)) { GLUTcontext ctx = (GLUTcontext)GET_INSTANCE(Self); ctx->glutKeyboardUpFunc = func; } void glut_GLUTIgnoreKeyRepeat(struct GlutIFace *Self, int ignore) { GLUTcontext ctx = (GLUTcontext)GET_INSTANCE(Self); ctx->ignoreKeyRepeat = ignore; } void glut_GLUTMouseFunc(struct GlutIFace *Self, void (*func)(int button, int state, int x, int y)) { GLUTcontext ctx = (GLUTcontext)GET_INSTANCE(Self); ctx->glutMouseFunc = func; } void glut_GLUTMotionFunc(struct GlutIFace *Self, void (*func)(int x, int y)) { GLUTcontext ctx = (GLUTcontext)GET_INSTANCE(Self); ctx->glutMotionFunc = func; } void glut_GLUTPassiveMotionFunc(struct GlutIFace *Self, void (*func)(int x, int y)) { GLUTcontext ctx = (GLUTcontext)GET_INSTANCE(Self); ctx->glutPassiveMotionFunc = func; } void glut_GLUTVisibilityFunc(struct GlutIFace *Self, void (*func)(int state)) { GLUTcontext ctx = (GLUTcontext)GET_INSTANCE(Self); ctx->glutVisibilityFunc = func; } void glut_GLUTEntryFunc(struct GlutIFace *Self, void (*func)(int state)) { GLUTcontext ctx = (GLUTcontext)GET_INSTANCE(Self); ctx->glutEntryFunc = func; } void glut_GLUTSpecialFunc(struct GlutIFace *Self, void (*func)(int key, int x, int y)) { GLUTcontext ctx = (GLUTcontext)GET_INSTANCE(Self); ctx->glutSpecialFunc = func; } void glut_GLUTSpecialUpFunc(struct GlutIFace *Self, void (*func)(int key, int x, int y)) { GLUTcontext ctx = (GLUTcontext)GET_INSTANCE(Self); ctx->glutSpecialUpFunc = func; } void glut_GLUTIdleFunc(struct GlutIFace *Self, void (*func)(void)) { GLUTcontext ctx = (GLUTcontext)GET_INSTANCE(Self); ctx->glutIdleFunc = func; } void glut_GLUTTimerFunc(struct GlutIFace *Self, unsigned int msecs, void (*func)(int value), int value) { GLUTcontext ctx = (GLUTcontext)GET_INSTANCE(Self); if (!ctx->timerHookPort) { ctx->timerHookPort = CreateMsgPortInternal(); if (!ctx->timerHookPort) { dprintf("Error: Could not allocate a message port\n"); return; } } TimerHook *timerHook = (TimerHook*) IExec->RemTail((struct List*) &(ctx->freeTimerHookList)); if (!timerHook) { timerHook = timerhook_new(ctx->timerHookPort); if (!timerHook) { dprintf("Error: Could not allocate a new timer request object\n"); return; } } uint64 ticks = msecs * ctx->ticksPerMSec; // Note, this is actually the e-clock so Seconds and Microseconds mean ev_hi & ev_lo timerHook->timerIO->Time.Seconds = ticks >> 32; timerHook->timerIO->Time.Microseconds = ticks & 0x00000000FFFFFFFF; timerHook->func = func; timerHook->value = value; IExec->SendIO((struct IORequest*)timerHook->timerIO); IExec->AddHead((struct List*)&(ctx->activeTimerHookList), (struct Node*)timerHook); } TimerHook* timerhook_new(struct MsgPort *timerPort) { TimerHook *timerHook = AllocVecInternal(sizeof(TimerHook), MEMF_PUBLIC | MEMF_CLEAR); struct TimeRequest* timerIO = (struct TimeRequest *)CreateIORequestInternal(timerPort, sizeof(struct TimeRequest)); if (!timerIO) { return NULL; } timerIO->Request.io_Command = TR_ADDREQUEST; timerHook->timerIO = timerIO; BYTE error = IExec->OpenDevice(TIMERNAME, UNIT_ECLOCK,(struct IORequest *) timerIO, 0L); if (error != 0 ){ timerhook_delete(timerHook); return NULL; } return timerHook; } void timerhook_delete(TimerHook *timerHook) { if (!timerHook) { return; } struct TimeRequest *timerIO = timerHook->timerIO; if (timerIO){ if (timerIO->Request.io_Command != NT_MESSAGE && IExec->CheckIO((struct IORequest*)timerIO) == NULL) { IExec->AbortIO((struct IORequest*)timerIO); IExec->WaitIO((struct IORequest*)timerIO); } IExec->CloseDevice((struct IORequest *) timerIO); DeleteIORequestInternal((struct IORequest *) timerIO); } FreeVecInternal(timerHook); } void glut_GLUTCloseFunc(struct GlutIFace *Self, void (*func)(void)) { GLUTcontext ctx = (GLUTcontext)GET_INSTANCE(Self); ctx->glutCloseFunc = func; } static uint32 __glutCheckWindowBox(struct Window *win) { if ( win->MouseX > win->BorderLeft && win->MouseX < win->Width - win->BorderRight && win->MouseY > win->BorderTop && win->MouseY < win->Height - win->BorderBottom ) { return 1; } return 0; } void glut_GLUTMainLoop(struct GlutIFace *Self) { struct IntuiMessage *imsg; struct Message *timerMsg; struct Window *window; BOOL idle = FALSE; uint32 buttons = 0; uint32 in = 0, oldin = 0; BOOL visible = TRUE; UWORD qualifier; GLUTcontext ctx = (GLUTcontext)GET_INSTANCE(Self); window = (struct Window *)ctx->__glutContext->GetWindowHandle(); IIntuition->ModifyIDCMP( window, IDCMP_RAWKEY|IDCMP_MOUSEMOVE|IDCMP_MOUSEBUTTONS|IDCMP_NEWSIZE|IDCMP_CLOSEWINDOW ); oldin = in = __glutCheckWindowBox(window); /* Do an initial reshape */ if (ctx->glutReshapeFunc) { ctx->glutReshapeFunc(ctx->GlutW, ctx->GlutH); } else { ctx->__glutContext->GLViewport(0, 0, ctx->GlutW, ctx->GlutH); } /* Do an initial visibiliy */ if (ctx->glutVisibilityFunc) { ctx->glutVisibilityFunc(GLUT_VISIBLE); } ctx->running = GL_TRUE; while (ctx->running == GL_TRUE) { idle = TRUE; window = (struct Window *)ctx->__glutContext->GetWindowHandle(); if (!ctx->glutIdleFunc && !ctx->GlutEvent) { // There's no point in busy waiting when there is no idle function to fill the time ULONG signals = (1 << ctx->timerHookPort->mp_SigBit) | (1 << window->UserPort->mp_SigBit); IExec->Wait(signals); } while ((imsg = (struct IntuiMessage *)IExec->GetMsg(window->UserPort))) { uint32 Class = imsg->Class; uint16 Code = imsg->Code; int16 MouseX = imsg->MouseX - window->BorderLeft; int16 MouseY = imsg->MouseY - window->BorderTop; idle = FALSE; IExec->ReplyMsg((struct Message *)imsg); /* Dispatch */ switch (Class) { case IDCMP_CLOSEWINDOW: { if (ctx->glutCloseFunc) { ctx->glutCloseFunc(); } else { switch (ctx->actionOnWindowClose) { case GLUT_ACTION_EXIT: exit(0); break; case GLUT_ACTION_GLUTMAINLOOP_RETURNS: ctx->running = GL_FALSE; break; case GLUT_ACTION_CONTINUE_EXECUTION: break; default: if (ctx->glutKeyboardFunc) { ctx->glutKeyboardFunc(27, MouseX, MouseY); } break; } break; } } case IDCMP_RAWKEY: qualifier = imsg->Qualifier; if ( (ctx->ignoreKeyRepeat || ctx->keyRepeatMode == GLUT_KEY_REPEAT_OFF) && (qualifier & IEQUALIFIER_REPEAT) ) { break; } ctx->modifiers = 0; if (qualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT)) { ctx->modifiers |= GLUT_ACTIVE_SHIFT; } if (qualifier & IEQUALIFIER_CONTROL) { ctx->modifiers |= GLUT_ACTIVE_CTRL; } if (qualifier & (IEQUALIFIER_LALT | IEQUALIFIER_RALT)) { ctx->modifiers |= GLUT_ACTIVE_ALT; } if (ctx->glutKeyboardFunc || ctx->glutKeyboardUpFunc) { struct InputEvent inputEvent; TEXT buffer[8]; WORD numChars; inputEvent.ie_Class = IECLASS_RAWKEY; inputEvent.ie_SubClass = 0; inputEvent.ie_Code = (Code & ~IECODE_UP_PREFIX); inputEvent.ie_Qualifier = qualifier; inputEvent.ie_EventAddress = (APTR *) *((ULONG *)imsg->IAddress); numChars = __IKeymap->MapRawKey(&inputEvent, buffer, 8, NULL); // want "vanilla" keys only if (numChars == 1) { if (Code & IECODE_UP_PREFIX) { if (ctx->glutKeyboardUpFunc) { ctx->glutKeyboardUpFunc((unsigned char)buffer[0], MouseX, MouseY); } } else { if (ctx->glutKeyboardFunc) { ctx->glutKeyboardFunc((unsigned char)buffer[0], MouseX, MouseY); } } ctx->modifiers = MODIFIERS_INVALID; break; } } if (ctx->glutSpecialFunc || ctx->glutSpecialUpFunc) { int key = -1; switch (Code & ~IECODE_UP_PREFIX) { case 0x50: key = GLUT_KEY_F1; break; case 0x51: key = GLUT_KEY_F2; break; case 0x52: key = GLUT_KEY_F3; break; case 0x53: key = GLUT_KEY_F4; break; case 0x54: key = GLUT_KEY_F5; break; case 0x55: key = GLUT_KEY_F6; break; case 0x56: key = GLUT_KEY_F7; break; case 0x57: key = GLUT_KEY_F8; break; case 0x58: key = GLUT_KEY_F9; break; case 0x59: key = GLUT_KEY_F10; break; case 0x4b: key = GLUT_KEY_F11; break; case 0x6f: key = GLUT_KEY_F12; break; case 0x4f: key = GLUT_KEY_LEFT; break; case 0x4c: key = GLUT_KEY_UP; break; case 0x4e: key = GLUT_KEY_RIGHT; break; case 0x4d: key = GLUT_KEY_DOWN; break; case 0x48: key = GLUT_KEY_PAGE_UP; break; case 0x49: key = GLUT_KEY_PAGE_DOWN;break; case 0x70: key = GLUT_KEY_HOME; break; case 0x71: key = GLUT_KEY_END; break; case 0x47: key = GLUT_KEY_INSERT; break; } if (key != -1) { if (Code & IECODE_UP_PREFIX) { if (ctx->glutSpecialUpFunc) { ctx->glutSpecialUpFunc(key, MouseX, MouseY); } } else { if (ctx->glutSpecialFunc) { ctx->glutSpecialFunc(key, MouseX, MouseY); } } } } ctx->modifiers = MODIFIERS_INVALID; break; case IDCMP_MOUSEBUTTONS: switch (Code) { case SELECTDOWN: if (ctx->glutMouseFunc) { ctx->glutMouseFunc(GLUT_LEFT_BUTTON, GLUT_DOWN, MouseX, MouseY); } buttons |= 1; break; case SELECTUP: if (ctx->glutMouseFunc) { ctx->glutMouseFunc(GLUT_LEFT_BUTTON, GLUT_UP, MouseX, MouseY); } buttons &= ~1; break; case MENUDOWN: if (ctx->glutMouseFunc) { ctx->glutMouseFunc(GLUT_RIGHT_BUTTON, GLUT_DOWN, MouseX, MouseY); } buttons |= 2; break; case MENUUP: if (ctx->glutMouseFunc) { ctx->glutMouseFunc(GLUT_RIGHT_BUTTON, GLUT_UP, MouseX, MouseY); } buttons &= ~2; break; case MIDDLEDOWN: if (ctx->glutMouseFunc) { ctx->glutMouseFunc(GLUT_MIDDLE_BUTTON, GLUT_DOWN, MouseX, MouseY); } buttons |= 4; break; case MIDDLEUP: if (ctx->glutMouseFunc) { ctx->glutMouseFunc(GLUT_MIDDLE_BUTTON, GLUT_UP, MouseX, MouseY); } buttons &= ~4; break; } break; case IDCMP_MOUSEMOVE: /* Check out-of-bounds */ in = __glutCheckWindowBox(window); if (in != oldin) { /* We either left or entered */ if (in && ctx->glutEntryFunc) { ctx->glutEntryFunc(GLUT_ENTERED); } else if (!in && ctx->glutEntryFunc) { ctx->glutEntryFunc(GLUT_LEFT); } } oldin = in; if (in && buttons && ctx->glutMotionFunc) { ctx->glutMotionFunc(MouseX, MouseY); } if (in && !buttons && ctx->glutPassiveMotionFunc) { ctx->glutPassiveMotionFunc(MouseX, MouseY); } break; case IDCMP_NEWSIZE: ctx->newW = window->Width - window->BorderLeft - window->BorderRight; ctx->newH = window->Height - window->BorderTop - window->BorderBottom; ctx->GlutEvent |= GLUTEVENT_RESHAPE; break; case IDCMP_REFRESHWINDOW: // Clear the refresh event IIntuition->BeginRefresh(window); IIntuition->EndRefresh(window, TRUE); // Trigger a redraw ctx->GlutEvent |= GLUTEVENT_REDISPLAY; break; } /* switch (Class) */ } /* while (imsg = ...) */ /* Handle outstanding events */ if (ctx->GlutEvent) { if (ctx->GlutEvent & GLUTEVENT_RESHAPE) { ctx->GlutEvent &= ~GLUTEVENT_RESHAPE; ctx->GlutEvent |= GLUTEVENT_REDISPLAY; if (ctx->__glutContext->SetDisplayMode(GL_TRUE, ctx->newW, ctx->newH, 0) == 0) { dprintf("Set display mode failed.\n"); displayWarningReq( window, NULL, "Fatal Error", "Error: Out of graphics memory.\n" "This program will now close", REQIMAGE_ERROR ); if (ctx->actionOnWindowClose == GLUT_ACTION_GLUTMAINLOOP_RETURNS) { return; } else { exit(10); } } window = (struct Window *)ctx->__glutContext->GetWindowHandle(); if (ctx->glutReshapeFunc) { ctx->glutReshapeFunc(ctx->newW, ctx->newH); } else { ctx->__glutContext->GLViewport(0, 0, ctx->newW, ctx->newH); } } if (ctx->GlutEvent & GLUTEVENT_REPOSITION) { ctx->GlutEvent &= ~GLUTEVENT_REPOSITION; IIntuition->MoveWindow(window, ctx->newX - window->LeftEdge, ctx->newY - window->TopEdge); } if (ctx->GlutEvent & GLUTEVENT_FULLSCREEN) { ctx->GlutEvent &= ~GLUTEVENT_FULLSCREEN; ctx->GlutEvent |= GLUTEVENT_REDISPLAY; ctx->newW = window->Width - window->BorderLeft - window->BorderRight; ctx->newH = window->Height - window->BorderTop - window->BorderBottom; if (ctx->__glutContext->SetDisplayMode(GL_FALSE, ctx->newW, ctx->newH, 0) == 0) { dprintf("Set display mode failed.\n"); displayWarningReq( window, NULL, "Fatal Error", "Error: Out of graphics memory.\n" "This program will now close", REQIMAGE_ERROR ); if (ctx->actionOnWindowClose == GLUT_ACTION_GLUTMAINLOOP_RETURNS) { return; } else { exit(10); } } window = (struct Window *)ctx->__glutContext->GetWindowHandle(); ctx->newW = window->Width - window->BorderLeft - window->BorderRight; ctx->newH = window->Height - window->BorderTop - window->BorderBottom; IExec->DebugPrintF("newW: %d newH: %d\n", ctx->newW, ctx->newH); if (ctx->glutReshapeFunc) { ctx->glutReshapeFunc(ctx->newW, ctx->newH); } else { ctx->__glutContext->GLViewport(0, 0, ctx->newW, ctx->newH); } } if (ctx->GlutEvent & GLUTEVENT_POPWINDOW) { ctx->GlutEvent &= ~GLUTEVENT_POPWINDOW; IIntuition->WindowToFront(window); } if (ctx->GlutEvent & GLUTEVENT_PUSHWINDOW) { ctx->GlutEvent &= ~GLUTEVENT_PUSHWINDOW; IIntuition->WindowToBack(window); } if (ctx->GlutEvent & GLUTEVENT_SHOWWINDOW) { ctx->GlutEvent &= ~GLUTEVENT_SHOWWINDOW; IIntuition->ShowWindow(window, WINDOW_FRONTMOST); visible = TRUE; } if (ctx->GlutEvent & GLUTEVENT_HIDEWINDOW) { ctx->GlutEvent &= ~GLUTEVENT_HIDEWINDOW; IIntuition->HideWindow(window); visible = FALSE; } if (ctx->GlutEvent & GLUTEVENT_ICONIFY) { ctx->GlutEvent &= ~GLUTEVENT_ICONIFY; /* FIXME: Implement iconification */ } if (ctx->GlutEvent & GLUTEVENT_REDISPLAY) { ctx->GlutEvent &= ~GLUTEVENT_REDISPLAY; if (ctx->glutDisplayFunc && visible) { ctx->glutDisplayFunc(); } /* When a single buffer is used, make the blit implicitly */ if (ctx->GlutSingle) { ctx->__glutContext->SwitchDisplay(); } } } /* if (ctx->GlutEvent) */ /* Check for timer hook events */ if (ctx->timerHookPort) { while ((timerMsg = IExec->GetMsg(ctx->timerHookPort))) { idle = FALSE; // Find the TimerHook TimerHook *currTimerHook = (TimerHook*)ctx->activeTimerHookList.mlh_Head; TimerHook *timerHook = NULL; while (currTimerHook->node.mln_Succ) { if (currTimerHook->timerIO == (struct TimeRequest*)timerMsg) { timerHook = currTimerHook; break; } currTimerHook = (TimerHook*)currTimerHook->node.mln_Succ; } if (timerHook) { // execute the hook timerHook->func(timerHook->value); // Move the TimerHook object from the active, to the free list IExec->Remove((struct Node*)timerHook); IExec->AddTail((struct List*)&(ctx->freeTimerHookList), (struct Node*) timerHook); } else { dprintf( "Internal Error: a timer hook event occurred, but the associated " "timer hook was not found\n" ); } } } if (idle && ctx->glutIdleFunc) { ctx->glutIdleFunc(); } } /* while (1) */ }