Add option to toggle between fullscreen and window mode on Win32

This commit is contained in:
Eden Salomon 2015-10-22 20:02:40 +03:00
parent d030b88c86
commit 061c273da6
5 changed files with 104 additions and 51 deletions

View File

@ -614,6 +614,7 @@ extern "C" {
#define GLFW_DECORATED 0x00020005
#define GLFW_AUTO_ICONIFY 0x00020006
#define GLFW_FLOATING 0x00020007
#define GLFW_FULLSCREEN 0x00020008
#define GLFW_RED_BITS 0x00021001
#define GLFW_GREEN_BITS 0x00021002
@ -2101,6 +2102,18 @@ GLFWAPI void glfwShowWindow(GLFWwindow* window);
*/
GLFWAPI void glfwHideWindow(GLFWwindow* window);
/*! @brief Toggles between fullscreen and windowed mode on the specified window.
*
* The functions enters fullscreen mode if the specified window was previously
* in windowed mode. If the window is already in fullscreen mode, the fuctions restores
* the monitor video mode and the specified window switches back to windowed mode.
*
* @param[in] window The window to toggle his mode.
*
* @ingroup window
*/
GLFWAPI void glfwToggleWindowFullscreen(GLFWwindow* window);
/*! @brief Returns the monitor that the window uses for full screen mode.
*
* This function returns the handle of the monitor that the specified window is

View File

@ -178,6 +178,7 @@ struct _GLFWwndconfig
GLFWbool focused;
GLFWbool autoIconify;
GLFWbool floating;
GLFWbool fullscreen;
_GLFWmonitor* monitor;
};
@ -245,6 +246,7 @@ struct _GLFWwindow
GLFWbool autoIconify;
GLFWbool floating;
GLFWbool closed;
GLFWbool fullscreen;
void* userPointer;
GLFWvidmode videoMode;
_GLFWmonitor* monitor;
@ -584,6 +586,11 @@ void _glfwPlatformUnhideWindow(_GLFWwindow* window);
*/
void _glfwPlatformHideWindow(_GLFWwindow* window);
/*! @copydoc glfwToggleWindowFullscreen
* @ingroup platform
*/
void _glfwPlatformToggleWindowFullscreen(_GLFWwindow* window);
/*! @brief Returns whether the window is focused.
* @ingroup platform
*/

View File

@ -600,7 +600,7 @@ void _glfwPlatformMakeContextCurrent(_GLFWwindow* window)
void _glfwPlatformSwapBuffers(_GLFWwindow* window)
{
// HACK: Use DwmFlush when desktop composition is enabled
if (_glfwIsCompositionEnabled() && !window->monitor)
if (_glfwIsCompositionEnabled() && !window->fullscreen)
{
int count = abs(window->wgl.interval);
while (count--)
@ -618,7 +618,7 @@ void _glfwPlatformSwapInterval(int interval)
// HACK: Disable WGL swap interval when desktop composition is enabled to
// avoid interfering with DWM vsync
if (_glfwIsCompositionEnabled() && !window->monitor)
if (_glfwIsCompositionEnabled() && !window->fullscreen)
interval = 0;
if (window->wgl.EXT_swap_control)

View File

@ -44,7 +44,7 @@ static DWORD getWindowStyle(const _GLFWwindow* window)
{
DWORD style = WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
if (window->decorated && !window->monitor)
if (window->decorated && !window->fullscreen)
{
style |= WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX;
@ -63,7 +63,7 @@ static DWORD getWindowExStyle(const _GLFWwindow* window)
{
DWORD style = WS_EX_APPWINDOW;
if (window->decorated && !window->monitor)
if (window->decorated && !window->fullscreen)
style |= WS_EX_WINDOWEDGE;
return style;
@ -224,15 +224,24 @@ static int translateKey(WPARAM wParam, LPARAM lParam)
return _glfw.win32.publicKeys[HIWORD(lParam) & 0x1FF];
}
static void updateWindowStyle(_GLFWwindow* window)
{
SetWindowLongPtr(window->win32.handle, GWL_EXSTYLE, getWindowExStyle(window));
SetWindowLongPtr(window->win32.handle, GWL_STYLE, getWindowStyle(window));
_glfwPlatformShowWindow(window);
}
// Enter full screen mode
//
static GLFWbool enterFullscreenMode(_GLFWwindow* window)
{
GLFWvidmode mode;
GLFWbool status;
int xpos, ypos;
status = _glfwSetVideoMode(window->monitor, &window->videoMode);
window->fullscreen = _glfwSetVideoMode(window->monitor, &window->videoMode);
updateWindowStyle(window);
_glfwPlatformGetVideoMode(window->monitor, &mode);
_glfwPlatformGetMonitorPos(window->monitor, &xpos, &ypos);
@ -240,7 +249,7 @@ static GLFWbool enterFullscreenMode(_GLFWwindow* window)
SetWindowPos(window->win32.handle, HWND_TOPMOST,
xpos, ypos, mode.width, mode.height, SWP_NOCOPYBITS);
return status;
return window->fullscreen;
}
// Leave full screen mode
@ -248,6 +257,10 @@ static GLFWbool enterFullscreenMode(_GLFWwindow* window)
static void leaveFullscreenMode(_GLFWwindow* window)
{
_glfwRestoreVideoMode(window->monitor);
window->fullscreen = GLFW_FALSE;
updateWindowStyle(window);
}
// Window callback function (handles window events)
@ -280,7 +293,7 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
if (window->cursorMode == GLFW_CURSOR_DISABLED)
_glfwPlatformSetCursorMode(window, GLFW_CURSOR_NORMAL);
if (window->monitor && window->autoIconify)
if (window->fullscreen && window->autoIconify)
_glfwPlatformIconifyWindow(window);
_glfwInputWindowFocus(window, GLFW_FALSE);
@ -294,7 +307,7 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
case SC_SCREENSAVE:
case SC_MONITORPOWER:
{
if (window->monitor)
if (window->fullscreen)
{
// We are running in full screen mode, so disallow
// screen saver and screen blanking
@ -508,8 +521,13 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
if (!window->win32.iconified && wParam == SIZE_MINIMIZED)
{
window->win32.iconified = GLFW_TRUE;
if (window->monitor)
if (window->fullscreen)
leaveFullscreenMode(window);
// We don't really toggle fullscreen,
// just temporally restore monitor video mode
window->fullscreen = GLFW_TRUE;
_glfwInputWindowIconify(window, GLFW_TRUE);
}
@ -517,7 +535,9 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
(wParam == SIZE_RESTORED || wParam == SIZE_MAXIMIZED))
{
window->win32.iconified = GLFW_FALSE;
if (window->monitor)
// check if we should go back to fullscreen mode
if (window->fullscreen)
enterFullscreenMode(window);
_glfwInputWindowIconify(window, GLFW_FALSE);
@ -673,7 +693,7 @@ static GLFWbool createWindow(_GLFWwindow* window,
int xpos, ypos, fullWidth, fullHeight;
WCHAR* wideTitle;
if (wndconfig->monitor)
if (wndconfig->fullscreen)
{
GLFWvidmode mode;
@ -732,7 +752,7 @@ static GLFWbool createWindow(_GLFWwindow* window,
WM_COPYGLOBALDATA, MSGFLT_ALLOW, NULL);
}
if (wndconfig->floating && !wndconfig->monitor)
if (wndconfig->floating && !wndconfig->fullscreen)
{
SetWindowPos(window->win32.handle,
HWND_TOPMOST,
@ -868,17 +888,12 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
if (!createWindow(window, wndconfig, ctxconfig, fbconfig))
return GLFW_FALSE;
}
if (window->monitor)
if (wndconfig->fullscreen)
{
// the following function calls ShowWindow
// which sends WM_SETFOCUS to windowProc()
// Which then enters fullscreen mode if autoIconify is enabled (win32_window.c : line 283)
_glfwPlatformShowWindow(window);
if (!window->autoIconify) { // add this to prevent entering full screen mode twice when autoIconify == true
if (!enterFullscreenMode(window))
return GLFW_FALSE;
}
if (!enterFullscreenMode(window))
return GLFW_FALSE;
}
return GLFW_TRUE;
@ -886,7 +901,7 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
void _glfwPlatformDestroyWindow(_GLFWwindow* window)
{
if (window->monitor)
if (window->fullscreen)
leaveFullscreenMode(window);
destroyWindow(window);
@ -939,7 +954,7 @@ void _glfwPlatformGetWindowSize(_GLFWwindow* window, int* width, int* height)
void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height)
{
if (window->monitor)
if (window->fullscreen)
enterFullscreenMode(window);
else
{
@ -1032,20 +1047,7 @@ void _glfwPlatformRestoreWindow(_GLFWwindow* window)
ShowWindow(window->win32.handle, SW_RESTORE);
}
void _glfwPlatformShowWindow(_GLFWwindow* window)
{
ShowWindow(window->win32.handle, SW_SHOW);
// Consider separating the following function calls to a different function?
// e.g. RequestFocus(_GLFWwindow* window) (any of these might fail)
BringWindowToTop(window->win32.handle);
SetForegroundWindow(window->win32.handle);
SetFocus(window->win32.handle);
}
/* one example of separation */
int _glfwPlatformGrabFocus(_GLFWwindow* window)
int WindowGrabFocus(_GLFWwindow* window)
{
if (!BringWindowToTop(window->win32.handle))
return GLFW_FALSE;
@ -1056,11 +1058,11 @@ int _glfwPlatformGrabFocus(_GLFWwindow* window)
return GLFW_FALSE;
}
void _glfwPlatformRequestFocus(_GLFWwindow* window)
void WindowRequestFocus(_GLFWwindow* window)
{
// The following can be used to flash the taskbar icon
// if any of the focus related functions fail
if (!_glfwPlatformGrabFocus(window)) {
if (!WindowGrabFocus(window)) {
// create a taskbar notification ("flash")
FLASHWINFO info;
info.cbSize = sizeof(FLASHWINFO);
@ -1073,6 +1075,13 @@ void _glfwPlatformRequestFocus(_GLFWwindow* window)
}
}
void _glfwPlatformShowWindow(_GLFWwindow* window)
{
ShowWindow(window->win32.handle, SW_SHOW);
WindowRequestFocus(window);
}
void _glfwPlatformUnhideWindow(_GLFWwindow* window)
{
ShowWindow(window->win32.handle, SW_SHOW);
@ -1083,6 +1092,15 @@ void _glfwPlatformHideWindow(_GLFWwindow* window)
ShowWindow(window->win32.handle, SW_HIDE);
}
void _glfwPlatformToggleWindowFullscreen(_GLFWwindow* window)
{
if (window->fullscreen) {
leaveFullscreenMode(window);
} else {
enterFullscreenMode(window);
}
}
int _glfwPlatformWindowFocused(_GLFWwindow* window)
{
return window->win32.handle == GetActiveWindow();

View File

@ -139,10 +139,10 @@ GLFWAPI GLFWwindow* glfwCreateWindow(int width, int height,
wndconfig.width = width;
wndconfig.height = height;
wndconfig.title = title;
wndconfig.monitor = (_GLFWmonitor*) monitor;
wndconfig.monitor = (_GLFWmonitor*) (monitor ? monitor : glfwGetPrimaryMonitor());
ctxconfig.share = (_GLFWwindow*) share;
if (wndconfig.monitor)
if (wndconfig.fullscreen)
{
wndconfig.resizable = GLFW_TRUE;
wndconfig.visible = GLFW_TRUE;
@ -208,7 +208,7 @@ GLFWAPI GLFWwindow* glfwCreateWindow(int width, int height,
// Restore the previously current context (or NULL)
_glfwPlatformMakeContextCurrent(previous);
if (wndconfig.monitor)
if (wndconfig.fullscreen)
{
int width, height;
_glfwPlatformGetWindowSize(window, &width, &height);
@ -249,6 +249,7 @@ void glfwDefaultWindowHints(void)
_glfw.hints.window.decorated = GLFW_TRUE;
_glfw.hints.window.focused = GLFW_TRUE;
_glfw.hints.window.autoIconify = GLFW_TRUE;
_glfw.hints.window.fullscreen = GLFW_FALSE;
// The default is 24 bits of color, 24 bits of depth and 8 bits of stencil,
// double buffered
@ -324,6 +325,9 @@ GLFWAPI void glfwWindowHint(int target, int hint)
case GLFW_FOCUSED:
_glfw.hints.window.focused = hint ? GLFW_TRUE : GLFW_FALSE;
break;
case GLFW_FULLSCREEN:
_glfw.hints.window.fullscreen = hint ? GLFW_TRUE : GLFW_FALSE;
break;
case GLFW_AUTO_ICONIFY:
_glfw.hints.window.autoIconify = hint ? GLFW_TRUE : GLFW_FALSE;
break;
@ -443,7 +447,7 @@ GLFWAPI void glfwSetWindowPos(GLFWwindow* handle, int xpos, int ypos)
_GLFW_REQUIRE_INIT();
if (window->monitor)
if (window->fullscreen)
{
_glfwInputError(GLFW_INVALID_VALUE,
"Full screen windows cannot be moved");
@ -472,7 +476,7 @@ GLFWAPI void glfwSetWindowSize(GLFWwindow* handle, int width, int height)
_GLFW_REQUIRE_INIT();
if (window->monitor)
if (window->fullscreen)
{
window->videoMode.width = width;
window->videoMode.height = height;
@ -489,7 +493,7 @@ GLFWAPI void glfwSetWindowSizeLimits(GLFWwindow* handle,
_GLFW_REQUIRE_INIT();
if (window->monitor || !window->resizable)
if (window->fullscreen || !window->resizable)
return;
_glfwPlatformSetWindowSizeLimits(window,
@ -503,7 +507,7 @@ GLFWAPI void glfwSetWindowAspectRatio(GLFWwindow* handle, int numer, int denom)
_GLFW_REQUIRE_INIT();
if (window->monitor || !window->resizable)
if (window->fullscreen || !window->resizable)
return;
if (!denom)
@ -567,8 +571,8 @@ GLFWAPI void glfwShowWindow(GLFWwindow* handle)
_GLFW_REQUIRE_INIT();
if (window->monitor)
return;
if (window->fullscreen)
_glfwPlatformToggleWindowFullscreen(window);
_glfwPlatformShowWindow(window);
}
@ -579,12 +583,21 @@ GLFWAPI void glfwHideWindow(GLFWwindow* handle)
_GLFW_REQUIRE_INIT();
if (window->monitor)
return;
if (window->fullscreen)
_glfwPlatformToggleWindowFullscreen(window);
_glfwPlatformHideWindow(window);
}
GLFWAPI void glfwToggleWindowFullscreen(GLFWwindow* handle)
{
_GLFWwindow* window = (_GLFWwindow*) handle;
_GLFW_REQUIRE_INIT();
_glfwPlatformToggleWindowFullscreen(window);
}
GLFWAPI int glfwGetWindowAttrib(GLFWwindow* handle, int attrib)
{
_GLFWwindow* window = (_GLFWwindow*) handle;
@ -605,6 +618,8 @@ GLFWAPI int glfwGetWindowAttrib(GLFWwindow* handle, int attrib)
return window->decorated;
case GLFW_FLOATING:
return window->floating;
case GLFW_FULLSCREEN:
return window->fullscreen;
case GLFW_CLIENT_API:
return window->context.api;
case GLFW_CONTEXT_VERSION_MAJOR: