X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?a=blobdiff_plain;f=src%2Fmswin%2Ffg_main_mswin.c;h=b384b082b0d736d82d4fed76d0830e80ffe76a30;hb=0554602cc69c9b917df41181817b5693158ab961;hp=dccb8ddd83b7060a6a3f9f78b480ffc6186890df;hpb=a00c7ee3552b527ac6b375d6a6ca42f90770ddc3;p=freeglut diff --git a/src/mswin/fg_main_mswin.c b/src/mswin/fg_main_mswin.c index dccb8dd..b384b08 100644 --- a/src/mswin/fg_main_mswin.c +++ b/src/mswin/fg_main_mswin.c @@ -1,5 +1,5 @@ /* - * freeglut_main_mswin.c + * fg_main_mswin.c * * The Windows-specific mouse cursor related stuff. * @@ -184,7 +184,7 @@ static struct WM_MESSAGE_MAP allMessages[] = -# if(_WIN32_WINNT >= 0x0500) +# if(_WIN32_WINNT >= 0x0500) && defined(WM_NCXBUTTONDOWN) DEFINE_MESSAGE(WM_NCXBUTTONDOWN), DEFINE_MESSAGE(WM_NCXBUTTONUP), DEFINE_MESSAGE(WM_NCXBUTTONDBLCLK), @@ -241,7 +241,7 @@ static struct WM_MESSAGE_MAP allMessages[] = DEFINE_MESSAGE(WM_UNINITMENUPOPUP), DEFINE_MESSAGE(WM_MENUCOMMAND), -# if(_WIN32_WINNT >= 0x0500) +# if(_WIN32_WINNT >= 0x0500) && defined(WM_CHANGEUISTATE) DEFINE_MESSAGE(WM_CHANGEUISTATE), DEFINE_MESSAGE(WM_UPDATEUISTATE), DEFINE_MESSAGE(WM_QUERYUISTATE), @@ -272,7 +272,7 @@ static struct WM_MESSAGE_MAP allMessages[] = # if (_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400) DEFINE_MESSAGE(WM_MOUSEWHEEL), # endif -# if (_WIN32_WINNT >= 0x0500) +# if (_WIN32_WINNT >= 0x0500) && defined(WM_XBUTTONDOWN) DEFINE_MESSAGE(WM_XBUTTONDOWN), DEFINE_MESSAGE(WM_XBUTTONUP), DEFINE_MESSAGE(WM_XBUTTONDBLCLK), @@ -364,7 +364,7 @@ static struct WM_MESSAGE_MAP allMessages[] = DEFINE_MESSAGE(WM_MOUSEHOVER), DEFINE_MESSAGE(WM_MOUSELEAVE), # endif -# if(WINVER >= 0x0500) +# if(WINVER >= 0x0500) && defined(WM_NCMOUSEHOVER) DEFINE_MESSAGE(WM_NCMOUSEHOVER), DEFINE_MESSAGE(WM_NCMOUSELEAVE), # endif /* WINVER >= 0x0500 */ @@ -398,7 +398,7 @@ static struct WM_MESSAGE_MAP allMessages[] = DEFINE_MESSAGE(WM_PRINTCLIENT), # endif /* WINVER >= 0x0400 */ -# if(_WIN32_WINNT >= 0x0500) +# if(_WIN32_WINNT >= 0x0500) && defined(WM_APPCOMMAND) DEFINE_MESSAGE(WM_APPCOMMAND), # endif /* _WIN32_WINNT >= 0x0500 */ @@ -578,6 +578,14 @@ static int fgPlatformGetModifiers (void) ( GetKeyState( VK_RMENU ) < 0 )) ? GLUT_ACTIVE_ALT : 0 ); } +/* Check whether a button (VK_*BUTTON) is currently depressed. Returns + * non-zero (not necessarily 1) if yes. */ +static SHORT fgGetKeyState(int vKey) +{ + /* MSDN says: "If the high-order bit is 1, the key is down; otherwise, it is up". */ + return GetKeyState(vKey) & 0xFF00; +} + static LRESULT fghWindowProcKeyPress(SFG_Window *window, UINT uMsg, GLboolean keydown, WPARAM wParam, LPARAM lParam) { static unsigned char lControl = 0, lShift = 0, lAlt = 0, @@ -598,60 +606,60 @@ static LRESULT fghWindowProcKeyPress(SFG_Window *window, UINT uMsg, GLboolean ke fgState.Modifiers = fgPlatformGetModifiers( ); /* Convert the Win32 keystroke codes to GLUTtish way */ -# define KEY(a,b) case a: keypress = b; break; +# define FG_KEY(a,b) case a: keypress = b; break; switch( wParam ) { - KEY( VK_F1, GLUT_KEY_F1 ); - KEY( VK_F2, GLUT_KEY_F2 ); - KEY( VK_F3, GLUT_KEY_F3 ); - KEY( VK_F4, GLUT_KEY_F4 ); - KEY( VK_F5, GLUT_KEY_F5 ); - KEY( VK_F6, GLUT_KEY_F6 ); - KEY( VK_F7, GLUT_KEY_F7 ); - KEY( VK_F8, GLUT_KEY_F8 ); - KEY( VK_F9, GLUT_KEY_F9 ); - KEY( VK_F10, GLUT_KEY_F10 ); - KEY( VK_F11, GLUT_KEY_F11 ); - KEY( VK_F12, GLUT_KEY_F12 ); - KEY( VK_PRIOR, GLUT_KEY_PAGE_UP ); - KEY( VK_NEXT, GLUT_KEY_PAGE_DOWN ); - KEY( VK_HOME, GLUT_KEY_HOME ); - KEY( VK_END, GLUT_KEY_END ); - KEY( VK_LEFT, GLUT_KEY_LEFT ); - KEY( VK_UP, GLUT_KEY_UP ); - KEY( VK_RIGHT, GLUT_KEY_RIGHT ); - KEY( VK_DOWN, GLUT_KEY_DOWN ); - KEY( VK_INSERT, GLUT_KEY_INSERT ); + FG_KEY( VK_F1, GLUT_KEY_F1 ); + FG_KEY( VK_F2, GLUT_KEY_F2 ); + FG_KEY( VK_F3, GLUT_KEY_F3 ); + FG_KEY( VK_F4, GLUT_KEY_F4 ); + FG_KEY( VK_F5, GLUT_KEY_F5 ); + FG_KEY( VK_F6, GLUT_KEY_F6 ); + FG_KEY( VK_F7, GLUT_KEY_F7 ); + FG_KEY( VK_F8, GLUT_KEY_F8 ); + FG_KEY( VK_F9, GLUT_KEY_F9 ); + FG_KEY( VK_F10, GLUT_KEY_F10 ); + FG_KEY( VK_F11, GLUT_KEY_F11 ); + FG_KEY( VK_F12, GLUT_KEY_F12 ); + FG_KEY( VK_PRIOR, GLUT_KEY_PAGE_UP ); + FG_KEY( VK_NEXT, GLUT_KEY_PAGE_DOWN ); + FG_KEY( VK_HOME, GLUT_KEY_HOME ); + FG_KEY( VK_END, GLUT_KEY_END ); + FG_KEY( VK_LEFT, GLUT_KEY_LEFT ); + FG_KEY( VK_UP, GLUT_KEY_UP ); + FG_KEY( VK_RIGHT, GLUT_KEY_RIGHT ); + FG_KEY( VK_DOWN, GLUT_KEY_DOWN ); + FG_KEY( VK_INSERT, GLUT_KEY_INSERT ); /* handle control, alt and shift. For GLUT, we want to distinguish between left and right presses. * The VK_L* & VK_R* left and right Alt, Ctrl and Shift virtual keys are however only used as parameters to GetAsyncKeyState() and GetKeyState() * so when we get an alt, shift or control keypress here, we manually check whether it was the left or the right */ -#define ASYNC_KEY_EVENT(winKey,glutKey,keyStateVar)\ - if (!keyStateVar && GetAsyncKeyState ( winKey ))\ +#define FG_KEY_EVENT(winKey,glutKey,keyStateVar)\ + if (!keyStateVar && fgGetKeyState ( winKey ))\ {\ keypress = glutKey;\ keyStateVar = 1;\ }\ - else if (keyStateVar && !GetAsyncKeyState ( winKey ))\ + else if (keyStateVar && !fgGetKeyState ( winKey ))\ {\ keypress = glutKey;\ keyStateVar = 0;\ } case VK_CONTROL: - ASYNC_KEY_EVENT(VK_LCONTROL,GLUT_KEY_CTRL_L,lControl); - ASYNC_KEY_EVENT(VK_RCONTROL,GLUT_KEY_CTRL_R,rControl); + FG_KEY_EVENT(VK_LCONTROL,GLUT_KEY_CTRL_L,lControl); + FG_KEY_EVENT(VK_RCONTROL,GLUT_KEY_CTRL_R,rControl); break; case VK_SHIFT: - ASYNC_KEY_EVENT(VK_LSHIFT,GLUT_KEY_SHIFT_L,lShift); - ASYNC_KEY_EVENT(VK_RSHIFT,GLUT_KEY_SHIFT_R,rShift); + FG_KEY_EVENT(VK_LSHIFT,GLUT_KEY_SHIFT_L,lShift); + FG_KEY_EVENT(VK_RSHIFT,GLUT_KEY_SHIFT_R,rShift); break; case VK_MENU: - ASYNC_KEY_EVENT(VK_LMENU,GLUT_KEY_ALT_L,lAlt); - ASYNC_KEY_EVENT(VK_RMENU,GLUT_KEY_ALT_R,rAlt); + FG_KEY_EVENT(VK_LMENU,GLUT_KEY_ALT_L,lAlt); + FG_KEY_EVENT(VK_RMENU,GLUT_KEY_ALT_R,rAlt); break; -#undef ASYNC_KEY_EVENT +#undef KEY_EVENT case VK_DELETE: /* The delete key should be treated as an ASCII keypress: */ @@ -744,7 +752,9 @@ SFG_Window* fghWindowUnderCursor(SFG_Window *window) /* Get mouse position at time of message */ DWORD mouse_pos_dw = GetMessagePos(); - POINT mouse_pos = {GET_X_LPARAM(mouse_pos_dw), GET_Y_LPARAM(mouse_pos_dw)}; + POINT mouse_pos; + mouse_pos.x = GET_X_LPARAM(mouse_pos_dw); + mouse_pos.y = GET_Y_LPARAM(mouse_pos_dw); ScreenToClient( window->Window.Handle, &mouse_pos ); hwnd = ChildWindowFromPoint(window->Window.Handle, mouse_pos); @@ -939,7 +949,9 @@ LRESULT CALLBACK fgPlatformWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPAR /* For child window, we should return relative to upper-left * of parent's client area. */ - POINT topleft = {windowRect.left,windowRect.top}; + POINT topleft; + topleft.x = windowRect.left; + topleft.y = windowRect.top; ScreenToClient(window->Parent->Window.Handle,&topleft); windowRect.left = topleft.x; @@ -1237,7 +1249,7 @@ LRESULT CALLBACK fgPlatformWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPAR SetCapture ( window->Window.Handle ) ; setCaptureActive = 1; /* Set to false in WM_CAPTURECHANGED handler */ } - else if (!GetAsyncKeyState(VK_LBUTTON) && !GetAsyncKeyState(VK_MBUTTON) && !GetAsyncKeyState(VK_RBUTTON)) + else if (!fgGetKeyState(VK_LBUTTON) && !fgGetKeyState(VK_MBUTTON) && !fgGetKeyState(VK_RBUTTON)) /* Make sure all mouse buttons are released before releasing capture */ ReleaseCapture () ; @@ -1275,7 +1287,7 @@ LRESULT CALLBACK fgPlatformWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPAR */ #else /* int modkeys = GET_KEYSTATE_WPARAM( wParam ); */ - short ticks = GET_WHEEL_DELTA_WPARAM( wParam ); + short ticks = HIWORD( wParam ); /* commented out as should not be needed here, mouse motion is processed in WM_MOUSEMOVE first: window->State.MouseX = GET_X_LPARAM( lParam ); window->State.MouseY = GET_Y_LPARAM( lParam ); @@ -1531,6 +1543,14 @@ LRESULT CALLBACK fgPlatformWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPAR break; } #endif + //Added by Jinrong Xie (stonexjr@gmail.com) 12/24/2014 + //for SpaceNavigator support on Windows. + case WM_INPUT: + if (fgHasSpaceball()) + { + fgSpaceballHandleWinEvent(hWnd, wParam, lParam); + } + break; default: /* Handle unhandled messages */ lRet = DefWindowProc( hWnd, uMsg, wParam, lParam ); @@ -1541,251 +1561,217 @@ LRESULT CALLBACK fgPlatformWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPAR } -/* Step through the work list */ -void fgPlatformProcessWork(SFG_Window *window) +/* deal with work list items */ +void fgPlatformInitWork(SFG_Window* window) { - unsigned int workMask = window->State.WorkMask; - /* Now clear it so that any callback generated by the actions below can set work again */ - window->State.WorkMask = 0; - - if (workMask&~GLUT_DISPLAY_WORK) /* Display work is the common case, skip all the below at once */ - { - /* This is before the first display callback: call a few callbacks to inform user of window size, position, etc - * we know this is before the first display callback of a window as for all windows GLUT_INIT_WORK is set when - * they are opened, and work is done before displaying in the mainloop. - */ - if (workMask & GLUT_INIT_WORK) - { - RECT windowRect; + RECT windowRect; - /* Notify windowStatus/visibility */ - fghPlatformOnWindowStatusNotify(window, window->State.Visible, GL_TRUE); + /* Notify windowStatus/visibility */ + fghPlatformOnWindowStatusNotify(window, window->State.Visible, GL_TRUE); - /* get and notify window's position */ - GetWindowRect(window->Window.Handle,&windowRect); - fghOnPositionNotify(window, windowRect.left, windowRect.top, GL_TRUE); + /* get and notify window's position */ + GetWindowRect(window->Window.Handle,&windowRect); + fghOnPositionNotify(window, windowRect.left, windowRect.top, GL_TRUE); - /* get and notify window's size */ - GetClientRect(window->Window.Handle,&windowRect); - fghOnReshapeNotify(window, windowRect.right-windowRect.left, windowRect.bottom-windowRect.top, GL_TRUE); - - /* Call init context callback */ - INVOKE_WCB( *window, InitContext, ()); + /* get and notify window's size */ + GetClientRect(window->Window.Handle,&windowRect); + fghOnReshapeNotify(window, windowRect.right-windowRect.left, windowRect.bottom-windowRect.top, GL_TRUE); +} - /* Lastly, check if we have a display callback, error out if not - * This is the right place to do it, as the redisplay will be - * next right after we exit this function, so there is no more - * opportunity for the user to register a callback for this window. - */ - if (!FETCH_WCB(*window, Display)) - fgError ( "ERROR: No display callback registered for window %d\n", window->ID ); - } +/* On windows we can position, resize and change z order at the same time */ +void fgPlatformPosResZordWork(SFG_Window* window, unsigned int workMask) +{ + UINT flags = SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOOWNERZORDER | SWP_NOSENDCHANGING | SWP_NOSIZE | SWP_NOZORDER; + HWND insertAfter = HWND_TOP; + RECT clientRect; - /* On windows we can position, resize and change z order at the same time */ - if (workMask & (GLUT_POSITION_WORK|GLUT_SIZE_WORK|GLUT_ZORDER_WORK|GLUT_FULL_SCREEN_WORK)) +#if !defined(_WIN32_WCE) /* FIXME: what about WinCE */ + if (workMask & GLUT_FULL_SCREEN_WORK) { - UINT flags = SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOOWNERZORDER | SWP_NOSENDCHANGING | SWP_NOSIZE | SWP_NOZORDER; - HWND insertAfter = HWND_TOP; - RECT clientRect; + /* This asks us to toggle fullscreen mode */ + flags |= SWP_FRAMECHANGED; -#if !defined(_WIN32_WCE) /* FIXME: what about WinCE */ - if (workMask & GLUT_FULL_SCREEN_WORK) + if (window->State.IsFullscreen) { - /* This asks us to toggle fullscreen mode */ - flags |= SWP_FRAMECHANGED; + /* If we are fullscreen, resize the current window back to its original size */ + /* printf("OldRect %i,%i to %i,%i\n",window->State.pWState.OldRect.left,window->State.pWState.OldRect.top,window->State.pWState.OldRect.right,window->State.pWState.OldRect.bottom); */ - if (window->State.IsFullscreen) - { - /* If we are fullscreen, resize the current window back to its original size */ - /* printf("OldRect %i,%i to %i,%i\n",window->State.pWState.OldRect.left,window->State.pWState.OldRect.top,window->State.pWState.OldRect.right,window->State.pWState.OldRect.bottom); */ + /* restore style of window before making it fullscreen */ + SetWindowLong(window->Window.Handle, GWL_STYLE, window->State.pWState.OldStyle); + SetWindowLong(window->Window.Handle, GWL_EXSTYLE, window->State.pWState.OldStyleEx); - /* restore style of window before making it fullscreen */ - SetWindowLong(window->Window.Handle, GWL_STYLE, window->State.pWState.OldStyle); - SetWindowLong(window->Window.Handle, GWL_EXSTYLE, window->State.pWState.OldStyleEx); - - /* Then set up resize/reposition, unless user already queued up reshape/position work */ - if (!(workMask & GLUT_POSITION_WORK)) - { - workMask |= GLUT_POSITION_WORK; - window->State.DesiredXpos = window->State.pWState.OldRect.left; - window->State.DesiredYpos = window->State.pWState.OldRect.top; - } - if (!(workMask & GLUT_SIZE_WORK)) - { - workMask |= GLUT_SIZE_WORK; - window->State.DesiredWidth = window->State.pWState.OldRect.right - window->State.pWState.OldRect.left; - window->State.DesiredHeight = window->State.pWState.OldRect.bottom - window->State.pWState.OldRect.top; - } - - /* We'll finish off the fullscreen operation below after the other GLUT_POSITION_WORK|GLUT_SIZE_WORK|GLUT_ZORDER_WORK */ + /* Then set up resize/reposition, unless user already queued up reshape/position work */ + if (!(workMask & GLUT_POSITION_WORK)) + { + workMask |= GLUT_POSITION_WORK; + window->State.DesiredXpos = window->State.pWState.OldRect.left; + window->State.DesiredYpos = window->State.pWState.OldRect.top; } - else + if (!(workMask & GLUT_SIZE_WORK)) { - /* we are currently not fullscreen, go to fullscreen: - * remove window decoration and then maximize - */ - RECT rect; - HMONITOR hMonitor; - MONITORINFO mi; - - /* save current window rect, style, exstyle and maximized state */ - window->State.pWState.OldMaximized = !!IsZoomed(window->Window.Handle); - if (window->State.pWState.OldMaximized) - /* We force the window into restored mode before going - * fullscreen because Windows doesn't seem to hide the - * taskbar if the window is in the maximized state. - */ - SendMessage(window->Window.Handle, WM_SYSCOMMAND, SC_RESTORE, 0); - - fghGetClientArea( &window->State.pWState.OldRect, window, GL_TRUE ); - window->State.pWState.OldStyle = GetWindowLong(window->Window.Handle, GWL_STYLE); - window->State.pWState.OldStyleEx = GetWindowLong(window->Window.Handle, GWL_EXSTYLE); - - /* remove decorations from style */ - SetWindowLong(window->Window.Handle, GWL_STYLE, - window->State.pWState.OldStyle & ~(WS_CAPTION | WS_THICKFRAME)); - SetWindowLong(window->Window.Handle, GWL_EXSTYLE, - window->State.pWState.OldStyleEx & ~(WS_EX_DLGMODALFRAME | - WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE | WS_EX_STATICEDGE)); - - /* For fullscreen mode, find the monitor that is covered the most - * by the window and get its rect as the resize target. - */ - GetWindowRect(window->Window.Handle, &rect); - hMonitor= MonitorFromRect(&rect, MONITOR_DEFAULTTONEAREST); - mi.cbSize = sizeof(mi); - GetMonitorInfo(hMonitor, &mi); - rect = mi.rcMonitor; - - /* then setup window resize, overwriting other work queued on the window */ - window->State.WorkMask |= GLUT_POSITION_WORK | GLUT_SIZE_WORK; - window->State.WorkMask &= ~GLUT_ZORDER_WORK; - window->State.DesiredXpos = rect.left; - window->State.DesiredYpos = rect.top; - window->State.DesiredWidth = rect.right - rect.left; - window->State.DesiredHeight = rect.bottom - rect.top; + workMask |= GLUT_SIZE_WORK; + window->State.DesiredWidth = window->State.pWState.OldRect.right - window->State.pWState.OldRect.left; + window->State.DesiredHeight = window->State.pWState.OldRect.bottom - window->State.pWState.OldRect.top; } + + /* We'll finish off the fullscreen operation below after the other GLUT_POSITION_WORK|GLUT_SIZE_WORK|GLUT_ZORDER_WORK */ } + else + { + /* we are currently not fullscreen, go to fullscreen: + * remove window decoration and then maximize + */ + RECT rect; + HMONITOR hMonitor; + MONITORINFO mi; + + /* save current window rect, style, exstyle and maximized state */ + window->State.pWState.OldMaximized = !!IsZoomed(window->Window.Handle); + if (window->State.pWState.OldMaximized) + /* We force the window into restored mode before going + * fullscreen because Windows doesn't seem to hide the + * taskbar if the window is in the maximized state. + */ + SendMessage(window->Window.Handle, WM_SYSCOMMAND, SC_RESTORE, 0); + + fghGetClientArea( &window->State.pWState.OldRect, window, GL_TRUE ); + window->State.pWState.OldStyle = GetWindowLong(window->Window.Handle, GWL_STYLE); + window->State.pWState.OldStyleEx = GetWindowLong(window->Window.Handle, GWL_EXSTYLE); + + /* remove decorations from style */ + SetWindowLong(window->Window.Handle, GWL_STYLE, + window->State.pWState.OldStyle & ~(WS_CAPTION | WS_THICKFRAME)); + SetWindowLong(window->Window.Handle, GWL_EXSTYLE, + window->State.pWState.OldStyleEx & ~(WS_EX_DLGMODALFRAME | + WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE | WS_EX_STATICEDGE)); + + /* For fullscreen mode, find the monitor that is covered the most + * by the window and get its rect as the resize target. + */ + hMonitor= MonitorFromWindow(window->Window.Handle, MONITOR_DEFAULTTONEAREST); + mi.cbSize = sizeof(mi); + GetMonitorInfo(hMonitor, &mi); + rect = mi.rcMonitor; + + /* then setup window resize, overwriting other work queued on the window */ + window->State.WorkMask |= GLUT_POSITION_WORK | GLUT_SIZE_WORK; + window->State.WorkMask &= ~GLUT_ZORDER_WORK; + window->State.DesiredXpos = rect.left; + window->State.DesiredYpos = rect.top; + window->State.DesiredWidth = rect.right - rect.left; + window->State.DesiredHeight = rect.bottom - rect.top; + } + } #endif /*!defined(_WIN32_WCE) */ - /* Now deal with normal position, reshape and z order requests (some might have been set when handling GLUT_FULLSCREEN_WORK above */ + /* Now deal with normal position, reshape and z order requests (some might have been set when handling GLUT_FULLSCREEN_WORK above */ + { + /* get rect describing window's current position and size, + * in screen coordinates and in FreeGLUT format + * (size (right-left, bottom-top) is client area size, top and left + * are outside of window including decorations). + */ + fghGetClientArea( &clientRect, window, TRUE ); + + if (workMask & GLUT_POSITION_WORK) { - /* get rect describing window's current position and size, - * in screen coordinates and in FreeGLUT format - * (size (right-left, bottom-top) is client area size, top and left - * are outside of window including decorations). - */ - fghGetClientArea( &clientRect, window, TRUE ); - - if (workMask & GLUT_POSITION_WORK) - { - flags &= ~SWP_NOMOVE; + flags &= ~SWP_NOMOVE; - /* Move rect so that top-left is at requested position */ - /* This also automatically makes sure that child window requested coordinates are relative - * to top-left of parent's client area (needed input for SetWindowPos on child windows), - * so no need to further correct rect for child windows below (childs don't have decorations either). - */ - OffsetRect(&clientRect,window->State.DesiredXpos-clientRect.left,window->State.DesiredYpos-clientRect.top); - } - if (workMask & GLUT_SIZE_WORK) - { - flags &= ~SWP_NOSIZE; + /* Move rect so that top-left is at requested position */ + /* This also automatically makes sure that child window requested coordinates are relative + * to top-left of parent's client area (needed input for SetWindowPos on child windows), + * so no need to further correct rect for child windows below (childs don't have decorations either). + */ + OffsetRect(&clientRect,window->State.DesiredXpos-clientRect.left,window->State.DesiredYpos-clientRect.top); + } + if (workMask & GLUT_SIZE_WORK) + { + flags &= ~SWP_NOSIZE; - /* Note on maximizing behavior of Windows: the resize borders are off - * the screen such that the client area extends all the way from the - * leftmost corner to the rightmost corner to maximize screen real - * estate. A caption is still shown however to allow interaction with - * the window controls. This is default behavior of Windows that - * FreeGLUT sticks with. To alter, one would have to check if - * WS_MAXIMIZE style is set when a resize event is triggered, and - * then manually correct the windowRect to put the borders back on - * screen. - */ - - /* Set new size of window, WxH specify client area */ - clientRect.right = clientRect.left + window->State.DesiredWidth; - clientRect.bottom = clientRect.top + window->State.DesiredHeight; - } - if (workMask & GLUT_ZORDER_WORK) - { - flags &= ~SWP_NOZORDER; - - /* Could change this to push it down or up one window at a time with some - * more code using GetWindow with GW_HWNDPREV and GW_HWNDNEXT. - * What would be consistent with X11? Win32 GLUT does what we do here... - */ - if (window->State.DesiredZOrder < 0) - insertAfter = HWND_BOTTOM; - } + /* Note on maximizing behavior of Windows: the resize borders are off + * the screen such that the client area extends all the way from the + * leftmost corner to the rightmost corner to maximize screen real + * estate. A caption is still shown however to allow interaction with + * the window controls. This is default behavior of Windows that + * FreeGLUT sticks with. To alter, one would have to check if + * WS_MAXIMIZE style is set when a resize event is triggered, and + * then manually correct the windowRect to put the borders back on + * screen. + */ + + /* Set new size of window, WxH specify client area */ + clientRect.right = clientRect.left + window->State.DesiredWidth; + clientRect.bottom = clientRect.top + window->State.DesiredHeight; } - - /* Adjust for window decorations - * Child windows don't have decoration, so no need to correct - */ - if (!window->Parent) - /* get the window rect from this to feed to SetWindowPos, correct for window decorations */ - fghComputeWindowRectFromClientArea_QueryWindow(&clientRect,window,TRUE); - - /* Do the requested positioning, moving, and z order push/pop. */ - SetWindowPos( window->Window.Handle, - insertAfter, - clientRect.left, clientRect.top, - clientRect.right - clientRect.left, - clientRect.bottom- clientRect.top, - flags - ); - - /* Finish off the fullscreen operation we were doing, if any */ - if (workMask & GLUT_FULL_SCREEN_WORK) + if (workMask & GLUT_ZORDER_WORK) { - if (window->State.IsFullscreen) - { - /* leaving fullscreen, restore maximized state, if any */ - if (window->State.pWState.OldMaximized) - SendMessage(window->Window.Handle, WM_SYSCOMMAND, SC_MAXIMIZE, 0); - - window->State.IsFullscreen = GL_FALSE; - } - else - window->State.IsFullscreen = GL_TRUE; + flags &= ~SWP_NOZORDER; + + /* Could change this to push it down or up one window at a time with some + * more code using GetWindow with GW_HWNDPREV and GW_HWNDNEXT. + * What would be consistent with X11? Win32 GLUT does what we do here... + */ + if (window->State.DesiredZOrder < 0) + insertAfter = HWND_BOTTOM; } } - if (workMask & GLUT_VISIBILITY_WORK) + /* Adjust for window decorations + * Child windows don't have decoration, so no need to correct + */ + if (!window->Parent) + /* get the window rect from this to feed to SetWindowPos, correct for window decorations */ + fghComputeWindowRectFromClientArea_QueryWindow(&clientRect,window,TRUE); + + /* Do the requested positioning, moving, and z order push/pop. */ + SetWindowPos( window->Window.Handle, + insertAfter, + clientRect.left, clientRect.top, + clientRect.right - clientRect.left, + clientRect.bottom- clientRect.top, + flags + ); + + /* Finish off the fullscreen operation we were doing, if any */ + if (workMask & GLUT_FULL_SCREEN_WORK) { - /* Visibility status of window gets updated in the WM_SHOWWINDOW and WM_SIZE handlers */ - int cmdShow = 0; - SFG_Window *win = window; - switch (window->State.DesiredVisibility) + if (window->State.IsFullscreen) { - case DesireHiddenState: - cmdShow = SW_HIDE; - break; - case DesireIconicState: - cmdShow = SW_MINIMIZE; - /* Call on top-level window */ - while (win->Parent) - win = win->Parent; - break; - case DesireNormalState: - if (win->IsMenu && (!fgStructure.GameModeWindow || win->ActiveMenu->ParentWindow != fgStructure.GameModeWindow)) - cmdShow = SW_SHOWNA; /* Just show, don't activate window if its a menu. Only exception is when the parent is a gamemode window as the menu would pop under it when we do this... */ - else - cmdShow = SW_SHOW; - break; - } + /* leaving fullscreen, restore maximized state, if any */ + if (window->State.pWState.OldMaximized) + SendMessage(window->Window.Handle, WM_SYSCOMMAND, SC_MAXIMIZE, 0); - ShowWindow( win->Window.Handle, cmdShow ); - } + window->State.IsFullscreen = GL_FALSE; + } + else + window->State.IsFullscreen = GL_TRUE; } +} - if (workMask & GLUT_DISPLAY_WORK) - { - if( window->State.Visible ) - fghRedrawWindow ( window ); - /* Strip out display work that might have ended up on work list now as some of the above genereates callbacks */ - window->State.WorkMask &= ~GLUT_DISPLAY_WORK; +void fgPlatformVisibilityWork(SFG_Window* window) +{ + /* Visibility status of window gets updated in the WM_SHOWWINDOW and WM_SIZE handlers */ + int cmdShow = 0; + SFG_Window *win = window; + switch (window->State.DesiredVisibility) + { + case DesireHiddenState: + cmdShow = SW_HIDE; + break; + case DesireIconicState: + cmdShow = SW_MINIMIZE; + /* Call on top-level window */ + while (win->Parent) + win = win->Parent; + break; + case DesireNormalState: + if (win->IsMenu && !fgStructure.GameModeWindow) + cmdShow = SW_SHOWNA; /* Just show, don't activate window if its a menu. Only exception is when there is a gamemode window as the menu would pop under it when we do this... */ + else + cmdShow = SW_SHOW; + break; } -} \ No newline at end of file + + ShowWindow( win->Window.Handle, cmdShow ); +}