From 0be4f3f75aebd9d24583ee86590a38e741db0904 Mon Sep 17 00:00:00 2001 From: Doug Binks Date: Tue, 29 May 2018 14:51:36 +0100 Subject: [PATCH] Add GLFW_FOCUS_ON_SHOW window hint and attribute This adds a window hint and attribute for controlling whether glfwShowWindow gives the specified window input focus in addition to making it visible. Fixes #1189. Closes #1275. --- README.md | 2 ++ docs/news.dox | 6 ++++++ docs/window.dox | 18 ++++++++++++++++-- include/GLFW/glfw3.h | 20 ++++++++++++++++++-- src/internal.h | 2 ++ src/window.c | 13 ++++++++++++- tests/windows.c | 11 +++++++++-- 7 files changed, 65 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 0573dcd9..82d4806a 100644 --- a/README.md +++ b/README.md @@ -165,6 +165,8 @@ information on what to include when reporting a bug. - Added `GLFW_HOVERED` window attribute for polling cursor hover state (#1166) - Added `GLFW_CENTER_CURSOR` window hint for controlling cursor centering (#749,#842) +- Added `GLFW_FOCUS_ON_SHOW` window hint and attribute to control input focus + on calling show window (#1189) - Added `GLFW_JOYSTICK_HAT_BUTTONS` init hint (#889) - Added `GLFW_LOCK_KEY_MODS` input mode and `GLFW_MOD_*_LOCK` mod bits (#946) - Added macOS specific `GLFW_COCOA_RETINA_FRAMEBUFFER` window hint diff --git a/docs/news.dox b/docs/news.dox index 13f3dd64..2d043ade 100644 --- a/docs/news.dox +++ b/docs/news.dox @@ -4,6 +4,12 @@ @section news_33 Release notes for 3.3 +@subsection news_33_focusonshow GLFW_FOCUS_ON_SHOW window hint and attribute + +GLFW now supports the [GLFW_FOCUS_ON_SHOW](@ref GLFW_DECORATED_hint) window hint +and attribute for controlling input focus when calling @ref glfwShowWindow + +@see @ref window_hide @subsection news_33_geterror Error query diff --git a/docs/window.dox b/docs/window.dox index 9e97ce3b..386fb9c7 100644 --- a/docs/window.dox +++ b/docs/window.dox @@ -234,6 +234,9 @@ alpha channel will be used to combine the framebuffer with the background. This does not affect window decorations. Possible values are `GLFW_TRUE` and `GLFW_FALSE`. +@anchor GLFW_FOCUS_ON_SHOW_hint +__GLFW_FOCUS_ON_SHOW__ specifies whether the window will be given input +focus when @ref glfwShowWindow is called. Possible values are `GLFW_TRUE` and `GLFW_FALSE`. @subsubsection window_hints_fb Framebuffer related hints @@ -489,6 +492,7 @@ GLFW_FLOATING | `GLFW_FALSE` | `GLFW_TRUE` or `GL GLFW_MAXIMIZED | `GLFW_FALSE` | `GLFW_TRUE` or `GLFW_FALSE` GLFW_CENTER_CURSOR | `GLFW_TRUE` | `GLFW_TRUE` or `GLFW_FALSE` GLFW_TRANSPARENT_FRAMEBUFFER | `GLFW_FALSE` | `GLFW_TRUE` or `GLFW_FALSE` +GLFW_FOCUS_ON_SHOW | `GLFW_TRUE` | `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` @@ -1009,6 +1013,10 @@ Hidden windows can be shown with @ref glfwShowWindow. glfwShowWindow(window); @endcode +By default, this function will also set the input focus to that window. Set +the [GLFW_FOCUS_ON_SHOW](@ref GLFW_FOCUS_ON_SHOW_hint) window hint to change +this behavior for all newly created windows, or change the behavior for an +existing window with @ref glfwSetWindowAttrib. You can also get the current visibility state with @ref glfwGetWindowAttrib. @@ -1196,8 +1204,9 @@ if (glfwGetWindowAttrib(window, GLFW_FOCUSED)) The [GLFW_DECORATED](@ref GLFW_DECORATED_attrib), [GLFW_RESIZABLE](@ref GLFW_RESIZABLE_attrib), -[GLFW_FLOATING](@ref GLFW_FLOATING_attrib) and -[GLFW_AUTO_ICONIFY](@ref GLFW_AUTO_ICONIFY_attrib) window attributes can be +[GLFW_FLOATING](@ref GLFW_FLOATING_attrib), +[GLFW_AUTO_ICONIFY](@ref GLFW_AUTO_ICONIFY_attrib) and +[GLFW_FOCUS_ON_SHOW](@ref GLFW_FOCUS_ON_SHOW_attrib) window attributes can be changed with @ref glfwSetWindowAttrib. @code @@ -1259,6 +1268,11 @@ a transparent framebuffer, i.e. the window contents is composited with the background using the window framebuffer alpha channel. See @ref window_transparency for details. +@anchor GLFW_FOCUS_ON_SHOW_attrib +__GLFW_FOCUS_ON_SHOW__ specifies whether the window will be given input +focus when @ref glfwShowWindow is called. This can be set before creation +with the [GLFW_FOCUS_ON_SHOW](@ref GLFW_FOCUS_ON_SHOW_hint) window hint or +after with @ref glfwSetWindowAttrib. @subsubsection window_attribs_ctx Context related attributes diff --git a/include/GLFW/glfw3.h b/include/GLFW/glfw3.h index 00256d4d..990fe3f7 100644 --- a/include/GLFW/glfw3.h +++ b/include/GLFW/glfw3.h @@ -819,6 +819,12 @@ extern "C" { * Mouse cursor hover [window attribute](@ref GLFW_HOVERED_attrib). */ #define GLFW_HOVERED 0x0002000B +/*! @brief Input focus on calling show window hint and attribute + * + * Input focus [window hint](@ref GLFW_FOCUS_ON_SHOW_hint) or + * [window attribute](@ref GLFW_FOCUS_ON_SHOW_attrib). + */ +#define GLFW_FOCUS_ON_SHOW 0x0002000C /*! @brief Framebuffer bit depth hint. * @@ -3085,6 +3091,11 @@ GLFWAPI void glfwMaximizeWindow(GLFWwindow* window); * hidden. If the window is already visible or is in full screen mode, this * function does nothing. * + * By default, windowed mode windows are focused when shown + * Set the [GLFW_FOCUS_ON_SHOW](@ref GLFW_FOCUS_ON_SHOW_hint) window hint + * to change this behavior for all newly created windows, or change the + * behavior for an existing window with @ref glfwSetWindowAttrib. + * * @param[in] window The window to make visible. * * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref @@ -3132,6 +3143,10 @@ GLFWAPI void glfwHideWindow(GLFWwindow* window); * initially created. Set the [GLFW_FOCUSED](@ref GLFW_FOCUSED_hint) to * disable this behavior. * + * Also by default, windowed mode windows are focused when shown + * with @ref glfwShowWindow. Set the + * [GLFW_FOCUS_ON_SHOW](@ref GLFW_FOCUS_ON_SHOW_hint) to disable this behavior. + * * __Do not use this function__ to steal focus from other applications unless * you are certain that is what the user wants. Focus stealing can be * extremely disruptive. @@ -3306,8 +3321,9 @@ GLFWAPI int glfwGetWindowAttrib(GLFWwindow* window, int attrib); * * The supported attributes are [GLFW_DECORATED](@ref GLFW_DECORATED_attrib), * [GLFW_RESIZABLE](@ref GLFW_RESIZABLE_attrib), - * [GLFW_FLOATING](@ref GLFW_FLOATING_attrib) and - * [GLFW_AUTO_ICONIFY](@ref GLFW_AUTO_ICONIFY_attrib). + * [GLFW_FLOATING](@ref GLFW_FLOATING_attrib), + * [GLFW_AUTO_ICONIFY](@ref GLFW_AUTO_ICONIFY_attrib) and + * [GLFW_FOCUS_ON_SHOW](@ref GLFW_FOCUS_ON_SHOW_attrib). * * Some of these attributes are ignored for full screen windows. The new * value will take effect if the window is later made windowed. diff --git a/src/internal.h b/src/internal.h index 92bbfcce..9fc626dd 100644 --- a/src/internal.h +++ b/src/internal.h @@ -267,6 +267,7 @@ struct _GLFWwndconfig GLFWbool floating; GLFWbool maximized; GLFWbool centerCursor; + GLFWbool focusOnShow; struct { GLFWbool retina; char frameName[256]; @@ -372,6 +373,7 @@ struct _GLFWwindow GLFWbool decorated; GLFWbool autoIconify; GLFWbool floating; + GLFWbool focusOnShow; GLFWbool shouldClose; void* userPointer; GLFWvidmode videoMode; diff --git a/src/window.c b/src/window.c index 38a8982b..4ed415ca 100644 --- a/src/window.c +++ b/src/window.c @@ -201,6 +201,7 @@ GLFWAPI GLFWwindow* glfwCreateWindow(int width, int height, window->decorated = wndconfig.decorated; window->autoIconify = wndconfig.autoIconify; window->floating = wndconfig.floating; + window->focusOnShow = wndconfig.focusOnShow; window->cursorMode = GLFW_CURSOR_NORMAL; window->minwidth = GLFW_DONT_CARE; @@ -267,6 +268,7 @@ void glfwDefaultWindowHints(void) _glfw.hints.window.focused = GLFW_TRUE; _glfw.hints.window.autoIconify = GLFW_TRUE; _glfw.hints.window.centerCursor = GLFW_TRUE; + _glfw.hints.window.focusOnShow = GLFW_TRUE; // The default is 24 bits of color, 24 bits of depth and 8 bits of stencil, // double buffered @@ -370,6 +372,9 @@ GLFWAPI void glfwWindowHint(int hint, int value) case GLFW_CENTER_CURSOR: _glfw.hints.window.centerCursor = value ? GLFW_TRUE : GLFW_FALSE; return; + case GLFW_FOCUS_ON_SHOW: + _glfw.hints.window.focusOnShow = value ? GLFW_TRUE : GLFW_FALSE; + return; case GLFW_CLIENT_API: _glfw.hints.context.client = value; return; @@ -755,7 +760,9 @@ GLFWAPI void glfwShowWindow(GLFWwindow* handle) return; _glfwPlatformShowWindow(window); - _glfwPlatformFocusWindow(window); + + if (window->focusOnShow) + _glfwPlatformFocusWindow(window); } GLFWAPI void glfwRequestWindowAttention(GLFWwindow* handle) @@ -810,6 +817,8 @@ GLFWAPI int glfwGetWindowAttrib(GLFWwindow* handle, int attrib) return _glfwPlatformWindowMaximized(window); case GLFW_HOVERED: return _glfwPlatformWindowHovered(window); + case GLFW_FOCUS_ON_SHOW: + return window->focusOnShow; case GLFW_TRANSPARENT_FRAMEBUFFER: return _glfwPlatformFramebufferTransparent(window); case GLFW_RESIZABLE: @@ -886,6 +895,8 @@ GLFWAPI void glfwSetWindowAttrib(GLFWwindow* handle, int attrib, int value) if (!window->monitor) _glfwPlatformSetWindowFloating(window, value); } + else if (attrib == GLFW_FOCUS_ON_SHOW) + window->focusOnShow = value; else _glfwInputError(GLFW_INVALID_ENUM, "Invalid window attribute 0x%08X", attrib); } diff --git a/tests/windows.c b/tests/windows.c index 1c129739..5fed58f3 100644 --- a/tests/windows.c +++ b/tests/windows.c @@ -56,9 +56,10 @@ static const struct static void usage(void) { - printf("Usage: windows [-h] [-b]\n"); + printf("Usage: windows [-h] [-b] [-f] \n"); printf("Options:\n"); printf(" -b create decorated windows\n"); + printf(" -f set focus on show off for all but first window\n"); printf(" -h show this help\n"); } @@ -92,16 +93,20 @@ int main(int argc, char** argv) { int i, ch; int decorated = GLFW_FALSE; + int focusOnShow = GLFW_TRUE; int running = GLFW_TRUE; GLFWwindow* windows[4]; - while ((ch = getopt(argc, argv, "bh")) != -1) + while ((ch = getopt(argc, argv, "bfh")) != -1) { switch (ch) { case 'b': decorated = GLFW_TRUE; break; + case 'f': + focusOnShow = GLFW_FALSE; + break; case 'h': usage(); exit(EXIT_SUCCESS); @@ -122,6 +127,8 @@ int main(int argc, char** argv) for (i = 0; i < 4; i++) { int left, top, right, bottom; + if (i) + glfwWindowHint(GLFW_FOCUS_ON_SHOW, focusOnShow); windows[i] = glfwCreateWindow(200, 200, titles[i], NULL, NULL); if (!windows[i])