Putting in Diederick Niehorster's fullstreen patch per e-mail from him dated 6/9/2011, updated 9/4/2011 with modified patch.

git-svn-id: https://svn.code.sf.net/p/freeglut/code/trunk@929 7f0cb862-5218-0410-a997-914c9d46530a
This commit is contained in:
fayjf 2011-09-04 19:38:32 +00:00
parent 42235dfaa1
commit cf91891cf8
8 changed files with 438 additions and 179 deletions

View File

@ -127,6 +127,7 @@ FGAPI void FGAPIENTRY glutExit ( void );
* Window management functions, see freeglut_window.c * Window management functions, see freeglut_window.c
*/ */
FGAPI void FGAPIENTRY glutFullScreenToggle( void ); FGAPI void FGAPIENTRY glutFullScreenToggle( void );
FGAPI void FGAPIENTRY glutLeaveFullScreen( void );
/* /*
* Window-specific callback functions, see freeglut_callbacks.c * Window-specific callback functions, see freeglut_callbacks.c

View File

@ -166,6 +166,7 @@ static GLUTproc fghGetGLUTProcAddress( const char* procName )
CHECK_NAME(glutWMCloseFunc); CHECK_NAME(glutWMCloseFunc);
CHECK_NAME(glutMenuDestroyFunc); CHECK_NAME(glutMenuDestroyFunc);
CHECK_NAME(glutFullScreenToggle); CHECK_NAME(glutFullScreenToggle);
CHECK_NAME(glutLeaveFullScreen);
CHECK_NAME(glutSetOption); CHECK_NAME(glutSetOption);
CHECK_NAME(glutGetModeValues); CHECK_NAME(glutGetModeValues);
CHECK_NAME(glutSetWindowData); CHECK_NAME(glutSetWindowData);

View File

@ -449,10 +449,16 @@ struct tagSFG_Context
typedef struct tagSFG_WindowState SFG_WindowState; typedef struct tagSFG_WindowState SFG_WindowState;
struct tagSFG_WindowState struct tagSFG_WindowState
{ {
/* Note that on Windows, sizes always refer to the client area, thus without the window decorations */
int Width; /* Window's width in pixels */ int Width; /* Window's width in pixels */
int Height; /* The same about the height */ int Height; /* The same about the height */
#if TARGET_HOST_POSIX_X11
int OldWidth; /* Window width from before a resize */ int OldWidth; /* Window width from before a resize */
int OldHeight; /* " height " " " " */ int OldHeight; /* " height " " " " */
#elif TARGET_HOST_MS_WINDOWS
RECT OldRect; /* window rect - stored before the window is made fullscreen */
DWORD OldStyle; /* window style - stored before the window is made fullscreen */
#endif
GLboolean Redisplay; /* Do we have to redisplay? */ GLboolean Redisplay; /* Do we have to redisplay? */
GLboolean Visible; /* Is the window visible now */ GLboolean Visible; /* Is the window visible now */
@ -926,6 +932,17 @@ void fgEnumWindows( FGCBenumerator enumCallback, SFG_Enumerator* enumerator );
void fgEnumSubWindows( SFG_Window* window, FGCBenumerator enumCallback, void fgEnumSubWindows( SFG_Window* window, FGCBenumerator enumCallback,
SFG_Enumerator* enumerator ); SFG_Enumerator* enumerator );
/*
* 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).
*/
void fghComputeWindowRectFromClientArea_UseStyle ( const DWORD windowStyle , RECT *clientRect, BOOL posIsOutside );
void fghComputeWindowRectFromClientArea_QueryWindow( const SFG_Window *window, RECT *clientRect, BOOL posIsOutside );
void fghComputeClientAreaFromWindowRect ( const SFG_Window *window, RECT *windowRect, BOOL wantPosOutside );
RECT fghGetClientArea ( const SFG_Window *window, BOOL wantPosOutside );
void fghGetBorderWidth(const DWORD windowStyle, int* xBorderWidth, int* yBorderWidth);
/* /*
* fgWindowByHandle returns a (SFG_Window *) value pointing to the * fgWindowByHandle returns a (SFG_Window *) value pointing to the
* first window in the queue matching the specified window handle. * first window in the queue matching the specified window handle.

View File

@ -109,8 +109,7 @@ static void fghReshapeWindow ( SFG_Window *window, int width, int height )
#elif TARGET_HOST_MS_WINDOWS && !defined(_WIN32_WCE) #elif TARGET_HOST_MS_WINDOWS && !defined(_WIN32_WCE)
{ {
RECT winRect; RECT windowRect;
int x, y, w, h;
/* /*
* For windowed mode, get the current position of the * For windowed mode, get the current position of the
@ -119,51 +118,43 @@ static void fghReshapeWindow ( SFG_Window *window, int width, int height )
*/ */
/* "GetWindowRect" returns the pixel coordinates of the outside of the window */ /* "GetWindowRect" returns the pixel coordinates of the outside of the window */
GetWindowRect( window->Window.Handle, &winRect ); GetWindowRect( window->Window.Handle, &windowRect );
x = winRect.left;
y = winRect.top;
w = width;
h = height;
if ( window->Parent == NULL ) /* Create rect in FreeGLUT format, (X,Y) topleft outside window, WxH of client area */
{ windowRect.right = windowRect.left+width;
if ( ! window->IsMenu && (window != fgStructure.GameModeWindow) && windowRect.bottom = windowRect.top+height;
!( fgState.DisplayMode & GLUT_BORDERLESS ))
{ if (window->Parent == NULL)
w += GetSystemMetrics( SM_CXSIZEFRAME ) * 2; /* get the window rect from this to feed to SetWindowPos, correct for window decorations */
h += GetSystemMetrics( SM_CYSIZEFRAME ) * 2 + fghComputeWindowRectFromClientArea_QueryWindow(window,&windowRect,TRUE);
GetSystemMetrics( SM_CYCAPTION );
}
}
else else
{ {
/* correct rect for position client area of parent window
* (SetWindowPos input for child windows is in coordinates
* relative to the parent's client area).
* Child windows don't have decoration, so no need to correct
* for them.
*/
RECT parentRect; RECT parentRect;
GetWindowRect( window->Parent->Window.Handle, &parentRect ); parentRect = fghGetClientArea( window->Parent, FALSE );
x -= parentRect.left + GetSystemMetrics( SM_CXSIZEFRAME ) * 2; windowRect.left -= parentRect.left;
y -= parentRect.top + GetSystemMetrics( SM_CYSIZEFRAME ) * 2 + windowRect.right -= parentRect.left;
GetSystemMetrics( SM_CYCAPTION ); windowRect.top -= parentRect.top;
windowRect.bottom -= parentRect.top;
} }
/* /* Do the actual resizing */
* SWP_NOACTIVATE Do not activate the window
* SWP_NOOWNERZORDER Do not change position in z-order
* SWP_NOSENDCHANGING Supress WM_WINDOWPOSCHANGING message
* SWP_NOZORDER Retains the current Z order (ignore 2nd param)
*/
SetWindowPos( window->Window.Handle, SetWindowPos( window->Window.Handle,
HWND_TOP, HWND_TOP,
x, y, w, h, windowRect.left, windowRect.top,
windowRect.right - windowRect.left,
windowRect.bottom- windowRect.top,
SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOSENDCHANGING | SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOSENDCHANGING |
SWP_NOZORDER SWP_NOZORDER
); );
} }
#endif #endif
/*
* XXX Should update {window->State.OldWidth, window->State.OldHeight}
* XXX to keep in lockstep with POSIX_X11 code.
*/
if( FETCH_WCB( *window, Reshape ) ) if( FETCH_WCB( *window, Reshape ) )
INVOKE_WCB( *window, Reshape, ( width, height ) ); INVOKE_WCB( *window, Reshape, ( width, height ) );
else else

