void __glutFinishMenu(Window win, int x, int y) { unmapMenu(__glutMappedMenu); /* XXX Put in a GdiFlush just in case. Probably unnecessary. -mjk */ GdiFlush(); if (__glutMenuStatusFunc) { __glutSetWindow(__glutMenuWindow); __glutSetMenu(__glutMappedMenu); /* Setting __glutMappedMenu to NULL permits operations that change menus or destroy the menu window again. */ __glutMappedMenu = NULL; __glutMenuStatusFunc(GLUT_MENU_NOT_IN_USE, x, y); } /* Setting __glutMappedMenu to NULL permits operations that change menus or destroy the menu window again. */ __glutMappedMenu = NULL; /* If an item is selected and it is not a submenu trigger, generate menu callback. */ if (__glutItemSelected && !__glutItemSelected->isTrigger) { __glutSetWindow(__glutMenuWindow); /* When menu callback is triggered, current menu should be set to the callback menu. */ __glutSetMenu(__glutItemSelected->menu); __glutItemSelected->menu->select(__glutItemSelected->value); } __glutMenuWindow = NULL; }
int GLUTAPIENTRY glutEnterGameMode( void ) { DFBDisplayLayerConfig prev, cur; glutInit( NULL, NULL ); primary->GetConfiguration( primary, &prev ); primary->SetCooperativeLevel( primary, DLSCL_EXCLUSIVE ); if (g_game) __glutDestroyWindow( g_game ); g_game = __glutCreateWindow( GL_TRUE ); if (!g_game) return 0; __glutSetWindow( g_game ); g_game->cursor = GLUT_CURSOR_NONE; primary->GetConfiguration( primary, &cur ); g_display_changed = (cur.width != prev.width || cur.height != prev.height || cur.pixelformat != prev.pixelformat); return g_game->id; }
void GLUTAPIENTRY glutMainLoop( void ) { __glutAssert( events != NULL ); __glutHandleWindows(); while (GL_TRUE) { DFBEvent evt, prev; g_idle = GL_TRUE; __glutHandleTimers(); prev.clazz = DFEC_NONE; while (events->GetEvent( events, &evt ) == DFB_OK) { g_idle = GL_FALSE; switch (evt.clazz) { case DFEC_WINDOW: if (prev.clazz == DFEC_WINDOW) __glutWindowEvent( &evt.window, &prev.window ); else __glutWindowEvent( &evt.window, NULL ); break; case DFEC_INPUT: if (prev.clazz == DFEC_INPUT) __glutInputEvent( &evt.input, &prev.input ); else __glutInputEvent( &evt.input, NULL ); break; default: __glutWarning( "unexpected event class %d!\n", evt.clazz ); break; } prev = evt; __glutHandleTimers(); } __glutHandleWindows(); if (g_idle) { if (idle_func) { idle_func(); } else { int msec; __glutSetWindow( NULL ); if (__glutGetTimeout( &msec )) events->WaitForEventWithTimeout( events, msec/1000, msec%1000 ); else events->WaitForEvent( events ); } } } }
void __glutStartMenu(GLUTmenu * menu, GLUTwindow * window, int x, int y, int x_win, int y_win) { assert(__glutMappedMenu == NULL); __glutMappedMenu = menu; __glutMenuWindow = window; __glutItemSelected = NULL; if (__glutMenuStatusFunc) { __glutSetMenu(menu); __glutSetWindow(window); __glutMenuStatusFunc(GLUT_MENU_IN_USE, x_win, y_win); } mapMenu(menu, x, y); }
/* CENTRY */ void GLUTAPIENTRY glutSetWindow(int win) { GLUTwindow *window; if (win < 1 || win > __glutWindowListSize) { __glutWarning("glutSetWindow attempted on bogus window."); return; } window = __glutWindowList[win - 1]; if (!window) { __glutWarning("glutSetWindow attempted on bogus window."); return; } __glutSetWindow(window); }
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); } /* An unmap is only reported on a single window; its descendents need to know they are no longer visible. */ child = window->children; while (child) { markWindowHidden(child); child = child->siblings; } } }
/* ARGSUSED5 */ /* Only Win32 uses gameMode parameter. */ GLUTwindow * __glutCreateWindow(GLUTwindow * parent, int x, int y, int width, int height, int gameMode) { GLUTwindow *window; XSetWindowAttributes wa; unsigned long attribMask; int winnum; int i; #if defined(GLX_VERSION_1_1) && defined(GLX_SGIX_fbconfig) GLXFBConfigSGIX fbc; #else void *fbc; #endif #if defined(__OS2PM__) { extern HAB hab; /* PM anchor block handle */ CLASSINFO classinfo; if(!WinQueryClassInfo(hab,"GLUT", &classinfo) ) __glutOpenOS2Connection(NULL); } #elif defined(_WIN32) WNDCLASS wc; int style; if (!GetClassInfo(GetModuleHandle(NULL), "GLUT", &wc)) { __glutOpenWin32Connection(NULL); } #else if (!__glutDisplay) { __glutOpenXConnection(NULL); } #endif #ifndef __OS2PM__ if (__glutGameModeWindow) { __glutFatalError("cannot create windows in game mode."); } #endif winnum = getUnusedWindowSlot(); window = (GLUTwindow *) malloc(sizeof(GLUTwindow)); if (!window) { __glutFatalError("out of memory."); } window->num = winnum; #if defined(__OS2PM__) /* Add this new window to the window list. */ __glutWindowList[winnum] = window; window->shownState = -1; #endif #if !defined(_WIN32) && !defined(__OS2PM__) window->vis = __glutDetermineWindowVisual(&window->treatAsSingle, &window->visAlloced, (void**) &fbc); if (!window->vis) { __glutFatalError( "visual with necessary capabilities not found."); } __glutSetupColormap(window->vis, &window->colormap, &window->cmap); #endif window->eventMask = StructureNotifyMask | ExposureMask; attribMask = CWBackPixmap | CWBorderPixel | CWColormap | CWEventMask; wa.background_pixmap = None; wa.border_pixel = 0; wa.colormap = window->cmap; wa.event_mask = window->eventMask; if (parent) { if (parent->eventMask & GLUT_HACK_STOP_PROPAGATE_MASK) wa.event_mask |= GLUT_HACK_STOP_PROPAGATE_MASK; attribMask |= CWDontPropagate; wa.do_not_propagate_mask = parent->eventMask & GLUT_DONT_PROPAGATE_FILTER_MASK; } else { wa.do_not_propagate_mask = 0; } /* Stash width and height before Win32's __glutAdjustCoords possibly overwrites the values. */ window->width = width; window->height = height; window->forceReshape = True; window->ignoreKeyRepeat = False; #if defined(__OS2PM__) { ULONG flStyle=0; int ii; ERRORID erridErrorCode;/* last error id code */ extern HAB hab; /* PM anchor block handle */ if (parent) { flStyle = WS_CLIPCHILDREN|WS_VISIBLE; } else { if (gameMode) { /* Game mode window should be a WS_POPUP window to ensure that the taskbar is hidden by it. A standard WS_OVERLAPPEDWINDOW does not hide the task bar. */ flStyle = FCF_STANDARD | WS_MAXIMIZED; } else { /* A standard toplevel window with borders and such. */ flStyle = FCF_STANDARD | WS_CLIPCHILDREN; // flStyle = WS_OVERLAPPEDWINDOW; } } { HWND hwnd; /* Window */ ULONG ListBoxId; /* Window id */ /* (supplied by application) */ HWND hwndClient; /* handle to the client */ HWND hwndFrame; /* handle to the frame */ PFNWP GenericWndProc; FRAMECDATA fcd; RECTL rect; /* Boundary rectangle */ /************************************************/ // flCreate = (FCF_STANDARD) & ~FCF_TASKLIST; /**********************************/ if (parent) { window->frame = NULL; hwnd = WinCreateWindow(parent->win, /* Parent window */ "GLUTCHILD", /* Class name */ "", /* Window text */ flStyle, /* Window style */ x, y, /* Position (x,y) */ width, height, /* Size (width,height) */ parent->win, /* Owner window */ HWND_TOP, /* Sibling window */ 0, /* Window id */ NULL, /* Control data */ NULL); /* Pres parameters */ erridErrorCode = WinGetLastError(hab); window->win = hwnd; window->hdc = WinOpenWindowDC(window->win); window->hpsBuffer = hpsCurrent; rect.xLeft = x; rect.xRight = x+width; rect.yBottom = y; rect.yTop = y + height; /***** else parent *****************************/ } else { hwnd = WinCreateStdWindow(HWND_DESKTOP, 0, /* WS_VISIBLE frame-window style */ &flStyle, /* window style */ "GLUT", /* class name */ "GLUT",/* window title */ 0L, /* default client style */ NULLHANDLE, /* resource in executable file */ ID_WINDOW, /* resource id */ &hwndClient); /* receives client window handle */ erridErrorCode = WinGetLastError(hab); window->win = hwndClient; window->frame = hwnd; window->hdc = WinOpenWindowDC(window->win); window->hpsBuffer = hpsCurrent; /* converts a client window's boundaries into an equivalent frame rectangle */ rect.xLeft = x; rect.xRight = x+width; rect.yBottom = y; rect.yTop = y + height; /* calculate equivalent frame boundary from boundary data */ WinCalcFrameRect(window->frame, &rect, FALSE); } /***** endof if(parent) *****************************/ /* Must set the XHDC for fake glXChooseVisual & fake glXCreateContext & fake XAllocColorCells. */ XHDC = window->hdc; XHWND = window->win; window->vis = __glutDetermineWindowVisual(&window->treatAsSingle, &window->visAlloced, &fbc); if (!window->vis) { __glutFatalError( "pixel format with necessary capabilities not found."); } { int rc; rc = wglChoosePixelFormat(window->hdc, window->vis), // evglSetPixelFormat(2); /* int iPixelFormat 1 - doublebuffer/2 - single buffer ??*/ wglSetPixelFormat(window->hdc,rc,window->vis); } __glutSetupColormap(window->vis, &window->colormap, &window->cmap); window->ctx = glXCreateContext(window->hpsBuffer, window->vis, None, __glutTryDirect); WinSetWindowPos(hwnd, HWND_TOP,rect.xLeft,rect.yBottom, rect.xRight-rect.xLeft, rect.yTop-rect.yBottom, SWP_ACTIVATE | SWP_MOVE | SWP_SIZE | SWP_SHOW|SWP_ZORDER); /* flags*/ /* Make sure subwindows get a windowStatus callback. */ if (parent) WinPostMsg(parent->win, WM_ACTIVATE, 0, 0); } } #elif defined(_WIN32) __glutAdjustCoords(parent ? parent->win : NULL, &x, &y, &width, &height); if (parent) { style = WS_CHILD; } else { if (gameMode) { /* Game mode window should be a WS_POPUP window to ensure that the taskbar is hidden by it. A standard WS_OVERLAPPEDWINDOW does not hide the task bar. */ style = WS_POPUP | WS_MAXIMIZE; } else { /* A standard toplevel window with borders and such. */ style = WS_OVERLAPPEDWINDOW; } } window->win = CreateWindow("GLUT", "GLUT", WS_CLIPSIBLINGS | WS_CLIPCHILDREN | style, x, y, width, height, parent ? parent->win : __glutRoot, NULL, GetModuleHandle(NULL), 0); window->hdc = GetDC(window->win); /* Must set the XHDC for fake glXChooseVisual & fake glXCreateContext & fake XAllocColorCells. */ XHDC = window->hdc; window->vis = __glutDetermineWindowVisual(&window->treatAsSingle, &window->visAlloced, &fbc); if (!window->vis) { __glutFatalError( "pixel format with necessary capabilities not found."); } if (!SetPixelFormat(window->hdc, ChoosePixelFormat(window->hdc, window->vis), window->vis)) { __glutFatalError("SetPixelFormat failed during window create."); } __glutSetupColormap(window->vis, &window->colormap, &window->cmap); /* Make sure subwindows get a windowStatus callback. */ if (parent) { PostMessage(parent->win, WM_ACTIVATE, 0, 0); } window->renderDc = window->hdc; #else window->win = XCreateWindow(__glutDisplay, parent == NULL ? __glutRoot : parent->win, x, y, width, height, 0, window->vis->depth, InputOutput, window->vis->visual, attribMask, &wa); #endif window->renderWin = window->win; #if defined(GLX_VERSION_1_1) && defined(GLX_SGIX_fbconfig) if (fbc) { window->ctx = __glut_glXCreateContextWithConfigSGIX(__glutDisplay, fbc, GLX_RGBA_TYPE_SGIX, None, __glutTryDirect); } else #endif #if defined(__OS2PM__) // window->ctx = glXCreateContext(window->hpsBuffer, window->vis, // None, __glutTryDirect); #else window->ctx = glXCreateContext(__glutDisplay, window->vis, None, __glutTryDirect); #endif if (!window->ctx) { __glutFatalError( "failed to create OpenGL rendering context."); } window->renderCtx = window->ctx; #if !defined(_WIN32) && !defined(__OS2PM__) window->isDirect = glXIsDirect(__glutDisplay, window->ctx); if (__glutForceDirect) { if (!window->isDirect) __glutFatalError("direct rendering not possible."); } #endif window->parent = parent; if (parent) { window->siblings = parent->children; parent->children = window; } else { window->siblings = NULL; } window->overlay = NULL; window->children = NULL; window->display = __glutDefaultDisplay; window->reshape = __glutDefaultReshape; window->mouse = NULL; window->motion = NULL; window->passive = NULL; window->entry = NULL; window->keyboard = NULL; window->keyboardUp = NULL; window->windowStatus = NULL; window->visibility = NULL; window->special = NULL; window->specialUp = NULL; window->buttonBox = NULL; window->dials = NULL; window->spaceMotion = NULL; window->spaceRotate = NULL; window->spaceButton = NULL; window->tabletMotion = NULL; window->tabletButton = NULL; #ifdef _WIN32 window->joystick = NULL; window->joyPollInterval = 0; #endif #if defined(__OS2PM__) window->wm_command = NULL; #endif window->tabletPos[0] = -1; window->tabletPos[1] = -1; #if defined(__OS2PM__) if(window->shownState == -1) window->shownState = 0; window->visState = window->shownState; #else window->shownState = 0; window->visState = -1; /* not VisibilityUnobscured, VisibilityPartiallyObscured, or VisibilityFullyObscured */ #endif window->entryState = -1; /* not EnterNotify or LeaveNotify */ window->desiredConfMask = 0; window->buttonUses = 0; window->cursor = GLUT_CURSOR_INHERIT; /* Setup window to be mapped when glutMainLoop starts. */ window->workMask = GLUT_MAP_WORK; #ifdef _WIN32 if (gameMode) { /* When mapping a game mode window, just show the window. We have already created the game mode window with a maximize flag at creation time. Doing a ShowWindow(window->win, SW_SHOWNORMAL) would be wrong for a game mode window since it would unmaximize the window. */ window->desiredMapState = GameModeState; } else { window->desiredMapState = NormalState; } #else window->desiredMapState = NormalState; #endif window->prevWorkWin = __glutWindowWorkList; __glutWindowWorkList = window; /* Initially, no menus attached. */ for (i = 0; i < GLUT_MAX_MENUS; i++) { window->menu[i] = 0; } /* Add this new window to the window list. */ __glutWindowList[winnum] = window; /* Make the new window the current window. */ __glutSetWindow(window); __glutDetermineMesaSwapHackSupport(); if (window->treatAsSingle) { /* We do this because either the window really is single buffered (in which case this is redundant, but harmless, because this is the initial single-buffered context state); or we are treating a double buffered window as a single-buffered window because the system does not appear to export any suitable single- buffered visuals (in which the following are necessary). */ glDrawBuffer(GL_FRONT); glReadBuffer(GL_FRONT); } return window; }
static GLUTwindow * processWindowWorkList(GLUTwindow * window) { int workMask; if (window->prevWorkWin) { window->prevWorkWin = processWindowWorkList(window->prevWorkWin); } else { beforeEnd = &window->prevWorkWin; } /* Capture work mask for work that needs to be done to this window, then clear the window's work mask (excepting the dummy work bit, see below). Then, process the captured work mask. This allows callbacks in the processing the captured work mask to set the window's work mask for subsequent processing. */ workMask = window->workMask; assert((workMask & GLUT_DUMMY_WORK) == 0); /* Set the dummy work bit, clearing all other bits, to indicate that the window is currently on the window work list _and_ that the window's work mask is currently being processed. This convinces __glutPutOnWorkList that this window is on the work list still. */ window->workMask = GLUT_DUMMY_WORK; /* Optimization: most of the time, the work to do is a redisplay and not these other types of work. Check for the following cases as a group to before checking each one individually one by one. This saves about 25 MIPS instructions in the common redisplay only case. */ if (workMask & (GLUT_EVENT_MASK_WORK | GLUT_DEVICE_MASK_WORK | GLUT_CONFIGURE_WORK | GLUT_COLORMAP_WORK | GLUT_MAP_WORK)) { #if !defined(_WIN32) /* Be sure to set event mask BEFORE map window is done. */ if (workMask & GLUT_EVENT_MASK_WORK) { long eventMask; /* Make sure children are not propogating events this window is selecting for. Be sure to do this before enabling events on the children's parent. */ 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 /* !_WIN32 */ /* Be sure to set device mask BEFORE map window is done. */ if (workMask & GLUT_DEVICE_MASK_WORK) { __glutUpdateInputDeviceMaskFunc(window); } /* Be sure to configure window BEFORE map window is done. */ 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 this window is a toplevel window, translate the 0,0 client coordinate into a screen coordinate for proper placement. */ 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; /* XXX If overlay exists, resize the overlay here, ie. if (window->overlay) ... */ } if (window->desiredConfMask & CWStackMode) { flags &= ~SWP_NOZORDER; /* XXX Overlay support might require something special here. */ } /* Adjust the window rectangle because Win32 thinks that the x, y, width & height are the WHOLE window (including decorations), whereas GLUT treats the x, y, width & height as only the CLIENT area of the window. Only do this to top level windows that are not in game mode (since game mode windows do not have any decorations). */ if (!window->parent && window != __glutGameModeWindow) { AdjustWindowRect(&changes, WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, FALSE); } /* Do the repositioning, moving, and push/pop. */ SetWindowPos(window->win, window->desiredStack == Above ? HWND_TOP : HWND_NOTOPMOST, changes.left, changes.top, changes.right - changes.left, changes.bottom - changes.top, flags); /* Zero out the mask. */ window->desiredConfMask = 0; /* This hack causes the window to go back to the right position when it is taken out of fullscreen mode. */ if (workMask & GLUT_FULL_SCREEN_WORK) { window->desiredConfMask |= CWX | CWY; window->desiredX = point.x; window->desiredY = point.y; } #else /* !_WIN32 */ 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; /* Absolutely no decorations. */ XChangeProperty(__glutDisplay, window->win, __glutMotifHints, __glutMotifHints, 32, PropModeReplace, (unsigned char *) &hints, 4); if (workMask & GLUT_MAP_WORK) { /* Handle case where glutFullScreen is called before the first time that the window is mapped. Some window managers will randomly or interactively position the window the first time it is mapped if the window's WM_NORMAL_HINTS property does not request an explicit position. We don't want any such window manager interaction when going fullscreen. Overwrite the WM_NORMAL_HINTS property installed by glutCreateWindow's XSetWMProperties property with one explicitly requesting a fullscreen window. */ 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; /* Do not let glutPushWindow push window beneath the underlay. */ 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) /* Be sure to establish the colormaps BEFORE map window is done. */ 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: /* Not an Xlib value. */ 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) { /* Guarantee that before a display callback is generated for a window, a reshape callback must be generated. */ __glutSetWindow(window); window->reshape(window->width, window->height); window->forceReshape = False; /* Setting the redisplay bit on the first reshape is necessary to make the "Mesa glXSwapBuffers to repair damage" hack operate correctly. Without indicating a redisplay is necessary, there's not an initial back buffer render from which to blit from when damage happens to the window. */ workMask |= GLUT_REDISPLAY_WORK; } /* The code below is more involved than otherwise necessary because it is paranoid about the overlay or entire window being removed or destroyed in the course of the callbacks. Notice how the global __glutWindowDamaged is used to record the layers' damage status. See the code in glutLayerGet for how __glutWindowDamaged is used. The point is to not have to update the "damaged" field after the callback since the window (or overlay) may be destroyed (or removed) when the callback returns. */ if (window->overlay && window->overlay->display) { int num = window->num; Window xid = window->overlay ? window->overlay->win : None; /* If an overlay display callback is registered, we differentiate between a redisplay needed for the overlay and/or normal plane. If there is no overlay display callback registered, we simply use the standard display callback. */ 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; } } } /* Render to normal plane. */ #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) { /* Render to overlay. */ #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 { /* Overlay may have since been destroyed or the overlay callback may have been disabled during normal display callback. */ } } } 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; } } } /* Render to normal plane (and possibly overlay). */ __glutWindowDamaged = (workMask & (GLUT_OVERLAY_REPAIR_WORK | GLUT_REPAIR_WORK)); __glutSetWindow(window); window->usedSwapBuffers = 0; window->display(); __glutWindowDamaged = 0; skippedDisplayCallback2:; } } /* Combine workMask with window->workMask to determine what finish and debug work there is. */ workMask |= window->workMask; if (workMask & GLUT_FINISH_WORK) { /* Finish work makes sure a glFinish gets done to indirect rendering contexts. Indirect contexts tend to have much longer latency because lots of OpenGL extension requests can queue up in the X protocol stream. __glutSetWindow is where the finish works gets queued for indirect contexts. */ __glutSetWindow(window); #if !defined(_WIN32) if (!window->isDirect) #endif { glFinish(); } } if (workMask & GLUT_DEBUG_WORK) { __glutSetWindow(window); glutReportErrors(); } /* Strip out dummy, finish, and debug work bits. */ window->workMask &= ~(GLUT_DUMMY_WORK | GLUT_FINISH_WORK | GLUT_DEBUG_WORK); if (window->workMask) { /* Leave on work list. */ return window; } else { /* Remove current window from work list. */ return window->prevWorkWin; } }
static void processEventsAndTimeouts(void) { do { #if defined(_WIN32) MSG event; if(!GetMessage(&event, NULL, 0, 0)) /* bail if no more messages */ exit(0); TranslateMessage(&event); /* translate virtual-key messages */ DispatchMessage(&event); /* call the window proc */ /* see win32_event.c for event (message) processing procedures */ #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) { /* Ignore ConfigureNotify sent to the overlay planes. GLUT could get here because overlays select for StructureNotify events to receive DestroyNotify. */ 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); /* Do not execute OpenGL out of sequence with respect to the XResizeWindow request! */ glXWaitX(); window->reshape(width, height); window->forceReshape = False; /* A reshape should be considered like posting a repair; this is necessary for the "Mesa glXSwapBuffers to repair damage" hack to operate correctly. Without it, there's not an initial back buffer render from which to blit from when damage happens to the window. */ __glutPostRedisplay(window, GLUT_REPAIR_WORK); } } break; case Expose: /* compress expose events */ 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 { /* there are more exposes to read; wait to redisplay */ } break; case ButtonPress: case ButtonRelease: if (__glutMappedMenu && event.type == ButtonRelease && mappedMenuButton == event.xbutton.button) { /* Menu is currently popped up and its button is released. */ __glutFinishMenu(event.xbutton.window, event.xbutton.x, event.xbutton.y); } else { window = __glutGetWindow(event.xbutton.window); /* added button check for mice with > 3 buttons */ if (window) { GLUTmenu *menu; int menuNum; if (event.xbutton.button <= GLUT_MAX_MENUS) menuNum = window->menu[event.xbutton.button - 1]; else menuNum = 0; /* Make sure that __glutGetMenuByNum is only called if there really is a menu present. */ 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 { /* Ignore a release of a button with a menu attatched to it when no menu is popped up, or ignore a press when another menu is already popped up. */ } } 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 { /* Stray mouse events. Ignore. */ } } else { /* Window might have been destroyed and all the events for the window may not yet be received. */ } } break; case MotionNotify: if (!__glutMappedMenu) { window = __glutGetWindow(event.xmotion.window); if (window) { /* If motion function registered _and_ buttons held * down, call motion function... */ if (window->motion && event.xmotion.state & (Button1Mask | Button2Mask | Button3Mask)) { __glutSetWindow(window); window->motion(event.xmotion.x, event.xmotion.y); } /* If passive motion function registered _and_ buttons not held down, call passive motion function... */ else if (window->passive && ((event.xmotion.state & (Button1Mask | Button2Mask | Button3Mask)) == 0)) { __glutSetWindow(window); window->passive(event.xmotion.x, event.xmotion.y); } } } else { /* Motion events are thrown away when a pop up menu is active. */ } break; case KeyPress: case KeyRelease: window = __glutGetWindow(event.xkey.window); if (!window) { break; } if (event.type == KeyPress) { keyboard = window->keyboard; } else { /* If we are ignoring auto repeated keys for this window, check if the next event in the X event queue is a KeyPress for the exact same key (and at the exact same time) as the key being released. The X11 protocol will send auto repeated keys as such KeyRelease/KeyPress pairs. */ 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) { /* Pop off the repeated KeyPress and ignore the auto repeated KeyRelease/KeyPress pair. */ 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; /* Introduced in X11R6: (Partial list of) Keypad Functions. Define in place in case compiling against an older pre-X11R6 X11/keysymdef.h file. */ #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); /* XXX Verbose, but makes no assumptions about keysym layout. */ switch (ks) { /* *INDENT-OFF* */ /* function keys */ 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; /* directional keys */ case XK_KP_Left: case XK_Left: key = GLUT_KEY_LEFT; break; case XK_KP_Up: /* Introduced in X11R6. */ case XK_Up: key = GLUT_KEY_UP; break; case XK_KP_Right: /* Introduced in X11R6. */ case XK_Right: key = GLUT_KEY_RIGHT; break; case XK_KP_Down: /* Introduced in X11R6. */ case XK_Down: key = GLUT_KEY_DOWN; break; /* *INDENT-ON* */ case XK_KP_Prior: /* Introduced in X11R6. */ case XK_Prior: /* XK_Prior same as X11R6's XK_Page_Up */ key = GLUT_KEY_PAGE_UP; break; case XK_KP_Next: /* Introduced in X11R6. */ case XK_Next: /* XK_Next same as X11R6's XK_Page_Down */ key = GLUT_KEY_PAGE_DOWN; break; case XK_KP_Home: /* Introduced in X11R6. */ case XK_Home: key = GLUT_KEY_HOME; break; #ifdef __hpux case XK_Select: #endif case XK_KP_End: /* Introduced in X11R6. */ case XK_End: key = GLUT_KEY_END; break; #ifdef __hpux case XK_InsertChar: #endif case XK_KP_Insert: /* Introduced in X11R6. */ case XK_Insert: key = GLUT_KEY_INSERT; break; #ifdef __hpux case XK_DeleteChar: #endif case XK_KP_Delete: /* Introduced in X11R6. */ /* The Delete character is really an ASCII key. */ __glutSetWindow(window); keyboard(127, /* ASCII Delete character. */ 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) { /* Careful to ignore Enter/LeaveNotify events that come from the pop-up menu pointer grab and ungrab. Also, ignore "virtual" Enter/LeaveNotify events since they represent the pointer passing through the window hierarchy without actually entering or leaving the actual real estate of a window. */ 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) { /* With overlays established, X can report two enter events for both the overlay and normal plane window. Do not generate a second enter callback if we reported one without an intervening leave. */ if (window->entryState != EnterNotify) { int num = window->num; Window xid = window->win; window->entryState = EnterNotify; __glutSetWindow(window); window->entry(GLUT_ENTERED); if (__glutMappedMenu) { /* Do not generate any passive motion events when menus are in use. */ } else { /* An EnterNotify event can result in a "compound" callback if a passive motion callback is also registered. In this case, be a little paranoid about the possibility the window could have been destroyed in the entry callback. */ 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) { /* When an overlay is established for a window already mapped and with the pointer in it, the X server will generate a leave/enter event pair as the pointer leaves (without moving) from the normal plane X window to the newly mapped overlay X window (or vice versa). This enter/leave pair should not be reported to the GLUT program since the pair is a consequence of creating (or destroying) the overlay, not an actual leave from the GLUT window. */ 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: /* MapNotify events are not needed to maintain visibility state since VisibilityNotify events will be delivered when a window becomes visible from mapping. However, VisibilityNotify events are not delivered when a window is unmapped (for the window or its children). */ window = __glutGetWindow(event.xunmap.window); if (window) { if (window->win != event.xconfigure.window) { /* Ignore UnmapNotify sent to the overlay planes. GLUT could get here because overlays select for StructureNotify events to receive DestroyNotify. */ break; } markWindowHidden(window); } break; case VisibilityNotify: window = __glutGetWindow(event.xvisibility.window); if (window) { /* VisibilityUnobscured+1 = GLUT_FULLY_RETAINED, VisibilityPartiallyObscured+1 = GLUT_PARTIALLY_RETAINED, VisibilityFullyObscured+1 = GLUT_FULLY_COVERED. */ 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: /* Uninteresting to GLUT (but possible for GLUT to receive). */ break; default: /* Pass events not directly handled by the GLUT main event loop to any event parsers that have been registered. In this way, X Input extension events are passed to the correct handler without forcing all GLUT programs to support X Input event handling. */ parser = eventParserList; while (parser) { if (parser->func(&event)) break; parser = parser->next; } break; } } #endif /* _WIN32 */ if (__glutTimerList) { handleTimeouts(); } } while (XPending(__glutDisplay)); }
/* ARGSUSED5 */ /* Only Win32 uses gameMode parameter. */ GLUTwindow * __glutCreateWindow(GLUTwindow * parent, int x, int y, int width, int height, int gameMode) { GLUTwindow *window; XSetWindowAttributes wa; unsigned long attribMask; int winnum; int i; void *fbc; #if defined(_WIN32) WNDCLASS wc; int style; if (!GetClassInfo(GetModuleHandle(NULL), TEXT("GLUT"), &wc)) { __glutOpenWin32Connection(NULL); } #else if (!__glutDisplay) { __glutOpenXConnection(NULL); } #endif if (__glutGameModeWindow) { __glutFatalError("cannot create windows in game mode."); } winnum = getUnusedWindowSlot(); window = (GLUTwindow *) malloc(sizeof(GLUTwindow)); if (!window) { __glutFatalError("out of memory."); } window->num = winnum; #if !defined(_WIN32) window->vis = __glutDetermineWindowVisual(&window->treatAsSingle, &window->visAlloced, &fbc); if (!window->vis) { __glutFatalError( "visual with necessary capabilities not found."); } __glutSetupColormap(window->vis, &window->colormap, &window->cmap); #endif window->eventMask = StructureNotifyMask | ExposureMask; attribMask = CWBackPixmap | CWBorderPixel | CWColormap | CWEventMask; wa.background_pixmap = None; wa.border_pixel = 0; wa.colormap = window->cmap; wa.event_mask = window->eventMask; if (parent) { if (parent->eventMask & GLUT_HACK_STOP_PROPAGATE_MASK) wa.event_mask |= GLUT_HACK_STOP_PROPAGATE_MASK; attribMask |= CWDontPropagate; wa.do_not_propagate_mask = parent->eventMask & GLUT_DONT_PROPAGATE_FILTER_MASK; } else { wa.do_not_propagate_mask = 0; } /* Stash width and height before Win32's __glutAdjustCoords possibly overwrites the values. */ window->width = width; window->height = height; window->forceReshape = True; window->ignoreKeyRepeat = False; #if defined(_WIN32) __glutAdjustCoords(parent ? parent->win : NULL, &x, &y, &width, &height); if (parent) { style = WS_CHILD; } else { if (gameMode) { /* Game mode window should be a WS_POPUP window to ensure that the taskbar is hidden by it. A standard WS_OVERLAPPEDWINDOW does not hide the task bar. */ style = WS_POPUP | WS_MAXIMIZE; } else { /* A standard toplevel window with borders and such. */ style = WS_OVERLAPPEDWINDOW; } } window->win = CreateWindow(TEXT("GLUT"), TEXT("GLUT"), WS_CLIPSIBLINGS | WS_CLIPCHILDREN | style, x, y, width, height, parent ? parent->win : __glutRoot, NULL, GetModuleHandle(NULL), 0); window->hdc = GetDC(window->win); /* Must set the XHDC for fake glXChooseVisual & fake glXCreateContext & fake XAllocColorCells. */ XHDC = window->hdc; window->vis = __glutDetermineWindowVisual(&window->treatAsSingle, &window->visAlloced, &fbc); if (!window->vis) { __glutFatalError( "pixel format with necessary capabilities not found."); } if (!SetPixelFormat(window->hdc, ChoosePixelFormat(window->hdc, window->vis), window->vis)) { __glutFatalError("SetPixelFormat failed during window create."); } __glutSetupColormap(window->vis, &window->colormap, &window->cmap); /* Make sure subwindows get a windowStatus callback. */ if (parent) { PostMessage(parent->win, WM_ACTIVATE, 0, 0); } window->renderDc = window->hdc; #else window->win = XCreateWindow(__glutDisplay, parent == NULL ? __glutRoot : parent->win, x, y, width, height, 0, window->vis->depth, InputOutput, window->vis->visual, attribMask, &wa); #endif window->renderWin = window->win; #if defined(GLX_VERSION_1_1) && defined(GLX_SGIX_fbconfig) if (fbc) { window->ctx = __glut_glXCreateContextWithConfigSGIX(__glutDisplay, fbc, GLX_RGBA_TYPE_SGIX, None, __glutTryDirect); } else #endif { window->ctx = glXCreateContext(__glutDisplay, window->vis, None, __glutTryDirect); } if (!window->ctx) { __glutFatalError( "failed to create OpenGL rendering context."); } window->renderCtx = window->ctx; #if !defined(_WIN32) window->isDirect = glXIsDirect(__glutDisplay, window->ctx); if (__glutForceDirect) { if (!window->isDirect) __glutFatalError("direct rendering not possible."); } #endif window->parent = parent; if (parent) { window->siblings = parent->children; parent->children = window; } else { window->siblings = NULL; } window->overlay = NULL; window->children = NULL; window->display = __glutDefaultDisplay; window->reshape = __glutDefaultReshape; window->mouse = NULL; window->motion = NULL; window->passive = NULL; window->entry = NULL; window->keyboard = NULL; window->keyboardUp = NULL; window->windowStatus = NULL; window->visibility = NULL; window->special = NULL; window->specialUp = NULL; window->buttonBox = NULL; window->dials = NULL; window->spaceMotion = NULL; window->spaceRotate = NULL; window->spaceButton = NULL; window->tabletMotion = NULL; window->tabletButton = NULL; #ifdef _WIN32 window->joystick = NULL; window->joyPollInterval = 0; #endif window->tabletPos[0] = -1; window->tabletPos[1] = -1; window->shownState = 0; window->visState = -1; /* not VisibilityUnobscured, VisibilityPartiallyObscured, or VisibilityFullyObscured */ window->entryState = -1; /* not EnterNotify or LeaveNotify */ window->desiredConfMask = 0; window->buttonUses = 0; window->cursor = GLUT_CURSOR_INHERIT; /* Setup window to be mapped when glutMainLoop starts. */ window->workMask = GLUT_MAP_WORK; #ifdef _WIN32 if (gameMode) { /* When mapping a game mode window, just show the window. We have already created the game mode window with a maximize flag at creation time. Doing a ShowWindow(window->win, SW_SHOWNORMAL) would be wrong for a game mode window since it would unmaximize the window. */ window->desiredMapState = GameModeState; } else { window->desiredMapState = NormalState; } #else window->desiredMapState = NormalState; #endif window->prevWorkWin = __glutWindowWorkList; __glutWindowWorkList = window; /* Initially, no menus attached. */ for (i = 0; i < GLUT_MAX_MENUS; i++) { window->menu[i] = 0; } /* Add this new window to the window list. */ __glutWindowList[winnum] = window; /* Make the new window the current window. */ __glutSetWindow(window); __glutDetermineMesaSwapHackSupport(); if (window->treatAsSingle) { /* We do this because either the window really is single buffered (in which case this is redundant, but harmless, because this is the initial single-buffered context state); or we are treating a double buffered window as a single-buffered window because the system does not appear to export any suitable single- buffered visuals (in which the following are necessary). */ glDrawBuffer(GL_FRONT); glReadBuffer(GL_FRONT); } return window; }
LONG WINAPI __glutWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { POINT point; /* Point structure. */ PAINTSTRUCT ps; /* Paint structure. */ LPMINMAXINFO minmax; /* Minimum/maximum info structure. */ GLUTwindow* window; /* GLUT window associated with message. */ GLUTmenu* menu; /* GLUT menu associated with message. */ int x, y, width, height, key; int button = -1; switch(msg) { case WM_CREATE: return 0; case WM_CLOSE: PostQuitMessage(0); return 0; case WM_DESTROY: #if 0 /* TODO: need to add this. */ purgeStaleWindow(hwnd); #endif return 0; case WM_PAINT: window = __glutGetWindow(hwnd); if (window) { BeginPaint(hwnd, &ps); /* Must have this for some Win32 reason. */ #if TAKE_THIS_OUT if (window->colormap) { SelectPalette(window->hdc, window->colormap->cmap, FORCE_FOREGROUND); RealizePalette(window->hdc); /* Remap the custom palette. */ } #endif EndPaint(hwnd, &ps); if (window->win == hwnd) { __glutPostRedisplay(window, GLUT_REPAIR_WORK); } else if (window->overlay && window->overlay->win == hwnd) { __glutPostRedisplay(window, GLUT_OVERLAY_REPAIR_WORK); } } return 0; case WM_SYSCHAR: case WM_CHAR: window = __glutGetWindow(hwnd); if (!window) { break; } /* Win32 is dumb and sends these messages only to the parent window. Therefore, find out if we're in a child window and call the child windows keyboard callback if we are. */ if (window->parent) { GetCursorPos(&point); ScreenToClient(hwnd, &point); hwnd = ChildWindowFromPoint(hwnd, point); window = __glutGetWindow(hwnd); } if (window->keyboard) { GetCursorPos(&point); ScreenToClient(window->win, &point); __glutSetWindow(window); __glutModifierMask = 0; if (GetKeyState(VK_SHIFT) < 0) /* < 0 = high order bit is on */ __glutModifierMask |= ShiftMask; if (GetKeyState(VK_CONTROL) < 0) __glutModifierMask |= ControlMask; if (GetKeyState(VK_MENU) < 0) __glutModifierMask |= Mod1Mask; window->keyboard((char)wParam, point.x, point.y); __glutModifierMask = (unsigned int) ~0; } return 0; case WM_SYSKEYDOWN: case WM_KEYDOWN: window = __glutGetWindow(hwnd); if (!window) { break; } /* Win32 is dumb and sends these messages only to the parent window. Therefore, find out if we're in a child window and call the child windows keyboard callback if we are. */ if (window->parent) { GetCursorPos(&point); ScreenToClient(hwnd, &point); hwnd = ChildWindowFromPoint(hwnd, point); window = __glutGetWindow(hwnd); } if (window->special) { switch (wParam) { /* *INDENT-OFF* */ /* function keys */ case VK_F1: key = GLUT_KEY_F1; break; case VK_F2: key = GLUT_KEY_F2; break; case VK_F3: key = GLUT_KEY_F3; break; case VK_F4: key = GLUT_KEY_F4; break; case VK_F5: key = GLUT_KEY_F5; break; case VK_F6: key = GLUT_KEY_F6; break; case VK_F7: key = GLUT_KEY_F7; break; case VK_F8: key = GLUT_KEY_F8; break; case VK_F9: key = GLUT_KEY_F9; break; case VK_F10: key = GLUT_KEY_F10; break; case VK_F11: key = GLUT_KEY_F11; break; case VK_F12: key = GLUT_KEY_F12; break; /* directional keys */ case VK_LEFT: key = GLUT_KEY_LEFT; break; case VK_UP: key = GLUT_KEY_UP; break; case VK_RIGHT: key = GLUT_KEY_RIGHT; break; case VK_DOWN: key = GLUT_KEY_DOWN; break; /* *INDENT-ON* */ case VK_PRIOR: /* VK_PRIOR is Win32's Page Up */ key = GLUT_KEY_PAGE_UP; break; case VK_NEXT: /* VK_NEXT is Win32's Page Down */ key = GLUT_KEY_PAGE_DOWN; break; case VK_HOME: key = GLUT_KEY_HOME; break; case VK_END: key = GLUT_KEY_END; break; case VK_INSERT: key = GLUT_KEY_INSERT; break; default: goto defproc; } GetCursorPos(&point); ScreenToClient(window->win, &point); __glutSetWindow(window); __glutModifierMask = 0; if (GetKeyState(VK_SHIFT) < 0) /* < 0 = high order bit is on */ __glutModifierMask |= ShiftMask; if (GetKeyState(VK_CONTROL) < 0) __glutModifierMask |= ControlMask; if (GetKeyState(VK_MENU) < 0) __glutModifierMask |= Mod1Mask; window->special(key, point.x, point.y); __glutModifierMask = (unsigned int) ~0; } return 0; case WM_LBUTTONDOWN: button = GLUT_LEFT_BUTTON; case WM_MBUTTONDOWN: if (button < 0) button = GLUT_MIDDLE_BUTTON; case WM_RBUTTONDOWN: if (button < 0) button = GLUT_RIGHT_BUTTON; /* finish the menu if we get a button down message (user must have cancelled the menu). */ if (__glutMappedMenu) { /* TODO: take this out once the menu on middle mouse stuff works properly. */ if (button == GLUT_MIDDLE_BUTTON) return 0; GetCursorPos(&point); ScreenToClient(hwnd, &point); __glutItemSelected = NULL; __glutFinishMenu(hwnd, point.x, point.y); return 0; } /* set the capture so we can get mouse events outside the window */ SetCapture(hwnd); /* Win32 doesn't return the same numbers as X does when the mouse goes beyond the upper or left side of the window. roll the Win32's 0..2^16 pointer co-ord range to 0 +/- 2^15. */ x = LOWORD(lParam); y = HIWORD(lParam); if(x & 1 << 15) x -= (1 << 16); if(y & 1 << 15) y -= (1 << 16); window = __glutGetWindow(hwnd); if (window) { menu = __glutGetMenuByNum(window->menu[button]); if (menu) { point.x = LOWORD(lParam); point.y = HIWORD(lParam); ClientToScreen(window->win, &point); __glutMenuButton = button == GLUT_RIGHT_BUTTON ? TPM_RIGHTBUTTON : button == GLUT_LEFT_BUTTON ? TPM_LEFTBUTTON : 0x0001; __glutStartMenu(menu, window, point.x, point.y, x, y); } else if (window->mouse) { __glutSetWindow(window); __glutModifierMask = 0; if (GetKeyState(VK_SHIFT) < 0) /* < 0 = high order bit is on. */ __glutModifierMask |= ShiftMask; if (GetKeyState(VK_CONTROL) < 0) __glutModifierMask |= ControlMask; if (GetKeyState(VK_MENU) < 0) __glutModifierMask |= Mod1Mask; window->mouse(button, GLUT_DOWN, x, y); __glutModifierMask = (unsigned int)~0; } else { /* Stray mouse events. Ignore. */ } } return 0; case WM_LBUTTONUP: button = GLUT_LEFT_BUTTON; case WM_MBUTTONUP: if (button < 0) button = GLUT_MIDDLE_BUTTON; case WM_RBUTTONUP: if (button < 0) button = GLUT_RIGHT_BUTTON; /* Bail out if we're processing a menu. */ if (__glutMappedMenu) { GetCursorPos(&point); ScreenToClient(hwnd, &point); /* if we're getting the middle button up signal, then something on the menu was selected. */ if (button == GLUT_MIDDLE_BUTTON) { return 0; /* For some reason, the code below always returns -1 even though the point IS IN THE ITEM! Therefore, just bail out if we get a middle mouse up. The user must select using the left mouse button. Stupid Win32. */ #if 0 int item = MenuItemFromPoint(hwnd, __glutHMenu, point); printf("item = %d %d %d\n", item, point.x, point.y); if (item != -1) __glutItemSelected = (GLUTmenuItem*)GetMenuItemID(__glutHMenu, item); else __glutItemSelected = NULL; __glutFinishMenu(hwnd, point.x, point.y); #endif } else { __glutItemSelected = NULL; __glutFinishMenu(hwnd, point.x, point.y); } return 0; } /* Release the mouse capture. */ ReleaseCapture(); window = __glutGetWindow(hwnd); if (window && window->mouse) { /* Win32 doesn't return the same numbers as X does when the mouse goes beyond the upper or left side of the window. roll the Win32's 0..2^16 pointer co-ord range to 0 +/- 2^15. */ x = LOWORD(lParam); y = HIWORD(lParam); if(x & 1 << 15) x -= (1 << 16); if(y & 1 << 15) y -= (1 << 16); __glutSetWindow(window); __glutModifierMask = 0; if (GetKeyState(VK_SHIFT) < 0) /* < 0 = high order bit is on */ __glutModifierMask |= ShiftMask; if (GetKeyState(VK_CONTROL) < 0) __glutModifierMask |= ControlMask; if (GetKeyState(VK_MENU) < 0) __glutModifierMask |= Mod1Mask; window->mouse(button, GLUT_UP, x, y); __glutModifierMask = (unsigned int)~0; } else { /* Window might have been destroyed and all the events for the window may not yet be received. */ } return 0; case WM_ENTERMENULOOP: /* KLUDGE: create a timer that fires every 100 ms when we start a menu so that we can still process the idle & timer events (that way, the timers will fire during a menu pick and so will the idle func. */ SetTimer(hwnd, 1, 1, NULL); return 0; case WM_TIMER: #if 0 /* if the timer id is 2, then this is the timer that is set up in the main glut message processing loop, and we don't want to do anything but acknowledge that we got it. It is used to prevent CPU spiking when an idle function is installed. */ if (wParam == 2) return 0; #endif /* only worry about the idle function and the timeouts, since these are the only events we expect to process during processing of a menu. */ /* we no longer process the idle functions (as outlined in the README), since drawing can't be done until the menu has finished...it's pretty lame when the animation goes on, but doesn't update, so you get this weird jerkiness. */ #if 0 if (__glutIdleFunc) __glutIdleFunc(); #endif if (__glutTimerList) handleTimeouts(); return 0; case WM_EXITMENULOOP: /* nuke the above created timer...we don't need it anymore, since the menu is gone now. */ KillTimer(hwnd, 1); return 0; case WM_MENUSELECT: if (lParam != 0) __glutHMenu = (HMENU)lParam; return 0; case WM_COMMAND: if (__glutMappedMenu) { if (GetSubMenu(__glutHMenu, LOWORD(wParam))) __glutItemSelected = NULL; else __glutItemSelected = __glutGetUniqueMenuItem(__glutMappedMenu, LOWORD(wParam)); GetCursorPos(&point); ScreenToClient(hwnd, &point); __glutFinishMenu(hwnd, point.x, point.y); } return 0; case WM_MOUSEMOVE: if (!__glutMappedMenu) { window = __glutGetWindow(hwnd); if (window) { /* If motion function registered _and_ buttons held * down, call motion function... */ x = LOWORD(lParam); y = HIWORD(lParam); /* Win32 doesn't return the same numbers as X does when the mouse goes beyond the upper or left side of the window. roll the Win32's 0..2^16 pointer co-ord range to 0..+/-2^15. */ if(x & 1 << 15) x -= (1 << 16); if(y & 1 << 15) y -= (1 << 16); if (window->motion && wParam & (MK_LBUTTON | MK_MBUTTON | MK_RBUTTON)) { __glutSetWindow(window); window->motion(x, y); } /* If passive motion function registered _and_ buttons not held down, call passive motion function... */ else if (window->passive && ((wParam & (MK_LBUTTON | MK_MBUTTON | MK_RBUTTON)) == 0)) { __glutSetWindow(window); window->passive(x, y); } } } else { /* Motion events are thrown away when a pop up menu is active. */ } return 0; case WM_GETMINMAXINFO: /* this voodoo is brought to you by Win32 (again). It allows the window to be bigger than the screen, and smaller than 100x100 (although it doesn't seem to help the y minimum). */ minmax = (LPMINMAXINFO)lParam; minmax->ptMaxSize.x = __glutScreenWidth; minmax->ptMaxSize.y = __glutScreenHeight; minmax->ptMinTrackSize.x = 0; minmax->ptMinTrackSize.y = 0; minmax->ptMaxTrackSize.x = __glutScreenWidth + GetSystemMetrics(SM_CXSIZE) * 2; minmax->ptMaxTrackSize.y = __glutScreenHeight + GetSystemMetrics(SM_CXSIZE) * 2 + GetSystemMetrics(SM_CYCAPTION); return 0; case WM_SIZE: window = __glutGetWindow(hwnd); if (window) { #if 0 if (window->win != hwnd) { /* Ignore ConfigureNotify sent to the overlay planes. GLUT could get here because overlays select for StructureNotify events to receive DestroyNotify. */ break; } #endif width = LOWORD(lParam); height = HIWORD(lParam); if (width != window->width || height != window->height) { #if 0 if (window->overlay) { XResizeWindow(__glutDisplay, window->overlay->win, width, height); } #endif window->width = width; window->height = height; __glutSetWindow(window); /* Do not execute OpenGL out of sequence with respect to the SetWindowPos request! */ GdiFlush(); window->reshape(width, height); window->forceReshape = FALSE; /* A reshape should be considered like posting a repair request. */ __glutPostRedisplay(window, GLUT_REPAIR_WORK); } } return 0; case WM_SETCURSOR: /* If the cursor is not in the client area, then we want to send this message to the default window procedure ('cause its probably in the border or title, and we don't handle that cursor. otherwise, set our cursor. Win32 makes us set the cursor every time the mouse moves (DUMB!). */ if(LOWORD(lParam) != HTCLIENT) goto defproc; window = __glutGetWindow(hwnd); if (window) { /* Since Win32 allows the parent to control a child windows cursor, if the cursor is in a child of this window, bail out. */ GetCursorPos(&point); ScreenToClient(hwnd, &point); if (hwnd != ChildWindowFromPoint(hwnd, point)) break; __glutCurrentWindow = window; glutSetCursor(window->cursor); } /* TODO: check out the info in DevStudio on WM_SETCURSOR in the DefaultAction section. */ return 1; case WM_SETFOCUS: window = __glutGetWindow(hwnd); if (window) { if (window->entry) { window->entryState = WM_SETFOCUS; __glutSetWindow(window); window->entry(GLUT_ENTERED); /* XXX Generation of fake passive notify? See how much work the X11 code does to support fake passive notify callbacks. */ } } return 0; case WM_KILLFOCUS: window = __glutGetWindow(hwnd); if (window) { if (window->entry) { window->entryState = WM_KILLFOCUS; __glutSetWindow(window); window->entry(GLUT_LEFT); } } return 0; case WM_ACTIVATE: window = __glutGetWindow(hwnd); /* make sure we re-select the correct palette if needed */ if (LOWORD(wParam)) { PostMessage(hwnd, WM_PALETTECHANGED, 0, 0); } if (window) { GLUTwindow* child; int visState; visState = !IsIconic(window->win); if (visState) { /* Not iconic. */ visState = IsWindowVisible(window->win); } if (visState != window->visState) { if (window->windowStatus) { window->visState = visState; __glutSetWindow(window); window->windowStatus(visState); } /* Since Win32 only sends an activate for the toplevel window, update the visibility for all the child windows. */ child = window->children; while (child) { child->visState = visState; if (child->windowStatus) { child->visState = visState; __glutSetWindow(child); child->windowStatus(visState); } child = child->siblings; } } } return 0; /* Colour Palette Management */ case WM_PALETTECHANGED: if (hwnd == (HWND)wParam) /* don't respond to the message that we sent! */ break; /* fall through to WM_QUERYNEWPALETTE */ case WM_QUERYNEWPALETTE: window = __glutGetWindow(hwnd); if (window && window->colormap) { UnrealizeObject(window->colormap->cmap); SelectPalette(window->hdc, window->colormap->cmap, FALSE); RealizePalette(window->hdc); return TRUE; } return FALSE; #if 0 /* Miscellaneous messages (don't really need to enumerate them, but it's good to know what you're not getting sometimes.) */ case WM_NCHITTEST: /* this event is generated by every mouse move event. */ goto defproc; case WM_NCMOUSEMOVE: goto defproc; case WM_NCACTIVATE: goto defproc; case WM_NCPAINT: goto defproc; case WM_NCCALCSIZE: goto defproc; case WM_NCCREATE: goto defproc; case WM_NCDESTROY: goto defproc; case WM_NCLBUTTONDOWN: goto defproc; case WM_SETTEXT: goto defproc; case WM_GETTEXT: goto defproc; case WM_ACTIVATEAPP: goto defproc; case WM_GETICON: goto defproc; case WM_ERASEBKGND: goto defproc; case WM_WINDOWPOSCHANGING: goto defproc; case WM_WINDOWPOSCHANGED: goto defproc; case WM_MOUSEACTIVATE: goto defproc; case WM_SHOWWINDOW: goto defproc; case WM_MOVING: goto defproc; case WM_MOVE: goto defproc; case WM_KEYUP: goto defproc; case WM_CAPTURECHANGED: goto defproc; case WM_SYSCOMMAND: goto defproc; case WM_ENTERSIZEMOVE: goto defproc; case WM_ENTERIDLE: goto defproc; #endif default: goto defproc; } defproc: return DefWindowProc(hwnd, msg, wParam, lParam); }
GLUTwindow * __glutCreateWindow(GLUTwindow * parent, int x, int y, int width, int height) { GLUTwindow *window; XSetWindowAttributes wa; unsigned long attribMask; int winnum; int i; #if defined(WIN32) WNDCLASS wc; if (!GetClassInfo(GetModuleHandle(NULL), "GLUT", &wc)) __glutOpenWin32Connection(NULL); #else if (!__glutDisplay) __glutOpenXConnection(NULL); #endif winnum = getUnusedWindowSlot(); window = (GLUTwindow *) malloc(sizeof(GLUTwindow)); if (!window) __glutFatalError("out of memory."); window->num = winnum; #if !defined(WIN32) window->vis = __glutDetermineWindowVisual(&window->treatAsSingle, &window->visAlloced); if (!window->vis) { __glutFatalError( "visual with necessary capabilities not found."); } __glutSetupColormap(window->vis, &window->colormap, &window->cmap); #endif window->eventMask = StructureNotifyMask | ExposureMask; attribMask = CWBackPixmap | CWBorderPixel | CWColormap | CWEventMask; wa.background_pixmap = None; wa.border_pixel = 0; wa.colormap = window->cmap; wa.event_mask = window->eventMask; if (parent) { if (parent->eventMask & GLUT_HACK_STOP_PROPAGATE_MASK) wa.event_mask |= GLUT_HACK_STOP_PROPAGATE_MASK; attribMask |= CWDontPropagate; wa.do_not_propagate_mask = parent->eventMask & GLUT_DONT_PROPAGATE_FILTER_MASK; } else { wa.do_not_propagate_mask = 0; } /* Stash width and height before Win32's __glutAdjustCoords possibly overwrites the values. */ window->width = width; window->height = height; window->forceReshape = True; #if defined(WIN32) __glutAdjustCoords(parent ? parent->win : NULL, &x, &y, &width, &height); window->win = XCreateWindow(__glutDisplay, parent == NULL ? __glutRoot : parent->win, x, y, width, height, 0, 0, InputOutput, 0, attribMask, &wa); window->hdc = GetDC(window->win); /* Must set the XHDC for fake glXChooseVisual & fake glXCreateContext & fake XAllocColorCells. */ XHDC = window->hdc; window->vis = __glutDetermineWindowVisual(&window->treatAsSingle, &window->visAlloced); if (!window->vis) { __glutFatalError( "visual with necessary capabilities not found."); } if (!SetPixelFormat(window->hdc, ChoosePixelFormat(window->hdc, window->vis), window->vis)) __glutFatalError("SetPixelFormat() failed in glutCreateWindow()."); __glutSetupColormap(window->vis, &window->colormap, &window->cmap); /* Make sure subwindows get a windowStatus callback. */ if (parent) PostMessage(parent->win, WM_ACTIVATE, 0, 0); #else window->win = XCreateWindow(__glutDisplay, parent == NULL ? __glutRoot : parent->win, x, y, width, height, 0, window->vis->depth, InputOutput, window->vis->visual, attribMask, &wa); #endif window->renderWin = window->win; window->ctx = glXCreateContext(__glutDisplay, window->vis, None, __glutTryDirect); if (!window->ctx) { __glutFatalError( "failed to create OpenGL rendering context."); } window->renderCtx = window->ctx; #if !defined(WIN32) window->isDirect = glXIsDirect(__glutDisplay, window->ctx); if (__glutForceDirect) { if (!window->isDirect) __glutFatalError("direct rendering not possible."); } #endif window->parent = parent; if (parent) { window->siblings = parent->children; parent->children = window; } else { window->siblings = NULL; } window->overlay = NULL; window->children = NULL; window->display = __glutDefaultDisplay; window->reshape = __glutDefaultReshape; window->mouse = NULL; window->motion = NULL; window->windowStatus = NULL; window->visibility = NULL; window->passive = NULL; window->entry = NULL; window->special = NULL; window->buttonBox = NULL; window->dials = NULL; window->spaceMotion = NULL; window->spaceRotate = NULL; window->spaceButton = NULL; window->tabletMotion = NULL; window->tabletButton = NULL; window->tabletPos[0] = -1; window->tabletPos[1] = -1; window->keyboard = NULL; window->shownState = 0; window->visState = -1; /* not VisibilityUnobscured, VisibilityPartiallyObscured, or VisibilityFullyObscured */ window->entryState = -1; /* not EnterNotify or LeaveNotify */ window->workMask = GLUT_MAP_WORK; window->desiredMapState = NormalState; window->desiredConfMask = 0; window->buttonUses = 0; window->cursor = GLUT_CURSOR_INHERIT; window->prevWorkWin = __glutWindowWorkList; __glutWindowWorkList = window; for (i = 0; i < GLUT_MAX_MENUS; i++) { window->menu[i] = 0; } __glutWindowList[winnum] = window; __glutSetWindow(window); __glutDetermineMesaSwapHackSupport(); if (window->treatAsSingle) { /* We do this because either the window really is single buffered (in which case this is redundant, but harmless, because this is the initial single-buffered context state); or we are treating a double buffered window as a single-buffered window because the system does not appear to export any suitable single- buffered visuals (in which the following are necessary). */ glDrawBuffer(GL_FRONT); glReadBuffer(GL_FRONT); } return window; }
static void __glutInputEvent( DFBInputEvent *e, DFBInputEvent *p ) { __glutAssert( g_game != NULL ); switch (e->type) { case DIET_KEYPRESS: g_game->modifiers = __glutModifiers( e->modifiers ); if (g_ignore_key_repeat && p) { if (p->type == DIET_KEYPRESS && p->key_symbol == e->key_symbol) break; } if (DFB_KEY_IS_ASCII( e->key_symbol )) { if (keyboard_func) { __glutSetWindow( g_game ); keyboard_func( e->key_symbol, g_game->cx, g_game->cy ); } } else { int key = __glutSpecialKey( e->key_symbol ); if (key && special_func) { __glutSetWindow( g_game ); special_func( key, g_game->cx, g_game->cy ); } } break; case DIET_KEYRELEASE: g_game->modifiers = __glutModifiers( e->modifiers ); if (DFB_KEY_IS_ASCII( e->key_symbol )) { if (keyboard_up_func) { __glutSetWindow( g_game ); keyboard_up_func( e->key_symbol, g_game->cx, g_game->cy ); } } else { int key = __glutSpecialKey( e->key_symbol ); if (key && special_up_func) { __glutSetWindow( g_game ); special_up_func( key, g_game->cx, g_game->cy ); } } break; case DIET_BUTTONPRESS: if (e->device_id == DIDID_JOYSTICK) { g_game->buttons = e->buttons; if (joystick_func) { __glutSetWindow( g_game ); joystick_func( g_game->buttons, g_game->jx, g_game->jy, g_game->jz ); } } else { if (mouse_func) { __glutSetWindow( g_game ); mouse_func( __glutButton( e->button ), GLUT_DOWN, g_game->cx, g_game->cy ); } } break; case DIET_BUTTONRELEASE: if (e->device_id == DIDID_JOYSTICK) { g_game->buttons = e->buttons; if (joystick_func) { __glutSetWindow( g_game ); joystick_func( g_game->buttons, g_game->jx, g_game->jy, g_game->jz ); } } else { if (mouse_func) { __glutSetWindow( g_game ); mouse_func( __glutButton( e->button ), GLUT_UP, g_game->cx, g_game->cy ); } } break; case DIET_AXISMOTION: if (e->device_id == DIDID_JOYSTICK) { switch (e->axis) { case DIAI_X: if (e->flags & DIEF_AXISABS) g_game->jx = e->axisabs; else if (e->flags & DIEF_AXISREL) g_game->jx += e->axisrel; break; case DIAI_Y: if (e->flags & DIEF_AXISABS) g_game->jy = e->axisabs; else if (e->flags & DIEF_AXISREL) g_game->jy += e->axisrel; break; case DIAI_Z: if (e->flags & DIEF_AXISABS) g_game->jz = e->axisabs; else if (e->flags & DIEF_AXISREL) g_game->jz += e->axisrel; break; default: break; } if (joystick_func) { __glutSetWindow( g_game ); joystick_func( g_game->buttons, g_game->jx, g_game->jy, g_game->jz ); } } else { switch (e->axis) { case DIAI_X: if (e->flags & DIEF_AXISABS) g_game->cx = e->axisabs; else if (e->flags & DIEF_AXISREL) g_game->cx += e->axisrel; break; case DIAI_Y: if (e->flags & DIEF_AXISABS) g_game->cy = e->axisabs; else if (e->flags & DIEF_AXISREL) g_game->cy += e->axisrel; break; default: return; } if (e->buttons && motion_func) { __glutSetWindow( g_game ); motion_func( g_game->cx, g_game->cy ); } else if (!e->buttons && passive_motion_func) { __glutSetWindow( g_game ); passive_motion_func( g_game->cx, g_game->cy ); } } break; default: break; } }
static void __glutWindowEvent( DFBWindowEvent *e, DFBWindowEvent *p ) { __GlutWindow *window; window = __glutFindWindow( e->window_id ); if (!window) /* window was destroyed */ return; switch (e->type) { case DWET_KEYDOWN: window->modifiers = __glutModifiers( e->modifiers ); if (g_ignore_key_repeat && p) { if (p->type == DWET_KEYDOWN && p->window_id == e->window_id && p->key_symbol == e->key_symbol) break; } if (DFB_KEY_IS_ASCII( e->key_symbol )) { if (keyboard_func) { __glutSetWindow( window ); keyboard_func( e->key_symbol, e->x, e->y ); } } else { int key = __glutSpecialKey( e->key_symbol ); if (key && special_func) { __glutSetWindow( window ); special_func( key, e->x, e->y ); } } break; case DWET_KEYUP: window->modifiers = __glutModifiers( e->modifiers ); if (DFB_KEY_IS_ASCII( e->key_symbol )) { if (keyboard_up_func) { __glutSetWindow( window ); keyboard_up_func( e->key_symbol, e->x, e->y ); } } else { int key = __glutSpecialKey( e->key_symbol ); if (key && special_up_func) { __glutSetWindow( window ); special_up_func( key, e->x, e->y ); } } break; case DWET_BUTTONDOWN: if (mouse_func) { __glutSetWindow( window ); mouse_func( __glutButton( e->button ), GLUT_DOWN, e->x, e->y ); } break; case DWET_BUTTONUP: if (mouse_func) { __glutSetWindow( window ); mouse_func( __glutButton( e->button ), GLUT_UP, e->x, e->y ); } break; case DWET_MOTION: if (e->buttons) { if (motion_func) { __glutSetWindow( window ); motion_func( e->cx, e->cy ); } } else { if (passive_motion_func) { __glutSetWindow( window ); passive_motion_func( e->cx, e->cy ); } } break; case DWET_ENTER: if (entry_func) { __glutSetWindow( window ); entry_func( GLUT_ENTERED ); } break; case DWET_LEAVE: if (entry_func) { __glutSetWindow( window ); entry_func( GLUT_LEFT ); } break; case DWET_SIZE: window->reshape = GL_TRUE; window->redisplay = GL_TRUE; break; default: break; } }
/*********************************************************** * FUNCTION: processEventsAndTimeouts * * DESCRIPTION: clear gBlock, then check all windows for events ***********************************************************/ static void processEventsAndTimeouts(void) { gBlock.WaitEvent(); // if there is already an event, returns // immediately, otherwise wait forever gBlock.ClearEvents(); if(gState.quitAll) exit(0); // exit handler cleans up windows and quits nicely if (gState.currentWindow) gState.currentWindow->LockGL(); for(int i=0; i<gState.windowListSize; i++) { if (gState.windowList[i]) { GlutWindow *win = gState.windowList[i]; // NOTE: we can use win as a shortcut for gState.windowList[i] // in callbacks, EXCEPT we need to check the original variable // after each callback to make sure the window hasn't been destroyed if (win->anyevents) { win->anyevents = false; if (win->reshapeEvent) { win->reshapeEvent = false; __glutSetWindow(win); win->reshape(win->m_width, win->m_height); } if (!gState.windowList[i]) continue; // window was destroyed by callback! if (win->displayEvent) { win->displayEvent = false; __glutSetWindow(win); win->display(); } if (!gState.windowList[i]) continue; // window was destroyed by callback! if (win->mouseEvent) { win->mouseEvent = false; __glutSetWindow(win); if (win->mouse) { gState.modifierKeys = win->modifierKeys; win->mouse(win->button, win->mouseState, win->mouseX, win->mouseY); gState.modifierKeys = ~0; } } if (!gState.windowList[i]) continue; // window was destroyed by callback! if (win->menuEvent) { win->menuEvent = false; __glutSetWindow(win); GlutMenu *menu = __glutGetMenuByNum(win->menuNumber); if (menu) { gState.currentMenu = menu; menu->select(win->menuValue); } } if (!gState.windowList[i]) continue; // window was destroyed by callback! if (win->statusEvent) { win->statusEvent = false; __glutSetWindow(win); if (gState.menuStatus) { gState.currentMenu = __glutGetMenuByNum(win->menuNumber); gState.menuStatus(win->menuStatus, win->statusX, win->statusY); } } if (!gState.windowList[i]) continue; // window was destroyed by callback! if (win->motionEvent) { win->motionEvent = false; __glutSetWindow(win); if (win->motion) win->motion(win->motionX, win->motionY); } if (!gState.windowList[i]) continue; // window was destroyed by callback! if (win->passiveEvent) { win->passiveEvent = false; __glutSetWindow(win); if (win->passive) win->passive(win->passiveX, win->passiveY); } if (!gState.windowList[i]) continue; // window was destroyed by callback! if (win->keybEvent) { win->keybEvent = false; __glutSetWindow(win); if (win->keyboard) { gState.modifierKeys = win->modifierKeys; win->keyboard(win->key, win->keyX, win->keyY); gState.modifierKeys = ~0; } } if (!gState.windowList[i]) continue; // window was destroyed by callback! if (win->specialEvent) { win->specialEvent = false; __glutSetWindow(win); if (win->special) { gState.modifierKeys = win->modifierKeys; win->special(win->specialKey, win->specialX, win->specialY); gState.modifierKeys = ~0; } } if (!gState.windowList[i]) continue; // window was destroyed by callback! if (win->keybUpEvent) { win->keybUpEvent = false; __glutSetWindow(win); if (win->keyboardUp) { gState.modifierKeys = win->modifierKeys; win->keyboardUp(win->key, win->keyX, win->keyY); gState.modifierKeys = ~0; } } if (!gState.windowList[i]) continue; // window was destroyed by callback! if (win->specialUpEvent) { win->specialUpEvent = false; __glutSetWindow(win); if (win->specialUp) { gState.modifierKeys = win->modifierKeys; win->specialUp(win->specialKey, win->specialX, win->specialY); gState.modifierKeys = ~0; } } if (!gState.windowList[i]) continue; // window was destroyed by callback! if (win->entryEvent) { win->entryEvent = false; __glutSetWindow(win); if (win->entry) win->entry(win->entryState); } if (!gState.windowList[i]) continue; // window was destroyed by callback! if (win->windowStatusEvent) { win->windowStatusEvent = false; __glutSetWindow(win); if (win->windowStatus) win->windowStatus(win->visState); } if (!gState.windowList[i]) continue; // window was destroyed by callback! } } } if (gState.currentWindow) gState.currentWindow->UnlockGL(); // This code isn't necessary since BGLView automatically traps errors #if 0 if(gState.debug) { for(int i=0; i<gState.windowListSize; i++) { if (gState.windowList[i]) { gState.windowList[i]->LockGL(); glutReportErrors(); gState.windowList[i]->UnlockGL(); } } } #endif if (__glutTimerList) { handleTimeouts(); } }