X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?a=blobdiff_plain;f=src%2Fmswin%2Ffg_window_mswin.c;h=641ea53410b583a433514f15ab183ae9cc4c8219;hb=daa90bda29db30afb45cc64b02a10b1994e2de94;hp=2837c5c1cdaa8db0a1b355b345dd76ec94078ef3;hpb=1bc8c778760ebbba826f2795a0f30e1ef2d47ec8;p=freeglut diff --git a/src/mswin/fg_window_mswin.c b/src/mswin/fg_window_mswin.c index 2837c5c..641ea53 100644 --- a/src/mswin/fg_window_mswin.c +++ b/src/mswin/fg_window_mswin.c @@ -85,13 +85,6 @@ typedef BOOL (WINAPI *pRegisterTouchWindow)(HWND,ULONG); static pRegisterTouchWindow fghRegisterTouchWindow = (pRegisterTouchWindow)0xDEADBEEF; #endif -/* - * Helper functions for getting client area from the window rect - * and the window rect from the client area given the style of the window - * (or a valid window pointer from which the style can be queried). - */ -extern void fghGetBorderWidth(const DWORD windowStyle, int* xBorderWidth, int* yBorderWidth); - /* * Setup the pixel format for a Win32 window @@ -240,7 +233,7 @@ static void fghFillPFD( PIXELFORMATDESCRIPTOR *ppfd, HDC hdc, unsigned char laye ppfd->cDepthBits = 24; ppfd->cStencilBits = 8; - ppfd->cAuxBuffers = fghNumberOfAuxBuffersRequested(); + ppfd->cAuxBuffers = (BYTE) fghNumberOfAuxBuffersRequested(); ppfd->iLayerType = layer_type; ppfd->bReserved = 0; ppfd->dwLayerMask = 0; @@ -378,6 +371,39 @@ void fgPlatformSetWindow ( SFG_Window *window ) } +void fghGetDefaultWindowStyle(DWORD *flags) +{ + if ( fgState.DisplayMode & GLUT_BORDERLESS ) + { + /* no window decorations needed, no-op */ + } + else if ( fgState.DisplayMode & GLUT_CAPTIONLESS ) + /* only window decoration is a border, no title bar or buttons */ + (*flags) |= WS_DLGFRAME; + else + /* window decoration are a border, title bar and buttons. */ + (*flags) |= WS_OVERLAPPEDWINDOW; +} + +/* Get window style and extended window style of a FreeGLUT window + * If the window pointer or the window handle is NULL, a fully + * decorated window (caption and border) is assumed. + */ +void fghGetStyleFromWindow( const SFG_Window *window, DWORD *windowStyle, DWORD *windowExStyle ) +{ + if (window && window->Window.Handle) + { + *windowStyle = GetWindowLong(window->Window.Handle, GWL_STYLE); + *windowExStyle = GetWindowLong(window->Window.Handle, GWL_EXSTYLE); + } + else + { + *windowStyle = 0; + fghGetDefaultWindowStyle(windowStyle); + /* WindowExStyle==0 is fine/default, exStyle is currently only used for menu windows */ + *windowExStyle = 0; + } +} /* Computes position of corners of window Rect (outer position including * decorations) based on the provided client rect and based on the style @@ -388,35 +414,25 @@ void fgPlatformSetWindow ( SFG_Window *window ) * (rect.right-rect.left,rect.bottom-rect.top) is the size of the drawable * area. */ -void fghComputeWindowRectFromClientArea_UseStyle( const DWORD windowStyle, RECT *clientRect, BOOL posIsOutside ) +void fghComputeWindowRectFromClientArea_UseStyle( RECT *clientRect, const DWORD windowStyle, const DWORD windowExStyle, BOOL posIsOutside ) { - int xBorderWidth = 0, yBorderWidth = 0; + RECT windowRect = {0,0,0,0}; + CopyRect(&windowRect,clientRect); - /* If window has title bar, correct rect for it */ - if (windowStyle & WS_MAXIMIZEBOX) /* Need to query for WS_MAXIMIZEBOX to see if we have a title bar, the WS_CAPTION query is also true for a WS_DLGFRAME only... */ - { - if (posIsOutside) - clientRect->bottom += GetSystemMetrics( SM_CYCAPTION ); - else - clientRect->top -= GetSystemMetrics( SM_CYCAPTION ); - } + /* Get rect including non-client area */ + AdjustWindowRectEx(&windowRect,windowStyle,FALSE,windowExStyle); - /* get width of window's borders (frame), correct rect for it. - * Note, borders can be of zero width if style does not specify borders - */ - fghGetBorderWidth(windowStyle, &xBorderWidth, &yBorderWidth); + /* Move window right and down by non-client area extent on left and top, if wanted */ if (posIsOutside) { - clientRect->right += xBorderWidth * 2; - clientRect->bottom += yBorderWidth * 2; - } - else - { - clientRect->left -= xBorderWidth; - clientRect->right += xBorderWidth; - clientRect->top -= yBorderWidth; - clientRect->bottom += yBorderWidth; + windowRect.right += clientRect->left-windowRect.left; + windowRect.bottom += clientRect->top -windowRect.top; + windowRect.left = clientRect->left; + windowRect.top = clientRect->top; } + + /* done, copy windowRect to output */ + CopyRect(clientRect,&windowRect); } /* Computes position of corners of window Rect (outer position including @@ -429,114 +445,49 @@ void fghComputeWindowRectFromClientArea_UseStyle( const DWORD windowStyle, RECT * (rect.right-rect.left,rect.bottom-rect.top) is the size of the drawable * area. */ -void fghComputeWindowRectFromClientArea_QueryWindow( const SFG_Window *window, RECT *clientRect, BOOL posIsOutside ) +void fghComputeWindowRectFromClientArea_QueryWindow( RECT *clientRect, const SFG_Window *window, BOOL posIsOutside ) { - DWORD windowStyle = 0; - - if (window && window->Window.Handle) - windowStyle = GetWindowLong(window->Window.Handle, GWL_STYLE); - else - windowStyle = WS_OVERLAPPEDWINDOW; + DWORD windowStyle = 0, windowExStyle = 0; + fghGetStyleFromWindow(window,&windowStyle,&windowExStyle); - fghComputeWindowRectFromClientArea_UseStyle(windowStyle, clientRect, posIsOutside); -} - -/* Computes position of corners of client area (drawable area) of a window - * based on the provided window Rect (outer position including decorations) - * and based on the style of the window in question. If the window pointer - * or the window handle is NULL, a fully decorated window (caption and - * border) is assumed. - * Furthermore, if wantPosOutside is set to true, the output client Rect - * will follow freeGLUT's window specification convention in which the - * top-left corner is at the outside of the window, the size - * (rect.right-rect.left,rect.bottom-rect.top) is the size of the drawable - * area. - */ -void fghComputeClientAreaFromWindowRect( const SFG_Window *window, RECT *windowRect, BOOL wantPosOutside ) -{ - DWORD windowStyle = 0; - int xBorderWidth = 0, yBorderWidth = 0; - - if (window && window->Window.Handle) - windowStyle = GetWindowLong(window->Window.Handle, GWL_STYLE); - else - windowStyle = WS_OVERLAPPEDWINDOW; - - /* If window has title bar, correct rect for it */ - if (windowStyle & WS_MAXIMIZEBOX) /* Need to query for WS_MAXIMIZEBOX to see if we have a title bar, the WS_CAPTION query is also true for a WS_DLGFRAME only... */ - { - if (wantPosOutside) - windowRect->bottom -= GetSystemMetrics( SM_CYCAPTION ); - else - windowRect->top += GetSystemMetrics( SM_CYCAPTION ); - } - - /* get width of window's borders (frame), correct rect for it. - * Note, borders can be of zero width if style does not specify borders - */ - fghGetBorderWidth(windowStyle, &xBorderWidth, &yBorderWidth); - if (wantPosOutside) - { - windowRect->right -= xBorderWidth * 2; - windowRect->bottom -= yBorderWidth * 2; - } - else - { - windowRect->left += xBorderWidth; - windowRect->right -= xBorderWidth; - windowRect->top += yBorderWidth; - windowRect->bottom -= yBorderWidth; - } + fghComputeWindowRectFromClientArea_UseStyle(clientRect, windowStyle, windowExStyle, posIsOutside); } /* Gets the rect describing the client area (drawable area) of the - * specified window. - * Returns an empty rect if window pointer or window handle is NULL. - * If wantPosOutside is set to true, the output client Rect - * will follow freeGLUT's window specification convention in which the - * top-left corner is at the outside of the window, while the size - * (rect.right-rect.left,rect.bottom-rect.top) is the size of the drawable - * area. + * specified window. Output is position of corners of client area (drawable area) on the screen. + * Does not touch clientRect if window pointer or window handle is NULL. + * (rect.right-rect.left,rect.bottom-rect.top) is the size of the drawable area. + * if posIsOutside is true, the output client Rect will follow freeGLUT's window + * specification convention in which the top-left corner is at the outside of + * the window, while the size (rect.right-rect.left,rect.bottom-rect.top) remains to be the + * size of the drawable area. */ -RECT fghGetClientArea( const SFG_Window *window, BOOL wantPosOutside ) +void fghGetClientArea( RECT *clientRect, const SFG_Window *window, BOOL posIsOutside ) { - RECT windowRect = {0,0,0,0}; + POINT topLeftClient = {0,0}; - freeglut_return_val_if_fail((window && window->Window.Handle),windowRect); + freeglut_return_if_fail((window && window->Window.Handle)); - /* - * call GetWindowRect() - * (this returns the pixel coordinates of the outside of the window) - */ - GetWindowRect( window->Window.Handle, &windowRect ); - - /* Then correct the results */ - fghComputeClientAreaFromWindowRect(window, &windowRect, wantPosOutside); - - return windowRect; -} - -/* Returns the width of the window borders based on the window's style. - */ -void fghGetBorderWidth(const DWORD windowStyle, int* xBorderWidth, int* yBorderWidth) -{ - if (windowStyle & WS_THICKFRAME) - { - *xBorderWidth = GetSystemMetrics(SM_CXSIZEFRAME); - *yBorderWidth = GetSystemMetrics(SM_CYSIZEFRAME); - } - else if (windowStyle & WS_DLGFRAME) + /* Get size of client rect */ + GetClientRect(window->Window.Handle, clientRect); + if (posIsOutside) { - *xBorderWidth = GetSystemMetrics(SM_CXFIXEDFRAME); - *yBorderWidth = GetSystemMetrics(SM_CYFIXEDFRAME); + RECT windowRect; + /* Get position of outside of window, including decorations */ + GetWindowRect(window->Window.Handle,&windowRect); + /* Add top-left offset */ + OffsetRect(clientRect,windowRect.left,windowRect.top); } else { - *xBorderWidth = 0; - *yBorderWidth = 0; + /* Get position of top-left of client area on the screen */ + ClientToScreen(window->Window.Handle,&topLeftClient); + /* Add top-left offset */ + OffsetRect(clientRect,topLeftClient.x,topLeftClient.y); } } + #if(WINVER >= 0x500) typedef struct { @@ -619,7 +570,7 @@ void fgPlatformOpenWindow( SFG_Window* window, const char* title, WNDCLASS wc; DWORD flags = 0; DWORD exFlags = 0; - ATOM atom; + BOOL atom; /* Grab the window class we have registered on glutInit(): */ atom = GetClassInfo( fgDisplay.pDisplay.Instance, _T("FREEGLUT"), &wc ); @@ -655,23 +606,9 @@ void fgPlatformOpenWindow( SFG_Window* window, const char* title, #if defined(_WIN32_WCE) /* no decorations for windows CE */ #else - /* if this is not a subwindow (child), set its style based on the requested display mode */ + /* if this is not a subwindow (child), set its style based on the requested window decorations */ else if( window->Parent == NULL ) - if ( fgState.DisplayMode & GLUT_BORDERLESS ) - { - /* no window decorations needed */ - } - else if ( fgState.DisplayMode & GLUT_CAPTIONLESS ) - /* only window decoration is a border, no title bar or buttons */ - flags |= WS_DLGFRAME; - else - /* window decoration are a border, title bar and buttons. - * NB: we later query whether the window has a title bar or - * not by testing for the maximize button, as the test for - * WS_CAPTION can be true without the window having a title - * bar. This style WS_OVERLAPPEDWINDOW gives you a maximize - * button. */ - flags |= WS_OVERLAPPEDWINDOW; + fghGetDefaultWindowStyle(&flags); #endif else /* subwindows always have no decoration, but are marked as a child window to the OS */ @@ -699,20 +636,11 @@ void fgPlatformOpenWindow( SFG_Window* window, const char* title, } if( !sizeUse ) { - if( ! window->IsMenu ) - { - w = CW_USEDEFAULT; - h = CW_USEDEFAULT; - } - else /* fail safe - Windows can make a window of size (0, 0) */ - w = h = 300; /* default window size */ + w = CW_USEDEFAULT; + h = CW_USEDEFAULT; } - /* store requested client area width and height */ - window->State.Width = w; - window->State.Height = h; - -#if !defined(_WIN32_WCE) /* no decorations for windows CE */ - if( sizeUse ) +#if !defined(_WIN32_WCE) /* no decorations for windows CE, so nothing to do */ + else { RECT windowRect; /* @@ -728,8 +656,9 @@ void fgPlatformOpenWindow( SFG_Window* window, const char* title, windowRect.right = x+w; windowRect.bottom = y+h; - fghComputeWindowRectFromClientArea_UseStyle(flags,&windowRect,TRUE); + fghComputeWindowRectFromClientArea_UseStyle(&windowRect,flags,exFlags,TRUE); + /* NB: w and h are now width and height of window including non-client area! */ w = windowRect.right - windowRect.left; h = windowRect.bottom- windowRect.top; } @@ -773,9 +702,14 @@ void fgPlatformOpenWindow( SFG_Window* window, const char* title, ); #endif /* defined(_WIN32_WCE) */ + /* WM_CREATE message got sent and was handled by window proc */ + if( !( window->Window.Handle ) ) fgError( "Failed to create a window (%s)!", title ); + /* Store title */ + window->State.pWState.WindowTitle = strdup(title); + #if !defined(_WIN32_WCE) /* Need to set requested style again, apparently Windows doesn't listen when requesting windows without title bar or borders */ SetWindowLong(window->Window.Handle, GWL_STYLE, flags); @@ -802,12 +736,15 @@ void fgPlatformOpenWindow( SFG_Window* window, const char* title, #if defined(_WIN32_WCE) ShowWindow( window->Window.Handle, SW_SHOW ); #else - ShowWindow( window->Window.Handle, - fgState.ForceIconic ? SW_SHOWMINIMIZED : SW_SHOW ); + if (!window->IsMenu) /* Don't show window after creation if its a menu */ + { + BOOL iconic = fgState.ForceIconic && !gameMode && !isSubWindow; + ShowWindow( window->Window.Handle, + iconic ? SW_SHOWMINIMIZED : SW_SHOWNORMAL ); + } #endif /* defined(_WIN32_WCE) */ - UpdateWindow( window->Window.Handle ); - ShowCursor( TRUE ); /* XXX Old comments say "hide cursor"! */ + ShowCursor( TRUE ); } @@ -842,33 +779,23 @@ void fgPlatformCloseWindow( SFG_Window* window ) } DestroyWindow( window->Window.Handle ); -} - - -/* - * This function makes the current window visible - */ -void fgPlatformGlutShowWindow( void ) -{ - ShowWindow( fgStructure.CurrentWindow->Window.Handle, SW_SHOW ); + /* clean up copied title text(s) */ + if (window->State.pWState.WindowTitle) + free(window->State.pWState.WindowTitle); + if (window->State.pWState.IconTitle) + free(window->State.pWState.IconTitle); } /* - * This function hides the current window + * Hide's specified window. For windows, currently only used + * to immediately hide menu windows... */ -void fgPlatformGlutHideWindow( void ) +void fgPlatformHideWindow( SFG_Window* window ) { - ShowWindow( fgStructure.CurrentWindow->Window.Handle, SW_HIDE ); + ShowWindow(window->Window.Handle, SW_HIDE); } -/* - * Iconify the current window (top-level windows only) - */ -void fgPlatformGlutIconifyWindow( void ) -{ - ShowWindow( fgStructure.CurrentWindow->Window.Handle, SW_MINIMIZE ); -} /* * Set the current window's title @@ -882,198 +809,30 @@ void fgPlatformGlutSetWindowTitle( const char* title ) free(wstr); } #else - SetWindowText( fgStructure.CurrentWindow->Window.Handle, title ); + if (!IsIconic(fgStructure.CurrentWindow->Window.Handle)) + SetWindowText( fgStructure.CurrentWindow->Window.Handle, title ); #endif + + /* Make copy of string to refer to later */ + if (fgStructure.CurrentWindow->State.pWState.WindowTitle) + free(fgStructure.CurrentWindow->State.pWState.WindowTitle); + fgStructure.CurrentWindow->State.pWState.WindowTitle = strdup(title); } /* * Set the current window's iconified title - * There really isn't a way to set the icon name separate from the - * windows name in Win32, so, just set the windows name. */ void fgPlatformGlutSetIconTitle( const char* title ) { -#ifdef _WIN32_WCE - { - wchar_t* wstr = fghWstrFromStr(title); - SetWindowText( fgStructure.CurrentWindow->Window.Handle, wstr ); - free(wstr); - } -#else - SetWindowText( fgStructure.CurrentWindow->Window.Handle, title ); +#ifndef _WIN32_WCE + if (IsIconic(fgStructure.CurrentWindow->Window.Handle)) + SetWindowText( fgStructure.CurrentWindow->Window.Handle, title ); #endif -} -/* - * Change the current window's position - */ -void fgPlatformGlutPositionWindow( int x, int y ) -{ - RECT winRect; - - /* "GetWindowRect" returns the pixel coordinates of the outside of the window */ - GetWindowRect( fgStructure.CurrentWindow->Window.Handle, &winRect ); - MoveWindow( - fgStructure.CurrentWindow->Window.Handle, - x, - y, - winRect.right - winRect.left, - winRect.bottom - winRect.top, - TRUE - ); -} - -/* - * Lowers the current window (by Z order change) - */ -void fgPlatformGlutPushWindow( void ) -{ - SetWindowPos( - fgStructure.CurrentWindow->Window.Handle, - HWND_BOTTOM, - 0, 0, 0, 0, - SWP_NOSIZE | SWP_NOMOVE - ); -} - -/* - * Raises the current window (by Z order change) - */ -void fgPlatformGlutPopWindow( void ) -{ - SetWindowPos( - fgStructure.CurrentWindow->Window.Handle, - HWND_TOP, - 0, 0, 0, 0, - SWP_NOSIZE | SWP_NOMOVE - ); -} - -/* - * Resize the current window so that it fits the whole screen - */ -void fgPlatformGlutFullScreen( SFG_Window *win ) -{ -#if !defined(_WIN32_WCE) /* FIXME: what about WinCE */ - - if (glutGet(GLUT_FULL_SCREEN)) - { - /* Leave full screen state before entering fullscreen again (resizing?) */ - glutLeaveFullScreen(); - } - - { -#if(WINVER >= 0x0500) /* Windows 2000 or later */ - DWORD s; - RECT rect; - HMONITOR hMonitor; - MONITORINFO mi; - - /* For fullscreen mode, first remove all window decoration - * and set style to popup so it will overlap the taskbar - * then force to maximize on the screen on which it has the most - * overlap. - */ - - - /* store current window rect */ - GetWindowRect( win->Window.Handle, &win->State.pWState.OldRect ); - - /* store current window style */ - win->State.pWState.OldStyle = s = GetWindowLong(win->Window.Handle, GWL_STYLE); - - /* remove decorations from style and add popup style*/ - s &= ~WS_OVERLAPPEDWINDOW; - s |= WS_POPUP; - SetWindowLong(win->Window.Handle, GWL_STYLE, s); - SetWindowPos(win->Window.Handle, HWND_TOP, 0,0,0,0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED); - - /* For fullscreen mode, find the monitor that is covered the most - * by the window and get its rect as the resize target. - */ - hMonitor= MonitorFromRect(&win->State.pWState.OldRect, MONITOR_DEFAULTTONEAREST); - mi.cbSize = sizeof(mi); - GetMonitorInfo(hMonitor, &mi); - rect = mi.rcMonitor; -#else /* if (WINVER >= 0x0500) */ - RECT rect; - - /* For fullscreen mode, force the top-left corner to 0,0 - * and adjust the window rectangle so that the client area - * covers the whole screen. - */ - - rect.left = 0; - rect.top = 0; - rect.right = fgDisplay.ScreenWidth; - rect.bottom = fgDisplay.ScreenHeight; - - AdjustWindowRect ( &rect, WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | - WS_CLIPCHILDREN, FALSE ); -#endif /* (WINVER >= 0x0500) */ - - /* - * then resize window - * SWP_NOACTIVATE Do not activate the window - * SWP_NOOWNERZORDER Do not change position in z-order - * SWP_NOSENDCHANGING Suppress WM_WINDOWPOSCHANGING message - * SWP_NOZORDER Retains the current Z order (ignore 2nd param) - */ - SetWindowPos( fgStructure.CurrentWindow->Window.Handle, - HWND_TOP, - rect.left, - rect.top, - rect.right - rect.left, - rect.bottom - rect.top, - SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOSENDCHANGING | - SWP_NOZORDER - ); - - win->State.IsFullscreen = GL_TRUE; - } -#endif -} - -/* - * If we are fullscreen, resize the current window back to its original size - */ -void fgPlatformGlutLeaveFullScreen( SFG_Window *win ) -{ -#if !defined(_WIN32_WCE) /* FIXME: what about WinCE */ - if (!glutGet(GLUT_FULL_SCREEN)) - { - /* nothing to do */ - return; - } - - /* restore style of window before making it fullscreen */ - SetWindowLong(win->Window.Handle, GWL_STYLE, win->State.pWState.OldStyle); - SetWindowPos(win->Window.Handle, HWND_TOP, 0,0,0,0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED); - - /* Then resize */ - SetWindowPos(win->Window.Handle, - HWND_TOP, - win->State.pWState.OldRect.left, - win->State.pWState.OldRect.top, - win->State.pWState.OldRect.right - win->State.pWState.OldRect.left, - win->State.pWState.OldRect.bottom - win->State.pWState.OldRect.top, - SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOSENDCHANGING | - SWP_NOZORDER - ); - - win->State.IsFullscreen = GL_FALSE; -#endif -} - -/* - * Toggle the window's full screen state. - */ -void fgPlatformGlutFullScreenToggle( SFG_Window *win ) -{ - if (!win->State.IsFullscreen) - glutFullScreen(); - else - glutLeaveFullScreen(); + /* Make copy of string to refer to later */ + if (fgStructure.CurrentWindow->State.pWState.IconTitle) + free(fgStructure.CurrentWindow->State.pWState.IconTitle); + fgStructure.CurrentWindow->State.pWState.IconTitle = strdup(title); }