diff --git a/docs/window.dox b/docs/window.dox index de53be9f9..5baf7567a 100644 --- a/docs/window.dox +++ b/docs/window.dox @@ -44,12 +44,29 @@ the event. @subsubsection window_full_screen Full screen windows -To create a full screen window, you need to specify which monitor the window -should use. In most cases, the user's primary monitor is a good choice. -For more information about retrieving monitors, see @ref monitor_monitors. +To create a full screen window, you can use the GLFW_FULLSCREEN window hint. +It is also possible to specify which monitor the window should use. In most +cases, the user's primary monitor is a good choice. For more information about +retrieving monitors, see @ref monitor_monitors. @code +glfwWindowHint(GLFW_FULLSCREEN, GLFW_TRUE); + GLFWwindow* window = glfwCreateWindow(640, 480, "My Title", glfwGetPrimaryMonitor(), NULL); + // same as passing null for the monitor +@endcode + +The mode of a window, whether created as fullscreen or as a windowed mode window, +can be toggled at any time using @ref glfwToggleWindowFullscreen. + +@code +glfwToggleWindowFullscreen(window); +@endcode + +You can also get the current window state with @ref glfwGetWindowAttrib. + +@code +int fullscreen = glfwGetWindowAttrib(window, GLFW_FULLSCREEN); @endcode Full screen windows cover the entire display area of a monitor, have no border @@ -92,6 +109,7 @@ such a window, simply request the current video mode. @code const GLFWvidmode* mode = glfwGetVideoMode(monitor); +glfwWindowHint(GLFW_FULLSCREEN, GLFW_TRUE); glfwWindowHint(GLFW_RED_BITS, mode->redBits); glfwWindowHint(GLFW_GREEN_BITS, mode->greenBits); glfwWindowHint(GLFW_BLUE_BITS, mode->blueBits); @@ -174,6 +192,9 @@ above other regular windows, also called topmost or always-on-top. This is intended primarily for debugging purposes and cannot be used to implement proper full screen windows. This hint is ignored for full screen windows. +`GLFW_FULLSCREEN` specifies whether the window will be created in fullscreen mode. +The window can always be switched back to windowed mode using @ref glfwToggleWindowFullscreen. + @subsubsection window_hints_fb Framebuffer related hints @@ -304,6 +325,7 @@ Window hint | Default value | Supported values `GLFW_FOCUSED` | `GLFW_TRUE` | `GLFW_TRUE` or `GLFW_FALSE` `GLFW_AUTO_ICONIFY` | `GLFW_TRUE` | `GLFW_TRUE` or `GLFW_FALSE` `GLFW_FLOATING` | `GLFW_FALSE` | `GLFW_TRUE` or `GLFW_FALSE` +`GLFW_FULLSCREEN` | `GLFW_FALSE` | `GLFW_TRUE` or `GLFW_FALSE` `GLFW_RED_BITS` | 8 | 0 to `INT_MAX` or `GLFW_DONT_CARE` `GLFW_GREEN_BITS` | 8 | 0 to `INT_MAX` or `GLFW_DONT_CARE` `GLFW_BLUE_BITS` | 8 | 0 to `INT_MAX` or `GLFW_DONT_CARE` @@ -605,8 +627,9 @@ GLFWmonitor* monitor = glfwGetWindowMonitor(window); This monitor handle is one of those returned by @ref glfwGetMonitors. -For windowed mode windows, this function returns `NULL`. This is the -recommended way to tell full screen windows from windowed mode windows. +For windowed mode windows, this function returns the monitor that will be used +if the mode would be switched to fullscreen. Using this function to query the mode +of the window will no longer work and @glfwGetWindowAttrib should be used instead. @subsection window_iconify Window iconification @@ -669,7 +692,8 @@ glfwHideWindow(window); This makes the window completely invisible to the user, including removing it from the task bar, dock or window list. Full screen windows cannot be hidden -and calling @ref glfwHideWindow on a full screen window does nothing. +and calling @ref glfwHideWindow on a full screen window does nothing. The window +should be switched to windowed mode first and then hidden. Hidden windows can be shown with @ref glfwShowWindow. diff --git a/include/GLFW/glfw3.h b/include/GLFW/glfw3.h index 7b31a7d07..2f12a5a6e 100644 --- a/include/GLFW/glfw3.h +++ b/include/GLFW/glfw3.h @@ -622,6 +622,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 @@ -1575,11 +1576,12 @@ GLFWAPI void glfwWindowHint(int target, int hint); * of the created window, framebuffer and context, see @ref * glfwGetWindowAttrib, @ref glfwGetWindowSize and @ref glfwGetFramebufferSize. * - * To create a full screen window, you need to specify the monitor the window - * will cover. If no monitor is specified, windowed mode will be used. Unless - * you have a way for the user to choose a specific monitor, it is recommended - * that you pick the primary monitor. For more information on how to query - * connected monitors, see @ref monitor_monitors. + * To create a full screen window, you can use the GLFW_FULLSCREEN window hint. + * It is also possible to specify which monitor the window should use. If no + * monitor is specified, the primary monitor is used. Unless you have a way for + * the user to choose a specific monitor, it is recommended that you pick the + * primary monitor. For more information on how to query connected monitors, + * see @ref monitor_monitors. * * For full screen windows, the specified size becomes the resolution of the * window's _desired video mode_. As long as a full screen window has input @@ -1610,7 +1612,7 @@ GLFWAPI void glfwWindowHint(int target, int hint); * This must be greater than zero. * @param[in] title The initial, UTF-8 encoded window title. * @param[in] monitor The monitor to use for full screen mode, or `NULL` to use - * windowed mode. + * the primary monitor. * @param[in] share The window whose context to share resources with, or `NULL` * to not share resources. * @return The handle of the created window, or `NULL` if an @@ -2106,6 +2108,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 the mode on. + * + * @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 diff --git a/src/internal.h b/src/internal.h index 2ee3e4b46..14aa1a335 100644 --- a/src/internal.h +++ b/src/internal.h @@ -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; @@ -583,6 +585,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 */ diff --git a/src/wgl_context.c b/src/wgl_context.c index 0bce17e78..ebb8e398f 100644 --- a/src/wgl_context.c +++ b/src/wgl_context.c @@ -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) diff --git a/src/win32_window.c b/src/win32_window.c index 2f2db36e2..049bb30a0 100644 --- a/src/win32_window.c +++ b/src/win32_window.c @@ -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,8 +888,8 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window, if (!createWindow(window, wndconfig, ctxconfig, fbconfig)) return GLFW_FALSE; } - - if (window->monitor) + + if (wndconfig->fullscreen) { _glfwPlatformShowWindow(window); if (!enterFullscreenMode(window)) @@ -881,7 +901,7 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window, void _glfwPlatformDestroyWindow(_GLFWwindow* window) { - if (window->monitor) + if (window->fullscreen) leaveFullscreenMode(window); destroyWindow(window); @@ -934,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 { @@ -1027,14 +1047,41 @@ void _glfwPlatformRestoreWindow(_GLFWwindow* window) ShowWindow(window->win32.handle, SW_RESTORE); } +int WindowGrabFocus(_GLFWwindow* window) +{ + if (!BringWindowToTop(window->win32.handle)) + return GLFW_FALSE; + if (!SetForegroundWindow(window->win32.handle)) + return GLFW_FALSE; + if (!SetFocus(window->win32.handle)) + return GLFW_FALSE; + return GLFW_FALSE; +} + +void WindowRequestFocus(_GLFWwindow* window) +{ + // The following can be used to flash the taskbar icon + // if any of the focus related functions fail + if (!WindowGrabFocus(window)) { + // create a taskbar notification ("flash") + FLASHWINFO info; + info.cbSize = sizeof(FLASHWINFO); + info.hwnd = window->win32.handle; + info.dwFlags = FLASHW_TRAY; + info.uCount = 3; + info.dwTimeout = 0; + + FlashWindowEx(&info); + } +} + void _glfwPlatformShowWindow(_GLFWwindow* window) { ShowWindow(window->win32.handle, SW_SHOW); - BringWindowToTop(window->win32.handle); - SetForegroundWindow(window->win32.handle); - SetFocus(window->win32.handle); + WindowRequestFocus(window); } + void _glfwPlatformUnhideWindow(_GLFWwindow* window) { ShowWindow(window->win32.handle, SW_SHOW); @@ -1045,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(); diff --git a/src/window.c b/src/window.c index 08426f852..967501f26 100644 --- a/src/window.c +++ b/src/window.c @@ -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; @@ -202,7 +202,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); @@ -318,6 +318,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; @@ -437,7 +440,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"); @@ -466,7 +469,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; @@ -483,7 +486,7 @@ GLFWAPI void glfwSetWindowSizeLimits(GLFWwindow* handle, _GLFW_REQUIRE_INIT(); - if (window->monitor || !window->resizable) + if (window->fullscreen || !window->resizable) return; _glfwPlatformSetWindowSizeLimits(window, @@ -497,7 +500,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) @@ -561,7 +564,7 @@ GLFWAPI void glfwShowWindow(GLFWwindow* handle) _GLFW_REQUIRE_INIT(); - if (window->monitor) + if (window->fullscreen) return; _glfwPlatformShowWindow(window); @@ -573,12 +576,21 @@ GLFWAPI void glfwHideWindow(GLFWwindow* handle) _GLFW_REQUIRE_INIT(); - if (window->monitor) + if (window->fullscreen) return; _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; @@ -599,6 +611,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: diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index d87837680..2f40ada2a 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -36,10 +36,13 @@ add_executable(threads WIN32 MACOSX_BUNDLE threads.c ${TINYCTHREAD} ${GLAD}) add_executable(title WIN32 MACOSX_BUNDLE title.c ${GLAD}) add_executable(windows WIN32 MACOSX_BUNDLE windows.c ${GLAD}) +add_executable(options MACOSX_BUNDLE options.c ${GETOPT} ${GLAD}) +set_target_properties(options PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Options") + target_link_libraries(empty "${CMAKE_THREAD_LIBS_INIT}" "${RT_LIBRARY}") target_link_libraries(threads "${CMAKE_THREAD_LIBS_INIT}" "${RT_LIBRARY}") -set(WINDOWS_BINARIES empty sharing tearing threads title windows) +set(WINDOWS_BINARIES empty sharing tearing threads title windows options) set(CONSOLE_BINARIES clipboard events msaa gamma glfwinfo iconify joysticks monitors reopen cursor) diff --git a/tests/options.c b/tests/options.c new file mode 100644 index 000000000..aabb03616 --- /dev/null +++ b/tests/options.c @@ -0,0 +1,289 @@ +//======================================================================== +// Simple 'Graphics' options test +// Copyright (C) 2015 Eden Salomon +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would +// be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, and must not +// be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source +// distribution. +// +//======================================================================== +// +// This test creates a window with the ability to change during runtime +// the window options typically seen in the 'Graphics' section of games. +// This includes resolution, refresh rate, and fullscreen / windowed mode. +// +//======================================================================== + +#include +#include +#define GLFW_EXPOSE_NATIVE_WIN32 +#define GLFW_EXPOSE_NATIVE_WGL +#include + +#include +#include + +#include "getopt.h" + +typedef struct _WindowState +{ + SIZE* dimenstions; + int size; + int count; + int current; +} WindowState; + +static void error_callback(int error, const char* description) +{ + fprintf(stderr, "Error: %s\n", description); +} + +static void list_resolutions(GLFWwindow* window) +{ + GLFWmonitor* monitor; + int count; + const GLFWvidmode* modes; + + monitor = glfwGetWindowMonitor(window); + modes = glfwGetVideoModes(monitor ? monitor : glfwGetPrimaryMonitor(), &count); + + printf("List of supported resolutions:\n"); + printf(" +----+------------------------+----+\n"); + printf(" | | resolution | color | |\n"); + printf(" | id | width height | r g b | rf |\n"); + printf(" +----+------------------------+----+\n"); + for (int i = 0; i < count; ++i) { + printf(" | %2d | %5d %6d | %d %d %d | %2d |\n", + i + 1, + modes[i].width, modes[i].height, + modes[i].redBits, + modes[i].greenBits, + modes[i].blueBits, + modes[i].refreshRate); + } + printf(" +----+------------------------+----+\n\n"); +} + +static void setVideoMode(GLFWwindow* window, WindowState* state, int index) +{ + GLFWmonitor* monitor; + const GLFWvidmode* mode; + int width, height; + + state->current = (index + state->count) % state->count; + width = state->dimenstions[state->current].cx; + height = state->dimenstions[state->current].cy; + + glfwSetWindowSize(window, width, height); + + monitor = glfwGetWindowMonitor(window); + mode = glfwGetVideoMode(monitor); + + printf("Changed resolution to %dx%d [%d].\n", width, height, mode->refreshRate); +} + +static void controls() +{ + printf("When the window is in focus, use the following keys to control the various options:\n"); + printf(" Esc Exit the application\n"); + printf(" h display this help\n"); + printf(" f toggle fullscreen / window mode\n"); + printf(" r toggle between different refresh rates\n"); + printf(" l list all supported resolutions\n"); + printf(" d, -> next resolution\n"); + printf(" a, <- previous resolution\n"); +} + +static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) +{ + WindowState* state = (WindowState*) glfwGetWindowUserPointer(window); + + if (action != GLFW_PRESS) + return; + + switch (key) + { + case GLFW_KEY_H: + controls(); + break; + case GLFW_KEY_L: + list_resolutions(window); + break; + case GLFW_KEY_F: + glfwToggleWindowFullscreen(window); + break; + case GLFW_KEY_ESCAPE: + glfwSetWindowShouldClose(window, GLFW_TRUE); + break; + case GLFW_KEY_A: + setVideoMode(window, state, state->current - 1); + break; + case GLFW_KEY_D: + setVideoMode(window, state, state->current + 1); + break; + case GLFW_KEY_R: + // TODO: toggle refresh rate on current resolution + // as of now the highest value is used due to + // GLFW_REFRESH_RATE being set to GLFW_DONT_CARE + break; + } +} + +static void usage() +{ + printf("Usage: oprions [OPTION]...\n"); + printf("Options:\n"); + printf(" -h, --help show this help\n"); + printf(" -l, --list-resolutions list all resolutions supported by the primary monitor\n"); + printf(" --width=640 specify the width of the window in pixels\n"); + printf(" --height=480 specify the height of the window in pixels\n"); + printf(" -r, --refresh-rate=RATE specify the refresh rate of the window in Hz\n"); +} + +int main(int argc, char** argv) +{ + int ch; + int width = 640; + int height = 480; + int list = GLFW_FALSE; + int fullscreen = GLFW_FALSE; + int running = GLFW_TRUE; + GLFWwindow* window; + GLFWmonitor* monitor; + WindowState state = { NULL, 0, 0, 0 }; + int i, j, count; + const GLFWvidmode* modes; + + enum { HELP, RESOLUTIONS, WIDTH, HIEGHT, REFRESH, FULLSCREEN }; + + const struct option options[] = + { + { "help", 0, NULL, HELP }, + { "list-resolutions", 0, NULL, RESOLUTIONS }, + { "width", 1, NULL, WIDTH }, + { "height", 1, NULL, HIEGHT }, + { "refresh-rate", 1, NULL, REFRESH }, + { "fullscreen", 0, NULL, FULLSCREEN }, + { NULL, 0, NULL, 0 } + }; + + glfwSetErrorCallback(error_callback); + + if (!glfwInit()) + exit(EXIT_FAILURE); + + while ((ch = getopt_long(argc, argv, "hlr:f", options, NULL)) != -1) { + switch (ch) { + case 'h': + case HELP: + usage(); + exit(EXIT_SUCCESS); + case 'l': + case RESOLUTIONS: + list = GLFW_TRUE; + break; + case WIDTH: + width = atoi(optarg); + break; + case HIEGHT: + height = atoi(optarg); + break; + case 'r': + case REFRESH: + glfwWindowHint(GLFW_REFRESH_RATE, atoi(optarg)); + break; + case 'f': + case FULLSCREEN: + glfwWindowHint(GLFW_FULLSCREEN, GLFW_TRUE); + break; + default: + usage(); + exit(EXIT_FAILURE); + } + } + + monitor = glfwGetPrimaryMonitor(); + window = glfwCreateWindow(width, height, "Graphics Options", (fullscreen ? monitor : NULL), NULL); + + modes = glfwGetVideoModes(monitor ? monitor : glfwGetPrimaryMonitor(), &count); + + for (i = 0; i < count; ++i) { + SIZE size; + + size.cx = modes[i].width; + size.cy = modes[i].height; + + for (j = 0; j < state.count; ++j) { + if (state.dimenstions[j].cx == size.cx && + state.dimenstions[j].cy == size.cy) + break; + } + + if (j < state.count) + continue; + + if (state.count == state.size) + { + if (state.count) + state.size *= 2; + else + state.size = 128; + + state.dimenstions = (SIZE*) realloc(state.dimenstions, state.size * sizeof(SIZE)); + } + + state.count++; + state.dimenstions[state.count - 1] = size; + } + + glfwSetWindowUserPointer(window, &state); + + if (!window) { + glfwTerminate(); + exit(EXIT_FAILURE); + } + + glfwSetKeyCallback(window, key_callback); + + glfwMakeContextCurrent(window); + + gladLoadGLLoader((GLADloadproc) glfwGetProcAddress); + + glClearColor(1.0f, 1.0f, 1.0f, 1.0f); + + if (list) + list_resolutions(window); + + controls(); + + while (running) + { + glClear(GL_COLOR_BUFFER_BIT); + glfwSwapBuffers(window); + + if (glfwWindowShouldClose(window)) + running = GLFW_FALSE; + + glfwPollEvents(); + } + + free(state.dimenstions); + glfwTerminate(); + exit(EXIT_SUCCESS); +} + diff --git a/tests/options.txt b/tests/options.txt new file mode 100644 index 000000000..352d8ad5e --- /dev/null +++ b/tests/options.txt @@ -0,0 +1,10 @@ +TODO: +- Change Resulution +- Refresh Rate +- Fullscreen / Window +all in runtime + +new state variables + + +Enter fullscreen mode: diff --git a/tests/reopen.c b/tests/reopen.c index 40f7b6f70..c8a666d18 100644 --- a/tests/reopen.c +++ b/tests/reopen.c @@ -76,6 +76,8 @@ static GLFWwindow* open_window(int width, int height, GLFWmonitor* monitor) base = glfwGetTime(); + glfwWindowHint(GLFW_FULLSCREEN, monitor ? GLFW_TRUE : GLFW_FALSE); + window = glfwCreateWindow(width, height, "Window Re-opener", monitor, NULL); if (!window) return NULL;