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_DECORATED 0x00020005
#define GLFW_AUTO_ICONIFY 0x00020006 #define GLFW_AUTO_ICONIFY 0x00020006
#define GLFW_FLOATING 0x00020007 #define GLFW_FLOATING 0x00020007
#define GLFW_FULLSCREEN 0x00020008
#define GLFW_RED_BITS 0x00021001 #define GLFW_RED_BITS 0x00021001
#define GLFW_GREEN_BITS 0x00021002 #define GLFW_GREEN_BITS 0x00021002
@ -2101,6 +2102,18 @@ GLFWAPI void glfwShowWindow(GLFWwindow* window);
*/ */
GLFWAPI void glfwHideWindow(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. /*! @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 * This function returns the handle of the monitor that the specified window is

View File

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

View File

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

View File

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

View File

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