View File

@ -64,16 +64,6 @@ static int fghGetConfig( int attribute )
} }
#endif #endif
/* Check if the window is in full screen state. */
static int fghCheckFullScreen(void)
{
#if TARGET_HOST_POSIX_X11
return fgStructure.CurrentWindow->State.IsFullscreen;
#else
return 0;
#endif
}
/* -- INTERFACE FUNCTIONS -------------------------------------------------- */ /* -- INTERFACE FUNCTIONS -------------------------------------------------- */
/* /*
@ -458,25 +448,11 @@ int FGAPIENTRY glutGet( GLenum eWhat )
freeglut_return_val_if_fail( fgStructure.CurrentWindow != NULL, 0 ); freeglut_return_val_if_fail( fgStructure.CurrentWindow != NULL, 0 );
/* #if defined(_WIN32_WCE)
* We need to call GetWindowRect() first...
* (this returns the pixel coordinates of the outside of the window)
*/
GetWindowRect( fgStructure.CurrentWindow->Window.Handle, &winRect ); GetWindowRect( fgStructure.CurrentWindow->Window.Handle, &winRect );
#else
/* ...then we've got to correct the results we've just received... */ winRect = fghGetClientArea(fgStructure.CurrentWindow, FALSE);
#endif /* defined(_WIN32_WCE) */
#if !defined(_WIN32_WCE)
if ( ( fgStructure.GameModeWindow != fgStructure.CurrentWindow ) && ( fgStructure.CurrentWindow->Parent == NULL ) &&
( ! fgStructure.CurrentWindow->IsMenu ) &&
!( fgState.DisplayMode & GLUT_BORDERLESS ))
{
winRect.left += GetSystemMetrics( SM_CXSIZEFRAME );
winRect.right -= GetSystemMetrics( SM_CXSIZEFRAME );
winRect.top += GetSystemMetrics( SM_CYSIZEFRAME ) + GetSystemMetrics( SM_CYCAPTION );
winRect.bottom -= GetSystemMetrics( SM_CYSIZEFRAME );
}
#endif /* !defined(_WIN32_WCE) */
switch( eWhat ) switch( eWhat )
{ {
@ -489,21 +465,32 @@ int FGAPIENTRY glutGet( GLenum eWhat )
break; break;
case GLUT_WINDOW_BORDER_WIDTH : case GLUT_WINDOW_BORDER_WIDTH :
#if defined(_WIN32_WCE)
return 0;
#else
if ( fgState.DisplayMode & GLUT_BORDERLESS )
return 0;
return GetSystemMetrics( SM_CXSIZEFRAME );
#endif /* !defined(_WIN32_WCE) */
case GLUT_WINDOW_HEADER_HEIGHT : case GLUT_WINDOW_HEADER_HEIGHT :
#if defined(_WIN32_WCE) #if defined(_WIN32_WCE)
return 0; return 0;
#else #else
if ( fgState.DisplayMode & GLUT_BORDERLESS ) {
return 0; DWORD windowStyle;
return GetSystemMetrics( SM_CYCAPTION );
if (fgStructure.CurrentWindow && fgStructure.CurrentWindow->Window.Handle)
windowStyle = GetWindowLong(fgStructure.CurrentWindow->Window.Handle, GWL_STYLE);
else
/* If no window, return sizes for a default window with title bar and border */
windowStyle = WS_OVERLAPPEDWINDOW;
switch( eWhat )
{
case GLUT_WINDOW_BORDER_WIDTH:
{
int xBorderWidth, yBorderWidth;
fghGetBorderWidth(windowStyle, &xBorderWidth, &yBorderWidth);
return xBorderWidth;
}
case GLUT_WINDOW_HEADER_HEIGHT:
/* 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... */
return (windowStyle & WS_MAXIMIZEBOX)? GetSystemMetrics( SM_CYCAPTION ) : 0;
}
}
#endif /* defined(_WIN32_WCE) */ #endif /* defined(_WIN32_WCE) */
case GLUT_DISPLAY_MODE_POSSIBLE: case GLUT_DISPLAY_MODE_POSSIBLE:
@ -559,7 +546,7 @@ int FGAPIENTRY glutGet( GLenum eWhat )
return fgState.DirectContext; return fgState.DirectContext;
case GLUT_FULL_SCREEN: case GLUT_FULL_SCREEN:
return fghCheckFullScreen(); return fgStructure.CurrentWindow->State.IsFullscreen;
case GLUT_AUX: case GLUT_AUX:
return fgState.AuxiliaryBufferNumber; return fgState.AuxiliaryBufferNumber;

View File

@ -79,7 +79,9 @@ SFG_Window* fgCreateWindow( SFG_Window* parent, const char* title,
/* Initialize the object properties */ /* Initialize the object properties */
window->ID = ++fgStructure.WindowID; window->ID = ++fgStructure.WindowID;
#if TARGET_HOST_POSIX_X11
window->State.OldHeight = window->State.OldWidth = -1; window->State.OldHeight = window->State.OldWidth = -1;
#endif
fgListInit( &window->Children ); fgListInit( &window->Children );
if( parent ) if( parent )

View File

@ -850,12 +850,167 @@ void fgSetWindow ( SFG_Window *window )
#if TARGET_HOST_MS_WINDOWS #if TARGET_HOST_MS_WINDOWS
/* 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.
* If posIsOutside is set to true, the input client Rect is taken to 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.
*/
void fghComputeWindowRectFromClientArea_UseStyle( const DWORD windowStyle, RECT *clientRect, BOOL posIsOutside )
{
int xBorderWidth = 0, yBorderWidth = 0;
/* 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 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 (posIsOutside)
{
clientRect->right += xBorderWidth * 2;
clientRect->bottom += yBorderWidth * 2;
}
else
{
clientRect->left -= xBorderWidth;
clientRect->right += xBorderWidth;
clientRect->top -= yBorderWidth;
clientRect->bottom += yBorderWidth;
}
}
/* 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. If the window pointer or the window handle
* is NULL, a fully decorated window (caption and border) is assumed.
* Furthermore, if posIsOutside is set to true, the input client Rect is
* taken to 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.
*/
void fghComputeWindowRectFromClientArea_QueryWindow( const SFG_Window *window, RECT *clientRect, BOOL posIsOutside )
{
DWORD windowStyle = 0;
if (window && window->Window.Handle)
windowStyle = GetWindowLong(window->Window.Handle, GWL_STYLE);
else
windowStyle = WS_OVERLAPPEDWINDOW;
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;
}
}
/* 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.
*/
RECT fghGetClientArea( const SFG_Window *window, BOOL wantPosOutside )
{
RECT windowRect = {0,0,0,0};
freeglut_return_val_if_fail((window && window->Window.Handle),windowRect);
/*
* 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)
{
*xBorderWidth = GetSystemMetrics(SM_CXFIXEDFRAME);
*yBorderWidth = GetSystemMetrics(SM_CYFIXEDFRAME);
}
else
{
*xBorderWidth = 0;
*yBorderWidth = 0;
}
}
#if(WINVER >= 0x500) #if(WINVER >= 0x500)
typedef struct { typedef struct
{
int *x; int *x;
int *y; int *y;
const char *name; const char *name;
}m_proc_t ; } m_proc_t;
static BOOL CALLBACK m_proc(HMONITOR mon, static BOOL CALLBACK m_proc(HMONITOR mon,
HDC hdc, HDC hdc,
@ -869,7 +1024,7 @@ static BOOL CALLBACK m_proc(HMONITOR mon,
res=GetMonitorInfo(mon,(LPMONITORINFO)&info); res=GetMonitorInfo(mon,(LPMONITORINFO)&info);
if( res ) if( res )
{ {
if( !strcmp(dp->name,info.szDevice) ) if( strcmp(dp->name,info.szDevice)==0 )
{ {
*(dp->x)=info.rcMonitor.left; *(dp->x)=info.rcMonitor.left;
*(dp->y)=info.rcMonitor.top; *(dp->y)=info.rcMonitor.top;
@ -880,13 +1035,18 @@ static BOOL CALLBACK m_proc(HMONITOR mon,
} }
/* /*
* this function is only used in fgOpenWindow. Currently it only sets * this function returns the origin of the screen identified by
* its output parameters, if the DisplayName is set in fgDisplay * fgDisplay.DisplayName, and 0 otherwise.
* (and if it is able to recognize the display) * This is used in fgOpenWindow to open the gamemode window on the screen
* identified by the -display command line argument. The function should
* not be called otherwise.
*/ */
static void get_display_origin(int *xp,int *yp) static void get_display_origin(int *xp,int *yp)
{ {
*xp = 0;
*yp = 0;
if( fgDisplay.DisplayName ) if( fgDisplay.DisplayName )
{ {
m_proc_t st; m_proc_t st;
@ -894,13 +1054,16 @@ static void get_display_origin(int *xp,int *yp)
st.y=yp; st.y=yp;
st.name=fgDisplay.DisplayName; st.name=fgDisplay.DisplayName;
EnumDisplayMonitors(0,0,m_proc,(LPARAM)&st); EnumDisplayMonitors(0,0,m_proc,(LPARAM)&st);
} }
} }
#else #else
#pragma message( "-display parameter only works if compiled with WINVER >= 0x0500") #pragma message( "-display parameter only works if compiled with WINVER >= 0x0500")
static void get_display_origin(int *xp,int *yp) static void get_display_origin(int *xp,int *yp)
{ {
*xp = 0;
*yp = 0;
if( fgDisplay.DisplayName ) if( fgDisplay.DisplayName )
{ {
fgWarning( "for working -display support FreeGLUT must be compiled with WINVER >= 0x0500"); fgWarning( "for working -display support FreeGLUT must be compiled with WINVER >= 0x0500");
@ -1139,16 +1302,16 @@ void fgOpenWindow( SFG_Window* window, const char* title,
#elif TARGET_HOST_MS_WINDOWS #elif TARGET_HOST_MS_WINDOWS
WNDCLASS wc; WNDCLASS wc;
DWORD flags; DWORD flags = 0;
DWORD exFlags = 0; DWORD exFlags = 0;
ATOM atom; ATOM atom;
int WindowStyle = 0;
/* Grab the window class we have registered on glutInit(): */ /* Grab the window class we have registered on glutInit(): */
atom = GetClassInfo( fgDisplay.Instance, _T("FREEGLUT"), &wc ); atom = GetClassInfo( fgDisplay.Instance, _T("FREEGLUT"), &wc );
FREEGLUT_INTERNAL_ERROR_EXIT ( atom, "Window Class Info Not Found", FREEGLUT_INTERNAL_ERROR_EXIT ( atom, "Window Class Info Not Found",
"fgOpenWindow" ); "fgOpenWindow" );
/* Determine window style flags*/
if( gameMode ) if( gameMode )
{ {
FREEGLUT_INTERNAL_ERROR_EXIT ( window->Parent == NULL, FREEGLUT_INTERNAL_ERROR_EXIT ( window->Parent == NULL,
@ -1163,64 +1326,100 @@ void fgOpenWindow( SFG_Window* window, const char* title,
} }
else else
{ {
int worig = w, horig = h; flags = WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
#if !defined(_WIN32_WCE)
if ( ( ! isSubWindow ) && ( ! window->IsMenu ) )
{
/*
* Update the window dimensions, taking account of window
* decorations. "freeglut" is to create the window with the
* outside of its border at (x,y) and with dimensions (w,h).
*/
w += (GetSystemMetrics( SM_CXSIZEFRAME ) )*2;
h += (GetSystemMetrics( SM_CYSIZEFRAME ) )*2 +
GetSystemMetrics( SM_CYCAPTION );
}
#endif /* defined(_WIN32_WCE) */
if( ! positionUse )
{
x = CW_USEDEFAULT;
y = CW_USEDEFAULT;
}
/* setting State.Width/Height to call resize callback later */
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 */
window->State.Width = window->State.Height = -1;
}
else
{
window->State.Width = worig;
window->State.Height = horig;
}
/* /*
* There's a small difference between creating the top, child and * There's a small difference between creating the top, child and
* game mode windows * menu windows
*/ */
flags = WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_VISIBLE;
if ( window->IsMenu ) if ( window->IsMenu )
{ {
flags |= WS_POPUP; flags |= WS_POPUP;
exFlags |= WS_EX_TOOLWINDOW; exFlags |= WS_EX_TOOLWINDOW;
} }
#if !defined(_WIN32_WCE) #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 */
else if( window->Parent == NULL ) else if( window->Parent == NULL )
flags |= WS_OVERLAPPEDWINDOW; 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;
#endif #endif
else else
/* subwindows always have no decoration, but are marked as a child window to the OS */
flags |= WS_CHILD; flags |= WS_CHILD;
} }
/* determine window size and position */
if( gameMode )
{
/* if in gamemode, query the origin of specified by the -display
* parameter command line (if any) and offset the upper-left corner
* of the window so we create the window on that screen.
* The -display argument doesn't do anything if not trying to enter
* gamemode.
*/
int xoff=0, yoff=0;
get_display_origin(&xoff,&yoff);
x += xoff;
y += yoff;
}
if( !positionUse )
{
x = CW_USEDEFAULT;
y = CW_USEDEFAULT;
}
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 */
}
/* 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 )
{
RECT windowRect;
/*
* Update the window dimensions, taking the window decorations
* into account. FreeGLUT is to create the window with the
* topleft outside corner at (x,y) and with client area
* dimensions (w,h).
* note: don't need to do this when w=h=CW_USEDEFAULT, so in the
* if( sizeUse ) here is convenient.
*/
windowRect.left = x;
windowRect.top = y;
windowRect.right = x+w;
windowRect.bottom = y+h;
fghComputeWindowRectFromClientArea_UseStyle(flags,&windowRect,TRUE);
w = windowRect.right - windowRect.left;
h = windowRect.bottom- windowRect.top;
}
#endif /* !defined(_WIN32_WCE) */
#if defined(_WIN32_WCE) #if defined(_WIN32_WCE)
{ {
wchar_t* wstr = fghWstrFromStr(title); wchar_t* wstr = fghWstrFromStr(title);
@ -1246,29 +1445,28 @@ void fgOpenWindow( SFG_Window* window, const char* title,
UpdateWindow(window->Window.Handle); UpdateWindow(window->Window.Handle);
} }
#else #else
{ window->Window.Handle = CreateWindowEx(
/* xoff and yoff are used to place window relative to current display */ exFlags,
/* The operation of gamemode also depends on this */ _T("FREEGLUT"),
int xoff=0,yoff=0; title,
get_display_origin(&xoff,&yoff); flags,
x, y, w, h,
window->Window.Handle = CreateWindowEx( (HWND) window->Parent == NULL ? NULL : window->Parent->Window.Handle,
exFlags, (HMENU) NULL,
_T("FREEGLUT"), fgDisplay.Instance,
title, (LPVOID) window
flags, );
x+xoff, y+yoff, w, h,
(HWND) window->Parent == NULL ? NULL : window->Parent->Window.Handle,
(HMENU) NULL,
fgDisplay.Instance,
(LPVOID) window
);
}
#endif /* defined(_WIN32_WCE) */ #endif /* defined(_WIN32_WCE) */
if( !( window->Window.Handle ) ) if( !( window->Window.Handle ) )
fgError( "Failed to create a window (%s)!", title ); fgError( "Failed to create a window (%s)!", 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);
SetWindowPos(window->Window.Handle, HWND_TOP, 0,0,0,0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
#endif /* defined(_WIN32_WCE) */
/* Make a menu window always on top - fix Feature Request 947118 */ /* Make a menu window always on top - fix Feature Request 947118 */
if( window->IsMenu || gameMode ) if( window->IsMenu || gameMode )
SetWindowPos( SetWindowPos(
@ -1278,23 +1476,6 @@ void fgOpenWindow( SFG_Window* window, const char* title,
SWP_NOMOVE | SWP_NOSIZE SWP_NOMOVE | SWP_NOSIZE
); );
/* Hack to remove the caption (title bar) and/or border
* and all the system menu controls.
*/
WindowStyle = GetWindowLong(window->Window.Handle, GWL_STYLE);
if ( fgState.DisplayMode & GLUT_CAPTIONLESS )
{
SetWindowLong ( window->Window.Handle, GWL_STYLE,
WindowStyle & ~(WS_DLGFRAME | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX));
}
else if ( fgState.DisplayMode & GLUT_BORDERLESS )
{
SetWindowLong ( window->Window.Handle, GWL_STYLE,
WindowStyle & ~(WS_BORDER | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_DLGFRAME | WS_SIZEBOX));
}
/* SetWindowPos(window->Window.Handle, NULL, 0, 0, 0, 0,
SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED); */
/* Enable multitouch: additional flag TWF_FINETOUCH, TWF_WANTPALM */ /* Enable multitouch: additional flag TWF_FINETOUCH, TWF_WANTPALM */
#ifdef WM_TOUCH #ifdef WM_TOUCH
if (fghRegisterTouchWindow == (pRegisterTouchWindow)0xDEADBEEF) if (fghRegisterTouchWindow == (pRegisterTouchWindow)0xDEADBEEF)
@ -1680,7 +1861,7 @@ void FGAPIENTRY glutReshapeWindow( int width, int height )
if (glutGet(GLUT_FULL_SCREEN)) if (glutGet(GLUT_FULL_SCREEN))
{ {
/* Leave full screen state before resizing. */ /* Leave full screen state before resizing. */
glutFullScreenToggle(); glutLeaveFullScreen();
} }
fgStructure.CurrentWindow->State.NeedToResize = GL_TRUE; fgStructure.CurrentWindow->State.NeedToResize = GL_TRUE;
@ -1699,7 +1880,7 @@ void FGAPIENTRY glutPositionWindow( int x, int y )
if (glutGet(GLUT_FULL_SCREEN)) if (glutGet(GLUT_FULL_SCREEN))
{ {
/* Leave full screen state before moving. */ /* Leave full screen state before moving. */
glutFullScreenToggle(); glutLeaveFullScreen();
} }
#if TARGET_HOST_POSIX_X11 #if TARGET_HOST_POSIX_X11
@ -1788,6 +1969,21 @@ void FGAPIENTRY glutFullScreen( void )
win = fgStructure.CurrentWindow; win = fgStructure.CurrentWindow;
if (win->Parent)
{
/* Child windows cannot be made fullscreen, consistent with GLUT's behavior
* Also, what would it mean for a child window to be fullscreen, given that it
* is confined to its parent?
*/
fgWarning("glutFullScreen called on a child window, ignoring...");
return;
}
else if (fgStructure.GameModeWindow != NULL && fgStructure.GameModeWindow->ID==win->ID)
{
/* Ignore fullscreen call on GameMode window, those are always fullscreen already */
return;
}
#if TARGET_HOST_POSIX_X11 #if TARGET_HOST_POSIX_X11
if(!glutGet(GLUT_FULL_SCREEN)) { if(!glutGet(GLUT_FULL_SCREEN)) {
if(fghToggleFullscreen() != -1) { if(fghToggleFullscreen() != -1) {
@ -1799,34 +1995,50 @@ void FGAPIENTRY glutFullScreen( void )
if (glutGet(GLUT_FULL_SCREEN)) if (glutGet(GLUT_FULL_SCREEN))
{ {
/* Leave full screen state before resizing. */ /* Leave full screen state before entering fullscreen again (resizing?) */
glutFullScreenToggle(); glutLeaveFullScreen();
} }
{ {
DWORD s;
RECT rect; RECT rect;
HMONITOR hMonitor;
MONITORINFO mi;
/* For fullscreen mode, force the top-left corner to 0,0 /* For fullscreen mode, first remove all window decoration
* and adjust the window rectangle so that the client area * and set style to popup so it will overlap the taskbar
* covers the whole screen. * then force to maximize on the screen on which it has the most
* overlap.
*/ */
rect.left = 0;
rect.top = 0; /* store current window rect */
get_display_origin(&rect.left,&rect.top); GetWindowRect( win->Window.Handle, &win->State.OldRect );
rect.right = fgDisplay.ScreenWidth+rect.left;
rect.bottom = fgDisplay.ScreenHeight+rect.top;
AdjustWindowRect ( &rect, WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | /* store current window style */
WS_CLIPCHILDREN, FALSE ); win->State.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.OldRect, MONITOR_DEFAULTTONEAREST);
mi.cbSize = sizeof(mi);
GetMonitorInfo(hMonitor, &mi);
rect = mi.rcMonitor;
/* /*
* then resize window
* SWP_NOACTIVATE Do not activate the window * SWP_NOACTIVATE Do not activate the window
* SWP_NOOWNERZORDER Do not change position in z-order * SWP_NOOWNERZORDER Do not change position in z-order
* SWP_NOSENDCHANGING Supress WM_WINDOWPOSCHANGING message * SWP_NOSENDCHANGING Suppress WM_WINDOWPOSCHANGING message
* SWP_NOZORDER Retains the current Z order (ignore 2nd param) * SWP_NOZORDER Retains the current Z order (ignore 2nd param)
*/ */
SetWindowPos( fgStructure.CurrentWindow->Window.Handle, SetWindowPos( fgStructure.CurrentWindow->Window.Handle,
HWND_TOP, HWND_TOP,
rect.left, rect.left,
@ -1842,6 +2054,51 @@ void FGAPIENTRY glutFullScreen( void )
#endif #endif
} }
/*
* If we are fullscreen, resize the current window back to its original size
*/
void FGAPIENTRY glutLeaveFullScreen( void )
{
SFG_Window *win;
FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutFullScreen" );
FREEGLUT_EXIT_IF_NO_WINDOW ( "glutFullScreen" );
win = fgStructure.CurrentWindow;
#if TARGET_HOST_POSIX_X11
if(glutGet(GLUT_FULL_SCREEN)) {
if(fghToggleFullscreen() != -1) {
win->State.IsFullscreen = GL_FALSE;
}
}
#elif TARGET_HOST_MS_WINDOWS && !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.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.OldRect.left,
win->State.OldRect.top,
win->State.OldRect.right - win->State.OldRect.left,
win->State.OldRect.bottom - win->State.OldRect.top,
SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOSENDCHANGING |
SWP_NOZORDER
);
win->State.IsFullscreen = GL_FALSE;
#endif
}
/* /*
* Toggle the window's full screen state. * Toggle the window's full screen state.
*/ */
@ -1859,8 +2116,10 @@ void FGAPIENTRY glutFullScreenToggle( void )
win->State.IsFullscreen = !win->State.IsFullscreen; win->State.IsFullscreen = !win->State.IsFullscreen;
} }
#elif TARGET_HOST_MS_WINDOWS #elif TARGET_HOST_MS_WINDOWS
glutFullScreen(); if (!win->State.IsFullscreen)
win->State.IsFullscreen = !win->State.IsFullscreen; glutFullScreen();
else
glutLeaveFullScreen();
#endif #endif
} }

View File

@ -139,6 +139,7 @@ EXPORTS
glutGetProcAddress glutGetProcAddress
glutExit glutExit
glutFullScreenToggle glutFullScreenToggle
glutLeaveFullScreen
glutGetModeValues glutGetModeValues
glutInitContextFlags glutInitContextFlags
glutInitContextVersion glutInitContextVersion