X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?a=blobdiff_plain;f=src%2Fmswin%2Ffg_window_mswin.c;h=518e0d32e5b9413b9426df8ed72f05694aefe29f;hb=1897e7e46186c5aa11700a72cb3331c1aabdb360;hp=621a18a7dcdeb78e35f8a7eda9504a85bd44da53;hpb=b08e8e8fbedd2df556da4897b1473ac26270cb48;p=freeglut diff --git a/src/mswin/fg_window_mswin.c b/src/mswin/fg_window_mswin.c index 621a18a..518e0d3 100644 --- a/src/mswin/fg_window_mswin.c +++ b/src/mswin/fg_window_mswin.c @@ -84,6 +84,7 @@ typedef HGLRC (WINAPI * PFNWGLCREATECONTEXTATTRIBSARBPROC) (HDC hDC, HGLRC hShar typedef BOOL (WINAPI *pRegisterTouchWindow)(HWND,ULONG); static pRegisterTouchWindow fghRegisterTouchWindow = (pRegisterTouchWindow)0xDEADBEEF; #endif +extern void fghNotifyWindowStatus(SFG_Window *window); /* @@ -405,7 +406,6 @@ void fghGetStyleFromWindow( const SFG_Window *window, DWORD *windowStyle, DWORD } } - /* Computes position of corners of window Rect (outer position including * decorations) based on the provided client rect and based on the style * of the window in question. @@ -454,50 +454,26 @@ void fghComputeWindowRectFromClientArea_QueryWindow( RECT *clientRect, const SFG fghComputeWindowRectFromClientArea_UseStyle(clientRect, windowStyle, windowExStyle, posIsOutside); } - /* Gets the rect describing the client area (drawable area) of the * specified window. Output is position of corners of client area (drawable area) on the screen. - * 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. + * 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. */ -void fghGetClientArea( RECT *clientRect, const SFG_Window *window, BOOL wantPosOutside ) +void fghGetClientArea( RECT *clientRect, const SFG_Window *window ) { POINT topLeftClient = {0,0}; - POINT topLeftWindow = {0,0}; freeglut_return_if_fail((window && window->Window.Handle)); - /* - * call GetWindowRect() - * (this returns the pixel coordinates of the outside of the window) - * cannot use GetClientRect as it returns a rect relative to - * the top-left point of the client area (.top and .left are thus always 0) - * and is thus only useful for querying the size of the client area, not - * its position. - */ - GetWindowRect( window->Window.Handle, clientRect ); - topLeftWindow.x = clientRect->top; - topLeftWindow.y = clientRect->left; - /* Get size of client rect */ GetClientRect(window->Window.Handle, clientRect); /* 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); - - /* replace top and left with top and left of window, if wanted */ - if (wantPosOutside) - { - clientRect->left = topLeftWindow.x; - clientRect->top = topLeftWindow.y; - } } + #if(WINVER >= 0x500) typedef struct { @@ -724,6 +700,12 @@ void fgPlatformOpenWindow( SFG_Window* window, const char* title, if( !( window->Window.Handle ) ) fgError( "Failed to create a window (%s)!", title ); + /* Store title */ + { + window->State.pWState.WindowTitle = malloc (strlen(title) + 1); + strcpy(window->State.pWState.WindowTitle, 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); @@ -751,11 +733,10 @@ void fgPlatformOpenWindow( SFG_Window* window, const char* title, ShowWindow( window->Window.Handle, SW_SHOW ); #else ShowWindow( window->Window.Handle, - fgState.ForceIconic ? SW_SHOWMINIMIZED : SW_SHOW ); + fgState.ForceIconic ? SW_SHOWMINIMIZED : SW_SHOWNORMAL ); #endif /* defined(_WIN32_WCE) */ - UpdateWindow( window->Window.Handle ); - ShowCursor( TRUE ); /* XXX Old comments say "hide cursor"! */ + ShowCursor( TRUE ); } @@ -773,6 +754,30 @@ void fgPlatformReshapeWindow ( SFG_Window *window, int width, int height ) RECT windowRect; /* + * HACK HACK HACK: + * Before we do anything else, check if this is a newly created window + * that did not have its windowStatus/visibility func called yet + * we do that on first paint, but because I want to keep the paint + * operation as lean as possible, we do it here. The first paint + * goes together with a first resize call before the display callback + * is called, so this is just in time. Shitty place to do it, but this + * is the only reliable way I can think of to call the callback upon + * first draw of the window. + * More broadly speaking, I know this is an ugly hack, but I'm not sure + * what else to do about it. Depending on WM_ACTIVATE would not work + * as not all windows get this when you are opening multiple before the + * mainloop starts. WM_SHOWWINDOW looked like an interesting candidate, + * but it is generated and processed before glutCreate(Sub)Window + * returns, so no callback can yet be set on the window. + */ + /* Check windowStatus/visibility func has been notified that window is visible (deferred from creation time to give user opportunity to register callbacks) */ + if (!window->State.pWState.WindowFuncCalled) + { + fghNotifyWindowStatus(window); + window->State.pWState.WindowFuncCalled = GL_TRUE; + } + + /* * For windowed mode, get the current position of the * window and resize taking the size of the frame * decorations into account. @@ -807,7 +812,7 @@ void fgPlatformReshapeWindow ( SFG_Window *window, int width, int height ) * for them. */ RECT parentRect; - fghGetClientArea( &parentRect, window->Parent, FALSE ); + fghGetClientArea( &parentRect, window->Parent ); OffsetRect(&windowRect,-parentRect.left,-parentRect.top); } @@ -858,6 +863,12 @@ void fgPlatformCloseWindow( SFG_Window* window ) } DestroyWindow( window->Window.Handle ); + + /* 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); } @@ -883,7 +894,14 @@ void fgPlatformGlutHideWindow( void ) */ void fgPlatformGlutIconifyWindow( void ) { - ShowWindow( fgStructure.CurrentWindow->Window.Handle, SW_MINIMIZE ); + SFG_Window *win = fgStructure.CurrentWindow; + + /* Call on parent window */ + while (win->Parent) + win = win->Parent; + + /* Visibility status of window gets updated in the WM_SHOWWINDOW handler */ + ShowWindow(win->Window.Handle, SW_MINIMIZE); } /* @@ -900,24 +918,24 @@ void fgPlatformGlutSetWindowTitle( const char* title ) #else 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 = malloc (strlen(title) + 1); + strcpy(fgStructure.CurrentWindow->State.pWState.WindowTitle, 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 ); -#endif + /* 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 = malloc (strlen(title) + 1); + strcpy(fgStructure.CurrentWindow->State.pWState.IconTitle, title); } /* @@ -980,7 +998,6 @@ void fgPlatformGlutFullScreen( SFG_Window *win ) { #if(WINVER >= 0x0500) /* Windows 2000 or later */ - DWORD s; RECT rect; HMONITOR hMonitor; MONITORINFO mi; @@ -992,16 +1009,25 @@ void fgPlatformGlutFullScreen( SFG_Window *win ) */ - /* store current window rect */ - GetWindowRect( win->Window.Handle, &win->State.pWState.OldRect ); + /* save current window rect, style, exstyle and maximized state */ + win->State.pWState.OldMaximized = !!IsZoomed(win->Window.Handle); + if (win->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(win->Window.Handle, WM_SYSCOMMAND, SC_RESTORE, 0); - /* store current window style */ - win->State.pWState.OldStyle = s = GetWindowLong(win->Window.Handle, GWL_STYLE); + GetWindowRect( win->Window.Handle, &win->State.pWState.OldRect ); + win->State.pWState.OldStyle = GetWindowLong(win->Window.Handle, GWL_STYLE); + win->State.pWState.OldStyleEx = GetWindowLong(win->Window.Handle, GWL_EXSTYLE); - /* remove decorations from style and add popup style*/ - s &= ~WS_OVERLAPPEDWINDOW; - s |= WS_POPUP; - SetWindowLong(win->Window.Handle, GWL_STYLE, s); + /* remove decorations from style */ + SetWindowLong(win->Window.Handle, GWL_STYLE, + win->State.pWState.OldStyle & ~(WS_CAPTION | WS_THICKFRAME)); + SetWindowLong(win->Window.Handle, GWL_EXSTYLE, + win->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. @@ -1063,6 +1089,7 @@ void fgPlatformGlutLeaveFullScreen( SFG_Window *win ) /* restore style of window before making it fullscreen */ SetWindowLong(win->Window.Handle, GWL_STYLE, win->State.pWState.OldStyle); + SetWindowLong(win->Window.Handle, GWL_EXSTYLE, win->State.pWState.OldStyleEx); /* Then resize */ SetWindowPos(win->Window.Handle, @@ -1075,6 +1102,9 @@ void fgPlatformGlutLeaveFullScreen( SFG_Window *win ) SWP_NOZORDER ); + if (win->State.pWState.OldMaximized) + SendMessage(win->Window.Handle, WM_SYSCOMMAND, SC_MAXIMIZE, 0); + win->State.IsFullscreen = GL_FALSE; #endif }